Index: /tags/start/bbc/collect/bbc/etc/collect.cfg
===================================================================
--- /tags/start/bbc/collect/bbc/etc/collect.cfg	(revision 13666)
+++ /tags/start/bbc/collect/bbc/etc/collect.cfg	(revision 13666)
@@ -0,0 +1,39 @@
+creator         sjboddie@cs.waikato.ac.nz
+maintainer      sjboddie@cs.waikato.ac.nz
+public          true
+beta            true
+indexes         document:Title paragraph:People document:ProgNumber document:CatNum document:zzabn document:text
+defaultindex    document:text
+
+plugin          ZIPPlug
+plugin          GMLPlug 
+plugin          ArcPlug 
+plugin          RecPlug 
+plugin          BRSPlug -input_encoding ascii
+
+dontgdbm ProgNumber
+dontgdbm People
+dontgdbm CatNum
+dontgdbm zzabn
+
+#ccscols         nsa bfi bbcother
+
+# Collection specific metadata
+#--
+collectionmeta  collectionname      "BBC (1900-2003)"
+collectionmeta  iconcollection      "_httpprefix_/collect/bbc/images/bbc_online.gif"
+collectionmeta .document:Title      "titles"
+collectionmeta .paragraph:People    "people"
+collectionmeta .document:ProgNumber "programme numbers"
+collectionmeta .document:CatNum     "catalogue numbers"
+collectionmeta .document:zzabn      "RFAB/RFAN"
+collectionmeta .document:text       "all fields"
+collectionmeta collectionextra      ""
+
+
+format DocumentButtons ""
+format DocumentHeading ""
+
+format          SearchVList \
+    "<td valign=top>[link][icon][/link]</td><td>{If}{[ItemTitle],[ItemTitle]; [Title],[Title]}</td><td width=160>[Date]</td>"
+
Index: /tags/start/bbc/collect/bbc/perllib/bbcotherbuildproc.pm
===================================================================
--- /tags/start/bbc/collect/bbc/perllib/bbcotherbuildproc.pm	(revision 13666)
+++ /tags/start/bbc/collect/bbc/perllib/bbcotherbuildproc.pm	(revision 13666)
@@ -0,0 +1,60 @@
+###########################################################################
+#
+# bbcbuildproc.pm -- 
+# 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.
+#
+###########################################################################
+
+# mgbuildproc for bbc collections. this file (and package name too) should
+# be renamed to the name of the collection currently being built (e.g. 
+# bbc1buildproc)
+
+package bbcotherbuildproc;
+
+use mgbuildproc;
+
+BEGIN {
+    @ISA = ('mgbuildproc');
+}
+
+
+sub new {
+    my ($class, $collection, $source_dir, $build_dir,
+	$verbosity, $outhandle) = @_;
+    my $self = new mgbuildproc ();
+
+    return bless $self, $class;
+}
+
+
+# we want to filter ProgNumbers to remove all whitespace and other 
+# non-alphanumeric characters when creating the index
+# $_[0] == field
+# $_[1] == text
+sub filter_text {
+    my $self = shift (@_);
+
+    if ($self->{'indexing_text'} && ($_[0] eq "ProgNumber" || $_[0] eq "zzabn" )) {
+	$_[1] =~ s/[^\w]//g;
+    }
+}
+
+1;
Index: /tags/start/bbc/collect/bbc/perllib/bfibuildproc.pm
===================================================================
--- /tags/start/bbc/collect/bbc/perllib/bfibuildproc.pm	(revision 13666)
+++ /tags/start/bbc/collect/bbc/perllib/bfibuildproc.pm	(revision 13666)
@@ -0,0 +1,60 @@
+###########################################################################
+#
+# bbcbuildproc.pm -- 
+# 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.
+#
+###########################################################################
+
+# mgbuildproc for bbc collections. this file (and package name too) should
+# be renamed to the name of the collection currently being built (e.g. 
+# bbc1buildproc)
+
+package bfibuildproc;
+
+use mgbuildproc;
+
+BEGIN {
+    @ISA = ('mgbuildproc');
+}
+
+
+sub new {
+    my ($class, $collection, $source_dir, $build_dir,
+	$verbosity, $outhandle) = @_;
+    my $self = new mgbuildproc ();
+
+    return bless $self, $class;
+}
+
+
+# we want to filter ProgNumbers to remove all whitespace and other 
+# non-alphanumeric characters when creating the index
+# $_[0] == field
+# $_[1] == text
+sub filter_text {
+    my $self = shift (@_);
+
+    if ($self->{'indexing_text'} && ($_[0] eq "ProgNumber" || $_[0] eq "zzabn" )) {
+	$_[1] =~ s/[^\w]//g;
+    }
+}
+
+1;
Index: /tags/start/bbc/collect/bbc/perllib/docsave.pm
===================================================================
--- /tags/start/bbc/collect/bbc/perllib/docsave.pm	(revision 13666)
+++ /tags/start/bbc/collect/bbc/perllib/docsave.pm	(revision 13666)
@@ -0,0 +1,234 @@
+###########################################################################
+#
+# docsave.pm
+# 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 document processor saves a document in the 
+# archives directory of a collection
+
+# use with doc.pm rewound to version 1.25
+
+
+package docsave;
+
+use arcinfo;
+use docproc;
+use util;
+
+
+sub BEGIN {
+    @ISA = ('docproc');
+}
+
+sub new {
+    my ($class, $collection, $archive_info, $verbosity, 
+	$gzip, $groupsize, $outhandle) = @_;
+    my $self = new docproc ();
+    
+    
+    $groupsize=1 unless defined $groupsize;
+    $self->{'collection'} = $collection;
+    $self->{'archive_info'} = $archive_info;
+    $self->{'verbosity'} = $verbosity;
+    $self->{'gzip'} = $gzip;
+    
+    $self->{'groupsize'} = $groupsize;
+    $self->{'gs_count'} = 0;
+    
+    $self->{'outhandle'} = STDERR;
+    $self->{'outhandle'} = $outhandle if defined $outhandle;
+    
+    # set a default for the archive directory
+    $self->{'archive_dir'} = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, "archives");
+    
+    $self->{'sortmeta'} = undef;
+
+    if ($groupsize != 1)
+    {
+	print STDERR "Warning: -groupsize not supported in BBC collection\n";
+	print STDERR "         documents are automatically grouped by date\n";
+    }
+    
+    return bless $self, $class;
+}
+
+sub setarchivedir {
+    my $self = shift (@_);
+    my ($archive_dir) = @_;
+
+    $self->{'archive_dir'} = $archive_dir;
+    &util::mk_all_dir ($archive_dir);
+
+    $self->{'lower_year'} = 1900;
+
+    my @lt_array =localtime(time);
+    my $lt_year = $lt_array[5];
+    $self->{'upper_year'} = 1900 + $lt_year;
+
+    print STDERR "*" x 70, "\n";
+    print STDERR "Processing dates between ";
+    print STDERR "$self->{'lower_year'} and $self->{'upper_year'}\n";
+    print STDERR "*" x 70, "\n\n";
+
+    # set up table of file handles -- one for each year
+    $self->{'date_files'} = [];
+    my $i;
+    for ($i=$self->{'lower_year'}; $i<=$self->{'upper_year'}; $i++)
+    {
+	my $FH = "OUTDATE$i";
+	my $date_file = &util::filename_cat($archive_dir, "$i.gml");
+	my $short_date_file = "$i.gml";
+
+	if (!open ($FH, ">$date_file")) 
+	{
+	    print STDERR "Warning: ";
+	    print STDERR "docsave::new could not write to file $date_file\n";
+	    $self->{'date_files'}->[$i-$self->{'lower_year'}] = undef;
+	    next;
+	}
+
+	$self->{'date_files'}->[$i-$self->{'lower_year'}] 
+	    = { 'short_filename' => $short_date_file, 
+		'long_filename' => $date_file, 
+		'OUTDATE' => $FH };	
+    }
+}
+
+sub process {
+    my $self = shift (@_);
+    my ($doc_obj) = @_;
+
+    my $archive_dir = $self->{'archive_dir'};
+    my $OID = $doc_obj->get_OID();
+    $OID = "NULL" unless defined $OID;
+
+    if (scalar(@{$doc_obj->get_assoc_files()})>0)
+    {
+	# get the document's directory.
+	my $doc_info = $self->{'archive_info'}->get_info($OID);
+	my $doc_dir = "";
+	if (defined $doc_info && scalar(@$doc_info) >= 1) {
+	    # this OID already has an assigned directory, use the
+	    # same one.
+	    $doc_dir = $doc_info->[0];
+	    $doc_dir =~ s/\/?doc\.gml(\.gz)?$//;
+	    
+	} else {
+	    # have to get a new document directory
+	    my $doc_dir_rest = $OID;
+	    my $doc_dir_num = 0;
+	    do {
+		$doc_dir .= "/" if $doc_dir_num > 0;
+		if ($doc_dir_rest =~ s/^(.{1,8})//) {
+		    $doc_dir .= $1;
+		    $doc_dir_num++;
+		}
+	    } while ($doc_dir_rest ne "" && 
+		     ((-d &util::filename_cat ($archive_dir, "$doc_dir.dir")) || 
+		      ($self->{'archive_info'}->size() >= 1024 && $doc_dir_num < 2)));
+	    $doc_dir .= ".dir";
+	}
+
+	&util::mk_all_dir ("$archive_dir/$doc_dir");
+
+	# copy all the associated files, add this information as metadata
+	# to the document
+	my @assoc_files = ();
+	foreach $assoc_file (@{$doc_obj->get_assoc_files()}) {
+	    if (-e $assoc_file->[0]) {
+		my $afile = &util::filename_cat($archive_dir, $doc_dir, $assoc_file->[1]);
+		&util::cp ($assoc_file->[0], $afile);
+		$doc_obj->add_metadata ($doc_obj->get_top_section(), 
+					"gsdlassocfile", 
+					"$assoc_file->[1]:$assoc_file->[2]");
+	    } else {
+		print STDERR "docsave::process couldn't copy the associated file " .
+		    "$assoc_file->[0] to $afile\n";
+	    }
+	}
+    }
+
+    # save this document to appropriate DATE file
+    my $top_section = $doc_obj->get_top_section();
+    my $date_metadata = $doc_obj->get_metadata_element($top_section, "Date");
+
+    my ($year) = ($date_metadata =~ m/^(\d{4})/);
+    my $df_index = $year - $self->{'lower_year'};
+
+    if ($df_index<0)
+    {
+	print STDERR "Warning: Year $year is earlier than lower bound.";
+    }
+    elsif (!defined $self->{'date_files'}->[$df_index])
+    {
+	print STDERR "Warning: No file data present for year $year.";
+    }
+    else
+    {
+	my $df_rec = $self->{'date_files'}->[$df_index];
+	my $FH = $df_rec->{'OUTDATE'};
+
+	$doc_obj->output_section("docsave::".$FH, $top_section);
+    }    
+}
+
+sub close_file_output
+{
+    my ($self) = @_;
+
+    my $i;
+    for ($i=$self->{'lower_year'}; $i<=$self->{'upper_year'}; $i++)
+    {
+	my $date_rec = $self->{'date_files'}->[$i-$self->{'lower_year'}];
+	close $date_rec->{'OUTDATE'};
+
+	my $short_doc_file = $date_rec->{'short_filename'};
+	my $doc_file = $date_rec->{'long_filename'};
+
+	if (-z $doc_file)
+	{
+	    &util::rm($doc_file);
+	    next;
+	}
+
+	if ($self->{'gzip'}) 
+	{
+	    my $doc_file = $self->{'gs_filename'};
+	    `gzip $doc_file`;
+	    $doc_file .= ".gz";
+	    $short_doc_file .= ".gz";
+	    if (!-e $doc_file) 
+	    {
+		print STDERR "error while gzipping: $doc_file doesn't exist\n";
+		return 0;
+	    }
+	}
+
+	# store reference in the archive_info
+	$self->{'archive_info'}->add_info("Year_$i", $short_doc_file);
+    }
+
+    return 1;
+}
+
+1;
Index: /tags/start/bbc/collect/bbc/perllib/nsabuildproc.pm
===================================================================
--- /tags/start/bbc/collect/bbc/perllib/nsabuildproc.pm	(revision 13666)
+++ /tags/start/bbc/collect/bbc/perllib/nsabuildproc.pm	(revision 13666)
@@ -0,0 +1,60 @@
+###########################################################################
+#
+# bbcbuildproc.pm -- 
+# 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.
+#
+###########################################################################
+
+# mgbuildproc for bbc collections. this file (and package name too) should
+# be renamed to the name of the collection currently being built (e.g. 
+# bbc1buildproc)
+
+package nsabuildproc;
+
+use mgbuildproc;
+
+BEGIN {
+    @ISA = ('mgbuildproc');
+}
+
+
+sub new {
+    my ($class, $collection, $source_dir, $build_dir,
+	$verbosity, $outhandle) = @_;
+    my $self = new mgbuildproc ();
+
+    return bless $self, $class;
+}
+
+
+# we want to filter ProgNumbers to remove all whitespace and other 
+# non-alphanumeric characters when creating the index
+# $_[0] == field
+# $_[1] == text
+sub filter_text {
+    my $self = shift (@_);
+
+    if ($self->{'indexing_text'} && ($_[0] eq "ProgNumber" || $_[0] eq "zzabn" )) {
+	$_[1] =~ s/[^\w]//g;
+    }
+}
+
+1;
Index: /tags/start/bbc/collect/bbc/perllib/plugins/BRSPlug.pm
===================================================================
--- /tags/start/bbc/collect/bbc/perllib/plugins/BRSPlug.pm	(revision 13666)
+++ /tags/start/bbc/collect/bbc/perllib/plugins/BRSPlug.pm	(revision 13666)
@@ -0,0 +1,820 @@
+
+# plugin which processes an the BBC Sound archive exported in an ASCII format
+
+package BRSPlug;
+
+use BasPlug;
+use ghtml;
+
+sub BEGIN 
+{
+    @ISA = ('BasPlug');
+    unshift (@INC, "$ENV{'GSDLCOLLECTDIR'}/perllib");
+}
+
+%Exclude = ();
+
+
+# Note: sext is short for scrollable text
+
+#field_id  label     disp_type crit_type width  height  brs_para
+#----------------------------------------------------------------
+#10      sport prdcr     text    text    30      1       T006
+#1       text            sext    text    40      16      TEXT
+#16      scol ref text   text    text    30      1       SCOL
+#19      date            text    date    10      1       D001
+#25      Item title      text    text    20      1       T001
+#26      B/W Seqs        text    text    30      1       S001
+#27      Medium          text    text    30      1       S002
+#28      shot type       text    text    30      1       S003
+#29      B/W Prog/Item   text    text    30      1       S004
+#30      Seqs            text    text    10      1       S005
+#31      Format          text    text    30      1       S006
+#32      prog/item       text    text    30      1       S007
+#35      reg libno       text    text    30      1       S008
+#36      reg tape no     text    text    30      1       S009
+#37      C Indicator     text    text    30      1       S010
+#38      C Holder        text    text    30      1       T002
+#39      cprd ind        text    text    30      1       S011
+#40      cprd name       text    text    30      1       T003
+#44      reference       sext    text    30      5       R001
+#49      prog num        text    text    10      1       PRNO
+#59      news title      text    text    30      1       T005
+#65      cat num         text    text    10      1       CATN
+#72      Record number   text    text    30      1       T007
+#73      rx_date         text    date    10      1       S013
+#74      Music performer text    text    30      2       T008
+#75      Composer        text    text    30      2       T009
+#76      mono/stereo     text    text    30      1       S014
+#77      music medium    text    text    30      1       S015
+#82      Sound Tech      text    text    30      1       S016
+#83      Music publisher text    text    30      1       S017
+#84      music tape      text    text    30      1       T012
+#89      catalogue       text    text    3       1       CODE
+#104     subcat          text    text    10      1       SUBC
+#106     prog title      text    text    40      1       TTLE
+#109     screen type     text    text    10      1       DOCT
+#110     stock title     text    text    30      1       T013
+#113     stock ln 4      text    text    30      1       T015
+#114     stock lib 1     text    text    30      1       S020
+#115     stock lib 2     text    text    30      1       S021
+#----------------------------------------------------------------
+
+
+my @brs_field_table 
+  = (
+      { field_name => "TTLE",  field_id   => 106, label => "Prog title",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 40,      height     => 1       },
+      { field_name => "T001",  field_id   => 25,  label => "Item title",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 20,      height     => 1       },
+      { field_name => "T005",  field_id   => 59,  label => "News title",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "T013",  field_id   => 110, label => "Stock title",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "T007",  field_id   => 72,  label => "Record number",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "TEXT",  field_id   => 1,   label => "Text",
+        disp_type  => "scrl",  crit_type  => "text",
+	width      => 40,      height     => 16      },
+
+      { field_name => "T006",  field_id   => 10,  label => "Sport prdcr",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "SCOL",  field_id   => 16,  label => "Scol ref text",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "D001",  field_id   => 19,  label => "Date",
+        disp_type  => "text",  crit_type  => "date",
+        width      => 10,      height     => 1       },
+      { field_name => "S001",  field_id   => 26,  label => "B/W Seqs",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S002",  field_id   => 27,  label => "Medium",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S003",  field_id   => 28,  label => "Shot type",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S004",  field_id   => 29,  label => "B/W Prog/Item",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S005",  field_id   => 30,  label => "Seqs",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 10,      height     => 1       },
+      { field_name => "S006",  field_id   => 31,  label => "Format",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S007",  field_id   => 32,  label => "Prog/item",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S008",  field_id   => 35,  label => "Reg libno",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S009",  field_id   => 36,  label => "Reg tape no",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S010",  field_id   => 37,  label => "C Indicator",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "T002",  field_id   => 38,  label => "C Holder",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S011",  field_id   => 39,  label => "Cprd ind",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "T003",  field_id   => 40,  label => "Cprd name",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "R001",  field_id   => 44,  label => "Reference",
+        disp_type  => "scrl",  crit_type  => "text",
+        width      => 30,      height     => 5       },
+      { field_name => "PRNO",  field_id   => 49,  label => "Prog num",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 10,      height     => 1       },
+      { field_name => "CATN",  field_id   => 65,  label => "Cat num",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 10,      height     => 1       },
+      { field_name => "S013",  field_id   => 73,  label => "Rx_date",
+        disp_type  => "text",  crit_type  => "date",
+        width      => 10,      height     => 1       },
+      { field_name => "T008",  field_id   => 74,  label => "Music performer",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 2       },
+      { field_name => "T009",  field_id   => 75,  label => "Composer",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 2       },
+      { field_name => "S014",  field_id   => 76,  label => "Mono/stereo",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S015",  field_id   => 77,  label => "Music medium",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S016",  field_id   => 82,  label => "Sound Tech",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S017",  field_id   => 83,  label => "Music publisher",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "T012",  field_id   => 84,  label => "Music tape",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "CODE",  field_id   => 89,  label => "Catalogue",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 3,      height     => 1       },
+      { field_name => "SUBC",  field_id   => 104, label => "Subcat",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 10,      height     => 1       },
+      { field_name => "DOCT",  field_id   => 109, label => "Screen type",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 10,      height     => 1       },
+      { field_name => "T015",  field_id   => 113, label => "Stock ln 4",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S020",  field_id   => 114, label => "Stock lib 1",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S021",  field_id   => 115, label => "Stock lib 2",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       }
+     );
+
+
+my @brs_title_list = ("TTLE", "T001", "T005", "T013", "T007", "RFTI");
+my %cat_num_list = ();
+
+sub new {
+    my ($class) = @_;
+    my $self = new BasPlug ($class, @_);
+
+    return bless $self, $class;
+}
+
+sub get_default_process_exp {
+    my $self = shift (@_);
+
+#    return q^(?i)\.brs$^;
+    return q^b.+^;
+}
+
+my $brs_doc_count = 0;
+my $brs_dot_count = 0;
+my $brs_line_no = 0;
+
+sub brs_error
+{
+    my ($file, $mess, $outhandle) = @_;
+
+    print $outhandle "Malformed BRS recorded at line $brs_line_no in $file:\n";
+    print $outhandle "  $mess\n";
+}
+
+sub read_brs_record
+{
+    my ($recordref, $file, $outhandle) = @_;
+
+    my $extra_trigger = '\s*>';
+    my $text_divider = "-" x 78;
+    my $text_end = '^\.\.[^:]+:$';
+
+    # Print "." to signify processing if enough records have been read in
+    $brs_doc_count++;
+    if (($brs_doc_count % 10) == 0)
+    {
+	print $outhandle ".";
+	$brs_dot_count++;
+	print $outhandle "\n" if (($brs_dot_count % 80) == 0);
+    }
+
+    my $brs_rec = undef;
+    my $line = undef;
+
+    # read in the record
+    my @brs_lines = split /\n/, $$recordref;
+
+    while (scalar(@brs_lines)>0)
+    {
+	$line = shift(@brs_lines);
+	$line =~ s/\cM//g;
+
+	$brs_line_no++;
+
+	if  ($line =~ m/^\.\.([^:]+):$/) 
+	{
+	    my $field_name = $1;
+
+	    if ($field_name eq "TEXT")
+	    {
+		my $text_above = "";
+		my $text_extra = "";
+		my $text_below = "";
+		
+		my $add_mode = "above";
+		
+		while (scalar(@brs_lines)>0)
+		{
+		    last if ($brs_lines[0] =~ m/$text_end/);
+
+		    $line = shift(@brs_lines);
+		    $brs_line_no++;
+		    
+		    if ($line =~ m/^$text_divider/)
+		    {
+			$add_mode = "below";
+			next;
+		    }
+		    
+		    if ($line =~ m/^$extra_trigger/)
+		    {
+			$text_extra .= "$line\n";
+			$add_mode = "below";
+			next;
+		    }
+			
+		    if ($line =~ m/^\.\.[^:]+:/)
+		    {
+			if ($line =~ m/^\.\.TEXT/)
+			{
+			    $add_mode = "above";
+			    next;
+			}
+			else
+			{
+			    brs_error($file, "Unexpected field $line", $outhandle);
+			    # put field name back
+			    unshift(@brs_lines, $line); 
+			    $brs_line_no--;
+			    last;
+			}
+		    }
+		    
+		    if ($line !~ m/^\s+(-){10,}$/)
+		    {
+			if ($add_mode eq "above")
+			{
+			    $text_above .= "$line ";
+			}
+			else
+			{
+			    $text_below .= "$line ";
+			}
+		    }
+		}
+
+		$brs_rec->{TEXTA} .= $text_above if ($text_above ne "");
+		$brs_rec->{TEXTB} .= $text_below if ($text_below ne "");
+		$brs_rec->{TEXTE} .= $text_extra if ($text_extra ne "");
+	    }
+	    elsif ($field_name =~ /^RF/)
+	    {
+		# read zz fields until end of record
+		    
+		while (scalar(@brs_lines)>0)
+		{
+		    my $line_ahead = $brs_lines[0];
+		    last if ($line_ahead =~ m/^\.\.[^:]+:$/);
+					
+		    $line = shift(@brs_lines);
+		    $brs_line_no++;
+			    
+		    if (!defined($brs_rec->{$field_name}))
+		    {
+			$brs_rec->{$field_name} = [$line];
+		    }
+		    else
+		    {
+			push(@{$brs_rec->{$field_name}},$line);
+		    }
+		}
+	    }
+	    else
+	    {
+		my $field_entry = "";
+		while ($brs_lines[0] !~ m/^\.\.[^:]+:$/)
+		{
+		    $field_entry .= shift(@brs_lines);
+		    $brs_line_no++;
+		    last if (scalar(@brs_lines)==0);
+		}		    
+
+		if (!defined($brs_rec->{$field_name}))
+		{
+		    $brs_rec->{$field_name} = $field_entry;
+		}
+		else
+		{
+		    brs_error($file, "$field_name already defined.", $outhandle);
+		}
+	    }		
+	}
+	else
+	{
+	    brs_error($file, "Malformed field: $line.", $outhandle);
+	}
+    }
+
+    # format the programme number if required
+    &format_prognum($brs_rec);
+
+    return ($brs_rec);
+}
+
+my $brs_processed_count = 0;
+
+sub brs_full_record_in_html
+{
+    my ($doc_obj,$cursection,$brs_rec) = @_;
+
+    my $html_table = "";
+    my $table_line = "";
+    my $cell_count = 0;
+    my $long_lines = "";
+
+    my $i;
+    for ($i=0; $i<=$#brs_field_table; $i++)
+    {
+	my $field_name = $brs_field_table[$i]->{'field_name'};
+	if (defined($brs_rec->{$field_name}))
+	{
+	    my $field_label = $brs_field_table[$i]->{'label'};
+	    my $field_value = $brs_rec->{$field_name};
+
+	    # these fields get their own line
+	    if ($field_label =~ /^(Prog|Item|News|Stock) title$/) {
+		my $safe_value = $field_value;
+		&ghtml::urlsafe ($safe_value);
+		$long_lines .= "<tr valign=top><td><b>$field_label:</b></td><td colspan=5>";
+		$long_lines .= "<a href=\"_httpquerytitle_&q=$safe_value\">$field_value</a></td></tr>\n";
+		$long_lines .= "$field_value</td></tr>\n";
+		
+	    } else {
+		
+		if (($cell_count>0) && ($cell_count%3 == 0))
+		{
+		    $html_table .= "\n<tr valign=top>\n$table_line\n</tr>\n";
+		    $table_line = "";
+		}
+		$cell_count++;
+		if ($field_name eq "D001") # a Dublin core style date
+		{
+		    my @mon_convert 
+			= ("Jan", "Feb", "Mar", "Apr", "May", "Jun",
+			   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
+		    
+		    my ($year,$monnum,$day) 
+			= ($field_value =~ m/(\d{4})(\d{2})(\d{2})/);
+		    my $moneng = $mon_convert[$monnum-1];
+		    
+		    $field_value = "$day $moneng $year";
+
+		} elsif ($field_name eq "PRNO") {
+		    my $safe_value = $field_value;
+		    &ghtml::urlsafe ($safe_value);
+		    $field_value = "<a href=\"_httpqueryprogname_&q=$safe_value\">$field_value</a>";
+
+		} elsif ($field_name eq "CATN") {
+		    my $safe_value = $field_value;
+		    &ghtml::urlsafe ($safe_value);
+		    $field_value = "<a href=\"_httpquerycatnum_&q=$safe_value\">$field_value</a>";
+
+		} elsif ($field_name eq "T003") {
+		    my $safe_value = $field_value;
+		    &ghtml::urlsafe ($safe_value);
+		    $field_value = "<a href=\"_httpqueryzzabn_&q=$safe_value\">$field_value</a>";
+		}
+		
+		$table_line .= "<td><b>$field_label:</b></td><td>$field_value</td>\n";
+	    }
+	}
+    }
+
+    if ($cell_count%3 != 0) {
+	$table_line .= "<td colspan=" . (3-($cell_count%3))*2 . "></td>";
+    }
+
+    $html_table .= "\n<tr>\n$table_line\n</tr>\n";    
+    $html_table = "<table>\n$long_lines$html_table\n</table>\n";
+
+    $doc_obj->add_utf8_text($cursection, $html_table);
+}
+
+sub process_brs_record
+{
+    my ($processor, $brs_rec, $file, $outhandle) = @_;
+
+    if (defined($brs_rec))
+    {
+
+	# only include those records in the chosen subcats - these lines
+	# should be commented out to build the entire collection
+
+	# National Sound Archive collection
+#	if (!defined ($brs_rec->{'SUBC'}) || 
+#	    $brs_rec->{'SUBC'} !~ /^(RADCOMP|RADIOX|RADPROG|RADNEWS|BDSPROG|UNCATRAD|RADIOREF|WILDSOUND)$/) {
+#	    return;
+#	}
+
+	# British Film Institute collection
+#	if (!defined ($brs_rec->{'SUBC'}) || 
+#	    $brs_rec->{'SUBC'} !~ /^(LONPROG|NEWS)$/) {
+#	    return;
+#	}
+
+	# "the rest" collection
+	if (!defined ($brs_rec->{'SUBC'}) || 
+	    $brs_rec->{'SUBC'} =~ /^(LONPROG|NEWS|RADCOMP|RADIOX|RADPROG|RADNEWS|BDSPROG|UNCATRAD|RADIOREF|WILDSOUND)$/) {
+	    return;
+	}
+
+	# don't include the secret stuff ;-)
+	if (defined ($brs_rec->{'SUBC'}) && $brs_rec->{'SUBC'} eq "HISTORY") {
+	    print STDERR "\nexcluding secret stuff - line $brs_line_no in $file\n";
+	    return;
+	}
+
+
+	my $doc_obj = new doc ($file, "indexed_doc");
+	$brs_processed_count++;
+
+	my $cursection = $doc_obj->get_top_section();
+
+	my $found_match = "no";
+
+	my $pot_title;	
+	foreach $pot_title ( @brs_title_list )
+	{
+	    if (defined ($brs_rec->{$pot_title}))
+	    {
+		my $title = "";
+
+		if ($pot_title =~ m/^zz/)
+		{
+		    my $zz_join = join(" ", @{$brs_rec->{$pot_title}});
+		    my @zz_split = split(" ", $zz_join);
+		    map { $title .= "$_ " if ($_ !~ m/^xx/); } @zz_split;
+		}
+		else
+		{
+		    $title =  $brs_rec->{$pot_title};
+		}
+
+		my $tl_ref = $doc_obj->get_metadata ($cursection, "Title");
+
+		if (scalar(@$tl_ref==0))
+		{
+		    $doc_obj->add_utf8_metadata ($cursection, "Title", $title);
+		}
+		else
+		{
+		    my $exists = "no";
+		    
+		    map { $exists = "yes" if ($title eq $_); } @$tl_ref;
+		    if ($exists eq "no")
+		    {
+			$doc_obj->add_utf8_metadata($cursection, "Title", $title);
+		    }
+		}
+		$found_match = "yes";
+	    }
+	}
+	if ($found_match eq "no")
+	{
+	    if (defined($brs_rec->{TEXTA}))
+	    {
+		my $sub_title = substr($brs_rec->{TEXTA},0,60) . " ... ";
+		$doc_obj->add_utf8_metadata ($cursection, "Title", $sub_title);
+	    }
+	    elsif (defined($brs_rec->{TEXTB}))
+	    {
+		my $sub_title = substr($brs_rec->{TEXTB},0,60) . " ... ";
+		$doc_obj->add_utf8_metadata ($cursection, "Title", $sub_title);
+	    }
+	    else
+	    {
+		print $outhandle "\nNo title or text for record ending at line ";
+		print $outhandle $brs_line_no-1, " in $file\n";
+	    }
+	}
+
+	if (defined($brs_rec->{'T001'})) # item title
+	{
+	    $doc_obj->add_utf8_metadata ($cursection, "ItemTitle", $brs_rec->{'T001'});
+	}
+	
+	if (defined($brs_rec->{'D001'})) # date
+	{
+	    $doc_obj->add_utf8_metadata ($cursection, "Date", $brs_rec->{'D001'});
+	}
+	else
+	{
+	    print $outhandle "\nNo date for record ending at line ";
+	    print $outhandle $brs_line_no-1, " in $file\n";
+	}
+
+	if (defined($brs_rec->{'PRNO'})) # programme number
+	{
+	    $doc_obj->add_utf8_metadata ($cursection, "ProgNumber", $brs_rec->{'PRNO'});
+	}
+
+	if (defined($brs_rec->{'CATN'})) # catalogue number
+	{
+	    $doc_obj->add_utf8_metadata ($cursection, "CatNum", $brs_rec->{'CATN'});
+	}
+
+	# RFAN, RFAB and T003 fields
+	if (defined($brs_rec->{'RFAB'}) || defined($brs_rec->{'RFAN'}) || defined($brs_rec->{'T003'}))
+	{
+	    my $zzabn = "";
+	    if (defined($brs_rec->{'RFAB'})) {
+		foreach my $a (@{$brs_rec->{'RFAB'}}) {
+		    $a =~ s/[^a-zA-Z0-9]//g;
+		    $zzabn .= " " . $a;
+		}
+	    } 
+	    if (defined($brs_rec->{'RFAN'})) {
+		foreach my $a (@{$brs_rec->{'RFAN'}}) {
+		    $a =~ s/[^a-zA-Z0-9]//g;
+		    $zzabn .= " " . $a;
+		}
+	    } 
+	    if (defined($brs_rec->{'T003'})) {
+		my $value = $brs_rec->{'T003'};
+		$value =~ s/[^a-zA-Z0-9]//g;
+		$zzabn .= " " . $value;
+	    } 
+	    $doc_obj->add_utf8_metadata ($cursection, "zzabn", $zzabn);
+	}
+
+	if (defined($brs_rec->{'RFN'}))
+	{
+	    my $name;
+	    foreach $name (@{$brs_rec->{'RFN'}})
+	    {
+		$doc_obj->add_utf8_metadata ($cursection, "People", $name);
+	    }
+	}
+
+	brs_full_record_in_html($doc_obj,$cursection,$brs_rec);
+
+	if (defined($brs_rec->{TEXTA}))
+	{
+
+	    my $desc_texta = "<h3>Description</h3>$brs_rec->{TEXTA}";
+	    $doc_obj->add_utf8_text ($cursection, $desc_texta);
+
+	    if (defined($brs_rec->{TEXTE}))
+	    {
+		my $raw_texte = $brs_rec->{TEXTE};
+		$raw_texte =~ s/^\s*>\s*/<li>/mg;
+		
+		my $test_empty = $raw_texte;
+		$test_empty =~ s/(<li>)+//g;
+		
+		if ($test_empty ne "")
+		{
+		    my $desc_texte = $raw_texte;
+		    $desc_texte =~ s/^<li>(.*)$/<li><i>$1<\/i>/mg;
+		    $desc_texte = "<p>Additional:<ul>$desc_texte</ul>";
+		    $doc_obj->add_utf8_text ($cursection, $desc_texte);
+		}
+	    }
+	}
+
+	if (defined($brs_rec->{TEXTB}))
+	{
+	    my $desc_textb = "<h3>Comments</h3>$brs_rec->{TEXTB}";
+	    $doc_obj->add_utf8_text($cursection, $desc_textb);
+	}
+
+	my $full_text = "";
+	$full_text .= "$brs_rec->{TEXTA}\n" if (defined($brs_rec->{TEXTA}));
+	$full_text .= "$brs_rec->{TEXTE}\n" if (defined($brs_rec->{TEXTE}));
+	$full_text .= "$brs_rec->{TEXTB}\n" if (defined($brs_rec->{TEXTB}));
+
+	my @zz_list = ( "RFPG", "RFLO", "RFN" );
+	my $zz;
+	foreach $zz ( @zz_list)
+	{
+	    if (defined($brs_rec->{$zz}))
+	    {
+		my $filtered_text = "";
+
+		my $name;
+		foreach $name (@{$brs_rec->{$zz}})
+		{
+		    my @split_zz = split(' ',$name);
+		    map { $filtered_text .= "$_ " if ($_ =~ m/^xx/) } @split_zz
+		}
+	
+		$full_text .= "$filtered_text\n";
+	    }
+	}
+
+	# format zz fields (tail end of record)
+	my $zz_html = "<table>\n";
+
+	my $pot_zz;
+	foreach $pot_zz (keys %{$brs_rec})
+	{
+	    if ($pot_zz =~ m/^RF/)
+	    {
+		my $zz = $pot_zz;
+		my $name;
+		foreach $name (@{$brs_rec->{$zz}})
+		{
+		    if ($zz eq "RFN") {
+			my $safe_name = $name;
+			&ghtml::urlsafe ($safe_name);
+			$zz_html .= "<tr><td><b>$zz:</b></td><td><a href=\"_httpquerypeople_&q=$safe_name\">$name</a></td></tr>\n";
+		    } elsif ($zz =~ /^RFA[BN]$/) {
+			my $safe_name = $name;
+			&ghtml::urlsafe ($safe_name);
+			$zz_html .= "<tr><td><b>$zz:</b></td><td><a href=\"_httpqueryzzabn_&q=$safe_name\">$name</a></td></tr>\n";
+
+		    } else {
+			$zz_html .= "<tr><td><b>$zz:</b></td><td>$name</td></tr>\n";
+		    }
+		}
+	    }
+	}
+	$zz_html .= "</table>\n";
+	$doc_obj->add_utf8_text($cursection, $zz_html);
+
+	# add OID - we'll use the catalog number (hoping it's unique)
+	my $cat_num = $brs_rec->{'CATN'};
+	if (!defined $cat_num) {
+	    print $outhandle "\n***** No catalogue number for record ending at line ";
+	    print $outhandle $brs_line_no-1, " in $file - THIS RECORD WILL BE IGNORED\n";
+	    foreach my $v (keys(%$brs_rec)) {
+		if (ref($brs_rec->{$v}) eq "ARRAY") {
+		    foreach my $i (@{$brs_rec->{$v}}) {
+			print STDERR "$v -> $i\n";
+		    }
+		} else {
+		    print STDERR $v . " -> " . $brs_rec->{$v} . "\n";
+		}
+	    }
+	    return;
+	}
+	if (defined ($cat_num_list{$cat_num})) {
+	    print $outhandle "WARNING: catalog number $cat_num used more than once\n";
+	}
+	$doc_obj->set_OID ("bbc" . $cat_num);
+	$cat_num_list{$cat_num} = 1;
+    
+	# process the document
+	$processor->process($doc_obj);
+    }
+    else
+    {
+	print $outhandle "BRS record empty\n";
+    }
+    
+}
+
+sub read {
+    my $self = shift (@_);
+    my ($pluginfo, $base_dir, $file, $metadata, $processor, $maxdocs) = @_;
+    my $outhandle = $self->{'outhandle'};
+
+    my $filename = &util::filename_cat($base_dir, $file);
+#    return 0 if $self->{'block_exp'} ne "" && $filename =~ /$self->{'block_exp'}/;
+    if ($filename !~ /$self->{'process_exp'}/ || !-f $filename) {
+	return undef;
+    }
+#    my $plugin_name = ref ($self);
+    $file =~ s/^[\/\\]+//; # $file often begins with / so we'll tidy it up
+    
+    # create a new document
+#    my $doc_obj = new doc ($filename, "indexed_doc");
+    
+    # read in file ($text will be in utf8)
+#    my $text = "";
+#    $self->read_file ($filename, \$text);
+
+#    if ($text !~ /\w/) {
+#	print $outhandle "$plugin_name: ERROR: $file contains no text\n" if $self->{'verbosity'};
+#	return 0;
+#    }
+
+    # text is always plain ascii
+    undef $/;
+    open (FILE, $filename) || die;
+    my $text = <FILE>;
+    close FILE;
+    $/ = "\n";
+
+
+    # include any metadata passed in from previous plugins 
+    # note that this metadata is associated with the top level section
+#    $self->extra_metadata ($doc_obj, $doc_obj->get_top_section(), $metadata);
+
+    print $outhandle "BBC Sound Archive Plug for BRS format: processing $file\n"
+	if $self->{'verbosity'} > 1;
+
+    # reset line number count
+    $brs_line_no = 0;
+
+    my @records = split /\*\*\* BRS DOCUMENT BOUNDARY \*\*\*\s+/, $text;
+    $text = "";
+
+    foreach $record (@records) {
+	next if $record !~ /\w/; # first record will be empty
+	my $brs_rec = &read_brs_record(\$record, $file, $self->{'outhandle'});
+	&process_brs_record ($processor, $brs_rec, $file, $self->{'outhandle'});
+    }
+
+    print $outhandle "\nNumber of BRS records = $brs_doc_count\n";
+    print $outhandle "Number of BRS records processed = $brs_processed_count\n";
+
+    return 1; # processed the file
+}
+
+sub end {
+    my $self = shift (@_);
+    my ($processor) = @_;
+
+    $processor->close_file_output() if defined $processor;
+}
+
+sub format_prognum {
+    my ($brs_rec) = @_;
+
+    return unless defined $brs_rec->{'PRNO'};
+
+    my $old_num = $brs_rec->{'PRNO'};
+
+    if (defined $brs_rec->{'magazine'}) {
+	if ($brs_rec->{'PRNO'} =~ /^\S\S /) { # space at position 3
+	    if ($brs_rec->{'magazine'} =~ /(\d+)/) {
+		# algorithm A
+		my $magnumber = $1;
+		$brs_rec->{'PRNO'} =~ /(\S\S) (\S\S)(\S+)/;
+		$brs_rec->{'PRNO'} = $2 . $1 . $3 . $magnumber;
+	    } else {
+		# common algorithm
+		$brs_rec->{'PRNO'} =~ /(\S\S) (\S\S)(\S+)/;
+		$brs_rec->{'PRNO'} = $2 . $1 . $3;
+	    }
+	}
+    } else {
+	if ($brs_rec->{'PRNO'} =~ /^\S\S / && $brs_rec->{'PRNO'} !~ /:/) { # space at position 3 and no colon
+	    # common algorithm
+	    $brs_rec->{'PRNO'} =~ /(\S\S) (\S\S)(\S+)/;
+	    $brs_rec->{'PRNO'} = $2 . $1 . $3;
+	} elsif ($brs_rec->{'PRNO'} =~ /^(\S):(\S\S) (\S\S)(\S+)/) { # colon at position 2 and space at position 5
+	    # algorithm B
+	    $brs_rec->{'PRNO'} = $3 . $2 . $4 . $1;
+	}
+    }
+
+#    if ($brs_rec->{'PRNO'} ne $old_num) {
+#	print STDERR "\n$old_num ... " . $brs_rec->{'PRNO'} . "\n";
+#    }
+}
+
+1;
Index: /tags/start/bbc/collect/bbcother/etc/collect.cfg
===================================================================
--- /tags/start/bbc/collect/bbcother/etc/collect.cfg	(revision 13666)
+++ /tags/start/bbc/collect/bbcother/etc/collect.cfg	(revision 13666)
@@ -0,0 +1,40 @@
+creator         sjboddie@cs.waikato.ac.nz
+maintainer      sjboddie@cs.waikato.ac.nz
+public          true
+beta            true
+indexes         document:Title paragraph:People document:ProgNumber document:CatNum document:zzabn document:text
+defaultindex    document:text
+maxnumeric      256 
+
+plugin          ZIPPlug
+plugin          GMLPlug 
+plugin          ArcPlug 
+plugin          RecPlug 
+plugin          BRSPlug -input_encoding ascii
+
+dontgdbm ProgNumber
+dontgdbm People
+dontgdbm CatNum
+dontgdbm zzabn
+
+ccscols         bbcother nsa bfi
+
+# Collection specific metadata
+#--
+collectionmeta  collectionname      "BBC (1900-2003)"
+collectionmeta  iconcollection      "_httpprefix_/collect/bbcother/images/bbc_online.gif"
+collectionmeta .document:Title      "titles"
+collectionmeta .paragraph:People    "people"
+collectionmeta .document:ProgNumber "programme numbers"
+collectionmeta .document:CatNum     "catalogue numbers"
+collectionmeta .document:zzabn      "RFAB/RFAN"
+collectionmeta .document:text       "all fields"
+collectionmeta collectionextra      ""
+
+
+format DocumentButtons ""
+format DocumentHeading ""
+
+format          SearchVList \
+    "<td valign=top>[link][icon][/link]</td><td>{If}{[ItemTitle],[ItemTitle]; [Title],[Title]}</td><td width=160>[Date]</td>"
+
Index: /tags/start/bbc/collect/bfi/etc/collect.cfg
===================================================================
--- /tags/start/bbc/collect/bfi/etc/collect.cfg	(revision 13666)
+++ /tags/start/bbc/collect/bfi/etc/collect.cfg	(revision 13666)
@@ -0,0 +1,40 @@
+creator         sjboddie@cs.waikato.ac.nz
+maintainer      sjboddie@cs.waikato.ac.nz
+public          true
+beta            true
+indexes         document:Title paragraph:People document:ProgNumber document:CatNum document:zzabn document:text
+defaultindex    document:text
+maxnumeric      256 
+
+plugin          ZIPPlug
+plugin          GMLPlug 
+plugin          ArcPlug 
+plugin          RecPlug 
+plugin          BRSPlug -input_encoding ascii
+
+dontgdbm ProgNumber
+dontgdbm People
+dontgdbm CatNum
+dontgdbm zzabn
+
+ccscols         bfi nsa bbcother
+
+# Collection specific metadata
+#--
+collectionmeta  collectionname      "British Film Institute (1900-2003)"
+collectionmeta  iconcollection      "_httpprefix_/collect/bfi/images/bbc_online.gif"
+collectionmeta .document:Title      "titles"
+collectionmeta .paragraph:People    "people"
+collectionmeta .document:ProgNumber "programme numbers"
+collectionmeta .document:CatNum     "catalogue numbers"
+collectionmeta .document:zzabn      "RFAB/RFAN"
+collectionmeta .document:text       "all fields"
+collectionmeta collectionextra      ""
+
+
+format DocumentButtons ""
+format DocumentHeading ""
+
+format          SearchVList \
+    "<td valign=top>[link][icon][/link]</td><td>{If}{[ItemTitle],[ItemTitle]; [Title],[Title]}</td><td width=160>[Date]</td>"
+
Index: /tags/start/bbc/collect/nsa/etc/collect.cfg
===================================================================
--- /tags/start/bbc/collect/nsa/etc/collect.cfg	(revision 13666)
+++ /tags/start/bbc/collect/nsa/etc/collect.cfg	(revision 13666)
@@ -0,0 +1,40 @@
+creator         sjboddie@cs.waikato.ac.nz
+maintainer      sjboddie@cs.waikato.ac.nz
+public          true
+beta            true
+indexes         document:Title paragraph:People document:ProgNumber document:CatNum document:zzabn document:text
+defaultindex    document:text
+maxnumeric      256 
+
+plugin          ZIPPlug
+plugin          GMLPlug 
+plugin          ArcPlug 
+plugin          RecPlug 
+plugin          BRSPlug -input_encoding ascii
+
+dontgdbm ProgNumber
+dontgdbm People
+dontgdbm CatNum
+dontgdbm zzabn
+
+ccscols         nsa bfi bbcother
+
+# Collection specific metadata
+#--
+collectionmeta  collectionname      "National Sound Archives (1900-2003)"
+collectionmeta  iconcollection      "_httpprefix_/collect/nsa/images/bbc_online.gif"
+collectionmeta .document:Title      "titles"
+collectionmeta .paragraph:People    "people"
+collectionmeta .document:ProgNumber "programme numbers"
+collectionmeta .document:CatNum     "catalogue numbers"
+collectionmeta .document:zzabn      "RFAB/RFAN"
+collectionmeta .document:text       "all fields"
+collectionmeta collectionextra      ""
+
+
+format DocumentButtons ""
+format DocumentHeading ""
+
+format          SearchVList \
+    "<td valign=top>[link][icon][/link]</td><td>{If}{[ItemTitle],[ItemTitle]; [Title],[Title]}</td><td width=160>[Date]</td>"
+
Index: /tags/start/cstr/etc/collect.cfg
===================================================================
--- /tags/start/cstr/etc/collect.cfg	(revision 13666)
+++ /tags/start/cstr/etc/collect.cfg	(revision 13666)
@@ -0,0 +1,37 @@
+creator       sjboddie@cs.waikato.ac.nz
+maintainer    sjboddie@cs.waikato.ac.nz
+public        true
+beta          true
+key           84138963
+indexes        document:text
+defaultindex  document:text
+#plugins       GMLPlug PrePlug ArcPlug RecPlug
+plugin		GMLPlug
+plugin		PrePlug
+plugin		ArcPlug
+plugin		RecPlug
+macrofiles    style.dm base.dm query.dm help.dm \
+              pref.dm about.dm home.dm document.dm \
+	      status.dm cstr.dm authen.dm english.dm \
+	      chinese.dm maori.dm
+classify      CSTRList
+
+
+format        QueryResults "<td valign=top>[link][icon][/link]</td><td valign=top>{If}{[parent(Top):Summary],[parent(Top):Summary],[Summary]}<br><b>Abstract:</b>{Or}{[parent(Top):Description],[Description], None}</td>"
+
+format        result "<td valign=top>[icon]</td><td valign=top>{If}{[parent(Top):Summary],[parent(Top):Summary],[Summary]}<br><b>Abstract:</b>{Or}{[parent(Top):Description],[Description], None}</td>"
+format        ListBrowse "<td valign=top>[link][icon][/link]</td><td>{If}{[classifytype],[Title],<a href=_httpcurrentdocument_&gg=postscript&gga=[cgisafe:Source]>[Source]</a>&#044; <i>[Date]</i><br>[Summary]}</td>"
+format        DocumentTopPages false
+format        DocumentButtons  "Detach|Highlight|Expand Text"
+
+
+collectionmeta collectionname  "Computer Science Technical Reports"
+collectionmeta collectionextra "Your source for up-to-date academic computer science publications!  This collection provides an index to\ncomputer science technical reports that we have downloaded from selected sites on the Internet.  The reports are mostly in English, but\nthere are some in a variety of different languages.  The collection contains many large documents such as PhD theses.  Every single word on\nevery page of every report is indexed -- not just the first few words, as in many other search engines -- so you can search for things that\noccur near the end of the document (like references) too.\n<p>This collection contains <b>_about:numdocs_</b> technical reports located in <b>296</b> sites around the world. The <b>_about:nummegbytes_ Mb</b> of text is extracted from <b>34 Gb</b> of PostScript by a <a\nhref=http://www.nzdl.org/cgi-bin/gw?c=cstr&a=page&p=Tec&z=x-D4xPMx>system developed here</a>.  All <b>_about:numwords_</b> words from <b>1.3 Million</b>\npages are indexed. The collection also contains <b>28846</b> figures extracted from the reports."
+
+collectionmeta iconcollection "http://www.nzdl.org/gsdl/collect/cstr/images/cstr.gif"
+collectionmeta iconcollectionsmall "http://www.nzdl.org/gsdl/collect/cstr/images/cstrsm.gif"
+
+collectionmeta .section:text  "document pages"
+collectionmeta .document:text "entire documents"
+receptionist   http://www.nzdl.org/cgi-bin/cstrlibrary?a=p&p=about&c=cstr
+
Index: /tags/start/cstr/macros/cstr.dm
===================================================================
--- /tags/start/cstr/macros/cstr.dm	(revision 13666)
+++ /tags/start/cstr/macros/cstr.dm	(revision 13666)
@@ -0,0 +1,94 @@
+package document
+
+_pagetitle_ [c=cstr] {_collectionname_}
+
+_javapostscript_ [c=cstr] {
+	ps\_on = new Image(_widthepsx_, _heightepsx_);
+	ps\_on.src = "_httpiconepson_";
+	ps\_off = new Image(_widthepsx_, _heightepsx_);
+	ps\_off.src = "_httpiconepsof_";
+}
+
+_javaviewtext_ [c=cstr] {
+        viewtext\_on = new Image(_widthetextx_, _heightetextx_); 
+        viewtext\_on.src = "_httpiconetexton_";
+        viewtext\_off = new Image(_widthetextx_, _heightetextx_); 
+        viewtext\_off.src = "_httpiconetextof_";
+}
+
+_javaabstract_ [c=cstr] {
+        abstract\_on = new Image(_widtheabstrx_, _heighteabstrx_); 
+        abstract\_on.src = "_httpiconeabstron_";
+        abstract\_off = new Image(_widtheabstrx_, _heighteabstrx_); 
+        abstract\_off.src = "_httpiconeabstrof_";
+}
+
+_javafigures_ [c=cstr] {
+        figures\_on = new Image(_widthefigx_, _heightefigx_); 
+        figures\_on.src = "_httpiconefigon_";
+        figures\_off = new Image(_widthefigx_, _heightefigx_); 
+        figures\_off.src = "_httpiconefigof_";
+}
+
+
+_iconpostscript_ [c=cstr] {<img name="ps" src="_httpiconepsof_" width=_widthepsx_ height=_heightepsx_ alt="_texticonpostscript_" border=0>}
+_iconpostscript_ [c=cstr,v=1] {_texticonpostscript_}
+
+_iconviewtext_ [c=cstr] {<img name="viewtext" src="_httpiconetextof_" width="_widthetextx_" height="_heightetextx_" alt="_texticonviewtext_" border="0">}
+_iconviewtext_ [c=cstr,v=1] {_texticonviewtext_}
+
+_iconabstract_ [c=cstr] {<img name="abstract" src="_httpiconeabstrof_" width="_widtheabstrx_" height="_heighteabstrx_" alt="_texticonabstract_" border="0">}
+_iconabstract_[c=cstr,v=1] {_texticonabstract_}
+
+_iconfigures_ [c=cstr] {<img name="figures" src="_httpiconefigof_" width="_widthefigx_" height="_heightefigx_" alt="_texticonfigures_" border="0">}
+_iconfigures_ [c=cstr,v=1] {_texticonfigures_}
+
+
+_imagepostscript_ [c=cstr] {<a href="_httpcurrentdocument_&gg=postscript&gga=_1_" onMouseover = "img\_on('ps')"
+onMouseout = "img\_off('ps')">_iconpostscript_</a>}
+_imagepostscript_ [c=cstr,v=1] {<a href="_httpcurrentdocument_&gg=postscript&gga=_1_">_texticonpostscript_</a><br>}
+
+_imageviewtext_ [c=cstr] {<a href="_httpcurrentdocument_&gg=text" onMouseover = "img\_on('viewtext')"
+onMouseout = "img\_off('viewtext')">_iconviewtext_</a>}
+_imageviewtext_ [c=cstr,v=1] {<a href="_httpcurrentdocument_&gg=text">_texticonviewtext_</a><br>}
+
+_imageabstract_ [c=cstr] {<a href="_httpcurrentdocument_&gg=abstract" onMouseover = "img\_on('abstract')"
+onMouseout = "img\_off('abstract')">_iconabstract_</a>}
+_imageabstract_ [c=cstr,v=1] {<a href="_httpcurrentdocument_&gg=abstract">_texticonabstract_</a><br>}
+
+_imagefigures_ [c=cstr] {<a href="_httpcurrentdocument_&gg=figures" onMouseover = "img\_on('figures')"
+onMouseout = "img\_off('figures')">_iconfigures_</a>}
+_imagefigures_ [c=cstr,v=1] {<a href="_httpcurrentdocument_&gg=figures">_texticonfigures_</a><br>}
+
+
+_httpiconepsof_ [c=cstr] {_httpimg_/epsof.gif}
+_httpiconepson_ [c=cstr] {_httpimg_/epson.gif}
+_widthepsx_ [c=cstr] {64}
+_heightepsx_ [c=cstr] {30}
+
+_httpiconetextof_ [c=cstr] {_httpimg_/etextof.gif}
+_httpiconetextof_ [c=cstr,l=mi] {_httpimg_/metextof.gif}
+_httpiconetexton_ [c=cstr] {_httpimg_/etexton.gif}
+_httpiconetexton_ [c=cstr,l=mi] {_httpimg_/metexton.gif}
+_widthetextx_ [c=cstr] {30}
+_widthetextx_ [c=cstr,l=mi] {31}
+_widthetextx_ [c=cstr] {30}
+_heightetextx_ [c=cstr] {30}
+
+_httpiconeabstrof_ [c=cstr] {_httpimg_/eabstrof.gif}
+_httpiconeabstron_ [c=cstr] {_httpimg_/eabstron.gif}
+_widtheabstrx_ [c=cstr] {59}
+_heighteabstrx_ [c=cstr] {30}
+
+_httpiconefigof_ [c=cstr] {_httpimg_/efigof.gif}
+_httpiconefigon_ [c=cstr] {_httpimg_/efigon.gif}
+_widthefigx_ [c=cstr] {47}
+_heightefigx_ [c=cstr] {30}
+
+
+_texticonpostscript_ [c=cstr] {Download postscript of this document}
+_texticonviewtext_ [c=cstr] {View the text of this page}
+_texticonabstract_ [c=cstr] {View the abstract of this document}
+_texticonfigures_ [c=cstr] {View figures extracted from document postscript}
+
+_texticonviewtext_ [c=cstr,l=mi] {Titiro ki ng&auml; kupu kua tuhia k&euml; ki te rorohiko}
Index: /tags/start/cstr/perllib/classify/CSTRList.pm
===================================================================
--- /tags/start/cstr/perllib/classify/CSTRList.pm	(revision 13666)
+++ /tags/start/cstr/perllib/classify/CSTRList.pm	(revision 13666)
@@ -0,0 +1,94 @@
+###########################################################################
+#
+# CSTRList.pm --
+# 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.
+#
+###########################################################################
+
+# hacked about version of List classifier for use with cstr collection. 
+# Creates list of Source's (ftp sites), each of which contains a list of
+# those documents originating from Source.
+
+# note that 'Source' metadata contains entire path to document so
+# we strip it down to get the ftp site.
+
+package CSTRList;
+
+use sorttools;
+
+sub new {
+    my ($class, @options) = @_;
+
+    my $listname = &util::filename_cat($ENV{'GSDLHOME'},"perllib/classify/List.pm"); 
+    if (-e $listname) { require $listname; }
+    else { die "CSTRList ERROR - couldn't find classifier \"$listname\"\n"; }
+
+    return bless {
+	'list'=>{},
+    }, $class;
+}
+
+sub init {
+    my $self = shift (@_);
+    $self->{'list'} = {};
+}
+
+sub classify {
+    my $self = shift (@_);
+    my ($doc_obj) = @_;
+
+    my $doc_OID = $doc_obj->get_OID();
+
+    my $source = $doc_obj->get_metadata_element ($doc_obj->get_top_section(), 'Source');
+
+    if (defined $source) {
+	my ($ftp_site) = $source =~ /^((ftp:\/\/)?([^\/\\]*))/;
+	print STDERR "CSTRList: Warning: ftp_site undefined\n" unless defined $ftp_site;
+	if (!defined ($self->{'list'}->{$ftp_site})) {
+	    my ($listclassobj);
+	    eval ("\$listclassobj = new List(\"sort=Date\", \"title=\$ftp_site\")");
+	    die "$@" if $@;
+	    $listclassobj->init();
+	    $self->{'list'}->{$ftp_site} = $listclassobj;
+	    $self->{'list'}->{$ftp_site}->classify ($doc_obj);
+	} else {
+	    $self->{'list'}->{$ftp_site}->classify ($doc_obj);
+	}	    
+    }
+}
+
+sub get_classify_info {
+    my $self = shift (@_);
+
+    # organise into classification structure
+    my %classifyinfo = ('classifytype'=>'List',
+			'Title'=>'Browse',
+			'contains'=>[]);
+    foreach $ftp_site (sort keys %{$self->{'list'}}) {
+	push (@{$classifyinfo{'contains'}}, 
+	      $self->{'list'}->{$ftp_site}->get_classify_info());
+    }
+    
+    return \%classifyinfo;
+}
+
+
+1;
Index: /tags/start/cstr/perllib/plugins/PrePlug.pm
===================================================================
--- /tags/start/cstr/perllib/plugins/PrePlug.pm	(revision 13666)
+++ /tags/start/cstr/perllib/plugins/PrePlug.pm	(revision 13666)
@@ -0,0 +1,281 @@
+###########################################################################
+#
+# PrePlug.pm --
+# 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.
+#
+###########################################################################
+
+# plugin that processes simple html files like those output 
+# by prescript when converting postscript to html. 
+# prescript output has <p> tags separating paragraphs
+# and <!--End Of Page--> tags separating pages.
+# it may also have <!--Page No--> tags at top or bottom of 
+# some or all pages.
+
+# if a .html1 version of a .html file exists then that version 
+# will be used so that the author name can be extracted
+# (.html1 files were generated by software which automatically 
+# extracts author names from .html files).
+
+# also looks for a .info file containing metadata (as used by 
+# the cstr collection)
+
+package PrePlug;
+
+use BasPlug;
+use sorttools;
+
+sub BEGIN {
+    @ISA = ('BasPlug');
+}
+
+sub new {
+    my ($class) = @_;
+    $self = new BasPlug ();
+
+    return bless $self, $class;
+}
+
+sub is_recursive {
+    my $self = shift (@_);
+
+    return 0; # this is not a recursive plugin
+}
+
+
+# return number of files processed, undef if can't process
+# Note that $base_dir might be "" and that $file might 
+# include directories
+sub read {
+    my $self = shift (@_);
+    my ($pluginfo, $base_dir, $file, $metadata, $processor) = @_;
+
+    my $filename = &util::filename_cat($base_dir, $file);
+
+    return 0 if ($filename =~ /\.(html1|html1\.gz|info|gif)/);
+
+    return undef unless ($filename =~ /\.(html(\.gz)?)$/i && (-e $filename));
+
+    my $gz = 0;
+    $gz = 1 if (defined $2 && $2 eq ".gz");
+
+    my $filename1 = $filename;
+    if ($gz) {
+	$filename1 =~ s/\.html\.gz$/\.html1\.gz/;
+    } else {
+	$filename1 .= "1";
+    }
+    
+    $filename = $filename1 if (-e $filename1);
+
+    print STDERR "PrePlug: processing $filename\n" if $processor->{'verbosity'};
+
+    # create a new document
+    my $doc_obj = new doc ($file, "indexed_doc");
+
+    if ($gz) {
+	open (FILE, "zcat $filename |") || die "PrePlug::read - zcat can't open $filename\n";
+    } else {
+	open (FILE, $filename) || die "PrePlug::read - can't open $filename\n";
+    }
+    my $cursection = $doc_obj->get_top_section();
+
+    my $text = "";
+    my $line = "";
+    my $pagenumber = 1;
+    my @creators = ();
+    my $numlines = 0;
+    while (defined ($line = <FILE>)) {
+	if ($filename =~ /html1$/) {
+	    while ($text =~ s/<_author_search_\([^\)]*\)>([^<]*)<\/a>/$1/i) {
+		push (@creators, $1);
+	    }
+	}
+
+	# numlines sorts out documents that just have a single <!-- End of Page--> tag at the end
+	if ($line =~ /<!--End\s+Of\s+Page-->/i && $numlines < 200) {
+
+	    $numlines = -1000;
+	    $cursection = 
+		$doc_obj->insert_section($doc_obj->get_end_child($doc_obj->get_top_section()));
+
+	    $text =~ s/<!--Page No-->\s*<p>\s*<center>\s*<b>\s*(\d+)<\/b>\s*<\/center>\s*//i;
+#	    if (defined $1 && $1 != $pagenumber) {
+#		print STDERR "PrePlug Warning: Pagenumbers don't line up in $filename\n";
+#	    }
+	    $doc_obj->add_text ($cursection, $text);
+	    $doc_obj->add_metadata ($cursection, "Title", $pagenumber);
+	    $pagenumber ++;
+	    $text = "";
+	} else {
+	    $text .= $line;
+	    $numlines ++; 
+	}
+    }
+    close FILE;
+
+    if ($cursection eq $doc_obj->get_top_section()) {
+	# there weren't any <!--End Of Page--> tags
+	
+	# see if there were any <!--Page No--> tags to split on
+	if ($text =~ /<!--Page No-->/i) {
+	    while ($text =~ s/^(.*?)<!--Page No-->\s*<p>\s*<center>\s*<b>\s*\d+<\/b>\s*<\/center>\s*//i) {
+		$cursection = 
+		    $doc_obj->insert_section($doc_obj->get_end_child($doc_obj->get_top_section()));
+		$doc_obj->add_text ($cursection, $text);
+		$doc_obj->add_metadata ($cursection, "Title", $pagenumber);
+		$pagenumber ++;
+	    }
+	}
+	# otherwise we'll just have to split pages on set number of lines
+	else {
+	    my $pagetext = "";
+	    my $line = "";
+	    my $count = 0;
+	    while (length ($text) && $text =~ s/^(.*?)(\n|$)//) {
+		$line = $1;
+		$line = "" unless defined $line;
+		$pagetext .= $line . "\n";
+		if (($count >= 50 && $line !~ /\w/) || $count == 80) {
+		    $cursection = 
+			$doc_obj->insert_section($doc_obj->get_end_child($doc_obj->get_top_section()));
+		    $doc_obj->add_text ($cursection, $pagetext);
+		    $doc_obj->add_metadata ($cursection, "Title", $pagenumber);
+		    $pagetext = "";
+		    $pagenumber ++;
+		    $count = 0;
+		} else {
+		    $count ++;
+		}
+	    }
+	}
+	    
+    }
+	    
+    # final section
+    if ($text =~ /\w/) {
+	$cursection = 
+	    $doc_obj->insert_section($doc_obj->get_end_child($doc_obj->get_top_section()));
+	
+	$text =~ s/<!--Page No-->\s*<p>\s*<center>\s*<b>\s*(\d+)<\/b>\s*<\/center>\s*//;
+#	if (defined $1 && $1 != $pagenumber) {
+#	    print STDERR "PrePlug Warning: Pagenumbers don't line up in $filename\n";
+#	}
+	$doc_obj->add_text ($cursection, $text);
+	$doc_obj->add_metadata ($cursection, "Title", $pagenumber);
+    }
+
+    # add meta data for top level of document
+    map {$doc_obj->add_metadata ($doc_obj->get_top_section(), "Creator", $_)} @creators;
+
+    my ($filesuff) = $filename =~ /^(.*?)\.html1?/;
+    if (!-e $filesuff . ".info") {
+	print STDERR "Preplug Warning: $filename has no corresponding .info file\n";
+    } else {
+	my ($dir) = $filesuff =~ /^(.*?)~?[^~]*$/;
+	open (INFO, $filesuff . ".info") || die "PrePlug::read - can't open $filesuff.info\n";
+	my $line = "";
+	while (defined ($line = <INFO>)) {
+	    chop $line;
+	    my ($key, $value) = $line =~ /^<([^>]*)>(.*)$/;
+	    next if $key =~ /^(pages|compressedsize|\/?info|size)$/i;
+	    next if $value !~ /\w/;
+	    if ($key =~ /^abstract$/i) {
+		$key = "Description";
+	    } elsif ($key =~ /^url$/i) {
+		$key = "Source";
+	    } elsif ($key =~ /^filedate$/i) {
+		$key = "Date";
+		my ($day, $month, $year) = split /\//, $value;
+		$value = &sorttools::format_date ($day, $month, $year);
+	    } elsif ($key =~ /^transferdate$/i) {
+		my ($day, $month, $year) = split /\//, $value;
+		$value = &sorttools::format_date ($day, $month, $year);
+	    } elsif ($key =~ /^facsimiles$/i) {
+		$value =~ s/^\s+//;
+		$value =~ s/\s+$//;
+		my @facsimiles = split /\s+/, $value;
+		$value = join ",", @facsimiles;
+		foreach $facsimile (@facsimiles) {
+		    # assume images are in the same directory
+		    my $imagefile = $dir . "~" . $facsimile;
+		    if (-e $imagefile) {
+			my ($imagetype) = $facsimile =~ /\.([^\.]*)$/;
+			$doc_obj->associate_file($imagefile, $facsimile, "image/" . $imagetype);
+		    } else {
+			print STDERR "PrePlug: Warning - facsimile file $imagefile doesn't exist\n";
+			next;
+		    }
+		}
+	    } elsif ($key =~ /^figures$/i) {
+		$value =~ s/^\s+//;
+		$value =~ s/\s+$//;
+		my @figures = split /\s+/, $value;
+		foreach $figure (@figures) {
+		    # assume images are in the same directory
+		    my $imagefile = $dir . "~" . $figure;
+		    if (-e $imagefile) {
+			my ($imagetype) = $figure =~ /\.([^\.]*)$/;
+			$doc_obj->associate_file($imagefile, $figure, "image/" . $imagetype);
+		    } else {
+			print STDERR "PrePlug: Warning - figure file $imagefile doesn't exist\n";
+			next;
+		    }
+		    $value = join ",", @figures;
+		}
+	    }
+	    $doc_obj->add_metadata ($doc_obj->get_top_section(), $key, $value);
+	}
+	close INFO;
+    }
+
+    foreach $field (keys(%$metadata)) {
+	# $metadata->{$field} may be an array reference
+	if (ref ($metadata->{$field}) eq "ARRAY") {
+	    map { 
+		$doc_obj->add_metadata ($doc_obj->get_top_section(), $field, $_); 
+	    } @{$metadata->{$field}};
+	} else {
+	    $doc_obj->add_metadata ($doc_obj->get_top_section(), $field, $metadata->{$field}); 
+	}
+    }
+
+    # add OID
+    $doc_obj->set_OID ();
+
+    # process the document
+    $processor->process($doc_obj);
+
+    return 1; # processed the file
+}
+
+1;
+
+
+
+
+
+
+
+
+
+
+
Index: /tags/start/cstr/src/recpt/Makefile.in
===================================================================
--- /tags/start/cstr/src/recpt/Makefile.in	(revision 13666)
+++ /tags/start/cstr/src/recpt/Makefile.in	(revision 13666)
@@ -0,0 +1,145 @@
+###########################################################################
+#
+# Makefile -- Makefile for cstrlibrary
+# 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.
+#
+###########################################################################
+
+GD = ../../../..
+MAINRECPTDIR = $(GD)/src/recpt
+MAINCOLSERVRDIR = $(GD)/src/colservr
+
+AR = ar
+CC = @CC@
+CCFLAGS = @CFLAGS@ -Wall -Wunused -pedantic -W -Woverloaded-virtual
+DEFS = -DNZDL -DQUIET -DSHORT_SUFFIX -DPARADOCNUM -DGSDLSERVER \
+       -D_LITTLE_ENDIAN -DGSDLSERVER @DEFS@
+
+USE_FASTCGI = @USE_FASTCGI@
+ifneq ($(USE_FASTCGI), 1)
+INCLUDES = -I$(MAINRECPTDIR) -I$(MAINCOLSERVRDIR) -I$(GD)/lib \
+	   -I$(GD)/packages/mg -I$(GD)/packages/mg/lib -I$(GD)/packages/mg/src/text 
+else
+INCLUDES = -I$(MAINRECPTDIR) -I$(MAINCOLSERVRDIR) -I$(GD)/lib \
+	   -I$(GD)/packages/mg -I$(GD)/packages/mg/lib -I$(GD)/packages/mg/src/text \
+           -I$(GD)/packages/fcgi/include
+endif
+
+RANLIB = @RANLIB@
+LDFLAGS = @LDFLAGS@
+LIBS = -lgdbm -lstdc++ -lm -lcrypt
+
+GSDLOS = @gsdlos@
+
+
+COMPILE = $(CC) -c $(CCFLAGS) $(DEFS) $(INCLUDES)
+LINK = $(CC) $(LDFLAGS) -o $@
+
+.SUFFIXES:
+.SUFFIXES: .c .o
+.c.o:
+	$(COMPILE) $<
+
+.SUFFIXES: .cpp .o
+.cpp.o:
+	$(COMPILE) $< 
+
+
+HEADERS = cstrbrowsetools.h cstrdocaction.h cstrqueryaction.h \
+	  cstrquerytools.h
+
+SOURCES = cstrlibrarymain.cpp cstrbrowsetools.cpp cstrdocaction.cpp \
+	  cstrqueryaction.cpp cstrquerytools.cpp
+
+
+OBJECTS = cstrlibrarymain.o cstrbrowsetools.o cstrdocaction.o \
+	  cstrqueryaction.o cstrquerytools.o
+
+
+EXEC    = cstrlibrary
+
+all : $(EXEC)
+
+install: $(EXEC)
+	cp $(EXEC) /home/nzdl/nzdl-1.2/cgi-bin;
+#	strip /home/httpd/cgi-bin/$(EXEC)
+
+clean:
+	rm -f $(OBJECTS) $(EXEC)
+
+depend:
+	makedepend -Y -- $(DEFS) $(INCLUDES) $(CCFLAGS) -- $(SOURCES)
+
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+
+CSTRLIBRARY_OBJS = $(OBJECTS) \
+    $(MAINRECPTDIR)/receptionist.o \
+    $(MAINRECPTDIR)/recptconfig.o \
+    $(MAINRECPTDIR)/cgiwrapper.o \
+    $(MAINRECPTDIR)/cgiargs.o \
+    $(MAINRECPTDIR)/action.o \
+    $(MAINRECPTDIR)/converter.o \
+    $(MAINRECPTDIR)/cgiutils.o \
+    $(MAINRECPTDIR)/OIDtools.o \
+    $(MAINRECPTDIR)/htmlgen.o \
+    $(MAINRECPTDIR)/statusaction.o \
+    $(MAINRECPTDIR)/pageaction.o \
+    $(MAINRECPTDIR)/comtypes.o \
+    $(MAINRECPTDIR)/recptproto.o \
+    $(MAINRECPTDIR)/pingaction.o \
+    $(MAINRECPTDIR)/queryaction.o \
+    $(MAINRECPTDIR)/documentaction.o \
+    $(MAINRECPTDIR)/htmlutils.o \
+    $(MAINRECPTDIR)/nullproto.o \
+    $(MAINRECPTDIR)/infodbclass.o \
+    $(MAINRECPTDIR)/formattools.o \
+    $(MAINRECPTDIR)/tipaction.o \
+    $(MAINRECPTDIR)/authenaction.o \
+    $(MAINRECPTDIR)/usersaction.o \
+    $(MAINRECPTDIR)/userdb.o \
+    $(MAINCOLSERVRDIR)/mgq.o \
+    $(MAINCOLSERVRDIR)/querycache.o \
+    $(MAINCOLSERVRDIR)/queryinfo.o \
+    $(MAINCOLSERVRDIR)/collectserver.o \
+    $(MAINCOLSERVRDIR)/colservrconfig.o \
+    $(MAINCOLSERVRDIR)/maptools.o \
+    $(MAINCOLSERVRDIR)/filter.o \
+    $(MAINCOLSERVRDIR)/source.o \
+    $(MAINCOLSERVRDIR)/browsefilter.o \
+    $(MAINCOLSERVRDIR)/queryfilter.o \
+    $(MAINCOLSERVRDIR)/phrasequeryfilter.o \
+    $(MAINCOLSERVRDIR)/phrasesearch.o \
+    $(MAINCOLSERVRDIR)/mggdbmsource.o \
+    $(MAINCOLSERVRDIR)/mgsearch.o \
+    $(GD)/lib/gsdllib.a  \
+    $(GD)/packages/mg/src/text/libtextin.a \
+    $(GD)/packages/mg/lib/libmg.a
+
+ifneq ($(USE_FASTCGI), 1)
+CSTRLIB_OBJS = $(CSTRLIBRARY_OBJS)
+else
+CSTRLIB_OBJS = $(CSTRLIBRARY_OBJS) $(GD)/packages/fcgi/libfcgi/libfcgi.a
+endif
+
+cstrlibrary: $(CSTRLIB_OBJS)
+	$(LINK) $(CSTRLIB_OBJS) $(LIBS) 
Index: /tags/start/cstr/src/recpt/cstrbrowsetools.cpp
===================================================================
--- /tags/start/cstr/src/recpt/cstrbrowsetools.cpp	(revision 13666)
+++ /tags/start/cstr/src/recpt/cstrbrowsetools.cpp	(revision 13666)
@@ -0,0 +1,847 @@
+/**********************************************************************
+ *
+ * cstrbrowsetools.cpp -- 
+ * Copyright (C) 1999  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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2000/02/01 22:32:37  sjboddie
+   Initial revision
+
+   Revision 1.1  1999/09/07 21:49:41  sjboddie
+   new cstr receptionist
+
+ */
+
+
+#include "cstrbrowsetools.h"
+#include "OIDtools.h"
+#include "cgiutils.h"
+
+// simply checks to see if formatstring begins with a <td> tag
+static bool is_table_content (const text_t &formatstring) {
+  text_t::const_iterator here = formatstring.begin();
+  text_t::const_iterator end = formatstring.end();
+  
+  while (here != end) {
+    if (*here != ' ') {
+      if (*here == '<') {
+	if ((*(here+1) == 't' || *(here+1) == 'T') &&
+	    (*(here+2) == 'd' || *(here+2) == 'D') &&
+	    (*(here+3) == '>' || *(here+3) == ' '))
+	  return true;
+      } else return false;
+    }
+    here ++;
+  }
+  return false;
+}
+
+static bool is_table_content (const format_t *formatlistptr) {
+
+  if (formatlistptr == NULL) return false;
+  
+  if (formatlistptr->command == comText)
+    return is_table_content (formatlistptr->text);
+    
+  return false;
+}
+
+
+// output_controls displays the detach, expand/contract contents,
+// expand/contract text and highlighting/no highlighting buttons
+static void output_controls (cgiargsclass &args, const text_tarray &ibuttons,
+			     recptproto */*collectproto*/, displayclass &disp, 
+			     outconvertclass &outconvert, ostream &textout, 
+			     ostream &/*logout*/) {
+
+  if (args["u"] != "1") {
+  
+    FilterResponse_t response;
+    text_tset metadata;
+    text_tarray buttons;
+
+    text_t &arg_gg = args["gg"];
+
+    text_tarray::const_iterator here = ibuttons.begin();
+    text_tarray::const_iterator end = ibuttons.end();
+
+    while (here != end) {
+    
+      if (*here == "Detach")
+	buttons.push_back ("_document:imagedetach_");
+      else if (*here == "Highlight" && arg_gg == "text") {
+	if (args["hl"] == "1") 
+	  buttons.push_back ("_document:imagenohighlight_");
+	else 
+	  buttons.push_back ("_document:imagehighlight_");
+	//      } else if (*here == "Expand Contents") {
+	//	if (args["gc"] == "1")
+	//	  buttons.push_back ("_document:imagecontracttoc_");
+	//	else 
+	//	  buttons.push_back ("_document:imageexpandtoc_");
+      } else if (*here == "Expand Text" && arg_gg == "text") {
+	if (args.getintarg("gt"))
+	  buttons.push_back ("_document:imagecontracttext_");
+	else 
+	  buttons.push_back ("_document:imageexpandtext_");
+      }
+      here ++;
+    }
+
+    here = buttons.begin();
+    end = buttons.end();
+    int count = 0;
+    while (here != end) {
+      if ((count != 0) && ((count % 3) == 0)) textout << "<br>\n";
+      textout << outconvert << disp << *here;
+      count ++;
+      here ++;
+    }
+  }
+}
+
+static void output_cstr_controls (cgiargsclass &args, const text_t &source, 
+				  const text_t &description, const text_t &figures, 
+				  displayclass &disp, outconvertclass &outconvert, 
+				  ostream &textout) {
+  text_tarray buttons;
+  text_t &arg_gg = args["gg"];
+  
+  if (!source.empty())
+    buttons.push_back ("_document:imagepostscript_(" + cgi_safe(source) + ")");
+
+  if ((!description.empty()) && (arg_gg != "abstract"))
+    buttons.push_back ("_document:imageabstract_");
+
+  if ((!figures.empty()) && (arg_gg != "figures"))
+    buttons.push_back ("_document:imagefigures_");
+
+  if (arg_gg != "text")
+    buttons.push_back ("_document:imageviewtext_");
+
+  textout << "<br>\n";
+
+  text_tarray::const_iterator here = buttons.begin();
+  text_tarray::const_iterator end = buttons.end();
+  int count = 0;
+  while (here != end) {
+    if ((count != 0) && ((count % 3) == 0)) textout << "<br>\n";
+    textout << outconvert << disp << *here;
+    count ++;
+    here ++;
+  }
+}
+
+/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+Functions for generating a document type tables of contents. These aren't really tables of
+contents at all, just a title, some navigation buttons and arrows and maybe a page ? of ?
+type thing. These should only be called for document level tocs (i.e. when the "d" argument 
+is set) as I don't think it makes sense to display top level classifications in this way.
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
+
+void output_document_toc (cgiargsclass &args, const formatinfo_t &formatinfo,
+			  recptproto *collectproto, displayclass &disp, 
+			  outconvertclass &outconvert, ostream &textout, 
+			  ostream &logout) {
+
+  text_t &arg_d = args["d"];
+  if (arg_d.empty()) return;
+
+  text_tset metadata;
+  FilterResponse_t response;
+  ResultDocInfo_t docinfo;
+  text_t booktop, facsimiles, figures, description, source, summary;
+  text_t &collection = args["c"];
+
+  metadata.insert ("Title");
+  if (get_info (arg_d, collection, metadata, false, collectproto, response, logout)) {
+
+    metadata.erase (metadata.begin(), metadata.end());
+    docinfo = response.docInfo[0];
+
+    textout 
+      << "\n<!-- Table of Contents produced by cstrbrowsetools::output_document_toc -->\n\n";
+
+    // get title and author of book
+    get_top (arg_d, booktop);
+    metadata.insert ("facsimiles");
+    metadata.insert ("figures");
+    metadata.insert ("Description");
+    metadata.insert ("Source");
+    metadata.insert ("Summary");
+    get_info (booktop, collection, metadata, false, collectproto, response, logout);
+    facsimiles = response.docInfo[0].metadata[0].values[0];
+    figures = response.docInfo[0].metadata[1].values[0];
+    description = response.docInfo[0].metadata[2].values[0];
+    source = response.docInfo[0].metadata[3].values[0];
+    summary = response.docInfo[0].metadata[4].values[0];
+
+    metadata.erase (metadata.begin(), metadata.end());
+  
+    textout << outconvert << disp 
+	    << "<p><center>\n"
+	    << "<table cellpadding=0 cellspacing=0 width=_pagewidth_>\n"
+	    << "<tr valign=top><td>\n";
+
+    // don't want arrows and page number if text expanded
+    if (formatinfo.DocumentArrowsBottom && !args.getintarg ("gt")) {
+    
+      // previous arrow
+      textout << outconvert << disp << "<table><tr valign=top>\n"
+	      << "<td align=left>_document:prevarrow_</td>\n";
+    
+      // page ? of ? text
+      textout << "<td align=center>\n";
+      
+      if (is_number (docinfo.metadata[0].values[0])) {
+	text_t doctop;
+	metadata.insert ("Title");
+	get_top (arg_d, doctop);
+	// get title of last sibling
+	if (get_info (doctop + ".lc", collection, metadata, false, collectproto, response, logout)) {
+	  if (is_number (response.docInfo[0].metadata[0].values[0])) {
+	    textout << outconvert << disp << "_document:page_" << docinfo.metadata[0].values[0]
+		    << "_document:of_" << response.docInfo[0].metadata[0].values[0];
+	  } else {
+	    textout << outconvert << docinfo.metadata[0].values[0];
+	  }
+	}
+      } else {
+	textout << outconvert << docinfo.metadata[0].values[0];
+      }
+  
+      // next arrow
+      textout << outconvert << disp << "</td>\n<td align=right>_document:nextarrow_</td>\n</table>\n";
+    }
+
+    // goto line ****** ????????????
+    //if (formatinfo.DocumentGoTo)
+    //  textout << outconvert << disp << "_document:gotoform_";
+
+    // control buttons
+    output_controls (args, formatinfo.DocumentButtons, collectproto, 
+		     disp, outconvert, textout, logout);
+    textout << "</td><td valign=top>\n";
+
+    if (!summary.empty())
+      textout << outconvert << summary << "\n";
+
+    output_cstr_controls (args, source, description, figures, 
+			  disp, outconvert, textout);
+
+    textout << "</td>\n";
+    
+    // facsimile image
+    // only want the first facsimile (some documents have two)
+    if (!facsimiles.empty()) {
+      text_t::const_iterator fbegin = facsimiles.begin();
+      facsimiles = substr (fbegin, findchar (fbegin, facsimiles.end(), ','));
+      textout << outconvert << disp << "<td valign=top><a href=\"_httpcurrentdocument_&gg=facsimiles\">"
+	      << "<img src=\"_httpcollection_/archives/_thisOID_/" 
+	      << facsimiles << "\" width=150 height=250></a>" << "</td>\n";
+    }
+
+
+    textout << "</td></tr></table></center>\n";
+    textout << "\n<!-- end of Table of Contents -->\n";
+
+  }
+}
+
+
+/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+Functions for generating a "Hierarchy" type table of contents. These can be used either
+at top classification level or at document level (the difference being that a cover
+image and control buttons may be displayed at document level).
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
+
+// prototypes
+
+static void output_contracted_hierarchy_toc (const text_t &classifytype, text_t &formatstring, 
+					     cgiargsclass &args, recptproto *collectproto, 
+					     displayclass &disp, outconvertclass &outconvert, 
+					     ostream &textout, ostream &logout);
+
+static void output_expanded_hierarchy_toc (cgiargsclass &args, recptproto *collectproto,
+					   displayclass &disp, outconvertclass &outconvert,
+					   ostream &textout, ostream &logout);
+
+static void output_parents_toc (cgiargsclass &args, const FilterResponse_t &parents,
+				int &tabcount, displayclass &disp,
+				format_t *formatlistptr, outconvertclass &outconvert, 
+				ostream &textout, ostream &logout);
+
+static void output_siblings_toc (const text_t &classifytype, cgiargsclass &args, 
+				 const FilterResponse_t &siblings, int &tabcount, 
+				 displayclass &disp, format_t *formatlistptr, 
+				 outconvertclass &outconvert, ostream &textout, 
+				 ostream &logout);
+
+static void output_stdlist (cgiargsclass &args, ResultDocInfo_tarray::iterator &here,
+			    ResultDocInfo_tarray::iterator &end, bool intable,
+			    displayclass &disp, format_t *formatlistptr, 
+			     outconvertclass &outconvert, ostream &textout);
+
+static void output_datelist (cgiargsclass &args, ResultDocInfo_tarray::iterator &here,
+			     ResultDocInfo_tarray::iterator &end, bool intable,
+			     displayclass &disp, format_t *formatlistptr, 
+			     outconvertclass &outconvert, ostream &textout);
+
+
+void output_standard_toc (const text_t &classifytype, const formatinfo_t &formatinfo,
+			  text_t &formatstring, cgiargsclass &args, 
+			  recptproto *collectproto, displayclass &disp, 
+			  outconvertclass &outconvert, ostream &textout, 
+			  ostream &logout) {
+
+  bool havecontrols = false;
+
+  textout << "\n<!-- Table of Contents produced by cstrbrowsetools::output_standard_toc -->\n\n";
+
+  // get the cover image (if there is one) and the control buttons
+  // if we're inside a book
+  if (!args["d"].empty()) {
+    textout << "<p><table cellpadding=0 cellspacing=0><tr>\n";
+    textout << "<td valign=top width=200>\n";
+    //    if (cover) output_cover_image (args, collectproto, disp, outconvert, textout, logout);
+    output_controls (args, formatinfo.DocumentButtons, collectproto, disp, outconvert, textout, logout);
+    textout << "</td><td valign=top>\n";
+    havecontrols = true;
+  }
+  
+  // get table of contents
+  textout << "<table>\n";
+
+  if (args.getintarg("gc"))
+    output_expanded_hierarchy_toc(args, collectproto, disp, outconvert, textout, logout);
+  else
+    output_contracted_hierarchy_toc(classifytype, formatstring, args, collectproto, 
+				    disp, outconvert, textout, logout);
+
+  textout << "</table>\n";
+
+  if (havecontrols) textout << "</td></tr></table>\n";
+
+  textout << "\n<!-- end of Table of Contents -->\n";
+}
+
+
+void output_contracted_hierarchy_toc (const text_t &classifytype, text_t &formatstring, 
+				      cgiargsclass &args, recptproto *collectproto, 
+				      displayclass &disp, outconvertclass &outconvert, 
+				      ostream &textout, ostream &logout) {
+
+  int tabcount = 0;
+  text_tarray parents;
+  text_tset metadata;
+  FilterResponse_t fsiblings, fparents;
+  bool getParents = false;
+
+  text_t &arg_d = args["d"];
+  text_t OID = arg_d;
+  if (OID.empty()) OID = args["cl"];
+  text_t &collection = args["c"];
+
+  // if format string is empty use the default
+  if (formatstring.empty()) 
+    formatstring = "<td valign=top nowrap>[link][icon][/link]</td><td>{Or}{[Title],Untitled}</td>";
+
+  format_t *formatlistptr = new format_t();
+  parse_formatstring (formatstring, formatlistptr, metadata, getParents);
+
+  metadata.insert ("Date");
+  metadata.insert ("hastxt");
+  metadata.insert ("haschildren");
+  metadata.insert ("doctype");
+  metadata.insert ("classifytype");
+
+  if (has_children (OID, collection, collectproto, logout)) {
+      get_parents_array (OID + ".fc", parents);
+
+      if (!get_children (OID, collection, metadata, getParents,
+			 collectproto, fsiblings, logout))
+	return;
+  } else {
+    get_parents_array (OID, parents);
+    if (!get_children (OID + ".pr", collection, metadata, 
+		       getParents, collectproto, fsiblings, logout))
+	return;
+  }
+  if (!get_info (parents, collection, metadata, false, collectproto, fparents, logout)) return;
+  
+  if (!fparents.docInfo.empty()) 
+    output_parents_toc(args, fparents, tabcount, disp, 
+		       formatlistptr, outconvert, textout, logout);
+  
+  if (!fsiblings.docInfo.empty()) 
+    output_siblings_toc (classifytype, args, fsiblings, tabcount, disp, 
+			 formatlistptr, outconvert, textout, logout);
+}
+void output_parents_toc (cgiargsclass &args, const FilterResponse_t &parents,
+			 int &tabcount, displayclass &disp,
+			 format_t *formatlistptr, outconvertclass &outconvert,
+			 ostream &textout, ostream &/*logout*/) {
+
+  text_t tab, icon;
+  text_t &arg_cl = args["cl"];
+  text_t &arg_d = args["d"];
+  int numcols = parents.docInfo.size() + 1;
+  
+  bool intable = is_table_content (formatlistptr);
+  
+  ResultDocInfo_tarray::iterator thisparent = parents.docInfo.begin();
+  ResultDocInfo_tarray::iterator end = parents.docInfo.end();
+
+  int len = (*thisparent).metadata.size();
+  const text_t &classifytype = (*thisparent).metadata[len-1].values[0];
+
+  // don't want top level of any classifications to be displayed
+  if (arg_d.empty() && thisparent != end) {thisparent ++; numcols --;}
+
+  // don't want second level of classifications using classification links
+  if ((classifytype == "AZList" || classifytype == "DateList") && (thisparent != end))
+    {thisparent ++; numcols --;}
+
+  // the tab line
+  if (thisparent != end) {
+    text_t coltabs;
+    for (int i = 0; i < numcols; i ++) coltabs += "_document:tab_";
+    textout << outconvert << disp << "<tr>" << coltabs << "<td></td></tr>\n";
+  }
+
+  while (thisparent != end) {
+
+    const text_t &doctype = (*thisparent).metadata[len-2].values.back();
+
+    // set up icon and pointer
+    icon = "_document:icon";
+    if ((doctype != "classify") && ((*thisparent).OID == arg_d))
+      icon += "arrow";
+    if (doctype == "classify") icon += "openbookshelf_";
+    else if (is_top((*thisparent).OID)) icon += "openbook_";
+    else icon += "openfolder_";
+    
+    if (tabcount == 1) textout << "<td></td>\n";
+    else if (tabcount > 1) textout << "<td colspan=" << tabcount << "></td>";
+    
+    // set up the link
+    text_t link = "<a href=\"_httpdocument_";
+    if (is_top((*thisparent).OID) && args.getintarg("x")) link = "<a name=top>";
+    else 
+      if (doctype == "classify") link += "&cl=" + (*thisparent).OID + ".pr\">";
+      else 
+	if (is_top ((*thisparent).OID)) 
+	  if (arg_cl.empty())
+	    link = "<a name=top>";
+	  else if (arg_cl == "search")
+	    link = "<a href=\"_httpquery_\">";
+	  else
+	    link += "&cl=" + arg_cl + "\">";
+	else link += "&cl=" + arg_cl + "&d=" + (*thisparent).OID + ".pr\">";
+    
+    if ((numcols-tabcount) == 1) textout << "<td>";
+    else if ((numcols-tabcount) > 1) textout << "<td colspan=" 
+					     << (numcols-tabcount) << ">";
+
+    if (intable) textout << "<table><tr>";
+    
+    textout << outconvert << disp 
+	    << get_formatted_string (*thisparent, formatlistptr, link, icon);
+    
+    if (intable) textout << "</tr></table>";
+    textout << "</td></tr>\n";
+
+    tabcount ++;
+    thisparent ++;
+  }
+}
+
+
+void output_siblings_toc (const text_t &classifytype, cgiargsclass &args, 
+			  const FilterResponse_t &siblings, int &tabcount, 
+			  displayclass &disp, format_t *formatlistptr, 
+			  outconvertclass &outconvert, ostream &textout, 
+			  ostream &/*logout*/) {
+
+  bool intable = is_table_content (formatlistptr); 
+
+  ResultDocInfo_tarray::const_iterator thissibling = siblings.docInfo.begin();
+  ResultDocInfo_tarray::const_iterator sibend = siblings.docInfo.end();
+
+  if (thissibling == sibend) return;
+
+  // tabbing
+  if (tabcount) {
+    if (tabcount == 1) textout << "<tr><td></td>\n";
+    else if (tabcount > 1) textout << "<tr><td colspan=" << tabcount << "></td>";
+    textout << "<td><table>\n";
+  }
+
+  if (!intable) textout << "<tr><td>\n";
+  
+  if (classifytype == "DateList")
+    output_datelist (args, thissibling, sibend, intable, disp, 
+		     formatlistptr, outconvert, textout);
+  else 
+    output_stdlist (args, thissibling, sibend, intable, disp, 
+		    formatlistptr, outconvert, textout);
+
+  if (!intable) textout << "</td></tr></table>\n";
+  if (tabcount) textout << "</table></td></tr>\n";
+}
+
+void output_stdlist (cgiargsclass &args, ResultDocInfo_tarray::iterator &here,
+		     ResultDocInfo_tarray::iterator &end, bool intable,
+		     displayclass &disp, format_t *formatlistptr, 
+		     outconvertclass &outconvert, ostream &textout) {
+
+  text_t icon;
+  int count = 1;
+  int gt = args.getintarg("gt");
+  text_t &arg_cl = args["cl"];
+  text_t &arg_d = args["d"];
+
+  while (here != end) {
+
+    int len = (*here).metadata.size();
+    const text_t &doctype = (*here).metadata[len-2].values.back();
+    const text_t &hastxt = (*here).metadata[len-4].values.back(); 
+    const text_t &haschildren = (*here).metadata[len-3].values.back();
+
+    // set up icon and pointer
+    icon = "_document:icon";
+    if (doctype == "classify") {
+      if (((*here).OID == arg_cl) && (hastxt == "1"))
+    	icon += "arrow";
+    } else if ((*here).OID == arg_d) icon += "arrow";
+
+    if (haschildren == "0") icon += "smalltext_";
+    else if (doctype == "classify") icon += "closedbookshelf_";
+    else if (is_top((*here).OID)) icon += "closedbook_";
+    else icon += "closedfolder_";
+    
+    // set up link
+    text_t link = "<a href=\"_httpdocument_";
+    if (doctype == "classify") link += "&cl=" + (*here).OID + "\">";
+    else link += "&cl=" + arg_cl + "&d=" + (*here).OID + "\">";
+    if (gt) {
+      link = "<a href=\"#" + text_t(count) + "\">";
+      count ++;
+    }
+
+    if (intable) textout << "<tr>";
+    
+    textout << outconvert << disp 
+	    << get_formatted_string (*here, formatlistptr, link, icon) << "\n";
+    
+    if (intable) textout << "</tr>";
+
+    here ++;
+  }
+}
+
+
+void output_datelist (cgiargsclass &args, ResultDocInfo_tarray::iterator &here,
+		      ResultDocInfo_tarray::iterator &end, bool intable,
+		      displayclass &disp, format_t *formatlistptr, 
+		      outconvertclass &outconvert, ostream &textout) {
+
+  text_t lastyear = "0000";
+  text_t lastmonth = "00";
+
+  while (here != end) {
+
+    int len = (*here).metadata.size();
+    const text_t &doctype = (*here).metadata[len-2].values.back();
+    const text_t &date = (*here).metadata[len-5].values.back(); 
+
+    // bail on this document if it has no date
+    if (date.empty()) continue;
+
+    text_t::const_iterator datebegin = date.begin();
+
+    text_t link = "<a href=\"_httpdocument_&cl=";
+    text_t icon = "_document:iconclosedbook_";
+      
+    if (doctype == "classify") {
+      icon = "_document:iconclosedbookshelf_";
+      link += (*here).OID + "\">";
+    } else link += args["cl"] + "&d=" + (*here).OID + "\">";
+
+    text_t thisyear = substr (datebegin, datebegin+4);
+    text_t thismonth = substr (datebegin+4, datebegin+6); 
+
+    textout << "<tr>\n";
+
+    if (thisyear != lastyear) {
+      textout << outconvert << "<td><b>" << thisyear << "</b></td>";
+      lastyear = thisyear;
+    } else
+      textout << "<td></td>";
+
+    if (thismonth != lastmonth) {
+      textout << outconvert << disp << ("<td><b>_textmonth" + thismonth + "_</b></td>");
+      lastmonth = thismonth;
+    } else
+      textout << "<td></td>";
+
+    if (!intable) textout << "<td>\n";
+    
+    textout << outconvert << disp 
+	      << get_formatted_string (*here, formatlistptr, link, icon) << "\n";
+
+    if (!intable) textout << "</td>";
+      
+    textout << "</tr>\n";
+
+    here ++;
+  }
+}
+
+void output_expanded_hierarchy_toc (cgiargsclass &args, recptproto *collectproto,
+				    displayclass &disp, outconvertclass &outconvert,
+				    ostream &textout, ostream &logout) {
+
+  text_t OID, topOID, icon;
+  bool is_classify;
+  FilterResponse_t response;
+  int tabcols=0, totalcols=0, lasttabcols=0;
+
+  int gt = args.getintarg("gt");
+  text_t doclink = "<a href=\"_httpdocument_&cl=";
+
+  text_t &arg_d = args["d"];
+  text_t &arg_cl = args["cl"];
+
+  if (arg_d.empty()) {
+    if (arg_cl.empty()) return;
+    OID = arg_cl;
+    topOID = OID; // don't always want to expand from top if expanding classifications
+    is_classify=true;
+  } else {
+    OID = arg_d;
+    get_top (arg_d, topOID);
+    is_classify=false;
+  }
+
+  // Get OIDs and metadata of all topOIDs contents (and topOID itself)
+  text_tset metadata;
+  metadata.insert ("Title");
+  metadata.insert ("haschildren");
+  metadata.insert ("doctype");
+  //  metadata.insert ("hastxt");
+
+  get_contents (topOID, is_classify, metadata, totalcols, 
+		args["c"], collectproto, response, logout);
+  int excess = countchar (topOID.begin(), topOID.end(), '.');
+  totalcols -= excess;
+
+  // allow for pointer
+  if (!is_classify && !gt) totalcols += 2;
+  else totalcols += 1;
+
+  ResultDocInfo_tarray::iterator thissection = response.docInfo.begin();
+  ResultDocInfo_tarray::iterator lastsection = response.docInfo.end();
+  
+  int count = 1;
+  while (thissection != lastsection) {
+    
+    const text_t &title = (*thissection).metadata[0].values[0];
+    const int haschildren = (*thissection).metadata[1].values[0].getint();
+    const text_t &doctype = (*thissection).metadata[2].values[0];
+
+    text_t icontabs, tab, pointer;
+
+    // set up icon
+    icon = "_document:iconsmalltext_";
+    if (is_top((*thissection).OID))
+      if (classifytype == "Document") icon = "_document:iconopenbook_";
+      else 
+	if (doctype == "classify") icon = "_document:iconopenbookshelf_";
+	else icon = "_document:iconclosedbook_";
+    else if (haschildren) 
+      if (classifytype == "Document") icon = "_document:iconopenfolder_";
+      else icon = "_document:iconopenbookshelf_";
+    
+    // set up tabbing
+    if ((classifytype == "classify") && (doctype != "classify"))
+      tabcols = lasttabcols + 1;
+    else {
+      tabcols = countchar ((*thissection).OID.begin(), (*thissection).OID.end(), '.');
+      lasttabcols = tabcols;
+    }
+    tabcols -= excess;
+
+    for (int i = 0; i < tabcols; i++) 
+      icontabs += "_document:icontab_";
+    
+    // set up pointer
+    if (classifytype == "Document" && !gt) {
+      if ((*thissection).OID == OID) pointer = "_document:iconpointer_";
+      else pointer = "_document:icontab_";
+      tabcols ++;
+    }
+    
+    int colsremaining = totalcols - tabcols;
+
+    if (tabcols > 0) {
+      tab = "<td";
+      if (tabcols > 1) tab += " colspan=" + text_t(tabcols);
+      tab += ">" + icontabs + pointer + "</td>";
+    }
+
+    textout << outconvert << disp << "<tr>" << tab << "<td>";
+    
+    if ((classifytype == "Document") && (is_top((*thissection).OID)) && 
+	(args.getintarg("x")))
+      textout << outconvert << disp << icon << "</td><td";
+
+    else {
+      if (!gt) {
+	const text_t &thisOID = (*thissection).OID;
+	text_t link;
+	if (is_top (thisOID))
+	  if (classifytype == "classify")
+	    link = doclink + arg_cl + "&d=" + thisOID + "\">";
+	  else
+	    if (arg_cl.empty())
+	      link.clear();
+	    else if (arg_cl == "search")
+	      link = "<a href=\"_httpquery_\">";
+	    else
+	      link = doclink + arg_cl + "\">";
+	else
+	  if (haschildren)
+	    if (classifytype == "classify")
+	      link = doclink + thisOID + ".pr\">";
+	    else
+	      link = doclink + arg_cl + "&d=" + thisOID + ".pr\">";
+	  else
+	    if (classifytype == "classify")
+	      link = doclink + thisOID + "\">";
+	    else
+	      link = doclink + arg_cl + "&d=" + thisOID + "\">";
+	
+	textout << outconvert << disp << link;
+      } else {
+	textout << "<a href=\"#" << count << "\">";
+	count ++;
+      }
+    
+      textout << outconvert << disp << icon << "</a></td><td";
+    }
+    if (colsremaining > 1) textout << " colspan=" << colsremaining;
+    textout << outconvert << disp << ">" << title << "</td></tr>\n";
+
+    thissection ++;
+  }
+}
+
+/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
+
+// set_arrow_macros sets the _httpprevarrow_ and _httpnextarrow_ macros
+// it shouldn't be called if OID is the top level of a book 
+// as the "hasprevious" and "hasnext" metadata won't be set
+// when the filter can't get OIDs parent info - one day I'll
+// fix this ;-)
+void set_arrow_macros (const text_t &OID, const text_t &classifytype,
+		       bool showtoppage, displayclass &disp, 
+		       recptproto *collectproto, const text_t &collection, 
+		       ostream &logout) {
+
+  if (OID.empty()) return;
+
+  text_tset metadata;
+  FilterResponse_t response;
+
+  metadata.insert ("haschildren");
+  metadata.insert ("hasnext");
+  metadata.insert ("hasprevious");
+  // get "haschildren", "hasnext" and "hasprevious" metadata for OID
+  if (get_info (OID, collection, metadata, false, collectproto, response, logout)) {
+
+    text_t haschildren = response.docInfo[0].metadata[0].values[0];
+    text_t hasnext = response.docInfo[0].metadata[1].values[0];
+    text_t hasprevious = response.docInfo[0].metadata[2].values[0];
+
+    if ((classifytype == "Hierarchy") || (classifytype == "Book")) {
+      if (haschildren == "1") 
+	disp.setmacro ("httpnextarrow", "document", 
+		       "_If_(_cgiargd_,_httpdocument_&cl=_cgiargcl_&d=_cgiargd_.fc,_httpdocument_&cl=_cgiargcl_.fc)");
+      else if (hasnext == "1")
+	disp.setmacro ("httpnextarrow", "document", 
+		       "_If_(_cgiargd_,_httpdocument_&cl=_cgiargcl_&d=_cgiargd_.ns,_httpdocument_&cl=_cgiargcl_.ns)");
+      else {
+	// see if parent has younger siblings
+	if (get_info (OID + ".pr", collection, metadata, false, collectproto, response, logout)) {
+	  if (!response.docInfo[0].metadata.empty() &&
+	      response.docInfo[0].metadata[1].values[0] == "1")
+	    disp.setmacro ("httpnextarrow", "document", 
+			   "_If_(_cgiargd_,_httpdocument_&cl=_cgiargcl_&d=_cgiargd_.pr.ns,_httpdocument_&cl=_cgiargcl_.pr.ns)");
+	}
+      }
+
+      if (hasprevious == "1") {
+	// see if OIDs older sibling has children
+	if (get_info (OID + ".ps", collection, metadata, false, collectproto, response, logout)) {
+	  if (response.docInfo[0].metadata[0].values[0] == "1")
+	    disp.setmacro ("httpprevarrow", "document", 
+			   "_If_(_cgiargd_,_httpdocument_&cl=_cgiargcl_&d=_cgiargd_.ps.lc,_httpdocument_&cl=_cgiargcl_.ps.lc)");
+	  else 
+	    disp.setmacro ("httpprevarrow", "document", 
+			   "_If_(_cgiargd_,_httpdocument_&cl=_cgiargcl_&d=_cgiargd_.ps,_httpdocument_&cl=_cgiargcl_.ps)");
+	} 
+      } else if (showtoppage && !is_top (OID))
+	disp.setmacro ("httpprevarrow", "document", 
+		       "_If_(_cgiargd_,_httpdocument_&cl=_cgiargcl_&d=_cgiargd_.pr,_httpdocument_&cl=_cgiargcl_.pr)");
+    }
+
+    else {
+      if (hasnext == "1")
+	disp.setmacro ("httpnextarrow", "document", 
+		       "_If_(_cgiargd_,_httpdocument_&cl=_cgiargcl_&d=_cgiargd_.ns,_httpdocument_&cl=_cgiargcl_.ns)");
+      if (hasprevious == "1")
+	disp.setmacro ("httpprevarrow", "document", 
+		       "_If_(_cgiargd_,_httpdocument_&cl=_cgiargcl_&d=_cgiargd_.ps,_httpdocument_&cl=_cgiargcl_.ps)");
+    }
+  }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: /tags/start/cstr/src/recpt/cstrbrowsetools.h
===================================================================
--- /tags/start/cstr/src/recpt/cstrbrowsetools.h	(revision 13666)
+++ /tags/start/cstr/src/recpt/cstrbrowsetools.h	(revision 13666)
@@ -0,0 +1,59 @@
+/**********************************************************************
+ *
+ * cstrbrowsetools.h -- 
+ * Copyright (C) 1999  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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+
+#ifndef CSTRBROWSETOOLS_H
+#define CSTRBROWSETOOLS_H
+
+#include "gsdlconf.h"
+#include "text_t.h"
+#include "cgiargs.h"
+#include "display.h"
+#include "recptproto.h"
+#include "formattools.h"
+
+
+void output_document_toc (cgiargsclass &args, const formatinfo_t &formatinfo,
+			  recptproto *collectproto, displayclass &disp, 
+			  outconvertclass &outconvert, ostream &textout, 
+			  ostream &logout);
+
+void output_standard_toc (const text_t &classifytype, const formatinfo_t &formatinfo,
+			  text_t &formatstring, cgiargsclass &args, 
+			  recptproto *collectproto, displayclass &disp, 
+			  outconvertclass &outconvert, ostream &textout, 
+			  ostream &logout);
+
+void set_arrow_macros (const text_t &OID, const text_t &classifytype,
+		       bool showtoppage, displayclass &disp, 
+		       recptproto *collectproto, const text_t &collection, 
+		       ostream &logout);
+
+#endif
+
+
+
Index: /tags/start/cstr/src/recpt/cstrdocaction.cpp
===================================================================
--- /tags/start/cstr/src/recpt/cstrdocaction.cpp	(revision 13666)
+++ /tags/start/cstr/src/recpt/cstrdocaction.cpp	(revision 13666)
@@ -0,0 +1,439 @@
+/**********************************************************************
+ *
+ * cstrdocaction.cpp -- 
+ * Copyright (C) 1999  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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2000/02/01 22:32:37  sjboddie
+   Initial revision
+
+   Revision 1.1  1999/09/07 21:49:42  sjboddie
+   new cstr receptionist
+
+ */
+
+
+#include <string.h>
+#include "cstrdocaction.h"
+#include "cstrbrowsetools.h"
+#include "OIDtools.h"
+#include "querytools.h"
+#include "unitool.h"
+
+cstrdocaction::cstrdocaction () {
+  // this action uses cgi variable "gg" and "gga" as well as
+  // those used by the standard documentaction
+
+  cgiarginfo arg_ainfo;
+
+  // in this action "gg" is the format of the
+  // document to view (i.e. "text", "postscript", "abstract", "figures", or "facsimiles")
+  arg_ainfo.shortname = "gg";
+  arg_ainfo.longname = "document format";
+  arg_ainfo.multiplechar = true;
+  arg_ainfo.defaultstatus = cgiarginfo::weak;
+  arg_ainfo.argdefault = "text";
+  arg_ainfo.savedarginfo = cgiarginfo::can;
+  argsinfo.addarginfo (NULL, arg_ainfo);
+
+  // in this action "gga" is the path to the postscript
+  // when "gg" == "postscript
+  arg_ainfo.shortname = "gga";
+  arg_ainfo.longname = "postscript path";
+  arg_ainfo.multiplechar = true;
+  arg_ainfo.defaultstatus = cgiarginfo::none;
+  arg_ainfo.argdefault = "";
+  arg_ainfo.savedarginfo = cgiarginfo::mustnot;
+  argsinfo.addarginfo (NULL, arg_ainfo);
+
+}
+
+cstrdocaction::~cstrdocaction () {
+}
+
+
+void cstrdocaction::get_cgihead_info (cgiargsclass &args, recptprotolistclass * /*protos*/,
+				      response_t &response,text_t &response_data, 
+				      ostream &/*logout*/) {
+
+  if (args["gg"] == "postscript") {
+    response = location;
+    response_data = args["gga"];
+  } else {
+    response = content;
+    response_data = "text/html";
+  }
+}
+
+
+void cstrdocaction::set_java_macros (cgiargsclass &args, displayclass &disp) {
+
+  text_t javaimagescontent = "_javaextras__javapostscript_";
+
+  text_t &arg_gg = args["gg"];
+  if (arg_gg == "text")
+    javaimagescontent += "_javaabstract__javafigures_";
+  else if (arg_gg == "abstract")
+    javaimagescontent += "_javafigures__javaviewtext_";
+  else if (arg_gg == "figures")
+    javaimagescontent += "_javaabstract__javaviewtext_";
+  else if (arg_gg == "facsimiles")
+    javaimagescontent += "_javaabstract__javaviewtext__javafigures_";
+	
+  int arg_gt = args.getintarg("gt");
+  //  int arg_gc = args.getintarg("gc");
+  int arg_hl = args.getintarg("hl");
+
+  text_tarray::const_iterator button_here = formatinfo.DocumentButtons.begin();
+  text_tarray::const_iterator button_end = formatinfo.DocumentButtons.end();
+
+  while (button_here != button_end) {
+    if (*button_here == "Detach") 
+      javaimagescontent += "_javadetach_";
+    else if (*button_here == "Expand Text" && arg_gg == "text") {
+      if (arg_gt == 1)
+	javaimagescontent += "_javacontracttext__javacontinue_";
+      else if (arg_gt == 2)
+	javaimagescontent += "_javacontracttext_";
+      else
+	javaimagescontent += "_javaexpandtext_";
+      //    } else if (*button_here == "Expand Contents") {
+      //      if (arg_gc == 1)
+      //	javaimagescontent += "_javacontractcontents_";
+      //      else
+      //	javaimagescontent += "_javaexpandcontents_";
+    } else if (*button_here == "Highlight" && arg_gg == "text") {
+      if (arg_hl == 1)
+	javaimagescontent += "_javanohighlighting_";
+      else 
+	javaimagescontent += "_javahighlighting_";
+    }
+    button_here ++;
+  }
+  disp.setmacro ("javaimagescontent", "document", javaimagescontent);
+}
+
+
+
+/*
+// define all the macros which are related to pages generated
+// by this action. we also load up the formatinfo structure 
+// here (it's used in do_action as well as here)
+void cstrdocaction::define_internal_macros (const ColInfoResponse_t &collectinfo, displayclass &disp, 
+					    cgiargsclass &args, recptproto *collectproto, 
+					    ostream &logout) {
+  
+  // define_internal_macros sets the following macros:
+
+  // _pagetitle_            the title to be displayed at the top of the browser window
+  
+  // _imagethispage_        the title image to be displayed at top right of page
+  
+  // _classificationlinks_  the links between classifications to be displayed
+  //                        at top of list or datelist classifications
+
+  // _httpprevarrow_        these are set if next or previous arrows
+  // _httpnextarrow_        are to be used - (i.e. if it's an AZList or a DateList 
+  //                        classifytype at a top level or if it's a Book or a
+  //                        Hierarchy classifytype at document level 
+
+  // _navarrows_            this may be overridden to "" when format option 
+  //                        DocumentArrowsBottom is false
+
+  // _header_               the header macro is overridden if we're not at a top level 
+  //                        classification to remove the title block
+
+  // _javaimagescontent_    this is the javascript code to shove in to make the 
+  //                        flashy buttons work
+
+  // _thisOID_              the OID (directory) of the current document - this corresponds
+  //                        to the archivedir metadata element
+
+  // can't do anything if collectproto is null (i.e. no collection was specified)
+  if (collectproto == NULL) return;
+  
+  text_tarray metadata;
+  FilterResponse_t response;
+  text_t &arg_d = args["d"];
+  text_t &arg_cl = args["cl"];
+  text_t &collection = args["c"];
+  int gt = args.getintarg("gt");
+  load_formatinfo (collectinfo.format, gt);
+
+  // don't want arrows or goto if we're in figures or facsimiles
+  if (args["gg"] != "text") {
+    formatinfo.DocumentArrowsBottom = false;
+    formatinfo.DocumentArrowsTop = false;
+    formatinfo.DocumentGoTo = false;
+  }
+
+  if (!formatinfo.DocumentArrowsBottom)
+    disp.setmacro("navarrows", "document", "");
+
+  metadata.push_back ("Title");
+  metadata.push_back ("classifytype");
+  metadata.push_back ("archivedir");
+  
+  if (!arg_d.empty()) {
+    // we're at document level
+    
+    // get metadata for this document and it's parents
+    if (get_info (arg_d, collection, metadata, true, collectproto, response, logout)) {
+      disp.setmacro ("header", "document", "_textheader_");
+
+      disp.setmacro ("thisOID", "Global", response.docInfo[0].metadata[2].values[0]);
+
+      text_t &classifytype = response.docInfo[0].metadata[1].values[0];
+      if (classifytype.empty()) classifytype = "Book"; // defaults to Book
+
+      // set arrow macros if required
+      if (((classifytype == "Book") && (formatinfo.DocumentArrowsTop || formatinfo.DocumentArrowsBottom)) ||
+	  ((classifytype == "Hierarchy") && formatinfo.DocumentArrowsBottom))
+	set_arrow_macros (arg_d, classifytype, formatinfo.DocumentTopPages, 
+			  disp, collectproto, collection, logout);
+      
+      if (args["u"] != "1")
+	set_java_macros (args, disp);
+
+    }
+  } else {
+    if (!arg_cl.empty()) {
+	
+      // get metadata for top level classification
+      text_t classtop;
+      get_top (arg_cl, classtop);
+      if (get_info (classtop, collection, metadata, false, collectproto, response, logout)) {
+	  
+	text_t &title = response.docInfo[0].metadata[0].values[0];
+	text_t &classifytype = response.docInfo[0].metadata[1].values[0];
+
+	disp.setmacro ("pagetitle", "document", "_text" + title + "page_");
+	disp.setmacro ("imagethispage", "document", "_icon" + title + "page_");
+
+	// now get the metadata for each child of top level
+	// so we can generate the _classificationlinks_ and arrow macros
+	// (if they're required by the current classification type)
+	
+	if ((classifytype == "AZList") || (classifytype == "DateList"))
+	  get_classificationlinks (arg_cl, collection, collectproto, disp, logout);
+      
+      }
+    }
+  }
+}
+
+*/
+
+void cstrdocaction::output_document (const text_t &OID, cgiargsclass &args, 
+				     recptproto *collectproto, displayclass &disp, 
+				     outconvertclass &outconvert, ostream &textout, 
+				     ostream &logout) {
+  FilterResponse_t inforesponse;
+  text_tset metadata;
+  bool getParents = false;
+  text_t &collection = args["c"];
+  text_t &arg_gg = args["gg"];
+
+  if (arg_gg == "abstract") {
+    metadata.insert ("Description");
+    text_t top;
+    get_top (OID, top);
+    if (get_info (top, collection, metadata, getParents, collectproto, inforesponse, logout)) {
+      text_t &description = inforesponse.docInfo[0].metadata["Description"].values[0];
+
+      if (!description.empty())
+	textout << outconvert << disp << "<p>\n" << description << "\n";
+      else
+	textout << outconvert << disp << "_textnoabstract_";
+    }
+  } else if (arg_gg == "figures") {
+    metadata.insert ("figures");
+    text_t top;
+    get_top (OID, top);
+    if (get_info (top, collection, metadata, false, collectproto, inforesponse, logout)) {
+      text_t &figures = inforesponse.docInfo[0].metadata["figures"].values[0];
+
+      if (!figures.empty()) {
+	text_tarray figure_array;
+	splitchar (figures.begin(), figures.end(), ',', figure_array);
+	text_tarray::const_iterator this_figure = figure_array.begin();
+	text_tarray::const_iterator end_figure = figure_array.end();
+	while (this_figure != end_figure) {
+	  textout << outconvert << disp 
+		  << "<p><center><img border=1 src=\"_httpcollection_/archives/_thisOID_/" 
+		  << *this_figure << "\"></center>\n";
+	  this_figure ++;
+	}
+      } else {
+	textout << outconvert << disp << "_textnofigures_";
+      }
+    }
+  } else if (arg_gg == "facsimiles") {
+    metadata.insert ("facsimiles");
+    text_t top;
+    get_top (OID, top);
+    if (get_info (top, collection, metadata, false, collectproto, inforesponse, logout)) {
+      text_t &facsimiles = inforesponse.docInfo[0].metadata["facsimiles"].values[0];
+      
+      if (!facsimiles.empty()) {
+	text_tarray facs_array;
+	splitchar (facsimiles.begin(), facsimiles.end(), ',', facs_array);
+	text_tarray::const_iterator this_facs = facs_array.begin();
+	text_tarray::const_iterator end_facs = facs_array.end();
+	while (this_facs != end_facs) {
+	  textout << outconvert << disp 
+		    << "<p><center><img border=1 src=\"_httpcollection_/archives/_thisOID_/" 
+		  << *this_facs << "\"></center>\n";
+	  this_facs ++;
+	}
+      } else {
+	textout << outconvert << disp << "_textnofacsimiles_";
+      }
+    }      
+    
+  } else {
+
+    FilterResponse_t queryresponse;
+    bool highlight = false;
+    int wanttext = 0;
+    int arg_gt = args.getintarg("gt");
+
+    // if we have a query string and highlighting is turned on we need
+    // to redo the query to get the terms for highlighting
+    if (!args["q"].empty() && args.getintarg("hl")) {
+      FilterRequest_t request;
+      request.filterResultOptions = FRmatchTerms;
+      comerror_t err;
+      text_t formattedstring = args["q"];
+      format_querystring(formattedstring, args.getintarg("b"));
+      set_queryfilter_options (request, formattedstring, args);
+      collectproto->filter (args["c"], request, queryresponse, err, logout);
+      if (err != noError) {
+	outconvertclass text_t2ascii;
+	logout << text_t2ascii
+	       << "documentaction::output_document: call to QueryFilter failed "
+	       << "for " << args["c"] << " collection (" << get_comerror_string (err) << ")\n";
+	highlight = false;
+      } else {
+	highlight = true;
+      }   
+
+    }
+    
+    format_t *formatlistptr = new format_t();
+    parse_formatstring (formatinfo.DocumentText, formatlistptr, metadata, getParents);
+    
+    metadata.insert ("hastxt");
+    metadata.insert ("haschildren");
+    
+    if (formatinfo.DocumentText == "[Text]")
+      wanttext = 1;
+    else {
+      char *docformat = formatinfo.DocumentText.getcstr();
+      if (strstr (docformat, "[Text]") != NULL)
+	wanttext = 2;
+      delete docformat;
+    }
+    
+    int metasize = metadata.size();
+    
+    if (get_info (OID, collection, metadata, getParents, collectproto, inforesponse, logout)) {
+      int hastxt = inforesponse.docInfo[0].metadata["hastxt"].values[0].getint();
+      int haschildren = inforesponse.docInfo[0].metadata["haschildren"].values[0].getint();
+      
+      if (arg_gt == 0) {
+	output_text (inforesponse.docInfo[0], formatlistptr, queryresponse.termInfo, 
+		     OID, highlight, hastxt, wanttext, collection, collectproto, 
+		     disp, outconvert, textout, logout);
+	
+	
+      } else {
+	
+	ResultDocInfo_t thisdocinfo = inforesponse.docInfo[0];
+	
+	// text is to be expanded
+	text_t exOID = OID;
+	if (haschildren != 1) exOID = get_parent (OID);
+	if (exOID.empty()) exOID = OID;
+	
+	// if we're not in a document (i.e. we're in a top level classification)
+	// we need to pass the "classify" string to get_contents so that it 
+	// doesn't recurse all the way through each document in the classification
+	bool is_classify = false;
+	if (args["d"].empty()) is_classify = true;
+
+	get_contents (exOID, is_classify, metadata, collection, 
+		      collectproto, inforesponse, logout);
+	
+	ResultDocInfo_tarray::iterator sechere = inforesponse.docInfo.begin();
+	ResultDocInfo_tarray::iterator secend = inforesponse.docInfo.end();
+	
+	if (arg_gt == 1) {
+	  // check if there are more than 10 sections containing text to be expanded - 
+	  // if there are output warning message - this isn't a great way to do this
+	  // since the sections may be very large or very small - one day I'll fix it 
+	  // -- Stefan.
+	  int seccount = 0;
+	  while (sechere != secend) {
+	    int shastxt = (*sechere).metadata["hastxt"].values[0].getint();
+	    if (shastxt == 1) seccount ++;
+	    if (seccount > 10) break;
+	    sechere ++;
+	  }
+	  if (seccount > 10) {
+	    // more than 10 sections so output warning message and text 
+	    // for current section only
+	    textout << outconvert << disp << "_document:textltwarning_";
+
+	    output_text (thisdocinfo, formatlistptr, queryresponse.termInfo, 
+			 OID, highlight, hastxt, wanttext, collection, 
+			 collectproto, disp, outconvert, textout, logout);
+	  
+	  }
+	  else arg_gt = 2;
+	}
+	
+	if (arg_gt == 2) {
+	  // get the text for each section
+	  sechere = inforesponse.docInfo.begin();
+	  int count = 0;
+	  while (sechere != secend) {
+	    textout << outconvert << disp << "\n<p><a name=" << count << "></a>\n";
+
+	    int shastxt = (*sechere).metadata["hastxt"].values[0].getint();
+
+	    output_text (*sechere, formatlistptr, queryresponse.termInfo, 
+			 (*sechere).OID, highlight, shastxt, wanttext, collection, 
+			 collectproto, disp, outconvert, textout, logout);
+	    count ++;
+	    sechere ++;
+	  }
+	}
+      }
+    }
+    delete formatlistptr;
+  }
+}
Index: /tags/start/cstr/src/recpt/cstrdocaction.h
===================================================================
--- /tags/start/cstr/src/recpt/cstrdocaction.h	(revision 13666)
+++ /tags/start/cstr/src/recpt/cstrdocaction.h	(revision 13666)
@@ -0,0 +1,64 @@
+/**********************************************************************
+ *
+ * cstrdocaction.h -- 
+ * Copyright (C) 1999  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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+
+#ifndef CSTRDOCACTION_H
+#define CSTRDOCACTION_H
+
+#include "documentaction.h"
+
+class cstrdocaction : public documentaction {
+
+protected:
+
+  void set_java_macros (cgiargsclass &args, displayclass &disp);
+
+  void output_document (const text_t &OID, cgiargsclass &args, 
+			recptproto *collectproto, displayclass &disp, 
+			outconvertclass &outconvert, ostream &textout, 
+			ostream &logout);
+
+public:
+  cstrdocaction ();
+  virtual ~cstrdocaction ();
+
+
+  void get_cgihead_info (cgiargsclass &args, recptprotolistclass *protos,
+			 response_t &response,text_t &response_data, 
+			 ostream &logout);
+
+    //  void define_internal_macros (const ColInfoResponse_t &collectinfo, displayclass &disp, 
+    //			       cgiargsclass &args, recptproto *collectproto, 
+    //			       ostream &logout);
+
+};
+
+
+
+#endif
+
+
Index: /tags/start/cstr/src/recpt/cstrlibrarymain.cpp
===================================================================
--- /tags/start/cstr/src/recpt/cstrlibrarymain.cpp	(revision 13666)
+++ /tags/start/cstr/src/recpt/cstrlibrarymain.cpp	(revision 13666)
@@ -0,0 +1,183 @@
+/**********************************************************************
+ *
+ * cstrlibrarymain.cpp -- 
+ * Copyright (C) 1999  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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2000/02/01 22:32:37  sjboddie
+   Initial revision
+
+   Revision 1.1  1999/09/07 21:49:43  sjboddie
+   new cstr receptionist
+
+ */
+
+#include "receptionist.h"
+#include "cgiwrapper.h"
+#include "nullproto.h"
+#include "collectserver.h"
+#include "filter.h"
+#include "browsefilter.h"
+#include "queryfilter.h"
+#include "infodbclass.h"
+#include "mgsearch.h"
+#include "mggdbmsource.h"
+#include "fileutil.h"
+#include <assert.h>
+
+#include "action.h"
+#include "statusaction.h"
+#include "pageaction.h"
+#include "pingaction.h"
+#include "queryaction.h"
+#include "cstrdocaction.h"
+#include "authenaction.h"
+#include "usersaction.h"
+#include "authenaction.h"
+
+#include "browserclass.h"
+#include "vlistbrowserclass.h"
+#include "hlistbrowserclass.h"
+#include "datelistbrowserclass.h"
+#include "invbrowserclass.h"
+#include "pagedbrowserclass.h"
+#include "htmlbrowserclass.h"
+
+#include "gsdlhome.h"
+
+
+int main () {
+  receptionist recpt;
+  nullproto nproto;
+  
+  // add a collection server
+  text_tarray collections;
+  collections.push_back ("cstr");
+
+  text_tarray::const_iterator thiscol = collections.begin();
+  text_tarray::const_iterator endcol = collections.end();
+
+  while (thiscol != endcol) {
+
+    // this memory is created but never destroyed
+    // we're also not doing any error checking to make sure we didn't
+    // run out of memory
+    collectserver *cserver = new collectserver();
+    gdbmclass *gdbmhandler = new gdbmclass();
+    mgsearchclass *mgsearch = new mgsearchclass();
+    
+    // add a null filter
+    filterclass *filter = new filterclass ();
+    cserver->add_filter (filter);
+    
+    // add a browse filter
+    browsefilterclass *browsefilter = new browsefilterclass();
+    browsefilter->set_gdbmptr (gdbmhandler);
+    cserver->add_filter (browsefilter);
+    
+    // add a query filter
+    queryfilterclass *queryfilter = new queryfilterclass();
+    queryfilter->set_gdbmptr (gdbmhandler);
+    queryfilter->set_mgsearchptr (mgsearch);
+    cserver->add_filter (queryfilter);
+
+    // add a mg and gdbm source
+    mggdbmsourceclass *mggdbmsource = new mggdbmsourceclass ();
+    mggdbmsource->set_gdbmptr (gdbmhandler);
+    mggdbmsource->set_mgsearchptr (mgsearch);
+    cserver->add_source (mggdbmsource);
+    
+    // inform collection server and everything it contains about its
+    // collection name
+    cserver->configure ("collection", *thiscol);
+    
+    nproto.add_collectserver (cserver);
+    thiscol ++;
+  }
+  
+  // add the protocol to the receptionist
+  recpt.add_protocol (&nproto);
+
+  // add other converters
+  utf8inconvertclass utf8inconvert;
+  utf8outconvertclass utf8outconvert;
+  recpt.add_converter ("u", &utf8inconvert, &utf8outconvert);
+
+  mapinconvertclass gbinconvert;
+  gbinconvert.setmapfile (GSDL_GSDLHOME, "gbku", 0x25a1);
+  mapoutconvertclass gboutconvert;
+  gboutconvert.setmapfile (GSDL_GSDLHOME, "ugbk", 0xa1f5);
+  recpt.add_converter ("g", &gbinconvert, &gboutconvert);
+
+  // the list of actions. Note: these actions will become invalid
+  // at the end of this function.
+  statusaction astatusaction;
+  astatusaction.set_receptionist (&recpt);
+  recpt.add_action (&astatusaction);
+
+  pageaction apageaction;
+  recpt.add_action (&apageaction);
+
+  pingaction apingaction;
+  recpt.add_action (&apingaction);
+
+  queryaction aqueryaction;
+  recpt.add_action (&aqueryaction);
+
+  cstrdocaction adocumentaction;
+  recpt.add_action (&adocumentaction);
+
+  usersaction ausersaction;
+  recpt.add_action (&ausersaction);
+
+  authenaction aauthenaction;
+  aauthenaction.set_receptionist(&recpt);
+  recpt.add_action (&aauthenaction);
+
+  // list of browsers
+  vlistbrowserclass avlistbrowserclass;
+  recpt.add_browser (&avlistbrowserclass);
+  recpt.setdefaultbrowser ("VList");
+
+  hlistbrowserclass ahlistbrowserclass;
+  recpt.add_browser (&ahlistbrowserclass);
+
+  datelistbrowserclass adatelistbrowserclass;
+  recpt.add_browser (&adatelistbrowserclass);
+
+  invbrowserclass ainvbrowserclass;
+  recpt.add_browser (&ainvbrowserclass);
+
+  pagedbrowserclass apagedbrowserclass;
+  recpt.add_browser (&apagedbrowserclass);
+
+  htmlbrowserclass ahtmlbrowserclass;
+  recpt.add_browser (&ahtmlbrowserclass);
+
+  cgiwrapper (recpt, "cstr");
+  return 0;
+}
+
Index: /tags/start/cstr/src/recpt/cstrqueryaction.cpp
===================================================================
--- /tags/start/cstr/src/recpt/cstrqueryaction.cpp	(revision 13666)
+++ /tags/start/cstr/src/recpt/cstrqueryaction.cpp	(revision 13666)
@@ -0,0 +1,192 @@
+/**********************************************************************
+ *
+ * cstrqueryaction.cpp -- 
+ * Copyright (C) 1999  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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2000/02/01 22:32:37  sjboddie
+   Initial revision
+
+   Revision 1.1  1999/09/07 21:49:43  sjboddie
+   new cstr receptionist
+
+
+ */
+
+
+#include "cstrqueryaction.h"
+#include "cstrquerytools.h"
+#include "formattools.h"
+#include "OIDtools.h"
+#include "text_t.h"
+
+
+struct ltint 
+{
+  bool operator()(const int &t1, const int &t2) const
+  { return t1 < t2; }
+};
+
+
+bool cstrqueryaction::do_action (cgiargsclass &args, const ColInfoResponse_t &collectinfo, 
+				 recptproto *collectproto, displayclass &disp, 
+				 outconvertclass &outconvert, ostream &textout, 
+				 ostream &logout) {
+
+  if (formatstring.empty()) {
+    text_tmap::const_iterator result = collectinfo.format.find("result");
+    if (result != collectinfo.format.end())
+      formatstring = (*result).second;
+  }
+
+  // if we still don't have a format string use the default
+  if (formatstring.empty()) 
+    formatstring = "<td valign=top nowrap>[link]_icontext_[/link]</td><td>[Title]</td>";
+
+  if (collectproto == NULL) {
+    logout << "cstrqueryaction::do_action called with NULL collectproto\n";
+    textout << outconvert << disp << "_query:header_\n" 
+	    << "Error: Attempt to do query without setting collection\n"
+	    << "_query:footer_\n";
+  } else {  
+
+    FilterRequest_t request;
+    FilterResponse_t response;
+    format_t *formatlistptr = new format_t();
+
+    parse_formatstring (formatstring, formatlistptr, request.fields, request.getParents);
+
+    request.fields.push_back ("Title"); 
+    int metasize = request.fields.size();
+
+    // do the query
+    request.filterResultOptions = FROID | FRmetadata | FRtermFreq;
+    if (!do_query (request, args, collectproto, response, logout))
+      return false;
+    
+    // set macros 
+    define_query_macros (args, disp, response);
+    
+    // output the header
+    textout << outconvert << disp << "_query:header_\n"
+	    << "_query:content_";
+
+    // output the results
+    textout << "<table cellspacing=4>\n";
+    ResultDocInfo_tarray::const_iterator this_doc = response.docInfo.begin();
+    ResultDocInfo_tarray::const_iterator end_doc = response.docInfo.end();
+
+    text_t top;
+    map<text_t, int, lttext_t> topOIDs;
+    map<int, ResultDocInfo_tarray, ltint> OIDs;
+    int count = 0;
+
+    // sort the result set to get document pages together
+    while (this_doc != end_doc) {
+      // don't include docs that didn't match phrases (if there were any)
+      // those that did match will have been sorted to the top
+      if ((*this_doc).num_phrase_match < num_phrases) break;
+
+      get_top ((*this_doc).OID, top);
+      map<text_t, int, lttext_t>::const_iterator it = topOIDs.find (top);
+      if (it == topOIDs.end()) {
+	// haven't seen this document before
+	topOIDs[top] = count;
+	OIDs[count].push_back (*this_doc);
+	count ++;
+      } else {
+	OIDs[(*it).second].push_back (*this_doc);
+      }
+      this_doc ++;
+    }
+
+    text_t link, icon;
+    map<int, ResultDocInfo_tarray, ltint>::iterator here = OIDs.begin();
+    map<int, ResultDocInfo_tarray, ltint>::iterator end = OIDs.end();
+    count = 1;
+    bool done = false;
+    int arg_r = args.getintarg("r");
+    int arg_o = args.getintarg("o");
+    int arg_m = args.getintarg("m");
+    while (here != end) {
+      ResultDocInfo_tarray::const_iterator thisOID = (*here).second.begin();
+      ResultDocInfo_tarray::const_iterator lastOID = (*here).second.end();
+      
+      icon.clear();
+      link.clear(); // link will always be empty as we're including the link in the icon
+      bool first = true;
+
+      while (thisOID != lastOID) {
+
+	if (count < arg_r) {thisOID ++; count ++; continue;}
+	if ((count >= (arg_o + arg_r)) || count > arg_m) {
+	  done = true; 
+	  if (!icon.empty()) {
+	    textout << outconvert << disp << "<tr>\n"
+		    << get_formatted_string (*thisOID, formatlistptr, link, icon) << "\n"
+		    << "</tr>\n";
+	  }
+	  break;
+
+	} else {
+
+	  const text_t &title = (*thisOID).metadata[metasize-1].values.back();
+	  
+	  if (title.empty() && ((*here).second.size() == 1)) 
+	    icon = "<a href=\"_httpdocument_&cl=search&d=" + (*thisOID).OID + "\">_iconclosedbook_</a>";
+	  else {
+	    if (first) icon += "_icontext_<br>";
+	    icon += "<a href=\"_httpdocument_&cl=search&d=" + (*thisOID).OID + "\">page " +
+	      title + "</a><br>\n";
+	  }
+	  
+	  if ((thisOID + 1) == lastOID) {
+	    textout << outconvert << disp << "<tr>\n"
+		    << get_formatted_string (*thisOID, formatlistptr, link, icon) << "\n"
+		    << "</tr>\n";
+	  }
+	  count ++;
+	}
+	if (done) break;
+	first = false;
+	thisOID ++;
+      }
+      here ++;
+    }
+
+    textout << "</table>\n";
+
+    delete (formatlistptr);
+
+    // output the footer
+    textout << outconvert << disp << "_query:footer_";
+  }
+  
+  return true;
+}
+
+
+
Index: /tags/start/cstr/src/recpt/cstrqueryaction.h
===================================================================
--- /tags/start/cstr/src/recpt/cstrqueryaction.h	(revision 13666)
+++ /tags/start/cstr/src/recpt/cstrqueryaction.h	(revision 13666)
@@ -0,0 +1,49 @@
+/**********************************************************************
+ *
+ * cstrqueryaction.h -- 
+ * Copyright (C) 1999  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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+
+#ifndef CSTRQUERYACTION_H
+#define CSTRQUERYACTION_H
+
+#include "gsdlconf.h"
+#include "queryaction.h"
+
+
+class cstrqueryaction : public queryaction {
+
+public:
+  cstrqueryaction () {}
+  virtual ~cstrqueryaction () {}
+  
+  bool do_action (cgiargsclass &args, const ColInfoResponse_t &collectinfo, 
+		  recptproto *collectproto, displayclass &disp, 
+		  outconvertclass &outconvert, ostream &textout, 
+		  ostream &logout);
+};
+
+
+#endif
Index: /tags/start/cstr/src/recpt/cstrquerytools.cpp
===================================================================
--- /tags/start/cstr/src/recpt/cstrquerytools.cpp	(revision 13666)
+++ /tags/start/cstr/src/recpt/cstrquerytools.cpp	(revision 13666)
@@ -0,0 +1,230 @@
+/**********************************************************************
+ *
+ * cstrquerytools.cpp -- 
+ * Copyright (C) 1999  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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2000/02/01 22:32:37  sjboddie
+   Initial revision
+
+   Revision 1.1  1999/09/07 21:49:44  sjboddie
+   new cstr receptionist
+
+
+ */
+
+
+// this is overridden for cstr as we're always going to get
+// maxdocs matches. They can then be sorted in the 
+// cstrqueryaction
+
+#include "cstrquerytools.h"
+
+
+// do_query sets the filter options and makes the protocol call to
+// do a query. The results are returned in response. 
+// request.filterResultOptions and request.fields (if required)
+// should be set by the calling function.
+
+bool do_query (FilterRequest_t &request, cgiargsclass &args, 
+	       recptproto *collectproto, FilterResponse_t &response, 
+	       ostream &logout) {
+
+  request.filterName = "QueryFilter";
+
+  comerror_t err;
+  OptionValue_t option;
+  text_t formattedstring = args["q"];
+  format_querystring (formattedstring, args.getintarg("b"));  
+  
+  option.name = "Term";
+  option.value = formattedstring;
+  request.filterOptions.push_back (option);
+
+  option.name = "QueryType";
+  option.value = (args.getintarg("t")) ? "ranked" : "boolean";
+  request.filterOptions.push_back (option);
+
+  option.name = "Casefold";
+  option.value = (args.getintarg("k")) ? "true" : "false";
+  request.filterOptions.push_back (option);
+
+  option.name = "Stem";
+  option.value = (args.getintarg("s")) ? "true" : "false";
+  request.filterOptions.push_back (option);
+
+  if (!args["h"].empty()) {
+    option.name = "Index";
+    option.value = args["h"];
+    request.filterOptions.push_back (option);
+  }
+
+  if (!args["j"].empty()) {
+    option.name = "Subcollection";
+    option.value = args["j"];
+    request.filterOptions.push_back (option);
+  }
+
+  if (!args["n"].empty()) {
+    option.name = "Language";
+    option.value = args["n"];
+    request.filterOptions.push_back (option);
+  }
+
+  // fill in the second query if needed
+  if (!args["cq2"].empty()) {
+    option.name = "CombineQuery";
+    option.value = args["cq2"];
+    request.filterOptions.push_back (option);
+    
+    text_t formattedstring2 = args["q2"];
+    format_querystring (formattedstring2, args.getintarg("b"));
+
+    option.name = "Term";
+    option.value = formattedstring2;
+    request.filterOptions.push_back (option);
+
+    option.name = "QueryType";
+    option.value = (args.getintarg("t")) ? "ranked" : "boolean";
+    request.filterOptions.push_back (option);
+
+    option.name = "Casefold";
+    option.value = (args.getintarg("k")) ? "true" : "false";
+    request.filterOptions.push_back (option);
+
+    option.name = "Stem";
+    option.value = (args.getintarg("s")) ? "true" : "false";
+    request.filterOptions.push_back (option);
+
+    if (!args["h2"].empty()) {
+      option.name = "Index";
+      option.value = args["h2"];
+      request.filterOptions.push_back (option);
+    }
+
+    if (!args["j2"].empty()) {
+      option.name = "Subcollection";
+      option.value = args["j2"];
+      request.filterOptions.push_back (option);
+    }
+
+    if (!args["n2"].empty()) {
+      option.name = "Language";
+      option.value = args["n2"];
+      request.filterOptions.push_back (option);
+    }
+  }
+
+  // we always want to retrieve all documents (i.e. 1 to maxdocs)
+  // for this collection
+  option.name = "Maxdocs";
+  option.value = args["m"];
+  request.filterOptions.push_back (option);
+  
+  option.name = "StartResults";
+  option.value = 1;
+  request.filterOptions.push_back (option);
+
+  option.name = "EndResults";
+  option.value = args["m"];
+  request.filterOptions.push_back (option);
+
+  collectproto->filter (args["c"], request, response, err, logout);
+
+  if (err != noError) {
+    outconvertclass text_t2ascii;
+    logout << text_t2ascii
+	   << "Error: call to QueryFilter failed in queryaction ("
+	   << get_comerror_string (err) << ")\n";
+    return false;
+  }
+  return true;
+}
+
+void format_querystring (text_t &querystring, int querymode) {
+  text_t formattedstring;
+
+  text_t::const_iterator here = querystring.begin();
+  text_t::const_iterator end = querystring.end();
+
+  // space is used to insert spaces between Chinese
+  // characters. No space is needed before the first
+  // Chinese character.
+  bool space = false;
+
+  // want to remove ()|!& from querystring so boolean queries are just
+  // "all the words" queries (unless querymode is advanced)
+  while (here != end) {
+    if ((querymode == 0) && (*here == '(' || *here == ')' || *here == '|' ||
+			     *here == '!' || *here == '&')) {
+      formattedstring.push_back(' ');
+    } else {
+      if ((*here >= 0x4e00 && *here <= 0x9fa5) ||
+	  (*here >= 0xf900 && *here <= 0xfa2d)) {
+	// Chinese character
+	if (space) formattedstring.push_back (0x200b);
+	formattedstring.push_back (*here);
+	formattedstring.push_back (0x200b);
+	space = true;
+      } else {
+	// non-Chinese character
+	formattedstring.push_back (*here);
+	space = false;
+      }
+    }
+    here ++;
+  }
+  querystring = formattedstring;
+}
+
+void get_phrases (const text_t &querystring, text_tarray &phrases) {
+
+  phrases.erase (phrases.begin(), phrases.end());
+  if (!querystring.empty()) {
+    
+    text_t::const_iterator end = querystring.end();
+    text_t::const_iterator here = findchar (querystring.begin(), end, '"');
+    if (here != end) {
+      text_t tmptext;
+      bool foundquote = false;
+      while (here != end) {
+	if (*here == '"') {
+	  if (foundquote) {
+	    if (!tmptext.empty()) {
+	      phrases.push_back(tmptext);
+	      tmptext.clear();
+	    }
+	    foundquote = false;
+	  } else foundquote = true;
+	} else {
+	  if (foundquote) tmptext.push_back (*here);
+	}
+	here ++;
+      }
+    }
+  }
+}
+
Index: /tags/start/cstr/src/recpt/cstrquerytools.h
===================================================================
--- /tags/start/cstr/src/recpt/cstrquerytools.h	(revision 13666)
+++ /tags/start/cstr/src/recpt/cstrquerytools.h	(revision 13666)
@@ -0,0 +1,41 @@
+/**********************************************************************
+ *
+ * cstrquerytools.h -- 
+ * Copyright (C) 1999  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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+
+#ifndef CSTRQUERYTOOLS_H
+#define CSTRQUERYTOOLS_H
+
+#include "cgiargs.h"
+#include "recptproto.h"
+
+bool do_query (FilterRequest_t &request, cgiargsclass &args, 
+	       recptproto *collectproto, FilterResponse_t &response, 
+	       ostream &logout);
+void format_querystring (text_t &querystring, int querymode);
+void get_phrases (const text_t &querystring, text_tarray &phrases);
+
+#endif
Index: /tags/start/gli/CGatherer
===================================================================
--- /tags/start/gli/CGatherer	(revision 13666)
+++ /tags/start/gli/CGatherer	(revision 13666)
@@ -0,0 +1,28 @@
+#!/bin/sh
+if [ "x$*" = "x" ] ; then
+	 echo "Compiling The Gatherer..."
+	 javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar src/org/greenstone/gatherer/*.java
+	 javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar src/org/greenstone/gatherer/cdm/*.java
+	 javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar src/org/greenstone/gatherer/cdm/custom/*.java
+	 javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar src/org/greenstone/gatherer/checklist/*.java
+	 javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar src/org/greenstone/gatherer/collection/*.java
+	 javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar src/org/greenstone/gatherer/file/*.java
+	 javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar src/org/greenstone/gatherer/gui/*.java
+	 javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar src/org/greenstone/gatherer/gui/border/*.java
+	 javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar src/org/greenstone/gatherer/gui/metaaudit/*.java
+	 javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar src/org/greenstone/gatherer/gui/tree/*.java
+	 javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar src/org/greenstone/gatherer/help/*.java
+	 javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar src/org/greenstone/gatherer/mem/*.java
+	 javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar src/org/greenstone/gatherer/msm/*.java
+	 javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar src/org/greenstone/gatherer/msm/parsers/*.java
+	 javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar src/org/greenstone/gatherer/sarm/*.java
+	 javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar src/org/greenstone/gatherer/shell/*.java
+	 javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar src/org/greenstone/gatherer/undo/*.java
+	 javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar src/org/greenstone/gatherer/util/*.java
+	 javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar src/org/greenstone/gatherer/valuetree/*.java
+	 echo "Done!"
+	 exit 0
+fi
+
+echo "Compiling $*"
+javac -d classes/ -sourcepath src/ -classpath classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar $*
Index: /tags/start/gli/Clean
===================================================================
--- /tags/start/gli/Clean	(revision 13666)
+++ /tags/start/gli/Clean	(revision 13666)
@@ -0,0 +1,34 @@
+#!/bin/sh
+echo "Making Clean..."
+echo "* Removing existing classes."
+pushd classes/
+rm *~
+pushd org/greenstone/gatherer
+rm *.class
+pushd cdm/
+rm *.class
+pushd custom/
+rm *.class
+rm *~
+popd
+popd
+rm -r checklist/
+rm -r collection/
+rm -r file/
+rm -r gui/
+rm -r help/
+rm -r mem/
+rm -r msm/
+rm -r sarm/
+rm -r shell/
+rm -r undo/
+rm -r util/
+rm -r valuetree/
+popd
+popd
+echo "* Removing misc files."
+rm -r gatherer.cfg
+rm -r *.log
+rm -r debug.txt
+rm -r output.txt
+echo "Done."
Index: /tags/start/gli/Document
===================================================================
--- /tags/start/gli/Document	(revision 13666)
+++ /tags/start/gli/Document	(revision 13666)
@@ -0,0 +1,5 @@
+#!/bin/sh
+echo "Generating documentation for The Gatherer..."
+
+javadoc -classpath classes/ -sourcepath src/ -source 1.4 -author -breakiterator -d docs/ -group "Gatherer v2.3" org.greenstone.gatherer:org.greenstone.gatherer.checklist:org.greenstone.gatherer.collection:org.greenstone.gatherer.file:org.greenstone.gatherer.gui:org.greenstone.gatherer.gui.browser:org.greenstone.gatherer.gui.combobox:org.greenstone.gatherer.gui.messages:org.greenstone.gatherer.gui.metaaudit:org.greenstone.gatherer.gui.table:org.greenstone.gatherer.help:org.greenstone.gatherer.sarm:org.greenstone.gatherer.shell:org.greenstone.gatherer.util -group "Collection Design Module" org.greenstone.gatherer.cdm:org.greenstone.gatherer.cdm.custom -group "Metadata Set Manager" org.greenstone.gatherer.msm:org.greenstone.gatherer.msm.parsers -group "GTree" org.greenstone.gatherer.tree -group "Value Tree Controls" org.greenstone.gatherer.valuetree -private -splitindex -version   org.greenstone.gatherer org.greenstone.gatherer.checklist org.greenstone.gatherer.collection org.greenstone.gatherer.file org.greenstone.gatherer.gui org.greenstone.gatherer.gui.browser org.greenstone.gatherer.gui.combobox org.greenstone.gatherer.gui.messages org.greenstone.gatherer.gui.metaaudit org.greenstone.gatherer.gui.table org.greenstone.gatherer.help org.greenstone.gatherer.sarm org.greenstone.gatherer.shell org.greenstone.gatherer.util org.greenstone.gatherer.cdm org.greenstone.gatherer.cdm.custom org.greenstone.gatherer.msm org.greenstone.gatherer.msm.parsers org.greenstone.gatherer.tree org.greenstone.gatherer.valuetree 
+
Index: /tags/start/gli/Gatherer
===================================================================
--- /tags/start/gli/Gatherer	(revision 13666)
+++ /tags/start/gli/Gatherer	(revision 13666)
@@ -0,0 +1,22 @@
+#!/bin/sh
+echo "Running The Gatherer..."
+
+if [ "x$GSDLHOME" = "x" ] ; then
+  echo "Setting GSDLHOME..."
+  pushd "**GSDLHOME**"
+  source setup.bash
+  popd
+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
+
+java -cp classes/:lib/apache.jar:lib/calpa.jar:lib/jp.jar:lib/polloxml.jar:lib/qfslib.jar:lib/skinlf.jar:lib/nanoxml.jar org.greenstone.gatherer.Gatherer -gsdl $GSDLHOME -library **LIBRARYPATH** $*
+#java -cp Gatherer.jar org.greenstone.gatherer.Gatherer -gsdl $GSDLHOME -library <greenstone server> $*
+
+echo "Done!"
+
Index: /tags/start/gli/Gatherer.bat
===================================================================
--- /tags/start/gli/Gatherer.bat	(revision 13666)
+++ /tags/start/gli/Gatherer.bat	(revision 13666)
@@ -0,0 +1,27 @@
+@echo off
+if "%OS%" == "Windows_NT" goto Run
+if "%OS%" == "" goto Win95
+
+:Win95
+if "%1" == "SetEnv" goto Run
+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
+
+:Run
+REM ********************************************
+set GSDLHOME=**GSDLHOME**
+set PERLHOME=**PERLHOME**
+set JAVAHOME=**JAVAHOME**
+set CGIBINHOME=**CGIBINHOME**
+REM ********************************************
+
+set GSDLOS=Windows
+if "%OS%" == "Windows_NT" set PATH=%PATH%;%PERLHOME%;%JAVAHOME%\bin;%GSDLHOME%\bin\windows;%GSDLHOME%\bin\script
+if "%OS%" == "" set PATH="%PATH%";"%PERLHOME%";"%JAVAHOME%\bin";"%GSDLHOME%\bin\windows";"%GSDLHOME%\bin\script"
+
+java.exe -cp Gatherer.jar;classes/;lib/apache.jar;lib/calpa.jar;lib/jp.jar;lib/polloxml.jar;lib/qfslib.jar;lib/skinlf.jar org.greenstone.gatherer.Gatherer -gsdl %GSDLHOME% -perl %PERLHOME% -library %CGIBINHOME%
+echo "Done!"
+
+:End
Index: /tags/start/gli/Install.sh
===================================================================
--- /tags/start/gli/Install.sh	(revision 13666)
+++ /tags/start/gli/Install.sh	(revision 13666)
@@ -0,0 +1,126 @@
+#!/bin/sh
+
+##  Install.sh -- Install the Gatherer
+
+
+# script must be run from within the directory in which it lives
+thisdir=`pwd`
+if [ ! -f "${thisdir}/Install.sh" ]; then
+    echo "Install.sh must be run from the directory in which it resides"
+    exit 1
+fi
+
+
+# see if we can find java
+java="java"
+
+# if JAVAHOME is set we'll use it to determine where java lives, otherwise
+# we just hope it's on the search path
+if [ "$JAVAHOME" != "" ] ; then
+    java="$JAVAHOME/bin/java"
+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 the Gatherer."
+	exit 1
+    fi
+fi
+
+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'`
+jok=1
+if [ $jvmajor -lt 1 ] ; then
+    jok=0
+fi
+if [ $jvmajor -eq 1 ] && [ $jvminor -lt 3 ] ; then
+    jok=0
+fi
+if [ $jok -eq 0 ] ; then
+    echo "The version of the java runtime environment you have installed is too"
+    echo "old to run the Gatherer. Please install a new version of the JRE (version"
+    echo "1.4 or newer) and rerun this installation."
+    exit 1
+fi
+
+
+# make sure perl is ok
+perl=`which perl 2> /dev/null`
+echo "perl: $perl"
+if [ ! -x "$perl" ] ; then
+    echo "The Gatherer 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
+
+
+# Try to find greenstone - greenstone defaults to being installed to
+# either /usr/local/gsdl (if installed as root) or ~/gsdl. We'll look
+# there first
+gsdlhome=
+if [ -d "/usr/local/gsdl" ] ; then
+    gsdlhome="/usr/local/gsdlhome"
+fi
+gsdlos=`uname -s | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+if [ "$gsdlos" = "linux" ]; then
+    logname=`whoami`
+else
+    logname=`logname`
+fi
+if [ -d "/home/${logname}/gsdl" ] ; then
+    gsdlhome="/home/${logname}/gsdl"
+fi
+
+if [ "$gsdlhome" != "" ] ; then
+    echo "A Greenstone installation has been detected at ${gsdlhome}."
+    echo "To use this Greenstone installation with the Gatherer hit enter."
+    echo "To use an alternative Greenstone installation enter the path to"
+    echo "that installation now and hit enter"
+    printf "%s" "> "
+    read ans
+    if [ "$ans" != "" ] ; then
+	gsdlhome="$ans"
+    fi
+else
+    echo "No Greenstone installation could be detected. If you have Greenstone"
+    echo "installed please enter the full path to your gsdl directory and hit"
+    echo "enter. If you don't have Greenstone installed please exit this"
+    echo "installation script by hitting ctrl-c and install Greenstone before"
+    echo "installing the Gatherer."
+    printf "%s" "> "
+    read ans
+    gsdlhome="$ans"
+fi
+# check the the given greenstone installation looks ok
+if [ ! -x "${gsdlhome}/bin/script/import.pl" ] ; then
+    echo "The Greenstone installation at ${gsdlhome} does not"
+    echo "appear to be complete. Try reinstalling Greenstone then running"
+    echo "the install script again."
+    exit 1
+fi
+
+
+# ask the installer for the http path to their greenstone installation
+echo "Please enter the http path to your Greenstone installation's"
+echo "library cgi program. Typically this might be"
+echo "http://localhost/cgi-bin/library,"
+echo "or http://localhost:8080/cgi-bin/library,"
+echo "or http://127.0.0.1/cgi-bin/library,"
+echo "or http://your-computer-name/cgi-bin/library,"
+echo "or http://nnn.nnn.nnn.nn/cgi-bin/library."
+printf "%s" "> "
+read ans
+librarypath="$ans"
+# don't include leading "http://" or trailing "library" in library path
+librarypath=`echo "$librarypath" | sed 's|^http://||'`
+librarypath=`echo "$librarypath" | sed 's|library$||'`
+
+# finally, edit the Gatherer shell script
+sed "s|\*\*GSDLHOME\*\*|${gsdlhome}|" Gatherer > tmp123.txt && mv tmp123.txt Gatherer
+sed "s|\*\*LIBRARYPATH\*\*|${librarypath}|" Gatherer > tmp123.txt && mv tmp123.txt Gatherer
+
+chmod u+x Gatherer
+
+exit 0
Index: /tags/start/gli/RemoveBackups
===================================================================
--- /tags/start/gli/RemoveBackups	(revision 13666)
+++ /tags/start/gli/RemoveBackups	(revision 13666)
@@ -0,0 +1,77 @@
+#!/bin/sh
+echo "* Removing emacs backup files. (*~)"
+rm *~
+pushd src/
+pushd org/greenstone/gatherer/
+rm *~
+pushd cdm/
+rm *~
+pushd custom/
+rm *~
+popd
+popd
+pushd checklist/
+rm *~
+popd
+pushd collection/
+rm *~
+popd
+pushd file/
+rm *~
+popd
+pushd gui/
+rm *~
+pushd browser/
+rm *~
+popd
+pushd combobox/
+rm *~
+popd
+pushd messages/
+rm *~
+popd
+pushd metaaudit/
+rm *~
+popd
+pushd table/
+rm *~
+popd
+pushd tree/
+rm *~
+popd
+popd
+pushd help/
+rm *~
+popd
+pushd mem/
+rm *~
+popd
+pushd msm/
+rm *~
+pushd parsers/
+rm *~
+popd
+popd
+pushd sarm/
+rm *~
+popd
+pushd shell/
+rm *~
+popd
+pushd undo/
+rm *~
+popd
+pushd util/
+rm *~
+popd
+pushd valuetree/
+rm *~
+popd
+popd
+popd
+echo "* Removing misc files."
+rm -r gatherer.cfg
+rm -r *.log
+rm -r debug*.txt
+rm -r output.txt
+echo "Done."
Index: /tags/start/gli/classes/META-INF/MANIFEST.MF
===================================================================
--- /tags/start/gli/classes/META-INF/MANIFEST.MF	(revision 13666)
+++ /tags/start/gli/classes/META-INF/MANIFEST.MF	(revision 13666)
@@ -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/start/gli/classes/dictionary.properties
===================================================================
--- /tags/start/gli/classes/dictionary.properties	(revision 13666)
+++ /tags/start/gli/classes/dictionary.properties	(revision 13666)
@@ -0,0 +1,888 @@
+Language:English - New Zealand
+Version:en_US
+#***** Formatting Arguments *****
+# Arguments 0 - 31 reserved for Gathaen
+Farg32:<HTML><STRONG><FONT FACE={0} COLOR=Black>
+Farg33:<HTML><STRONG><FONT FACE={0} COLOR=Black SIZE=4>
+Farg34:</FONT></STRONG></HTML>
+Farg35:<BR>
+Farg36:<U>
+Farg37:</U>
+Farg38:<HTML><STRONG><FONT FACE={0} COLOR=Black SIZE=2>
+Farg39:<HTML><STRONG><FONT FACE={0} COLOR=Black SIZE=5>
+Farg40:<HTML><STRONG><FONT FACE={0} COLOR=Gray>
+Farg41:<HTML><STRONG><FONT FACE={0} COLOR=Black><CENTER>
+Farg42:</CENTER></FONT></STRONG></HTML>
+Farg43:<HTML><FONT FACE={0} COLOR=Black>
+Farg44:</CENTER></FONT></HTML>
+Farg45:</FONT></HTML>
+Farg46:<CENTER>
+Farg47:</CENTER>
+Farg48:<I>
+Farg49:</I>
+#*******************
+#
+#***** AboutDialog *****
+AboutDialog.Acknowledgement:Acknowledgements for proprietary programs, packages or classes...
+AboutDialog.Item0:'Xerces Java 1' from The Apache Software Foundation (http://www.apache.org/)
+AboutDialog.Item1:'CalPane' HTML renderer by Andrew Moulden (http://www.netcomuk.co.uk/~offshore/index.html)
+AboutDialog.Item2:'WGet' from Free Software Foundation, Inc. (http://www.gnu.org/software/wget/wget.html)
+AboutDialog.Item2:'qflib' from Quality First Software GmbH. (http://www.qfs.de/en/qflib/index.html)
+AboutDialog.Item3:'ExtensionFileFilter.class' by Bruno Dumon and contributors (http://pollo.sourceforge.net/)
+AboutDialog.Item4:'How to disable file renaming in file chooser" - vladi21 (http://www.experts-exchange.com/)
+AboutDialog.Item5:'Autoscrolling" - Java Swing by Robert Eckstein, Marc Loy & Dave Wood (http://www.oreilly.com/catalog/jswing/chapter/dnd.beta.pdf)
+AboutDialog.Item6:'Add ghosted drag images to your JTrees' - By Andrew J. Armstrong (http://www.javaworld.com/javaworld/javatips/jw-javatip114.html)
+AboutDialog.Item7:'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:The Librarian Interface
+AboutDialog.Title_Two:Greenstone Digital Library, University of Waikato
+AboutDialog.Copyright:Copyright (C) 2003 New Zealand Digital Library Project
+#***********************
+#
+#***** Audit Table *****
+AuditTable.File:Filename
+#***********************
+#
+#***** Browser *****
+Browser.Address:{33}Address{34}
+Browser.Back:Back
+Browser.Download_Begun:Downloading {0}
+Browser.Download_Complete:Download of {0} complete
+Browser.Follow:Follow hyperlink to {0}
+Browser.Forward:Forward
+Browser.Go:Go
+Browser.History:History
+Browser.Home:Home
+Browser.Loading:Downloading {0}
+Browser.Ready:Ready
+Browser.Stop:Stop
+#*******************
+#
+#***** Collection *****
+Collection.Cancel_Action:Cancel
+Collection.Collection:{32}Collection: {0}{34}
+Collection.No_Collection:No Collection
+Collection.Selection_Information:Selection Information
+Collection.Workspace:{32}Workspace{34}
+Collection.Workspace_View:{32}View:{34}
+#**********************
+#
+#***** CollectionManager *****
+CollectionManager.Cannot_Open:The collection at {0} cannot be opened.
+CollectionManager.Collection_Saved:The collection "{0}" has been saved.
+CollectionManager.Creating_New:Creating a new collection {0}.
+CollectionManager.File_Not_Found:{0}\nThe collection above cannot be opened as it no longer exists.
+CollectionManager.Gcache_Created:The Librarian Interface cache directory created.
+CollectionManager.Gimport_Created:The Librarian Interface import directory created.
+CollectionManager.Loading_Successful:Loaded collection {0}.
+CollectionManager.Save_Error:Cannot save collection {0}.
+CollectionManager.Session_Ready:Collection {0} ready for use.
+#*****************************
+#
+#***** CollectionPopupMenu *****
+CollectionPopupMenu.Delete:Delete
+CollectionPopupMenu.New_Folder:New Folder
+#*******************************
+#
+#***** CreatePane *****
+CreatePane.All:All
+CreatePane.AllClassifications:allclassifications
+CreatePane.AllClassifications_Tip:Prevent the build process from removing classifications that include no documents (for example, the "X" classification in title if there are no documents whose titles start with the letter <i>X</i>).
+CreatePane.ArchiveDir:archivedir
+CreatePane.ArchiveDir_Tip:Specify where the Greenstone archive files are stored - that is, where <i>import.pl</i> puts them and where <i>buildcol.col</i> finds them. Defaults to <i>GSDLHOME/collect/col_name/archives</i>
+CreatePane.Build:Build
+CreatePane.Build_Collection:Build Collection
+CreatePane.BuildDir:builddir
+CreatePane.BuildDir_Tip:Specify where the result of building is to be stored (defaults to <i>GSDLHOME/collect/col_name/building</i>).
+CreatePane.Build_Progress:Build Progress
+CreatePane.Cancel_Build:Cancel Build
+CreatePane.CollectDir:collectdir
+CreatePane.CollectDir_Tip:Specify where the collection can be found. Defaults to <i>GSDLHOME/collect</i>
+CreatePane.Copy_Progress:Copy Progress
+CreatePane.CreateImages:create_images
+CreatePane.CreateImages_Tip:Create colleciton icons automatically (to use this, GIMP, and the Gimp Perl module, must be installed).
+CreatePane.Debug:debug
+CreatePane.Debug_Tip:Print plugin output to standard output.
+CreatePane.Document_Count:Collection contains {0} files.
+CreatePane.General:General
+CreatePane.GroupSize:groupsize
+CreatePane.GroupSize_Tip:Number of documents to group together into one Greenstone archive file, defaults 1 (that is, one document per file).
+CreatePane.GZip:gzip
+CreatePane.GZip_Tip:Zip up the Greenstone archive documents produced by <i>import</i> (ZIPPlug must be included in the plugin list, and <i>gzip</i> must be installed on your machine).
+CreatePane.Import:Import
+CreatePane.Import_Progress:Import Progress
+CreatePane.Index:index
+CreatePane.Index_Tip:Specify which indexes to build. This defaults to all the indexes indicated in the collection configuration file.
+CreatePane.KeepOld:keepold
+CreatePane.KeepOld_Tip:Do not remove the result of the previous import or build operation. In the case of import, do not remove the contents of the <i>archives</i> directory; when building, do not remove the content of the <i>building</i> directory.
+CreatePane.ImportDir:importdir
+CreatePane.ImportDir_Tip:Where material to be imported is found. Defaults to <i>GSDLHOME/collection/col_name/gimport</i>
+CreatePane.Log:Message Log
+CreatePane.MaxDocs:maxdocs
+CreatePane.MaxDocs_Tip:Indicates the maximum number of documents to be imported or built. Useful when testing a new collection configuration file, or new plugins.
+CreatePane.Mode:mode
+CreatePane.Mode_All:all
+CreatePane.Mode_Build_Index:build index
+CreatePane.Mode_Compress_Text:compress text
+CreatePane.Mode_InfoDB:infodb
+CreatePane.Mode_Tip:Determine what the build process is to do (defaults to <i>all</i>). <i>All</i> does a full build, <i>compress_text</i> only compresses the document text, <i>infodb</i> creates a database of information pertaining the to collection and <i>build_index</i> builds the indexes specified in the collection configuration file or on the command line.
+CreatePane.NoText:no_text
+CreatePane.NoText_Tip:Don't store compressed text. This options is useful for minimizing the size of the built indexes if you intend to always display the original documents at run-time.
+CreatePane.OIDType:OIDtype
+CreatePane.OIDType_Hash:hash
+CreatePane.OIDType_Incremental:incremental
+CreatePane.OIDType_Tip:Method of creatings OIDs for documents: <i>hash</i> hashes the content but is slow; <i>incremental</i> simply assigns document numbers sequentially, and is faster.
+CreatePane.Options:Option Groups
+CreatePane.Options_Title:Collection Import & Build Options
+CreatePane.Out:out
+CreatePane.Out_Tip:Specify a file to which to write all output messages, which defaults to standard error (the screen). Useful when working with debugging statements.
+CreatePane.RemoveOld:removeold
+CreatePane.RemoveOld_Tip:Remove the contents of the <i>archives</i> directory before importing.
+CreatePane.Statistics_Title:Collection Statistics
+CreatePane.SortMeta:sortmeta
+CreatePane.SortMeta_Tip:Sort the documents alphabetically by the named metadata tag. However, if the collection has more than one group in the collection (i.e. <i>groupsize</i> > 1), this functionality is disabled.
+CreatePane.Verbosity:verbosity
+CreatePane.Verbosity_Tip: A number between zero and three that controls how much information about the process is printed to the standard error stream; 0 gives a little, 3 gives lots.
+#**********************
+#
+#***** Delete Collection Prompt *****
+DeleteCollectionPrompt.Collection_Details:Selected collections details.
+DeleteCollectionPrompt.Collection_List:Available collections.
+DeleteCollectionPrompt.Confirm_Delete:Please tick the box to confirm collection deletion.
+DeleteCollectionPrompt.Details:Title    - {0}\nFilename - {1}\nEmail    - {2}\nDescription\n{3}
+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
+#************************************
+#
+#***** Dictionary *****
+# 0 - A String representing a key value.
+Dictionary.Missing_Phrase:Missing dictionary phrase for key {0}
+#**********************
+#
+#***** DirectoryLevelMetadata *****
+DirectoryLevelMetadata.Message:You are about to assign 'directory 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 the OK button.
+DirectoryLevelMetadata.Title:About to add folder level metadata
+#****************************************
+#
+#***** FileActions *****
+FileActions.Calculating_Size:Calculating selected files total size.
+FileActions.Cannot_Copy:Files cannot be copied. Please check disk space.
+FileActions.Cannot_Delete:Files cannot be deleted. Please check permissions.
+FileActions.Copied_Files:Copied {0} files to {1}.
+FileActions.Copying:Copying {0}.
+FileActions.Deleted: Deleted {0} files.
+FileActions.Deleting:Deleting {0}.
+FileActions.File_Already_Exists_Message:"{0}"\nA file with the name shown above already exists at the\ndestination, and despite your previous choice the Librarian Interface\nis unable to overwrite it. Please check file permissions.
+FileActions.File_Already_Exists_Title:Error - File Already Exists.
+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_Not_Found_Title:Error - File Not Found.
+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.Insufficient_Space_Title:Error - Insufficient Space
+FileActions.Jobs:{0} file actions remaining.
+FileActions.No_Activity:No action requested.
+FileActions.No_Parent_For_New_Folder:To create a new folder you must first select a single destination folder in the collection tree.
+FileActions.No_Selection:No files selected.
+FileActions.Pre_Action:Select destination for these {0} files.
+FileActions.Read_Only:Files from the workspace are read only and cannot be deleted.
+FileActions.Reading_Metadata:Reading existing metadata. Please be patient.
+FileActions.Selected:{0} files and {1} directories selected
+FileActions.Unknown:unknown
+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.Unknown_File_Error_Title:Error - Unknown File Error
+#***********************
+#
+#***** GAuthenticator *****
+GAuthenticator.Password:Password:
+GAuthenticator.Title:Password Required.
+GAuthenticator.Username:User Name:
+#**************************
+#
+#***** General Messages *****
+# 0 - A String representing the name and method of the class in question.
+General.Apply:Apply
+General.Apply_Tooltip:Click here to immediately apply any changes made.
+General.Browse:Browse
+General.Cancel:Cancel
+General.Cancel_Tooltip:Click here to cancel the prompt and ignore changes.
+General.Close:Close
+General.Edit:Edit Value
+General.Error:Error
+General.Expand:Edit Text...
+General.File_Description:Librarian Interface Collection (*.col)
+General.No:No
+General.OFF:Off
+General.OK:OK
+General.OK_Tooltip:Click here to accept the changes then remove the prompt.
+General.ON:On
+General.Open:Open
+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.Proxy_Set_Error:Warning. Proxy not available.
+General.Usage:Usage: Gathaen <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.Warning:Warning
+General.Yes:Yes
+#****************************
+#
+#***** GShell *****
+GShell.Build:buildcol.pl
+GShell.Cancelled:Process cancelled by user or by unrecoverable exception.
+GShell.Command:Command
+GShell.Failure:Command failed.
+GShell.Import:import.pl
+GShell.New:makecol.pl
+GShell.Other:other
+GShell.Success:Command complete.
+#******************
+#
+#***** GStartBox *****
+GStartBox.Exit:{32}Exit{34}
+GStartBox.Load:{32}Load{34}
+GStartBox.New:{32}New{34}
+#*********************
+#
+#***** GUI *****
+# Currently Enabled and Disabled display the same text but in different
+* colours. If necessary this can be changed.
+GUI.Browser:Browse
+GUI.Build:Design
+GUI.Collection:Gather
+GUI.Create:Create
+GUI.Export:Export
+GUI.Import:Import
+GUI.Main:Start
+GUI.Messages:Log
+GUI.MetaEdit:Enrich
+GUI.Mirroring:Mirror
+GUI.Preview:Preview
+#***************
+#
+#***** HELP *****
+Help.Contents:Contents
+Help.Index:Index
+Help.Title:Gathaen Help Pages
+#***** Inherited Metadata *****
+InheritedMetadata.Message:The selected file or folder inherits some of its metadata from folders above it. Such entries are denoted by a folder icon, and you can visit the actual folder containing the metadata by clicking on the aforementioned icon.
+InheritedMetadata.Title:This File/Folder Has Inherited Metadata
+#***** Levels *****
+Level.Error:Error
+Level.Event:Event
+Level.Information:Information
+Level.Main:Main
+Level.Unknown:Unknown
+#******************
+#
+#***** LockFileDialog *****
+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 (not recommended)?
+LockFileDialog.Machine:Where
+LockFileDialog.Name:Name
+LockFileDialog.Title:Lock File Detected
+LockFileDialog.User:Who
+#**************************
+#
+#***** Menu Options *****
+Menu.Edit:Edit
+Menu.Edit_Redo:Redo
+Menu.Edit_Undo:Undo
+Menu.File:File
+Menu.File_Close:Close
+Menu.File_Delete:Delete
+Menu.File_Exit:Exit
+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:Metadata
+Menu.Metadata_Add:Add Set
+Menu.Metadata_Edit:Edit Set
+Menu.Metadata_Export:Export Set
+Menu.Tools:Tools
+Menu.Tools_Log:View Log
+#************************
+#
+#***** Messages *****
+Messages.Browser:{32}Browser{34}
+Messages.Build:{32}Build{34}
+Messages.Error:{32}Error{34}
+Messages.Event:{32}Event{34}
+Messages.General:{32}General{34}
+Messages.Information:{32}Information{34}
+Messages.Level:{33}Levels{34}
+Messages.Main:{32}Main{34}
+Messages.Message_Count:Viewing {0} of {1} entires.
+Messages.Metaedit:{32}MetaEdit{34}
+Messages.Mirroring:{32}Mirroring{34}
+Messages.Save_Messages:{32}Save{35}Log{34}
+Messages.Session:{32}Collection{34}
+Messages.Source:{33}Sources{34}
+#********************
+#
+#***** MetaAudit *****
+MetaAudit.Hide_Columns:View/Hide Empty Columns
+MetaAudit.Title:All Metadata
+#*********************
+#
+#***** Metadata *****
+Metadata.Set:Set
+Metadata.Element:Element
+Metadata.Value:Value
+#********************
+#
+#***** MetaEdit *****
+MetaEdit.Add:Add
+MetaEdit.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.
+MetaEdit.Element:Element
+MetaEdit.List:Matching Previous Values
+MetaEdit.No_Description:{38}No description for chosen key.{34}
+MetaEdit.No_File:No File Chosen
+MetaEdit.No_Metadata:{32}No Metadata Assigned{34}
+MetaEdit.No_Type:{38}(Any value){34}
+MetaEdit.Remove:Remove
+MetaEdit.Restore:Restore Tree
+MetaEdit.Search:Search
+MetaEdit.Thumbnail:{32}Thumbnails for selection{34}
+MetaEdit.Tools_Off:{32}No File Chosen{34}
+MetaEdit.Tree:All Previous Values
+MetaEdit.Update:Update
+MetaEdit.Value:Value
+MetaEdit.View:View
+MetaEdit.View_Assigned:View Assigned Metadata
+MetaEdit.View_Unassigned:View Unassigned Metadata
+#********************
+#
+#***** MetaEditPrompt *****
+MetaEditPrompt.Accumulate:Add
+MetaEditPrompt.Accumulate_All:Add All
+MetaEditPrompt.Add_Title:Confirm Addition
+MetaEditPrompt.Cancel:Cancel
+MetaEditPrompt.File:File name: {0}
+MetaEditPrompt.Key:Key: {0}
+MetaEditPrompt.New_Value:New value: {0}
+MetaEditPrompt.Old_Value:Old value: {0}
+MetaEditPrompt.Overwrite:Replace
+MetaEditPrompt.Overwrite_All:Replace All
+MetaEditPrompt.Remove:Remove
+MetaEditPrompt.Remove_All:Remove All
+MetaEditPrompt.Remove_Title:Confirm Removal
+MetaEditPrompt.Skip:Skip File
+MetaEditPrompt.Update:Replace
+MetaEditPrompt.Update_All:Replace All
+MetaEditPrompt.Update_Title:Confirm Update
+MetaEditPrompt.Value:Value: {0}
+#*****************************
+#
+#***** Mirroring *****
+Mirroring.Destination_Folder:Destination Folder:
+Mirroring.Destination_Private:Private
+Mirroring.Destination_Shared:Public
+Mirroring.Download:{39}Download{34}
+Mirroring.Download_Controls:Download Controls
+Mirroring.Download_Depth:Download Depth:
+Mirroring.Download_Hidden:Automatically download embedded objects (images etc)?
+Mirroring.Download_List:Download List
+Mirroring.Download_List_Configuration:Download List Options
+Mirroring.Further_Options:For further options see the configuration screen.
+Mirroring.Higher_Directories:Mirror files from directories above the url given?
+Mirroring.Overwrite_Existing:Overwrite files if they already exist locally?
+Mirroring.Remove_Failed:Automatically remove failed downloads from the list?
+Mirroring.Same_Host:Only mirror within the same site?
+Mirroring.Source_URL:Source URL:
+Mirroring.View_Selector:Show:
+Mirroring.Workspace_Tree:Temporary Workspace
+#*********************
+#
+#***** Missing EXEC *****
+MissingEXEC.Message:Warning! You will not be able to view your new collections within Librarian Interface unless you specify the path to the locally running Greenstone Library Webserver. If you believe you are recieving this message in error please check your installation, and the paths specified in Librarian Interface batch or script file.
+MissingEXEC.Title:Missing Greenstone Library 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 recieving 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 recieving this message in error please check your installation, and the paths specified in Librarian Interface batch or script file.
+MissingPERL.Title:Missing PERL Path
+#***** New Folder Prompt *****
+NewFolderPrompt.Default_Folder_Name:new folder
+NewFolderPrompt.Folder_Name:Folder Name
+NewFolderPrompt.Title:Enter the new folders name.
+#*****************************
+#
+#***** New Session *****
+NewCollectionPrompt.Base_Collection:Base this collection on:
+NewCollectionPrompt.Collection_Description:Description of content:
+NewCollectionPrompt.Collection_Email:Author's Email:
+NewCollectionPrompt.Collection_Name:Short Name:
+NewCollectionPrompt.Collection_Title:Title:
+NewCollectionPrompt.Default_Description:A Greenstone Digital Collection built with The Librarian Interface.
+NewCollectionPrompt.DLS:DLS
+NewCollectionPrompt.Dublin_Core:Dublin Core
+NewCollectionPrompt.Error:Error in new collection.
+NewCollectionPrompt.Instructions:Fill out all of the fields below in order to create a new Collection.
+NewCollectionPrompt.Metadata_Elements:Elements within selected set:
+NewCollectionPrompt.Metadata_Instructions:Check the boxes beside the metadata sets you would like to be initially present in your collection.
+NewCollectionPrompt.NewCollection:-- New Collection --
+NewCollectionPrompt.Select_MDS:Available metadata sets:
+NewCollectionPrompt.Set_Contains:This metadata set contains the elements
+NewCollectionPrompt.Title:Create a new Collection.
+#***********************
+#
+NoMetadataSetsSelected.Message:If you create the collection now it will have no initial metadata sets. You will not be able to import nor assign any metadata until a set is imported or added to your collection. Do you wish to continue?
+NoMetadataSetsSelected.Title:No Metadata Sets Selected
+#
+#***** OpenCollectionDialog *****
+OpenCollectionDialog.Collection:Greenstone Collection (".col")
+OpenCollectionDialog.Locked_Collection:Greenstone collection already is use
+OpenCollectionDialog.No_Description:Please select a greenstone collection ('.col' file) to see description.
+OpenCollectionDialog.Normal_Collection:Greenstone collection
+OpenCollectionDialog.Title:Open Greenstone Collection
+#********************************
+#
+#***** Options *****
+Options.Connection:Connection
+Options.Download:Download
+Options.Establish_Connection:Establish Connection
+Options.General:General
+Options.Proxy_Configuration:Proxy Configuration
+Options.Proxy_Host:Host Name
+Options.Proxy_Port:Port Number
+Options.Title:The Librarian Interface Options
+Options.Use_Colours:Use Colours?
+Options.Use_Proxy:Internet connection through proxy server.
+#*******************
+#
+#***** Preferences *****
+Preferences:Preferences
+Preferences.Connection:Connection
+Preferences.Connection.Proxy_Host:Proxy host
+Preferences.Connection.Proxy_Port:Proxy port
+Preferences.Connection.Use_Proxy:Use proxy connection?
+Preferences.Warnings:Warnings
+Preferences.Workflow:Workflow
+Preferences.Workflow.Browse:Browse - Search for web-based resources
+Preferences.Workflow.Create:Create - Build your collection using Greenstone 
+Preferences.Workflow.Design:Design - Change collection appearence
+Preferences.Workflow.Enrich:Enrich - Annotate with metadata
+Preferences.Workflow.Export:Export - Export to collection
+Preferences.Workflow.Gather:Gather - Select files for collection
+Preferences.Workflow.Mirror:Mirror - Download web-based resources
+Preferences.Workflow.Predefined.Label:Predefined Workflows
+Preferences.Workflow.Preview:Preview - Browse built collection
+Preferences.Workflow.Title:Check box to enable view
+#***********************
+#
+#***** POLLO *****
+Pollo.Message:Pollo Message
+Pollo.Well_Formedness_Error:This edited xml contains well formedness errors. Do you wish to discard changes and close editor?
+#*****************
+#
+#***** Save Collection Box *****
+SaveCollectionBox.Label:Do you wish to save "{0}"?
+SaveCollectionBox.Title:Save Collection
+#*******************************
+#
+#***** Sources *****
+Source.Browse:Browse
+Source.Build:Create
+Source.Building:Perl
+Source.Collect:Gather
+Source.General:General
+Source.MetaEdit:Enrich
+Source.Mirror:Mirror
+Source.Unknown:Unknown
+#*******************
+#
+#***** Trees *****
+Tree.Multiple_Items:files.
+Tree.New_Folder:New Folder
+Tree.Private:Private WebCache
+Tree.Public:Public WebCache
+Tree.Root:Local Filespace
+Tree.Unnamed:Unnamed
+Tree.World:Greenstone Collections
+#*****************
+#
+#***** UndoManager *****
+UndoManager.Redo:Redo Change
+UndoManager.Undo:Undo Change
+#***********************
+#
+#***** Warning Dialog *****
+WarningDialog.Dont_Show_Again:Do not show this warning again.
+#
+#     ********************************************************
+#     *************** 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:Add
+CDM.ArgumentConfiguration.Bad_Integer:<html>The argument '{0}' requires an integer value,<br>but no integer can be parsed from {1}.</html>
+CDM.ArgumentConfiguration.Custom:Custom Arguments:
+CDM.ArgumentConfiguration.Error_Title:Error In Arguments
+CDM.ArgumentConfiguration.Header:{39}{46}Please configure the arguments for {0}.{47}{34}
+CDM.ArgumentConfiguration.Remove:Remove
+CDM.ArgumentConfiguration.Required_Argument:The argument '{0}' must be given a value.
+CDM.ArgumentConfiguration.Title:Configuring Arguments
+CDM.ClassifierManager.Add:Add Specified Classifier
+CDM.ClassifierManager.Assigned:Currently Assigned Classifiers
+CDM.ClassifierManager.Classifier:Select classifier to add:
+CDM.ClassifierManager.Configure:Configure Selected Classifier
+CDM.ClassifierManager.Controls:Editing Controls
+CDM.ClassifierManager.Instructions:Use this view to add, configure or remove classifiers in your collection. To add a classifier, choose it from the combobox and click "Add Specified Classifier".\nTo remove a classifier choose it from the list of assigned classifiers and click "Remove Selected Classifier".\nFinally to configure a classifier, again choose it from the assigned classifiers list, then press "Configure Selected Classifier".\n\nIf you choose to configure a classifier you will be presented with a new pop-up design area with a scrollable list of known arguments you can provide to the classifier. Simply enable the argument you wish to provide and enter or select a value if necessary. If the design manager cannot determine what the arguments are for this classifier, then you will instead be presented with a text field into which you can type the desired arguments.
+CDM.ClassifierManager.Remove:Remove Selected Classifier
+CDM.ClassifierManager.Title:{39}{46}Classifier Selection & Configuration{47}{34}
+CDM.ClassifierManager.Parsing.Message:Design tool is loading classifier information.
+CDM.ClassifierManager.Parsing.Title:Loading Classifiers
+CDM.General.Access:Is this collection publically accessible?
+CDM.General.Beta:Is this collection still under construction?
+CDM.General.Collection_Extra:Collection description:
+CDM.General.Collection_Name:Collection title:
+CDM.General.Icon_Collection:URL to collection icon:
+CDM.CollectionMetaManager.Add:Add New Metdata
+CDM.CollectionMetaManager.Any:Any Language
+CDM.CollectionMetaManager.Instructions:This design view allows you to add, modify and remove collection level metadata. To add metadata first select or type the name of the part of the collection you wish to add metadata to. Next choose a target language if applicable. Finally enter the value of the metadata and press 'Add New Metadata'.\nEditing an metadata entry is also simple. Select it from the list of metadata, then edit of change the assignment, language and value as necessary. Pressing 'Add New Metadata' now will add the modified metadata -without- changing the old. Otherwise when you select a different metadata entry, or leave the view, the metadata entry will be updated with the modified details.\nThe last action available is to delete a piece of metadata. Again select it  from the list of metadata, then press the "Remove Selected Metadata" button. Easy.
+CDM.CollectionMetaManager.Language:Target language:
+CDM.CollectionMetaManager.Metadata:Assigned Metadata
+CDM.CollectionMetaManager.Name:Assign metadata to:
+CDM.CollectionMetaManager.Remove:Remove Selected Metadata
+CDM.CollectionMetaManager.Title:{39}{46}Collection Level Metadata{47}{34}
+CDM.CollectionMetaManager.Value:Metadata value:
+CDM.FormatManager.Add:Add Format
+CDM.FormatManager.Assigned_Formats:Currently Assigned Format Commands
+CDM.FormatManager.Custom:{43}{48}custom{49}{45}
+CDM.FormatManager.Editor:Edit Format String
+CDM.FormatManager.Feature:Choose Feature
+CDM.FormatManager.Insert:Insert
+CDM.FormatManager.Off:False
+CDM.FormatManager.On:True
+CDM.FormatManager.Part:Affected Component
+CDM.FormatManager.Preview:Preview Format
+CDM.FormatManager.Remove:Remove Format
+CDM.FormatManager.Special:Variables
+CDM.FormatManager.Title:{39}{46}Format Commands{47}{34}
+CDM.FormatManager.Value:Value:
+CDM.General.Email.Creator:Creator's Email
+CDM.General.Email.Maintainer:Maintainer's Email
+CDM.General.Instructions:The design section of the Librarian Interface contains tools and options for controlling many aspects of your collections appearance. For ease and clarity the design is split up into several sections. This section is the general options view and contains options and settings which don't clearly belong anywhere else. To choose a different section simply click on its name in the list to the left of the screen.
+CDM.General.Title:{39}{46}General Options{47}{34}
+CDM.GUI.Building:Creating the {0} design view.
+CDM.GUI.Classifiers:Classifiers
+CDM.GUI.CollectionMeta:Collection Metadata
+CDM.GUI.Design_Topics:Design Sections
+CDM.GUI.Formats:Format
+CDM.GUI.General:General
+CDM.GUI.Indexes:Indexes
+CDM.GUI.Languages:Languages
+CDM.GUI.MetadataSets:Metadata Sets
+CDM.GUI.Plugins:Plug-ins
+CDM.GUI.Ready:Ready
+CDM.GUI.Root:CDM_ROOT
+CDM.GUI.Subcollections:Subcollections
+CDM.IndexManager.Add:Add Specified Index
+CDM.IndexManager.Clear_Default:Clear Default Index
+CDM.IndexManager.Default_Index:Default Index:
+CDM.IndexManager.Document:document
+CDM.IndexManager.Indexes:Assigned Indexes
+CDM.IndexManager.Instructions:This design view allows you to modify the indexes that the collection will be built with.\nTo add a new index, select the source or sources to build the index on, choose the level of the index, and click "Add Specified Index".\nTo remove an index select it from the assigned indexes list and click "Remove Selected Index".\nYou can also set the default index by selecting it from the same list and clicking "Set Selected As Default", or clear the default by clicking the "Clear Default Index" button.
+CDM.IndexManager.Level:At the level:
+CDM.IndexManager.Name:Index Name:
+CDM.IndexManager.Paragraph:paragraph
+CDM.IndexManager.Remove:Remove Selected Index
+CDM.IndexManager.Section:section
+CDM.IndexManager.Set_Default:Set Selected As Default
+CDM.IndexManager.Source:Build index on:
+CDM.IndexManager.Text_Only:'text' only.
+CDM.IndexManager.Title:{39}{46}Index Selection{47}{34}
+CDM.LanguageManager.Add:Add Language
+CDM.LanguageManager.Clear_Default:Clear Default Language
+CDM.LanguageManager.Default_Language:Default Language
+CDM.LanguageManager.Instructions:Use this panel to specify what languages the indexes should be built in.\nAlso use it to set the default language for this collection.
+CDM.LanguageManager.Remove:Remove Language
+CDM.LanguageManager.Selector:Language to add: 
+CDM.LanguageManager.Set_Default:Set Default Language
+CDM.LanguageManager.Title:{39}{46}Language Selection{47}{34}
+CDM.LanguageManager.Translate:Translate Assigned Text Fragments
+CDM.MetadataSetManager.Elements:Elements in selected Metadata Set
+CDM.MetadataSetManager.Instructions:While this design view is read-only, it does provide you with an opportunity to review the Metadata Sets currently imported into your collection, what Metadata Elements they contain, and how they will appear in the collection configuration file.
+CDM.MetadataSetManager.Sets:Available Metadata Sets
+CDM.MetadataSetManager.Title:{39}{46}Metadata Set Review{47}{34}
+CDM.Move.At_Bottom:Cannot move the plugin {0} lower as it is already at the bottom of the list.
+CDM.Move.At_Top:Cannot move the plugin {0} 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.Title:Error - Cannot Move
+CDM.PlugInManager.Add:Add Specified Plugin
+CDM.PlugInManager.Assigned:Currently Assigned Plugins
+CDM.PlugInManager.Configure:Configure Selected Plugin
+CDM.PlugInManager.Controls:Editing Controls
+CDM.PlugInManager.Instructions:Use this view to add, configure or remove plugins from your collection. Adding a new plugin simply involves choosing it from the combobox and clicking "Add Specified Plugin".\nOnce you select a plugin from the list of assigned plugins you can:\ni)   Change its position in the plugin order by clicking on the various movement buttons,\nii)  Further configure the plugin by clicking "Configure Selected Plugin",\niii) or remove the selected plugin by clicking "Remove Selected Plugin".\n\nIf you choose to configure a plugin you will be presented with a new pop-up design area with a scrollable list of known arguments you can provide to the plugin. Simply enable the argument you wish to provide and enter or select a value if necessary. If the design manager cannot determine what the arguments are for this plugin, then you will instead be presented with a text field into which you can type the desired arguments.\n\nNote: The position of the RecPlug and ArcPlug are fixed. 
+CDM.PlugInManager.Move_Bottom:Move To Bottom
+CDM.PlugInManager.Move_Down:Move Down
+CDM.PlugInManager.Move_Top:Move To Top
+CDM.PlugInManager.Move_Up:Move Up
+CDM.PlugInManager.PlugIn:Select plugin to add:
+CDM.PlugInManager.Remove:Remove Selected Plugin
+CDM.PlugInManager.Title:{39}{46}Plugin Selection & Configuration{47}{34}
+CDM.PlugInManager.Parsing.Message:Design tool is loading plugin information.
+CDM.PlugInManager.Parsing.Title:Loading PlugIns
+CDM.SubcollectionManager.Add:Add New Subcollection
+CDM.SubcollectionManager.Add_Subindex:Add Selected As New Subindex
+CDM.SubcollectionManager.Assigned:Assigned Subcollections
+CDM.SubcollectionManager.Clear_Default_Subindex:Clear Default Subindex
+CDM.SubcollectionManager.Default_Subindex:Default Subindex:
+CDM.SubcollectionManager.Exclude:Exclude
+CDM.SubcollectionManager.Flags:Flags to set when matching.
+CDM.SubcollectionManager.Include:Include
+CDM.SubcollectionManager.Inclusive:What do we do with files that match?
+CDM.SubcollectionManager.Instructions:Use this panel to edit the design of subcollections. The tabbed pane below allows you to choose either: Subcollection Controls to add or remove subcollections, or Subindex Controls to change how these subcollections are indexed. In Subindex Controls you can add multiple subcollections as one index by using the multiple selection methods, detailed in help, to select the series of subcollections to build indexes across. 
+CDM.SubcollectionManager.Match:Regular expression to match with: 
+CDM.SubcollectionManager.Name:Name the subcollection:
+CDM.SubcollectionManager.Remove:Remove Selected Subcollection
+CDM.SubcollectionManager.Remove_Subindex:Remove Selected Subindex
+CDM.SubcollectionManager.Set_Default_Subindex:Set Default Subindex
+CDM.SubcollectionManager.Source:Document attribute to match against:
+CDM.SubcollectionManager.Subcollection:Available Subcollections
+CDM.SubcollectionManager.Subcollection_Controls:Subcollection Controls
+CDM.SubcollectionManager.Subindexes:Assigned Subindexes
+CDM.SubcollectionManager.Subindex_Controls:Subindex Controls
+CDM.SubcollectionManager.Title:{39}{46}Subcollection Design{47}{34}
+CDM.TranslationManager.Affected_Features:Affected Features
+CDM.TranslationManager.Assigned:Ready
+CDM.TranslationManager.Assigned_Languages:Assigned Languages
+CDM.TranslationManager.Default_Text:Default Text Fragment
+CDM.TranslationManager.Existing_Text:First Existing Text Fragment
+CDM.TranslationManager.Language:Language
+CDM.TranslationManager.No_Text:No Existing Text
+CDM.TranslationManager.Text:Text Fragment
+CDM.TranslationManager.Translation:Translation
+#     ********************************************************
+#
+#     ********************************************************
+#     ****************** Metadata Set Module *****************
+#     ********************************************************
+MSMPrompt.Add:Add
+MSMPrompt.Add_Failed:Cannot add the element "{0}" because:\n{1}
+MSMPrompt.Add_Failed_Title:Add Failed
+MSMPrompt.Attribute:Attribute
+MSMPrompt.AssignedValues:\nAssigned Values:\n{0}
+MSMPrompt.Cancel:Cancel
+MSMPrompt.Current_Details:Details of existing Metadata Element
+MSMPrompt.Current_Element:Current Element
+MSMPrompt.Element_Name:Element Name
+MSMPrompt.Export_All_Values:All Values
+MSMPrompt.Export_Conditions:Using the condition:
+MSMPrompt.Export_File:Choose file to export to:
+MSMPrompt.Export_No_Values:No Values
+MSMPrompt.Export_Set:Select metadata set to export:
+MSMPrompt.Export_Subjects_Only:Subjects Only
+MSMPrompt.Export_Title:Export Metadata Set
+MSMPrompt.File_Export:Export
+MSMPrompt.File_Filter_Description:Metadata Sets (.mds)
+MSMPrompt.File_Import:Import
+MSMPrompt.GDMParser.Parsing:Parsing the file at:
+MSMPrompt.GDMParser.Title:Parsing Greenstone Metadata File
+MSMPrompt.Invalid_Name:The name given is of zero length.
+MSMPrompt.Merge:Merge
+MSMPrompt.Merge_MDE:Merging Metadata Elements
+MSMPrompt.Merge_MDS:Merging Action Required.
+MSMPrompt.Merge_Progress:Metadata Set Merging Progress.
+MSMPrompt.Name_Exists:Name already in use.
+MSMPrompt.New_Details:Details of new Metadata Element
+MSMPrompt.New_Element:Imported Element
+MSMPrompt.New_Name:New Name
+MSMPrompt.No_Details:No Details Available
+MSMPrompt.No_Element:No Current Element Exists
+MSMPrompt.Old_Name:Current Name
+MSMPrompt.OptionList:\nOption List: {0}\n{1}
+MSMPrompt.Progress:Percent Complete
+MSMPrompt.Remove_Failed:Cannot remove element "{0}" because:\n{1}
+MSMPrompt.Remove_Failed_Title:Remove Failed
+MSMPrompt.Rename:Rename
+MSMPrompt.Rename_Failed:Cannot rename "{0}" to "{1}" because:\n{2}
+MSMPrompt.Rename_Failed_Title:Rename Failed
+MSMPrompt.Replace:Replace
+MSMPrompt.Select_Element_Add:Add
+MSMPrompt.Select_Element_Element:Select Element:
+MSMPrompt.Select_Element_Ignore:Ignore
+MSMPrompt.Select_Element_Instructions:The metadata element {0} cannot be automatically imported into the collection. Either select a metadata set and press 'Add' to add the metadata to that set, or choose a set, then an element and press merge to import metadata from the original element to the selected one. 
+MSMPrompt.Select_Element_Merge:Merge
+MSMPrompt.Select_Element_Original:Original element name:
+MSMPrompt.Select_Element_Set:Select Set:
+MSMPrompt.Select_Element_Title:Importing Metadata
+MSMPrompt.Select_Set_Instructions:The metadata element {0} cannot be automatically imported into the collection, as it matches no existing metadata set (including any current default metadata set). Select a default metadata set to attempt to add this and subsequent metadata elements to:
+MSMPrompt.Select_Set_None:No Metadata Set
+MSMPrompt.Select_Set_Title:Importing Metadata
+MSMPrompt.Skip:Skip
+MSMPrompt.Structural:Metadata Set: {0}\nNamespace: {1}\nElement: {2}\nAttributes:\n{3}
+#********************************
+#
+#***** NEW NEW NEW NEW NEW *****
+Autofilter.AND:AND
+Autofilter.Ascending:Ascending
+Autofilter.Case_Sensitive:Match Case
+Autofilter.Clear:Clear Filter
+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.Set:Set Filter
+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
+Browser.Bookmarks:Bookmarks
+Browser.Reload:Reload
+CDM.FormatManager.Instructions: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, and come in two flavours: those that control the display of documents or parts of documents, and those that affect the lists and pages generated by classifiers. The former are often simple boolean switches, while the remainder and the later category require html code as an argument.\nTo add a format command first choose it from the 'feature' list. If it is a simple switch then a True/False option panel appears, with the state selected by clicking on the appropriate button. On the other hand if it requires further arguments a different panel containing the 'Affected Feature' and 'Edit Format Strings' controls become available. The component list is only used for classifier based formatting, and is used to specify a specific part of the lists returned by a classifier. The editing field is used to type in an html text argument. Note the preset variables list. To add a preset place the editing caret at the appropriate position in the html text, choose your desired variable from the list, and press insert. To remove a preset, delete or backspace it just as in regular text editing.\nFinally, once you are statisfied with your changes, press 'Add Format' to add it to the configuration file.\nRemoving a format command is accomplished by selecting it from the 'Assigned Format Commands' and clicking the 'Remove Format' button.
+CDM.IndexManager.Index_Exists:That index has already been assigned for this collection.
+CollectionManager.Creation_Failed_Already_Exists:Collection cannot be created because a collection with the filename '{0}' already exists.
+CollectionManager.Locked:<html>A lock file already exists for the collection '{0}'.<br>Do you wish to ignore this lock?<br>(Doing so may have dire conquences if you intend to save)</html>
+CollectionManager.Not_Col_File:'{0}' is not a Librarian Interface Collection File (.col)
+CollectionManager.Preview_Ready:The collection has been built and is ready for previewing.
+CollectionManager.Preview_Ready_Failed:An error has occured which will prevent the collection being previewed.
+CollectionManager.Preview_Ready_Title:Collection Preview State.
+FileActions.Cannot_Move:Files cannot be moved. Please check disk space and permissions.
+FileActions.Directories_Selected:{0} directories selected
+FileActions.Directory_Exists:<html>The directory<br>{0}<br>already exists within the collection. Files will be copied into it.</html>
+FileActions.Directory_Selected:1 directory selected
+FileActions.File_And_Directories_Selected:1 file and {0} directories selected
+FileActions.File_And_Directory_Selected:1 file and 1 directory selected
+FileActions.File_Exists:<html>{0} already exists in the destination directory. Overwrite it?</html>
+FileActions.File_Selected:1 file selected
+FileActions.Files_And_Directory_Selected:{0} files and 1 directory selected
+FileActions.Files_Selected:{0} files selected
+FileActions.Moved_Files:Moved {0} files to {1}.
+FileActions.Moving:Moving {0}.
+FileActions.No_To_All:No to All
+FileActions.Recalculating:Folder found. Recalculating total file size.
+FileActions.Yes_To_All:Yes to All
+FileAssociationDialog.Batch_File:Batch files
+FileAssociationDialog.Browse:Browse
+FileAssociationDialog.Browse_Title:Choose Application
+FileAssociationDialog.Command:Open using:
+FileAssociationDialog.Command_File:Command files
+FileAssociationDialog.Executable_File:Executable files
+FileAssociationDialog.Extension:For files ending:
+FileAssociationDialog.Title:Edit File Associations
+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:{43}The pattern you have entered for filter files is invalid.{35}Please try again using regular expression syntax and with{35}* for the wildcard character.{45}
+GShell.Extracted:Extracted metadata for {0}.
+GShell.Parsing_Metadata_Complete:Archived metadata extraction complete.
+GShell.Parsing_Metadata_Start:Extracting new metadata from archive files.
+MappingPrompt.File:Directory
+MappingPrompt.Map:Map Chosen Directory
+MappingPrompt.Name:Name
+MappingPrompt.Title:Set Directory Mapping
+MappingPrompt.Unmap:Unmap Directory
+MEM.Add:Add
+MEM.AddAttribute:Add Attribute
+MEM.AddSet:Add Set
+MEM.AddValue:Add Value
+MEM.Alias:Alias
+MEM.Attribute:Attribute
+MEM.Attributes:Attributes
+MEM.Cannot_Add_Elements_To_Greenstone_MDS:You cannot manually add elements to the Greenstone Metadata. If\nnecessary create a new set, then add you new element to it instead.
+MEM.Confirm_Removal:Are you sure you wish to remove this {0}?
+MEM.Confirm_Removal_Title:Confirm Removal
+MEM.Edit:Edit
+MEM.EditAttribute:Edit Attribute
+MEM.EditValue:Edit Value
+MEM.Element:Element
+MEM.Element_Details:Metadata Element Details
+MEM.File:File
+MEM.Ignore:IGNORE
+MEM.Language:Language
+MEM.Language_Code:Language
+MEM.Name:Name
+MEM.Namespace:Namespace
+MEM.Profiles:Importing Profiles
+MEM.Profile:Profile Values
+MEM.Profile_Details:Profile Details
+MEM.Remove:Remove
+MEM.Set:Set
+MEM.Set_Details:Metadata Set Details
+MEM.Source:From
+MEM.Subject:Subject
+MEM.Target:To
+MEM.Title:Edit Metadata Sets
+MEM.Value:Value
+MEM.Values:Values
+Menu.Edit_Copy:Copy
+Menu.Edit_Cut:Cut
+Menu.Edit_Paste:Paste
+Menu.Edit_Replace:Search and Replace
+Menu.Edit_Search:Search
+Menu.File_Associations:File Associations...
+Menu.File_Save_As:Save As
+Menu.Metadata_View:Assigned Metadata for the
+MetaAudit.Close:Close
+MetaEdit.Building:Building
+MetaEdit.Not_Applicable:Not Applicable
+MetaEdit.Ready:Ready
+MSM.No_Description:No description found.
+MSM.No_Name:No name found.
+NewCollectionPrompt.Description_Error:The description field must be filled out. Please correct.
+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.Email_Error:You have either failed to enter an email, or the email as typed is not a valid. Please correct.
+NewCollectionPrompt.Title_Error:The title field must be filled out. Please correct.
+Options.Automatic_Metadata_Extraction:Automatic Metadata Extraction
+SaveCollectionBox.File_Name:File Name:
+SaveCollectionBox.Files_Of_Type:Files of Type:
+SaveCollectionBox.Look_In:Look In:
+SaveProgressDialog.Saving:Saving {0}%
+SaveProgressDialog.Title:Saving Collection
+SearchAndReplace.Case_Sensitive:match case
+SearchAndReplace.Find_Button:Find
+SearchAndReplace.Find_Next_Button:Find Next
+SearchAndReplace.Found:Found match for {0}
+SearchAndReplace.Not_Found:No matches found for {0}
+SearchAndReplace.Options:Options
+SearchAndReplace.Redo:Redo
+SearchAndReplace.Regular_Expression:regular expression
+SearchAndReplace.Replace:Replace with
+SearchAndReplace.Replaced:Replaced this occurance of {0}
+SearchAndReplace.Replaced_All:Replaced a total of {1} occurances matching {0} 
+SearchAndReplace.Replace_Button:Replace
+SearchAndReplace.Replace_All_Button:Replace All
+SearchAndReplace.Reset:Restart
+SearchAndReplace.Search:Search for
+SearchAndReplace.Search_Elements:metadata elements
+SearchAndReplace.Search_In:Search in
+SearchAndReplace.Search_Records:file names
+SearchAndReplace.Search_Values:metadata values
+SearchAndReplace.Status:Status
+SearchAndReplace.Title:Search and Replace
+SearchAndReplace.Undo:Undo
+Source.Design:Design
+Source.Preview:Preview
Index: /tags/start/gli/classes/org/greenstone/gatherer/cdm/custom/CustomAZList.properties
===================================================================
--- /tags/start/gli/classes/org/greenstone/gatherer/cdm/custom/CustomAZList.properties	(revision 13666)
+++ /tags/start/gli/classes/org/greenstone/gatherer/cdm/custom/CustomAZList.properties	(revision 13666)
@@ -0,0 +1,34 @@
+A:A
+B:B
+Buttonname_JCheckBox:Button name
+C:C
+Cancel_JButton:Cancel
+D:D
+E:E
+F:F
+G:G
+H:H
+I:I
+J:J
+K:K
+L:L
+M:M
+Metadata_JLabel:Select metadata
+N:N
+Numbers:#
+O:O
+OK_JButton:Create Classifier
+P:P
+Q:Q
+R:R
+S:S
+Separations_JLabel:Allocate separations:
+Sort_JLabel:Sort by
+T:T
+Title_JDialog:Custom AZList Classifier Configuration
+U:U
+V:V
+W:W
+X:X
+Y:Y
+Z:Z
Index: /tags/start/gli/classes/xml/buildcol.xml
===================================================================
--- /tags/start/gli/classes/xml/buildcol.xml	(revision 13666)
+++ /tags/start/gli/classes/xml/buildcol.xml	(revision 13666)
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Info [
+  <!ELEMENT Info      (Name, Desc, Arguments)>
+  <!ELEMENT Arguments (Option*)>
+  <!ELEMENT Option    (Name, Desc, Type, Required, Default?, List?)>
+  <!ELEMENT Name      (#PCDATA)>
+  <!ELEMENT Desc      (#PCDATA)>
+  <!ELEMENT Type      (#PCDATA)>
+  <!ELEMENT Required  (#PCDATA)>
+  <!ELEMENT Default   (#PCDATA)>
+  <!ELEMENT List      (Value*)>
+  <!ELEMENT Value     (Name, Desc?)>
+]>
+
+<Info>
+  <Name>buildcol.pl</Name>
+  <Desc>PERL script used to build a greenstone collection from GML documents.</Desc>
+  <Arguments>
+    <Option>
+      <Name>archivedir</Name>
+      <Desc>Where the archives live</Desc>
+      <Type>string</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>verbosity</Name>
+      <Desc>0=none, 3=lots</Desc>
+      <Type>int</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>builddir</Name>
+      <Desc>Where to put the built indexes</Desc>
+      <Type>string</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>maxdocs</Name>
+      <Desc>Maximum number of documents to build</Desc>
+      <Type>int</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>debug</Name>
+      <Desc>Print output to STDOUT</Desc>
+      <Type>flag</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>mode</Name>
+      <Desc></Desc>
+      <Type>enum</Type>
+      <Required>no</Required>
+      <List>
+        <Value>
+          <Name>all</Name>
+        </Value>
+        <Value>
+          <Name>compress_text</Name>
+        </Value>
+        <Value>
+          <Name>build_index</Name>
+        </Value>
+        <Value>
+          <Name>infodb</Name>
+        </Value>
+      </List>
+    </Option>
+    <Option>
+      <Name>index</Name>
+      <Desc>Index to build (will build all in config file if not set)</Desc>
+      <Type>string</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>keepold</Name>
+      <Desc>will not destroy the current contents of the building directory</Desc>
+      <Type>flag</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>no_text</Name>
+      <Desc>Don't store compressed text. This option is useful for minimizing the size of the built indexes if you intend always to display the original documents at run time (i.e. you won't be able to retrieve the compressed text version)</Desc>
+      <Type>flag</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>allclassifications</Name>
+      <Desc>Don't remove empty classifications</Desc>
+      <Type>flag</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>create_images</Name>
+      <Desc>Attempt to create default images for new collection. This relies on the Gimp being installed along with relevant perl modules to allow scripting from perl</Desc>
+      <Type>flag</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>collectdir</Name>
+      <Desc>Collection directory (defaults to /research/jmt12/gsdl/collect)</Desc>
+      <Type>string</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>out</Name>
+      <Desc>Filename or handle to print output status to. The default is STDERR</Desc>
+      <Type>string</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>buildtype</Name>
+      <Desc>This will override the config file setting. (default is mg)</Desc>
+      <Type>enum</Type>
+      <Required>no</Required>
+      <List>
+        <Value>
+          <Name>mg</Name>
+        </Value>
+        <Value>
+          <Name>mgpp</Name>
+        </Value>
+      </List>
+    </Option>
+    <Option>
+      <Name>no_strip_html</Name>
+      <Desc>Do not strip the html tags from the indexed text (only used for mgpp collections)</Desc>
+      <Type>flag</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>faillog</Name>
+      <Desc>Fail log filename. This log receives the filenames of any files which fail to be processed (defaults. to &lt;collectdir&gt;/colname/etc/fail.log)</Desc>
+      <Type>string</Type>
+      <Required>no</Required>
+    </Option>
+  </Arguments>
+</Info>
Index: /tags/start/gli/classes/xml/collect_cfg.xml
===================================================================
--- /tags/start/gli/classes/xml/collect_cfg.xml	(revision 13666)
+++ /tags/start/gli/classes/xml/collect_cfg.xml	(revision 13666)
@@ -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/start/gli/classes/xml/config.xml
===================================================================
--- /tags/start/gli/classes/xml/config.xml	(revision 13666)
+++ /tags/start/gli/classes/xml/config.xml	(revision 13666)
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE Configuration [
+  <!ELEMENT Configuration  (GathererConfig, Other)>
+  <!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)>
+]>
+
+<Configuration>
+  <GathererConfig>
+    <!-- ***** General Options: apply globally to the Gatherers execution. ***** -->
+    <!-- Automatically extract metadata from archive files after import. default = [true] -->
+    <Argument name="general.auto">true</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.locale">en_NZ</Argument>
+    <Argument name="general.home_page">http://www.greenstone.org/</Argument>
+    <Argument name="general.open_collection"></Argument>
+    <Argument name="general.proxy_host"></Argument>
+    <Argument name="general.proxy_port"></Argument>
+    <!-- The skins file to be used. The user can disable skins to improve processor performance. [lib/greenaqua/greenaqua.xml] -->
+    <Argument name="general.skin">lib/greenaqua/greenaqua.xml</Argument>
+    <Argument name="general.size">800, 600</Argument>
+    <Argument name="general.tooltip_font">Courier, PLAIN, 12</Argument>
+    <!-- Do we expect to connect to the internet via a proxy server. [false] -->
+    <Argument name="general.use_proxy">false</Argument>
+
+    <!-- Colouring -->
+    <Argument name="coloring.button_background">255, 255, 255</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.error_background">250, 180, 180</Argument>
+    <Argument name="coloring.error_foreground">255, 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>
+
+	 <!-- Messages -->
+	 <!-- Whether messages are displayed for certain sources and levels. Very out of date. -->
+	 <Argument name="messages.level_error">true</Argument>
+	 <Argument name="messages.level_event">true</Argument>
+	 <Argument name="messages.level_information">true</Argument>
+	 <Argument name="messages.level_main">true</Argument>
+	 <Argument name="messages.source_browser">true</Argument>
+	 <Argument name="messages.source_build">true</Argument>
+	 <Argument name="messages.source_general">true</Argument>
+	 <Argument name="messages.source_metaedit">true</Argument>
+	 <Argument name="messages.source_mirroring">true</Argument>
+	 <Argument name="messages.source_session">true</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. -->
+	 <!-- Do we show a warning message when a user attempts to add folder level metadata. [true] -->
+    <Argument name="warning.DirectoryLevelMetadataPrompt">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.NoMetadataSetsSelected">true</Argument>
+
+    <!-- Workflow -->
+    <!-- Disabling a view here will cause it to be hidden from the Gatherer display. -->
+	 <Argument name="workflow.browse">false</Argument>
+    <Argument name="workflow.create">true</Argument>
+    <Argument name="workflow.design">true</Argument>
+    <Argument name="workflow.enrich">true</Argument>
+    <Argument name="workflow.export">false</Argument>
+    <Argument name="workflow.gather">true</Argument>
+    <Argument name="workflow.mirror">false</Argument>
+    <Argument name="workflow.preview">true</Argument>
+  </GathererConfig>
+  <Other/>
+</Configuration>
Index: /tags/start/gli/classes/xml/gatherer.lck
===================================================================
--- /tags/start/gli/classes/xml/gatherer.lck	(revision 13666)
+++ /tags/start/gli/classes/xml/gatherer.lck	(revision 13666)
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="ASCII" ?>
+
+<LockFile>
+  <User></User>
+  <Machine></Machine>
+  <Date></Date>
+</LockFile>
Index: /tags/start/gli/classes/xml/import.xml
===================================================================
--- /tags/start/gli/classes/xml/import.xml	(revision 13666)
+++ /tags/start/gli/classes/xml/import.xml	(revision 13666)
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Info [
+  <!ELEMENT Info      (Name, Desc, Arguments)>
+  <!ELEMENT Arguments (Option*)>
+  <!ELEMENT Option    (Name, Desc, Type, Required, Default?, List?)>
+  <!ELEMENT Name      (#PCDATA)>
+  <!ELEMENT Desc      (#PCDATA)>
+  <!ELEMENT Type      (#PCDATA)>
+  <!ELEMENT Required  (#PCDATA)>
+  <!ELEMENT Default   (#PCDATA)>
+  <!ELEMENT List      (Value*)>
+  <!ELEMENT Value     (Name, Desc?)>
+]>
+
+<Info>
+  <Name>import.pl</Name>
+  <Desc>PERL script used to import files into a GML format ready for building.</Desc>
+  <Arguments>
+    <Option>
+      <Name>archivedir</Name>
+      <Desc>Where the converted material ends up</Desc>
+      <Type>string</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>collectdir</Name>
+      <Desc>Collection directory (defaults to /research/jmt12/gsdl/collect)</Desc>
+      <Type>string</Type>
+      <Required>no</Required>
+      <Default>/research/jmt12/gsdl/collect</Default>
+    </Option>
+    <Option>
+      <Name>debug</Name>
+      <Desc>Print imported text to STDOUT</Desc>
+      <Type>flag</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>faillog</Name>
+      <Desc>Fail log filename. This log receives the filenames of any files which fail to be processed (defaults to &lt;collectdir&gt;/colname/etc/fail.log)</Desc>
+      <Type>string</Type>
+      <Required>no</Required>
+      <Default>&lt;collectdir&gt;/colname/etc/fail.log</Default>
+    </Option>
+    <Option>
+      <Name>groupsize</Name>
+      <Desc>Number of import documents to group into one XML file</Desc>
+      <Type>int</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>gzip</Name>
+      <Desc>Use gzip to compress resulting xml documents (don't forget to include ZIPPlug in your plugin list when building from compressed documents)</Desc>
+      <Type>flag</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>importdir</Name>
+      <Desc>Where the original material lives</Desc>
+      <Type>string</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>keepold</Name>
+      <Desc>Will not destroy the current contents of the archives directory (the default)</Desc>
+      <Type>flag</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>maxdocs</Name>
+      <Desc>Maximum number of documents to import</Desc>
+      <Type>int</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>OIDtype</Name>
+      <Desc>The method to use when generating unique identifiers for each document. "hash" (the default) hashes the contents of the file and so will be the same every time the collection is imported. "incremental" is a simple document count and so will be significantly faster than "hash". It is not guaranteed to always assign the same identifier to a given document though and does not allow further documents to be added to existing xml archives</Desc>
+      <Type>enum</Type>
+      <Required>no</Required>
+      <List>
+        <Value>
+          <Name>hash</Name>
+        </Value>
+        <Value>
+          <Name>incremental</Name>
+        </Value>
+      </List>
+    </Option>
+    <Option>
+      <Name>out</Name>
+      <Desc>Filename or handle to print output status to. The default is STDERR</Desc>
+      <Type>string</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>removeold</Name>
+      <Desc>Will remove the old contents of the archives directory -- use with care</Desc>
+      <Type>flag</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>sortmeta</Name>
+      <Desc>Sort documents alphabetically by metadata for building. This will be disabled if groupsize > 1</Desc>
+      <Type>string</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>statsfile</Name>
+      <Desc>Filename or handle to print import statistics to. The default is STDERR</Desc>
+      <Type>string</Type>
+      <Required>no</Required>
+    </Option>
+    <Option>
+      <Name>verbosity</Name>
+      <Desc>A number between zero and three that controls how much information about the process is printed to the standard error stream; 0 gives a little, 3 gives lots</Desc>
+      <Type>int</Type>
+      <Required>no</Required>
+    </Option>
+  </Arguments>
+</Info>
Index: /tags/start/gli/classes/xml/metadata.xml
===================================================================
--- /tags/start/gli/classes/xml/metadata.xml	(revision 13666)
+++ /tags/start/gli/classes/xml/metadata.xml	(revision 13666)
@@ -0,0 +1,3 @@
+<?xml version="1.0"  encoding="UTF-8" standalone="no"?>
+<!DOCTYPE GreenstoneDirectoryMetadata SYSTEM "http://greenstone.org/dtd/GreenstoneDirectoryMetadata/1.0/GreenstoneDirectoryMetadata.dtd">
+<GreenstoneDirectoryMetadata/>
Index: /tags/start/gli/classes/xml/protemp.xml
===================================================================
--- /tags/start/gli/classes/xml/protemp.xml	(revision 13666)
+++ /tags/start/gli/classes/xml/protemp.xml	(revision 13666)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Profiles [
+			 <!ELEMENT Profiles (Source*)>
+			 <!ELEMENT Collection (Map*|Ignore*)>
+			 <!ATTLIST Collection
+						  source CDATA #REQUIRED>
+			 <!ELEMENT Map (#PCDATA)>
+			 <!ATTLIST Map
+						  source CDATA #REQUIRED
+						  target CDATA "">
+			 <!ELEMENT Ignore (#PCDATA)>
+			 <!ATTLIST Ignore
+			           source CDATA #REQUIRED>
+]>
+
+<Profiles>
+</Profiles>
Index: /tags/start/gli/classes/xml/template.col
===================================================================
--- /tags/start/gli/classes/xml/template.col	(revision 13666)
+++ /tags/start/gli/classes/xml/template.col	(revision 13666)
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE GathererCollection [
+  <!ELEMENT GathererCollection (Argument*, GathererConfig, BuildConfig, DirectoryMappings)>
+  <!ELEMENT GathererConfig    (Arguments*)>
+  <!ELEMENT BuildConfig       (Build, Import)>
+  <!ELEMENT Build             (Arguments*)>
+  <!ELEMENT Import            (Arguments*)>
+  <!ELEMENT Argument          (#PCDATA)>
+  <!ATTLIST Argument
+            name              CDATA #REQUIRED
+				enabled           CDATA "true">
+  <!ELEMENT DirectoryMappings (Mapping*)>
+  <!ELEMENT Mapping           (#PCDATA)>
+  <!ATTLIST Mapping 
+            name              CDATA #REQUIRED
+				file              CDATA #REQUIRED>
+]>
+
+<GathererCollection>
+  <Argument name="built">false</Argument>
+  <Argument name="imported">false</Argument>
+  <GathererConfig/>
+  <BuildConfig>
+    <Build/>
+	 <Import/>
+  </BuildConfig>
+  <DirectoryMappings/>
+</GathererCollection>
+
+
+
Index: /tags/start/gli/classes/xml/template.mds
===================================================================
--- /tags/start/gli/classes/xml/template.mds	(revision 13666)
+++ /tags/start/gli/classes/xml/template.mds	(revision 13666)
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE MetadataSet [
+
+  <!-- The outer tag of any metadata set. Contains some number of elements.             -->
+  <!-- @param creator     The name of the entity resposibly for this set.               -->
+  <!-- @param contact     A contact address for the creator.                            -->
+  <!-- @param description A description of this metadata set.                           -->
+  <!-- @param family      The namespace of this metadata set.                           -->
+  <!-- @param lastchanged The full date, user name and machine name of the last editor. --> 
+  <!--   uses the form:                                                                 -->
+  <!--   Day Mon(th) dd hh:mm:ss yyyy '-' <username> on <machine>                       -->
+  <!-- @param name        The name of this metadata set.                                -->
+  <!-- @param namespace   The abbreviated namespace of this metadata set.               -->
+  <!ELEMENT MetadataSet (Element+)>
+  <!ATTLIST MetadataSet
+				contact     CDATA #REQUIRED
+				creator     CDATA #REQUIRED
+				description CDATA #REQUIRED
+            family      CDATA #REQUIRED
+				lastchanged CDATA #REQUIRED
+            name        CDATA #REQUIRED
+				namespace   CDATA #REQUIRED>
+
+  <!-- An element in the metadata set. -->
+  <!ELEMENT Element (Attribute*,OptionList?,AssignedValues?)>
+  <!ATTLIST Element
+            name       CDATA #REQUIRED
+				occurances CDATA "0">
+
+  <!-- Each element has several attribute children. -->
+  <!ELEMENT Attribute (#PCDATA)>
+  <!ATTLIST Attribute
+            name CDATA #REQUIRED>
+
+  <!-- For listing predefined values for this element. -->
+  <!ELEMENT OptionList (Value+)>
+  <!ATTLIST OptionList
+            restricted (true|false) "false">
+
+  <!-- Each element also contains a tree of values that have been assigned to it. This may include a multilayer nested subject hierachy. -->
+  <!ELEMENT AssignedValues (Subject+)>
+
+  <!-- A value. -->
+  <!ELEMENT Subject (Value|Alias?|Subject*)>
+  <!ELEMENT Value (#PCDATA)>
+  <!ATTLIST Value
+            occurances CDATA "1">
+  <!ELEMENT Alias (#PCDATA)>
+]>
+
+<MetadataSet>
+</MetadataSet>
Index: /tags/start/gli/classes/xml/template.mdv
===================================================================
--- /tags/start/gli/classes/xml/template.mdv	(revision 13666)
+++ /tags/start/gli/classes/xml/template.mdv	(revision 13666)
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE AssignedValues [
+
+  <!-- A tree of values that have been assigned to a metadata element. This may include a multilayer nested subject hierachy. -->
+  <!ELEMENT AssignedValues (Subject+)>
+  <!ATTLIST AssignedValues
+				element CDATA #REQUIRED>
+
+  <!-- A subject. -->
+  <!ELEMENT Subject (Value|Alias?|Subject*)>
+
+  <!-- A value. -->
+  <!ELEMENT Value (#PCDATA)>
+  <!ATTLIST Value
+            occurances CDATA "1">
+
+  <!-- An alias. -->
+  <!ELEMENT Alias (#PCDATA)>
+]>
+
+<AssignedValues element = "">
+</AssignedValues>
Index: /tags/start/gli/classes/xml/valuetree.xml
===================================================================
--- /tags/start/gli/classes/xml/valuetree.xml	(revision 13666)
+++ /tags/start/gli/classes/xml/valuetree.xml	(revision 13666)
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE AssignedValues [
+
+  <!-- A tree of values that have been assigned to a metadata element. This may include a multilayer nested subject hierachy. -->
+  <!ELEMENT AssignedValues (Subject+)>
+  <!ATTLIST AssignedValues
+				element CDATA #REQUIRED>
+
+  <!-- A subject. -->
+  <!ELEMENT Subject (Value|Alias?|Subject*)>
+
+  <!-- A value. -->
+  <!ELEMENT Value (#PCDATA)>
+  <!ATTLIST Value
+            occurances CDATA "1">
+
+  <!-- An alias. -->
+  <!ELEMENT Alias (#PCDATA)>
+]>
+
+<AssignedValues element = "">
+</AssignedValues>
Index: /tags/start/gli/classes/xml/workflows.xml
===================================================================
--- /tags/start/gli/classes/xml/workflows.xml	(revision 13666)
+++ /tags/start/gli/classes/xml/workflows.xml	(revision 13666)
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE PredefinedWorkflows [
+  <!ELEMENT PredefinedWorkflows (Workflow*)>
+  <!ELEMENT Workflow            (#PCDATA)>
+  <!ATTLIST Workflow
+            browse              CDATA "true"
+				mirror				  CDATA "true"
+				import				  CDATA "true"
+				gather				  CDATA "true"
+				enrich				  CDATA "true"
+				design				  CDATA "true"
+				export				  CDATA "true"
+				create				  CDATA "true"
+				preview				  CDATA "true">
+]>
+
+<PredefinedWorkflows>
+  <Workflow>All panels</Workflow>
+  <Workflow browse="false" mirror="false" import="false" export="false">Local source collection building.</Workflow>
+  <Workflow import="false" export="false">Web based source collection building.</Workflow>
+  <Workflow import="false" design="false" create="false" preview="false">Field data gathering.</Workflow>
+</PredefinedWorkflows>
Index: /tags/start/gli/help/1-0.htm
===================================================================
--- /tags/start/gli/help/1-0.htm	(revision 13666)
+++ /tags/start/gli/help/1-0.htm	(revision 13666)
@@ -0,0 +1,70 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+1.0 Introduction
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+The Greenstone Librarian Interface is a tool for collecting, expanding and building digital libraries. It gives you access to the Greenstone Digital Library Software's functionality from an easy-to-use 'point and click' interface. This tutorial walks you through the functionality of the Librarian Interface.
+</p>
+<p style="text-align:justify">
+The initial screen is titled "The Librarian Interface: No Collection". The software directs you through the process of creating a collection in an ordered way. This is why many components on the initial screen are greyed out.
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/1-1.htm
===================================================================
--- /tags/start/gli/help/1-1.htm	(revision 13666)
+++ /tags/start/gli/help/1-1.htm	(revision 13666)
@@ -0,0 +1,305 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+1.1 Of Mice and Menus
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+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 the next section.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Basic concepts
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td>
+                  &nbsp;
+                </td>
+                <td>
+                  <font face="Verdana" size="4">
+Controls
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td>
+                  &nbsp;
+                </td>
+                <td>
+                  <font face="Verdana" size="4">
+Keyboard
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td>
+                  &nbsp;
+                </td>
+                <td>
+                  <font face="Verdana" size="4">
+Mouse actions
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Menus
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td>
+                  &nbsp;
+                </td>
+                <td>
+                  <font face="Verdana" size="4">
+Opening menus
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td>
+                  &nbsp;
+                </td>
+                <td>
+                  <font face="Verdana" size="4">
+Selecting menu items
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td>
+                  &nbsp;
+                </td>
+                <td>
+                  <font face="Verdana" size="4">
+Closing menus
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Exiting the program
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#AI">Advanced instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Quick keys
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+The Librarian Interface behaves like other Microsoft Windows programs and draws upon ordinary knowledge of Windows. There are several basic concepts which you must understand before you can proceed.
+</p>
+<p style="text-align:justify">
+We call any part of the screen that you can interact with a 'control'. Examples include buttons you can press and text fields into which you can type values. At any time there is one control, called the 'focus', which you can interact with simply by typing on the keyboard. When in focus a button gains a dotted border and a text field has a flashing line (a 'caret') that shows the position in the text. Several controls allow you to select them or parts of them as discussed later. In all cases the control or its contents are highlighted in dark blue. Finally, controls may be enabled or disabled. Enabled controls can be interacted with by clicking or typing. Disabled ones cannot be interacted with and are greyed out.
+</p>
+<p style="text-align:justify">
+One method of interacting with a control is by using the keyboard to type into text fields and other text based controls. The keyboard can be used with buttons too -- for example, the [Tab] key cycles through the controls visible on the screen. This help text tells you what keys are available. We put the key's name in square brackets, and use a plus sign to show when other keys must be pressed at the same time. For example, a common command for any text field is [Ctrl] + [C], which copies the currently selected text.
+</p>
+<p style="text-align:justify">
+You also interact with the Librarian Interface using the mouse. As you move it, the mouse pointer follows along. You interact with the control under the mouse pointer by clicking on it. There are several different types of click:
+</p>
+<p style="text-align:justify">
+Single left mouse-button click. This is what we normally use,
+</p>
+<p style="text-align:justify">
+Single right mouse-button click. This is used to open context sensitive menus and is always explicitly noted within these help pages,
+</p>
+<p style="text-align:justify">
+Double click. This involves clicking the mouse button twice in quick succession. (It can take practice to get right. You can practice by opening the Microsoft Windows Start Menu, choosing Settings->Control Panel, and opening the 'mouse' icon in this folder. The window that appears will not only let you practice double clicking on the test area at the bottom right of the window, but will let you slow the required clicking down using the double-click speed slider),
+</p>
+<p style="text-align:justify">
+Drag'n'drop. 'Dragging' is when you press a mouse button and move the mouse before releasing it; 'dropping' is when you finally release the button. If you begin dragging over certain controls, such as icons on the Windows desktop, the control attaches to the mouse pointer and you can move it elsewhere on the screen and drop it there. However, you can only drop into certain places, called 'drop targets', and they are indicated by highlighting. If you drop something where it can't be dropped it returns immediately to its original position.
+</p>
+<p style="text-align:justify">
+To use the Librarian Interface you also need to be able to use menus. The 'menu bar' is at the top of the program's window just below the blue title bar. This contains several drop-down submenus, accessed by clicking their label.
+</p>
+<p style="text-align:justify">
+Move the mouse over the label File, and it changes appearance to look like a button. Click once on the label/button File, and the file menu 'drops down' beneath where you clicked.
+</p>
+<p style="text-align:justify">
+You can then move to an item, indicated by blue highlighting, and click once on it. This will execute the corresponding command, or perhaps open a further submenu which appears beside the current menu.
+</p>
+<p style="text-align:justify">
+To close the menu click anywhere else on the screen (not the submenu), or click again on the File label. These menu actions are the same for all menus within Librarian Interface.
+</p>
+<p style="text-align:justify">
+When you have finished working, you can exit the Librarian Interface program at any time either by choosing the Exit item from the File menu, or by clicking the little 'x' button just to the right of the program title (this buttons is called 'Destroy'). If you are working on a collection you will be prompted to save your collection before the program terminates.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="AI">Advanced Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+In each menu and submenu label one letter is underlined. To quickly access any menu within the menu bar, hold down the [ALT] key and then press the underlined letter corresponding to what you want to do. For example, to access the [F]ile menu press [ALT] + [F]. To choose items from a submenu, press the key matching the indicated letter. Thus once in the File menu, press [S] to [S]ave a collection.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/1-2.htm
===================================================================
--- /tags/start/gli/help/1-2.htm	(revision 13666)
+++ /tags/start/gli/help/1-2.htm	(revision 13666)
@@ -0,0 +1,154 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+1.2 How to Avoid Reading This Document
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+You don't have to read this help text all the way through! You just have to know how to get help when you need it.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Context sensitive help
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Tool tips
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Other documents
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+One of the menu items is [H]elp. This provides context sensitive help by highlighting what it thinks is the most appropriate help item with a little book icon (the same as appears next to the help menu item).
+</p>
+<p style="text-align:justify">
+Some controls have tool tips associated with them. If you leave you mouse pointer over them, for a second or two, the tip will appear detailing what the control does.
+</p>
+<p style="text-align:justify">
+Before using the Librarian Interface, you should be generally familiar with Greenstone. The documentation explains some of the terms and actions available within the Librarian Interface.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/10-0.htm
===================================================================
--- /tags/start/gli/help/10-0.htm	(revision 13666)
+++ /tags/start/gli/help/10-0.htm	(revision 13666)
@@ -0,0 +1,67 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+10.0 Miscellaneous
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This chapter describes features of the Librarian Interface which are not associated with any particular view.
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/10-1.htm
===================================================================
--- /tags/start/gli/help/10-1.htm	(revision 13666)
+++ /tags/start/gli/help/10-1.htm	(revision 13666)
@@ -0,0 +1,200 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+10.1 Search And Replace
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section explains the search and replace functionality of the Librarian Interface.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Search and replace
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#AI">Advanced instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Match case
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Regular expressions
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Search space
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+It becomes tedious to correct a spelling mistake in an metadata value one occurrence at time.  Consequently the Librarian Interface includes a search and replace feature that allows text to be modified over the entire breadth of a collection. To search, click on the menu item [E]dit -> [S]earch, and to replace choose [E]dit- >Search and [R]eplace. Both prompts are essentially the same, but the former has the replace part disabled.
+</p>
+<p style="text-align:justify">
+Type the term that you seek and press [F]ind to begin the search. The first matching text will be shown, in the appropriate view, using highlighting. Furthermore the [F]ind button is disabled and two new buttons become active.  Find [N]ext carries on searching from the last match found, while re[S]tart causes the search position to be reset to the start so that pressing the re-enabled find button find the first match again.
+</p>
+<p style="text-align:justify">
+If a replace prompt was chosen, you may type a text string to be substituted for any matches to the search term. When you enter a value in the 'Replace with' field, two new buttons become active. [R]eplace replaces the currently located text with the replacement text. If no text has yet been found, a find operation is run first.  Replace [A]ll replaces all occurrences of the search term within the search space. Once you have performed a replace operation, the [U]ndo button becomes active. Clicking this will undo the most recent operation (or operations if you chose replace all). The Re[D]o button redoes something you've just undone. During any of these steps, Re[S]tart works exactly as described above (although the first match returned may not be the same if you have substituted it with replacement text).
+</p>
+<p style="text-align:justify">
+At any time, in either prompt you may click the [C]lose button to hide the dialog prompt.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="AI">Advanced Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+Below the text fields are several checkboxes that allow you to further customize the search. By default all searches are case insensitive, but you can change this by checking the match case box.
+</p>
+<p style="text-align:justify">
+You can also use regular expressions within the search and replace text fields. Most standard regular expression functionality is supported, including capture groups. For instance you could choose to search for 'Re\(.*\)gees'.  This will seek all the 'shortest' text fragments that match 're', followed by any number of characters, followed by 'gees' -- matching 'Refugees', for example. The 'any number of characters' is marked as a capture group (in this case capture group 1) by escaped parentheses. In the replace field you can type '\1\1', which if run would replace 'Refugees' with 'fufu'.
+</p>
+<p style="text-align:justify">
+You can control just what gets searched by checking and unchecking the boxes called metadata elements, filenames and metadata values. Only those that are checked will be searched during a find operation.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/10-2.htm
===================================================================
--- /tags/start/gli/help/10-2.htm	(revision 13666)
+++ /tags/start/gli/help/10-2.htm	(revision 13666)
@@ -0,0 +1,154 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+10.2 Preferences
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section explains the preferences dialog, accessed by opening [F]ile->[P]references.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Workflow
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Connection
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Warnings
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+One of the more powerful features of the Librarian Interface is the ability to model different workflows, or progressions through the various view tabs. For instance a simple user might prefer the Librarian Interface without any of the web browsing or mirroring capability, while a user 'in the field' might prefer a Librarian Interface which does everything up to the create step but instead has an export ability to send thier collection to a central 'repository'. Use the 'Workflow' tab of the preferences pane to customise what views are available. Check the box next to the view you wish to be available, otherwise leave it unchecked to cause that view to be disabled. You can use the combobox at the bottom of this page to select predetermined configurations of settings. Once you are done, closing the preferences dialog will establish these workflow settings. Note that these settings are stored with the collection, and not in the Librarian Interface configuration file. In fact the workflow settings in the configuration file are used to hide the view tabs in the Librarian Interface, rather than just disable them (useful for Librarian Interface administrators).
+</p>
+<p style="text-align:justify">
+If you wish to connect to the interent, such as when Browsing or Mirroring your files (see 3.0 and 4.0 for details), but you must connect via a proxy, then the 'Connection' tab of the preferences dialog is used to set the proxy information. Check the box to enabled proxy connection then fill in the details of the proxy host address and port number. When you close the preferences dialog the proxy connection will be established.
+</p>
+<p style="text-align:justify">
+During the course of a session you may be provided with one or more warning dialogs. These dialogs inform you of possible unforeseen consequences of an action (such as metadata that is added to a folder automatically being persistantly inherited by all the child files and folders of that folder). If you wish you may choose to disable these dialogs by checking the 'Do not show this warning again' box. However if you later decide to re-enable a warning message then the third tab of the preferences dialog, 'Warnings', will allow you to do this. Simply check the box next to the warning message you wish to show again, selected from the list of dialogs.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/11-0.htm
===================================================================
--- /tags/start/gli/help/11-0.htm	(revision 13666)
+++ /tags/start/gli/help/11-0.htm	(revision 13666)
@@ -0,0 +1,35 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+11.0 Metadata Set and Profile Editing
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This chapter explains how to edit the various metadata sets used by the Librarian Interface, and is pertinent to anyone who wishes to remove a value from the previous values tree. While it is simple to remove a certain metadata value from a record or records, the value itself still appears in the the value tree. This is a feature, not a bug. Instead the way to remove previously assigned values, or indeed any part of the metadata set including its elements, is via the metadata set editor, available under the Metadata menu. 
+</p>
+<p style="text-align:justify">
+Also this is a tool used to alter the import profiles, the instructions used to map metadata from files imported into the collection onto existing metadata sets.
+</p>
+
+      </font>
+    </td>
+  </tr>
Index: /tags/start/gli/help/11-1.htm
===================================================================
--- /tags/start/gli/help/11-1.htm	(revision 13666)
+++ /tags/start/gli/help/11-1.htm	(revision 13666)
@@ -0,0 +1,160 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+11.1 Edit Metadata Sets
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section describes the various parts of metadata set and profile editing.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Editing sets
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Editing elements
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Editing profiles
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+The 'Edit Metadata Sets' dialog, which is co-incidently modal, is once again split into tree areas. The left consists of a tree containing all of the various parts of the metadata sets or profiles which can be edited. The right instead shows the details of the currently selected part of the tree, in one or more tables. The bottom is layed out with an array of buttons for adding, editing or removing the various parts, while along-side them is the button to close this prompt. Many of the buttons are grayed out initially, but will change depending on your selections in the tree and tables. Now we look at the slightly differing tasks of editing sets, elements and profiles. 
+</p>
+<p style="text-align:justify">
+There are two ways in which you can modify the metadata sets associated with this collection. Firstly you can add a new set or remove an exiting set. Adding can be done at any time, and when you click the button you will be presented with another prompt for garnering details about the new set. The namespace is a short but unique indentifer for your new set (for the namespace for the Development Library Subset is 'dls', while the Dublin Core is 'dc'). Clicking OK in this prompt will create the new set, while Cancel will dispose of the dialog without altering your collection. Removing a set can only be done when a set is selected from the tree. A click on the set Remove button will causes a confirmation prompt to appear, and confirming it will <strong>permanently</strong> remove the set, and all metadata associated with it. The second way in which you can edit a set is by selecting a set, then altering its attributes. The general method for altering attributes is used int several parts of the editor. Add attribute becomes active as soon as a set is selected, and clicking it will provide a dialog for gathering attribute details such as name, language and value. Note that the combobox for the name and value will be empty and each set is considered unique. Pressing OK here will add the new attribute, while Cancel removes the prompt without altering your collection. Edit attribute becomes active when a certain attribute from the table shown when a set is selected. The edit prompt is exactly the same as the add one, except the previous value should be filled out. Edit as necessary and click OK to update. Remove also becomes active, and if clicked and the subsequent confirmation made, the selected attribute is removed.
+</p>
+<p style="text-align:justify">
+For metadata elements there are three more editing tasks you can undertake. You could choose to add or remove elements. Adding a element can be done whenever a set is selected, and is accomplished by clicking add on the element row of controls. A prompt will appear asking for the elements name, and once filled out and submitted with the OK button, a new element will be created in the selected set. To <strong>permanently</strong> remove an element, select it from the tree, click the remove button, an accept the confirmation dialog. Note that removing an element will remove all metadata associated with that element. The second subtask, attribute editing, has exactly the same proceedure as for sets explained above. The biggest difference is the the comboboxes in the add and edit prompts should contain several values, as noticed from other elements within the same set. Thus is you have assigned comment to several other elements, other than this one, in the set, then the name 'comment' plus the various values for comment should be available via the comboboxes on the prompt. A feature specific to element editing is the ability to alter the value tree. The value tree contains all the past value assigned for the element selected. You can add a new value whenever an element is selected. Press the appropriate add button, then from the choose the parent subject (if any), enter the value and optionally the alias. Finally click OK to create the node. Editing values is similar except you must first have selected an entry from the value tree. The prompt shown is the same as form adding, except the various fields should already be filled out. Note that changing the parent subject will cause the value to be moved to that subject. Press OK to commit the changes, Cancel to revert. And if a value in the tree is selected the remove button should also become active, and if clicked and the confirmation made, the value will be removed from the tree. Take note, that this <strong>doesn't</strong> remove all metadata referring to this value. In fact this value will be restored, next time you save, if it is still in use.
+</p>
+<p style="text-align:justify">
+If you expand the 'Importing Profiles' folder, which in and of itself has no editing ability, you will be presented with the source locations that have importing profiles associated with them. Not all files you include in your collection will have previous metadata, and not all those that do will require special instructions to map onto existing metadata (especially if they are built from the same metadata set). Once the 'Importing Profiles' folder is selected you may add new 'file' sources by clicking the add button next to the 'file' label. The prompt displayed is rather basic requiring you only to fill in a file name (the Librarian Interface doesn't even check that its legal, unfortunately), before pressing OK to add the file source. If you select a file you can choose to delete it using the same method for all other removals. Also once a file is selected its 'attributes' table appears. In this case the attributes are actually the mappings from the name of an element from the source file location to the name of an element within the collection. The add a new mapping, select a source file, then click the add attribute button. The standard add/edit attribute dialog will appear, except the language field will be disabled and the values combobox will contain all of the elements currently available in the collection. OK will add the new profile while Cancel does exactly that. Editing a napping is exactly as above, as is deletion.
+</p>
+<p style="text-align:justify">
+Once you are happy with the changes click Close to close the dialog.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/2-0.htm
===================================================================
--- /tags/start/gli/help/2-0.htm	(revision 13666)
+++ /tags/start/gli/help/2-0.htm	(revision 13666)
@@ -0,0 +1,67 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+2.0 Starting Off
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This chapter covers how to create, save and load a collection session.
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/2-1.htm
===================================================================
--- /tags/start/gli/help/2-1.htm	(revision 13666)
+++ /tags/start/gli/help/2-1.htm	(revision 13666)
@@ -0,0 +1,317 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+2.1 Creating a New Collection
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section describes how to create a new collection.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The new collection prompt
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The collection title
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The collection name
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The creator's email
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Default metadata sets
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Collection description
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Creating the new collection
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Cancelling the new collection
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#AI">Advanced instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Quick keys
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Current collection
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#QA">Problems and solutions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+"I want to change the values I entered for title/email/description. How do I do that?"
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+To create a new collection, open the [F]ile menu and choose the menu item [N]ew. A new form, the New Collection Prompt, appears. Several fields need to be filled out. Click in any field (the white area) to move the cursor there, or press [Tab] to cycle through the fields (and buttons). You can change any value you enter later, in the 'Design' view.
+</p>
+<p style="text-align:justify">
+The collection title is the text that will be displayed at the top of your collection's homepage, and can be any length. You should not use the quotation character (") in this (or any other) text field; if you do the Librarian Interface will remove it.
+</p>
+<p style="text-align:justify">
+The collection name is the actual file name of your collection, under which it will be saved to disk. The Librarian Interface uses this name in several places. It is limited to seven characters in length. Also note that it must be unique, and that if a collection with this name already exists the new collection action will fail with an error message. If this happens you will be returned to the new collection prompt and the name field will be highlit to indicate the file clash.
+</p>
+<p style="text-align:justify">
+The author's email must be a valid email address.
+</p>
+<p style="text-align:justify">
+The collection description should describe, in as much detail as possible, what your new collection is about. It is unlimited in length, and you can use the [Enter] key to break it into paragraphs. You cannot use the [Tab] key to set margins, because this key shifts the focus to one of the buttons at the bottom of the screen.
+</p>
+<p style="text-align:justify">
+The final field allows you to chose which metadata sets are to be available within your collection. All the metadata sets found in the Librarian Interface metadata directory will be shown here.  Click the checkbox next to the sets you want to add. You may of course choose to start a new collection with no metadata sets loaded. Regardless one metadata set is always loaded, "Greenstone.mds".
+</p>
+<p style="text-align:justify">
+Once you have entered information in these fields, click the [O]K button to create the collection.
+</p>
+<p style="text-align:justify">
+If at any time you decide not to create a new collection, click the [C]ancel button. The prompt will close and you will return to the main screen.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="AI">Advanced Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+Buttons, like menus, have one character underlined. If you press [ALT] and the underlined character at the same time, the response will be just as if you clicked the button. (This goes for most buttons in the Librarian Interface.)
+</p>
+<p style="text-align:justify">
+If a collection is already open and you ask for a new one, a Save Collection prompt appears before the New Collection prompt. This is described in the next section, saving your collection. You have to finish with this prompt before the New Collection prompt will appear.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="QA">Problems and Solutions:</a>
+      </u>
+      <font size="3">
+      <i>
+<p style="text-align:justify">
+"I want to change the values I entered for title/email/description. How do I do that?"
+</p>
+
+      </i>
+<p style="text-align:justify">
+Once a collection has been created these details can be changed in the Design view.
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/2-2.htm
===================================================================
--- /tags/start/gli/help/2-2.htm	(revision 13666)
+++ /tags/start/gli/help/2-2.htm	(revision 13666)
@@ -0,0 +1,222 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+2.2 Saving Your Collection
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section describes how to save a collection, and how to address the Save Collection Prompt.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+How to save
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The save collection prompt
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#AI">Advanced instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Where the files are saved
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+Problems and Solutions
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+"What happens if I make a mistake while I'm working and want to reload the original collection?"
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+Now you have created a new collection, you should save it regularly. To do this, open the [F]ile menu and choose the [S]ave command, or type [Alt] + [F] followed by [S]. After a slight delay while the collection is saved, you will return to the main screen ready to continue. Note that this saved collection needs to be 'created' before it can be viewed through Greenstone (see Previewing Your Collection).
+</p>
+<p style="text-align:justify">
+If the current collection is unsaved and you take any action that might lose it (such as exiting the program or loading another collection), the Librarian Interface will prompt you to save first by presenting a small window in the middle of the screen that won't go away until you attend to it. For the Save prompt, the available actions are:
+</p>
+<p style="text-align:justify">
+[Y]es -- saves the current collection before carrying out the next action. [N]o -- does not save the collection and carries out the next action regardless. [C]ancel -- does not save the collection, but does not carry out the action either. The program returns to the state it was in before the action.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="AI">Advanced Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+When you save a collection, its data will be written to a file whose name is the same as the collection name (maximum seven characters), with file extension .col, located in a directory of the same name within the collect directory of your Greenstone installation.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="QA">Problems And Solutions:</a>
+      </u>
+      <font size="3">
+      <i>
+<p style="text-align:justify">
+"What happens if I make a mistake while I'm working and want to reload the original collection?"
+</p>
+
+      </i>
+<p style="text-align:justify">
+Just open the original collection as described in Opening An Existing Collection, but select [N]o within the Save Collection prompt. The current version will not be saved, and the original will be reloaded.
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/2-3.htm
===================================================================
--- /tags/start/gli/help/2-3.htm	(revision 13666)
+++ /tags/start/gli/help/2-3.htm	(revision 13666)
@@ -0,0 +1,207 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+2.3 Opening an Existing Collection
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section tells you how to open existing collections using the Open Collection prompt.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+How to open a collection
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#QA">Problems and solutions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+"I can't see my collection file?"
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+"Whenever I try to load my collection I receive an error message about some other Librarian Interface session using the collection?" or "What does the little red icon next to my collection mean?"
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+To open an existing collection, choose [O]pen from the [F]ile menu to get the Open Collection prompt (just like in any Windows program). 
+</p>
+<p style="text-align:justify">
+At the top of the window is a text field with a little triangular button at its right end (this is called a 'ComboBox'). Click on the triangle to reveal a list of items that you can select. The items are directories in your file system; this is a quick way to select one.
+</p>
+<p style="text-align:justify">
+Another of the buttons to the right of the dropdown box shows a folder with an upward-pointing arrow, and this is used to move to a parent directory. If you are in the directory 'c:\program files\gsdl\collect\modelcol\', pressing this button would move to 'c:\program files\gsdl\collect\'.
+</p>
+<p style="text-align:justify">
+Most of the screen is a large white area that lists the files and subdirectories within the directory you are currently in. If you interact with a file it will appear in the text field at the bottom of the screen, and may be opened as well (depending on the interaction). If you interact with a directory you will move into it. Down the right-hand side of this white space is a scroll bar with arrows at top and bottom to move the list up and down, and a large grey button which represents the part you are viewing. Drag the scroll bar up and down to move to a desired part of the page.
+</p>
+<p style="text-align:justify">
+Next on the page is a text area where the description of the collection is displayed (if a collection is currently selected).
+</p>
+<p style="text-align:justify">
+To the left of the [O]pen and [C]ancel buttons is the text field where the name of any selected file is shown. If you know what file you are seeking, type its name here and click [O]pen.
+</p>
+<p style="text-align:justify">
+The list of files displayed initially is determined from the collect directory of your Greenstone installation. Open the folder corresponding to your collection by double-clicking it and in it locate the file whose name is the collection name followed by ".col". Click once and then respond [O]K, or alternatively double-click on the file (anywhere in its row will do), or use the arrow keys to change your selection. After a short loading delay, the collection will open and you will be returned to the main screen. Clicking [C]ancel will return you to the main screen without opening anything.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="QA">Problems And Solutions:</a>
+      </u>
+      <font size="3">
+      <i>
+<p style="text-align:justify">
+"I can't see my collection file?"
+</p>
+
+      </i>
+<p style="text-align:justify">
+The file is named '<collection name>.col' within a directory named '<collection name>'. Ensure that you are in the correct directory. If you are unsure, cancel the Open Collection prompt by clicking [C]ancel, then reopen it as described above. It always starts in the Greenstone collection directory.
+</p>
+
+      <i>
+<p style="text-align:justify">
+"Whenever I try to load my collection I receive an error message about some other Librarian Interface session using the collection. Why? How do I fix it?" or "What does the little red icon next to my collection mean?"
+</p>
+
+      </i>
+<p style="text-align:justify">
+To allow for several copies of the Librarian Interface to be running at once, without encountering problems when two users attempt to edit the same collection, 'lock files' are used. When you open or create a collection, a small temporary file, 'lock.tmp', is created in that collection's directory. Before the Librarian Interface opens a collection, it checks whether a lock file exists, and if so refuses to open the collection. You can quickly tell if the collection is locked by the colour of its icon: greenstone green for a normal collection, red for a locked collection. However, sometimes lock files are left behind when the Librarian Interface is exited prematurely. In this case you can choose to 'steal' control over the collection. Be warned though that stealing the lock from a collection that is currently opened by someone else will cause one of the users data to be lost adter saving (it depends on who saves last).
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/3-0.htm
===================================================================
--- /tags/start/gli/help/3-0.htm	(revision 13666)
+++ /tags/start/gli/help/3-0.htm	(revision 13666)
@@ -0,0 +1,70 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+3.0 Hunting For Your Files
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+Please note that this section is only relevant if you have run the Librarian Interface using the '-mirror' argument flag used to enable the 'Hunt' and 'Mirror' views. If the flag was not used then those tabs will not appear in the row of tabs, nor will any preference options related to these features be available.
+</p>
+<p style="text-align:justify">
+While the Librarian Interface allows you to import files from anywhere on the local file system, it was originally designed to locate web-based resources. To support this required two distinct stages. This chapter describes the first, Hunting, where you browse the internet for files of interest.
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/3-1.htm
===================================================================
--- /tags/start/gli/help/3-1.htm	(revision 13666)
+++ /tags/start/gli/help/3-1.htm	(revision 13666)
@@ -0,0 +1,191 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+3.1 The 'Hunt' view
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section describes how to use the simplified browsing interface to locate resources on the internet.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The address field
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The controls
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+Problems and Solutions
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+"The page I'm attempting to view to won't renderer or only partially renders, then the program appears to hang?"
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+When you first encounter the 'Hunt' view, by clicking on the similarily named tab along the top of the screen, you should hopefully be greeted by a familiar screen. The majority of the screen is dedicated to the view of the webpage, and also provides scrollable ability if the page shown is large than the available space. The document shown within this pane is either a 'rendered' HTML page, or and image or other media. Rendering is the process whereby specially structured text, such as HTML, is turned into a formatted page. The document itself is exactly the same as any web-page shown in Internet Explorer or similar internet browing software, with hyperlinks underlined and highlighted. Clicking on a hyperlink will take you to the page it refers to. At the very bottom of the screen is the status bar which gives you feedback as to what the browser is currently doing. When it displays 'Ready' the current page is fully loaded.
+</p>
+<p style="text-align:justify">
+Directly above the page view, and in the center of the screen, is the address field. You type URL addresses into this box, which should be in the same form as http://www.greenstone.org/ or http://www.cs.waikato.ac.nz/ etc. The field will also be updated to show the address of any page you surf through to (by clicking on hyperlinks within the html page), or are redirected to.
+</p>
+<p style="text-align:justify">
+To the left and right of the address field are six buttons. These provide control over the web page being shown. The buttons are, from left to right: Back, Reload, Home, Go, Stop and Forward. Back is used to return to the previous page you viewed this session, and will only have an effect if there was a page previous to the currently shown one. Reload caused the currently displayed page to be reloaded from its web source, ensuring the latest copy is shown or reattempting to find images and other imbedded objects that may have failed on the first attempt. Home causes the nzdl homepage to be loaded. Go is used to make the browser visit the url you have typed in the address field. It is usually quicker to press [Enter] while in the address field. Stop causes the browser to stop whatever it is doing and return to the ready state. Forward only works if you have previously gone back in the browsing history, and it loads the next page you visited. To review which button is which, let your mouse pointer sit over it for a moment and its name should appear.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="QA">Problems And Solutions:</a>
+      </u>
+      <font size="3">
+      <i>
+<p style="text-align:justify">
+"The page I'm attempting to view to won't renderer or only partially renders, then the program appears to hang?"
+</p>
+
+      </i>
+<p style="text-align:justify">
+Currently no 'perfect' html renderer exists for pure java programs. The package I've choosen to use, CalpaHTML, is one of the best, but it too has some drawbacks. The most common of these is that it flickers when its renderer a web page that contains animated images. Less common, but more problematic, is when it encounters pages with heavy use of frames, internal frames or nested tables. Most of the time these pages will render, although their layout will be questionable. Occasionally they will cause CalpaHTML to get stuck in an infinite loop, and even pressing stop will have no effect. The only solution known is to press the back button, which will return you to the last page successfully rendered. However you will not be able to view the problem page in the built-in browser.
+</p>
+<p style="text-align:justify">
+Investigation was done into whether we could use a more stable, native HTML renderer, such as the Mozilla engine, to renderer. But these too had serious drawbacks such as lack of control, the restriction to only one view pane per JVM and large library sizes (increasing the size of Librarian Interface to unreasonable proportions).
+</p>
+<p style="text-align:justify">
+(That said, I have found web pages which even Internet Explorer and Netscape refuse to render, so perhaps the Librarian Interfaces not doing too badly.)
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/4-0.htm
===================================================================
--- /tags/start/gli/help/4-0.htm	(revision 13666)
+++ /tags/start/gli/help/4-0.htm	(revision 13666)
@@ -0,0 +1,73 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+4.0 Downloading Chosen Files
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+Please note that this section is only relevant if you have run the Librarian Interface using the '-mirror' argument flag used to enable the 'Hunt' and 'Mirror' views. If the flag was not used then those tabs will not appear in the row of tabs, nor will any preference options related to these features be available.
+</p>
+<p style="text-align:justify">
+The current system of downloading requires you to have a copy of the open source mirroring tool wget installed (preferrably WGet v1.8) and have it accessible from the Librarian Interface install directory (by including it in your path settings).
+</p>
+<p style="text-align:justify">
+As mentioned previously, sourcing files from the web is a two stage process. The second stage, having found the files you wish to gather, is to download (or 'mirror') onto the local filespace. This chapter explains the Librarian Interfaces mirroring process.
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/4-1.htm
===================================================================
--- /tags/start/gli/help/4-1.htm	(revision 13666)
+++ /tags/start/gli/help/4-1.htm	(revision 13666)
@@ -0,0 +1,208 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+4.1 The 'Mirror' view
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section describes how to configure a download task, and how to control the downloading process.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The workspace tree
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Download configuration
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The download list
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#AI">Advanced instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Enabling web proxies
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Advanced mode
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+The 'Mirror' view is accessed by clicking on its tab within the row of tabs. Unfortunately the mirroring view is probably the most complex in the Librarian Interface. To the left of the screen is the workspace tree which is the same as the one shown on the left of the 'Gather' view. The bottom of the screen is initially blank, but will later contain a list of pending download jobs. Finally the right of the screen is covered with the controls used to configure a new download job.
+</p>
+<p style="text-align:justify">
+The workspace tree will be discussed in detail in later sections. But for now notice the appearance of one or two new base level folders. The first of these, 'Public Workspace', is always present when mirroring is enabled, and can be thought of as the shared cache of files. Any files downloaded here will be availble to any other collections built with this copy of the Librarian Interface. The second folder, 'Private Workspace', only appears once a collection has been opened. This file cache is stored with the collection, so only this collection has access to it. In either case, files will be stored into these areas using their full path names as determined from the url of these source page. Thus a new folder will be created for the url host name, then more as necessary as the path specifies. This ensures that each file is distinct, so that you can download several index.htm pages from different urls, without overwriting the previous ones.
+</p>
+<p style="text-align:justify">
+Now for the new download task configuration controls. The very top field is used to enter the url to the target resource you wish to retrieve. If you have been browsing using the 'Hunt' view, this field will automatically be filled with the url of the last page visited. The next control, labelled 'Download depth' informs the Librarian Interface how many times you wish to follow hyperlinks and download the resources found there as well. A depth of 0 means no hyperlinks will be followed and only the target resource will be retrieved, while ticking the infinite box could possibly cause you to mirror <strong>the entire internet!</strong> The depth is ignored when downloading media other than html pages. The next control lets you choose the destination for the files downloaded, by clicking on the appropriate toggle button. The selected destination is denoted by a large tick. The next control, when ticked, causes any hyperlinked objects needed to render the page properly to be downloaded. Note that this is independant of the download depth setting as it only considers embedded objects (i.e. internal not external hyperlinks). The next control lets you determine if the Librarian Interface can mirror files from paths above the target url (this is determined from the path, which is the portion of the url after the hostname). The 'Only mirror within the same site' control restricts the mirroring to files with the same host name when ticked. The next control determines whether local files should ever be overwritten during download and the second to last control, within the 'Download List Options' group, allows you to specify what should happen to download tasks if they fail for some reason. Note that changes to this control are immediate, rather than part of a specific download job. The final control to discuss is the 'Download' button which creates a new job by looking at the configuration settings above, then adds it to the download list.
+</p>
+<p style="text-align:justify">
+Whil blank initially the download list will eventually contain several entries, each representing a download task, and each with the same general appearance. You can scroll the list to see further tasks. Looking at a single task, you will notice two buttons to the left and right, and a central region with several lines of text and a progress bar. The text gives details of the task, and will update as the task progresses, while the progress bar gives an indicating of activity. The button to the left, with the blue 'play' triangle on it, will begin the current task. Once it has been pressed the downloading will begin, and its icon will change to double vertical bars or 'pause'. Pressing pause will pause the current download. The button to the right, with the blue 'stop' square, will cause the current download task to be removed from the list. If a download task completes successfully it will automatically be removed from the download list, while whether it is removed on failure is controlled by the download list option.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="AI">Advanced Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+You may have noticed that there is a label at the bottom of the download configuration controls that states you should see the preferences page for more options. This is available for those users who must access the internet via a proxy web server. If you open the preference prompt, found under the File menu, and change to the 'Connection' tab, you will be presented with controls for setting the proxy. First tick the box if it is appropriate, then enter the name and port of the proxy server. Finally you can press the 'Establish Connection' button to attempt to connect to the proxy immediately, otherwise the Librarian Interface will connect the next time it is started. The reason these options are provded here, and not on the 'Mirror' view, is that they are persistant between sessions, and are automatically re-established whenever the Librarian Interface starts. Also note that if authentication is needed for connection to the proxy server you should be prompted for a login and password (you may infact be prompted twice due to a bug in how Java connects to proxies). A valid login/password is persistant for the remainder of that Librarian Interface session, but is not stored between sessions due to security considerations.
+</p>
+<p style="text-align:justify">
+Again you may have noticed that the feedback during downloading is poor at the very best, with the progress bar only showing that something is happening, and the status text sometimes very vague about what is actually happening (you are told last file downloaded, not what is downloading at this time). This is due to limitations of running Wget as an external process to the Librarian Interface. There is a more advance mode of running the mirroring part of the Librarian Interface which integrate WGet functionality directly using special java libraries called the JNI. This provides exact details of what is happening including an accurate progress bar for each file. However this mode is currently disabled due to its platform specific nature. Watch for this ability in the future.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/5-0.htm
===================================================================
--- /tags/start/gli/help/5-0.htm	(revision 13666)
+++ /tags/start/gli/help/5-0.htm	(revision 13666)
@@ -0,0 +1,67 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+5.0 Collecting Files for Your Collection
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+You have created a new collection and it's time to import some files into it. These files may be sourced from several areas, including previous Greenstone Collections. You may also choose to import files that already have metadata assigned to them. The actions involved in this file gathering stage are detailed within this chapter.
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/5-1.htm
===================================================================
--- /tags/start/gli/help/5-1.htm	(revision 13666)
+++ /tags/start/gli/help/5-1.htm	(revision 13666)
@@ -0,0 +1,270 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+5.1 The 'Gather' View
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section introduces the Gather area that you use to select what files to include in the collection you are building.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+How to view the gather screen
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The file trees
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The status area
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Control buttons
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#AI">Advanced instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Selection methods
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Special directory mapping
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#QA">Problems and solutions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+"I attempt to change the name of a file but nothing happens? or I can't drag'n'drop files in the workspace tree?"
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+The Librarian Interface starts with the Gather view. If, later, you need to return to this view, notice the tabs (like file-cabinet tabs) directly below the menu bar. Clicking a tab opens the view with that name. To open the Gather view, click on the tab labelled Gather.
+</p>
+<p style="text-align:justify">
+There are two large areas titled 'Workspace' and 'Collection'. These are used to move files into and out of your collection. They contain 'file trees', which are graphical structures that represent directories (shown with folder icons) and the files they contain.
+</p>
+<p style="text-align:justify">
+Select any item in the tree by clicking on it once. (There are more ways; see below.) Double-clicking a directory node whose children (files and directories) are not shown expands that directory by making its children visible. Double clicking an expanded directory node collapses it again. You can also expand and collapse directories by clicking on the little switch symbol that precedes the folder name. If you double-click on a file the Librarian Interface will attempt to open it in whatever program is best suited to view it. If you press [F2] (Function Key 2) while a file or directory is selected (or if you did not double-click quickly enough), a black box will appear around the selected item, with a flashing cursor. This visual prompt indicates that you can now edit the name of the selected item. (As explained below, you can only do this if the item is not read-only). When you have finished editing, press [Enter], or click anywhere else on the program screen, to leave edit mode. The areas containing the trees are also scrollable as explained earlier.
+</p>
+<p style="text-align:justify">
+There are two different file trees; the Workspace and the Collection. The Workspace contains the sources of data that are available to the Librarian Interface. These include: the complete local file system (including all disk and CD-ROM drives), the contents of existing Greenstone collections, the public download space if Web mirroring is enabled, and the private download space, again only if mirroring is enabled. The files in this tree are read-only: you can copy and view them but you cannot move, delete, or edit them. Navigate around this tree until you find the files you want to include in your collection. The Collection represents the contents of your collection so far, and can be fully edited except the very top folder (which can never be deleted). Initially, it will be empty. This tree is shared with the MetaEdit view described later in this document.
+</p>
+<p style="text-align:justify">
+If you move the mouse pointer over the small vertical grey bar that separates the two trees, the shape of the pointer changes, and you can alter the two spaces by pressing and dragging the mouse, widening one while shrinking the other.
+</p>
+<p style="text-align:justify">
+At the bottom are the Status Area and the Control Buttons. The Status Area tells you about the state of the Librarian Interface: how many items you have selected and what action you are requesting. When you start performing actions that involve files it reports on the progress of the operation. Actions involving large files can take some time to complete, but you needn't wait. While one action is being performed you can initiate others, and they will just wait until the current action is complete. This feature allows you to perform other actions, or visit other views, without having to wait for the current action to finish.
+</p>
+<p style="text-align:justify">
+The three large Control Buttons occupy the lower right corner of the screen. The first is the Cancel Action button, which is used to immediately cancel any file movement tasks that are occurring or pending. The next is the New Folder button, which is used to create new folders: it shows a picture of a folder (see Creating folders). The last is the Delete button, which is used to remove files; it shows a garbage can.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="AI">Advanced Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+There are more powerful techniques for file selection. To select several contiguous items, select the one at the start of the range and then hold down a [Shift] key while clicking on the one at the end of the range -- the selection will encompass all intervening items. You can select non-sequential files by holding down the [Ctrl] key while clicking on the target item. These two methods, which are common to all Microsoft Windows applications, can be used in combination to select groups of non-adjacent items.
+</p>
+<p style="text-align:justify">
+There are sometimes folders in your filespace that have special significance such as the root folder of your home web pages, or perhaps a 'drop-box' used as the destination folder for resources from other programs. To provide move convenient access to these directories, which may otherwise appear deep within the workspace tree, you may crate a special 'mapping' to such a folder, causing it to appear at the first level of the tree. For instance the 'Greenstone Collections' folder is simply a special mapping to the greenstone collections folder. To create a mapping, expand the workspace tree so that the special folder is visible, then right button mouse click over the folder. A menu should appear with the option the 'map' the folder. If you choose this option a prompt will appear asking you for a meaningful alias for this folder. Providing a name and clicking OK will create the new special folder mapping at the top level of the tree. Now you access the files in the special folder via this aliased shortcut, or by expanding the tree as before. To remove a special mapping you once again right click over the mapped folder. The option to remove the mapped folder is available. Note that no confirmation is asked for when removing the mapping. 
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="QA">Problems And Solutions:</a>
+      </u>
+      <font size="3">
+      <i>
+<p style="text-align:justify">
+"Nothing happens when I try to change the name of a file?" or "I can't drag'n'drop files in the workspace tree?"
+</p>
+
+      </i>
+<p style="text-align:justify">
+Files and directories in the Workspace tree are read-only and the Librarian Interface cannot change them. This protects other people's collections, and also your own files. The topmost directory of the Collection tree, which has your collection name as a title, is also read-only. If you try to edit these, nothing will happen.
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/5-2.htm
===================================================================
--- /tags/start/gli/help/5-2.htm	(revision 13666)
+++ /tags/start/gli/help/5-2.htm	(revision 13666)
@@ -0,0 +1,222 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+5.2 Creating Folders
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section shows how to create new folders, and introduces the right-button-click menu.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The new folder button
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The right-button menu
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#AI">Advanced instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Multiple folders
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#QA">Problems and solutions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+"No matter how I try I can't create a new folder?"
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+A 'folder' in Microsoft Windows is the same as a directory, and directories are indicated by the folder icon. When the Librarian Interface creates a folder it is actually creating a directory. However, we continue to use the more familiar term 'folder'. Folders are used in the tree to group files together, and to introduce structure that makes it easier to find files. 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 style="text-align:justify">
+To create a folder, select a non-read-only folder from either tree and click the New Folder button. A folder called 'New Folder' appears within the selected one. [Renaming files using Java is problematic, so for the time being it is disabled. If you rename this folder using some other method, the new name will be visible the next time the tree is refreshed; when it parent folder is collapsed and expanded, or when the collection is reloaded].
+</p>
+<p style="text-align:justify">
+Folders can be created more conveniently using the right-click menu. Move the mouse pointer over the parent folder and click the right mouse button. A menu, just like those in the menu bar, appears below the mouse pointer. It may have just one item, or several of them, depending on what item you clicked it over. Choose the New Folder item to create a new child folder exactly as above.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="AI">Advanced Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+You can create several folders, one after another, without having to rename them in between. They will be given names New Folder 001, New Folder 002, and so on.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="QA">Problems And Solutions:</a>
+      </u>
+      <font size="3">
+      <i>
+<p style="text-align:justify">
+"No matter how I try I can't create a new folder."
+</p>
+
+      </i>
+<p style="text-align:justify">
+If a folder is read-only, the Librarian Interface cannot change its contents. You are probably trying to create a folder where you're not able to.
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/5-3.htm
===================================================================
--- /tags/start/gli/help/5-3.htm	(revision 13666)
+++ /tags/start/gli/help/5-3.htm	(revision 13666)
@@ -0,0 +1,228 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+5.3 Adding Files
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section shows how to get files into your collection.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Dragging a file
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Multiple files
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#AI">Advanced instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Existing metadata
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#QA">Problems and solutions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+"I drag a file, but when I drop it nothing happens?"
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+Files can be copied into the collection using the drag-and-drop method introduced earlier. After selecting one or more files and directories, you initiate a drag action by clicking and holding over any selected item. The mouse pointer changes into a ghost of the item (if just one was selected) or the number of selected items (if more than one was selected). The Status Area changes to reflect the beginning of a drag.
+</p>
+<p style="text-align:justify">
+Keeping the mouse button pressed, move the mouse around the screen. Areas that become highlighted when you move over them are valid drop targets, places where you can drop the selected items. If you drop items into a tree, they are copied from their origin into the place where you dropped them.
+</p>
+<p style="text-align:justify">
+To copy files into your collection, select them from the Workspace (???) and drag them into a folder within your collection. You can copy directories as well. You can also copy files about within the same tree if you wish. If you drag files from an existing collection which contains metadata information for them, the metadata will be automatically imported along with the files. (See Adding Metadata for a detailed explanation of metadata and its use in the Librarian Interface.)
+</p>
+<p style="text-align:justify">
+Some extra rules apply when copying multiple files. No matter what directory structure the files occupied before you copied them, they are all placed in the target folder at the same level. If you try to copy two files with the same name into the same folder, the Librarian Interface will ask whether you want to overwrite the first one. If you say No, the file in question will not be copied, but the other files will. If instead you wish to cancel all remaining copy actions click the stop button as described in the 'Gather' View.
+</p>
+<p style="text-align:justify">
+Another rule is that only the 'highest' items in a selection will be moved. A folder is higher than its children, which are higher than their own children, and so on. If you choose several files within a folder and the folder itself, the folder will be copied in its entirety and your selections within it will be ignored.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="AI">Advanced Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+When you add a file, the Librarian Interface also performs a further task. It searches through the source directories for auxiliary files which contain metadata previously assigned to the target file, and if found begins a process of importing this metadata. As this operation proceeds, you may be prompted several times to provide extra information to enable the Librarian Interface to correctly match the imported metadata to metadata you may have already added to your collection. This process involves many different prompts, which are described in the section titled Importing Previously Assigned Metadata.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="QA">Problems And Solutions:</a>
+      </u>
+      <font size="3">
+      <i>
+<p style="text-align:justify">
+"I drag a file, but when I drop it nothing happens."
+</p>
+
+      </i>
+<p style="text-align:justify">
+In principle, only valid drop targets are highlighted, so most drops should succeed. However, successful drops must meet several conditions: they must be dropped on a valid target; they must be dropped into some other place than where the drag started; they must be dropped into a folder, not a file; and the target must not be read-only.
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/5-4.htm
===================================================================
--- /tags/start/gli/help/5-4.htm	(revision 13666)
+++ /tags/start/gli/help/5-4.htm	(revision 13666)
@@ -0,0 +1,202 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+5.4 Removing Files
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section shows how to remove files and folders from your collection.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The delete button
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The delete key
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Delete by drag and drop
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#QA">Problems and solutions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+"Why can't I remove a certain selected item?"
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+The files in your collection are copies of the original files, so you can remove them without fear of deleting the only copy. There are several methods for removing files and folders.
+</p>
+<p style="text-align:justify">
+In general, all remove actions require you to first select the items to remove. You may select one or more files and directories using the techniques outlined here.
+</p>
+<p style="text-align:justify">
+Once some files have been selected, click once on the Delete Button in the Control Button area. This immediately removes the selected items.
+</p>
+<p style="text-align:justify">
+Another method is to make your selection and then press the [Delete] key on your keyboard to remove the files.
+</p>
+<p style="text-align:justify">
+The final way to remove files uses the same drag and drop method you used to copy the files, except this time you drag from your collection down to the Delete Button. The button responds by becoming highlit, indicating that it is a valid drop target. Drop the selected items here and they will be removed from your collection.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="QA">Problems And Solutions:</a>
+      </u>
+      <font size="3">
+      <i>
+<p style="text-align:justify">
+"Why can't I remove a certain item?"
+</p>
+
+      </i>
+<p style="text-align:justify">
+If you can't remove a file, then most likely you are not meant to because it is read-only.
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/5-5.htm
===================================================================
--- /tags/start/gli/help/5-5.htm	(revision 13666)
+++ /tags/start/gli/help/5-5.htm	(revision 13666)
@@ -0,0 +1,166 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+5.5 Filtering the Tree
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+In order to allow you to narrow down your search for particular files, we introduce the concept of filtering the trees.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The filter control
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#AI">Advanced instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Custom filtering
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+There is a ComboBox control at the bottom of the trees; it says 'All Files'. If you select the down arrow button at the end of the box, you will see a list of predefined filters, such as: 'Images' or 'Text Files'. Choosing one of these temporarily hides all files within the tree that do not match the chosen filter. To restore the tree to its original state, restore the filter to 'All Files'. Note that filtering does not change what files are in your collection, nor does it affect the folders within the tree.
+</p>
+<p style="text-align:justify">
+The workspace tree filter stands alone. However, the collection trees here and on the Enrich view share the same filter. 
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="AI">Advanced Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+The filter control ComboBox is editable. You can specify a custom filter by typing in a pattern against which files will be matched. This pattern may be a regular expression, or use standard file system abbreviations such as *.* or *.doc.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/6-0.htm
===================================================================
--- /tags/start/gli/help/6-0.htm	(revision 13666)
+++ /tags/start/gli/help/6-0.htm	(revision 13666)
@@ -0,0 +1,67 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+6.0 Enriching Your Collection with Metadata
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+Now that you have gathered several files into your collection it is time to enrich them with additional information. This process is also known as marking-up or assigning metadata. This chapter explains how to do this, how metadata is created, edited, remembered and retrieved within the Librarian Interface, and how to use external sources of metadata (such as the hand-edited metadata.xml files that Greenstone can use). 
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/6-1.htm
===================================================================
--- /tags/start/gli/help/6-1.htm	(revision 13666)
+++ /tags/start/gli/help/6-1.htm	(revision 13666)
@@ -0,0 +1,243 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+6.1 The Enrich View
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section describes how to input and edit metadata using the Enrich view.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The collection tree
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The metaedit controls
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The value tree
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The metadata table
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#QA">Problems and solutions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+"How can I quickly see all the metadata I've assigned in this collection?"
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+"How can I make the metadata table larger?"
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+The Enrich view is where you assign metadata to the documents in your collection. Metadata is data about data -- typically information such as title, author, creation date, and so on. Each metadata item has two parts: 'element' and 'value'. The element tells what kind of item it is (such as author or subject); the value gives the value of that metadata element (such as the name of the author or of the subject).
+</p>
+<p style="text-align:justify">
+On the left of the Enrich view is the Collection file tree. This is the same as the Collection file tree in the Gather view. It can be expanded, collapsed, scrolled and filtered, just as before. In fact, the same filter is shared between the Gather and Enrich Collection trees, so filtering one applies the same filter to the other. However, you cannot edit the tree. When you select files their details appear on the right.
+</p>
+<p style="text-align:justify">
+The Metadata Table is a spreadsheet-like table that occupies the upper right of the screen. It can show all metadata assigned for the selected files, or just the unassigned elements, or both assigned and unassigned metadata. These views are obtained by toggling the two appropriately named buttons directly underneath the table. Names of the columns are shown in grey labels at the top. You can resize columns by selecting and dragging the lines separating their names. Clicking any row of the table transfers its details to the MetaEdit Controls, as explained below, and the Remove button becomes active. If several files are selected in the tree, some of the tables' rows will be greyed out. If you click on one of these rows, only the Append and Remove edit controls become active. That is because this row's metadata is not common to all the selected files. A row which retains its normal black text colour shows metadata that is common to all selected files, and enables the use of the Update edit control when clicked. Having selected a file, you may find magnifying glass icons alongside some of the metadata entries. This indicates metadata that is inherited from one of this files parent folders. Such inherited metadata cannot be edited or removed, only appended to or overwritten. Click on the magnifying glass to be taken directly to the folder where the metadata is assigned, where you are free to update or remove it.
+</p>
+<p style="text-align:justify">
+On the lower right are the MetaEdit Controls. They remain hidden until you select a file; when they appear you use them to assign, update and remove metadata associated with the selected file. At the top is a grey ComboBox that shows the label elements. You cannot type new elements directly into it because the text area is disabled. However, the triangular arrow button drops down a scrollable list of available elements. If you choose one, the large white area immediately below the ComboBox will change. This area, including the text field below it, is called the Value Tree and is described shortly. Finally, the six buttons along the bottom only become active when their actions make sense. [S]earch and Restore [T]ree are used to search for particular metadata values. The [E]dit Text... button causes a large text editing dialog to appear, for multi-line metadata values. [A]ppend is used to append a new metadata value to the ones assigned to a file and is used when a file is selected and you have selected an element and entered a value. [U]pdate is used when a row in the metadata table is selected; it updates that metadata with whatever value has been entered for it. [R]emove removes a metadata value and is only active when a metadata row is selected.
+</p>
+<p style="text-align:justify">
+The Value Tree is a scrollable tree which expands and collapses just as you expect. Usually this tree acts as a list, showing all previous values that have been entered for the selected element. Clicking an entry in the Value Tree automatically enters it into the text field labelled Value. Conversely, typing in the text field auto-selects the Value Tree entry that starts with the characters you have typed. Pressing [Enter] auto-completes the typing with the selected value.
+</p>
+<p style="text-align:justify">
+Unlike an ordinary list, the Value Tree can also show hierarchical structures -- like a subject hierarchy. Values can be grouped into subjects, and subjects and values can be further grouped. Note that a 'subject' is a value as well, and can be assigned as part of a metadata item or used to expedite access to large collections of values. You can figure out the 'path' to a certain value by tracing from the highest level down to the value in question. This path can be typed into the text field using the character '\' to separate the various levels. For example, in a hierarchy that represents pack of playing cards hierarchy you might type "Red\Diamonds\Jack" or "Black\Clubs\Seven".
+</p>
+<p style="text-align:justify">
+If you know the value you seek is unique, just type the value name. The Value Tree will find and select the first item that matches. When you press [Enter], the full hierarchical path appears in the text field.
+</p>
+<p style="text-align:justify">
+The [S]earch button beneath the Value Tree reduces the tree by showing only entries that contain a target text fragment. First type the desired text fragment into the value field, then press search. Press the Restore [T]ree button to return the Value Tree to its initial state.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="QA">Problems And Solutions:</a>
+      </u>
+      <font size="3">
+      <i>
+<p style="text-align:justify">
+"How can I quickly review all metadata I've assigned to this collection?"
+</p>
+
+      </i>
+<p style="text-align:justify">
+The easiest way is to use the All Metadata View as discussed later under 'Reviewing All Metadata'.
+</p>
+
+      <i>
+<p style="text-align:justify">
+"How can I make the metadata table larger?"
+</p>
+
+      </i>
+<p style="text-align:justify">
+Between the MetaEdit Controls and the Metadata Table is a movable divider that you can use to make the Controls smaller so that you can see more of the Value Tree.
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/6-2.htm
===================================================================
--- /tags/start/gli/help/6-2.htm	(revision 13666)
+++ /tags/start/gli/help/6-2.htm	(revision 13666)
@@ -0,0 +1,197 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+6.2 Selecting Metadata Sets
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section explains how to specify metadata elements and how to add metadata sets to your collection.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Adding a metadata set
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#AI">Advanced instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Updating a set
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Creating new sets
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Exporting a set
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+Sets of predefined elements known as 'metadata sets' can be loaded from the Librarian Interface's directory. 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 prepended to the element name. For instance the Dublin Core element Creator becomes dc_Creator.
+</p>
+<p style="text-align:justify">
+To add a metadata set, open the [M]etadata menu from the menu bar and select the [A]dd Metadata Set action. You will be presented with an Open File Prompt (just like the Open Collection Prompt discussed earlier) that shows the contents of the Librarian Interface's metadata directory. Choose an '.mds' or metadata set file and open it. Next you will be prompted as to whether you wish to import all of the values associated with the elements in this set, just those values that make up the structure of hierarchy-based metadata, or no values at all. When you return to the Enrich view the element ComboBox will now show the appropriate entries.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="AI">Advanced Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+To install a newer version of a metadata set, simply add it as above. The Librarian Interface uses some simple strategies for merging the two sets, and will not lose track of values you have entered. You may however be prompted as to how to merge certain elements. For example if a currently available set and the set you are importing have an element of the same name (which is most likely if you are installing a new version of a set), you will be presented with a prompt showing as much information about the existing and new elements as possible, and providing you with several options on how to proceed with the merging. These options include merging the two elements, renaming the new element so there is no longer a clash, replacing the old element entirely, or not adding this element by skipping it. Merging the elements provides basically the same options, but at an element attributes level. You may of course choose to cancel the metadata set import at any time.
+</p>
+<p style="text-align:justify">
+The ".mds" files themselves are expressed in XML format. To edit an existing metadata set, or to create a brand new one, you can use an ordinary text editor. If you are starting a new file, copy the Document Type Definition (the text within the tag) to the top of your new file and ensure that you follow it, otherwise the Librarian Interface will be unable to load your metadata set. Use of an XML validator or validating editor is recommended. 
+</p>
+<p style="text-align:justify">
+If you know XML, the text itself will look familiar. It comprises a series of tags between '<' and '>' symbols. Each opening tag is closed by a correspondingly-named closing tag, which contains the same name preceded by '/'. For example, <Element>...</Element>.
+</p>
+<p style="text-align:justify">
+Any time you want to export a metadata set, or part of a metadata set (e.g. its assigned value hierarchy, or all its values), return to the Librarian Interface and choose [E]xport Metadata Set from the [M]etadata menu. A prompt will ask you to select appropriate export options, and a file to export into.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/6-3.htm
===================================================================
--- /tags/start/gli/help/6-3.htm	(revision 13666)
+++ /tags/start/gli/help/6-3.htm	(revision 13666)
@@ -0,0 +1,311 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+6.3 Appending New Metadata
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section explains how to add metadata and values to files, and how to add new values for metadata elements.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Adding to files
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Adding to directories or multiple files
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#AI">Advanced instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Adding to the metadata table
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Subject hierarchies
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td>
+                  &nbsp;
+                </td>
+                <td>
+                  <font face="Verdana" size="4">
+Introduction to subjects
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td>
+                  &nbsp;
+                </td>
+                <td>
+                  <font face="Verdana" size="4">
+Metadata set editor
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Text field entry
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#QA">Problems and solutions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+"How do I fix a value that has ended up in the wrong subject?"
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+"What if I have a value and a subject with the same name?"
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+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. Notice that the Select action causes some changes to the right of the view. If this is the first file selected, the MetaEdit Controls will appear in the upper right, ready for you to start editing. The name of the selected file appears in the text field in the middle on the right. Any metadata previously assigned to this file appears in a table at the bottom right.
+</p>
+<p style="text-align:justify">
+Next, select the metadata element you want to add. Click on the triangle at the right of the 'element' ComboBox and scroll to find the element name you wish to add; then click it. The Value Tree below may change when you change elements -- but probably, right now, it's blank.
+</p>
+<p style="text-align:justify">
+Now focus on the 'value' text field, either by pressing [Tab] several time or by clicking anywhere in the field. When the flashing caret appears in the field, you can type your value. Be careful not to use the character '\', because it is used for constructing hierarchies. When finished, press [Enter] or [Tab], or just click elsewhere on the screen. If you have entered a new value for the first time a pop-up will ask for confirmation of the value. When you confirm by clicking [Y]es, the value is added to the Value Tree, and the [A]dd button is enabled. Click [A]dd to add the new value as metadata for the chosen file. The metadata immediately appears in the Metadata Table. If the file already had a value assigned for that specific metadata element you may be prompted for what action to take. This prompt and the available actions are described below.
+</p>
+<p style="text-align:justify">
+You can also add metadata to a folder, or to several files at once that have been multiply selected.  This adds it to all files within the folder or selection, and to any child directories. However keep in mind that if you assign metadata to a folder that any new files added to that folder will automatically inherit the aforementioned metadata.
+</p>
+<p style="text-align:justify">
+When you add metadata in this way, or if previous metadata exists for the element you have selected, you will be prompted for the action to take on the files it contains. The prompt includes the name of the file in question, the element's title, any previously-assigned values for this element, and the new value that you have entered. The buttons offer different options: '[A]ppend' appends the metadata to the specified file without altering any existing values; 'Append All ([D])' adds the new value in the same way to all child files; '[R]eplace' replaces any previous value with the new one; 'R[E]place All' adds the new value in the same way to all child files; '[S]kip File' skips the current file and proceeds to the next; '[C]ancel' undoes any changes and cancels the action.
+</p>
+<p style="text-align:justify">
+If you choose metadata that is not common to all the selected files, and you press the Add button in the edit controls, the metadata will be added as necessary to make it common to all files in the selection.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="AI">Advanced Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+You can add structure to metadata values by using paths. When Greenstone builds certain classifiers, it uses as additional information a hierarchy of possible values. No longer is the classifier a flat list; instead it has a tree structure which can make large collections far easier to navigate. The Librarian Interface automates the process of generating hierarchy files.
+</p>
+<p style="text-align:justify">
+All values you assign in the Librarian Interface can also be subjects. They begin with no subvalues, and so appear flat. However, you can create a value that is a child of another value, and now the parent appears as a folder in the Value Tree. Expanding the folder shows the value contained within. Remember that all subject folders are also values, so you can assign a folder from the Value Tree as the value for a metadata element. For instance, the subject folder might be the default value of some element, while its child values and folders offer increasingly specific metadata values.
+</p>
+<p style="text-align:justify">
+The way to build hierarchies is to specify a path, using '\' as a level separator, when typing into the Value text field of the MetaEdit Control. If you type in a new path, any subject folders that aren't already in the tree will be created. This method can be used to build arbitrarily complex structures.
+</p>
+<p style="text-align:justify">
+Anywhere you can type in a value for the metadata value, you can use a fully-qualified path to specify its position in the hierarchy. However, be warned: a spelling mistake may introduce several new subject folders unintentionally.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="QA">Problems And Solutions:</a>
+      </u>
+      <font size="3">
+      <i>
+<p style="text-align:justify">
+"A value has ended up in the wrong subject."
+</p>
+
+      </i>
+<p style="text-align:justify">
+The easiest fix is to create the value in the right place and ignore the incorrect one. It won't vanish from the tree, but it won't matter as long as you assign the correctly located value. Alternatively you can use the Metadata Set Editor, explained in chapter 11, to move the value from its current parent subject to the desired one.
+</p>
+
+      <i>
+<p style="text-align:justify">
+"What if I have a value and a subject with the same name?"
+</p>
+
+      </i>
+<p style="text-align:justify">
+At first this seems a problem. What if I wanted a Words subject folder, and then one of the values I wanted to place in it was Words? There are two solutions. First, it is perfectly ok to add "Words\Words". It may look strange but it works -- just make sure you get the right one when adding it as metadata to files. The second, preferred, solution is to use the folder Words when you want to assign the values Words. Remember, all folders are also values!
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/6-4.htm
===================================================================
--- /tags/start/gli/help/6-4.htm	(revision 13666)
+++ /tags/start/gli/help/6-4.htm	(revision 13666)
@@ -0,0 +1,140 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+6.4 Adding Previously Defined Metadata
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section explains how to add metadata that assigns values that already exist in the value tree.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Adding to files
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Adding to directories or multiple files
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+To add metadata that has an already-existing value, first select the file and then select the required value from the value tree, expanding subject folders as necessary. The value of any selected entry in the tree automatically appears in the Value text field. Alternatively, you can use the auto-select and auto-complete features of the value tree. Click [A]dd to add the metadata to the selected file.
+</p>
+<p style="text-align:justify">
+The process of adding metadata with already-existing values to directories or multiple files is just the same. 
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/6-5.htm
===================================================================
--- /tags/start/gli/help/6-5.htm	(revision 13666)
+++ /tags/start/gli/help/6-5.htm	(revision 13666)
@@ -0,0 +1,182 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+6.5 Updating Metadata
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section explains how to update the metadata assigned to a file.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Updating files
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Updating directories or multiple files
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#QA">Problems and solutions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+"I've updated a value, why does the old value still appear in the Value Tree?"
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+To update the value of a certain piece of metadata, first choose the file to which that value applies. In the Metadata Table control, find the metadata element whose value you want to change, and select it by clicking anywhere in that row. Your selection appears in the MetaEdit Controls above, and the [U]pdate button is activated. Edit the value in the Value Text field and then click [U]pdate to alter the metadata.
+</p>
+<p style="text-align:justify">
+The process is the same when updating a directory with child folders or multiple files, except that pressing [U]pdate yields a prompt to specify what to do with child files. The buttons offer different options: '[R]eplace' replaces any previous value with the new one; 'R[E]place All' adds the new value in the same way to all child files; '[S]kip File' skips the current file and proceeds to the next; '[C]ancel' undoes any changes and cancels the action. Note that you can only update metadata that is common to all files selected. For a directory this means that all its children must share the same metadata.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="QA">Problems And Solutions:</a>
+      </u>
+      <font size="3">
+      <i>
+<p style="text-align:justify">
+"I've updated a value, why does the old value still appear in the Value Tree?"
+</p>
+
+      </i>
+<p style="text-align:justify">
+This is a feature, not a bug! Even if you remove all references to a value, it doesn't mean you'll never want that value again.
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/6-6.htm
===================================================================
--- /tags/start/gli/help/6-6.htm	(revision 13666)
+++ /tags/start/gli/help/6-6.htm	(revision 13666)
@@ -0,0 +1,203 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+6.6 Removing Metadata
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section explains how to remove metadata from a file.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Removing from files
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Removing from directories or multiple files
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#AI">Advanced instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Removing from the table
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#QA">Problems and solutions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+"I've removed some metadata, buts its value still appears in the Value Tree?"
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+You remove metadata the same way as you update it. First select a file from the file tree, then use the Metadata Table in its Assigned Metadata or All Metadata modes to select the metadata. If the metadata has a value assigned, the [R]emove button in the MetaEdit Controls becomes active. Click it to remove the metadata from the specified file. Other files remain unchanged, and the value still appears in the Value Tree.
+</p>
+<p style="text-align:justify">
+If you remove metadata from a directory with children or from multiple files, a prompt presents several options. '[R]emove' removes the metadata from this file; 'Remove [A]ll' removes it from all remaining files; '[S]kip' leaves the metadata in this file and proceeds to the next; '[C]ancel' undoes any changes and cancels the action. Note that if you choose metadata that is not common to all the selected files, and you click the [R]emove button in the edit controls, the metadata will be removed from those files that have it. Those that do not contain this metadata will be unaffected.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="QA">Problems And Solutions:</a>
+      </u>
+      <font size="3">
+      <i>
+<p style="text-align:justify">
+"I've removed some metadata, but its value still appears in the Value Tree"
+</p>
+
+      </i>
+<p style="text-align:justify">
+This is a feature, not a bug!  Even if you remove all references to a value, it doesn't mean you'll never want that value again. If you truely wish to remove the value as well you should use the Metadata Set Editor explained at the end of these help pages.
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/6-7.htm
===================================================================
--- /tags/start/gli/help/6-7.htm	(revision 13666)
+++ /tags/start/gli/help/6-7.htm	(revision 13666)
@@ -0,0 +1,204 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+6.7 Reviewing Assigned Metadata
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section shows how to view all metadata assigned to an entire collection.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+The audit table
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#AI">Advanced instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Right button menu
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Autofilter
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+Sometimes you need to see all metadata assigned to all files. For instance, you may wonder how many files are left to work on, or you may want to get some idea of the spread of dates.
+</p>
+<p style="text-align:justify">
+>From the [M]etadata menu choose the 'Assigned [M]etadata...' action. This opens a new window called the All Metadata view. The view is dominated by a large table like the Metadata Table, with many columns. The first column shows file names; the remaining ones show metadata element names. Each row shows all metadata values assigned to that file. 
+</p>
+<p style="text-align:justify">
+The audit view itself is non-modal, which means that you can carry on using the Librarian Interface even while the audit window is open. In fact, any changes in the collection files selected will immediately update the table accordingly.
+</p>
+<p style="text-align:justify">
+A lot of preparatory work must be done when creating the audit view's model, so drawing the table can take some time. If you select ten thousand files, the audit view may take thirty seconds to calculate and display.
+</p>
+<p style="text-align:justify">
+Once you have finished reviewing the metadata, click [C]lose to hide the audit table.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="AI">Advanced Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+You may view the metadata audit table at any time by selecting the files you wish to audit and opening the right click menu. Now click on the item [V]iew All Metadata. If a directory has been selected, all its child files will be included in the table.
+</p>
+<p style="text-align:justify">
+The metadata audit table quickly becomes daunting to navigate, and so a filtering mechanism is included, modelled on Microsoft Excel's concept of 'Autofilter'.  It allows a single filter to be applied to each column of the audit table. As new filters is added, only those rows that match the filters set on all columns remain visible. To set, modify or clear a filter, click on the grey area containing the metadata element name and an icon of a funnel, at the top of the column you wish to filter.  A new prompt appears allowing you to control filtering. Once a filter is set, the column header, and the funnel within it, changes colour to indicate that the column is being filtered.
+</p>
+<p style="text-align:justify">
+The prompt itself contains four main components. The top field reminds you of the name of the column, the second to bottom ComboBox control allows you to change the alphabetical order of the values in the column (move rows as necessary) and the bottom area offers you buttons to [S]et and [C]lear the filter. This leaves the middle area, where the filtering is actually controlled. Initially the Simple tab will be selected. This allows you to filter a column so that it only shows rows which contain a certain existing metadata value. Note that the * matches all values. Just choose the value you want to limit the column to, then set the filter.
+</p>
+<p style="text-align:justify">
+There is also an 'advanced' tab. While the simple filter is essentially a 'must equal', the advanced tab allows several different matching operations such as: must start with, does not contain, alphabetically less than and is equal to. Furthermore, the value to be matched can be edited to be any string, not just values that already exist within that column (although by default these values are made available as the drop down list connected to the value ComboBox). You may also choose whether the matching should be case sensitive. Finally, the advanced filtering allows you to specify a second condition that must be matched. This allows you to specify ranges of values accepted (by selecting the AND checkbox then filling out the filter) or possibly alternate values accepted (by selecting the OR checkbox instead). 
+</p>
+<p style="text-align:justify">
+Once you have finished select the ordering, click [S]et Filter. The new filter will be applied to the column, and you should notice that fewer rows are now visible.
+</p>
+<p style="text-align:justify">
+If at any time you wish to stop adding a new filter, or to remove a current filter, click the [C]lear Filter button. Note that the details of a certain filter are retained even when the filter is cleared.
+</p>
+<p style="text-align:justify">
+A trick to quickly sort the table is to choose the column to sort by, select a simple filter of *, then choose ascending or descending ordering.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/6-8.htm
===================================================================
--- /tags/start/gli/help/6-8.htm	(revision 13666)
+++ /tags/start/gli/help/6-8.htm	(revision 13666)
@@ -0,0 +1,217 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+6.8 Importing Previously Assigned Metadata
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section details the process for importing previously assigned metadata, and how to install parsers to handle various metadata types.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+While adding files
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#AI">Advanced instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+New parsers
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#QA">Problems and solutions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+"What if I accidentally import information to the wrong element?"
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+If metadata has been previously assigned to a certain file, and that metadata is in a form recognized by the Librarian Interface, the metadata will be imported when you add the file. This sometimes happens without any user intervention. However, if the Librarian Interface does not know how to map previously assigned metadata onto the metadata sets available in the collection, it prompts the user on how to do so.
+</p>
+<p style="text-align:justify">
+The prompt contains brief instructions on what must be done. Below the instruction box are three text fields.  The first shows the name of the metadata element that the Librarian Interface is importing, just as it appears in whatever source file the Librarian Interface has found. This field cannot be edited or changed. The second control allows you to choose what metadata set this element should map to, and contains all the sets available in the collection. The third control allows you to choose which metadata element the original element should map to if you intend to merge elements.
+</p>
+<p style="text-align:justify">
+When this display is created the Librarian Interface makes an educated guess about which element and set should be chosen. For instance, if the element being imported were called 'Publisher' and there existed only one element within the available sets called 'dls.Publisher', then the Librarian Interface would guess the metadata set to be the Development Library Subset (dls) and the element to be Publisher. However this doesn't always work as intended, so be sure to check the fields before committing any changes.
+</p>
+<p style="text-align:justify">
+The actions allowed are: [A]dd, [M]erge or [I]gnore. The add button allows you to add a new element to the chosen metadata set with the name as given in the original. This control is only enabled if there is no element of the same name within the chosen set. Merging maps the original element to the element chosen by the user. Finally, ignore skips importing any metadata which has an element as named in the original element field.
+</p>
+<p style="text-align:justify">
+Once you have advised the Librarian Interface how to import a certain piece of metadata from a certain source location, it retains this information for the lifetime of the collection.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="AI">Advanced Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+When attempting to find metadata, the Librarian Interface consults a series of dynamically loaded metadata file parsers for information about where to find metadata and how to read it once it is found. For instance, the directory '<gatherer install directory>\classes\org\greenstone\gatherer\msm\parsers' contains a file named 'GreenstoneMetadataParser.class'. This, and the other files starting with the same name, instructs the Librarian Interface how to read Greenstone metadata files, or metadata.xml files. Any new parser must implement the org.greenstone.gatherer.msm.MetadataParser interface. If this is done it is simply a matter of placing the file in the directory named above and restarting the Librarian Interface. Thus you are able to parse metadata from any source you have installed a parser for.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="QA">Problems And Solutions:</a>
+      </u>
+      <font size="3">
+      <i>
+<p style="text-align:justify">
+"What if I accidentally import information to the wrong element?"
+</p>
+
+      </i>
+<p style="text-align:justify">
+Currently the solution is the edit the profile.xml file located in the collection's metadata directory, to remove any erroneous entries. Once this is done, remove the files affected then re-import them. Eventually an 'import profile' editor will be included with the option of re-importing metadata.
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/7-0.htm
===================================================================
--- /tags/start/gli/help/7-0.htm	(revision 13666)
+++ /tags/start/gli/help/7-0.htm	(revision 13666)
@@ -0,0 +1,67 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+7.0 Designing Your Collection's Appearance
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+Once you have a set of marked-up files, it is time to consider how it will appear to users as a Greenstone collection.  What kind of information will be searchable?  What ways are provided to browse through the documents?  What languages are supported?  Where do the buttons appear on the page?  Many such features can be customized; this chapter shows how to do it.
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/7-1.htm
===================================================================
--- /tags/start/gli/help/7-1.htm	(revision 13666)
+++ /tags/start/gli/help/7-1.htm	(revision 13666)
@@ -0,0 +1,132 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+7.1 The 'Design' View
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section introduces you to the design view, and explains how to navigate between the various sub-views within this pane.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Choosing a design section
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+In Greenstone every collection has a collection configuration file, called collect.cfg, which controls most aspects of how the collection appears to the user. The Librarian Interface provides a graphical user interface to this file. It divides the kinds of commands that are available into different sections, each associated with a particular stage of the collection building or presentation.
+</p>
+<p style="text-align:justify">
+The design view is split into two halves. On the left is a list of different sub-views, and on the right are the controls associated with the current sub-view. To change to a different sub-view, click its name in the list. The right pane updates to reflect the change.
+</p>
+<p style="text-align:justify">
+When you change panes, the state of the previous pane is retained so that you can return to it later.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/7-2.htm
===================================================================
--- /tags/start/gli/help/7-2.htm	(revision 13666)
+++ /tags/start/gli/help/7-2.htm	(revision 13666)
@@ -0,0 +1,135 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+7.2 General Settings
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section explains how to review and alter the general settings associated with your collection.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+General settings
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+When you first switch to the design view, the general settings section is the one that is open. This is where the values provided during collection creation can be modified.
+</p>
+<p style="text-align:justify">
+At the top of the page is an instruction box, which appears for each of the different sections.  The brief list of instructions it contains is intended as a reminder of what functionality is available. The box can be scrolled using the scrollbar at the right edge, but is not itself editable.
+</p>
+<p style="text-align:justify">
+The first two fields below the instructions give the contact email of the collection's creator and maintainer, and must be valid email addresses. The next two controls are checkboxes. The next and last text boxes show details from the 'new collection' prompt, and can be modified if necessary.  The remaining control allows you to specify the URL path to the image that will be used as the icon for your collection from the Greenstone server's home page.
+</p>
+<p style="text-align:justify">
+The labels beside the text boxes (which most likely say 'English') show the language of the currently displayed values. Here, in conjunction with the Languages section, you can specify such things as the collection's title in several different languages. However, this is more easily done through the Translate prompt found in the Languages section.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/7-3.htm
===================================================================
--- /tags/start/gli/help/7-3.htm	(revision 13666)
+++ /tags/start/gli/help/7-3.htm	(revision 13666)
@@ -0,0 +1,168 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+7.3 Indexes
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section explains how to add and remove indexes, and how to set an index as the default one.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Add an index
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Remove an index
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Set default index
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Clear default index
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+We start by adding a new index. First, notice the instructions area at the top of the screen. Directly below it, on the left, are the controls used to add indexes.  To add an index, first provide a name for it by typing into the Index Name field. Next, select exactly what is to be indexed from the list of available sources. This list shows all the assigned metadata elements, as well as an option to use a full 'text' index. Having selected a source, now choose the level (i.e. what granularity) of the index, using the level selector. Once these details are complete (and assuming that there is not already an index with the same settings), the [A]dd Specified Index button becomes active. Click it to add the new index to the list of assigned indexes.
+</p>
+<p style="text-align:justify">
+To remove an index, select it from the list of indexes beneath the instructions and to the right, and click the [R]emove Selected Index button. The selected index will then be removed from the list.
+</p>
+<p style="text-align:justify">
+The default index is the one used on the collections search page. To set it, select the desired index from the list and click [S]et Default Index. The index's name will appear in the default index field directly below the assigned indexes list. Note that the default index field is not editable.
+</p>
+<p style="text-align:justify">
+To reset the default index click the [C]lear Default Index button and the default index field will become blank.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/7-4.htm
===================================================================
--- /tags/start/gli/help/7-4.htm	(revision 13666)
+++ /tags/start/gli/help/7-4.htm	(revision 13666)
@@ -0,0 +1,247 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+7.4 Sub-collections
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section describes how to create sub-collections within a collection, and how to create indexes upon these sub-collections.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Sub-collection controls
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Add a sub-collection
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Remove a sub-collection
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#AI">Advanced instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Sub-index controls
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Add a sub-index
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Remove a sub-index
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Set default sub-index
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Clear default sub-index
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+The Sub-collections feature allows you to group together all documents in a collection for which a specified metadata value matches a given pattern.  Within this section are two related views, chosen by clicking the appropriate tab on the tabbed pane. The Sub-collection Controls are discussed here, while the Sub-index Controls are relegated to the 'advanced topics' below.
+</p>
+<p style="text-align:justify">
+To add a new sub-collection, first give it a name by typing into the name field. Next, choose what part of the documents must match in order to belong to this sub-collection. You can choose any metadata, or the name of the file in question. Next, enter a regular expression that will be used in the match.  You can toggle between [I]ncluding documents that match the filter, or e[X]cluding them.  Finally, you can specify flags to be set while matching. These may be any of the standard PERL regular expression flags, such as 'i' for case-insensitive matching; alternatively just leave this field blank. Once you have filled out these fields, click on the [A]dd New Sub-collection button to add the sub-collection to the list. This list contains the sub-collection commands exactly as they appear in the collection configuration file.
+</p>
+<p style="text-align:justify">
+To remove a sub-collection, select it from the list of assigned sub-collections and click [R]emove Selected Sub-collection.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="AI">Advanced Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+Once you have a sub-collection you can instruct Greenstone to build indexes specifically for that sub-collection, or for a group of sub-collections.  To do this, click on the Sub-index Controls tab. The centre of the pane changes to show two lists, a field and four buttons. The upper list shows all currently assigned Sub-collections. Below it is a list of groupings for which you can build indexes. The field shows the current default sub-collection sub-index. Note that sub-indexes are not the same as indexes.
+</p>
+<p style="text-align:justify">
+To assign a sub-index, select the desired sub-collection or sub-collections from the upper list, using multiple selection methods as necessary. Now click [A]dd Selected As New Sub-index, and a new grouping for the selected sub-collections will appear in the assigned sub-indexes.
+</p>
+<p style="text-align:justify">
+Remove an existing sub-index group be first selecting it from the sub-index list, then clicking the [R]emove Selected Sub-index.
+</p>
+<p style="text-align:justify">
+You can make a particular sub-index the default by selecting it from the list of sub-indexes, then click [S]et Default Sub-index.  The grouping of the selected sub-index will appear in the default sub-index field.
+</p>
+<p style="text-align:justify">
+To clear the default sub-index, click [C]lear Default Sub-index.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/7-5.htm
===================================================================
--- /tags/start/gli/help/7-5.htm	(revision 13666)
+++ /tags/start/gli/help/7-5.htm	(revision 13666)
@@ -0,0 +1,222 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+7.5 Languages
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section details how multilingual support is defined by entries in the collection configuration file, and shows how to modify such settings using the Language section sub-view.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Language controls
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Add language
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Remove language
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Set default language
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Clear default language
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#AI">Advanced instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Translate assigned text fragments
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+Directly below the instruction text area is the control used to select a language. To the right is a list of currently supported languages and a field showing the default. At the bottom are four buttons for manipulating assignments.
+</p>
+<p style="text-align:justify">
+To add a new language to those we wish to publish a collection in, first select the desired language from the Language to add ComboBox control. These values come from a file called language.dat in the Librarian Interface's install directory. Once a language is chosen, press [A]dd Language to add it to the list of supported languages.
+</p>
+<p style="text-align:justify">
+Removing language support is just as easy. Select the language you wish to remove from the list, then click [R]emove Language.
+</p>
+<p style="text-align:justify">
+The default language is set by selecting it from the list of supported languages, then clicking [S]et Default Language.  The name of the chosen language will appear in the default language field.
+</p>
+<p style="text-align:justify">
+To reset the default language, click [C]lear Default Language. 
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="AI">Advanced Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+There is one remaining button, [T]ranslate Assigned Text Fragment. This opens a new prompt box containing three entry areas and a list titled 'Affected Features' on the left. If you select a feature from this list, the panels to the left will change.
+</p>
+<p style="text-align:justify">
+The top area, titled 'Assigned Languages', displays a table with two columns.  The first is the languages you have chosen to support; the second is the text fragment for the associated feature, in each language. The central text shows the fragment associated with the default language for this collection.  This may be blank, but is more likely to be a value that you entered previously. It is used as a reference when translating text fragments.  The bottom pane will remain blank until you select a row from the Assigned Languages table. Then, it shows the previous string entered for this language and this feature (if any). To add or edit the text for the chosen row, click within the editable bottom text area and type as desired. As you type, the fragment entry within the table changes to reflect what you have typed. However, the reference text area does not change, even if you are editing the default language text fragment. Changes to the default language will be committed only when you select a different language.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/7-6.htm
===================================================================
--- /tags/start/gli/help/7-6.htm	(revision 13666)
+++ /tags/start/gli/help/7-6.htm	(revision 13666)
@@ -0,0 +1,236 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+7.6 Plug-ins
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section describes how to configure the plug-ins used in your Greenstone collection. It explains how the Librarian Interface determines what plug-ins are available to the system, and how you specify what plug-ins to use, what parameters to pass to them, and in what order they occur.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Plug-in selection and configuration
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Add a plug-in
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Remove a plug-in
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Configure a plug-in
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Change plug-in order
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#AI">Advanced instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Custom configuration
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Rebuilding the plug-in database
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+As usual, a text area of instructions appears at the top of the view, with several controls below. The controls are split into a list of currently assigned plug-ins, and a group of 'Editing Controls' used to change the current plug-ins. Note that the list shows the plug-in commands as they will actually appear in the collection configuration file; thus you can review the arguments that are set.
+</p>
+<p style="text-align:justify">
+To add a plug-in, use the 'Select plug-in to add' ComboBox in the edit controls. Once a plug-in is selected, press the [A]dd Specified Plug-in button. A new dialog window will appear titled 'Configuring Arguments'; it is described in detail later. If you accept any changes you have made to the configuration, the prompt will vanish and the new plug-in will be added to the end of the 'movable' plug-ins within the assigned plug-in list.  Note that a plug-in may only occur in this list once only.
+</p>
+<p style="text-align:justify">
+To remove a plug-in, first select it from the assigned plug-ins list and then click [R]emove Selected Plug-in.
+</p>
+<p style="text-align:justify">
+Plug-ins are PERL scripts used to convert the collection's documents from one format to another, and for metadata extraction. Arguments can be used to configure what they do. To alter these arguments, select the desired plug-in from the assigned plug-in list, then click [C]onfigure Selected Plug-in. This will cause the 'Configuring Arguments' dialog window to appear again. This window has three parts, a text field for entering custom arguments, as explained below, a scrollable area from which particular arguments can be specified, and two buttons at the very bottom.
+</p>
+<p style="text-align:justify">
+The controls come in several flavours.  The most basic is a flag value, represented by a checkbox. Clicking the checkbox instructs the Librarian Interface to add the appropriate flag (for example, for a control named 'cover_image' the flag added is '-cover_image'). The second control is a text parameter argument comprising a checkbox and a text field. Click on the checkbox to enable this argument, then type appropriate text (regular expression, file path etc) in the box. The next type of control uses a ComboBox from which you can select one of a limited set of values. The final control is a variation on the ComboBox in which multiple selections can be made from a restricted list, and multiple parameters are passed with the argument. This control consists of a checkbox, to enable the argument, a ComboBox, from which the user selects desired values, two buttons 'add' and 'remove' which perform the corresponding functions, and a scrollable list of the values that are currently assigned for this argument. To add a value, select it from the ComboBox and click Add; to remove it, select it and click Remove. To review exactly what an argument does, leave the mouse pointer hovering over its name for a moment and a tool tip box will appear with description of the argument. When you have changed the configuration to suit, click the [O]k button to commit the changes and close the dialog, or [C]ancel to close the dialog without changing any plug-in arguments.
+</p>
+<p style="text-align:justify">
+The ordering of plug-ins in the list can be important.  The plug-ins in the list are executed in order. Two standard plug-ins, ArcPlug and RecPlug, are vital to the collection building process (ArcPlug identifies the collection files within the archives directory and RecPlug recursively traverses the collection tree.) These plug-ins are fixed in place at the end of the list -- denoted by a separator line. Only the plug-ins above the line can be moved.  To change the ordering, select the plug-in you want to move.  There are four options, Move To [T]op, Move [U]p, Move [D]own, and Move To [B]ottom, which re-order the list in corresponding ways.  You cannot move a component outside the list bounds, nor can you move a fixed component.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="AI">Advanced Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+When you enter the plug-in configuration dialog, the focus is initially on a text field called 'Custom Arguments'.  This field is provided because although the Librarian Interface does its best to determine the arguments supported by the plug-in, there may be cases when the user wants to specify special arguments. Any text in it is appended verbatim to the end of the plug-in command.
+</p>
+<p style="text-align:justify">
+Whenever a new plug-in becomes available for use, the Librarian Interface's plug-in database should be rebuilt. To do this, rename the file 'plugins.dat' to something like 'plugins.bak'.  The next time the Librarian Interface starts (or a collection is loaded), the plug-in database will be rebuilt automatically. This is done using a Greenstone PERL script called pluginfo.pl, with the special argument -xml, and requires the latest versions of the plugins and pluginfo to work properly (such files are available for download from the Librarian Interface site). This causes each plug-in found in the appropriate directories to be polled and asked what arguments it supports. The process is automatic and requires no further user intervention. If for any reason the process fails you can restore the original plugins database to get the Librarian Interface running again.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/7-7.htm
===================================================================
--- /tags/start/gli/help/7-7.htm	(revision 13666)
+++ /tags/start/gli/help/7-7.htm	(revision 13666)
@@ -0,0 +1,236 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+7.7 Classifiers
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section explains the process of assigning classifiers to your collection using the Librarian Interface.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Classifier selection and configuration
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Add a classifier
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Remove a classifier
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Configure a classifier
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#AI">Advanced instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Rebuilding the classifier database
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Custom classifiers
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+CustomAZList
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+The classifiers sub-view is just the same as the plug-in sub-view, except that there are no movement controls.
+</p>
+<p style="text-align:justify">
+To add a classifier, choose it from the ComboBox of known classifiers. Click the [A]dd Specified Classifier button, configure the classifier as desired, and commit the changes. Once this is done the new classifier appears in the list of assigned classifiers.
+</p>
+<p style="text-align:justify">
+To remove a classifier, select it from the list and click [R]emove Selected Classifier.
+</p>
+<p style="text-align:justify">
+To change the argument configuration of a classifier, select it from the list and press [C]onfigure Selected Classifier. Instructions for the 'Configuring Arguments' dialog are just the same as for plug-ins (except for custom classifiers explained below).
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="AI">Advanced Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+As for plug-ins, the Librarian Interface automatically rebuilds the classifier database when it detects that the old one is missing. This is how new standard classifiers can be registered with the Librarian Interface. Make sure that the classifier is in an appropriate directory, then rename the file 'classifiers.dat' from the Librarian Interface's installation directory. The next time the Librarian Interface requires classifier data it will rebuild the database, including the new classifier. Note that this is not the same as using custom classifiers. Also, as with plugins, you requires the latest classifier and clasinfo.pl to ensure the -xml flag is supported. Again such versions are available for download from the Librarian Interface site.
+</p>
+<p style="text-align:justify">
+A custom classifier is not a classifier in itself, but instead uses one or more basic classifiers to accomplish an advanced classification task. Custom classifiers are written in Java (not PERL like other classifiers) and dynamically loaded when the Librarian Interface is started.  To add a new custom classifier, place it in the classes/org/greenstone/gatherer/cdm/custom directory within the Librarian Interface install directory. (On a more technical note, custom classifiers implement the class org.greenstone.gatherer.cdm.CustomClassifier.)  Aside from the control differences explained below, custom classifiers are added, configured and removed in the same way as regular ones.
+</p>
+<p style="text-align:justify">
+The CustomAZList classifier, included with the Librarian Interface, is an example of a custom classifier. It allows users to build an AZList, and specify what the various letter ranges should be, e.g. #,A-F,G-P,Q-Z. This is accomplished by using a Hierarchy classifier behind the scenes, and adding hidden metadata to files in the collection.
+</p>
+<p style="text-align:justify">
+Custom classifiers provide a fully-customized set of controls for the purposes of configuration.  The CustomAZList classifier has a distinct dialog window, with two familiar fields, metadata and button name, at the top. Most of the pane is taken by several rows of buttons, each one matching a letter of the alphabet (with # for numbers), and a field below that shows the current letter ranges. Toggling a button on (so it appears selected) indicates the letter a range should begin with. There are two buttons at the bottom. [C]reate Classifier causes the custom classifier to be applied to the collection. While adding normal classifiers is just a case of writing an extra line in the collection configuration file, custom classifiers may require changes to the entire collection. Thus the creation of a custom classifier can take considerable time. Clicking the [C]ancel button rolls back any changes and prevents the CustomAZList from being added.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/7-8.htm
===================================================================
--- /tags/start/gli/help/7-8.htm	(revision 13666)
+++ /tags/start/gli/help/7-8.htm	(revision 13666)
@@ -0,0 +1,230 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+7.8 Format Settings
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section discusses the dark art of format settings, and how the Librarian Interface simplifies and enhances access to this powerful feature of Greenstone.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Format commands
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Static vs. Dynamic features
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Components
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Flag controls
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Format string editing
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Add format command
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Remove format command
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Editing assigned controls
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+Format strings are how you control the appearance of your collection, from where buttons appear on the screen to what colours and icons are displayed in the horizontal component of a DateList classifier. The procedure of using formatting commands can be quite daunting. 
+</p>
+<p style="text-align:justify">
+Below the instructions text area are several controls. The lower third of this control area depends on the type of feature you have selected, static vs. dynamic, flag vs. format string. The list at the top of the control area shows the format commands exactly as they appear in the collection configuration file.  The two ComboBoxes in the centre (one of which may be disabled, again depending on feature selection) allow you to specify what feature and component are to be formatted.
+</p>
+<p style="text-align:justify">
+When you begin choosing what feature you wish to format, keep in mind that there are two (overlapping) types of feature: static and dynamic. Static features are always the same and are used to format more general parts of the Greenstone collection, such as whether documents show a cover image, or whether the collection should behave differently as it is exclusively HTML based???. Dynamic features are ones based upon the classifiers assigned to the collection. When a selection is made from the 'Choose feature' ComboBox, the controls below change to reflect the current selection.
+</p>
+<p style="text-align:justify">
+If the selected feature is associated with a browsable result page, such as the dynamic features or the static feature Search, there are several components of this page that may be formatted separately. The possible components are DateList, HList, Invisible or VList. For an explanation of these components please refer to the Greenstone Developers Guide. You may also apply a format to an entire feature by choosing the blank entry from the ComboBox. You may also decide to set a default format for all components of a certain type by choosing a blank entry for the features ComboBox.
+</p>
+<p style="text-align:justify">
+Many of the static featured are 'flags' that have only an on or off state. Selecting one of these changes the controls at the button of the view to toggle buttons titled 'True' and 'False'. Selecting one deselects the other. For example, to format DocumentArrowsBottom so that next and previous arrows are show at the bottom of the page, select DocumentArrowsBottom from the feature ComboBox and then click on the True button to prepare the appropriate format command.
+</p>
+<p style="text-align:justify">
+The second type of control provides you with a text area title 'Edit Format String' with a sidebar of controls titled 'Variables'. I will not go into the details of how to write format strings; again, refer to the Greenstone Developers Guide.
+</p>
+<p style="text-align:justify">
+To make string editing simpler a list of predefined 'variables', including the current assigned metadata elements, are provided in a ComboBox.  To add a certain variable, first ensure that the editing caret is at the appropriate place within the text area. Next choose the variable from the ComboBox, then press [I]nsert to insert the variable at the cursor position.
+</p>
+<p style="text-align:justify">
+To add a new format command, fill out the details as explained above and click [A]dd Format. The new format command appears in the list of 'Currently Assigned Format Commands'.
+</p>
+<p style="text-align:justify">
+To remove a format command, select it from the list of assigned format commands, then click [R]emove Format.
+</p>
+<p style="text-align:justify">
+To alter an assigned format command, select it from the assigned commands list. The command's details appear in the editing controls; change them as desired. Any changes will be immediately reflected in the assigned command. Select a different feature to stop editing.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/7-9.htm
===================================================================
--- /tags/start/gli/help/7-9.htm	(revision 13666)
+++ /tags/start/gli/help/7-9.htm	(revision 13666)
@@ -0,0 +1,129 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+7.9 Metadata Sets
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section explains the metadata sets sub-view.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Available metadata sets
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+The metadata sets sub-view is read-only. It is used to review what metadata sets have been imported, and what elements are available within that set. It contains a brief set of instructions in a scrollable text area at the top of the page. There are very few other controls. Choose a set from the list of available metadata sets in order to see details of the elements in that set.
+</p>
+<p style="text-align:justify">
+The main use of this sub-view is to provide context for an element during a search and replace action, as described later in this help text.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/8-0.htm
===================================================================
--- /tags/start/gli/help/8-0.htm	(revision 13666)
+++ /tags/start/gli/help/8-0.htm	(revision 13666)
@@ -0,0 +1,67 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+8.0 Producing Your Collection
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+Your collection is ready to go. You have collected the documents for it, annotated them with metadata, designed how your collection will appear and specified what control options a user will have. You only have to feed this information to Greenstone and have it produce a finished collection. This chapter explains how to do this.
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/8-1.htm
===================================================================
--- /tags/start/gli/help/8-1.htm	(revision 13666)
+++ /tags/start/gli/help/8-1.htm	(revision 13666)
@@ -0,0 +1,103 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+8.1 The 'Create' View
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section explains the Create view, used to produce the collection.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+How to view the 'Create' viewOnly two tabs remained unexplored in the main control pane. The 'Create' view is used to create the collection by running the various Greenstone collection building scripts on the data you have collected and otherwise created. This is generally as straight-forward as clicking the [B]uild Collection button at the bottom of the screen. However, the Librarian Interface provides graphical access to Greenstone features, and here it is possible to customize the build process via arguments passed to Greenstone's PERL scripts. Moreover, this view is used to review details of previous attempts to build this collection, successful or otherwise.Apart from a brief status area stating the number of files in the collection and two buttons for building or canceling the building process, the bulk of this view is taken up by a group of controls titled 'Collection Import & Build Options'.  This contains a contents tree located to the left of the group, and a sub-view pane which reflects the currently chosen item in the tree.First look at the buttons at the bottom of the view. Clicking [B]uild Collection initiates the collection building process. The time this takes depends on the size of your collection and the number of indexes being created (for huge collections it can he hours). To cancel the building process at any time, click on the [C]ancel Build button. Cancelling the build does not damage the collection in any way other than ensuring that the remove_old flag is set within the import settings.
+                  </font>
+                  </a>
+                </td>
+              </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/8-2.htm
===================================================================
--- /tags/start/gli/help/8-2.htm	(revision 13666)
+++ /tags/start/gli/help/8-2.htm	(revision 13666)
@@ -0,0 +1,190 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+8.2 Import and Build Settings
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section explains how to access the various import and build settings.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+General settings
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Import settings
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Build settings
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+All settings
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Spinner control
+                  </font>
+                  </a>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+CheckList control
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+The first entry in the Option Groups tree is 'Import' settings. These settings are specific to the import script.  The second entry is 'Build' settings and apply only the build script.
+</p>
+<p style="text-align:justify">
+Controlling the various settings is done in the same way as for the 'Configuring Arguments' dialog window described under "7.6 Plug-ins". There are two previously unseen controls: the Spinner and the CheckList.
+</p>
+<p style="text-align:justify">
+The spinner is like a text field in that you can type into it and use the checkbox to enable it. However, it only accepts numeric values, and only within a certain range. For instance, the verbosity argument only accepts values in the range 0-3 inclusive. The two small up and down arrows at the far right of the field, reminiscent of the controls on a vertical scroll bar, allow you to increment or decrement the value in the field.
+</p>
+<p style="text-align:justify">
+The CheckList control is the same as that used when selecting what metadata sets to include in a new collection. After you have enabled it by clicking on the checkbox next to the argument's name, you select the active values by checking the checkbox next to them. The list is scrollable because there may be many entries to review. Note that the selection highlight has no real effect other than indicating the last entry whose state you changed.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/8-3.htm
===================================================================
--- /tags/start/gli/help/8-3.htm	(revision 13666)
+++ /tags/start/gli/help/8-3.htm	(revision 13666)
@@ -0,0 +1,126 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+8.3 Message Log
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section explains the message log.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Message log
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+The final entry in the Option Groups tree is 'Message Log'. This has little to do with the import and build arguments, but instead holds a record of the output generated from the Greenstone PERL scripts the last time the collection was built.  The text area contains three types of lines: Command, import.pl and buildcol.pl. Command lines show the exact command issued to the Greenstone script. Lines beginning 'import.pl>' come from the importing phase of the collection build, and those starting 'buildcol.pl' are from the building phase.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/8-4.htm
===================================================================
--- /tags/start/gli/help/8-4.htm	(revision 13666)
+++ /tags/start/gli/help/8-4.htm	(revision 13666)
@@ -0,0 +1,129 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+8.4 The 'Progress' View
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This section explains the building progress view.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Measuring progress
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+When you click the [B]uild Collection button, the view immediately changes. The controls described in the first section of this chapter are replaced by two progress bars and a text area. The progress bars indicate how much of the import phase, then build phase are complete. The current implementation shows only that work is progressing by offering an indeterminate progress bar (where a coloured band moves from left to right). Immediately below the progress bars in a scrollable text area which has the same general appearance as the Message Log explained in the previous section. However this log shows the messages for this build attempt. All of this display is for interest sake only.
+</p>
+<p style="text-align:justify">
+Whether the build process succeeds, fails or is cancelled, when it has completed the view returns to the original 'Create' view. If the attempt has failed, the Message Log will automatically be opened to the appropriate line.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/9-0.htm
===================================================================
--- /tags/start/gli/help/9-0.htm	(revision 13666)
+++ /tags/start/gli/help/9-0.htm	(revision 13666)
@@ -0,0 +1,67 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+9.0 Previewing Your Collection
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+This chapter explains how to use the final view, the 'Preview', to inspect the freshly built collection.
+</p>
+
+      </font>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/9-1.htm
===================================================================
--- /tags/start/gli/help/9-1.htm	(revision 13666)
+++ /tags/start/gli/help/9-1.htm	(revision 13666)
@@ -0,0 +1,126 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>The Gatherer - Help Pages</title>
+</head>
+<body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+<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="*">
+      <font face="Verdana" size="5">
+      <strong>
+9.1 The 'Preview' View
+      </strong>
+      </font>
+    </td>
+    <td align="center" width="15%">
+      <img height="45" src="gatherer_medium.gif" width="45">
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <font face="Verdana" size="3">
+<p style="text-align:justify">
+In this section we look at how to preview what our built collection will look like before we publish it.
+</p>
+
+      </font>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td align="center" colspan="3" width="100%">
+      <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+        <tr>
+          <td align="center">
+            <font face="Verdana" size="4">
+            <strong>
+            Contents
+            </strong>
+            </font>
+          </td>
+        </tr>
+        <tr>
+          <td>
+            <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+              <tr>
+                <td colspan="3">
+                  <font face="Verdana" size="4">
+                  <strong>
+<a href="#SI">Simple instructions</a>
+                  </strong>
+                  </a>
+                  </font>
+                </td>
+              </tr>
+              <tr>
+                <td>
+                  &nbsp;
+                </td>
+                <td colspan="2">
+                  <font face="Verdana" size="4">
+Browsing the preview
+                  </font>
+                  </a>
+                </td>
+              </tr>
+            </font>
+            </table>
+          </td>
+        </tr>
+      </table>
+    </td>
+  </tr>
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20">
+      <font face="Verdana" size="4">
+      <u>
+<a name="SI">Simple Instructions:</a>
+      </u>
+      <font size="3">
+<p style="text-align:justify">
+After you have successfully built a collection, the final tab on the main screen becomes enabled. This tab opens up the preview view so that you can inspect the collection. The pane itself is a simplified Web browser with initial page, and home page, set to the new collection's title page. The title page appears inside a scrollable pane. You can navigate the collection using standard hyperlink clicks. Some browser controls are also provided. The back button, far left, returns to the previous page, and become active as some as you click out of the initial screen. Next is the home button which returns you to the collection's title page. Third is the refresh button, which causes a new copy of the page to be loaded (rather than using an older version cached within the Librarian Interface), and is especially important for determining the effect of changing format statements.  Format statements are live: as soon as you change them Greenstone will begin to format the HTML pages returned using the new specifications. The forward button, on the far right, is used to 'undo' a back button click.
+</p>
+
+      </font>
+      </p>
+    </td>
+  </tr>
+</table>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+&nbsp;<br>
+</body>
+</html>
Index: /tags/start/gli/help/ghelp.dtd
===================================================================
--- /tags/start/gli/help/ghelp.dtd	(revision 13666)
+++ /tags/start/gli/help/ghelp.dtd	(revision 13666)
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Document Type Definition for Gatherer Help documents. -->
+<!ELEMENT HelpFile        (Header, Description, SimpleText?, AdvancedText?, QuestionBlock*)>
+<!ELEMENT Header          (#PCDATA)>
+<!ELEMENT Description     (Para*)>
+<!ELEMENT Contents        (SimpleSection?, AdvancedSection?, QuestionSection?)>
+<!ELEMENT Section         (SubSection+)>
+<!ATTLIST type            CDATA 's'>
+<!ELEMENT SubSection      (#PCDATA, SubSection*)>
+<!ELEMENT Text				  (Para*)>
+<!ATTLIST Text            
+          type            CDATA 's'>
+<!ELEMENT QuestionBlock   (Question, Para*)>
+<!ELEMENT Question        (#PCDATA)>
+<!ELEMENT Para            (#PCDATA)>
+
+
+
+
+
+
+
+
+
+
+
Index: /tags/start/gli/help/ghelp.xsl
===================================================================
--- /tags/start/gli/help/ghelp.xsl	(revision 13666)
+++ /tags/start/gli/help/ghelp.xsl	(revision 13666)
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<xsl:output method="html"/>
+
+<xsl:template match="HelpFile">
+  <html>
+  <head>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"></meta>
+  <title>The Gatherer - Help Pages</title>
+  </head>
+  <body bgcolor="#E0F0E0" link="#000000" vlink="#000000">
+  <table border="2" bgcolor="#B0D0B0" cellpadding="5" cellspacing="0" width="100%">
+  <xsl:apply-templates/>
+  </table>
+  </body>
+  </html>
+</xsl:template>
+
+<xsl:template match="Header">
+  <tr>
+  <td align="center" width="15%">
+  <img src="gatherer_medium.gif" height="45" width="45"/>
+  </td>
+  <td align="center" width="*">
+  <font face="Verdana" size="4">
+  <strong>
+  <xsl:apply-templates/>
+  </strong>
+  </font>
+  </td>
+  <td align="center" width="15%">
+  <img src="gatherer_medium.gif" height="45" width="45"/>
+  </td>
+  </tr>
+</xsl:template>
+
+<!-- The document description -->
+<xsl:template match="Description">
+  <tr bgcolor="#E0F0E0">
+  <td colspan="3" width="100%">
+  <font face="Verdana" size="3">
+  <xsl:apply-templates/>
+  </font>
+  </td>
+  </tr>
+</xsl:template>
+
+<!-- The document contents -->
+<xsl:template match="Contents">
+  <tr bgcolor="#E0F0E0">
+  <td align="center" colspan="3" width="100%">
+    <table border="2" cellpadding="2" width="480" bgcolor="#B0D0B0">
+    <tr>
+    <td align="center" width="100%">
+    <font face="Verdana" size="3">
+    <strong>Contents</strong>
+    </font>
+    </td>
+    </tr>
+    <tr>
+    <td width="100%">
+      <table background="gatherer.gif" bgcolor="#FFFFFF" border="0" cellpadding="2" width="100%">
+		<xsl:apply-templates/>
+		</table>
+    </td>
+    </tr>
+    </table>
+  </td>
+  </tr>
+</xsl:template>
+
+<xsl:template match="Section">
+  <tr>
+  <td colspan="3">
+  <font face="Verdana" size="3">
+  <strong>
+  <xsl:choose>
+    <xsl:when test="@type='s'">
+	 Simple instructions
+	 </xsl:when>
+    <xsl:when test="@type='a'">
+	 Advanced instructions
+	 </xsl:when>
+    <xsl:when test="@type='q'">
+	 Problems and Solutions
+	 </xsl:when>
+  </xsl:choose>
+  </strong>
+  </font>
+  </td>
+  </tr>
+  <xsl:apply-templates/>
+</xsl:template>
+
+<xsl:template match="SubSection/SubSection">
+  <tr>
+  <td width="10">
+  </td>
+  <td width="10">
+  </td>
+  <td>
+  <font face="Verdana" size="3">
+  <xsl:apply-templates/>
+  </font>
+  </td>
+  </tr>
+</xsl:template>
+
+<xsl:template match="SubSection">
+  <tr>
+  <td width="10">
+  </td>
+  <td colspan="2">
+  <font face="Verdana" size="3">
+  <xsl:apply-templates/>
+  </font>
+  </td>
+  </tr>
+</xsl:template>
+
+
+<!-- The text block -->
+<xsl:template match="Text">
+  <tr bgcolor="#E0F0E0">
+  <td colspan="3" width="100%">
+  <img src="gatherer_small.gif" height="20" width="20"/>
+  <font face="Verdana" size="3">
+  <u>
+  <xsl:choose>
+    <xsl:when test="@type='s'">
+	 Simple Instructions:
+	 </xsl:when>
+	 <xsl:when test="@type='a'">
+	 Advanced Instructions:
+	 </xsl:when>
+  </xsl:choose>
+  </u>
+  <xsl:apply-templates/>
+  </font>
+  </td>
+  </tr>
+</xsl:template>
+
+<xsl:template match="QuestionBlock">
+  <tr bgcolor="#E0F0E0">
+    <td colspan="3" width="100%">
+      <img height="20" src="gatherer_small.gif" width="20"/>
+      <font face="Verdana" size="3">
+      <u>Problems and Solutions:</u>
+		<xsl:apply-templates/>
+      </font>
+    </td>
+  </tr>
+</xsl:template>
+
+<xsl:template match="Question">
+  <p style="text-align:justify">
+  <i>
+  <xsl:apply-templates/>
+  </i>
+  </p>
+</xsl:template>
+
+<!-- A paragraph block -->
+<xsl:template match="Para">
+  <p style="text-align:justify">
+  <xsl:apply-templates/>
+  </p>
+</xsl:template>
+
+</xsl:stylesheet>
Index: /tags/start/gli/help/index.txt
===================================================================
--- /tags/start/gli/help/index.txt	(revision 13666)
+++ /tags/start/gli/help/index.txt	(revision 13666)
@@ -0,0 +1,48 @@
+ 1.0 "Introduction"
+ 1.1 "Of Mice and Menus"
+ 1.2 "How to Avoid Reading This Document"
+ 2.0 "Starting Off"
+ 2.1 "Creating a New Collection"
+ 2.2 "Saving Your Collection"
+ 2.3 "Opening an Existing Collection"
+ 3.0 "Hunting For Your Files"
+ 3.1 "The 'Hunt' View"
+ 4.0 "Downloading Chosen Files"
+ 4.1 "The 'Mirror' View
+ 5.0 "Collecting Files for Your Collection"
+ 5.1 "The 'Gather' View"
+ 5.2 "Creating Folders"
+ 5.3 "Adding Files"
+ 5.4 "Removing Files"
+ 5.5 "Filtering the Tree"
+ 6.0 "Enriching Your Collection with Metadata"
+ 6.1 "The 'Enrich' View"
+ 6.2 "Selecting Metadata Sets"
+ 6.3 "Adding New Metadata"
+ 6.4 "Adding Previously Defined Metadata"
+ 6.5 "Updating Metadata"
+ 6.6 "Removing Metadata"
+ 6.7 "Reviewing Assigned Metadata"
+ 6.8 "Importing Previously Assigned Metadata"
+ 7.0 "Designing Your Collection's Appearance"
+ 7.1 "The 'Design' View"
+ 7.2 "General Settings"
+ 7.3 "Indexes"
+ 7.4 "Sub-collections"
+ 7.5 "Languages"
+ 7.6 "Plug-ins"
+ 7.7 "Classifiers"
+ 7.8 "Format Settings"
+ 7.9 "Metadata Sets"
+ 8.0 "Producing Your Collection"
+ 8.1 "The 'Create' View"
+ 8.2 "Import and Build Settings"
+ 8.3 "Message Log"
+ 8.4 "The 'Progress' View"
+ 9.0 "Previewing Your Collection"
+ 9.1 "The 'Preview' View"
+10.0 "Miscellaneous"
+10.1 "Search And Replace"
+10.2 "Preferences"
+11.0 "Metadata Set and Profile Editing"
+11.1 "Edit Metadata Sets"
Index: /tags/start/gli/languages.dat
===================================================================
--- /tags/start/gli/languages.dat	(revision 13666)
+++ /tags/start/gli/languages.dat	(revision 13666)
@@ -0,0 +1,139 @@
+ENGLISH          EN     GERMANIC
+MAORI            MI     OCEANIC/INDONESIAN
+#AFAR             AA     HAMITIC
+#ABKHAZIAN        AB     IBERO-CAUCASIAN
+#AFRIKAANS        AF     GERMANIC
+#AMHARIC          AM     SEMITIC
+ARABIC           AR     SEMITIC
+#ASSAMESE         AS     INDIAN
+#AYMARA           AY     AMERINDIAN
+#AZERBAIJANI      AZ     TURKIC/ALTAIC
+#BASHKIR          BA     TURKIC/ALTAIC
+#BYELORUSSIAN     BE     SLAVIC
+#BULGARIAN        BG     SLAVIC
+#BIHARI           BH     INDIAN
+#BISLAMA          BI     [not given]
+#BENGALI(BANGLA)  BN     INDIAN
+#TIBETAN          BO     ASIAN
+#BRETON           BR     CELTIC
+#CATALAN          CA     ROMANCE
+#CORSICAN         CO     ROMANCE
+#CZECH            CS     SLAVIC
+#WELSH            CY     CELTIC
+#DANISH           DA     GERMANIC
+GERMAN           DE     GERMANIC
+#BHUTANI          DZ     ASIAN
+#GREEK            EL     LATIN/GREEK
+#ESPERANTO        EO     INTERNATIONAL AUX.
+SPANISH          ES     ROMANCE
+#ESTONIAN         ET     FINNO-UGRIC
+#BASQUE           EU     BASQUE
+#PERSIAN(FARSI)   FA     IRANIAN
+#FINNISH          FI     FINNO-UGRIC
+#FIJI             FJ     OCEANIC/INDONESIAN
+#FAROESE          FO     GERMANIC
+FRENCH           FR     ROMANCE
+#FRISIAN          FY     GERMANIC
+#IRISH            GA     CELTIC
+#SCOTS(GAELIC)    GD     CELTIC
+#GALICIAN         GL     ROMANCE
+#GUARANI          GN     AMERINDIAN
+#GUJARATI         GU     INDIAN
+#HAUSA            HA     NEGRO-AFRICAN
+HEBREW           HE     SEMITIC [*Changed 1989 from original ISO 639:1988, IW] 
+#HINDI            HI     INDIAN
+#CROATIAN         HR     SLAVIC
+#HUNGARIAN        HU     FINNO-UGRIC
+#ARMENIAN         HY     INDO-EUROPEAN (OTHER)
+#INTERLINGUA      IA     INTERNATIONAL AUX.
+#INTERLINGUE      IE     INTERNATIONAL AUX.
+#INUPIAK          IK     ESKIMO
+INDONESIAN       ID     OCEANIC/INDONESIAN [*Changed 1989 from original ISO 639:1988, IN] 
+#ICELANDIC        IS     GERMANIC
+ITALIAN          IT     ROMANCE
+#INUKTITUT        IU     [        ]
+#JAPANESE         JA     ASIAN
+#JAVANESE         JV     OCEANIC/INDONESIAN
+#GEORGIAN         KA     IBERO-CAUCASIAN
+#KAZAKH           KK     TURKIC/ALTAIC
+#GREENLANDIC      KL     ESKIMO
+#CAMBODIAN        KM     ASIAN
+#KANNADA          KN     DRAVIDIAN
+#KOREAN           KO     ASIAN
+#KASHMIRI         KS     INDIAN
+#KURDISH          KU     IRANIAN
+#KIRGHIZ          KY     TURKIC/ALTAIC
+#LATIN            LA     LATIN/GREEK
+#LINGALA          LN     NEGRO-AFRICAN
+#LAOTHIAN         LO     ASIAN
+#LITHUANIAN       LT     BALTIC
+#LATVIAN(LETTISH) LV     BALTIC
+#MALAGASY         MG     OCEANIC/INDONESIAN
+#MACEDONIAN       MK     SLAVIC
+#MALAYALAM        ML     DRAVIDIAN
+#MONGOLIAN        MN     [not given]
+#MOLDAVIAN        MO     ROMANCE
+#MARATHI          MR     INDIAN
+#MALAY            MS     OCEANIC/INDONESIAN
+#MALTESE          MT     SEMITIC
+#BURMESE          MY     ASIAN
+#NAURU            NA     [not given]
+#NEPALI           NE     INDIAN
+DUTCH            NL     GERMANIC
+#NORWEGIAN        NO     GERMANIC
+#OCCITAN          OC     ROMANCE
+#AFAN(OROMO)      OM     HAMITIC
+#ORIYA            OR     INDIAN
+#PUNJABI          PA     INDIAN
+#POLISH           PL     SLAVIC
+#PASHTO(PUSHTO)   PS     IRANIAN
+#PORTUGUESE       PT     ROMANCE
+#QUECHUA          QU     AMERINDIAN
+#RHAETO-ROMANCE   RM     ROMANCE
+#KURUNDI          RN     NEGRO-AFRICAN
+#ROMANIAN         RO     ROMANCE
+RUSSIAN          RU     SLAVIC
+#KINYARWANDA      RW     NEGRO-AFRICAN
+#SANSKRIT         SA     INDIAN
+#SINDHI           SD     INDIAN
+#SANGHO           SG     NEGRO-AFRICAN
+#SERBO-CROATIAN   SH     SLAVIC
+#SINGHALESE       SI     INDIAN
+#SLOVAK           SK     SLAVIC
+#SLOVENIAN        SL     SLAVIC
+#SAMOAN           SM     OCEANIC/INDONESIAN
+#SHONA            SN     NEGRO-AFRICAN
+#SOMALI           SO     HAMITIC
+#ALBANIAN         SQ     INDO-EUROPEAN (OTHER)
+#SERBIAN          SR     SLAVIC
+#SISWATI          SS     NEGRO-AFRICAN
+#SESOTHO          ST     NEGRO-AFRICAN
+#SUNDANESE        SU     OCEANIC/INDONESIAN
+#SWEDISH          SV     GERMANIC
+#SWAHILI          SW     NEGRO-AFRICAN
+#TAMIL            TA     DRAVIDIAN
+#TELUGU           TE     DRAVIDIAN
+#TAJIK            TG     IRANIAN
+#THAI             TH     ASIAN
+#TIGRINYA         TI     SEMITIC
+#TURKMEN          TK     TURKIC/ALTAIC
+#TAGALOG          TL     OCEANIC/INDONESIAN
+#SETSWANA         TN     NEGRO-AFRICAN
+#TONGA            TO     OCEANIC/INDONESIAN
+#TURKISH          TR     TURKIC/ALTAIC
+#TSONGA           TS     NEGRO-AFRICAN
+#TATAR            TT     TURKIC/ALTAIC
+#TWI              TW     NEGRO-AFRICAN
+#UIGUR            UG     [       ]
+#UKRAINIAN        UK     SLAVIC
+#URDU             UR     INDIAN
+#UZBEK            UZ     TURKIC/ALTAIC
+#VIETNAMESE       VI     ASIAN
+#VOLAPUK          VO     INTERNATIONAL AUX.
+#WOLOF            WO     NEGRO-AFRICAN
+#XHOSA            XH     NEGRO-AFRICAN
+#YIDDISH          YI     GERMANIC [*Changed 1989 from original ISO 639:1988, JI] 
+#YORUBA           YO     NEGRO-AFRICAN
+#ZHUANG           ZA     [       ]
+#CHINESE          ZH     ASIAN
+#ZULU             ZU     NEGRO-AFRICAN
Index: /tags/start/gli/lib/greenaqua/greenaqua.xml
===================================================================
--- /tags/start/gli/lib/greenaqua/greenaqua.xml	(revision 13666)
+++ /tags/start/gli/lib/greenaqua/greenaqua.xml	(revision 13666)
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+
+<skinlf-themepack require="0.3">
+	<property name="JDesktopPane.backgroundEnabled" value="false" />
+	<property name="ScrollBar.alternateLayout" value="true" />
+	<property name="PopupMenu.animation" value="false"/>
+	
+	<font name="Global" value="Tahoma,0,11"/>
+
+	<skin>
+		<skin url="gtk/gtkrc"></skin>
+		<skin url="kde/kde.themerc"></skin>
+	</skin>
+
+</skinlf-themepack>
Index: /tags/start/gli/lib/greenaqua/gtk/gtkrc
===================================================================
--- /tags/start/gli/lib/greenaqua/gtk/gtkrc	(revision 13666)
+++ /tags/start/gli/lib/greenaqua/gtk/gtkrc	(revision 13666)
@@ -0,0 +1,1144 @@
+include "testgtkrc2"
+
+module_path ".:/home/raster/themes"
+
+style "eventbox" {
+  bg_pixmap[NORMAL] = "<parent>"
+  bg_pixmap[INSENSITIVE] = "<parent>"
+  bg_pixmap[PRELIGHT] = "<parent>"
+  bg_pixmap[SELECTED] = "<parent>"
+  bg_pixmap[ACTIVE] = "<parent>"
+}
+
+class "GtkEventBox" style "eventbox"
+
+#
+# Buttons
+#
+
+style "checkradiobutton" {
+  engine "pixmap" {
+    image 
+      {
+        function        = FLAT_BOX
+	recolorable     = TRUE
+	file            = "button5.png"
+	border          = { 10,5,5,10 }
+	stretch         = TRUE
+      }
+  }
+}
+
+class "GtkRadioButton" style "checkradiobutton"
+class "GtkCheckButton" style "checkradiobutton"
+
+style "togglebutton"
+{
+   engine "pixmap" {
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	shadow          = IN
+	file            = "button2.png"
+	border          = { 5,5,10,10 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	shadow          = OUT
+	file            = "button1.png"
+	border          = { 10,10,10,10 }
+	stretch         = TRUE
+      }
+  }
+}
+
+class "GtkToggleButton" style "togglebutton"
+
+style "button"
+{
+  bg[NORMAL] = "#ffffff"
+
+  engine "pixmap" 
+    {
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	state           = NORMAL
+	shadow          = OUT
+	file            = "button5.png"
+	border          = { 10,5,5,10 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	state           = PRELIGHT
+	shadow          = OUT
+	file            = "button9.png"
+	border          = { 10,5,5,10 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	state           = NORMAL
+	shadow          = IN
+	file            = "button4.png"
+	border          = { 10,5,5,10 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	state           = INSENSITIVE
+	shadow          = IN
+	file            = "button3.png"
+	border          = { 10,5,5,10 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	state           = INSENSITIVE
+	shadow          = OUT
+	file            = "button3.png"
+	border          = { 10,5,5,10 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	state           = SELECTED
+	shadow          = IN
+	file            = "button4.png"
+	border          = { 10,5,5,10 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	state           = ACTIVE
+	shadow          = IN
+	file            = "button0.png"
+	border          = { 10,5,5,10 }
+	stretch         = TRUE
+      }
+   }
+}
+
+class "GtkButton" style "button"
+
+style "clist"
+{
+  bg[PRELIGHT] = "#eeeeee"
+  fg[PRELIGHT] = "#000000"
+  base[NORMAL] = "#eeeeee"
+}
+
+class "GtkCList" style "clist"
+
+style "notebook"
+{
+  engine "pixmap" 
+    {
+    image 
+      {
+        function        = EXTENSION
+	recolorable     = TRUE
+	state           = ACTIVE
+	file            = "notebook2.png"
+	border          = { 10, 10, 10, 10 }
+	stretch         = TRUE
+	gap_side	= BOTTOM
+      }
+    image 
+      {
+        function        = EXTENSION
+	recolorable     = TRUE
+	state           = ACTIVE
+	file            = "notebook5.png"
+	border          = { 10, 10, 10, 10 }
+	stretch         = TRUE
+	gap_side	= TOP
+      }
+    image 
+      {
+        function        = EXTENSION
+	recolorable     = TRUE
+	state           = ACTIVE
+	file            = "notebook6.png"
+	border          = { 10, 10, 10, 10 }
+	stretch         = TRUE
+	gap_side	= RIGHT
+      }
+    image 
+      {
+        function        = EXTENSION
+	recolorable     = TRUE
+	state           = ACTIVE
+	file            = "notebook6.png"
+	border          = { 10, 10, 10, 10 }
+	stretch         = TRUE
+	gap_side	= LEFT
+      }
+    image 
+      {
+        function        = EXTENSION
+	recolorable     = TRUE
+	file            = "notebook3.png"
+	border          = { 10, 10, 10, 10 }
+	stretch         = TRUE
+	gap_side        = BOTTOM
+      }
+    image 
+      {
+        function        = EXTENSION
+	recolorable     = TRUE
+	file            = "notebook4.png"
+	border          = { 10, 10, 10, 10 }
+	stretch         = TRUE
+	gap_side        = TOP
+      }
+    image 
+      {
+        function        = EXTENSION
+	recolorable     = TRUE
+	file            = "notebook7.png"
+	border          = { 10, 10, 10, 10 }
+	stretch         = TRUE
+	gap_side        = RIGHT
+      }
+    image 
+      {
+        function        = EXTENSION
+	recolorable     = TRUE
+	file            = "notebook7.png"
+	border          = { 10, 10, 10, 10 }
+	stretch         = TRUE
+	gap_side        = LEFT
+     }
+#
+# How to draw boxes with a gap on one side (ie the page of a notebook)
+#
+    image 
+      {
+        function        = BOX_GAP
+	recolorable     = TRUE
+	file            = "notebook6.png"
+	border          = { 10, 10, 10, 10 }
+	stretch         = TRUE
+        gap_file        = "gap_top.png"
+        gap_border      = { 0, 0, 0, 0 }
+        gap_start_file  = "gap_top_start.png"
+        gap_start_border= { 2, 0, 0, 0 }
+        gap_end_file    = "gap_top_end.png"
+        gap_end_border  = { 0, 2, 0, 0 }
+	gap_side        = TOP
+      }
+    image 
+      {
+        function        = BOX_GAP
+	recolorable     = TRUE
+	file            = "notebook6.png"
+	border          = { 10, 10, 10, 10 }
+	stretch         = TRUE
+        gap_file        = "gap_bottom.png"
+        gap_border      = { 0, 0, 0, 0 }
+        gap_start_file  = "gap_bottom_start.png"
+        gap_start_border= { 2, 0, 0, 0 }
+        gap_end_file    = "gap_bottom_end.png"
+        gap_end_border  = { 0, 2, 0, 0 }
+	gap_side        = BOTTOM
+      }
+    image 
+      {
+        function        = BOX_GAP
+	recolorable     = TRUE
+	file            = "notebook6.png"
+	border          = { 10, 10, 10, 10 }
+	stretch         = TRUE
+        gap_file        = "gap_left.png"
+        gap_border      = { 0, 0, 0, 0 }
+        gap_start_file  = "gap_left_start.png"
+        gap_start_border= { 0, 0, 2, 0 }
+        gap_end_file    = "gap_left_end.png"
+        gap_end_border  = { 0, 0, 0, 2 }
+	gap_side        = LEFT
+      }
+    image 
+      {
+        function        = BOX_GAP
+	recolorable     = TRUE
+	file            = "notebook6.png"
+	border          = { 10, 10, 10, 10 }
+	stretch         = TRUE
+        gap_file        = "gap_right.png"
+        gap_border      = { 0, 0, 0, 0 }
+        gap_start_file  = "gap_right_start.png"
+        gap_start_border= { 0, 0, 2, 0 }
+        gap_end_file    = "gap_right_end.png"
+        gap_end_border  = { 0, 0, 0, 2 }
+	gap_side        = RIGHT
+      }
+#
+# How to draw the box of a notebook when it isnt attached to a tab
+#
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	file            = "notebook6.png"
+	border          = { 10, 10, 10, 10 }
+	stretch         = TRUE
+	gap_side	= TOP
+      }
+  }
+}
+
+class "GtkNotebook" style "notebook"
+
+style "menu"
+{
+  engine "pixmap" {
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	file            = "background.png"
+	border          = { 3, 3, 3, 3 }
+	stretch         = FALSE
+	overlay_file    = "menu_shadow.png"
+	overlay_border  = { 3, 3, 3, 3 }
+	overlay_stretch = TRUE
+      }
+  }
+}
+
+class "GtkMenu" style "menu"
+
+style "menuitem"
+{
+  engine "pixmap" {
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	file            = "menu_selected.png"
+	border          = { 0, 0, 0, 0 }
+	stretch         = TRUE
+      }
+  }
+}
+
+class "GtkMenuItem" style "menuitem"
+
+style "menubar"
+{
+  engine "pixmap" {
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	file            = "background.png"
+	border          = { 3, 3, 3, 3 }
+	stretch         = FALSE
+      }
+  }
+}
+
+class "GtkMenuBar" style "menubar"
+
+style "optionmenu"
+{
+  engine "pixmap" {
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	file            = "option_menu2.png"
+	border          = { 12, 32, 2, 3 }
+	stretch         = TRUE
+      }
+  }
+}
+
+class "GtkOptionMenu" style "optionmenu"
+
+style "progressbar"
+{
+  engine "pixmap" 
+    {
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "bar"
+	file            = "button6.png"
+	border          = { 5, 5, 5, 5 }
+	stretch         = TRUE
+      }
+    image
+      {
+        function        = BOX
+        recolorable     = TRUE
+        detail          = "trough"
+        file            = "button5.png"
+        border          = { 10, 10, 10, 10 }
+        stretch         = TRUE
+        orientation     = HORIZONTAL
+      }
+    }
+}
+
+class "GtkProgressBar" style "progressbar"
+class "GtkBar" style "progressbar"
+
+style "ruler"
+{
+  engine "pixmap" {
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "vruler"
+	file            = "button5.png"
+	border          = { 2, 2, 2, 2 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "hruler"
+	file            = "button5.png"
+	border          = { 2, 2, 2, 2 }
+	stretch         = TRUE
+      }
+  }
+}
+
+class "GtkRuler" style "ruler"
+
+style "item" 
+{
+  engine "pixmap" {
+    image 
+      {
+        function        = FLAT_BOX
+	recolorable     = TRUE
+	state           = INSENSITIVE
+	file            = "button3.png"
+	border          = { 10, 5, 5, 10 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = FLAT_BOX
+	recolorable     = TRUE
+	file            = "button6.png"
+	border          = { 10, 5, 5, 10 }
+	stretch         = TRUE
+      }
+  }
+}
+
+class "GtkTreeItem" style "item"
+class "GtkListItem" style "item"
+
+style "window" 
+{
+  engine "pixmap" {
+    image 
+      {
+	function        = FLAT_BOX
+	recolorable     = TRUE
+	file            = "background.png"
+	stretch         = FALSE
+      }
+  }
+}
+
+class "GtkWindow" style "window"
+
+style "curve"
+{
+  engine "pixmap" {
+    image 
+      {
+        function        = FLAT_BOX
+	recolorable     = TRUE
+	detail          = "curve_bg"
+	file            = "button1.png"
+	border          = { 2, 2, 2, 2 }
+	stretch         = TRUE
+      }
+  }
+}
+
+class "GtkCurve" style "curve"
+
+style "scrollbar"
+{
+  engine "pixmap" 
+  {
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "slider"
+	state           = PRELIGHT
+	file            = "scrollbar_horiz1.png"
+	border          = { 15, 15, 2, 2 }
+	stretch         = TRUE
+	orientation     = HORIZONTAL
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "slider"
+	state           = NORMAL
+	file            = "scrollbar_horiz1.png"
+	border          = { 13, 12, 2, 2 }
+	stretch         = TRUE
+	orientation     = HORIZONTAL
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "slider"
+	state           = PRELIGHT
+	file            = "scrollbar_vert1.png"
+	border          = { 2, 2, 15, 15 }
+	stretch         = TRUE
+	orientation     = VERTICAL
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "slider"
+	file            = "scrollbar_vert1.png"
+	border          = { 2, 2, 15, 15 }
+	stretch         = TRUE
+	orientation     = VERTICAL
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "trough"
+	file            = "vtrough.png"
+	border          = { 3, 3, 23, 23 }
+	stretch         = TRUE
+	orientation     = VERTICAL
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "trough"
+	file            = "htrough.png"
+	border          = { 23, 23, 3, 3 }
+	stretch         = TRUE
+	orientation     = HORIZONTAL
+      }
+  }
+}
+
+class "GtkScrollbar" style "scrollbar"
+
+style "range"
+{
+  engine "pixmap" {
+    image 
+      {
+        function        = SLIDER
+	recolorable     = TRUE
+	file            = "slider_hth2.png"
+	border          = { 2, 2, 5, 5 }
+	stretch         = FALSE
+	overlay_file    = "slider_horiz1.png"
+	overlay_border  = { 5, 5, 5, 5 }
+	overlay_stretch = FALSE
+	orientation     = HORIZONTAL
+      }
+    image 
+      {
+        function        = SLIDER
+	recolorable     = TRUE
+	file            = "slider_vth2.png"
+	border          = { 5, 5, 2, 2 }
+	stretch         = FALSE
+	overlay_file    = "slider_vert1.png"
+	overlay_border  = { 5, 5, 5, 5 }
+	overlay_stretch = FALSE
+	orientation     = VERTICAL
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "trough"
+	file            = "slider_vth1.png"
+	border          = { 5, 2, 2, 2 }
+	stretch         = TRUE
+	orientation     = VERTICAL
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "trough"
+	file            = "slider_hth1.png"
+	border          = { 2, 2, 5, 2 }
+	stretch         = TRUE
+	orientation     = HORIZONTAL
+      }
+  }
+}
+class "GtkRange" style "range"
+
+style "default"
+{
+  font = "-*-helvetica-medium-r-normal--10-*-*-*-*-*-*-*"
+  fg[NORMAL]      = { 0.00, 0.00, 0.00 }
+  fg[PRELIGHT]    = { 0.00, 0.00, 0.00 }
+  fg[ACTIVE]      = { 0.00, 0.00, 0.00 }
+  fg[SELECTED]    = { 0.00, 0.00, 0.00 }
+  fg[INSENSITIVE] = { 0.70, 0.70, 0.70 }
+  bg[NORMAL]      = "#ffffff"
+  bg[PRELIGHT]    = "#ffffff"
+  bg[ACTIVE]      = "#ffffff"
+  bg[INSENSITIVE] = "#ffffff"
+  bg[SELECTED]    = "#6ba5e7"
+  base[NORMAL]    = "#ffffff"
+  engine "pixmap" 
+  {
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "slider"
+	state           = PRELIGHT
+	file            = "scrollbar_horiz1.png"
+	border          = { 15, 15, 2, 2 }
+	stretch         = TRUE
+	orientation     = HORIZONTAL
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "slider"
+	state           = NORMAL
+	file            = "scrollbar_horiz1.png"
+	border          = { 13, 12, 2, 2 }
+	stretch         = TRUE
+	orientation     = HORIZONTAL
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "slider"
+	state           = PRELIGHT
+	file            = "scrollbar_vert1.png"
+	border          = { 2, 2, 15, 15 }
+	stretch         = TRUE
+	orientation     = VERTICAL
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "slider"
+	file            = "scrollbar_vert1.png"
+	border          = { 2, 2, 15, 15 }
+	stretch         = TRUE
+	orientation     = VERTICAL
+      }
+#
+# Any trough....
+#
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "trough"
+	file            = "vtrough.png"
+	border          = { 3, 3, 23, 23 }
+	stretch         = TRUE
+	orientation     = VERTICAL
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "trough"
+#        file            = "button5.png"
+#        border          = { 10, 10, 10, 10 }
+	file            = "htrough.png"
+	border          = { 23, 23, 3, 3 }
+	stretch         = TRUE
+	orientation     = HORIZONTAL
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "bar"
+	file            = "scrollbar_horiz2.png"
+	border          = { 36, 36, 2, 2 }
+	stretch         = TRUE
+      }
+#
+# Handlebox
+#
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "handlebox_bin"
+	file            = "button1.png"
+	border          = { 10, 10, 10, 10 }
+	stretch         = TRUE
+      }
+#
+# Paned widget
+#
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "paned"
+	file            = "button5.png"
+	border          = { 10, 5, 5, 10 }
+	stretch         = TRUE
+      }
+#
+# Tooltips
+#
+    image 
+      {
+        function        = FLAT_BOX
+	recolorable     = TRUE
+	detail          = "tooltip"
+	file            = "button5.png"
+	border          = { 10, 5, 5, 10 }
+	stretch         = TRUE
+      }
+#      
+# Selected text in entries, text widget, lists and trees      
+#
+    image 
+      {
+        function        = FLAT_BOX
+	recolorable     = TRUE
+	state           = INSENSITIVE
+	detail          = "selected"
+	file            = "button5.png"
+	border          = { 10, 5, 5, 10 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = FLAT_BOX
+	recolorable     = TRUE
+	detail          = "selected"
+	file            = "button2.png"
+	border          = { 10, 5, 5, 10 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = FLAT_BOX
+	recolorable     = TRUE
+	state           = INSENSITIVE
+	detail          = "text"
+	file            = "button5.png"
+	border          = { 10, 5, 5, 10 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = FLAT_BOX
+	recolorable     = TRUE
+	detail          = "text"
+	file            = "button6.png"
+	border          = { 4, 4, 3, 3 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = FLAT_BOX
+	recolorable     = TRUE
+	detail          = "viewportbin"
+	file            = "background.png"
+	stretch         = FALSE
+      }
+#
+# Arrows for all occasions
+#
+    image 
+      {
+        function        = ARROW
+	recolorable     = TRUE
+	state           = NORMAL
+	file            = "arrow_up1.png"
+	stretch         = FALSE
+	arrow_direction = UP
+      }
+    image 
+      {
+        function        = ARROW
+	recolorable     = TRUE
+	state           = PRELIGHT
+	file            = "arrow_up1.png"
+	stretch         = FALSE
+	arrow_direction = UP
+      }
+    image 
+      {
+        function        = ARROW
+	recolorable     = TRUE
+        shadow          = IN
+	file            = "arrow_up1.png"
+	stretch         = FALSE
+	arrow_direction = UP
+      }
+
+    image 
+      {
+        function        = ARROW
+	recolorable     = TRUE
+	state           = NORMAL
+	file            = "arrow_down1.png"
+	stretch         = TRUE
+	arrow_direction = DOWN
+      }
+    image 
+      {
+        function        = ARROW
+	recolorable     = TRUE
+	state           = PRELIGHT
+	file            = "arrow_down1.png"
+	stretch         = TRUE
+	arrow_direction = DOWN
+      }
+    image 
+      {
+        function        = ARROW
+	recolorable     = TRUE
+        shadow          = IN
+	file            = "arrow_down1.png"
+	stretch         = TRUE
+	arrow_direction = DOWN
+      }
+
+    image 
+      {
+        function        = ARROW
+	recolorable     = TRUE
+	state           = NORMAL
+	file            = "arrow_left1.png"
+	stretch         = FALSE
+	arrow_direction = LEFT
+      }
+    image 
+      {
+        function        = ARROW
+	recolorable     = TRUE
+	state           = PRELIGHT
+	file            = "arrow_left1.png"
+	stretch         = FALSE
+	arrow_direction = LEFT
+      }
+    image 
+      {
+        function        = ARROW
+	recolorable     = TRUE
+        shadow          = IN
+	file            = "arrow_left1.png"
+	stretch         = FALSE
+	arrow_direction = LEFT
+      }
+
+    image 
+      {
+        function        = ARROW
+	recolorable     = TRUE
+	state           = NORMAL
+	file            = "arrow_right1.png"
+	stretch         = FALSE
+	arrow_direction = RIGHT
+      }
+    image 
+      {
+        function        = ARROW
+	recolorable     = TRUE
+	state           = PRELIGHT
+	file            = "arrow_right1.png"
+	stretch         = FALSE
+	arrow_direction = RIGHT
+      }
+    image 
+      {
+        function        = ARROW
+	recolorable     = TRUE
+        shadow          = IN
+	file            = "arrow_right1.png"
+	stretch         = FALSE
+	arrow_direction = RIGHT
+      }
+#
+# Hline and Vline widgets
+#
+    image 
+      {
+        function        = HLINE
+	recolorable     = TRUE
+	file            = "hline.png"
+	border          = { 0, 0, 1, 1 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = VLINE
+	recolorable     = TRUE
+	file            = "vline.png"
+	border          = { 1, 1, 0, 0 }
+	stretch         = TRUE
+      }
+#
+# Check marks
+#
+    image 
+      {
+        function        = CHECK
+	recolorable     = TRUE
+	shadow          = OUT
+	overlay_file    = "check1.png"
+	overlay_stretch = FALSE
+      }
+    image 
+      {
+        function        = CHECK
+	recolorable     = TRUE
+	shadow          = IN
+	overlay_file    = "check2.png"
+	overlay_stretch = FALSE
+      }
+#
+# Option marks
+#
+    image 
+      {
+        function        = OPTION
+	recolorable     = TRUE
+	shadow          = OUT
+	overlay_file    = "option1.png"
+	overlay_border  = { 0, 0, 0, 0 }
+	overlay_stretch = FALSE
+      }
+    image 
+      {
+        function        = OPTION
+	recolorable     = TRUE
+	shadow          = IN
+	overlay_file    = "option2.png"
+	overlay_border  = { 0, 0, 0, 0 }
+	overlay_stretch = FALSE
+      }
+#
+# The "tab" on the OptionMenu
+#
+#    image 
+#      {
+#        function        = TAB
+#	recolorable     = TRUE
+#	overlay_file    = "button2.png"
+#	overlay_stretch = FALSE
+#      }
+#
+# Fun with Scrollbars
+#      
+    image 
+      {
+        function        = SLIDER
+	recolorable     = TRUE
+	file            = "scrollbar_horiz1.png"
+	border          = { 13, 12, 2, 2 }
+	stretch         = TRUE
+	orientation     = HORIZONTAL
+      }
+    image 
+      {
+        function        = SLIDER
+	recolorable     = TRUE
+	file            = "scrollbar_vert1.png"
+	border          = { 2, 2, 13, 12 }
+	stretch         = TRUE
+	orientation     = VERTICAL
+      }
+#
+# The handle on Handleboxes
+#
+    image 
+      {
+        function        = HANDLE
+	recolorable     = TRUE
+	file            = "button5.png"
+	border          = { 10, 5, 5, 10 }
+	stretch         = TRUE
+	overlay_file    = "handle_vert_thumb.png"
+	overlay_border  = { 0, 0, 0, 0 }
+	overlay_stretch = FALSE
+	orientation     = VERTICAL
+      }
+#
+# The background for entry widgets
+#
+    image 
+      {
+	function        = FLAT_BOX
+	recolorable     = TRUE
+	state           = INSENSITIVE
+        detail          = "entry_bg"
+	file            = "entry2.png"
+	border          = { 3, 3, 3, 3 }
+	stretch         = TRUE
+      }
+    image 
+      {
+	function        = FLAT_BOX
+	recolorable     = TRUE
+        detail          = "entry_bg"
+	file            = "entry1.png"
+	border          = { 3, 3, 3, 3 }
+	stretch         = TRUE
+      }
+#
+# How to draw the focus around a widget 
+#
+    image 
+      {
+        function        = FOCUS
+	recolorable     = TRUE
+	overlay_file    = "focus.png"
+	overlay_border  = { 4, 4, 4, 4 }
+	overlay_stretch = TRUE
+      }
+#
+# How to draw shadows in general
+#
+    image 
+      {
+        function        = SHADOW
+	recolorable     = TRUE
+	shadow          = IN
+	file            = "shadow2.png"
+	border          = { 2, 2, 2, 2 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = SHADOW
+	recolorable     = TRUE
+	shadow          = OUT
+	file            = "shadow1.png"
+	border          = { 2, 2, 2, 2 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = SHADOW
+	recolorable     = TRUE
+	shadow          = ETCHED_IN
+	file            = "frame1.png"
+	border          = { 2, 2, 2, 2 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = SHADOW
+	recolorable     = TRUE
+	shadow          = ETCHED_OUT
+	file            = "frame2.png"
+	border          = { 2, 2, 2, 2 }
+	stretch         = TRUE
+      }
+#
+# How to draw shadows with a gap on one side
+#
+    image 
+      {
+        function        = SHADOW_GAP
+	recolorable     = TRUE
+	file            = "frame_gap.png"
+	border          = { 2, 2, 2, 2 }
+	stretch         = FALSE
+	gap_start_file  = "frame_gap_top_start.png"
+	gap_start_border= { 0, 0, 1, 1 }
+	gap_end_file    = "frame_gap_top_end.png"
+	gap_end_border  = { 0, 2, 1, 1 }
+	gap_side        = TOP
+      }
+#
+# Some defaults as to how to draw boxes if they haven't already been covered
+#
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "hruler"
+	file            = "button5.png"
+	border          = { 10, 10, 10, 10 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	detail          = "vruler"
+	file            = "button5.png"
+	border          = { 10, 10, 10, 10 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	shadow          = IN
+	file            = "button2.png"
+	border          = { 10, 10, 10, 10 }
+	stretch         = TRUE
+      }
+    image 
+      {
+        function        = BOX
+	recolorable     = TRUE
+	file            = "button7.png"
+	border          = { 10, 10, 10, 10 }
+	stretch         = TRUE
+      }
+   }
+}
+
+
+# common default
+class "GtkWidget" style "default"
+
+
Index: /tags/start/gli/lib/greenaqua/kde/kde.themerc
===================================================================
--- /tags/start/gli/lib/greenaqua/kde/kde.themerc	(revision 13666)
+++ /tags/start/gli/lib/greenaqua/kde/kde.themerc	(revision 13666)
@@ -0,0 +1,111 @@
+[General]
+name=kAqua
+author=Jeff Marlow
+email=jeff@bluegenesis.com
+homepage=http://jeff.marlow.net
+description=Apple's Aqua (Mac OS X)\nThanks to Dangeruss for the Graphics\nThanks to Steve Jobs for the Vision
+version=1.03
+
+[Panel]
+background=panelx.PNG
+
+[File Manager]
+# Kfm's common background image:
+backgroundImage=kfmbackground.PNG
+# Kfm's colors:
+htmlBackground=255,255,255
+htmlForeground=0,0,0
+htmlLinks=35,107,200
+htmlFollowedLinks=25,73,144
+
+[Konsole]
+schema=MacOSX.schema
+background=bondiblue.PNG
+
+[Display]
+CommonDesktop=True
+Wallpaper0=aquabackground.PNG
+WallpaperMode0=Scaled
+Wallpaper1=aquabackground.PNG
+WallpaperMode1=Scaled
+Wallpaper2=aquabackground.PNG
+WallpaperMode2=Scaled
+Wallpaper3=aquabackground.PNG
+WallpaperMode3=Scaled
+Wallpaper4=aquabackground.PNG
+WallpaperMode4=Scaled
+Wallpaper5=aquabackground.PNG
+WallpaperMode5=Scaled
+Wallpaper6=aquabackground.PNG
+WallpaperMode6=Scaled
+Wallpaper7=aquabackground.PNG
+WallpaperMode7=Scaled
+RootIconTextStyle=1
+RootIconTextForeground=0,0,27
+RootIconTextBackground=240,247,255
+
+[Colors]
+foreground=0,0,0
+selectForeground=255,255,255
+activeBlend=53,99,144
+selectBackground=25,73,144
+inactiveBackground=128,128,128
+contrast=7
+background=233,237,247
+activeBackground=233,233,233
+inactiveBlend=192,192,192
+inactiveForeground=103,105,145
+activeForeground=0,0,0
+windowForeground=0,0,0
+windowBackground=255,255,255
+terminalForeground=black
+terminalBackground=ghostwhite
+
+[Window Titlebar]
+CloseButton=close.PNG
+CloseDownButton=close_down.PNG
+CloseInactiveButton=close_disabled.PNG
+
+MaximizeButton=maximize.PNG
+MaximizeDownButton=maximizedown.PNG
+MaximizeInactiveButton=maximize_disabled.PNG
+
+MinimizeButton=iconify.PNG
+MinimizeDownButton=iconify_down.PNG
+MinimizeInactiveButton=iconify_disabled.PNG
+
+MenuButton=menu.PNG
+
+StickyButton=sticky.PNG
+StickyDownButton=stickydown.PNG
+TitlebarPixmapActive=activetitle.PNG
+TitlebarPixmapInactive=inactivetitle.PNG
+PixmapUnderTitleText=yes
+TitleFrameShaded=no
+TitleAlignment=middle
+
+[Window Border]
+
+[Window Button Layout]
+ButtonA=Off
+ButtonB=Maximize
+ButtonC=Iconify
+ButtonD=Off
+ButtonE=Off
+ButtonF=Close
+
+[Window Gimmick]
+
+[Sounds]
+WindowShadeDown=RollUp.wav
+WindowShadeUp=RollUp.wav
+WindowClose=Close.wav
+
+[Icons]
+PanelGo=go.PNG:mini-go.PNG
+inode/directory=folder_blue.PNG:mini_folder_blue.PNG
+
+[Extra Icons]
+Extra1=netscape.PNG:mini-netscape.PNG
+Extra2=icq.PNG:mini-icq.PNG
+
Index: /tags/start/gli/metadata/dls.mds
===================================================================
--- /tags/start/gli/metadata/dls.mds	(revision 13666)
+++ /tags/start/gli/metadata/dls.mds	(revision 13666)
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE MetadataSet [
+
+  <!-- The outer tag of any metadata set. Contains some number of elements.             -->
+  <!-- @param contact     A contact address for the creator.                            -->
+  <!-- @param creator     The name of the entity resposibly for this set.               -->
+  <!-- @param family      The namespace of this metadata set.                           -->
+  <!-- @param lastchanged The full date, user name and machine name of the last editor. --> 
+  <!--   uses the form:                                                                 -->
+  <!--   Day Mon(th) dd hh:mm:ss yyyy '-' <username> on <machine>                       -->
+  <!-- @param namespace   The abbreviated namespace of this metadata set.               -->
+  <!ELEMENT MetadataSet (Element+)>
+  <!ATTLIST MetadataSet
+				contact     CDATA #REQUIRED
+				creator     CDATA #REQUIRED
+            family      CDATA #REQUIRED
+				lastchanged CDATA #REQUIRED
+				namespace   CDATA #REQUIRED>
+
+  <!-- The name of a metadata set. Is language specific. -->
+  <!ELEMENT Name (#PCDATA)>
+  <!ATTLIST Name
+            language CDATA "en">
+
+  <!-- The description of a metadata set. Is language specific. -->
+  <!ELEMENT Description (#PCDATA)>
+  <!ATTLIST Description
+            language CDATA "en">
+
+  <!-- An element in the metadata set. -->
+  <!ELEMENT Element (Attribute*,OptionList?)>
+  <!ATTLIST Element
+            name       CDATA #REQUIRED
+				occurances CDATA "0">
+
+  <!-- Each element has several attribute children. -->
+  <!ELEMENT Attribute (#PCDATA)>
+  <!ATTLIST Attribute
+            name CDATA #REQUIRED>
+
+  <!-- For listing predefined values for this element. -->
+  <!ELEMENT OptionList (Value+)>
+  <!ATTLIST OptionList
+            restricted (true|false) "false">
+]>
+
+<MetadataSet 
+contact = "nzdl.org"
+creator = "New Zealand Digital Libraries Project: Greenstone"
+family = "Development Library Subset"
+lastchanged = "Tue Jun 04 10:35:30 2002 - jmt12 on blackbird"
+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="AZList">
+    <Attribute name="comment" language="en">Not the same as an AZList classifier.</Attribute>
+    <Attribute name="definition" language="en">A customizable AZList based on document titles.</Attribute>
+    <Attribute name="identifier" language="en">AZList</Attribute>
+	 <Attribute name="version">1.0</Attribute>
+  </Element>
+
+  <Element name="Keyword">
+    <Attribute name="comment" language="en">Informal.</Attribute>
+    <Attribute name="definition" language="en">A more specific indication of what the resourse can be used for.</Attribute>
+    <Attribute name="identifier" language="en">Keyword</Attribute>
+	 <Attribute name="version">1.0</Attribute>
+  </Element>
+
+  <Element name="Language">
+    <Attribute name="comment" language="en">Language.</Attribute>
+    <Attribute name="definition" language="en">The language of this resource.</Attribute>
+    <Attribute name="identifier" language="en">Language</Attribute>
+    <Attribute name="version">1.0</Attribute>
+  </Element>
+
+  <Element name="Organization">
+    <Attribute name="comment" language="en">Organization.</Attribute>
+    <Attribute name="definition" language="en">The organization responisble for producing this resource.</Attribute>
+    <Attribute name="identifier" language="en">Organization</Attribute>
+    <Attribute name="version">1.0</Attribute>
+  </Element>
+
+  <Element name="Subject">
+    <Attribute name="comment" language="en">Currently uses a hierarchy.</Attribute>
+    <Attribute name="definition" language="en">The subject of this resource.</Attribute>
+    <Attribute name="identifier" language="en">Subject</Attribute>
+    <Attribute name="version">1.0</Attribute>
+  </Element>
+
+  <Element name="Title">
+    <Attribute name="comment" language="en">Title.</Attribute>
+    <Attribute name="definition" language="en">The title of this resource.</Attribute>
+    <Attribute name="identifier" language="en">Title</Attribute>
+    <Attribute name="version">1.0</Attribute>
+  </Element>
+
+</MetadataSet>
+
Index: /tags/start/gli/metadata/dublin.mds
===================================================================
--- /tags/start/gli/metadata/dublin.mds	(revision 13666)
+++ /tags/start/gli/metadata/dublin.mds	(revision 13666)
@@ -0,0 +1,228 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE MetadataSet [
+
+  <!-- The outer tag of any metadata set. Contains some number of elements.             -->
+  <!-- @param contact     A contact address for the creator.                            -->
+  <!-- @param creator     The name of the entity resposibly for this set.               -->
+  <!-- @param family      The name of this sets family.                                 -->
+  <!-- @param lastchanged The full date, user name and machine name of the last editor. --> 
+  <!--   uses the form:                                                                 -->
+  <!--   Day Mon(th) dd hh:mm:ss yyyy '-' <username> on <machine>                       -->
+  <!-- @param namespace   The namespace of this metadata set.                           -->
+  <!ELEMENT MetadataSet ((Name|Description|Element)+)>
+  <!ATTLIST MetadataSet
+				contact     CDATA #REQUIRED
+				creator     CDATA #REQUIRED
+				description CDATA #REQUIRED
+            family      CDATA #REQUIRED
+				lastchanged CDATA #REQUIRED
+            name        CDATA #REQUIRED
+				namespace   CDATA #REQUIRED>
+
+  <!-- The name of a metadata set. Is language specific. -->
+  <!ELEMENT Name (#PCDATA)>
+  <!ATTLIST Name
+            language CDATA "en">
+
+  <!-- The description of a metadata set. Is language specific. -->
+  <!ELEMENT Description (#PCDATA)>
+  <!ATTLIST Description
+            language CDATA "en">
+
+  <!-- An element in the metadata set. -->
+  <!ELEMENT Element (Attribute*,OptionList?)>
+  <!ATTLIST Element
+            name       CDATA #REQUIRED
+				language   CDATA #IMPLIED
+				occurances CDATA "0">
+
+  <!-- Each element has several attribute children. -->
+  <!ELEMENT Attribute (#PCDATA)>
+  <!ATTLIST Attribute
+            name CDATA #REQUIRED>
+
+  <!-- For listing predefined values for this element. -->
+  <!ELEMENT OptionList (Value+)>
+  <!ATTLIST OptionList
+            restricted (true|false) "false">
+]>
+
+<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" 
+>
+
+  <Name language="en">Basic Dublin Core 1.1</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>
+
+  <Element name="Title">
+    <Attribute name="identifier" language="en">Title</Attribute>
+    <Attribute name="definition" language="en">A name given to the resource.</Attribute>
+    <Attribute name="version">1.1</Attribute>
+    <Attribute name="registration_authority" language="en">Dublin Core Metadata Initiative</Attribute>
+    <Attribute name="obligation">Optional</Attribute>
+    <Attribute name="datatype">Charater String</Attribute>
+    <Attribute name="maximum_occurance">Unlimited</Attribute>
+    <Attribute name="comment">Typically, a Title will be a name by which the resource is formally known.</Attribute>
+	 <Attribute name="lastchanged">Tue Jun 04 10:35:30 2002 - jmt12 on blackbird</Attribute>
+  </Element>
+
+  <Element name="Creator">
+    <Attribute name="identifier" language="en">Creator</Attribute>
+    <Attribute name="definition" language="en">An entity primarily responsible for making the content of the resource.</Attribute>
+    <Attribute name="version">1.1</Attribute>
+    <Attribute name="registration_authority" language="en">Dublin Core Metadata Initiative</Attribute>
+    <Attribute name="obligation">Optional</Attribute>
+    <Attribute name="datatype">Charater String</Attribute>
+    <Attribute name="maximum_occurance">Unlimited</Attribute>
+    <Attribute name="comment" language="en">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>
+  </Element>
+
+  <Element name="Subject and Keywords">
+    <Attribute name="identifier" language="en">Subject</Attribute>
+    <Attribute name="definition" language="en">The topic of the content of the resource.</Attribute>
+    <Attribute name="version">1.1</Attribute>
+    <Attribute name="registration_authority" language="en">Dublin Core Metadata Initiative</Attribute>
+    <Attribute name="obligation">Optional</Attribute>
+    <Attribute name="datatype">Charater String</Attribute>
+    <Attribute name="maximum_occurance">Unlimited</Attribute>
+    <Attribute name="comment" language="en">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>
+  </Element>
+
+  <Element name="Description">
+    <Attribute name="identifier" language="en">Description</Attribute>
+    <Attribute name="definition" language="en">An account of the content of the resource.</Attribute>
+    <Attribute name="version">1.1</Attribute>
+    <Attribute name="registration_authority" language="en">Dublin Core Metadata Initiative</Attribute>
+    <Attribute name="obligation">Optional</Attribute>
+    <Attribute name="datatype">Charater String</Attribute>
+    <Attribute name="maximum_occurance">Unlimited</Attribute>
+    <Attribute name="comment" language="en">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>
+  </Element>
+
+  <Element name="Publisher">
+    <Attribute name="identifier" language="en">Publisher</Attribute>
+    <Attribute name="definition" language="en">An entity responsible for making the resource available.</Attribute>
+    <Attribute name="version">1.1</Attribute>
+    <Attribute name="registration_authority" language="en">Dublin Core Metadata Initiative</Attribute>
+    <Attribute name="obligation">Optional</Attribute>
+    <Attribute name="datatype">Charater String</Attribute>
+    <Attribute name="maximum_occurance">Unlimited</Attribute>
+    <Attribute name="comment" language="en">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>
+  </Element>
+
+  <Element name="Contributor">
+    <Attribute name="identifier" language="en">Contributor</Attribute>
+    <Attribute name="definition" language="en">An entity responsible for making contributions to the content of the resource.</Attribute>
+    <Attribute name="version">1.1</Attribute>
+    <Attribute name="registration_authority" language="en">Dublin Core Metadata Initiative</Attribute>
+    <Attribute name="obligation">Optional</Attribute>
+    <Attribute name="datatype">Charater String</Attribute>
+    <Attribute name="maximum_occurance">Unlimited</Attribute>
+    <Attribute name="comment" language="en">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>
+  </Element>
+
+  <Element name="Date">
+    <Attribute name="identifier" language="en">Date</Attribute>
+    <Attribute name="definition" language="en">A date associated with an event in the life cycle of the resource.</Attribute>
+    <Attribute name="version">1.1</Attribute>
+    <Attribute name="registration_authority" language="en">Dublin Core Metadata Initiative</Attribute>
+    <Attribute name="obligation">Optional</Attribute>
+    <Attribute name="datatype">Charater String</Attribute>
+    <Attribute name="maximum_occurance">Unlimited</Attribute>
+    <Attribute name="comment" language="en">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>
+  </Element>
+
+  <Element name="Resource Type">
+    <Attribute name="identifier" language="en">Type</Attribute>
+    <Attribute name="definition" language="en">The nature or genre of the content of the resource.</Attribute>
+    <Attribute name="version">1.1</Attribute>
+    <Attribute name="registration_authority" language="en">Dublin Core Metadata Initiative</Attribute>
+    <Attribute name="obligation">Optional</Attribute>
+    <Attribute name="datatype">Charater String</Attribute>
+    <Attribute name="maximum_occurance">Unlimited</Attribute>
+    <Attribute name="comment" language="en">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>
+  </Element>
+
+  <Element name="Format">
+    <Attribute name="identifier" language="en">Format</Attribute>
+    <Attribute name="definition" language="en">The physical or digital manifestation of the resource.</Attribute>
+    <Attribute name="version">1.1</Attribute>
+    <Attribute name="registration_authority" language="en">Dublin Core Metadata Initiative</Attribute>
+    <Attribute name="obligation">Optional</Attribute>
+    <Attribute name="datatype">Charater String</Attribute>
+    <Attribute name="maximum_occurance">Unlimited</Attribute>
+    <Attribute name="comment" language="en">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>
+
+  <Element name="Resource Identifier">
+    <Attribute name="identifier" language="en">Identifier</Attribute>
+    <Attribute name="definition" language="en">An unambiguous reference to the resource within a given context.</Attribute>
+    <Attribute name="version">1.1</Attribute>
+    <Attribute name="registration_authority" language="en">Dublin Core Metadata Initiative</Attribute>
+    <Attribute name="obligation">Optional</Attribute>
+    <Attribute name="datatype">Charater String</Attribute>
+    <Attribute name="maximum_occurance">Unlimited</Attribute>
+    <Attribute name="comment" language="en">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="Source">
+    <Attribute name="identifier" language="en">Source</Attribute>
+    <Attribute name="definition" language="en">A Reference to a resource from which the present resource is derived.</Attribute>
+    <Attribute name="version">1.1</Attribute>
+    <Attribute name="registration_authority" language="en">Dublin Core Metadata Initiative</Attribute>
+    <Attribute name="obligation">Optional</Attribute>
+    <Attribute name="datatype">Charater String</Attribute>
+    <Attribute name="maximum_occurance">Unlimited</Attribute>
+    <Attribute name="comment" language="en">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>
+  </Element>
+
+  <Element name="Language">
+    <Attribute name="identifier" language="en">Language</Attribute>
+    <Attribute name="definition" language="en">A language of the intellectual content of the resource.</Attribute>
+    <Attribute name="version">1.1</Attribute>
+    <Attribute name="registration_authority" language="en">Dublin Core Metadata Initiative</Attribute>
+    <Attribute name="obligation">Optional</Attribute>
+    <Attribute name="datatype">Charater String</Attribute>
+    <Attribute name="maximum_occurance">Unlimited</Attribute>
+    <Attribute name="comment" language="en">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, 'en' for English, 'fr' for French, or 'en-uk' for English used in the United Kingdom.</Attribute>
+  </Element>
+
+  <Element name="Relation">
+    <Attribute name="identifier" language="en">Relation</Attribute>
+    <Attribute name="definition" language="en">A reference to a related resource.</Attribute>
+    <Attribute name="version">1.1</Attribute>
+    <Attribute name="registration_authority" language="en">Dublin Core Metadata Initiative</Attribute>
+    <Attribute name="obligation">Optional</Attribute>
+    <Attribute name="datatype">Charater String</Attribute>
+    <Attribute name="maximum_occurance">Unlimited</Attribute>
+    <Attribute name="comment" language="en">Recommended best practice is to reference the resource by means of a string or number conforming to a formal identification system.</Attribute>
+  </Element>
+
+  <Element name="Coverage">
+    <Attribute name="identifier" language="en">Coverage</Attribute>
+    <Attribute name="definition" language="en">The extent or scope of the content of the resource.</Attribute>
+    <Attribute name="version">1.1</Attribute>
+    <Attribute name="registration_authority" language="en">Dublin Core Metadata Initiative</Attribute>
+    <Attribute name="obligation">Optional</Attribute>
+    <Attribute name="datatype">Charater String</Attribute>
+    <Attribute name="maximum_occurance">Unlimited</Attribute>
+    <Attribute name="comment" language="en">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>
+
+  <Element name="Rights Management">
+    <Attribute name="identifier" language="en">Rights</Attribute>
+    <Attribute name="definition" language="en">Information about rights held in and over the resource.</Attribute>
+    <Attribute name="version">1.1</Attribute>
+    <Attribute name="registration_authority" language="en">Dublin Core Metadata Initiative</Attribute>
+    <Attribute name="obligation">Optional</Attribute>
+    <Attribute name="datatype">Charater String</Attribute>
+    <Attribute name="maximum_occurance">Unlimited</Attribute>
+    <Attribute name="comment" language="en">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>
+  </Element>
+
+</MetadataSet>
Index: /tags/start/gli/metadata/extracted.mds
===================================================================
--- /tags/start/gli/metadata/extracted.mds	(revision 13666)
+++ /tags/start/gli/metadata/extracted.mds	(revision 13666)
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE MetadataSet [
+
+  <!-- The outer tag of any metadata set. Contains some number of elements.             -->
+  <!-- @param contact     A contact address for the creator.                            -->
+  <!-- @param creator     The name of the entity resposibly for this set.               -->
+  <!-- @param family      The name of this sets family.                                 -->
+  <!-- @param lastchanged The full date, user name and machine name of the last editor. --> 
+  <!--   uses the form:                                                                 -->
+  <!--   Day Mon(th) dd hh:mm:ss yyyy '-' <username> on <machine>                       -->
+  <!-- @param namespace   The namespace of this metadata set.                           -->
+  <!ELEMENT MetadataSet ((Name|Description|Element)+)>
+  <!ATTLIST MetadataSet
+				contact     CDATA #REQUIRED
+				creator     CDATA #REQUIRED
+				description CDATA #REQUIRED
+            family      CDATA #REQUIRED
+				lastchanged CDATA #REQUIRED
+            name        CDATA #REQUIRED
+				namespace   CDATA #REQUIRED>
+
+  <!-- The name of a metadata set. Is language specific. -->
+  <!ELEMENT Name (#PCDATA)>
+  <!ATTLIST Name
+            language CDATA "en">
+
+  <!-- The description of a metadata set. Is language specific. -->
+  <!ELEMENT Description (#PCDATA)>
+  <!ATTLIST Description
+            language CDATA "en">
+
+  <!-- An element in the metadata set. -->
+  <!ELEMENT Element (Attribute*,OptionList?)>
+  <!ATTLIST Element
+            name       CDATA #REQUIRED
+				occurances CDATA "0">
+
+  <!-- Each element has several attribute children. -->
+  <!ELEMENT Attribute (#PCDATA)>
+  <!ATTLIST Attribute
+            name CDATA #REQUIRED>
+
+  <!-- For listing predefined values for this element. -->
+  <!ELEMENT OptionList (Value+)>
+  <!ATTLIST OptionList
+            restricted (true|false) "false">
+]>
+
+<MetadataSet 
+contact     = "nzdl.org"
+creator     = "New Zealand Digital Libraries Project: Greenstone"
+family      = "Extracted Greenstone"
+lastchanged = "Tue May 20 10:30:32 2003 - jmt12 on narya"
+namespace   = "" 
+>
+
+  <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 name="comment" language="en">Not always available.</Attribute>
+    <Attribute name="definition" language="en">The encoding of the imported document as extracted by Greenstone.</Attribute>
+    <Attribute name="identifier" language="en">Encoding</Attribute>
+  </Element>
+
+  <Element name="Language">
+    <Attribute name="comment" language="en">Not always available.</Attribute>
+    <Attribute name="definition" language="en">The language of the imported document as extracted by Greenstone.</Attribute>
+    <Attribute name="identifier" language="en">Language</Attribute>
+  </Element>
+
+  <Element name="Source">
+    <Attribute name="comment" language="en">Hidden in the Librarian Interface as it already shown by the various file trees.</Attribute>
+    <Attribute name="definition" language="en">The filename of the document imported by Greenstone.</Attribute>
+    <Attribute name="identifier" language="en">Source</Attribute>
+  </Element>
+
+  <Element name="Title">
+    <Attribute name="comment" language="en">Not always available.</Attribute>
+    <Attribute name="definition" language="en">The title of the imported document as extracted by Greenstone.</Attribute>
+    <Attribute name="identifier" language="en">Title</Attribute>
+  </Element>
+
+</MetadataSet>
Index: /tags/start/gli/src/org/greenstone/gatherer/Configuration.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/Configuration.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/Configuration.java	(revision 13666)
@@ -0,0 +1,555 @@
+package org.greenstone.gatherer;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+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.Message;
+import org.greenstone.gatherer.gui.Coloring;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.greenstone.gatherer.util.GURL;
+import org.greenstone.gatherer.util.Utility;
+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 {
+	 /** The path (or url) to the webserver which is serving the Greenstone collection. */
+	 public String exec_path = null;
+	 /** The path to the Greenstone Suite installation directory. */
+	 public String gsdl_path = "";
+    /** The path to the PERL executable, up to and including Perl.exe. */
+    public String perl_path = "";
+	 /** The password for the proxy server indicated above. */
+	 public String proxy_pass = null;
+	 /** The username for the proxy server indicated above. */
+	 public String proxy_user = null;
+	 /** The screen size of the desktop the Gatherer will be displayed on. */
+	 public Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
+	 /** Collection level configuration (which in some cases overrides general configuration. */
+	 private Document collection_config;
+	 /** The general configuration settings. */
+	 private Document general_config;
+	 private int cache_hit = 0;
+	 private int cache_miss = 0;
+	 private URL exec_address = null;
+	 /** The string identifying an argument's name attribute. */
+	 static final private String ARGUMENT_NAME = "name";
+	 /** The name of the general Gatherer configuration file. */
+	 static final private String CONFIG_XML = "config.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";
+	 /** 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 an information Element within the Other subtree. */
+	 static final private String OTHER_INFO = "Info";
+	 /** The name of the general Gatherer configuration template. */
+	 static final private String TEMPLATE_CONFIG_XML = "xml/config.xml";
+	 /** The first of two patterns used during tokenization, this pattern handles a comma separated list. */
+	 static final private String TOKENIZER_PATTERN1 = " ,\n\t";
+	 /** The second of two patterns used during tokenization, this pattern handles an underscore separated list. */
+	 static final private String TOKENIZER_PATTERN2 = "_\n\t";
+	 /** Constructor.
+	  * @param gsdl_path The path to the Greenstone directory as a <strong>String</strong>.
+	  * @param exec_path A <strong>String</strong> containing the path or url to the webserver serving the greenstone collections.
+	  * @param perl_path The path to the PERL executable, as a <strong>String</strong>.
+	  */
+	 public Configuration(String gsdl_path, String exec_path, String perl_path) {
+		  super();
+		  this.gsdl_path = gsdl_path;
+		  this.exec_path = exec_path;
+		  this.perl_path = perl_path;
+		  // Ensure the perl path includes exe under windoze
+		  if(Utility.isWindows() && !perl_path.toLowerCase().endsWith(".exe")) {
+				if(!perl_path.endsWith(File.separator)) {
+					 perl_path = perl_path + File.separator;
+				}
+				perl_path = perl_path + "perl.exe";
+		  }
+		  // Try to reload the configuration.
+		  File config_xml = new File(CONFIG_XML);
+		  if(config_xml.exists()) {
+				general_config = Utility.parse(CONFIG_XML, false);
+		  }
+		  // If that fails retrieve the default configuration file from our xml library, which I'll personally guarantee to work.
+		  if(general_config == null) {
+				general_config = Utility.parse(TEMPLATE_CONFIG_XML, true);
+				Gatherer.println("Loaded default Gatherer configuration template.");
+		  }
+		  else {
+				Gatherer.println("Loaded current Gatherer configuration.");
+		  }
+		  // Re-establish the color settings.
+		  updateUI();
+	 }
+
+	 /** The default get action retrieves the named property from the desired configuration, and returns a true or false. */
+	 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. */
+	 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) MSMUtils.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 = MSMUtils.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.
+								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 error) {
+		  }
+		  return properties;
+	 }
+
+	 /** Retrieve the information subtree containing the arguments for the desired external program. If the program has marked superclasses append their arguments as well. */
+	 public Element getArguments(String filename) {
+		  Element argument_element = null;
+		  try {
+				// Retrieve the other information subtree.
+				Element document_element = general_config.getDocumentElement();
+				Element other_element = (Element) MSMUtils.getNodeFromNamed(document_element, OTHER);
+				NodeList argument_elements = other_element.getElementsByTagName(OTHER_INFO);
+				for(int i = 0; argument_element == null && i < argument_elements.getLength(); i++) {
+					 Element possible_element = (Element) argument_elements.item(i);
+					 Element possible_name_element = (Element) MSMUtils.getNodeFromNamed(possible_element, NAME);
+					 String possible_name = MSMUtils.getValue(possible_name_element);
+					 ///ystem.err.println("Does " + possible_name + " equal " + filename);
+					 if(possible_name.equalsIgnoreCase(filename)) {
+						  argument_element = possible_element;
+					 }
+					 possible_name = null;
+					 possible_name_element = null;
+					 possible_element = null;
+				}
+				argument_elements = null;
+				other_element = null;
+				document_element = null;
+		  }
+		  catch(Exception error) {
+		  }
+		  return argument_element;
+	 }
+
+	 /** Retrieve the value of the named property as a Color. */
+	 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 error) {
+				Gatherer.printStackTrace(error);
+		  }
+		  return result;
+	 }
+
+	 /** Retrieve the value of the named property as a Dimension. */
+	 public Dimension getDimension(String property, boolean general) {
+		  Dimension result = new Dimension(100, 100); // Default
+		  try {
+				String raw = getString(property, general);
+				// Dimension is a width by height pair, comma separated (also remove whitespace)
+				StringTokenizer tokenizer = new StringTokenizer(raw, TOKENIZER_PATTERN1);
+				int width = Integer.parseInt(tokenizer.nextToken());
+				int height = Integer.parseInt(tokenizer.nextToken());
+				result = new Dimension(width, height);
+		  }
+		  catch(Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+		  return result;
+	 }
+
+	 /** Retrieve the value of the named property as a FontUIResource. */
+	 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_PATTERN1);
+				String face = tokenizer.nextToken();
+				int style = Font.PLAIN;
+				String temp = tokenizer.nextToken().toUpperCase();
+				if(temp.equals("BOLD")) {
+					 style = Font.BOLD;
+				}
+				else if(temp.equals("ITALIC")) {
+					 style = Font.ITALIC;
+				}
+				int size = Integer.parseInt(tokenizer.nextToken());
+				result = new FontUIResource(face, style, size);
+		  }
+		  catch(Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+		  return result;
+	 }
+
+	 /** Retrieve the value of the named property as an integer. */
+	 public int getInt(String property, boolean general) {
+		  int result = -1;
+		  try {
+				String raw = getString(property, general);
+				result = Integer.parseInt(raw);
+		  }
+		  catch(Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+		  return result;
+	 }
+
+	 /** Retrieve the value of the named property as a Locale. */
+	 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();
+				String country = tokenizer.nextToken();
+				result = new Locale(language, country);
+		  }
+		  catch(Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+		  return result;
+	 }
+
+	 /** Retrieve the value of the named property, and noting whether we consult the general or collection specific configuration. */
+	 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) get(property + general);
+				if(reference != null) {
+					 Element argument_element = (Element) reference.get();
+					 if(argument_element != null) {
+						  cache_hit++;
+						  result = MSMUtils.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) MSMUtils.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 = MSMUtils.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.
+									 put(property + general, new SoftReference(argument_element));
+								}
+						  }
+					 }
+				}
+		  }
+		  catch (Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+		  // 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;
+	 }
+
+	 /** Retrieve the path to the PERL scripts within the Greenstone directory.
+	  * @return A <strong>String</strong> containing the path.
+	  */
+	 public String getScriptPath() {
+		  return gsdl_path + "bin" + File.separator + "script" + File.separator;
+	 }
+
+	 /** Export the general configuration to file. */
+	 public void save() {
+		  ///ystem.err.println("Hits " + cache_hit + " vs Misses " + cache_miss);
+		  Utility.export(general_config, Utility.BASE_DIR + CONFIG_XML);
+	 }
+
+	 /** Set the named property, from the specified configuration, using the given boolean value. */
+	 public void set(String property, boolean general, boolean value) {
+		  setString(property, general, (value ? "true" : "false"));
+	 }
+
+	 /** Add a subtree of argument information to the other arguments part of the general configuration. This overwrites any such existing subtree. */
+	 public void setArguments(Element arguments_element) {
+		  try {
+				Element document_element = general_config.getDocumentElement();
+				Element other_element = (Element) MSMUtils.getNodeFromNamed(document_element, OTHER);
+				// Retrieve the name of the information
+				Element arguments_name_element = (Element)MSMUtils.getNodeFromNamed(arguments_element, NAME);
+				String filename = MSMUtils.getValue(arguments_element);
+				// Find any argument information subtree starting with the same name
+				Element obsolete_arguments_element = getArguments(filename);
+				// Create a copy of the arguments_element within our tree (import).
+				Element our_arguments_element = (Element) general_config.importNode(arguments_element, true);
+				// Now we insert this new node into the tree. If a previous node exists we replace it instead.
+				if(obsolete_arguments_element == null) {
+					 other_element.appendChild(our_arguments_element);
+				}
+				else {
+					 other_element.replaceChild(our_arguments_element, obsolete_arguments_element);
+				}
+				our_arguments_element = null;
+				obsolete_arguments_element = null;
+				filename = null;
+				arguments_name_element = null;
+				other_element = null;
+				document_element = null;
+		  }
+		  catch (Exception error) {
+				Gatherer.println("Error in Configuration.setArguments(): " + error);
+				Gatherer.printStackTrace(error);
+		  }
+	 }
+
+	 /** Set the collection configuration. */
+	 public void setCollectionConfiguration(Document collection_config) {
+		  this.collection_config = collection_config;
+		  updateUI();
+		  ///atherer.println("Collection configuration set.");
+	 }
+
+	 /** Set the named property, from the specified configuration, using the given Color value. */
+	 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());
+	 }
+
+	 /** Set the named property, from the specified configuration, using the given Dimension value. */
+	 public void setDimension(String property, boolean general, Dimension value) {
+		  StringBuffer text = new StringBuffer("");
+		  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 Font value. */
+	 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. */
+	 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. */
+	 public void setLocale(String property, boolean general, Locale value) {
+		  StringBuffer text = new StringBuffer("");
+		  text.append(value.getLanguage());
+		  text.append("_");
+		  text.append(value.getCountry());
+		  setString(property, general, text.toString());
+	 }
+
+	 /** Sets the value of the named property argument using the given string. */
+	 public void setString(String property, boolean general, String value) {
+		  ///atherer.println("Set configuration property: " + property + " = " + value + (general ? "" : " [Collection]"));
+		  try {
+				Document document = null;
+				if(general) {
+					 document = general_config;
+				}
+				else if(collection_config != null) {
+					 document = collection_config;
+				}
+				if(document != null) {
+					 Element argument_element = null;
+					 // Try to retrieve from cache
+					 SoftReference reference = (SoftReference) get(property + general);
+					 if(reference != null) {
+						  argument_element = (Element) reference.get();
+					 }
+					 if(argument_element == null) {
+						  Element document_element = document.getDocumentElement();
+						  Element gatherer_element = (Element) MSMUtils.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
+						  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 error) {
+		  }
+	 }
+
+	 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.button_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.collection_tree_background", false)));
+		  UIManager.put("Table.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)));
+
+		  // 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)));
+		  if(Gatherer.g_man != null) {
+				JPanel pane = (JPanel) Gatherer.g_man.getContentPane();
+				pane.updateUI();
+				// Also update all of the tabs according to workflow.
+				Gatherer.g_man.workflowUpdate("Browser", get("workflow.browse", false));
+				Gatherer.g_man.workflowUpdate("Mirroring", get("workflow.mirror", false));
+				Gatherer.g_man.workflowUpdate("Collection", get("workflow.gather", false));
+				Gatherer.g_man.workflowUpdate("MetaEdit", get("workflow.enrich", false));
+				Gatherer.g_man.workflowUpdate("Build", get("workflow.design", false));
+				Gatherer.g_man.workflowUpdate("Export", get("workflow.export", false));
+				Gatherer.g_man.workflowUpdate("Create", get("workflow.create", false));
+				Gatherer.g_man.workflowUpdate("Preview", get("workflow.preview", false));
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/Dictionary.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/Dictionary.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/Dictionary.java	(revision 13666)
@@ -0,0 +1,612 @@
+package org.greenstone.gatherer;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.util.*;
+import javax.swing.*;
+import javax.swing.plaf.*;
+import javax.swing.text.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.gui.border.TitledBorder;
+import org.greenstone.gatherer.util.DictionaryTreeNode;
+import org.greenstone.gatherer.util.MutableComboBoxEntry;
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.Utility;
+/** Extends the ResourceBundle class to allow for the automatic insertion of  arguments. Note that the key names beginning Farg are reserved for formatting. <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 {
+	 /** A String which more explicitly states the Locale of this dictionary. */
+	 public String language = null;
+	 /** A static reference to ourself. */
+	 static public Dictionary self;
+	 /** The font used when displaying various html text. */
+	 private FontUIResource font = null;
+	 /** A reference to remind us of the current locale. */
+	 private Locale locale = null;
+	 /** The ResourceBundle which contains the raw key-value mappings. Loaded from a file named "dictionary<I>locale</I>.properties*/
+	 private ResourceBundle dictionary = null;
+	 /**  Constructs the Dictionary class by first checking if a Locale has been set. If not the default locale is used, and a ResourceBundle is created. Finally a single important String, Language, is made available outside the class so a more read-able version of the Locale of this Dictionary is present.
+	  * @param locale The <strong>Locale</strong> used to load the desired dictionary resource bundle.
+	  */
+	 public Dictionary(Locale locale, FontUIResource font) {
+		  super();
+		  this.self = this;
+		  // Initialize.
+		  this.font = font;
+		  if(locale == null) {
+				this.locale = Locale.getDefault();
+		  }
+		  else {
+				this.locale = locale;
+				Locale.setDefault(locale);
+		  }
+		  dictionary = ResourceBundle.getBundle(Utility.DICTIONARY, this.locale);
+		  // Now quickly read in language name.
+		  language = dictionary.getString("Language");
+	 }
+	 /** Change the currently loaded dictionary and update registered (ie dynamic) components as possible. */
+	 public void changeDictionary(Locale locale) {
+		  this.locale = locale;
+		  // Load new dictionary
+		  dictionary = ResourceBundle.getBundle(Utility.DICTIONARY, locale);
+		  // Refresh all registered component
+		  for(Iterator keys = keySet().iterator(); keys.hasNext(); ) {
+				Object component = keys.next();
+				String[] args = (String[]) get(component);
+				if(component instanceof AbstractButton) {
+					 register((AbstractButton)component, args, true);
+				}
+				else if(component instanceof JComboBox) {
+					 register((JComboBox)component, args, true);
+				}
+				else if(component instanceof JDialog) {
+					 register((JDialog)component, args, true);
+				}
+				else if(component instanceof JFrame) {
+					 register((JFrame)component, args, true);
+				}
+				else if(component instanceof JLabel) {
+					 register((JLabel)component, args, true);
+				}
+				else if(component instanceof JTabbedPane) {
+					 register((JTabbedPane)component, args, true);
+				}
+				else if(component instanceof JTextComponent) {
+					 register((JTextComponent)component, args, true);
+				}
+				else if(component instanceof JTree) {
+					 register((JTree)component, args, true);
+				}
+				else if(component instanceof TitledBorder) {
+					 register((TitledBorder)component, args, true);
+				}
+				args = null;
+				component = null;
+		  }
+	 }
+	 /** Remove the component from our registered components list. */
+	 public void deregister(Object component) {
+		  remove(component);
+	 }
+
+	 /** 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 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.
+	  */
+	 public String get(String key) {
+		  return get(key, (String[])null);
+	 }
+	 /** Convienence method with transforms the second string argument into a string array. */
+	 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. Note that argument numbers greater than or equal to 32 are automatically mapped to the formatting String named Farg<I>n</I>.
+	  * @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.
+	  */
+	 public String get(String key, String args[]) {
+		  try {
+				String initial = dictionary.getString(key);
+				// 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];
+					 }
+					 else if(arg_num >= 32) {
+						  String f_subargs[] = new String[1];
+						  if(font != null) {
+								f_subargs[0] = font.getFontName();
+						  }
+						  else {
+								f_subargs[0] = "Arial";
+						  }
+						  complete = complete + get("Farg" + arg_num, f_subargs);
+					 }
+				}
+			   return complete + initial;
+		  }
+		  catch (Exception e) {
+				if(!key.endsWith("_Tooltip")) {
+					 Gatherer.println("Missing value for key: " + key);
+				}
+				return key;
+		  }
+	 }
+	 /** 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.
+	  */
+	 public String getLanguage() {
+		  return locale.getLanguage();
+	 }
+	 /** Register an abstract button component. */
+	 public void register(AbstractButton component, String[] args, boolean already_registered) {
+		  if(component != null) {
+				// Determine the key
+				String key = "";
+				if(!already_registered) {
+					 key = component.getText();
+				}
+				else {
+					 key = args[args.length - 1];
+				}
+				// Update the component using the AWTEvent queue
+				String value = get(key, args);
+				String tooltip = get(key + "_Tooltip", (String[])null);
+				ChangeTask task = new AbstractButtonChangeTask(component, key, value, tooltip);
+				SwingUtilities.invokeLater(task);
+				// Register as necessary
+				if(!already_registered) {
+					 args = ArrayTools.add(args, key);
+					 put(component, args);
+				}
+		  }
+	 }
+	 /** Register a combobox component. */
+	 public void register(JComboBox component, String[] args, boolean already_registered) {
+		  if(component != null) {
+				// If not already registered then args will be null.
+				if(!already_registered) {
+					 args = new String[component.getItemCount()];
+				}
+				// Retrieve the tooltip. The key is mostly derived from the comboboxes name.
+				String key = component.getName();
+				String tooltip = get(key + "_Tooltip", (String[])null);
+				ChangeTask task = new JComboBoxChangeTask(component, key, -1, tooltip);
+				SwingUtilities.invokeLater(task);
+				// Iterate through the combobox, updating values and recording the original key of each item in args.
+				for(int i = 0; i < args.length; i++) {
+					 if(args[i] == null) {
+						  args[i] = component.getItemAt(i).toString();
+					 }
+					 String value = get(args[i], (String[])null);
+					 task = new JComboBoxChangeTask(component, key, i, value);
+					 SwingUtilities.invokeLater(task);
+				}
+				// Register if necessary
+				if(!already_registered) {
+					 put(component, args);
+				}
+		  }
+	 }
+	 /** Register a dialog component. */
+	 public void register(JDialog component, String[] args, boolean already_registered) {
+		  if(component != null) {
+				// Determine the key
+				String key = "";
+				if(!already_registered) {
+					 key = component.getTitle();
+				}
+				else {
+					 key = args[args.length - 1];
+				}
+				// Update the component using the AWTEvent queue
+				String value = get(key, args);
+				ChangeTask task = new JDialogChangeTask(component, key, value);
+				SwingUtilities.invokeLater(task);
+				// Register as necessary
+				if(!already_registered) {
+					 args = ArrayTools.add(args, key);
+					 put(component, args);
+				}
+		  }
+	 }
+	 /** Register a frame component. */
+	 public void register(JFrame component, String[] args, boolean already_registered) {
+		  if(component != null) {
+				// Determine the key
+				String key = "";
+				if(!already_registered) {
+					 key = component.getTitle();
+				}
+				else {
+					 key = args[args.length - 1];
+				}
+				// Update the component using the AWTEvent queue
+				String value = get(key, args);
+				ChangeTask task = new JFrameChangeTask(component, key, value);
+				SwingUtilities.invokeLater(task);
+				// Register as necessary
+				if(!already_registered) {
+					 args = ArrayTools.add(args, key);
+					 put(component, args);
+				}
+		  }
+	 }
+	 /** Register a label component. */
+	 public void register(JLabel component, String[] args, boolean already_registered) {
+		  if(component != null) {
+				// Determine the key
+				String key = "";
+				if(!already_registered) {
+					 key = component.getText();
+				}
+				else {
+					 key = args[args.length - 1];
+				}
+				// Update the component using the AWTEvent queue
+				String value = get(key, args);
+				ChangeTask task = new JLabelChangeTask(component, key, value);
+				SwingUtilities.invokeLater(task);
+				// Register as necessary
+				if(!already_registered) {
+					 args = ArrayTools.add(args, key);
+					 put(component, args);
+				}
+		  }
+	 }
+	 /** Register a tab pane component. */
+	 public void register(JTabbedPane component, String[] args, boolean already_registered) {
+		  if(component != null) {
+				// If not already registered then args will be null.
+				if(!already_registered) {
+					 args = new String[component.getTabCount()];
+				}
+				// Iterate through the tabbed panes tabs, updating values and recording the original key of each item in args.
+				for(int i = 0; i < args.length; i++) {
+					 if(args[i] == null) {
+						  args[i] = component.getTitleAt(i);
+					 }
+					 String value = get(args[i], (String[])null);
+					 String tooltip = get(args[i] + "_Tooltip", (String[])null);
+					 ChangeTask task = new JTabbedPaneChangeTask(component, args[i], i, value, tooltip);
+					 SwingUtilities.invokeLater(task);
+				}
+				// Register if necessary
+				if(!already_registered) {
+					 put(component, args);
+				}
+		  }
+	 }
+	 /** Register a text component. */
+	 public void register(JTextComponent component, String[] args, boolean already_registered) {
+		  if(component != null) {
+				// Determine the key
+				String key = "";
+				if(!already_registered) {
+					 key = component.getText();
+				}
+				else {
+					 key = args[args.length - 1];
+				}
+				// Update the component using the AWTEvent queue
+				String value = get(key, args);
+				String tooltip = get(key + "_Tooltip", (String[])null);
+				ChangeTask task = new JTextComponentChangeTask(component, key, value, tooltip);
+				SwingUtilities.invokeLater(task);
+				// Register as necessary
+				if(!already_registered) {
+					 args = ArrayTools.add(args, key);
+					 put(component, args);
+				}
+		  }
+	 }
+	 /** Register a tree component. */
+	 public void register(JTree component, String[] args, boolean already_registered) {
+		  if(component != null) {
+				// Retrieve the tooltip using the components name
+				String key = component.getName();
+				String tooltip = get(key + "_Tooltip", (String[])null);
+				ChangeTask task = new JTreeChangeTask(component, key, tooltip);
+				SwingUtilities.invokeLater(task);
+				// A tree can never be previously registered. In otherwords the keys are harvested each time. Thus for a tree to remain consistant its up to the implementer to implement DictionaryTreeNode for the tree nodes!
+				ArrayList nodes = new ArrayList();
+				nodes.add(component.getModel().getRoot());
+				while(nodes.size() > 0) {
+					 DictionaryTreeNode node = (DictionaryTreeNode) nodes.remove(0);
+					 // Update
+					 String value = get(node.getKey(), (String[])null);
+					 task = new JTreeChangeTask(component, node.getKey(), node, value);
+					 SwingUtilities.invokeLater(task);
+					 // Add children to nodes
+					 for(int i = 0; i < node.getChildCount(); i++) {
+						  nodes.add(node.getChildAt(i));
+					 }
+				}
+		  }
+	 }
+	 /** Register a titled border component. */
+	 public void register(TitledBorder component, String[] args, boolean already_registered) {
+		  if(component != null) {
+				// Determine the key
+				String key = "";
+				if(!already_registered) {
+					 key = component.getTitle();
+				}
+				else {
+					 key = args[args.length - 1];
+				}
+				// Update the component using the AWTEvent queue
+				String value = get(key, args);
+				ChangeTask task = new TitledBorderChangeTask(component, key, value);
+				SwingUtilities.invokeLater(task);
+				// Register as necessary
+				if(!already_registered) {
+					 args = ArrayTools.add(args, key);
+					 put(component, args);
+				}
+		  }
+	 }
+	 /** A get method called internally by components that have been previously been registered, which means that arg[index] is the original key value. Index is usually the last entry in the array, however this is not true for comboboxes, tabbed panes and trees. */
+	 private String get(String[] args, int index) {
+		  return get(args[index], args);
+	 }
+
+	 private abstract class ChangeTask
+		  implements Runnable {
+		  protected String key;
+		  protected String value;
+		  public ChangeTask(String key, String value) {
+				this.key = key;
+				this.value = value;
+		  }
+		  public void run() {
+		  }
+	 }
+	 /** Update the text and tooltip for this button. */
+	 private class AbstractButtonChangeTask
+		  extends ChangeTask {
+		  private AbstractButton component;
+		  private String tooltip;
+		  public AbstractButtonChangeTask(AbstractButton component, String key, String value, String tooltip) {
+				super(key, value);
+				this.component = component;
+				this.tooltip = tooltip;
+		  }
+		  public void run() {
+				component.setText(value);
+				if(!tooltip.equals(key+"_Tooltip")) {
+					 component.setToolTipText(tooltip);
+				}
+				else {
+					 component.setToolTipText(null);
+				}
+		  }
+	 }
+	 /** Update the text associated with a combobox. If the index used is -1 then we are setting the tooltip for this combobox. */
+	 private class JComboBoxChangeTask
+		  extends ChangeTask {
+		  private int index;
+		  private JComboBox component;
+		  public JComboBoxChangeTask(JComboBox component, String key, int index, String value) {
+				super(key, value);
+				this.component = component;
+				this.index = index;
+		  }
+		  public void run() {
+				if(index != -1) {
+					 try {
+						  MutableComboBoxEntry entry = (MutableComboBoxEntry)component.getItemAt(index);
+						  entry.setText(value);
+					 }
+					 catch (Exception error) {
+					 }
+				}
+				else {
+					 if(!value.equals(key+"_Tooltip")) {
+						  component.setToolTipText(value);
+					 }
+					 else {
+						  component.setToolTipText(null);
+					 }
+				}
+		  }
+	 }
+	 /** Update the title of this dialog. */
+	 private class JDialogChangeTask
+		  extends ChangeTask {
+		  private JDialog component;
+		  public JDialogChangeTask(JDialog component, String key, String value) {
+				super(key, value);
+				this.component = component;
+		  }
+		  public void run() {
+				component.setTitle(value);
+		  }
+	 }
+	 /** Update the title of this frame. */
+	 private class JFrameChangeTask
+		  extends ChangeTask {
+		  private JFrame component;
+		  public JFrameChangeTask(JFrame component, String key, String value) {
+				super(key, value);
+				this.component = component;
+		  }
+		  public void run() {
+				component.setTitle(value);
+		  }
+	 }
+	 /** Update the text of this label. */
+	 private class JLabelChangeTask
+		  extends ChangeTask {
+		  private JLabel component;
+		  public JLabelChangeTask(JLabel component, String key, String value) {
+				super(key, value);
+				this.component = component;
+		  }
+		  public void run() {
+				component.setText(value);
+		  }
+	 }
+	 /** Updates a tabbed panes tab title and tooltip. */
+	 private class JTabbedPaneChangeTask
+		  extends ChangeTask {
+		  private int index;
+		  private JTabbedPane component;
+		  private String tooltip;
+		  public JTabbedPaneChangeTask(JTabbedPane component, String key, int index, String value, String tooltip) {
+				super(key, value);
+				this.component = component;
+				this.index = index;
+				this.tooltip = tooltip;
+		  }
+		  public void run() {
+				component.setTitleAt(index, value);
+				if(!tooltip.equals(key+"_Tooltip")) {
+					 component.setToolTipTextAt(index, tooltip);
+				}
+				else {
+					 component.setToolTipTextAt(index, null);
+				}
+		  }
+	 }
+	 /** Update the text and tooltip of this text component. */
+	 private class JTextComponentChangeTask
+		  extends ChangeTask {
+		  private JTextComponent component;
+		  private String tooltip;
+		  public JTextComponentChangeTask(JTextComponent component, String key, String value, String tooltip) {
+				super(key, value);
+				this.component = component;
+				this.tooltip = tooltip;
+		  }
+		  public void run() {
+				component.setText(value);
+				if(!tooltip.equals(key+"_Tooltip")) {
+					 component.setToolTipText(tooltip);
+				}
+				else {
+					 component.setToolTipText(null);
+				}
+		  }
+	 }
+	 /** Update the tooltip of a tree and its tree node's labels. Shouldn't really ever be used on a dynamic tree, but is quite useful for a 'contents' tree type control. */
+	 private class JTreeChangeTask
+		  extends ChangeTask {
+		  private DictionaryTreeNode node;
+		  private JTree component;
+		  public JTreeChangeTask(JTree component, String key, String value) {
+				super(key, value);
+				this.component = component;
+		  }
+		  public JTreeChangeTask(JTree component, String key, DictionaryTreeNode node, String value) {
+				super(key, value);
+				this.component = component;
+				this.node = node;
+		  }
+		  public void run() {
+				if(value != null) {
+					 node.setText(value);
+					 ((DefaultTreeModel)component.getModel()).nodeChanged((TreeNode)node);
+				}
+				// Set the tool tip
+				else {
+					 if(!value.equals(key+"_Tooltip")) {
+						  component.setToolTipText(value);
+					 }
+					 else {
+						  component.setToolTipText(null);
+					 }
+				}
+		  }
+	 }
+	 /** Update the title of this titled border. */
+	 private class TitledBorderChangeTask
+		  extends ChangeTask {
+		  private TitledBorder component;
+		  public TitledBorderChangeTask(TitledBorder component, String key, String value) {
+				super(key, value);
+				this.component = component;
+		  }
+		  public void run() {
+				component.setTitle(value);
+				component.getParent().repaint();
+		  }
+	 }
+}
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/GAuthenticator.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/GAuthenticator.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/GAuthenticator.java	(revision 13666)
@@ -0,0 +1,190 @@
+package org.greenstone.gatherer;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */ 
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.Point;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.net.Authenticator;
+import java.net.PasswordAuthentication;
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JTextField;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+/** 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 {
+	 /** 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,130);
+	 /** 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, get("Title"), true);
+		  dialog.setModal(true);
+		  dialog.setSize(SIZE);
+		  JPanel content_pane = (JPanel)dialog.getContentPane();
+		  JLabel title_label = new JLabel(getRequestingPrompt());
+		  JPanel user_panel = new JPanel();
+		  JLabel username_label = new JLabel(get("Username"));
+		  JTextField username = new JTextField();
+		  JPanel password_panel = new JPanel();
+		  JLabel password_label = new JLabel(get("Password"));
+		  password = new JPasswordField();
+		  password.setEchoChar ('*');
+		  JPanel button_panel = new JPanel();
+		  ok_button = new JButton(get("General.OK"));
+		  cancel_button = new JButton(get("General.Cancel"));
+		  // Connect listeners.
+		  cancel_button.addActionListener(new AuthenticationActionListener(true));
+		  ok_button.addActionListener(new AuthenticationActionListener(false));
+		  password.addActionListener(new AuthenticationActionListener(false));
+		  username.addActionListener(new RequestFocusListener(password));
+		  // Layout the components.
+		  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));
+		  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.show();
+		  if(!authentication_cancelled) {
+				return new PasswordAuthentication(username.getText(), password.getPassword());
+		  } else {
+				return null;
+		  }
+	 }
+
+	 /** Retrieve a phrase from the dictionary.
+	  * @param key A <strong>String</strong> used to determine what phrase to retrieve.
+	  * @return The required phrase as a <strong>String</strong>, or at least some meaningful error message.
+	  * @see org.greenstone.gatherer.Dictionary
+	  * @see org.greenstone.gatherer.Gatherer
+	  */
+	 private String get(String key) {
+		  if(key.indexOf(".") == -1) {
+				key = "GAuthenticator." + key;
+		  }
+		  return Gatherer.dictionary.get(key);
+	 }
+	/** 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/start/gli/src/org/greenstone/gatherer/Gatherer.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/Gatherer.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/Gatherer.java	(revision 13666)
@@ -0,0 +1,750 @@
+package org.greenstone.gatherer;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import com.l2fprod.gui.*;
+import com.l2fprod.gui.plaf.skin.*;
+import com.l2fprod.util.*;
+
+import java.awt.*;
+import java.io.*;
+import java.lang.*;
+import java.net.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.plaf.*;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.GAuthenticator;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.file.FileManager;
+import org.greenstone.gatherer.file.FileAssociationManager;
+import org.greenstone.gatherer.gui.Coloring;
+import org.greenstone.gatherer.gui.GUIManager;
+import org.greenstone.gatherer.gui.Splash;
+import org.greenstone.gatherer.gui.WarningDialog;
+import org.greenstone.gatherer.msm.MetadataSetManager;
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.Utility;
+import sun.misc.*;
+/** Containing the main() method for the Gatherer, this class is the starting point for the rest of the application. 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 {
+	 /** Has the exit flag been set? <i>true</i> if so, <i>false</i> otherwise. */
+	 public boolean exit = false;
+	 /** The size of the Gatherer window. */
+	 public Dimension frame_size = null;
+	 /** A temporary shared memory area to store HIndexes to speed up metadata.xml writing. */
+	 public Hashtable known_indexes = null;
+	 /** Legacy copy of the debug_ps. */
+	 public PrintStream debug_ps;
+	 /** All of the external applications that must exit before we close the Gatherer. */
+	 public Vector apps = new Vector();
+	 /** Messages that have been issued before we have anyway to show them, ie prior to Log initialization. */
+	 public Vector waiting_messages = new Vector();
+	 /** The manager in charge of remembering what file extension gets opened with what program. */
+	 static public FileAssociationManager assoc_man;
+	 /** A public reference to the CollectionManager. */
+	 static public CollectionManager c_man;
+	 /** A public reference to the Gatherer's configuration. */
+	 static public Configuration config;
+	 /** A public reference to the Dictionary. */
+	 static public Dictionary dictionary;
+	 /** A public reference to the FileManager. */
+	 static public FileManager f_man;
+	 /** A public reference to the GUIManager. */
+	 static public GUIManager g_man;
+	 /** A static reference to ourselves. */
+	 static public Gatherer self;
+	 /** A public reference to the message log. */
+	 static public Log log;
+	 /** The debug print stream. */
+	 static public PrintStream debug;
+	 /** The name of the necessary environment variable to check for in the programs environment. */
+	 static public String KEY = "GSDLPATH";
+	 /** Extra environment information which must be set before shell processes will run properly. Should always be null if the startup script/program has done its job properly. */
+	 static public String extra_env[] = null;
+	 /** The name of the Gatherers configuration file. */
+	 static private String CONFIG_FILE_NAME = "gatherer.cfg";
+	 /** Constructor. Make the three main modules, c_man, f_man and g_man, and any other necessary classes such as Dictionary.
+	  * @param size The desired size of the Gatherer window as a <strong>Dimension</strong>.
+	  * @param gsdl_path The path to the gsdl directory, gathered from the startup arguments, and presented as a <strong>String</strong>.
+	  * @param exec_path The path to the library executable, gathered from the startup arguments, and presented as a <strong>String</strong>.
+	  * @param debug <i>true</i> to print verbose debug messages to "debug.txt", <i>false</i> otherwise.
+	  * @param perl_path The path to the PERL compiler as a <strong>String</strong>. Necessary for windows platform versions.
+	  * @param splash A reference to the splash screen.
+	  * @param no_load <i>true</i> to prevent the previously opened collection from reopening.
+	  * @see java.io.FileOutputStream
+	  * @see java.io.PrintStream
+	  * @see java.lang.Exception
+	  * @see java.lang.StringBuffer
+	  * @see java.util.Calendar
+	  * @see org.greenstone.gatherer.Configuration
+	  * @see org.greenstone.gatherer.Dictionary
+	  * @see org.greenstone.gatherer.Gatherer.CTRLCHandler
+	  * @see org.greenstone.gatherer.GAuthenticator
+	  * @see org.greenstone.gatherer.collection.CollectionManager
+	  * @see org.greenstone.gatherer.file.FileManager
+	  * @see org.greenstone.gatherer.gui.GUIManager
+	  * @see org.greenstone.gatherer.gui.Splash
+	  */
+	 public Gatherer() {
+		  this.self = this;
+	 }
+
+	 public void run(Dimension size, String gsdl_path, String exec_path, boolean debug_enabled, String perl_path, boolean no_load, Splash splash, String open_collection) {
+
+		  // This will hopefully catch ctrl-c and terminate, and exit gracefully. However it is platform specific, and may not be supported by some JVMs.
+		  /** It does, but I get bloddy sick of it working when the Gatherer hangs.
+		  CTRLCHandler handler = new CTRLCHandler();
+		  Signal.handle(new Signal("INT"), handler);
+		  Signal.handle(new Signal("TERM"), handler);
+		  handler = null;
+		  */
+		  // Create the debug stream only if required.
+		  if(debug_enabled) {
+				try {
+					 Calendar now = Calendar.getInstance();
+					 StringBuffer name = new StringBuffer("debug");
+					 name.append(now.get(Calendar.DATE));
+					 name.append("-");
+					 name.append(now.get(Calendar.MONTH));
+					 name.append("-");
+					 name.append(now.get(Calendar.YEAR));
+					 name.append(".txt");
+					 this.debug = new PrintStream(new FileOutputStream(name.toString()));
+					 Properties props = System.getProperties();
+					 props.list(debug);
+					 // Legacy
+					 debug_ps = debug;
+				}
+				catch(Exception error) {
+					 ///ystem.err.println("Error in Gatherer.init(): " + error);
+					 error.printStackTrace();
+					 System.exit(1);
+				}
+		  }
+		  try {
+				// Create log
+				log = new Log();
+				// Load Config
+				loadConfig(gsdl_path, exec_path, perl_path);
+
+				// Read Dictionary
+				dictionary = new Dictionary(config.getLocale("general.locale", true), config.getFont("general.font", true));
+
+				// Having loaded the configuration (necessary to determine if certain warnings have been disabled) and dictionary, we now check if the necessary path variables have been provided.
+				
+				if(exec_path == null) {
+					 missingEXEC(dictionary);
+				}
+				if(gsdl_path == null) {
+					 missingGSDL(dictionary);
+				}
+				// Perl path is a little different as it is perfectly ok to start the Gatherer without providing a perl path 
+				boolean found_perl = false;
+				if(config.perl_path != null) {
+					 // See if the file pointed to actually exists
+					 File perl_file = new File(config.perl_path);
+					 found_perl = perl_file.exists();
+					 perl_file = null;
+				}
+				if(config.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).
+						  config.perl_path = perl_test.toString();
+						  found_perl = true;
+					 }
+				}
+				if(!found_perl) {
+					 // Time for an error message.
+					 missingPERL(dictionary);
+				}
+				else {
+					 ///ystem.err.println("Now perl_path = " + config.perl_path);
+				}
+
+				// Size the screen
+				Dimension temp = config.getDimension("general.size", true);
+				if(temp != null) {
+					 size = temp;
+				}
+				if (size.height > config.screen_size.height) {
+					 size.setSize(size.width, config.screen_size.height);
+				}
+				if (size.width > config.screen_size.width) {
+					 size.setSize(config.screen_size.width, size.height);
+				}
+				// Set default font
+				setUIFont(config.getFont("general.font", true), config.getFont("general.tooltip_font", true));
+				// 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();
+				// If there was an open collection last session, reopen it.
+				if(open_collection == null) {
+					 open_collection = config.getString("general.open_collection", true);
+				}
+				if(!no_load && open_collection.length() > 0) {
+					 c_man.loadCollection(open_collection);
+				}
+				// Create GUI Manager (last) or else suffer the death of a thousand NPE's
+				splash.toFront();
+				g_man = new GUIManager(size);
+				g_man.display();
+
+				// Center 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((config.screen_size.width - size.width) / 2, (config.screen_size.height - size.height) / 2);
+				g_man.setVisible(true);
+				// 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();
+				// Hide the splash.
+				splash.hide();
+				splash.destroy();
+				splash = null;
+		  }
+		  catch (Exception error) {
+				error.printStackTrace();
+		  }
+	 }
+	 /** Writes a message to the debug filestream.
+	  * @param message The message as a <strong>String</strong>.
+	  */
+	 public void debug(String message) {
+		  debug(null, message);
+	 }
+	 /** Writes a message to the debug filestream.
+	  * @param error The <strong>Exception</strong> associated with this message, or <i>null</i> for no exception.
+	  * @param message The message as a <strong>String</strong>.
+	  * @see java.io.FileOutputStream
+	  * @see java.io.PrintStream
+	  * @see java.lang.Exception
+	  */
+    public void debug(Exception exception, String message) {
+		  if(message != null) {
+				Gatherer.println(message);
+		  }
+		  if(exception != null) {
+				Gatherer.printStackTrace(exception);
+		  }
+	 }
+	 /** 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
+	  */
+	 public void exit() {
+		  exit = true;
+		  // If we have an open collection make note of it.
+		  config.setString("general.open_collection", true, null);
+		  if(c_man.ready()) {
+				///ystem.err.println("Collection open.");
+				if(c_man.saved()) {
+					 ///ystem.err.println("Collection has been recently saved, so I'll remember it for next time.");
+					 config.setString("general.open_collection", true, c_man.getCollectionFilename());
+				}
+				c_man.closeCollection();
+		  }
+		  if(assoc_man != null) {
+				assoc_man.destroy();
+				assoc_man = null;
+		  }
+		  // Check the current size of the Gatherer, and if its reasonable (ie greater than minsize) then store it for next time.
+		  Dimension size = g_man.getSize();
+		  if(size.width > 100 && size.height > 100) {
+				config.setDimension("general.size", true, size);
+		  }
+		  // Save configuration.
+		  saveConfig();
+		  // Flush debug
+		  if(debug != null) {
+				try {
+					 debug.flush();
+					 debug.close();
+				}
+				catch (Exception error) {
+					 error.printStackTrace();
+				}
+		  }
+		  if(apps.size() == 0) {
+				try {
+					 wait(200);
+				}
+				catch(Exception error) {
+				}
+				System.exit(0);
+		  }
+		  else {
+				JOptionPane.showMessageDialog(g_man, get("General.Outstanding_Processes"), get("General.Outstanding_Processes_Title"), JOptionPane.ERROR_MESSAGE);
+				g_man.hide();
+		  }
+	 }
+	 /** 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 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.
+	  */
+	 public String get(String key) {
+		  return dictionary.get(key, (String[])null);
+	 }
+	 /** Overloaded to call get with both a key and an argument array with one element.
+	  * @param key A <strong>String</strong> which is mapped to a initial String within the ResourceBundle.
+	  * @param arg A single argument as a <strong>String</strong>.
+	  * @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.
+	  */
+	 public String get(String key, String arg) {
+		  String args[] = new String[1];
+		  args[0] = arg;
+		  return dictionary.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. Note that argument numbers greater than or equal to 32 are automatically mapped to the formatting String named Farg<I>n</I>.
+	  * @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 automatically populated with formatting Strings of with argument String provided in the get call.
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.Dictionary
+	  */
+	 public String get(String key, String args[]) {
+		  return dictionary.get(key, args);
+	 }
+	 /** Retrieve the metadata directory, as required by any MSMCaller implementation.
+	  * @return The currently active collection metadata directory as a <strong>String</strong>.
+	  * @see org.greenstone.gatherer.collection.CollectionManager
+	  */
+	 public String getCollectionMetadata() {
+		  if(c_man != null && c_man.ready()) {
+				return c_man.getCollectionMetadata();
+		  }
+		  return "";
+	 }
+	 /** Retrieve a reference to the frame that any dialog boxes will appear relative to, as required by any MSMCaller or CDMCaller implementation.
+	  * @return A <strong>JFrame</strong>.
+	  * @see org.greenstone.gatherer.gui.GUIManager
+	  */
+	 public JFrame getFrame() {
+		  return g_man;
+	 }
+	 /** Method to retrieve a reference to the metadata set manager class. This is then used to create the 'metadataset' commands in the collection configuration file.
+	  * @return A reference to the <Strong>MetadataSetManager</strong>.
+	  * @see org.greenstone.gatherer.collection.CollectionManager
+	  */
+	 public MetadataSetManager getMSM() {
+		  if(c_man != null && c_man.getCollection() != null && c_man.getCollection().msm != null) {
+				return c_man.getCollection().msm;
+		  }
+		  return null;
+	 }
+	 /** Used to 'spawn' a new child application when a file is double clicked.
+	  * @param command The command to run in the child process to start the application, garnered from the registry of a default associations file, and presented as a <strong>String</strong>.
+	  * @see java.util.Vector
+	  * @see org.greenstone.gatherer.Gatherer.ExternalApplication
+	  */
+	 public void spawnApplication(File file) {
+		  String command = assoc_man.getCommand(file);
+		  if(command != null) {
+				ExternalApplication app = new ExternalApplication(command);
+				apps.add(app);
+				app.start();
+		  }
+		  else {
+				///ystem.err.println("No open command available.");
+		  }
+	 }
+
+	 /** Some startup arguments to the Gatherer have been encoded, where ' ' is replaced with '%', in order to allow arguments containing spaces to be parsed correctly by the JVM, and this method restores these arguments to thier original state.
+	  * @param encoded An encoded <strong>String</strong>.
+	  * @return The decoded <strong>String</strong>.
+	  */
+    static public String decode(String encoded) {
+		  return encoded.replace('%', ' ');
+    }
+	 /** The entry point into the Gatherer. Parses arguments.
+	  * @param args A collection of arguments that may include: initial screen size, dictionary, path to the GSDL etc.
+	  * @see java.io.File
+	  * @see java.io.FileInputStream
+	  * @see java.lang.Exception
+	  * @see java.util.Properties
+	  * @see org.greenstone.gatherer.Dictionary
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.gui.Splash
+	  */
+	 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"); // One message every 600 hours!
+
+		  Gatherer gatherer = new Gatherer();
+
+		  boolean debug = false;
+		  boolean no_load = false;
+		  Dictionary dictionary = new Dictionary(null, null); // Default dictionary. Only used for starting error messages.
+		  Dimension size = new Dimension(800, 540);
+		  String exec_path = null;
+		  String extra = null;
+		  String filename = null;
+		  String gsdl_path = null;
+		  String perl_path = null;
+		  // Parse arguments
+		  for(int i = 0; i < args.length; i++) {
+		      if(args[i].equals("-gsdl")) {
+					 gsdl_path = decode(args[i+1]);
+					 if(!gsdl_path.endsWith(File.separator)) {
+						  gsdl_path = gsdl_path + File.separator;
+					 }
+		      }
+				if(args[i].equals("-load")) {
+					 filename = decode(args[i+1]);
+		      }
+		      else if(args[i].equals("-library")) {
+					 exec_path = args[i+1];
+		      }
+		      else if(args[i].equals("-perl")) {
+					 perl_path = decode(args[i+1]);
+					 // 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 its fine as it is
+					 ///ystem.err.println("Perl executable is: " + perl_path);
+		      }
+		      else if(args[i].equals("--help") || args[i].equals("-help") || args[i].equals("?") || args[i].equals("/?") || args[i].equals("/help")) {
+					 printUsage(dictionary);
+					 System.exit(0);
+		      }
+		      else if(args[i].equals("--debug") || args[i].equals("-debug")) {
+					 debug = true;
+		      }
+				// Don't load any previous collection. Convenient for me
+				else if(args[i].equals("-no_load")) {
+					 no_load = true;
+				}
+				// Check if they want it skinned.
+				else if(args[i].equals("-skinlf")) {
+					 // SkinLF
+					 try {
+						  SkinLookAndFeel.setSkin(SkinLookAndFeel.loadThemePackDefinition(SkinUtils.toURL(new File("lib/greenaqua/greenaqua.xml"))));
+						  SkinLookAndFeel.enable();
+					 }
+					 catch (Exception error) {
+						  ///ystem.err.println("Error: " + error);
+						  error.printStackTrace();
+					 }
+				}
+		  }
+
+		  // Splash screen.
+		  Splash splash = new Splash();
+
+		  // We take appropriate action when an empty gsdl_path is detected.
+		  if(gsdl_path == null) {
+				// Check for the presence of the path.cfg file.
+				File path_file = new File("path.cfg");
+				if(path_file.exists()) {
+					 try {
+						  // Read in then add each property to the Java Environment.
+						  FileInputStream prop_file = new FileInputStream(path_file);
+						  Properties p = new Properties();
+						  p.load(prop_file);
+						  extra = p.getProperty(KEY);
+					 }
+					 catch (Exception error) {
+						  System.out.println("Error in main():");
+						  error.printStackTrace();
+						  System.exit(1);
+					 }
+				}
+				else {
+					 missingGSDL(dictionary);
+				}
+		  }
+		  // We take appropriate action when an empty bin_path is detected.
+		  gatherer.run(size, gsdl_path, exec_path, debug, perl_path, no_load, splash, filename);
+	 }
+	 /** Prints a warning message about a missing library path, which means the final collection cannot be previewed in the Gatherer.
+	  */
+	 static public void missingEXEC(Dictionary dictionary) {
+		  WarningDialog dialog = new WarningDialog("warning.MissingEXEC", false);
+		  dialog.display();
+		  dialog.dispose();
+		  dialog = null;
+		  ///ystem.out.println(dictionary.get("General.Missing_EXEC"));
+	 }
+	 /** Prints a warning message about a missing GSDL path, which although not fatal pretty much ensures nothing will work properly in the Gatherer.
+	  */
+	 static public void missingGSDL(Dictionary dictionary) {
+		  WarningDialog dialog = new WarningDialog("warning.MissingGSDL", false);
+		  dialog.display();
+		  dialog.dispose();
+		  dialog = null;
+		  ///ystem.out.println(dictionary.get("General.Missing_GSDL"));
+	 }
+	 /** Prints a warning message about a missing PERL path, which although not fatal pretty much ensures no collection creation/building will work properly in the Gatherer. */
+	 static public void missingPERL(Dictionary dictionary) {
+		  WarningDialog dialog = new WarningDialog("warning.MissingPERL", false);
+		  dialog.display();
+		  dialog.dispose();
+		  dialog = null;
+		  ///ystem.out.println(dictionary.get("General.Missing_PERL"));
+	 }
+	 /** Print a message to the debug stream. */
+	 static synchronized public void println(String message) {
+		  if(debug != null) {
+				debug.println(message);
+		  }
+		  else {
+				System.err.println(message);
+		  }
+	 }
+	 /** Print a stack trace to the debug stream. */
+	 static synchronized public void printStackTrace(Exception exception) {
+		  if(debug != null) {
+				exception.printStackTrace(debug);
+		  }
+		  else {
+				exception.printStackTrace();
+		  }
+	 }
+	 /** Prints a usage message to screen.
+	  */
+	 static public void printUsage(Dictionary dictionary) {
+		  System.out.println(dictionary.get("General.Usage"));
+	 }
+
+	 /** 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(Gatherer.config.get("general.use_proxy", true)) {
+					 System.setProperty("http.proxyType", "4");
+					 System.setProperty("http.proxyHost", Gatherer.config.getString("general.proxy_host", true));
+					 System.setProperty("http.proxyPort", Gatherer.config.getString("general.proxy_port", true));
+					 System.setProperty("http.proxySet", "true");
+				} else {
+					 System.setProperty("http.proxySet", "false");
+				}
+		  } catch (Exception error) {
+				Gatherer.println("Error in Gatherer.initProxy(): " + error);
+				Gatherer.printStackTrace(error);
+		  }
+	 }
+
+	 /** Set all the default fonts of the program to a choosen font, except the tooltip font which should be some fixed width font.
+	  * @param f The default font to use in the Gatherer as a <strong>FontUIResource</strong>.
+	  * @param ttf The tooltip font to use also as a <strong>FontUIResource</strong>.
+	  * @see java.util.Enumeration
+	  * @see javax.swing.UIManager
+	  */
+	 static public void setUIFont (FontUIResource f, FontUIResource ttf){
+		  // sets the default font for all Swing components.
+		  // ex.
+		  //  setUIFont (new FontUIResource("Serif",Font.ITALIC,12));
+		  //
+		  Enumeration keys = UIManager.getDefaults().keys();
+		  while (keys.hasMoreElements()) {
+				Object key = keys.nextElement();
+				Object value = UIManager.get (key);
+				if (value instanceof FontUIResource)
+					 UIManager.put (key, f);
+		  }
+		  // Now set the tooltip font to some fixed width font
+		  UIManager.put("ToolTip.font", ttf);
+    }
+
+	 /** Loads the configuration file if one exists. Otherwise it creates a new one. Currently uses serialization.
+	  * @param size The desired size of the Gatherer window as a <strong>Dimension</strong>.
+	  * @param gsdl_path The path to the gsdl directory, gathered from the startup arguments, and presented as a <strong>String</strong>.
+	  * @param exec_path The path to the library executable, gathered from the startup arguments, and presented as a <strong>String</strong>.
+	  * @param perl_path The path to the PERL compiler as a <strong>String</strong>. Necessary for windows platform versions.
+	  * @see java.io.FileInputStream
+	  * @see java.io.ObjectInputStream
+	  * @see java.lang.Exception
+	  * @see org.greenstone.gatherer.Configuration
+	  */
+	 private void loadConfig(String gsdl_path, String exec_path, String perl_path) {
+		  try {
+				config = new Configuration(gsdl_path, exec_path, perl_path);
+		  } 
+		  catch (Exception error) {
+				Gatherer.println("config.xml is not a well formed XML document.");
+				Gatherer.printStackTrace(error);
+		  }
+	 }
+
+	 /** Creates and dispatches a message given the initial details.
+	  * @param level An <i>int</i> indicating the message level for this message.
+	  * @param message A <strong>String</strong> which contains the payload of this message.
+	  * @see org.greenstone.gatherer.Message
+	  * @see org.greenstone.gatherer.Log
+	  */
+	 private void message(int level, String message) {
+		  Message msg = new Message(Message.GENERAL, level, message);
+		  log.add(msg);
+	 }
+
+	 /** Causes the general configuration file to export itself to xml. Doesn't effect any remaining collection configuration, as its up to the collection manager to handle them (especially since we have no idea where they are going). */
+	 private void saveConfig() {
+		  try {
+				config.save();
+		  } catch (Exception error) {
+				Gatherer.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. */
+	 private class ExternalApplication
+		  extends Thread {
+		  /** The initial command string given to this sub-process. */
+		  private String command = null;
+		  /** Constructor.
+			* @param command The initial command <strong>String</strong>.
+			*/
+		  public ExternalApplication(String command) {
+				this.command = command;
+		  }
+		  /** 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 {
+					 debug("Running " + command);
+					 Runtime rt = Runtime.getRuntime();
+					 Process prcs = rt.exec(command);
+					 prcs.waitFor();
+				}
+				catch (Exception error) {
+					 debug(error, "Error in ExternalApplication.run(): " + error);
+				}
+				// 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(0);
+				}
+		  }
+	 }
+	/** This class is intented to detect a specific SIGNAL, in this case SIGINT, and exit properly, rather than letting the Gatherer be interrupted which has the potential to leave erroneous lock files. */
+	 private class CTRLCHandler
+		  implements SignalHandler {
+			/** <i>true</i> if we ignore any other signals we receive, most likely because we are already dealing with one, <i>false</i> otherwise. */
+		  private boolean ignore = false;
+			/** The method called by the system to inform us a signal has occured.
+			* @param sig The <strong>Signal</strong> itself.
+			* @see org.greenstone.gatherer.collection.CollectionManager
+			*/
+		  public void handle(Signal sig) {
+				if(!ignore) {
+					 ignore = true;
+					 // handle SIGINT
+					 System.out.println("Caught Ctrl-C...");
+					 if(c_man != null && c_man.ready()) {
+						  c_man.closeCollection();
+					 }
+					 exit();
+					 ignore = false;
+				}
+		  }
+	 }
+
+	 private class PerlTest {
+
+		  private String[] command = new String[2];
+
+		  public PerlTest() {
+				if(Utility.isWindows()) {
+					 command[0] = Utility.PERL_EXECUTABLE_WINDOWS;
+				}
+				else {
+					 command[0] = Utility.PERL_EXECUTABLE_UNIX;
+				}
+				command[1] = "-version";
+		  }
+
+		  public boolean found() {
+				boolean found = false;
+				try {
+					 Process prcs = Runtime.getRuntime().exec(command);
+					 prcs.waitFor();
+					 found = (prcs.exitValue() == 0);
+					 prcs = null;
+				}
+				catch(Exception error) {
+				}
+				return found;
+		  }
+
+		  public String toString() {
+				return command[0];
+		  }
+	 }
+}
+
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/Log.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/Log.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/Log.java	(revision 13666)
@@ -0,0 +1,82 @@
+package org.greenstone.gatherer;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.event.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.Message;
+/** The GLog provides a logging class for various messages around Gatherer.
+ * It includes methods to adding to the log, sorting and filtering the log,
+ * reading/writing the log to disk and viewing the log (via a dialog, haha).
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 1.0
+ */
+public class Log
+	 implements ActionListener {
+	 /** A reference to the dialog box the log will be displayed in so our inner classes have the ability to interact. */
+	 private JDialog dialog  = null;
+	 /** Constructor */
+	 public Log() {
+	 }
+	 /** Any implementation of ActionListener must include this method so
+	  * we can be informed when an action has occured.
+	  * @param event An <strong>ActionEvent</strong> which contains the details about the
+	  * event which fired this call.
+	  */
+	 public void actionPerformed(ActionEvent event) {
+		  if(event.getSource() == dialog) {
+				dialog.dispose();
+		  }
+	 }
+	 /** Add a message to the log. Note that this may be called from within
+	  * several different threads so I'd better synchronize.
+	  * @param message A <strong>Message</strong> which contains, surprisingly enough, the
+	  * message.
+	  * @see org.greenstone.gatherer.Gatherer
+	  */
+	 public synchronized void add(Message message) {
+		  //Gatherer.println(message.toString());
+		  /* @TODO */
+	 }
+	 /** Create a modal dialog box components to allow the user to view, and
+	  * filter the log.
+	  */
+	 public void display() {
+		  /* @TODO */
+	 }
+}
+
Index: /tags/start/gli/src/org/greenstone/gatherer/Message.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/Message.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/Message.java	(revision 13666)
@@ -0,0 +1,163 @@
+/**
+ *#########################################################################
+ *
+ * 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;
+/**************************************************************************************
+ * Title:        Gatherer
+ * Description:  The Gatherer: a tool for gathering and enriching a digital collection.
+ * Copyright:    Copyright (c) 2001
+ * Company:      The University of Waikato
+ * Written:        /  /01
+ * Revised:      28/05/01
+ **************************************************************************************/
+import java.util.Date;
+import java.util.Random;
+/** Provides an event-type wrapper around a message for displaying to the user.
+* @author John Thompson, Greenstone Digital Library, University of Waikato
+* @version 2.1
+*/
+public class Message {
+	 /** The level of this message. See above. */
+	 public int level;
+	 /** The source of this message. See above. */
+	 public int source;
+	 /** The age of this message. Used for ordering. */
+	 public long time;
+	 /** The actual message content of this message. */
+	 public String message;
+	 /** Used to indicate the source of the message is anywhere in general. */
+	 static final public int GENERAL   = 0;
+	 /** Used to indicate the source of the message is the browsing methods. */
+	 static final public int BROWSER   = 1;
+	 /** Used to indicate the source of the message is the mirroring methods. */
+	 static final public int MIRRORING = 2;
+	 /** 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 metadata and set methods. */
+	 static final public int METAEDIT  = 4;
+	 /** Used to indicate the source of the message is the building methods. */
+	 static final public int BUILDING  = 5;
+	 /** Used to indicate the source of the message is the preview methods. */
+	 static final public int FINAL     = 6;
+	 /** Used to indicate the source of the message is the log itself. */
+	 static final public int LOG       = 7;
+	 /** Used to indicate the level of the message is Main. */
+	 static final public int MAIN = 0;
+	 /** Used to indicate the level of the message is Event. */
+	 static final public int EVENT = 1;
+	 /** Used to indicate the level of the message is Information. */
+	 static final public int INFO = 2;
+	 /** Used to indicate the level of the message is Error. */
+	 static final public int ERROR = 3;
+
+	 /**
+	  * Creates a new message.
+	  * @param source the source of this message as an <i>int</i>. See above.
+	  * @param level the level of this message as an <i>int</i>. See above.
+	  * @param message the message content of this message as a <strong>String</strong>.
+	  */
+	 public Message(int source, int level, String message) {
+		  this.level = level;
+		  this.source = source;
+		  time = (new Date()).getTime();
+		  this.message = message;
+	 }
+	 /**
+	  * Used to display a message, stating level and source.
+	  * @param gatherer the main <strong>Gatherer</strong> class, used to get at the Dictionary.
+	  * @see org.greenstone.gatherer.Dictionary
+	  */
+	 public String toString(Gatherer gatherer) {
+		  String source_str = "";
+		  switch(source) {
+		  case GENERAL:
+				source_str = gatherer.dictionary.get("Source.General");
+				break;
+		  case BROWSER:
+				source_str = gatherer.dictionary.get("Source.Browser");
+				break;
+		  case MIRRORING:
+				source_str = gatherer.dictionary.get("Source.Mirroring");
+				break;
+		  case COLLECT:
+				source_str = gatherer.dictionary.get("Source.Collect");
+				break;
+		  case METAEDIT:
+				source_str = gatherer.dictionary.get("Source.MetaEdit");
+				break;
+		  case BUILDING:
+				source_str = gatherer.dictionary.get("Source.Building");
+				break;
+		  default:
+				source_str = gatherer.dictionary.get("Source.Unknown");
+		  }
+
+		  String level_str = "";
+		  switch(level) {
+		  case MAIN:
+				level_str = gatherer.dictionary.get("Level.Main");
+				break;
+		  case EVENT:
+				level_str = gatherer.dictionary.get("Level.Event");
+				break;
+		  case INFO:
+				level_str = gatherer.dictionary.get("Level.Information");
+				break;
+		  case ERROR:
+				level_str = gatherer.dictionary.get("Level.Error");
+				break;
+		  default:
+				level_str = gatherer.dictionary.get("Level.Unknown");
+		  }
+		  return source_str + " " + level_str + " > " + message;
+	 }
+	/** Used during testing testing to generate a random message.
+	* @return A new <strong>Message</strong> object which has a random source, level and a message body of the current system time.
+	*/
+	 static public Message random() {
+		  Random generator = new Random();
+		  int s = generator.nextInt(6);
+		  int l = generator.nextInt(4);
+		  String m = new Long(System.currentTimeMillis()).toString();
+		  return new Message(s,l,m);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/WGet.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/WGet.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/WGet.java	(revision 13666)
@@ -0,0 +1,356 @@
+package org.greenstone.gatherer;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.Job;
+import org.greenstone.gatherer.util.GURL;
+/** 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 WGet
+	 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;
+	/** The panel that the task list will be shown it. */
+	 private JPanel list_pane;
+	/** The job currently underway. */
+	 private Job 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;
+	/** A static flag used to switch between simple and advanced modes. If <i>true</i> the Process object is used to externally call the Wget program. If <i>false</i> the native WGet libraries are statically loaded and the JNI used to download directly. */
+	 static final private boolean simple = true;
+	 /** Load the WGet native library. */
+	 static {
+		  if(!simple) {
+				System.load(System.getProperty("user.dir") + File.separator + "libgatherer.so");
+		  }
+	 }
+
+	 /** Constructor. Nothing special. */
+	 public WGet() {
+		  job = null;
+		  job_queue = new Vector();
+		  list_pane = new JPanel();
+		  list_pane.setLayout(new BoxLayout(list_pane, BoxLayout.Y_AXIS));
+		  //list_pane.setLayout(new GridLayout(1,1));
+		  list_scroll = new JScrollPane(list_pane);
+		  //list_scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+	 }
+
+	 /** Called by the WGet native code to inform us of a new download starting within the given job.
+	 * @param url The url that is being downloaded, as a <strong>String</strong>.
+	 * @see org.greenstone.gatherer.collection.Job
+	 */
+	 public synchronized void addDownload(String url) {
+		  job.addDownload(url);
+	 }
+
+	 /* Used to advise the Job of a newly parsed link. Its up to Job to decide if it already knows about this url, and if not to update its progress bar.
+	  * @param url The url in question as a <strong>String</strong>.
+	  * @param type <i>true</i> if this is an internal link, <i>false</i> for and external one.
+	  * @return A <i>boolean</i> with a value of <i>true</i> indicating if the url was added, <i>false</i> otherwise.
+	  * @see org.greenstone.gatherer.collection.Job
+	  */
+	 public synchronized boolean addLink(String url, int type) {
+		  return job.addLink(url, type);
+	 }
+
+	 /* Whenever files are moved into or out of the collection we need to
+	  * run convertLinks on the files remaining. This ensures that we have
+	  * the most efficient balance between local and absolute links.
+	  * @param records A <strong>Vector</strong> containing information about the files in
+	  * the current collection. From these url and file information is
+	  * harvested.
+	  */
+	 // public void convertLinks(Vector records) {
+	 public void convertLinks() {
+		  Vector args = new Vector();
+	 Vector files = new Vector();
+	 Vector urls = new Vector();
+	 // Args - there ain't many
+	 args.add("-d");
+	 args.add("-o");
+	 args.add("debug.txt");
+	 args.add("-P");
+	 args.add("/tmp/");
+
+	 // Downloaded urls (two entries for each record). The pattern here is:
+	 // local file
+	 // original url of file
+	 /*
+	 for(Enumeration e = records.elements(); e.hasMoreElements();) {
+		  urls.add(((GURL)e).getLocalName());
+		  urls.add(((GURL)e).getURL());
+	 }
+	 */
+	 //urls.add("/tmp//www.cs.waikato.ac.nz/index.html");
+	 //urls.add("http://www.cs.waikato.ac.nz/index.html");
+	 //urls.add("/tmp//www.cs.waikato.ac.nz/events.html");
+	 //urls.add("http://www.cs.waikato.ac.nz/events.html");
+	 //urls.add("/tmp//www.cs.waikato.ac.nz/history.html");
+	 //urls.add("http://www.cs.waikato.ac.nz/history.html");
+	 //urls.add("/tmp//www.cs.waikato.ac.nz/icons/cs_title_logo.gif");
+	 //urls.add("http://www.cs.waikato.ac.nz/icons/cs_title_logo.gif");
+	 //urls.add("/tmp//www.cs.waikato.ac.nz/icons/scms_title_logo.gif");
+	 //urls.add("http://www.cs.waikato.ac.nz/icons/scms_title_logo.gif");
+
+	 // Downloaded files (html only). We race back through our records
+	 // looking for html/text content ones.
+	 /*
+	 for(Enumeration e = records.elements(); e.hasMoreElements(); ) {
+		  GURL record = (GURL)e;
+		  if(record.isHTML()) {
+				files.add(record.getLocalName());
+		  }
+	 }
+	 */
+	 //files.add("/tmp//www.cs.waikato.ac.nz/index.html");
+
+	 //wren(args.size(), args.toArray(), urls.size(), urls.toArray(),
+	 //		files.size(), files.toArray());
+  }
+
+	 /** This method is called to delete a certain job from the queue.
+	  * This job may be pending, complete or even in progress. However
+	  * if it is currently downloading then the delete method must
+	  * wait until the native job has cleanly exited before removing
+	  * the job.
+	  * @param delete_me The <strong>Job</strong> that is to be deleted.
+	  */
+	 public void deleteJob(Job delete_me) {
+		  if(delete_me == job) {
+				// While this seems wasteful its only for the briefest moment.
+				while(busy) {
+				}
+				job = null;
+		  }
+		  if(delete_me.hasSignalledStop()) {
+				list_pane.remove(delete_me.getProgressBar());
+				list_pane.updateUI();
+				job_queue.remove(delete_me);
+		  }
+		  else {
+				Gatherer.println("Somehow we're trying to delete a job that is still running.");
+		  }
+	 }
+
+  /** Called by the WGet native code when the current download,
+	* for the indicated job, is completed. In turn all download
+	* listeners are informed.
+	* @see org.greenstone.gatherer.collection.Job
+	*/
+  public synchronized void downloadComplete() {
+	 job.downloadComplete();
+  }
+
+  /** Called by the WGet native code when the requested download returns
+	* a status code other than 200-399 for the specified download job.
+	* for.
+	* @see org.greenstone.gatherer.collection.Job
+	*/
+  public synchronized void downloadFailed() {
+	 // Add the failed download as a new job if the user so requests.
+	 job.downloadFailed();
+  }
+
+  /** Called by the WGet native code when some non-fatal error has caused
+	* a download to fail. An example of a warning would be if a file can't
+	* be downloaded as doing so would clobber an existing file and the -nc
+	* flag is set.
+	* @see org.greenstone.gatherer.collection.Job
+	*/
+  public synchronized void downloadWarning() {
+	 job.downloadWarning();
+  }
+
+	 /** Used by other graphic functions to get a reference to the
+	  * scroll pane containing the current list of jobs.
+	  */
+	 public JScrollPane getJobList() {
+		  return list_scroll;
+	 }
+
+  /** Returns the current state of the stop flag for the job indicated.
+	* @return A boolean representing whether the user has requested to
+	* stop.
+	* @see org.greenstone.gatherer.collection.Job
+	*/
+  public synchronized boolean hasSignalledStop() {
+	 return job.hasSignalledStop();
+  }
+
+	 /** Creates a new mirroring job on the queue given the target url and the destination (private, public). All other details are harvested from the config file, but these two must be  captured from the GUI's current state.
+	  * @param url A <strong>GURL</strong> which points to the root url for the mirroring.
+	  * @param model The <strong>GTreeModel</strong> that any new records should be added to.
+	  * @param destination The destination file as a <strong>String</strong>.
+	  * @see org.greenstone.gatherer.Configuration
+	  * @see org.greenstone.gatherer.Gatherer
+    * @see org.greenstone.gatherer.collection.Job
+	  * @see org.greenstone.gatherer.gui.GProgressBar
+	  * @see org.greenstone.gatherer.util.GURL
+	  */
+	 public void newJob(GURL url, TreeModel model, String destination) {
+		  if(url.valid()) {
+				// Create the job and fill in the details from gatherer.config.
+				Gatherer.println("About to create a new job");
+				Job new_job = new Job(model, Gatherer.config.get("mirroring.overwrite", false), Gatherer.config.get("mirroring.debug", false), Gatherer.config.get("mirroring.no_parents", false), Gatherer.config.get("mirroring.other_hosts", false), Gatherer.config.get("mirroring.page_requisites", false), Gatherer.config.get("mirroring.quiet", false), url, Gatherer.config.getInt("mirroring.depth", false), destination, Gatherer.config.proxy_pass, Gatherer.config.proxy_user, this, simple);
+				// Add to job_queue job list.
+				job_queue.add(new_job);
+				// Now add it to the visual component, job list.
+				list_pane.add(new_job.getProgressBar());
+				//list_pane.setAlignmentX(Component.LEFT_ALIGNMENT);
+				list_pane.updateUI();
+				new_job = null;
+				synchronized(this) {
+					 notify(); // Just incase its sleeping.
+				}
+		  }
+	 }
+
+  /** Called by the WGet native code to signal the current progress of
+	* downloading for the specified job.
+	* @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.
+	* @see org.greenstone.gatherer.collection.Job
+	*/
+  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.
+	 }
+  }
+
+  /* This begins the WGet thread, which simply iterates through the waiting
+	* jobs attempting each one. Successful downloads are removed from the
+	* waiting list.
+	* @see org.greenstone.gatherer.Gatherer
+	* @see org.greenstone.gatherer.collection.Job
+	*/
+  public void run() {
+	 while(true) {
+		// If there are jobs job_queue and we have more room.
+		if(job_queue.size() > 0) {
+		  // Get the first job that isn't stopped.
+		  for(Enumeration e = job_queue.elements(); e.hasMoreElements();) {
+			 job = (Job) e.nextElement();
+			 if(job.getState() == Job.RUNNING) {
+				Gatherer.println("Job " + job.toString() + " Begun.");
+				// A lock to prevent us deleting this job while its being
+				// run, unless you want things to go really wrong.
+				busy = true;
+				if(simple) {
+					 job.callWGet();
+				}
+				else {
+					 job.callWGetNative();
+				}
+				busy = false;
+				Gatherer.println("Job " + job.toString() + " complete.");
+				// And if the user has requested that complete jobs
+				// be removed, then remove it from the list.
+				if(remove_complete_jobs) {
+					 deleteJob(job);
+				}
+				job = null;
+			 }
+		  }
+		}
+		// In order to save processor time, I'll suspend the thread
+		// if theres no advantage to it running. Actions such as
+		// new or complete jobs will resume the thread.
+		else {
+		  try {
+			 synchronized(this) {
+				  Gatherer.println("WGet thread is waiting for Jobs.");
+				  wait();
+			 }
+		  } catch (InterruptedException e) {
+			 // Time to get going again.
+		  }
+		}
+	 } // End While.
+  }
+
+  /* Link to the call to the WGet Native method for downloading.
+	* @param argc An int representing the number of elements in argv.
+	* @param argv An array of objects passed as arguments to wget.
+	* @param debug Whether the native code should show java-only debug
+	* messages.
+	*/
+  public native int wget(int argc, Object argv[], boolean debug);
+
+  /* Link to the call to the WGet Native method for converting url links.
+	* @param argc An int representing the number of object elements in argv.
+	* @param argv An array of objects passed as arguments to wget.
+	* @param urlc An int representing the number of url string elements
+	* in urlv.
+	* @param urlv An array of strings representing urls.
+	* @param filec An int representing the number of file string elements
+	* in filev.
+	* @param filev An array of strings representing files.
+	*/
+   public native void wren(int argc, Object argv[], int urlc, Object urlv[], int filec, Object filev[]);
+}
+
+
+
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/Argument.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/Argument.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/Argument.java	(revision 13666)
@@ -0,0 +1,375 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+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:      01/05/02
+ * Revised:      16/08/02 Optimized and Commented.
+ **************************************************************************************/
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.HashMap;
+/** 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 Digital Library, University of Waikato
+ * @version 2.3
+ */
+
+// ####################################################################################
+// Optimization                          Saving
+// ####################################################################################
+// Vector -> ArrayList                   + Memory, + Processor (pos. - Processor)
+// Hashtable -> HashMap                  + Processor
+// int -> byte (x7)                      + Memory (168b)
+// External method calls                 + Memory, Processor
+// ####################################################################################
+
+public class Argument
+	 implements Comparable, Serializable {
+	 /** If this argument has multiple values, then they are stored here. This was originally a Hashtable, but since the synchronization overhead is unwarrented it was changed to a HashMap. */
+	 private ArrayList values = null;
+	 /** <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. Initially an int, but bytes are cheaper. */
+	 private byte type = FLAG;
+	 /** 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 HashMap 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 desc = 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;
+	 /** If this argument has been assigned, what is its value. Must be non-null for the argument to be printed. */
+	 private String value = null;
+	 /** An element of the argument type enumeration. */
+	 static final public byte ENUM = 0;
+	 /** An element of the argument type enumeration. */
+	 static final public byte FLAG = 1;
+	 /** An element of the argument type enumeration. */
+	 static final public byte HIERARCHY = 2;
+	 /** An element of the argument type enumeration. */
+	 static final public byte INTEGER = 3;
+	 /** An element of the argument type enumeration. */
+	 static final public byte LANGUAGE = 4;
+	 /** An element of the argument type enumeration. */
+	 static final public byte METADATA = 5;
+	 /** An element of the argument type enumeration. */
+	 static final public byte METADATUM = 6;
+	 /** An element of the argument type enumeration. */
+	 static final public byte STRING = 7;
+	 /** Default Constructor. */
+	 public Argument() {
+	 }
+	 /** Normal Constructor, based on data parsed from an information script.
+	  * @param name The argument flag as it appears in the command, as a <strong>String</strong>. Also used as the unique identifier of an argument.
+	  * @param desc The text description of this argument parsed from the output as a <strong>String</strong>.
+	  * @param type The type of this argument as a <i>byte</i>.
+	  * @param default_value The default value for a parameter type argument, which may include a Perl type regular expression, as a <strong>String</strong>.
+	  */
+	 public Argument(String name, String desc, byte type, String default_value) {
+		  this.default_value = default_value;
+		  this.desc = desc;
+		  this.name = name;
+		  this.type = type;
+		  if(type == ENUM) {
+				this.list = new HashMap();
+		  }
+		  if(type == METADATUM) {
+				values = new ArrayList();
+		  }
+	 }
+	 /** Method to add an element to the option list.
+	  * @param name The name value of the option as a <strong>String</strong>.
+	  * @param desc The description of this options as a <strong>String</strong>.
+	  */
+	 public void addOption(String name, String desc) {
+		  if(type == ENUM && name != null) {
+				if(desc == null) {
+					 desc = "";
+				}
+				if(!list.containsKey(name)) {
+					 list.put(name, desc);
+				}
+		  }
+	 }
+	 /** Method to compare two arguments for ordering.
+	  * @param object The argument we are comparing to, as an <strong>Object</strong>.
+	  * @return An <i>int</i> specifying the argument order, using values as set out in String.
+	  * @see java.lang.String#compareTo
+	  * @see org.greenstone.gatherer.cdm.Argument
+	  */
+	 public int compareTo(Object object) {
+		  Argument argument = (Argument)object;
+		  return getName().compareTo(argument.getName());
+	 }
+	 /** Method to deep copy this argument.
+	  * @return A newly created <strong>Argument</strong> which has the same details as this one.
+	  */
+	 public Argument copy() {
+		  Argument copy = new Argument(name, desc, type, default_value);
+		  copy.setRequired(required);
+		  if(values != null) {
+				copy.setValues(values);
+		  }
+		  if(list != null) {
+				HashMap list_deep_copy = new HashMap();
+				Iterator it = list.keySet().iterator();
+				while(it.hasNext()) {
+					 String key = (String) it.next();
+					 String desc = (String) list.get(key);
+					 list_deep_copy.put(new String(key), new String(desc));
+				}
+				copy.setOptions(list_deep_copy);
+		  }
+		  return copy;
+	 }
+	 /** Method to determine if two arguments are equal.
+	  * @param object The argument to test against, as an <strong>Object</strong>.
+	  * @return <i>true</i> if the arguments names match, <i>false</i> otherwise.
+	  */
+	 public boolean equals(Object object) {
+		  return (compareTo(object) == 0);
+	 }
+	 /** Method to retrieve the value of default_value.
+	  * @return A <strong>String</strong> containing the default value.
+	  */
+	 public String getDefaultValue() {
+		  return default_value;
+	 }
+	 /** Method to retrieve this arguments description.
+	  * @return A <strong>String</strong> containing the description.
+	  */
+	 public String getDesc() {
+		  return desc;
+	 }
+	 /** Method to retrieve the description of a certain list option value.
+	  * @param key The <strong>String</strong> whose description we are searching for.
+	  * @return The description of the desired key as a <strong>String</strong> which may be empty if no such key exists.
+	  */
+	 public String getDesc(String key) {
+		  if(list.containsKey(key)) {
+				return (String)list.get(key);
+		  }
+		  return "";
+	 }
+	 /** Method to retrieve the option list for this argument.
+	  * @return A <strong>HashMap</strong> containing &lt;option value&gt; -&gt; &lt;description&gt; entries.
+	  */
+	 public HashMap getList() {
+		  return list;
+	 }
+	 /** Method to retrieve the value of name.
+	  * @return A <strong>String</strong> containing the argument name.
+	  */
+	 public String getName() {
+		  return name;
+	 }
+	 /** Retrieve the name of the owner of this argument.
+	  * @return The owners name as a <strong>String</strong>.
+	  */
+	 public String getOwner() {
+		  return owner;
+	 }
+	 /** Method to determine the type of this argument.
+	  * @return An <i>byte</i> specifying the type.
+	  */
+	 public byte getType() {
+		  return type;
+	 }
+	 /** Method to retrieve the value of value.
+	  * @return The value of value as a <strong>String</strong>.
+	  */
+	 public String getValue() {
+		  return value;
+	 }
+	 /** Retrieve the vector of values.
+	  * @return An <strong>ArrayList</strong> of values.
+	  */
+	 public ArrayList getValues() {
+		  return values;
+	 }
+	 /** Method to determine if this argument has been assigned.
+	  * @return <i>true</i> if it has, <i>false</i> otherwise.
+	  */
+	 public boolean isAssigned() {
+		  return (required || value != null || (values != null && values.size() > 0));
+	 }
+	 /** Method to determine of this argument is required for the associated script to work.
+	  * @return <i>true</i> if this argument is required, <i>false</i> otherwise.
+	  */
+	 public boolean isRequired() {
+		  return required;
+	 }
+	 /** Method to allow for the activation of arguments that might never have their setValue() method called.
+	  * @param new_state The required state as a <i>boolean</i>.
+	  */
+	 public void setAssigned(boolean new_state) {
+		  if(new_state && (value == null || values == null)) {
+				value = "";
+		  }
+		  else {
+				value = null;
+		  }
+	 }
+	 /** Sets the value of default_value.
+	  * @param new_default_value The new value for default_value as a <strong>String</strong>.
+	  */
+	 public void setDefault(String new_default_value) {
+		  default_value = new_default_value;
+	 }
+	 /** Set the value of desc.
+	  * @param new_desc The new value of desc as a <strong>String</strong>.
+	  */
+	 public void setDesc(String new_desc) {
+		  desc = new_desc;
+	 }
+	 /** Set the value of name.
+	  * @param new_name The new value of name as a <strong>String</strong>.
+	  */
+	 public void setName(String new_name) {
+		  name = new_name;
+	 }
+	 /** Sets the value of the options list.
+	  * @param new_list The new options list as a <strong>HashMap</strong>.
+	  */
+	 public void setOptions(HashMap new_list) {
+		  list = new_list;
+	 }
+	 /** Set the owner of this argument.
+	  * @param owner The name of the owner of this argument as a <strong>String</strong>.
+	  */
+	 public void setOwner(String owner) {
+		  this.owner = owner;
+	 }
+	 /** Set the value of required.
+	  * @param new_required The new value of required as a <i>boolean</i>.
+	  */
+	 public void setRequired(boolean new_required) {
+		  required = new_required;
+	 }
+	 /** Set the value of type.
+	  * @param new_type The new value of type as an <i>byte</i>.
+	  */
+	 public void setType(byte new_type) {
+		  type = new_type;
+		  if(type == ENUM) {
+				list = new HashMap();
+		  }
+		  if(type == METADATUM && values == null) {
+				values = new ArrayList();
+		  }
+	 }
+	 /** Set the value of type, by matching a type to the given string.
+	  * @param new_type A <strong>String</strong> which contains the name of a certain argument type.
+	  */
+	 public void setType(String new_type) {
+		  if(new_type.equalsIgnoreCase("enum")) {
+				this.type = ENUM;
+				list = new HashMap();
+		  }
+		  else if(new_type.equalsIgnoreCase("flag")) {
+				this.type = FLAG;
+		  }
+		  else if(new_type.equalsIgnoreCase("hierarchy")) {
+				this.type = HIERARCHY;
+		  }
+		  else if(new_type.equalsIgnoreCase("int")) {
+				this.type = INTEGER;
+		  }
+		  else if(new_type.equalsIgnoreCase("language")) {
+				this.type = LANGUAGE;
+		  }
+		  else if(new_type.equalsIgnoreCase("metadata")) {
+				this.type = METADATA;
+		  }
+		  else if(new_type.equalsIgnoreCase("metadatum")) {
+				this.type = METADATUM;
+				if(values == null) {
+					 values = new ArrayList();
+				}
+		  }
+		  else if(new_type.equalsIgnoreCase("string")) {
+				this.type = STRING;
+		  }
+	 }
+	 /** Method to set the value of value.
+	  * @param new_value The new value of value as a <strong>String</strong>.
+	  */
+	 public void setValue(String new_value) {
+		  this.value = new_value;
+	 }
+	 /** 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 new_values An <strong>ArrayList</strong> of values.
+	  */
+	 public void setValues(ArrayList new_values) {
+		  values = new_values;
+	 }
+	 /** Method for translating the data of this class into a string.
+	  * @return A <strong>String</strong> containing a fragment of the total arguments string.
+	  */
+	 public String toString() {
+		  switch(type) {
+		  case FLAG:
+				return "-" + name;
+		  case METADATUM:
+				String text = "-" + name + " ";
+				for(int i = 0; i < values.size(); i++) {
+					 text = text + values.get(i).toString();
+					 if(i < values.size() - 1) {
+						  text = text + ",";
+					 }
+				}
+				return text;
+		  default:
+				return "-" + name + " " + value;
+		  }
+	 }
+}
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/ArgumentConfiguration.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/ArgumentConfiguration.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/ArgumentConfiguration.java	(revision 13666)
@@ -0,0 +1,936 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+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:      01/05/02
+ * Revised:      16/08/02 Optimized and Commented. Added destructor.
+ **************************************************************************************/
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.KeyEvent;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
+import javax.swing.DefaultListModel;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.Argument;
+import org.greenstone.gatherer.cdm.ArgumentContainer;
+import org.greenstone.gatherer.cdm.Classifier;
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.cdm.PlugIn;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.valuetree.GValueModel;
+/** 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
+ */
+// ####################################################################################
+// Optimization                          Saving
+// ####################################################################################
+// Vector -> ArrayList                   + Processor
+// Hashtable -> HashMap                  + Processor
+// Remove several global references      + Memory (1Kb+)
+// ####################################################################################
+
+public class ArgumentConfiguration
+	 extends JDialog
+	 implements ActionListener {
+	 /** The data whose arguments we are editing. */
+	 private ArgumentContainer data = null;
+	 /** Argument these argument controls coloured or uncoloured (alternates to indicate inheritance). */
+	 private boolean coloured = false;
+	 /** 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 reference to the main CollectionDesignManager class for access to other managers. */
+	 private CollectionDesignManager manager = null;
+	 /** A reference to the Gatherer. */
+	 private Gatherer gatherer = null;
+	 /** 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 field for entering custom arguments. */
+	 private JTextField custom = null;
+	 /** The name of the owner of the last argument control. */
+	 private String previous_owner = 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, 400);
+	 /** Constructor.
+	  * @param gatherer A reference to the <strong>Gatherer</strong>.
+	  * @param manager The <strong>CollectionDesignManager</strong> for access to other configuration managers.
+	  * @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(Gatherer gatherer, CollectionDesignManager manager, ArgumentContainer data) {
+		  super(gatherer.g_man);
+		  this.data = data;
+		  this.gatherer = gatherer;
+		  this.manager = manager;
+		  this.self = this;
+		  String custom_str = data.getCustom();
+		  // Create
+		  setModal(true);
+		  setSize(SIZE);
+		  setTitle(get("Title"));
+		  JPanel button_pane = new JPanel();
+		  cancel = new JButton(get("General.Cancel"));
+		  cancel.setMnemonic(KeyEvent.VK_C);
+		  central_pane = new JPanel();
+		  JPanel content_pane = (JPanel) getContentPane();
+		  if(custom_str != null) {
+				custom = new JTextField(custom_str);
+		  }
+		  else {
+				custom = new JTextField();
+		  }
+		  JLabel custom_label = new JLabel(get("Custom"));
+		  custom_label.setPreferredSize(LABEL_SIZE);
+		  JPanel custom_pane = new JPanel();
+		  String args[] = new String[1];
+		  args[0] = data.getName();
+		  JLabel header = new JLabel(get("Header",args));
+		  args = null;
+		  header.setHorizontalAlignment(JLabel.CENTER);
+		  header.setOpaque(true);
+		  JPanel header_pane = new JPanel();
+		  ok = new JButton(get("General.OK"));
+		  ok.setMnemonic(KeyEvent.VK_O);
+		  // Listeners
+		  cancel.addActionListener(this);
+		  ok.addActionListener(this);
+		  // Layout
+		  custom_pane.setLayout(new BorderLayout());
+		  custom_pane.add(custom_label, BorderLayout.WEST);
+		  custom_pane.add(custom, BorderLayout.CENTER);
+
+		  header_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+		  header_pane.setLayout(new BorderLayout());
+		  header_pane.add(header, BorderLayout.NORTH);
+		  header_pane.add(custom_pane, BorderLayout.CENTER);
+
+		  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_pane, 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 = gatherer.config.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) {
+				// Update the details stored in the data objects arguments.
+				if(custom.getText().length() > 0) {
+					 data.setCustom(custom.getText());
+				}
+				// 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) {
+						  // Once cont goes false it stays false
+						  cont = cont && ((ArgumentControl)component).updateArgument();
+					 }
+				}
+				if(cont) {
+					 success = true;
+				}
+		  }
+		  if(cont) {
+				dispose();
+		  }
+	 }
+	 /** Destructor. */
+	 public void destroy() {
+		  cancel = null;
+		  central_pane = null;
+		  custom = null;
+		  data = null;
+		  gatherer = null;
+		  manager = 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() {
+		  show();
+		  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(Gatherer.config.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() {
+		  ArrayList arguments = data.getArguments();
+		  int total_height = 250;
+		  int size = arguments.size();
+		  for(int i = 0; i < size; i++) {
+				Argument argument = (Argument) arguments.get(i);
+				ArgumentControl argument_control = new ArgumentControl(argument);
+				total_height = total_height - argument_control.getPreferredSize().height;
+				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);
+		  }
+	 }
+	 /** Method to retrieve a phrase from the dictionary based on a key.
+	  * @param key A <strong>String</strong> used to find the correct phrase.
+	  * @param args A <strong>String[]</strong> of arguments used in formatting and filling out the phrase.
+	  * @return A <strong>String</strong> containing the correct phrase with the correct formatting.
+	  */
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+	 /** Method to retrieve a phrase from the dictionary based on a key.
+	  * @param key A <strong>String</strong> used to find the correct phrase.
+	  * @return A <strong>String</strong> containing the correct phrase with the correct formatting.
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf(".") == -1) {
+				key = "CDM.ArgumentConfiguration." + key;
+		  }
+		  return gatherer.dictionary.get(key, args);
+	 }
+	 /** This class encapsulates all the technical difficulty of creating a specific control based on an Argument. */
+	 private class ArgumentControl
+		  extends JPanel {
+		  /** The Argument this control will be based on. */
+		  private Argument argument = null;
+		  /** One of a possible two buttons available for adding to this control. */
+		  private JButton one = null;
+		  /** The second of two buttons available for adding to this control. */
+		  private JButton two = 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 = null;
+		  /** Can be used in place of the other editor components if a list is required. */
+		  private JList list = null;
+		  /** Constructor.
+			* @param argument The <strong>Argument</strong> this control will be built around.
+			* @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.AddListener
+			* @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.EnabledListener
+			* @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.HierarchyListener
+			* @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.ListOption
+			* @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.RemoveListener
+			* @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.ToolTipUpdater
+			*/
+		  public ArgumentControl(Argument argument) {
+				this.argument = argument;
+				String tip = "<html>" + argument.getDesc() + "</html>";
+				tip = Utility.formatHTMLWidth(tip, 60);
+				// If this is the first control, there is no history.
+				if(previous_owner == null) {
+					 previous_owner = argument.getOwner();
+					 addHeader(previous_owner, Color.white);
+				}
+				// Otherwise if the owner of the control has changed since the last argument, toggle the colouring of the control.
+				else if(previous_owner != argument.getOwner()) {
+					 coloured = !coloured;
+					 previous_owner = argument.getOwner();
+					 addHeader(previous_owner, (coloured ? Gatherer.config.getColor("coloring.collection_tree_background", false) : Color.white));
+				}
+				// Create
+				if(coloured) {
+					 setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				}
+				else {
+					 setBackground(Color.white);
+				}
+				JLabel owner_label = new JLabel(argument.getOwner());
+				owner_label.setOpaque(false);
+				JLabel label = new JLabel(argument.getName());
+				label.setOpaque(false);
+				label.setPreferredSize(LABEL_SIZE);
+				label.setToolTipText(tip);
+				enabled = new JCheckBox(argument.getName());
+				enabled.setOpaque(false);
+				enabled.setPreferredSize(LABEL_SIZE);
+				enabled.setToolTipText(tip);
+				JPanel inner_pane = new JPanel();
+				inner_pane.setOpaque(false);
+				String existing_value = argument.getValue();
+				String default_value = argument.getDefaultValue();
+				switch(argument.getType()) {
+				case Argument.ENUM:
+					 // Build an option model, wrapping each entry of the list table.
+					 HashMap arg_list = argument.getList();
+					 ArrayList options_model = new ArrayList();
+					 Iterator it = arg_list.keySet().iterator();
+					 while(it.hasNext()) {
+						  String key = (String) it.next();
+						  options_model.add(new ListOption(key, (String)arg_list.get(key)));
+					 }
+					 Collections.sort(options_model);
+					 value = new JComboBox(options_model.toArray());
+					 ((JComboBox)value).addActionListener(new ToolTipUpdater());
+					 if(existing_value != null) {
+						  // Select the correct value. Since they're all text strings we better iterate to be safe.
+						  selectValue((JComboBox)value, existing_value);
+					 }
+					 else if(default_value != null) {
+						  // Same as above except for default value.
+						  selectValue((JComboBox)value, default_value);
+					 }
+					 break;
+				case Argument.FLAG:
+					 // Only need the check box.
+					 break;
+				case Argument.HIERARCHY:
+					 value = new JComboBox(gatherer.c_man.msm.getAssignedElements(true));
+					 /** @TODO - figure out a smarter way of allowing Greenstone extracted metadata to be selected. */
+					 ((JComboBox)value).setEditable(true);
+					 ((JComboBox)value).addItemListener(new HierarchyListener());
+					 // Now ensure we have the existing value or default value selected if either exist.
+					 if(existing_value != null) {
+						  selectValue((JComboBox)value, existing_value);
+					 }
+					 else if(default_value != null) {
+						  selectValue((JComboBox)value, default_value);
+					 }
+					 break;
+				case Argument.INTEGER:
+				case Argument.STRING:
+					 // Use a standard text field
+					 if(existing_value != null) {
+						  value = new JTextField(existing_value);
+					 }
+					 else {
+						  if(default_value != null) {
+								value = new JTextField(default_value);
+						  }
+						  // Special test just for the hfile field.
+						  else if(argument.getName().equals("hfile")) {
+								// Work through previous controls looking for the metadata one.
+								for(int i = 0; i < central_pane.getComponentCount(); i++) {
+									 Object object = central_pane.getComponent(i);
+									 if(object instanceof ArgumentControl) {
+										  ArgumentControl control = (ArgumentControl) object;
+										  if(control.toString().equals("metadata")) {
+												Object temp = control.getValue();
+												if(temp != null) {
+													 value = new JTextField(temp.toString() + ".txt");
+												}
+										  }
+
+									 }
+								}
+						  }
+						  else {
+								value = new JTextField();
+						  }
+					 }
+					 break;
+				case Argument.LANGUAGE:
+					 value = new JComboBox(manager.languages.getLanguageCodes().toArray());
+					 // Now ensure we have the existing value or default value selected if either exist.
+					 Language selected = null;
+					 if(existing_value != null) {
+						  selected = manager.languages.getLanguage(existing_value, false);
+					 }
+					 else if(default_value != null) {
+						  selected = manager.languages.getLanguage(default_value, false);
+					 }
+					 if(selected != null) {
+						  ((JComboBox)value).setSelectedItem(selected);
+					 }
+					 break;
+				case Argument.METADATA:
+					 value = new JComboBox(gatherer.c_man.msm.getAssignedElements());
+					 /** @TODO - figure out a smarter way of allowing Greenstone extracted metadata to be selected. */
+					 ((JComboBox)value).setEditable(true);
+					 // Now ensure we have the existing value or default value selected if either exist.
+					 if(existing_value != null) {
+						  selectValue((JComboBox)value, existing_value);
+					 }
+					 else if(default_value != null) {
+						  selectValue((JComboBox)value, default_value);
+					 }
+					 break;
+				case Argument.METADATUM:
+					 // Comma separated metadata values.
+					 ArrayList values = argument.getValues();
+					 value = new JComboBox(gatherer.c_man.msm.getAssignedElements());
+					 DefaultListModel model = new DefaultListModel();
+					 list = new JList(model);
+					 list.setVisibleRowCount(3);
+					 for(int i = 0; i < values.size(); i++) {
+						  model.addElement(values.get(i));
+					 }
+					 one = new JButton(get("Add"));
+					 one.addActionListener(new AddListener((JComboBox)value, list));
+					 two = new JButton(get("Remove"));
+					 two.addActionListener(new RemoveListener(list));
+					 if(argument.getValues().size() > 0 || argument.isRequired()) {
+						  enabled.setSelected(true);
+						  list.setBackground(Color.white);
+						  list.setEnabled(true);
+						  one.setEnabled(true);
+						  two.setEnabled(true);
+						  value.setEnabled(true);
+					 }
+					 else {
+						  enabled.setSelected(false);
+						  list.setBackground(Color.lightGray);
+						  list.setEnabled(false);
+						  one.setEnabled(false);
+						  two.setEnabled(false);
+						  value.setEnabled(false);
+					 }
+					 break;
+				}
+				// Enable or disable as necessary.
+				if(argument.isRequired() || argument.isAssigned()) {
+					 enabled.setSelected(true);
+					 if(value != null) {
+						  value.setOpaque(true);
+						  value.setBackground(Color.white);
+						  value.setEnabled(true);
+					 }
+				}
+				else {
+					 enabled.setSelected(false);
+					 if(value != null) {
+						  value.setOpaque(true);
+						  value.setBackground(Color.lightGray);
+						  value.setEnabled(false);
+					 }
+				}
+				// Listener
+				if(value != null && !argument.isRequired()) {
+					 enabled.addActionListener(new EnabledListener(one, two, list, value));
+				}
+				// Layout
+				if(list == null) {
+					 enabled.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+					 inner_pane.setLayout(new BorderLayout());
+					 if(argument.isRequired()) {
+						  inner_pane.add(label, BorderLayout.WEST);
+					 }
+					 else {
+						  inner_pane.add(enabled, BorderLayout.WEST);
+					 }
+					 if(value != null) {
+						  inner_pane.add(value, BorderLayout.CENTER);
+					 }
+				}
+				else {
+					 JPanel control_pane = new JPanel(new GridLayout(2,1));
+					 control_pane.add(enabled);
+					 control_pane.add(value);
+					 control_pane.setOpaque(false);
+
+					 JPanel left_pane = new JPanel(new BorderLayout());
+					 left_pane.add(control_pane, BorderLayout.CENTER);
+					 left_pane.add(one, BorderLayout.SOUTH);
+					 left_pane.setOpaque(false);
+
+					 JPanel right_pane = new JPanel(new BorderLayout());
+					 right_pane.add(new JScrollPane(list), BorderLayout.CENTER);
+					 right_pane.add(two, BorderLayout.SOUTH);
+					 right_pane.setOpaque(false);
+
+					 inner_pane.setLayout(new GridLayout(1,2));
+					 inner_pane.add(left_pane);
+					 inner_pane.add(right_pane);
+				}
+				setLayout(new BorderLayout());
+				//add(owner_label, BorderLayout.NORTH);
+				add(inner_pane, BorderLayout.CENTER);
+		  }
+		  public Object getValue() {
+				if(value instanceof JComboBox) {
+					 return ((JComboBox)value).getSelectedItem();
+				}
+				else if(value instanceof JTextField) {
+					 return ((JTextField)value).getText();
+				}
+				return null;
+		  }
+		  /** 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.ArgumentControl.ListOption
+			* @see org.greenstone.gatherer.cdm.Language
+			* @see org.greenstone.gatherer.msm.ElementWrapper
+			*/
+		  public boolean updateArgument() {
+				if(enabled.isSelected() || argument.isRequired()) {
+					 argument.setAssigned(true);
+					 String result = null;
+					 switch(argument.getType()) {
+					 case Argument.ENUM:
+						  ListOption option = (ListOption)((JComboBox)value).getSelectedItem();
+						  result = option.getValue();
+						  if(result.length() > 0) {
+								argument.setValue(result);
+						  }
+						  else {
+								if(argument.isRequired()) {
+									 String args[] = new String[1];
+									 args[0] = argument.getName();
+									 JOptionPane.showMessageDialog(self, get("Required_Argument", args), get("Error_Title"), JOptionPane.ERROR_MESSAGE);
+									 args = null;
+									 return false;
+								}
+								else {
+									 argument.setValue(null);
+								}
+						  }
+						  return true;
+					 case Argument.FLAG:
+						  // Should have already been handled above.
+						  return true;
+					 case Argument.INTEGER:
+						  result = ((JTextField)value).getText();
+						  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(self, get("Bad_Integer", args), get("Error_Title"), JOptionPane.ERROR_MESSAGE);
+									 args = null;
+									 return false;
+								}
+								argument.setValue(result);
+						  }
+						  else {
+								if(argument.isRequired()) {
+									 String args[] = new String[1];
+									 args[0] = argument.getName();
+									 JOptionPane.showMessageDialog(self, get("Required_Argument", args), get("Error_Title"), JOptionPane.ERROR_MESSAGE);
+									 args = null;
+									 return false;
+								}
+								else {
+									 argument.setValue(null);
+								}
+						  }
+						  return true;
+					 case Argument.LANGUAGE:
+						  Language language = (Language) ((JComboBox)value).getSelectedItem();
+						  argument.setValue(language.getCode());
+						  // Kinda lucked out here. Its impossible not to choose an entry from these comboboxes as they are restricted.
+						  return true;
+					 case Argument.METADATA:
+					 case Argument.HIERARCHY:
+						  argument.setValue(((JComboBox)value).getSelectedItem().toString());
+						  // Kinda lucked out here. Its impossible not to choose an entry from these comboboxes as they are restricted.
+						  return true;
+					 case Argument.METADATUM:
+						  DefaultListModel model = (DefaultListModel)list.getModel();
+						  ArrayList values = new ArrayList();
+						  for(int i = 0; i < model.size(); i++) {
+								values.add(model.get(i));
+						  }
+						  argument.setValues(values);
+						  return true;
+					 case Argument.STRING:
+						  result = ((JTextField)value).getText();
+						  if(result.length() > 0) {
+								argument.setValue(result);
+						  }
+						  else {
+								if(argument.isRequired()) {
+									 String args[] = new String[1];
+									 args[0] = argument.getName();
+									 JOptionPane.showMessageDialog(self, get("Required_Argument", args), get("Error_Title"), JOptionPane.ERROR_MESSAGE);
+									 return false;
+								}
+								else {
+									 argument.setValue(null);
+								}
+						  }
+						  return true;
+					 }
+					 return false;
+				}
+				else {
+					 argument.setAssigned(false);
+					 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>.
+			* @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.ListOption
+			* @see org.greenstone.gatherer.msm.ElementWrapper
+			*/
+		  public void selectValue(JComboBox combobox, String target) {
+				for(int i = 0; i < combobox.getItemCount(); i++) {
+					 Object object = combobox.getItemAt(i);
+					 if(object instanceof ListOption) {
+						  ListOption lo = (ListOption) object;
+						  if(lo.getValue().equals(target)) {
+								combobox.setSelectedIndex(i);
+								return;
+						  }
+					 }
+					 else if(object instanceof ElementWrapper) {
+						  if(object.toString().equals(target)) {
+								combobox.setSelectedIndex(i);
+								return;
+						  }
+					 }
+				}
+		  }
+		  /** 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).setText(value_str);
+		  }
+		  /** Listener which adds entries to a list from a combobox when fired. */
+		  private class AddListener
+				implements ActionListener {
+				/** The model behind the target list. */
+				private DefaultListModel model = null;
+				/** The source for data to be added to the list. */
+				private JComboBox source = null;
+				/** The list to add data to. */
+				private JList target = null;
+				/** Constructor.
+				 * @param source A <strong>JComboBox</strong> which serves as the source for data.
+				 * @param target A <strong>JList</strong> which serves as the target for data.
+				 */
+				public AddListener(JComboBox source, JList target) {
+					 this.model = (DefaultListModel) target.getModel();
+					 this.source = source;
+					 this.target = target;
+				}
+				/** When the add button is clicked, we attempt to add the selected metadata from the source into the target.
+				 * @param event An <strong>ActionEvent</strong> containing information about the event.
+				 * @see org.greenstone.gatherer.msm.ElementWrapper
+				 */
+				public void actionPerformed(ActionEvent event) {
+					 ElementWrapper element = (ElementWrapper) source.getSelectedItem();
+					 String name = element.toString();
+					 if(!model.contains(name)) {
+						  boolean found = false;
+						  int index = 0;
+						  while(!found && index < model.size()) {
+								String sibling = (String) model.get(index);
+								if(name.compareTo(sibling) < 0) {
+									 model.add(index, name);
+									 found = true;
+								}
+								else {
+									 index++;
+								}
+						  }
+						  if(!found) {
+								model.addElement(name);
+						  }
+					 }
+				}
+		  }
+		  /** Listens for actions apon the enable checkbox, and if detected enables or diables control appropriately. */
+		  private class EnabledListener
+				implements ActionListener {
+				/** One of two possible buttons that might have their enabled state changed by this listener. */
+				private JButton one = null;
+				/** One of two possible buttons that might have their enabled state changed by this listener. */
+				private JButton two = null;
+				/** An editor component, such as a JComboBox or JTextField, that might have its enabled state changed by this listener. */
+				private JComponent target = null;
+				/** A list which might have its enabled state changed by this listener. */
+				private JList list = null;
+				/** Constructor.
+				 * @param one A <strong>JButton</strong> whose enabled state is determined by the listener, or <i>null</i> if no button.
+				 * @param two A <strong>JButton</strong> whose enabled state is determined by the listener, or <i>null</i> if no button.
+				 * @param list A <strong>JList</strong> whose enabled state is determined by the listener, or <i>null</i> if no list.
+				 * @param list A <strong>JComponent</strong> whose enabled state is determined by the listener, or <i>null</i> if no component.
+				 */
+				public EnabledListener(JButton one, JButton two, JList list, JComponent target) {
+					 this.list = list;
+					 this.one = one;
+					 this.target = target;
+					 this.two = two;
+				}
+				/** 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) {
+					 JCheckBox source = (JCheckBox)event.getSource();
+					 if(source.isSelected()) {
+						  target.setBackground(Color.white);
+						  target.setEnabled(true);
+						  if(one != null && two != null && list != null) {
+								one.setEnabled(true);
+								two.setEnabled(true);
+								list.setBackground(Color.white);
+								list.setEnabled(true);
+						  }
+					 }
+					 else {
+						  target.setBackground(Color.lightGray);
+						  target.setEnabled(false);
+						  if(one != null && two != null && list != null) {
+								one.setEnabled(false);
+								two.setEnabled(false);
+								list.setBackground(Color.lightGray);
+								list.setEnabled(false);
+						  }
+					 }
+				}
+		  }
+		  /** If a metadata element is selected that requires an hfile, then this listener defaults that hfile. */
+		  private class HierarchyListener
+				implements ItemListener {
+				/** Any implementation of ItemListener must include this method so that we can be informed when an item from the list is selected, and generate a predetermined hfile for that selection.
+				 * @param event An <strong>ItemEvent</strong> containing information about the selection.
+				 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl
+				 * @see org.greenstone.gatherer.valuetree.GValueModel
+				 */
+				public void itemStateChanged(ItemEvent event) {
+					 // Determine if the selected element represents a hierarchy.
+					 Object temp = ((JComboBox)value).getSelectedItem();
+					 String filename = temp.toString();
+					 // Search for a argument control called hfile and enable and set value.
+					 for(int i = 0; i < central_pane.getComponentCount(); i++) {
+						  Object object = central_pane.getComponent(i);
+						  if(object instanceof ArgumentControl) {
+								ArgumentControl control = (ArgumentControl) object;
+								if(control.toString().equals("hfile")) {
+									 control.setValue(filename + ".txt");
+									 control.setEnabled(true);
+								}
+						  }
+					 }
+				}
+		  }
+		  /** A ListOption is a compound item which is constructed from several Strings. That magic part is that the length of screen real-estate used by the text version of this item is limited. */
+		  private class ListOption
+				implements Comparable {
+				/** The maximum length of this String version of this item. */
+				private int MAX_DESC = 35;
+				/** The description of the value for this item. */
+				private String description = null;
+				/** A cached value for the text value of this option, as it never changes after the first call to toString(). */
+				private String text = null;
+				/** The value for this item. */
+				private String value = null;
+				/** Constructor.
+				 * @param value The value for this item as a <strong>String</strong>.
+				 * @param description The description of the value as a <strong>String</strong>.
+				 */
+				public ListOption(String value, String description) {
+					 this.description = description;
+					 this.value = value;
+				}
+				/** Compare two possible ListOption objects for ordering.
+				 * @param object The <strong>Object</strong> to compare to.
+				 * @return An <i>int</i> indicating order as explained in String.
+				 * @see java.lang.String#compareTo
+				 */
+				public int compareTo(Object object) {
+					 return toString().compareTo(object.toString());
+				}
+				/** Tests two possible ListOption objects for equality. Uses the result from compareTo().
+				 * @param The <strong>Object</strong> which may be equal.
+				 * @return <i>true</i> if the objects are equal, <i>false</i> otherwise.
+				 */
+				public boolean equals(Object object) {
+					 return (compareTo(object) == 0);
+				}
+				/** Retrieve the description of this list item.
+				 * @return The description as a <strong>String</strong>.
+				 */
+				public String getDesc() {
+					 return description;
+				}
+				/** Retrieve the value of this list item.
+				 * @return The value as a <strong>String</strong>.
+				 */
+				public String getValue() {
+					 return value;
+				}
+				/** Convert this object into a nice readable String.
+				 * @return A <strong>String</strong> representing this object.
+				 */
+				public String toString() {
+					 if(text == null) {
+						  if(description.length() >= MAX_DESC) {
+								text = value + " - " + description.substring(0, MAX_DESC);
+						  }
+						  else {
+								text = value + " - " + description;
+						  }
+					 }
+					 return text;
+				}
+		  }
+		  /** Listener which removes entries from a list from a combobox when fired. */
+		  private class RemoveListener
+				implements ActionListener {
+				/** The model behind the target list. */
+				private DefaultListModel model = null;
+				/** The list to remove data from. */
+				private JList target = null;
+				/** Constructor.
+				 * @param target A <strong>JList</strong>.
+				 */
+				public RemoveListener(JList target) {
+					 this.model = (DefaultListModel) target.getModel();
+					 this.target = target;
+				}
+				/** When the remove button is clicked, we attempt to remove the selected metadata from the target.
+				 * @param event An <strong>ActionEvent</strong> containing information about the event.
+				 */
+				public void actionPerformed(ActionEvent event) {
+					 if(!target.isSelectionEmpty()) {
+						  int index = target.getSelectedIndex();
+						  model.remove(index);
+					 }
+				}
+		  }
+		  /** 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();
+					 ListOption lo = (ListOption)source.getSelectedItem();
+					 String description = Utility.formatHTMLWidth(lo.getDesc(), 60);
+					 source.setToolTipText(description);
+				}
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/ArgumentContainer.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/ArgumentContainer.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/ArgumentContainer.java	(revision 13666)
@@ -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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+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:
+ **************************************************************************************/
+import java.util.ArrayList;
+/** 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
+ */
+public interface ArgumentContainer {
+	 /** 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 <strong>ArrayList</strong>.
+	  */
+	 public ArrayList getArguments();
+	 /** Method to retrieve this containers custom argument string.
+	  * @return The custom arguments as a <strong>String</strong>.
+	  */
+	 public String getCustom();
+	 /** Method to retrieve the name associated with this argument container.
+	  * @return The name as a <strong>String</strong>.
+	  */
+	 public String getName();
+	 /** Method to set the custom arguments string.
+	  * @param custom The new custom argument <strong>String</strong>.
+	  */
+	 public void setCustom(String custom);
+}
+
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/Classifier.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/Classifier.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/Classifier.java	(revision 13666)
@@ -0,0 +1,265 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+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:      01/05/02
+ * Revised:      16/08/02 Optimized and Commented.
+ **************************************************************************************/
+import java.io.Serializable;
+import java.util.ArrayList;
+import org.greenstone.gatherer.cdm.Argument;
+import org.greenstone.gatherer.cdm.ArgumentContainer;
+import org.greenstone.gatherer.cdm.CustomClassifier;
+import org.greenstone.gatherer.cdm.Format;
+/** 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
+ */
+// ####################################################################################
+// Optimization                          Saving
+// ####################################################################################
+// Vector -> ArrayList (x8)              + Processor
+// ####################################################################################
+public class Classifier
+	 extends ArrayList
+	 implements ArgumentContainer, Comparable, Serializable {
+	 /** A reference to the classifier that this one inherits from. */
+	 private Classifier super_classifier = null;
+	 /** A reference to the manager of this classifier. Only available once the classifiers been assigned, always <i>null</i> for classifiers in reserve. */
+	 private ClassifierManager manager = null;
+	 /** Custom arguments (ie those unparsable from classinfo.pl) provided to this class. */
+	 private String custom = null;
+	 /** A description of this classifier. */
+	 private String desc = null;
+	 /** The name of the classifier as it would appear in the collect.cfg file. */
+	 private String name = null;
+	 /** A list of format commands that are dependant on this classifier. */
+	 private ArrayList dependant_formats = null;
+	 /** Default Constructor.
+	  */
+	 public Classifier() {
+		  super();
+		  dependant_formats = new ArrayList();
+	 }
+	 /** Constructor.
+	  * @param name The name of this classifier as a <strong>String</strong>.
+	  * @param desc A description of this classifier as a <strong>String</strong>.
+	  * @param super_classifier The super class of this classifier, as a <strong>Classifier</strong>.
+	  */
+	 public Classifier(String name, String desc, Classifier super_classifier) {
+		  this();
+		  this.desc = desc;
+		  this.name = name;
+		  this.super_classifier = super_classifier;
+	 }
+	 /** Method to add an argument to this classifier. Only adds the argument if it isn't already present.
+	  * @param argument The <strong>Argument</strong> to add.
+	  */
+	 public void addArgument(Argument argument) {
+		  if(!contains(argument)) {
+				add(argument);
+				argument.setOwner(name);
+		  }
+	 }
+	 /** Method to register a dependant format with this classifier. If the classifier changes, this format also needs to be updated.
+	  * @param format A <strong>Format</strong> which is dependant on this classifier.
+	  */
+	 public void addDependantFormat(Format format) {
+		  dependant_formats.add(format);
+	 }
+	 /** Method to compare two classifiers for ordering.
+	  * @param object The classifier we are comparing to, as an <strong>Object</strong>.
+	  * @return An <i>int</i> specifying the classifier order, using values as set out in String.
+	  * @see java.lang.String#compareTo
+	  */
+	 public int compareTo(Object object) {
+		  if(object instanceof Classifier) {
+				Classifier classifier = (Classifier) object;
+				return name.compareTo(classifier.getName());
+		  }
+		  return name.compareTo(object.toString());
+	 }
+	 /** This method produces a deep copy of this classifier. Note that this also creates a new copy of each of the super classes of classifiers as well. This is the way it should be, as each assigned classifier may have different values for the higher classifiers (such as BasPlug).
+	  * @return A newly created <strong>Classifier</strong> with the same details and Arguments as this one.
+	  * @see org.greenstone.gatherer.cdm.Argument
+	  */
+	 public Classifier copy() {
+		  Classifier copy = null;
+		  if(super_classifier == null) {
+				copy = new Classifier(name, desc, null);
+		  }
+		  else {
+				copy = new Classifier(name, desc, super_classifier.copy());
+		  }
+		  for(int i = 0; i < size(); i++) {
+				copy.addArgument(((Argument)get(i)).copy());
+		  }
+		  return copy;
+	 }
+	 /** Method to determine if two classifiers are equal.
+	  * @param object The classifier to test against, as an <strong>Object</strong>.
+	  * @return <i>true</i> if the classifier names match, <i>false</i> otherwise.
+	  * @see org.greenstone.gatherer.cdm.CustomClassifier
+	  */
+	 public boolean equals(Object object) {
+		  if(object instanceof CustomClassifier) {
+				CustomClassifier classifier = (CustomClassifier) object;
+				return (toString().equalsIgnoreCase(classifier.getCommand()));
+		  }
+		  else {
+				return(toString().equalsIgnoreCase(object.toString()));
+		  }
+	 }
+	 /** 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();
+		  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 all of the arguments available to a classifier, including both specific and general ones.
+	  * @return A <strong>Hashtable</strong> of arguments, with &lt;name&gt; -&gt; &lt;argument&gt; entries.
+	  */
+	 public ArrayList getArguments() {
+		  ArrayList all_arguments = new ArrayList(this);
+		  if(super_classifier != null) {
+				ArrayList super_arguments = super_classifier.getArguments();
+				for(int i = 0; i < super_arguments.size(); i++) {
+					 Object argument = super_arguments.get(i);
+					 if(!all_arguments.contains(argument)) {
+						  all_arguments.add(argument);
+					 }
+				}
+		  }
+		  return all_arguments;
+	 }
+	 /** Method to retrieve a classifiers custom argument information.
+	  * @return The custom arguments as a <strong>String</strong>.
+	  */
+	 public String getCustom() {
+		  return custom;
+	 }
+	 /** Method to retrieve a classifiers name.
+	  * @return A <strong>String</strong> containing the classifiers name.
+	  */
+	 public String getName() {
+		  return name;
+	 }
+	 /** Method to retrieve the position of this classifier as a special keyword or the form "CL#" where # is the classifiers order in the set of classifiers. Note that if this is called for a Classifier that has never been assigned a position of 'Search' is returned, as this is the only case where we will try to write a Classifier that does not have a manager.
+	  * @return A <strong>String</strong> containing the special position keyword.
+	  * @see org.greenstone.gatherer.cdm.ClassifierManager
+	  */
+	 public String getPositionString() {
+		  if(manager == null) {
+				return "Search";
+		  }
+		  return "CL" + (manager.indexOf(this) + 1);
+	 }
+	 /** Method to set the value of custom.
+	  * @param custom The new value of custom as a <strong>String</strong>.
+	  */
+	 public void setCustom(String custom) {
+		  this.custom = custom;
+	 }
+	 /** Method to set the value of desc.
+	  * @param desc The new value of desc as a <strong>String</strong>.
+	  */
+	 public void setDesc(String desc) {
+		  this.desc = desc;
+	 }
+	 /** Method to set the value of manager.
+	  * @param manager The new manager as a <strong>ClassifierManager</strong>.
+	  */
+	 public void setManager(ClassifierManager manager) {
+		  this.manager = manager;
+	 }
+	 /** 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_classifier.
+	  * @param super_classifier The new value of super_classifier as a <strong>Classifier</strong>, or <i>null</i> if this class has no inheritance.
+	  */
+	 public void setSuper(Classifier super_classifier) {
+		  this.super_classifier = super_classifier;
+	 }
+	 /** Method to print out this classifier as it would appear as a command within the collection configuration file.
+	  * @return A <strong>String</strong> containing a single classifier command.
+	  */
+	 public String toString() {
+		  StringBuffer text = new StringBuffer("classify ");
+		  text.append(name);
+		  text.append(" ");
+		  ArrayList arguments = getArguments();
+		  for(int i = 0; i < arguments.size(); i++) {
+				Argument argument = (Argument)arguments.get(i);
+				if(argument.isAssigned()) {
+					 text.append(argument.toString());
+					 text.append(" ");
+				}
+		  }
+		  if(custom != null) {
+				text.append(custom);
+		  }
+		  return text.toString();
+	 }
+}
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/ClassifierManager.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/ClassifierManager.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/ClassifierManager.java	(revision 13666)
@@ -0,0 +1,971 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+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:      01/05/02
+ * Revised:      16/08/02 Optimized and Commented.
+ **************************************************************************************/
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.StringReader;
+import java.lang.Exception;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.jar.JarFile;
+import javax.swing.BorderFactory;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import org.apache.xerces.parsers.DOMParser;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.Argument;
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.cdm.CommandTokenizer;
+import org.greenstone.gatherer.cdm.Classifier;
+import org.greenstone.gatherer.cdm.CustomClassifier;
+import org.greenstone.gatherer.cdm.DynamicListModel;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.msm.MSMEvent;
+import org.greenstone.gatherer.msm.MSMListener;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.greenstone.gatherer.util.Utility;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.xml.sax.InputSource;
+/** 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
+ */
+// ####################################################################################
+// Optimization                          Saving
+// ####################################################################################
+// Vector -> ArrayList                   + Memory, + Processor, (pos. - Processor)
+// Unnecessary global references         + Memory (5Kb+)
+// ####################################################################################
+public class ClassifierManager
+	 implements MSMListener {
+	 /** An interface to the Gatherer, the creator of this cdm module, for access to the Greenstone installation directory. */
+	 private Gatherer gatherer = null;
+	 /** A reference to the CollectionDesignManager for access to other configuration managers. */
+	 private CollectionDesignManager manager = null;
+	 /** The controls for editing the contents of this manager. */
+	 private Control controls = null;
+	 /** A list of assigned classifiers. */
+	 private DynamicListModel assigned = null;
+	 /** A list of known, but currently unassigned, classifiers. */
+	 private DynamicListModel reserve = null;
+	 /** We may have somehow recieved a classifier command that are, in fact, custom classifiers which can refer to classifiers that haven't been parsed yet, so this holds a list of failed commands which are retried after the loading is complete. */
+	 private ArrayList unresolved_commands = null;
+	 /** Constructor.
+	  * @param gatherer A reference to the <strong>Gatherer</strong> for access to the Dictionary.
+	  * @param manager A reference to the <strong>CollectionDesignManager</strong> itself.
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.cdm.DynamicListModel
+	  * @see org.greenstone.gatherer.collection.CollectionManager
+	  * @see org.greenstone.gatherer.msm.MetadataSetManager
+	  * @see org.greenstone.gatherer.msm.MSMListener
+	  */
+	 public ClassifierManager(Gatherer gatherer, CollectionDesignManager manager) {
+		  this.assigned = new DynamicListModel();
+		  this.gatherer = gatherer;
+		  this.manager = manager;
+		  this.unresolved_commands = new ArrayList();
+		  loadClassifiers();
+		  saveClassifiers();
+		  // Register as a MSMListener.
+		  Gatherer.c_man.getCollection().msm.addMSMListener(this);
+	 }
+	 /** Method to add a new classifier to reserve.
+	  * @param classifier The new <strong>Classifier</strong>.
+	  * @see org.greenstone.gatherer.cdm.DynamicListModel
+	  */
+	 public void addClassifier(Classifier classifier) {
+		  if(!reserve.contains(classifier)) {
+				reserve.addElement(classifier);
+		  }
+	 }
+	 /** Method to assign a classifier.
+	  * @param classifier The reserve <strong>Classifier</strong> to assign.
+	  * @see org.greenstone.gatherer.cdm.DynamicListModel
+	  */
+	 public void assignClassifier(Classifier classifier) {
+		  if(!assigned.contains(classifier)) {
+				assigned.addElement(classifier);
+				classifier.setManager(this);
+				gatherer.c_man.configurationChanged();
+		  }
+	 }
+	 /** Method to assign a classifier.
+	  * @param classifier The <strong>CustomClassifier</strong> to assign.
+	  * @see org.greenstone.gatherer.cdm.DynamicListModel
+	  */
+	 public void assignClassifier(CustomClassifier classifier) {
+		  if(!assigned.contains(classifier)) {
+				assigned.addElement(classifier);
+			   classifier.setManager(this);
+				gatherer.c_man.configurationChanged();
+		  }
+	 }
+	 /** Destructor.
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.cdm.CollectionDesignManager
+	  * @see org.greenstone.gatherer.cdm.DynamicListModel
+	  */
+	 public void destroy() {
+		  // Deregister as a listener
+		  if(gatherer.c_man != null && gatherer.c_man.msm != null) {
+				gatherer.c_man.msm.removeMSMListener(this);
+		  }
+		  // Null globals
+		  assigned = null;
+		  controls = null;
+		  gatherer = null;
+		  manager = null;
+		  reserve = null;
+		  unresolved_commands = 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 as an <strong>Object</strong> or <i>null</i> if no such classifier exists.
+	  * @see org.greenstone.gatherer.cdm.DynamicListModel
+	  */
+	 public Object getClassifier(int index) {
+		  if(0 <= index && index < assigned.size()) {
+				return assigned.get(index);
+		  }
+		  return null;
+	 }
+	 /** Method to retrieve the named classifier.
+	  * @param name The name of the desired classifier as a <strong>String</strong>.
+	  * @return The requested <strong>Classifier</strong> or <i>null</i> if no such classifier exists.
+	  * @see org.greenstone.gatherer.cdm.DynamicListModel
+	  */
+	 public Classifier getClassifier(String name) {
+		  for(int i = 0; i < reserve.size(); i++) {
+				Classifier classifier = (Classifier)reserve.get(i);
+				if(classifier.getName().equals(name)) {
+					 return classifier;
+				}
+		  }
+		  // No success.
+		  return null;
+	 }
+	 /** Method to retrieve the control for this manager.
+	  * @return A <strong>JPanel</strong> containing the controls.
+	  */
+	 public JPanel getControls() {
+		  if(controls == null) {
+				controls = new Control();
+		  }
+		  return controls;
+	 }
+	 /** Called whenever a metadata element changes significantly.
+	  * @param event A <strong>MSMEvent</strong> choc' full of event informationy goodness.
+	  */
+	 public void elementChanged(MSMEvent event) {
+		  // Don't really care, as the elements dealt with here are all live references so changes like identifier change will propagate immediately.
+	 }
+	 /** Method to find the index of the given classifier within the assigned classifiers.
+	  * @param classifier The <strong>Classifier</strong> whose index you wish to find.
+	  * @return The index of the classifier as an <i>int</i>, which has a value of -1 if the classifier was not found.
+	  * @see org.greenstone.gatherer.cdm.DynamicListModel
+	  */
+	 public int indexOf(Classifier classifier) {
+		  for(int i = 0; i < assigned.size(); i++) {
+				Classifier sibling = (Classifier) assigned.get(i);
+				if(sibling.equals(classifier)) {
+					 return i;
+				}
+		  }
+		  return -1;
+	 }
+	 /** Method to invalidate controls after a significant change in the system state.
+	  */
+	 public void invalidateControls() {
+		  if(controls != null) {
+				controls.destroy();
+		  }
+		  controls = null;
+	 }
+	 /** Method to load the details of a single plug-in.
+	  * @param classifier The classifier <strong>File</strong> you wish to load.
+	  */
+	 public void loadClassifier(File classifier) {
+		  ///ystem.err.println("Attempting to parse " + classifier.toString());
+		  Document document = null;
+		  long start;
+		  long end;
+		  // Run classinfo on this classifier, and then send the results for parsing.
+		  try {
+				String args[] = null;
+				if(Utility.isWindows()) {
+					 args = new String[4];
+					 if(Gatherer.config.perl_path != null) {
+						  args[0] = gatherer.config.perl_path + "Perl.exe";
+					 }
+					 else {
+						  args[0] = "Perl.exe";
+					 }
+					 args[1] = gatherer.config.gsdl_path + "bin" + File.separator + "script" + File.separator + "classinfo.pl";
+					 args[2] = "-xml";
+					 args[3] = getClassifierName(classifier);
+				}
+				else {
+					 args = new String[3];
+					 args[0] = "classinfo.pl";
+					 args[1] = "-xml";
+					 args[2] = getClassifierName(classifier);
+				}
+
+				// Create the process.
+				Runtime runtime = Runtime.getRuntime();
+				Process process = runtime.exec(args);
+				InputStream input_stream = process.getErrorStream();
+				BufferedReader error_in = new BufferedReader(new InputStreamReader(process.getErrorStream()));
+				String line = "";
+				StringBuffer xml = new StringBuffer("");
+				while((line = error_in.readLine()) != null) {
+					 xml.append(line);
+					 xml.append("\n");
+				}
+				// Then read the xml from the piped input stream.
+				InputSource source = new InputSource(new StringReader(xml.toString()));
+				DOMParser parser = new DOMParser();
+				parser.parse(source);
+				document = parser.getDocument();
+		  }
+		  catch (Exception error) {
+				error.printStackTrace();
+				//ystem.err.println("Error: Cannot parse " + getClassifierName(classifier));
+		  }
+		  if(document != null) {
+				parse(document.getDocumentElement());
+		  }
+	 }
+	 /** Called whenever the metadata value associated to a certain record changes. */
+	 public void metadataChanged(MSMEvent event) {
+		  FileNode record = event.getRecord();
+		  if(record != null) {
+				for(int i = 0; i < assigned.size(); i++) {
+					 Object object = assigned.get(i);
+					 if(object instanceof CustomClassifier) {
+						  CustomClassifier classifier = (CustomClassifier) object;
+						  classifier.process(record);
+					 }
+				}
+		  }
+	 }
+	 /** This method attempts to parse a classifier command from a command string taken from the collection configuration file. This process is quite complex as not only must the correct classifier be matched but also all of the parameters given must be legal. If such a command is found, the classifier is immediately assigned.
+	  * @param command The command <strong>String</strong> that may include classifier information.
+	  * @return <i>true</i> if a classifier command was parsed, <i>false</i> otherwise.
+	  * @see org.greenstone.gatherer.cdm.Argument
+	  * @see org.greenstone.gatherer.cdm.Classifier
+	  * @see org.greenstone.gatherer.cdm.CommandTokenizer
+	  */
+	 public boolean parse(String command) {
+		  String command_lc = command.toLowerCase();
+		  if(command_lc.startsWith("classify")) {
+				CommandTokenizer tokenizer = new CommandTokenizer(command);
+				if(tokenizer.countTokens() >= 2) {
+					 tokenizer.nextToken(); // Throw away 'classifier'
+					 String name = tokenizer.nextToken();
+					 // Try to locate the classifier with this name.
+					 Classifier classifier = getClassifier(name);
+					 // And if successful start to parse the arguments.
+					 if(classifier != null) {
+						  // Take a copy.
+						  classifier = classifier.copy();
+						  String key = null;
+						  while((key = tokenizer.nextToken()) != null) {
+								// Try to retrieve a matching argument.
+								Argument argument = classifier.getArgument(key);
+								if(argument != null) {
+									 // Set as assigned.
+									 argument.setAssigned(true);
+									 // And if the argument is of a parameter type, parse a parameter.
+									 if(argument.getType() != Argument.FLAG && tokenizer.hasMoreTokens()) {
+										  String value = tokenizer.nextToken();
+										  value = value.replace(':', MSMUtils.NS_SEP);
+										  argument.setValue(value);
+									 }
+								}
+								// Argument cannot be matched.
+								else {
+									 String cur_key = key;
+									 String value = tokenizer.nextToken();
+									 if(value.startsWith("-")) {
+										  key = value;
+										  value = null;
+									 }
+									 else {
+										  key = null;
+									 }
+									 String custom = classifier.getCustom();
+									 if(custom == null) {
+										  if(value == null) {
+												classifier.setCustom(cur_key);
+										  }
+										  else {
+												classifier.setCustom(cur_key + " " + value);
+										  }
+									 }
+									 else {
+										  if(value == null) {
+												classifier.setCustom(custom + " " + cur_key);
+										  }
+										  else {
+												classifier.setCustom(custom + " " + cur_key + " " + value);
+										  }
+									 }
+								}
+						  }
+						  assignClassifier(classifier);
+						  return true;
+					 }
+					 else {
+						  ///ystem.err.println("Unknown classifier");
+					 }
+				}
+		  }
+		  else if(command_lc.startsWith("customclassifier")) {
+				unresolved_commands.add(command);
+				return true;
+		  }
+		  return false;
+	 }
+	 /** 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 reserve.
+	  * @param classifier The Classifier or CustomClassifier, as an <strong>Object</strong>, to remove.
+	  * @see org.greenstone.gatherer.cdm.DynamicListModel
+	  */
+	 public void removeClassifier(Object classifier) {
+		  assigned.removeElement(classifier);
+		  gatherer.c_man.configurationChanged();
+	 }
+	 /** Method which attempts to reparse obvious classifier commands which previously referenced unresovable Classifiers.
+	  * @see org.greenstone.gatherer.cdm.Classifier
+	  * @see org.greenstone.gatherer.cdm.CommandTokenizer
+	  * @see org.greenstone.gatherer.cdm.CustomClassifier
+	  */
+	 public void reparseUnresolved() {
+		  for(int i = 0; i < unresolved_commands.size(); i++) {
+				String command = (String) unresolved_commands.get(i);
+				CommandTokenizer tokenizer = new CommandTokenizer(command);
+				if(tokenizer.countTokens() >= 6) {
+					 tokenizer.nextToken();// Loose customclassifier
+					 // Get class name.
+					 String class_name = tokenizer.nextToken();
+					 // Parse arguments.
+					 String replaces = null;
+					 String separations = null;
+					 while(tokenizer.hasMoreTokens()) {
+						  String arg_name = tokenizer.nextToken();
+						  if(arg_name.equalsIgnoreCase("-replaces")) {
+								replaces = tokenizer.nextToken();
+						  }
+						  else {
+								separations = tokenizer.nextToken();
+						  }
+					 }
+					 try {
+						  replaces = replaces.substring(2);
+						  int index = Integer.parseInt(replaces);
+						  Classifier original = (Classifier)getClassifier(index);
+						  if(original != null) {
+								Class custom_classifier_class = Class.forName("org.greenstone.gatherer.cdm.custom." + class_name);
+								CustomClassifier custom_classifier = (CustomClassifier) custom_classifier_class.newInstance();
+								custom_classifier.setGatherer(gatherer);
+								custom_classifier.recreate(original, separations);
+								assigned.add(indexOf(original), custom_classifier);
+								assigned.removeElement(original);
+						  }
+						  else {
+								///ystem.err.println("Missing original.");
+						  }
+					 }
+					 catch (Exception error) {
+						  error.printStackTrace();
+					 }
+				}
+		  }
+		  // Regardless of if they work, clear the commands.
+		  unresolved_commands.clear();
+	 }
+	 /** Method to cache the current contents of reserve (known classifiers) to file.
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public void saveClassifiers() {
+		  try {
+				FileOutputStream file = new FileOutputStream(Utility.BASE_DIR + "classifiers.dat");
+				ObjectOutputStream out = new ObjectOutputStream(file);
+				out.writeObject(reserve);
+				out.close();
+		  }
+		  catch (Exception error) {
+		  }
+	 }
+	 /** Called when a metadata set changed significantly.
+	  * @param event A <strong>MSMEvent</strong> containing information about the set change.
+	  */
+	 public void setChanged(MSMEvent event) {
+		  // Again, we would only worry about this if we contained 'inanimate' references to elements or something, but our references are live, and controls are rebuilt everytime a pop-up is needed.
+	 }
+	 /** Method used to determine the number of classifiers that have been assigned.
+	  * @return An <i>int</i> which is the number of classifiers.
+	  */
+	 public int size() {
+		  return assigned.size();
+	 }
+	 /** Method to print out a block of classifier commands, much like you'd find in a collection configuration file.
+	  * @return A <strong>String</strong> containing a series of classifier commands separated by new lines.
+	  * @see org.greenstone.gatherer.cdm.Classifier
+	  * @see org.greenstone.gatherer.cdm.CustomClassifier
+	  */
+	 public String toString() {
+		  StringBuffer text = new StringBuffer();
+		  for(int i = 0; i < assigned.size(); i++) {
+				Object object = assigned.get(i);
+				if(object instanceof Classifier) {
+					 Classifier classifier = (Classifier) object;
+					 text.append(classifier.toString());
+				}
+				else if(object instanceof CustomClassifier) {
+					 CustomClassifier classifier = (CustomClassifier) object;
+					 text.append(classifier.getCommand());
+					 text.append("\n");
+					 text.append(classifier.getCustomCommand(i));
+				}
+				text.append("\n");
+		  }
+		  text.append("\n");
+		  return text.toString();
+	 }
+	 /** Called when a significant change has occured to a value tree for a certain element, however we take no further action.
+	  * @param event A <strong>MSMEvent</strong> containing information relevant to the event.
+	  */
+	 public void valueChanged(MSMEvent event) {
+	 }
+	 /** Retrieve a phrase from the dictionary based on a certain key.
+	  * @param key The search <strong>String</strong>.
+	  * @return The matching phrase from the Dictionary.
+	  */
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+	 /** Retrieve a phrase from the dictionary based on a certain key and certain arguments.
+	  * @param key The search <strong>String</strong>.
+	  * @param args A <strong>String[]</strong> used to complete and format the returned phrase.
+	  * @return The matching phrase from the Dictionary.
+	  * @see org.greenstone.gatherer.Dictionary
+	  * @see org.greenstone.gatherer.Gatherer
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf(".") == -1) {
+				key = "CDM.ClassifierManager." + key;
+		  }
+		  return gatherer.dictionary.get(key, args);
+	 }
+	 /** Method to extract just the classifiers name from a file object.
+	  * @param classifier The <strong>File</strong> which references a certain classifier.
+	  * @return A <strong>String</strong> containing just the classifiers name, without extension.
+	  */
+	 private String getClassifierName(File classifier) {
+		  String name = classifier.getName();
+		  if(name.indexOf(".") != -1) {
+				name = name.substring(0, name.indexOf("."));
+		  }
+		  return name;
+	 }
+	 /** Method to initially load information from the standard plug-ins within the gsdl Perl library.
+	  * @see org.greenstone.gatherer.cdm.DynamicListModel
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 private void loadClassifiers() {
+		  // Attempt to restore the cached file.
+		  try {
+				FileInputStream file = new FileInputStream(Utility.BASE_DIR + "classifiers.dat");
+				ObjectInputStream input = new ObjectInputStream(file);
+				reserve = (DynamicListModel) input.readObject();
+		  }
+		  catch (Exception error) {
+		  }
+		  if(reserve == null) {
+				reserve = new DynamicListModel();
+				// Retrieve the gsdl home directory...
+				String directory = gatherer.config.gsdl_path;
+				directory = directory + "perllib" + File.separator + "classify" + File.separator;
+				loadClassifiers(new File(directory));
+		  }
+	 }
+	 /** Method to load plug-in information from a specified directory. Of course no plug-ins may be found at this location.
+	  * @param directory A <strong>File</strong> indicating the directory to be scanned for plug-ins.
+	  * @see org.greenstone.gatherer.cdm.ParsingProgress
+	  */
+	 private void loadClassifiers(File directory) {
+		  File files[] = directory.listFiles();
+		  if(files != null) {
+				// Create a progress indicator.
+				ParsingProgress progress = new ParsingProgress(get("CDM.ClassifierManager.Parsing.Title"), get("CDM.ClassifierManager.Parsing.Message"), files.length);
+				for(int i = 0; i < files.length; i++) {
+					 // We only want to check Perl Modules.
+					 if(files[i].getName().endsWith(".pm")) {
+						  loadClassifier(files[i]);
+					 }
+					 progress.inc();
+				}
+				progress.dispose();
+				progress.destroy();
+				progress = null;
+		  }
+	 }
+	 /** Parses a DOM tree model turning it into a Classifier and its associated arguments.
+	  * @param root The <strong>Node</strong> at the root of the DOM model.
+	  * @return A newly created <strong>Classifier</strong> based on the information parsed from the DOM model.
+	  * @see org.greenstone.gatherer.cdm.Argument
+	  */
+	 private Classifier parse(Node root) {
+		  Classifier classifier = new Classifier();
+		  String node_name = null;
+		  for(Node node = root.getFirstChild(); node != null;
+				node = node.getNextSibling()) {
+				node_name = node.getNodeName();
+				if(node_name.equals("Name")) {
+					 String name = MSMUtils.getValue(node);
+					 // We can save ourselves some processing time if a classifier with this name already exists in our manager. If so retrieve it and return it.
+					 Classifier existing = getClassifier(name);
+					 if(existing != null) {
+						  return existing;
+					 }
+					 classifier.setName(name);
+				}
+				else if(node_name.equals("Desc")) {
+					 classifier.setDesc(MSMUtils.getValue(node));
+				}
+				// Parse the multitude of arguments.
+				else if(node_name.equals("Arguments")) {
+					 for(Node arg = node.getFirstChild(); arg != null; arg = arg.getNextSibling()) {
+						  node_name = arg.getNodeName();
+						  // An option.
+						  if(node_name.equals("Option")) {
+								Argument argument = new Argument();
+								// If its an option we parse the multitude of details an options might have.
+								for(Node det = arg.getFirstChild(); det != null; det = det.getNextSibling()) {
+									 node_name = det.getNodeName();
+									 if(node_name.equals("Name")) {
+										  argument.setName(MSMUtils.getValue(det));
+									 }
+									 else if(node_name.equals("Desc")) {
+										  argument.setDesc(MSMUtils.getValue(det));
+									 }
+									 else if(node_name.equals("Type")) {
+										  argument.setType(MSMUtils.getValue(det));
+									 }
+									 else if(node_name.equals("Default")) {
+										  argument.setDefault(MSMUtils.getValue(det));
+									 }
+									 else if(node_name.equals("List")) {
+										  // Two final loops are required to parse lists.
+										  for(Node value = det.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 = MSMUtils.getValue(subvalue);
+														  }
+														  else if(node_name.equals("Desc")) {
+																desc = MSMUtils.getValue(subvalue);
+														  }
+													 }
+													 if(key != null) {
+														  argument.addOption(key, desc);
+													 }
+												}
+										  }
+									 }
+									 else if(node_name.equals("Required")) {
+										  String v = MSMUtils.getValue(det);
+										  ///ystem.err.println("Required = " + v);
+										  if(v.equalsIgnoreCase("yes")) {
+												///ystem.err.println("Setting required to true.");
+												argument.setRequired(true);
+										  }
+									 }
+								}
+								classifier.addArgument(argument);
+						  }
+						  // A super classifier class.
+						  else if(node_name.equals("ClasInfo")) {
+								Classifier super_classifier = parse(arg);
+								classifier.setSuper(super_classifier);
+						  }
+					 }
+				}
+		  }
+		  if(classifier.getName() != null) {
+				addClassifier(classifier);
+				return classifier;
+		  }
+		  return null;
+	 }
+	 /** A class which provides controls for assigned and editing classifiers. */
+	 private class Control
+		  extends JPanel {
+		  /** Button for adding classifiers. */
+		  private JButton add = null;
+		  /** Button for configuring the selected classifier. */
+		  private JButton configure = null;
+		  /** Button to remove the selected classifier. */
+		  private JButton remove = null;
+		  /** A combobox containing all of the known classifiers, including those that may have already been assigned. */
+		  private JComboBox classifier = null;
+		  /** A list of assigned classifiers. */
+		  private JList classifier_list = null;
+		  /** The text area containing instructions on the use of this control. */
+		  private JTextArea instructions = null;
+		  /** Constructor.
+			* @see org.greenstone.gatherer.cdm.ClassifierManager.Control.AddListener
+			* @see org.greenstone.gatherer.cdm.ClassifierManager.Control.ConfigureListener
+			* @see org.greenstone.gatherer.cdm.ClassifierManager.Control.RemoveListener
+			*/
+		  public Control() {
+				Object classifiers[] = reserve.toArray();
+				ArrayList classifier_model = new ArrayList();
+				for(int i = 0; i < classifiers.length; i++) {
+					 classifier_model.add(((Classifier)classifiers[i]).getName());
+				}
+				// Now we add custom classifiers.
+				addCustomClassifiers(classifier_model);
+				Collections.sort(classifier_model);
+				// Create
+				add = new JButton(get("Add"));
+				JPanel button_pane = new JPanel();
+				JPanel central_pane = new JPanel();
+				configure = new JButton(get("Configure"));
+				JPanel header_pane = new JPanel();
+				instructions = new JTextArea(get("Instructions"));
+				instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				instructions.setEditable(false);
+				instructions.setLineWrap(true);
+				instructions.setRows(5);
+				instructions.setWrapStyleWord(true);
+				classifier = new JComboBox(classifier_model.toArray());
+				classifier.setEditable(true);
+				JLabel classifier_label = new JLabel(get("Classifier"));
+				classifier_list = new JList(assigned);
+				JLabel classifier_list_label = new JLabel(get("Assigned"));
+				classifier_list_label.setHorizontalAlignment(JLabel.CENTER);
+				classifier_list_label.setOpaque(true);
+				JPanel classifier_list_pane = new JPanel();
+				JPanel classifier_pane = new JPanel();
+				remove = new JButton(get("Remove"));
+				JLabel title = new JLabel(get("Title"));
+				title.setHorizontalAlignment(JLabel.CENTER);
+				title.setOpaque(true);
+				JPanel temp = new JPanel(new BorderLayout());
+				// Listeners
+				add.addActionListener(new AddListener());
+				configure.addActionListener(new ConfigureListener());
+				remove.addActionListener(new RemoveListener());
+				classifier_list.addMouseListener(new ClickListener());
+				// Layout
+				title.setBorder(BorderFactory.createEmptyBorder(0,0,2,0));
+				instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
+				header_pane.setLayout(new BorderLayout());
+				header_pane.add(title, BorderLayout.NORTH);
+				header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER);
+				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_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+				classifier_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+				classifier_pane.setLayout(new GridLayout(1,2));
+				classifier_pane.add(classifier_label);
+				classifier_pane.add(classifier);
+				button_pane.setLayout(new GridLayout(3,1));
+				button_pane.add(add);
+				button_pane.add(configure);
+				button_pane.add(remove);
+				// Scope these mad bordering skillz.
+				temp.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,0,5,0), BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(get("Controls")), BorderFactory.createEmptyBorder(2,2,2,2))));
+				temp.add(classifier_pane, BorderLayout.NORTH);
+				temp.add(button_pane, BorderLayout.SOUTH);
+				central_pane.setLayout(new BorderLayout());
+				central_pane.add(classifier_list_pane, BorderLayout.CENTER);
+				central_pane.add(temp, BorderLayout.SOUTH);
+				setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+				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 = null;
+				classifier_list = null;
+				configure = null;
+				instructions = null;
+				remove = null;
+		  }
+		  /** This method is overridden to ensure the instructions are scrolled to top, before the super classes updateUI() is called.
+			*/
+		  public void updateUI() {
+				if(instructions != null) {
+					 instructions.setCaretPosition(0);
+				}
+				super.updateUI();
+		  }
+		  /** Searches and adds a list of dynamically located CustomClassifiers. Note that the classes must be located under org.greenstone.gatherer.cdm.custom and have accompaning properties files which are used as dictionaries.
+			* @param classifier_model An <strong>ArrayList</strong> which will be used as the model for the combobox listing all known Classifiers.
+			*/
+		  private void addCustomClassifiers(ArrayList classifier_model) {
+				//classifier_model.add("CustomAZList");
+				// Search for classifiers under the org.greenstone.gatherer.cdm.custom directory.
+				File custom_directory = new File(Utility.BASE_DIR + "classes" + File.separator + "org" + File.separator + "greenstone" + File.separator + "gatherer" + File.separator + "cdm" + File.separator + "custom");
+				if(custom_directory.exists()) {
+					 File children[] = custom_directory.listFiles();
+					 for(int i = 0; i < children.length; i++) {
+						  String temp = children[i].getName().toLowerCase();
+						  // There are a whole bunch of conditions about what files are custom classifier main classes.
+						  if(temp.endsWith(".class") && temp.indexOf("$") == -1) {
+								// Determine the name of this custom classifier.
+								String name = children[i].getName();
+								name = name.substring(0, name.indexOf("."));
+								classifier_model.add(name);
+						  }
+					 }
+				}
+				// Search for any other CustomClassifiers within the jar file (if present)
+				File jar_file = new File("Gatherer.jar");
+				if(jar_file.exists()) {
+					 try {
+						  JarFile jar = new JarFile(jar_file);
+						  for(Enumeration entries = jar.entries(); entries.hasMoreElements(); ) {
+								String name = entries.nextElement().toString();
+								if(name.startsWith("org/greenstone/gatherer/cdm/custom/") && name.endsWith(".class") && name.indexOf("$") == -1) {
+									 name = name.substring(35, name.length() - 6);
+									 if(!classifier_model.contains(name)) {
+										  classifier_model.add(name);
+									 }
+								}
+								name = null;
+						  }
+						  jar = null;
+					 }
+					 catch (Exception error) {
+						  error.printStackTrace();
+					 }
+				}
+				jar_file = null;
+		  }
+		  /** This class listens for actions upon the add button in the controls, and if detected calls the assignClassifier() method.
+			*/
+		  private class AddListener
+				implements ActionListener {
+				/** Any implementation of ActionListener must include this method so that we can be informed when an action has occured on one of our target controls, so that we can add the selected Classifier.
+				 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
+				 * @see org.greenstone.gatherer.Gatherer
+				 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration
+				 * @see org.greenstone.gatherer.cdm.Classifier
+				 * @see org.greenstone.gatherer.cdm.CustomClassifier
+				 */
+				public void actionPerformed(ActionEvent event) {
+					 String name = (String)classifier.getSelectedItem();
+					 Classifier target = getClassifier(name);
+					 Classifier classifier = null;
+					 CustomClassifier custom_classifier = null;
+					 if(target != null) {
+						  classifier = target.copy();
+					 }
+					 else {
+						  // Try to retrieve custom classifier for name.
+						  try {
+								Class custom_class = Class.forName("org.greenstone.gatherer.cdm.custom." + name);
+								custom_classifier = (CustomClassifier)custom_class.newInstance();
+								custom_classifier.setGatherer(gatherer);
+						  }
+						  catch (Exception error) {
+								gatherer.debug(error, "Error in ClassifierManager.AddListener.actionPerformed(): " + error);
+						  }
+						  // And if all else fails create a new classifier.
+						  if(classifier == null && custom_classifier == null) {
+								classifier = new Classifier(name, "", null);
+						  }
+					 }
+					 if(classifier != null) {
+						  // Automatically chain to configuration. This ensures required arguments are filled out.
+						  ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, classifier);
+						  if(ac.display()) {
+								assignClassifier(classifier);
+						  }
+						  ac.destroy();
+						  ac = null;
+					 }
+					 // Custom classifier
+					 else {
+						  if(custom_classifier.display(true)) {
+								assignClassifier(custom_classifier);
+						  }
+						  custom_classifier.destroy(); // Remove gui prompt or else.
+						  custom_classifier = 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()) {
+								Object object = classifier_list.getSelectedValue();
+								if(object instanceof Classifier) {
+									 ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, (Classifier)object);
+									 if(ac.display()) {
+										  assigned.refresh();
+									 }
+									 ac.destroy();
+									 ac = null;
+								}
+								else if(object instanceof CustomClassifier) {
+									 CustomClassifier cc = (CustomClassifier)object;
+									 if(cc.display(true)) {
+										  assigned.refresh();
+									 }
+									 cc.destroy(); // Remove gui prompt or else.
+									 cc = 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
+				 * @see org.greenstone.gatherer.cdm.CustomClassifier
+				 */
+				public void actionPerformed(ActionEvent event) {
+					 if(!classifier_list.isSelectionEmpty()) {
+						  Object object = classifier_list.getSelectedValue();
+						  if(object instanceof Classifier) {
+								ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, (Classifier)object);
+								if(ac.display()) {
+									 assigned.refresh();
+								}
+								ac.destroy();
+								ac = null;
+						  }
+						  else if(object instanceof CustomClassifier) {
+								CustomClassifier cc = (CustomClassifier)object;
+								if(cc.display(true)) {
+									 assigned.refresh();
+								}
+								cc.destroy(); // Remove gui prompt or else.
+								cc = null;
+						  }
+					 }
+				}
+		  }
+		  /** This class listens for actions upon the remove button in the controls, and if detected calls the removeClassifier() 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, so we can remove the selected Classifier.
+				 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
+				 * @see org.greenstone.gatherer.cdm.Classifier
+				 * @see org.greenstone.gatherer.cdm.CustomClassifier
+				 */
+				public void actionPerformed(ActionEvent event) {
+					 if(!classifier_list.isSelectionEmpty()) {
+						  Object object = classifier_list.getSelectedValue();
+						  if(object instanceof Classifier || object instanceof CustomClassifier) {
+								removeClassifier(object);
+						  }
+					 }
+				}
+		  }
+	 }
+}
+
+
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/CollectionDesignManager.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/CollectionDesignManager.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/CollectionDesignManager.java	(revision 13666)
@@ -0,0 +1,420 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+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:      02/05/02
+ * Revised:      16/08/02 Optimized and added Destructor.
+ **************************************************************************************/
+import java.awt.BorderLayout;
+import java.awt.Rectangle;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileOutputStream;
+import java.lang.Exception;
+import java.lang.String;
+import java.lang.StringBuffer;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+import javax.swing.JPanel;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.ClassifierManager;
+import org.greenstone.gatherer.cdm.CollectionMetaManager;
+import org.greenstone.gatherer.cdm.FormatManager;
+import org.greenstone.gatherer.cdm.GUI;
+import org.greenstone.gatherer.cdm.Index;
+import org.greenstone.gatherer.cdm.IndexManager;
+import org.greenstone.gatherer.cdm.MetadataSetManager;
+import org.greenstone.gatherer.cdm.PlugInManager;
+import org.greenstone.gatherer.cdm.SubcollectionManager;
+import org.greenstone.gatherer.util.EmailAddress;
+/** 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.3
+ */
+// ####################################################################################
+// Optimization                          Saving
+// ####################################################################################
+// Vector -> ArrayList                   + Processor
+// String -> StringBuffer                + Memory, + Processor
+// ####################################################################################
+public class CollectionDesignManager {
+	 /** Whether this collection is to be made public or not. */
+	 public boolean public_col = false;
+	 /** Whether this collection is a beta version or not. */
+	 public boolean beta = true;
+	 /** A list of classifiers to use at build time. */
+	 public ClassifierManager classifiers = null;
+	 /** A manager of collection level metadata. */
+	 public CollectionMetaManager collectionmetadatum = null;
+	 /** E-mail address of the collection's creator. */
+	 public EmailAddress creator = null;
+	 /** E-mail address of the collection's maintainer. */
+	 public EmailAddress maintainer = null;
+	 /** The collection configuration file. */
+	 public File in_file = null;
+	 /** A list of formating strings to use at build time. */
+	 public FormatManager formats = null;
+	 /** The manager in charge of displaying this manager and the controls for other managers. */
+	 public GUI gui = null;
+	 /** List of indexes to be built, and the default index. */
+	 public IndexManager indexes = null;
+	 /** Contains instructions dealing with the collection language. */
+	 public LanguageManager languages = null;
+	 /** A simple manager for the visual review of metadata sets. */
+	 public MetadataSetManager metadatasets = null;
+	 /** A list of plugins to use at build time. */
+	 public PlugInManager plugins = null;
+	 /** Contains: A list of subcollections, (defined on metadatadata), a list of which subcollection indexes to build and the default subcollection index. */
+	 public SubcollectionManager subcollections = null;
+	 /** A list of whatever commands could not be parsed at all. */
+	 private ArrayList rest = null;
+	 /** A reference to the Gatherer. */
+	 private Gatherer gatherer = null;
+	 /** Constructor.
+	  * @param gatherer The <strong>Gatherer</strong> that created this class.
+	  * @see org.greenstone.gatherer.cdm.ClassifierManager
+	  * @see org.greenstone.gatherer.cdm.CollectionMetaManager
+	  * @see org.greenstone.gatherer.cdm.FormatManager
+	  * @see org.greenstone.gatherer.cdm.IndexManager
+	  * @see org.greenstone.gatherer.cdm.LanguageManager
+	  * @see org.greenstone.gatherer.cdm.MetadataSetManager
+	  * @see org.greenstone.gatherer.cdm.PlugInManager
+	  * @see org.greenstone.gatherer.cdm.SubcollectionManager
+	  */
+	 public CollectionDesignManager() {
+		  this.gatherer = Gatherer.self;
+		  this.classifiers = new ClassifierManager(gatherer, this);
+		  this.collectionmetadatum = new CollectionMetaManager(gatherer, this);
+		  this.formats = new FormatManager(gatherer, this);
+		  this.indexes = new IndexManager(gatherer, this);
+		  this.languages = new LanguageManager(gatherer, this);
+		  this.metadatasets = new MetadataSetManager(gatherer);
+		  this.plugins = new PlugInManager(gatherer, this);
+		  this.rest = new ArrayList();
+		  this.subcollections = new SubcollectionManager(gatherer);
+	 }
+	 /** In order to prevent Components that have registered themselves wasting memory, this method invalidates each of the sub-managers controls, causing them to unregister listeners.
+	  * @see org.greenstone.gatherer.cdm.ClassifierManager
+	  * @see org.greenstone.gatherer.cdm.CollectionMetaManager
+	  * @see org.greenstone.gatherer.cdm.FormatManager
+	  * @see org.greenstone.gatherer.cdm.IndexManager
+	  * @see org.greenstone.gatherer.cdm.LanguageManager
+	  * @see org.greenstone.gatherer.cdm.MetadataSetManager
+	  * @see org.greenstone.gatherer.cdm.PlugInManager
+	  * @see org.greenstone.gatherer.cdm.SubcollectionManager
+	  */
+	 public void destroy() {
+		  // Remove visual the component from its parent.
+		  if(gui.getParent() != null) {
+				gui.getParent().remove(gui);
+		  }
+		  // Remove references from persistant listeners.
+		  if(classifiers != null && formats != null && gui != null && indexes != null && languages != null && metadatasets != null && plugins != null && subcollections != null) {
+				classifiers.invalidateControls();
+				formats.invalidateControls();
+				gui.invalidateControls();
+				indexes.invalidateControls();
+				languages.invalidateControls();
+				metadatasets.invalidateControls();
+				plugins.invalidateControls();
+				subcollections.invalidateControls();
+		  }
+		  // Null globals.
+		  classifiers = null;
+		  collectionmetadatum = null;
+		  creator = null;
+		  maintainer = null;
+		  in_file = null;
+		  formats = null;
+		  gui = null;
+		  indexes = null;
+		  languages = null;
+		  metadatasets = null;
+		  plugins = null;
+		  subcollections = null;
+		  rest = null;
+		  gatherer = null;
+	 }
+
+	 /** Display the GUI interface for the CollectionDesignManager in the centre of the indicated panel.
+	  * @param target The <strong>JPanel</strong> you wish to display the GUI on.
+	  * @see org.greenstone.gatherer.cdm.GUI
+	  */
+	 public void display(JPanel target) {
+		 this.gui = new GUI(gatherer, this);
+		 target.add(gui, BorderLayout.CENTER);
+	 }
+	 /** When the tab on the JTabbedPane that contains the GUI is selected, this method is called to ensure that the controls are all up to date, in terms of references to metadata etc.
+	  * @see org.greenstone.gatherer.cdm.GUI
+	  */
+	 public void gainFocus() {
+		  gui.updateUI();
+	 }
+	 /** Retrieve the current set of indexes as defined by the user configuration.
+	  * @return An <strong>ArrayList</strong> of indexes.
+	  * @see org.greenstone.gatherer.cdm.Index
+	  * @see org.greenstone.gatherer.cdm.IndexManager
+	  */
+	 public ArrayList getIndexes() {
+		  ArrayList result = new ArrayList();
+		  int size = indexes.size();
+		  for(int i = 0; i < size; i++) {
+				result.add(indexes.getIndex(i));
+		  }
+		  return result;
+	 }
+	 /** Retrieve the name of the collection configuration file which is being used as the source of the information in this object.
+	  * @return The files absolute path as a <strong>String</strong>.
+	  */
+	 public String getFilename() {
+		  return in_file.getAbsolutePath();
+	 }
+	 /** Used to parse the given file as if it was a collection configuration file, passing any parsed commands to the relevant submanager. Currently ignores any comments, and marks any other lines as being unrecognizable if they can't be parsed.
+	  * @param filename The name of the file you wish to attempt to pass as a <strong>String</strong>.
+	  * @see org.greenstone.gatherer.cdm.ClassifierManager
+	  * @see org.greenstone.gatherer.cdm.CollectionMetaManager
+	  * @see org.greenstone.gatherer.cdm.FormatManager
+	  * @see org.greenstone.gatherer.cdm.IndexManager
+	  * @see org.greenstone.gatherer.cdm.LanguageManager
+	  * @see org.greenstone.gatherer.cdm.MetadataSetManager
+	  * @see org.greenstone.gatherer.cdm.PlugInManager
+	  * @see org.greenstone.gatherer.cdm.SubcollectionManager
+	  * @see org.greenstone.gatherer.util.EmailAddress
+	  */
+	 public void parse(String filename) {
+		  try {
+				in_file = new File(filename);
+				FileReader in_reader = new FileReader(in_file);
+				BufferedReader in = new BufferedReader(in_reader);
+				String command = null;
+				while((command = in.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 = in.readLine();
+								if(next_line != null) {
+									 command = command + next_line;
+								}
+						  }
+						  // Now we've finished parsing a command line, see what manager wants a piece of it.
+						  boolean found = false;
+						  String command_lc = command.toLowerCase();
+						  if(command_lc.startsWith("creator")) {
+								creator = new EmailAddress(gatherer, command);
+								found = true;
+						  }
+						  if(command_lc.startsWith("maintainer")) {
+								maintainer = new EmailAddress(gatherer, command);
+								found = true;
+						  }
+						  if(command_lc.startsWith("public")) {
+								if(command_lc.endsWith("true")) {
+									 public_col = true;
+								}
+								else {
+									 public_col = false;
+								}
+								found = true;
+						  }
+						  if(command_lc.startsWith("beta")) {
+								if(command_lc.endsWith("false")) {
+									 beta = false;
+								}
+								else {
+									 beta = true;
+								}
+								found = true;
+						  }
+						  if(!found) {
+								found = indexes.parse(command);
+						  }
+						  if(!found) {
+								found = subcollections.parse(command, false);
+						  }
+						  if(!found) {
+								found = languages.parse(command);
+						  }
+						  if(!found) {
+								found = plugins.parse(command);
+						  }
+						  if(!found) {
+								found = classifiers.parse(command);
+						  }
+						  if(!found) {
+								found = formats.parse(command, false);
+						  }
+						  if(!found) {
+								found = collectionmetadatum.parse(command, false);
+						  }
+						  // Metadataset commands
+						  if(command_lc.startsWith("metadataset")) {
+								// Nothing yet. Eventually used to import metadata.
+								found = true;
+						  }
+						  // Comments we ignore.
+						  if(command_lc.startsWith("# these instructions are not recognized by the gatherer.")) {
+								// Ignore
+								found = true;
+						  }
+						  // We have been unable to parse this command, add it to rest.
+						  if(!found) {
+								rest.add(command);
+						  }
+					 }
+				}
+				in.close();
+				// Now attempt to finalize any commands that were not immediately parsed as they were waiting for unresolved references.
+				subcollections.reparseUnresolved();
+				classifiers.reparseUnresolved();
+				formats.reparseUnresolved();
+				collectionmetadatum.reparseUnresolved();
+		  }
+		  catch(Exception error) {
+				error.printStackTrace();
+		  }
+	 }
+	 /** Cause the current definitions within the Collection Design Manager to be written back out to whatever collect.cfg it is based upon, taking care to change reference pointers into something more sensible within the text file.
+	  * @see org.greenstone.gatherer.cdm.ClassifierManager
+	  * @see org.greenstone.gatherer.cdm.CollectionMetaManager
+	  * @see org.greenstone.gatherer.cdm.FormatManager
+	  * @see org.greenstone.gatherer.cdm.IndexManager
+	  * @see org.greenstone.gatherer.cdm.LanguageManager
+	  * @see org.greenstone.gatherer.cdm.MetadataSetManager
+	  * @see org.greenstone.gatherer.cdm.PlugInManager
+	  * @see org.greenstone.gatherer.cdm.SubcollectionManager
+	  * @see org.greenstone.gatherer.util.EmailAddress
+	  */
+	 public void save() {
+		  try {
+				// If the file already exists (it should) rename it.
+				if(in_file.exists()) {
+					 String filename = in_file.getAbsolutePath();
+					 File backup = new File(filename + "~");
+					 backup.deleteOnExit();
+					 if(!in_file.renameTo(backup)) {
+						  gatherer.debug("Error in CollectionDesignManager.parse(): FileRenamedException");
+					 }
+					 in_file = new File(filename); // Just in case we moved it.
+				}
+				FileOutputStream out = new FileOutputStream(in_file);
+
+				StringBuffer text = new StringBuffer("");
+				if(creator != null) {
+					 text.append(creator.toString());
+					 text.append("\n");
+				}
+				if(maintainer != null) {
+					 text.append(maintainer.toString());
+					 text.append("\n");
+				}
+				if(public_col) {
+					 text.append("public true\n");
+				}
+				else {
+					 text.append("public false\n");
+				}
+				if(beta) {
+					 text.append("beta true\n");
+				}
+				else {
+					 text.append("beta false\n");
+				}
+				if(text.length() > 0) {
+					 text.append("\n");
+				}
+				if(indexes.size() > 0) {
+					 text.append(indexes.toString());
+				}
+				if(subcollections.size() > 0) {
+					 text.append(subcollections.toString());
+				}
+				if(languages.size() > 0) {
+					 text.append(languages.toString());
+				}
+				if(plugins.size() > 0) {
+					 text.append(plugins.toString());
+				}
+				if(classifiers.size() > 0) {
+					 text.append(classifiers.toString());
+				}
+				if(formats.size() > 0) {
+					 text.append(formats.toString());
+				}
+				if(collectionmetadatum.size() > 0) {
+					 text.append(collectionmetadatum.toString());
+				}
+				text.append(metadatasets.toString());
+				if(rest.size() > 0) {
+					 // Write out rest at the bottom.
+					 text.append("# These instructions are not recognized by the Gatherer.\n");
+					 for(int i = 0; i < rest.size(); i++) {
+						  text.append(rest.get(i));
+						  text.append("\n");
+					 }
+				}
+				out.write(text.toString().getBytes());
+				out.close();
+				out = null;
+		  }
+		  catch(Exception error) {
+				error.printStackTrace();
+		  }
+	 }
+	 /** Method used during a global search and replace to highlight the appropriate record within the Collection Design Managers version of the Metadata Set Manager (view only).
+	  * @param element The name of the desired element as a <strong>String</strong>.
+	  * @see org.greenstone.gatherer.cdm.GUI
+	  * @see org.greenstone.gatherer.cdm.MetadataSetManager
+	  */
+	 public Rectangle setSelectedElement(String element) {
+		  // First ensure that the metadata set controls are visible.
+		  gui.setSelectedView("CDM.GUI.MetadataSets");
+		  // Then tell them to select the given element.
+		  return metadatasets.setSelectedElement(element);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/CollectionMeta.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/CollectionMeta.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/CollectionMeta.java	(revision 13666)
@@ -0,0 +1,176 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+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:        /05/02
+ * Revised:      22/08/02 Revamped, Optimized and Commented.
+ **************************************************************************************/
+import org.greenstone.gatherer.cdm.Index;
+import org.greenstone.gatherer.cdm.Language;
+import org.greenstone.gatherer.util.Utility;
+/** 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.3
+ */
+public class CollectionMeta
+	 implements Comparable {
+	 /** A reference to the collection design manager for access to the language manager. */
+	 private CollectionDesignManager manager = null;
+	 /** The language of this metadata. Should be a two letter code. */
+	 private Language language = null;
+	 /** The name of the thing this metadata is assigned to, which may index an Index. */
+	 private Object name = null;
+	 /** The value of this metadata. */
+	 private String value = null;
+	 /** Constructor.
+	  * @param name The object the metadata is assigned to as an <strong>Object</strong>.
+	  * @param language The language of the metadata as a <strong>Language</strong>. Should be a two letter code.
+	  * @param value The value of this metadata, as a <strong>String</strong>.
+	  */
+	 public CollectionMeta(CollectionDesignManager manager, Object name, Language language, String value) {
+		  this.language = language;
+		  this.manager = manager;
+		  this.name = name;
+		  this.value = value;
+	 }
+	 /** Method to compare two collection metadata objects to calculate their respective ordering.
+	  * @param object The other metadata to compare to, as an <strong>Object</strong>.
+	  * @return An <i>int</i> 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) {
+		  if(object instanceof CollectionMeta) {
+				CollectionMeta metadata = (CollectionMeta) object;
+				int result = name.toString().compareTo(metadata.getName().toString());
+				if(result == 0) {
+					 Language other_language = metadata.getLanguage();
+					 if(language != null && other_language != null) {
+						  result = language.compareTo(metadata.getLanguage());
+						  if(result == 0) {
+								return value.compareTo(metadata.getValue());
+						  }
+					 }
+					 else if(language != null) {
+						  return -1;
+					 }
+					 else if(other_language != null) {
+						  return 1;
+					 }
+				}
+				return result;
+		  }
+		  return toString().compareTo(object.toString());
+	 }
+	 /** 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) {
+		  if(compareTo(object) == 0) {
+				return true;
+		  }
+		  return false;
+	 }
+	 /** Method to retrieve the value of language.
+	  * @return The value of language as a <strong>Language</strong>.
+	  */
+	 public Language getLanguage() {
+		  return language;
+	 }
+	 /** Method to retrieve the value of name.
+	  * @return The value of name as an <strong>Object</strong>.
+	  */
+	 public Object getName() {
+		  return name;
+	 }
+	 /** 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() {
+		  return value;
+	 }
+	 /** 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() {
+		  String text = "collectionmeta ";
+		  if(name instanceof Index) {
+				text = text + ".";
+				Index index = (Index)name;
+				text = text + index.toString(false) + " ";
+		  }
+		  else {
+				text = text + name.toString() + " ";
+		  }
+		  if(language != null && manager.languages.size() > 0 && !manager.languages.isDefaultLanguage(language)) {
+				text = text + "[l=" + language.getCode() + "] ";
+		  }
+		  text = text + "\"" + Utility.encodeGreenstone(value) + "\"\n";
+		  return text;
+	 }
+	 /** Used to update the contents of this collection level metadata to the given 'new' values.
+	  * @param name The new name of the metadata, as a <strong>Object</strong>.
+	  * @param language The new <strong>Language</strong> of the metadata.
+	  * @param value And the value the metadata is assigned, as a <strong>String</strong>.
+	  */
+	 public void update(Object name, Language language, String value) {
+		  this.name = name;
+		  this.language = language;
+		  this.value = value;
+	 }
+	 /** Ensure this is a valid metadata entry by checking that the value is non-null and non-zero length (after having removed whitespace).
+	  * @return <i>true</i> if this metadata has a valid value and should be added to the config, <i>false</i> otherwise.
+	  */
+	 public boolean valid() {
+		  return(value != null && value.trim().length() > 0);
+	 }
+}
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/CollectionMetaManager.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/CollectionMetaManager.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/CollectionMetaManager.java	(revision 13666)
@@ -0,0 +1,336 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+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:        /05/02
+ * Revised:      22/08/02 Revamped, Optimized and Commented.
+ **************************************************************************************/
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.util.ArrayList;
+import java.util.Collections;
+import javax.swing.BorderFactory;
+import javax.swing.ButtonGroup;
+import javax.swing.DefaultListModel;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.cdm.CollectionMeta;
+import org.greenstone.gatherer.cdm.Index;
+import org.greenstone.gatherer.cdm.Language;
+import org.greenstone.gatherer.gui.EditorDialog;
+import org.greenstone.gatherer.util.Utility;
+/** 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.3
+ */
+// ####################################################################################
+// Optimization                               Saving
+// ####################################################################################
+// Removed Vector and Hashtable               + Memory, + Processor
+// ####################################################################################
+public class CollectionMetaManager
+	 extends DefaultListModel {
+	 /** A reference to the cdm manager so we can access indexes and languages. */
+	 private CollectionDesignManager manager = null;
+	 /** A reference to ourself so that inner classes can use us as a model. */
+	 private DefaultListModel model = null;
+	 /** A reference to the Gatherer. */
+	 private Gatherer gatherer = null;
+	 /** The language the most recent metadata returned was in. */
+	 private Language current_language = null;
+	/** We can't safely parse metadata commands until after all the other commands have been parsed, so we store commands here for now. */
+	private ArrayList unresolved_commands = null;
+	 /** Constructor.
+	  * @param gatherer A reference to the <strong>Gatherer</strong>.
+	  * @param manager A reference to the <strong>CollectionDesignManager</strong> for access to other configuration managers.
+	  */
+	 public CollectionMetaManager(Gatherer gatherer, CollectionDesignManager manager) {
+		  super();
+		  this.gatherer = gatherer;
+		  this.manager = manager;
+		  this.model = this;
+		  this.unresolved_commands = new ArrayList();
+	 }
+	 /** Method to add a new piece of metadata.
+	  * @param metadata The new <strong>CollectionMeta</strong>.
+	  */
+	 public void addMetadata(CollectionMeta metadata) {
+		  CollectionMeta existing = getMetadata(metadata.getName().toString(), metadata.getLanguage(), false);
+		  if(existing != null) {
+				removeElement(existing);
+		  }
+		  addElement(metadata);
+		  gatherer.c_man.configurationChanged();
+	 }
+	 /** Retrieve the collectionextra metadata in the default language, if present.
+	  * @return A <strong>CollectionMeta</strong> containing the collectionextra in the default language if present, or else the first collectionextra of any language, otherwise <i>null</i>.
+	  * @see org.greenstone.gatherer.cdm.Language
+	  */
+	 public CollectionMeta getCollectionExtra() {
+		  CollectionMeta result = getMetadata("collectionextra", manager.languages.getDefaultLanguage(), true);
+		  if(result == null) {
+				result = new CollectionMeta(manager, "collectionextra", manager.languages.getDefaultLanguage(), "");
+				addMetadata(result);
+		  }
+		  return result;
+	 }
+	 /** Retrieve the collectionname metadata in the default language, if present.
+	  * @return A <strong>CollectionMeta</strong> containing the collectionname in the default language if present, or else the first collectionname of any language, otherwise <i>null</i>.
+	  * @see org.greenstone.gatherer.cdm.Language
+	  */
+	 public CollectionMeta getCollectionName() {
+		  return getMetadata("collectionname", manager.languages.getDefaultLanguage(), true);
+	 }
+	 /** Retrieve the iconcollection metadata in the default language, if present.
+	  * @return A <strong>CollectionMeta</strong> containing the iconcollection in the default language if present, or else the first iconcollection of any language, otherwise <i>null</i>.
+	  * @see org.greenstone.gatherer.cdm.Language
+	  */
+	 public CollectionMeta getIconCollection() {
+		  CollectionMeta result = getMetadata("iconcollection", manager.languages.getDefaultLanguage(), true);
+		  if(result == null) {
+				result = new CollectionMeta(manager, "iconcollection", manager.languages.getDefaultLanguage(), "");
+				addMetadata(result);
+		  }
+		  return result;
+	 }
+	 /** Method to retrieve the list of metadata.
+	  * @return An <strong>ArrayList</strong> containing the metadata.
+	  */
+	 public ArrayList getMetadata() {
+		 	ArrayList metadata = new ArrayList();
+		 	for(int i = 0; i < size(); i++) {
+				metadata.add(get(i));
+			}
+		  Collections.sort(metadata);
+		  return metadata;
+	 }
+	 
+	 /** Retrieve all of the metadata for the given feature, regardless of language. */
+	 public ArrayList getMetadata(String name) {
+		  ArrayList result = new ArrayList();
+		  for(int i = 0; i < size(); i++) {
+				CollectionMeta metadata = (CollectionMeta) get(i);
+				if(metadata.getName().equals(name)) {
+					 result.add(metadata);
+				}
+		  }
+		  return result;
+	 }
+	 /** Method to retrieve a certain piece of metadata based on its name and language.
+	  * @param name The name of the metadata as a <strong>String</strong>.
+	  * @param language The <strong>Language</strong> 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, Language language, boolean partial) {
+		  CollectionMeta partial_match = null;
+		  for(int i = 0; i < size(); i++) {
+				CollectionMeta metadata = (CollectionMeta) get(i);
+				if(metadata.getName().equals(name)) {
+					 if (metadata.getLanguage().equals(language)) {
+						  return metadata;
+					 }
+					 partial_match = metadata;
+				}
+		  }
+		  if(partial) {
+				return partial_match;
+		  }
+		  return null;
+	 }
+	 /** Method that attempts to parse a collection metadata command from the given text. If a command is parsed successfully it is immediately added to the the collections metadata.
+	 * @param command The command text we wish to parse, as a <strong>String</strong>.
+	 * @return A <i>boolean</i> which is <i>true</i> if a collection metadata command was successfully parsed, <i>false</i> otherwise.
+	 * @see org.greenstone.gatherer.cdm.CollectionDesignManager
+	 * @see org.greenstone.gatherer.cdm.CommandTokenizer
+	 * @see org.greenstone.gatherer.cdm.Language
+	 * @see org.greenstone.gatherer.cdm.LanguageManager
+	 * @see org.greenstone.gatherer.util.Utility
+	 */
+	 public boolean parse(String command, boolean finished) {
+		 String temp = command.toLowerCase();
+		 if(temp.startsWith("collectionmeta")) {
+			  if(finished) {
+					CommandTokenizer ct = new CommandTokenizer(command);
+					if(ct.countTokens() >= 3) {
+						 ct.nextToken(); // Throw away collectionmeta
+						 Object key = ct.nextToken();
+						 Language language = null;
+						 String language_code = null;
+						 String value = ct.nextToken();
+						 // Arg. Remember a language token will be '[l=<code>]'
+						 if(value.startsWith("[") && value.endsWith("]")) {
+							  language_code = value.substring(3, value.length() - 1);
+							  ///ystem.err.println("Language code = " + language_code);
+							  value = ct.nextToken();
+						 }
+						 // Check if the key is an index, an if so retrieve it.
+						 if(((String)key).startsWith(".")) {
+							  String key_str = (String)key;
+							  key_str = key_str.substring(1);
+							  key = manager.indexes.getIndex(key_str);
+						 }
+						 // An if we have a language code, retrieve its object too.
+						 if(language_code != null) {
+							  language = manager.languages.getLanguage(language_code, false);
+						 }
+						 // Otherwise set language to the default language.
+						 else {
+							  language = manager.languages.getDefaultLanguage();
+						 }
+						 if(key != null) {
+							  // Trim any "
+							  if(value.equals("\"\"")) {
+									value = "";
+							  }
+							  else {
+									if(value.startsWith("\"")) {
+										 value = value.substring(1);
+									}
+									if(value.endsWith("\"")) {
+										 value = value.substring(0, value.length() - 1);
+									}
+							  }
+							  CollectionMeta meta = new CollectionMeta(manager, key, language, Utility.decodeGreenstone(value));
+							  addMetadata(meta);
+						 }
+						 return true;
+					}
+			  }
+			  else {
+					unresolved_commands.add(command);
+					return true;
+			  }
+		 }
+		 return false;
+	 }
+	 /** Ensure that the values being showed are the most up to date. */
+	 public void refresh() {
+		  fireContentsChanged(this, 0, size());
+	 }
+
+	 /** Method to remove a piece of metadata.
+	  * @param metadata The <strong>CollectionMeta</strong> you wish to remove.
+	  */
+	 public void removeMetadata(CollectionMeta metadata) {
+		  removeElement(metadata);
+		  gatherer.c_man.configurationChanged();
+	 }
+	 /** Method which attempts to reparse obvious metadata commands which used unresovable references.
+	  */
+	 public void reparseUnresolved() {
+		  for(int i = 0; i < unresolved_commands.size(); i++) {
+				parse((String)unresolved_commands.get(i), true);
+		  }
+		  // Regardless of if they work, clear the commands.
+		  unresolved_commands.clear();
+	 }
+	 /** Sets the value of a certain metadata.
+	  * @param name The name of the metadata as a <strong>String</strong>.
+	  * @param language The <strong>Language</strong> to use.
+	  * @param value The value of the metadata also as a <strong>String</strong>.
+	  */
+	 public void setMetadata(String name, Language language, String value) {
+		  addMetadata(new CollectionMeta(manager, name, language, value));
+	 }
+	 /** Method to produce the list of metadata in a string such as you would find in the collection configuration file.
+	  * @return A <strong>String</strong> containing the list of collection metadata.
+	  */
+	 public String toString() {
+		  StringBuffer text = new StringBuffer("");
+		  for(int i = 0; i < size(); i++) {
+				CollectionMeta data = (CollectionMeta) get(i);
+				if(data.valid()) {
+					 text.append(data.toString());
+				}
+		  }
+		  text.append("\n");
+		  return text.toString();
+	 }
+	 /** 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 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.
+	  */
+	 private 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. Note that argument numbers greater than or equal to 32 are automatically mapped to the formatting String named Farg<I>n</I>.
+	  * @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.
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.Dictionary
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf('.') == -1) {
+				key = "CDM.CollectionMetaManager." + key;
+		  }
+		  return gatherer.dictionary.get(key, args);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/CommandTokenizer.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/CommandTokenizer.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/CommandTokenizer.java	(revision 13666)
@@ -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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+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.util.StringTokenizer;
+/** 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
+	 extends StringTokenizer {
+
+	 private int last_type = -1;
+
+	 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;
+
+	 /** Constructor.
+	  * @param command The command <strong>String</strong> you wish to tokenize.
+	  */
+	 public CommandTokenizer(String command) {
+		  super(command);
+	 }
+
+	 public int getLastType() {
+		  return last_type;
+	 }
+
+	 public boolean isComment() {
+		  return (last_type == DOUBLE_QUOTE_ENCLOSED || last_type == QUOTE_ENCLOSED);
+	 }
+
+	 /** Method to retrieve the next token from the command, taking care to group tokens enclosed in speech marks.
+	  * @return A <strong>String</strong> containing the next token from the command.
+	  */
+	 public String nextToken() {
+		  String result = null;
+		  if(hasMoreTokens()) {
+				StringBuffer buffer = new StringBuffer(super.nextToken());
+				switch(buffer.charAt(0)) {
+				case '\"':
+					 while((buffer.length() == 1 || buffer.charAt(buffer.length() - 1) != '\"') && hasMoreTokens()) {
+						  buffer.append(" ");
+						  buffer.append(super.nextToken());
+						  ///ystem.err.println("Current Buffer = '" + buffer.toString() + "'");
+					 }
+					 ///ystem.err.println("Final Buffer = '" + buffer.toString() + "'");
+					 last_type = DOUBLE_QUOTE_ENCLOSED;
+					 break;
+				case '\'':
+					 while((buffer.length() == 1 || buffer.charAt(buffer.length() - 1) != '\'') && hasMoreTokens()) {
+						  buffer.append(" ");
+						  buffer.append(super.nextToken());
+					 }
+					 last_type = QUOTE_ENCLOSED;
+					 break;
+				case '[':
+					 while((buffer.length() == 1 || buffer.charAt(buffer.length() - 1) != ']') && hasMoreTokens()) {
+						  buffer.append(" ");
+						  buffer.append(super.nextToken());
+					 }
+					 last_type = BRACKET_ENCLOSED;
+					 break;
+				default:
+					 last_type = NORMAL;
+				}
+				result = buffer.toString();
+		  }
+		  return result;
+	 }
+	 /** Unfortunately the StringBuffer doesn't have a built in endsWith method, so I'll just have to implement my own.
+	  * @param str The <strong>StringBuffer</strong> we are checking the end of.
+	  * @param target The <strong>String</strong> fragment we are searching for.
+	  * @return <i>true</i> if str ends with target, <i>false</i> otherwise.
+	  */
+	 private boolean endsWith(StringBuffer str, String target) {
+		  String temp = str.toString();
+		  if(temp.endsWith(target) != (str.lastIndexOf(target) == str.length() - target.length())) {
+				///ystem.err.println("Holy error that'll crash the HFile creator if it happens twice, Batman!");
+				///ystem.err.println("String = '" + temp + "'");
+				///ystem.err.println("Target = '" + target + "'");
+		  }
+		  return str.lastIndexOf(target) == str.length() - target.length();
+	 }
+}
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/CustomClassifier.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/CustomClassifier.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/CustomClassifier.java	(revision 13666)
@@ -0,0 +1,86 @@
+package org.greenstone.gatherer.cdm;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.Classifier;
+import org.greenstone.gatherer.file.FileNode;
+/** The interface for any custom classifier.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public interface CustomClassifier
+	 extends Comparable {
+	 /** Constructor.
+	  * public CustomClassifier(Gatherer gatherer);
+	  */
+	 /** Create a blank copy of this pseudo-classifier.
+	  * @return A newly allocated <strong>CustomClassifier</strong>.
+	  */
+	 public CustomClassifier copy();
+	 /** Destructor. */
+	 public void destroy();
+	 /** Show the controls for configuring this pseudo-classifier.
+	  * @param show <i>true</i> if the component should immediately show itself, <i>false</i> if you just wish to initialize components.
+	  */
+	 public boolean display(boolean show);
+	 /** Method to return this pseudo-classifier represented as a String.
+	  * @return A <strong>String</strong>.
+	  */
+	 public String getCommand();
+	 /** Retrieve the custom command, a command line that overrides and replaces some other 'actual' classifier.
+	  * @param index The number of the classifer this one is replacing.
+	  */
+	 public String getCustomCommand(int index);
+	 /** Get the name of this custom classifier.
+	  * @return A <strong>String</strong> representing the name.
+	  */
+	 public String getName();
+	 public void process(FileNode record);
+	 /** Recreate a CustomAZList given several parameters including the real classifier created during custom design.
+	  * @param classifier The real <strong>Classifier</strong>.
+	  * @param separations A <strong>String</strong> representing the choosen separations.
+	  */
+	 public void recreate(Classifier classifier, String separations);
+	 /** Sets the value of Gatherer, for those classes loaded dynamically.
+	  * @param gatherer A reference to the <strong>Gatherer</strong>.
+	  */
+	 public void setGatherer(Gatherer gatherer);
+	 /** Sets the Classifier manager in charge of this classifier.
+	  * @param manager This classifiers <strong>ClassifierManager</strong>.
+	  */
+	 public void setManager(ClassifierManager manager);
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/DefaultSubIndex.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/DefaultSubIndex.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/DefaultSubIndex.java	(revision 13666)
@@ -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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+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:      03/05/02
+ * Revised:      03/10/02 - Commented
+ **************************************************************************************/
+import java.util.Collections;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import org.greenstone.gatherer.cdm.Subcollection;
+import org.greenstone.gatherer.cdm.SubIndex;
+/** The DefaultSubIndex contains a single subcollection which is used as the default index.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class DefaultSubIndex
+	 extends SubIndex {
+	 /** Copy constructor.
+	  * @param subindex The <strong>SubIndex</strong> we are copying.
+	  */
+	 public DefaultSubIndex(SubIndex subindex) {
+		  for(int i = 0; i < subindex.size(); i++) {
+				add(subindex.get(i));
+		  }
+	 }
+	 /** Parsed data Constructor.
+	  * @param raw A <strong>String</strong> containing a comma separated list of subcollection names.
+	  * @param manager A reference to the <strong>SubcollectionManager</strong> via which we retrieve the required <strong>Subcollection</strong>s.
+	  */
+	 public DefaultSubIndex(String raw, SubcollectionManager manager) {
+		  super(raw, manager);
+	 }
+	 /** Method to extract just the subindex information from this class.
+	  * @return A <strong>SubIndex</strong> based on the information in this class.
+	  */
+	 public SubIndex getSubIndex() {
+		  return new SubIndex(this);
+	 }
+	 /** Method to produce this class as a string much like you'd find in the collection configuration file.
+	  * @return A <strong>String</string> with the default index entry.
+	  */
+	 public String toString() {
+		  String text = "defaultsubcollection ";
+		  for(int i = 0; i < size(); i++) {
+				Object object = get(i);
+				Subcollection sub = (Subcollection) get(i);
+				text = text + sub.getName();
+				if(i < size() - 1) {
+					 text = text + ",";
+				}
+		  }
+		  text = text + "\n";
+		  return text;
+	 }
+}
+
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/DynamicListModel.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/DynamicListModel.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/DynamicListModel.java	(revision 13666)
@@ -0,0 +1,124 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+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);
+		  }
+	 }
+
+	 public 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/start/gli/src/org/greenstone/gatherer/cdm/ElementWrapper.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/ElementWrapper.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/ElementWrapper.java	(revision 13666)
@@ -0,0 +1,51 @@
+package org.greenstone.gatherer.cdm;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.w3c.dom.*;
+/** For even more confusion this class provides a convience wrapper around an element, to allow it to appear in the <strong>JList</strong> with both name and description. However this class has nothing to do with its namesake.
+ * @see org.greenstone.gatherer.msm.ElementWrapper
+ */
+public class ElementWrapper
+	 implements Comparable {
+	 /** The element as the data from this object. */
+	 private Node element = null;
+	 /** Constructor.
+	  * @param element The <strong>Node</strong> this object is wrapped around.
+	  */
+	 public ElementWrapper(Node element) {
+		  this.element = element;
+	 }
+	 /** Compare two objects for ordering.
+	  * @param object The other <strong>Object</strong> to compare to.
+	  * @return An <i>int</i> indicating the ordering as is String.compareTo
+	  */
+	 public int compareTo(Object object) {
+		  if(object == null) {
+				return 1;
+		  }
+		  return toString().compareTo(object.toString());
+	 }
+	 /** Compare two objects for equality.
+	  * @param object The <strong>Object</strong> to compare to.
+	  * @return <i>true</i> if the objects are equal, <i>false</i> otherwise.
+	  */
+	 public boolean equals(Object object) {
+		  if(compareTo(object) == 0) {
+				return true;
+		  }
+		  return false;
+	 }
+	 /** Retrieve the name of the element.
+	  * @return The fully qualified name as a <strong>String</strong>.
+	  * @see org.greenstone.gatherer.msm.MSMUtils
+	  */
+	 public String name() {
+		  return MSMUtils.getFullName((Element)element);
+	 }
+	 /** Retrieve a textual representation of this object.
+	  * @return A <strong>String</strong>.
+	  * @see org.greenstone.gatherer.msm.MSMUtils
+	  */
+	 public String toString() {
+		  return MSMUtils.getIdentifier(element) + ": " + MSMUtils.getDescription(element);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/Format.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/Format.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/Format.java	(revision 13666)
@@ -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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+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:      06/05/02
+ * Revised:      04/10/02 - Commented
+ **************************************************************************************/
+import org.greenstone.gatherer.cdm.Classifier;
+/** 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.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class Format {
+	 /** If this format is of a true/false type, the current state. */
+	 private boolean state = false;
+	 /** The type of this format command, either FLAG, FORMAT or PARAM. */
+	 private int type = -1;
+	 /** The feature this format command affects. */
+	 private Object feature = null;
+	 /** If this format refers to a specific part of a feature, this indicates the part. */
+	 private String part = null;
+	 /** A command string, which may include a specific HTML chunk used to format a control. */
+	 private String value = null;
+	 /** An element of the format type enumeration. A true/false option. */
+	 static final public int FLAG = 0;
+	 /** An element of the format type enumeration. A string parameter. */
+	 static final public int VALUE = 1;
+	 /** The default features as specified by the Greenstone Developers manual. */
+	 static final public String DEFAULT_FEATURES[] = {"", "DocumentArrowsBottom","DocumentButtons","DocumentContents","DocumentHeading","DocumentImages","DocumentText","DocumentUseHTML","Search"};
+	 /** The list of known feature parts. */
+	 static final public String DEFAULT_PARTS[] = {"","DateList","HList","Invisible","VList"};
+	 /** 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) {
+		  this.feature = feature;
+		  this.part = part;
+		  this.state = state;
+		  this.type = FLAG;
+	 }
+	 /** 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) {
+		  this.feature = feature;
+		  this.part = part;
+		  this.type = VALUE;
+		  this.value = value;
+	 }
+	 /** 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() {
+		  return feature;
+	 }
+	 /** Method to retrieve the value of part.
+	  * @return The value of part as a <Strong>String</strong>.
+	  */
+	 public String getPart() {
+		  return part;
+	 }
+	 /** Method to retrieve this formats special Greenstone position code.
+	  * @return A <strong>String</strong> which distinctly indicates this classifiers position.
+	  * @see org.greenstone.gatherer.cdm.Classifier
+	  */
+	 public String getPosition() {
+		  ///ystem.err.println("Retrieving the name of feature " + feature);
+		  String position = null;
+		  if(feature instanceof Classifier) {
+				position = ((Classifier)feature).getPositionString();
+		  }
+		  else {
+				position = feature.toString();
+		  }
+		  ///ystem.err.println("Result: " + position + part);
+		  return position + part;
+	 }
+	 /** Method to retrieve the value of state.
+	  * @param The value of state as a <i>boolean</i>.
+	  */
+	 public boolean getState() {
+		  return state;
+	 }
+	 /** Method to retrieve the value of type.
+	  * @param The value of type as an <i>int</i>.
+	  */
+	 public int getType() {
+		  return type;
+	 }
+	 /** Retrieve the value of value.
+	  * @return A <strong>String</strong> which is the value of value.
+	  */
+	 public String getValue() {
+		  return value;
+	 }
+	 /** Set the value of state.
+	  * @param state The new value for state as a <i>boolean</i>.
+	  */
+	 public void setState(boolean state) {
+		  this.state = state;
+	 }
+	 /** Set the value of type.
+	  * @param type The new value for type as an <i>int</i>.
+	  */
+	 public void setType(int type) {
+		  this.type = type;
+	 }
+	 /** Set the value of value. Hmmm.
+	  * @param value The new value from value as a <strong>String</strong>.
+	  */
+	 public void setValue(String value) {
+		  this.value = value;
+	 }
+	 /** 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() {
+		  String text = "format ";
+		  text = text + getPosition() + " ";
+		  switch(type) {
+		  case FLAG:
+				if(state) {
+					 text = text + "true";
+				}
+				else {
+					 text = text + "false";
+				}
+				break;
+		  default:
+				text = text + "\"" + value + "\"";
+		  }
+		  return text;
+	 }
+	 /** Retrieve the type of a certain named feature.
+	  * @param name The name of the feature as a <strong>String</strong>.
+	  * @return An <i>int</i> indicating the type, and hence the controls needed to edit this type.
+	  */
+	 static public int getType(String name) {
+		  int index = -1;
+		  for(int i = 1; i < DEFAULT_FEATURES.length; i++) {
+				if(name.equalsIgnoreCase(DEFAULT_FEATURES[i])) {
+					 index = i;
+				}
+		  }
+		  if(index == 1 || index == 3 || index == 5 || index == 7) {
+				return FLAG;
+		  }
+		  return VALUE;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/FormatManager.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/FormatManager.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/FormatManager.java	(revision 13666)
@@ -0,0 +1,917 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+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:        /05/02
+ * Revised:      04/10/02 - Commented
+ **************************************************************************************/
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Vector;
+import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
+import javax.swing.ButtonGroup;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.JToggleButton;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.Classifier;
+import org.greenstone.gatherer.cdm.ClassifierManager;
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.cdm.CommandTokenizer;
+import org.greenstone.gatherer.cdm.DynamicListModel;
+import org.greenstone.gatherer.cdm.Format;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.util.Utility;
+/** 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 DynamicListModel {
+	 /** The main manager so we can get to ClassifierManager which is needed to turn position reference such as "CL1" into the appropriate Classifier. */
+	 private CollectionDesignManager manager = 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 DynamicListModel model = null;
+	 /** A reference to the Gatherer. */
+	 private Gatherer gatherer = null;
+	 /** We may have somehow recieved a format command which references a classifier that hasn't been parsed yet, so this variable holds a list of failed commands which are retried after the loading is complete. */
+	 private Vector unresolved_commands = null;
+	 /** Constructor.
+	  * @param gatherer A reference to the <strong>Gatherer</strong>.
+	  * @param manager A reference to the <strong>CollectionDesignManager</strong> that created this manager.
+	  */
+	 public FormatManager(Gatherer gatherer, CollectionDesignManager manager) {
+		  super();
+		  this.gatherer = gatherer;
+		  this.manager = manager;
+		  this.model = this;
+		  this.unresolved_commands = new Vector();
+	 }
+	 /** Method to add a new format to this manager.
+	  * @param format The <strong>Format</strong> to add.
+	  */
+	 public void addFormat(Format format) {
+		  if(formatExists(format) == null) {
+				addElement(format);
+				gatherer.c_man.configurationChanged();
+		  }
+	 }
+	 /** Method which determines if a certain format exists, in which case it must be removed before a new format of the same component is added. For general formatting statements this compares types, for 'custom' ones it compares list and part.
+	  * @param format The <strong>Format</strong> whose uniqueness we want to check.
+	  * @return The <strong>Format</strong> that matches the one given, or <i>null</i> if no such format exists.
+	  */
+	 public Format formatExists(Format format) {
+		  for(int i = 0; i < size(); i++) {
+				Format current = (Format) get(i);
+				if(format.getPosition().equals(current.getPosition())) {
+					 return current;
+				}
+		  }
+		  return null;
+	 }
+	 /** Gets the format indicated by the index.
+	  * @param index The location of the desired format, as an <i>int</i>.
+	  */
+	 public Format getFormat(int index) {
+		  return (Format)get(index);
+	 }
+	 /** Method to retrieve this managers controls.
+	  * @return The <strong>Control</strong> for this collection.
+	  */
+	 public Control getControls() {
+		  if(controls == null) {
+				controls = new Control();
+		  }
+		  return controls;
+	 }
+	 /** Method to invalidate controls when some significant change has occured within the collection. */
+	 public void invalidateControls() {
+		  if(controls != null) {
+				controls.destroy();
+		  }
+		  controls = null;
+	 }
+	 /** This method attempts to parse a format command from the given string. If a format is parsed, it is immediately added to this managers list of format commands.
+	  * @param command The <strong>String</strong> we are trying to parse a command from.
+	  * @param finished A <i>boolean</i> which is <i>true</i> if we are calling this after the the input has been completely parsed (i.e all legal Classifiers are know to exist), or <i>false</i> otherwise.
+	  * @return A <i>boolean</i> which is <i>true</i> if we managed to parse a command, <i>false</i> otherwise.
+	  * @see org.greenstone.gatherer.cdm.Classifier
+	  * @see org.greenstone.gatherer.cdm.CommandTokenizer
+	  * @see org.greenstone.gatherer.cdm.Format
+	  */
+	 public boolean parse(String command, boolean finished) {
+		  String temp = command.toLowerCase();
+		  if(temp.startsWith("format")) {
+				if(finished) {
+					 CommandTokenizer ct = new CommandTokenizer(command);
+					 ct.nextToken(); // Throw away 'format'
+					 String position = ct.nextToken();
+					 String value = ct.nextToken();
+					 // String speech marks.
+					 if(value.startsWith("\"") && value.endsWith("\"")) {
+						  if(value.equals("\"\"")) {
+								value = "";
+						  }
+						  else {
+								value = value.substring(1, value.length() - 1);
+						  }
+					 }
+					 // Ensure we parsed a good command.
+					 if(position != null && value != null) {
+						  // The trickiest bit of parsing format commands is figuring out how much of the position is feature, and how much part. Since the parts are far less likely to change or be customized in any way, we'll try to match them first (except "" of course).
+						  String feature_name = null;
+						  String part = null;
+						  // If this works, then we're all finished. Yay.
+						  for(int i = 1; i < Format.DEFAULT_PARTS.length; i++) {
+								if(position.endsWith(Format.DEFAULT_PARTS[i])) {
+									 part = Format.DEFAULT_PARTS[i];
+									 feature_name = position.substring(0, position.length() - part.length());
+								}
+						  }
+						  // Otherwise we can attempt to find the default features, but we have less chance of success.
+						  if(feature_name == null || part == null) {
+								for(int i = 1; i < Format.DEFAULT_FEATURES.length; i++) {
+									 if(position.startsWith(Format.DEFAULT_FEATURES[i])) {
+										  feature_name = Format.DEFAULT_FEATURES[i];
+										  if(position.length() > feature_name.length()) {
+												part = position.substring(feature_name.length());
+										  }
+										  else {
+												part = "";
+										  }
+									 }
+								}
+						  }
+						  // Otherwise we can assume we are dealing with a classifier and split the position using...
+						  // position            ::= <classifier_position><part>
+						  // classifier_position ::= <alphanum>[0-9]$
+						  // part                ::= ^![0-9]<alpha>
+						  // But I don't like my chances of this working if someone does a scary like CL4Part8B. I just have
+						  // to hope no-one uses numbers, and no-one expects CustomFeatureCustomPart to parse properly.
+						  if(feature_name == null || part == null) {
+								part = "";
+								boolean found = false;
+								int index = position.length() - 1;
+								while(index >= 0 && !found) {
+									 if(Character.isDigit(position.charAt(index))) {
+										  found = true;
+									 }
+									 else {
+										  part = position.charAt(index) + part;
+										  index--;
+									 }
+								}
+								if(found) {
+									 feature_name = position.substring(0, index + 1);
+								}
+								// We ran out of string. No digits. Arg!
+								else {
+									 part = null;
+								}
+						  }
+						  // And if all else fails, stick it all in feature.
+						  if(feature_name == null || part == null) {
+								feature_name = position;
+								part = "";
+						  }
+						  // Now try to retrieve a classifier with the feature name.
+						  Object feature = null;
+						  String feature_name_lc = feature_name.toLowerCase();
+						  if(feature_name_lc.startsWith("cl") && feature_name.length() >= 3) {
+								String raw_index = feature_name.substring(2); // Lose the 'CL'
+								int index = -1;
+								try {
+									 index = Integer.parseInt(raw_index);
+								}
+								catch(NumberFormatException nfe) {
+									 nfe.printStackTrace();
+								}
+								feature = manager.classifiers.getClassifier(index - 1);
+						  }
+						  else {
+								///ystem.err.println("name to short for classifier.");
+						  }
+						  if(feature == null) {
+								feature = feature_name;
+						  }
+						  ///ystem.err.println("Feature name = " + feature_name + "\nPart = " + part);
+						  if(feature instanceof Classifier) {
+								///ystem.err.println("Feature is a classifier.");
+						  }
+						  else {
+								///ystem.err.println("Feature is a String.");
+						  }
+						  // Now we have a quick look at value. If its true or false we create a FLAG type
+						  if(value.equalsIgnoreCase("true")) {
+								addFormat(new Format(feature, part, true));
+						  }
+						  else if(value.equalsIgnoreCase("false")) {
+								addFormat(new Format(feature, part, false));
+						  }
+						  // Otherwise add a plain old value based format
+						  else {
+								addFormat(new Format(feature, part, value));
+						  }
+						  return true;
+					 }
+					 // Somethings gone terribly, terribly wrong.
+					 return false;
+				}
+				else {
+					 unresolved_commands.add(command);
+				}
+				return true;
+		  }
+		  return false;
+	 }
+	 /** Method to remove a format.
+	  * @param format The <strong>Format</strong> to remove.
+	  */
+	 public void removeFormat(Format format) {
+		  removeElement(format);
+		  gatherer.c_man.configurationChanged();
+	 }
+	/** Method which attempts to reparse obvious format commands which previously referenced unresovable Classifiers.
+	*/
+	public void reparseUnresolved() {
+		for(int i = 0; i < unresolved_commands.size(); i++) {
+			if(!parse((String)unresolved_commands.get(i), true)) {
+				 ///ystem.err.println("*** Error: Command " + unresolved_commands.get(i));
+			}
+		}
+		// Regardless of if they work, clear the commands.
+		unresolved_commands.clear();
+	}
+	/** Method to produce a block of text representing the format commands in this manager, ready to be used in the collection configuration file.
+	* @return A <strong>String</strong> containing a series of format commands.
+	*/
+	public String toString() {
+		StringBuffer text = new StringBuffer("");
+		for(int i = 0; i < size(); i++) {
+			Format format = (Format) get(i);
+			text.append(format.toString());
+			text.append("\n");
+		}
+		text.append("\n");
+		return text.toString();
+	}
+	 /** 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 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.
+	  */
+	 private 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. Note that argument numbers greater than or equal to 32 are automatically mapped to the formatting String named Farg<I>n</I>.
+	  * @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.
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.Dictionary
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf('.') == -1) {
+				key = "CDM.FormatManager." + key;
+		  }
+		  return gatherer.dictionary.get(key, args);
+	 }
+	 private class Control
+		  extends JPanel {
+		  /** Do we ignore selection changing events (mainly because we're generating them!) */
+		  private boolean ignore = false;
+		  private boolean new_entry = true;
+		  private boolean ready = false;
+		  private ButtonGroup button_group = null;
+		  private CardLayout card_layout = null;
+		  private Dimension LABEL_SIZE = new Dimension(175,25);
+		  private Format current_format = null;
+		  private String view_type = "custom";
+		  private JButton add = null;
+		  private JButton insert = null;
+		  private JButton preview = null;
+		  private JButton remove = null;
+		  private JComboBox feature = null;
+		  private JComboBox part = null;
+		  private JComboBox special = null;
+		  private JLabel editor_label = null;
+		  private JLabel feature_label = null;
+		  private JLabel format_list_label = null;
+		  private JLabel part_label = null;
+		  private JLabel special_label = null;
+		  private JLabel title = null;
+		  private JLabel value_label = null;
+		  private JList format_list = null;
+		  private JPanel blank_pane = null;
+		  private JPanel control_pane = null;
+		  private JPanel editor_pane = null;
+		  private JPanel feature_pane = null;
+		  private JPanel format_list_pane = null;
+		  private JPanel header_pane = null;
+		  private JPanel inner_button_pane = null;
+		  private JPanel inner_state_pane = null;
+		  private JPanel inner_value_pane = null;
+		  private JPanel options_pane = null;
+		  private JPanel outer_button_pane = null;
+		  private JPanel part_pane = null;
+		  private JPanel special_pane = null;
+		  private JPanel state_pane = null;
+		  private JPanel value_pane = null;
+		  private JPanel view_pane = null;
+		  private JTextArea editor = null;
+		  private JTextArea instructions = null;
+		  private JTextField value = null;
+		  private JToggleButton off = null;
+		  private JToggleButton on = null;
+		  private String BLANK = "blank";
+		  private String CUSTOM = "custom";
+		  private String FLAG = "flag";
+		  private String PARAM = "param";
+		  private Vector part_model = null;
+		  private Vector special_model = null;
+		  public Control() {
+				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 < manager.classifiers.size(); j++) {
+					 feature_model.add(new Entry(manager.classifiers.getClassifier(j)));
+				}
+				Collections.sort(feature_model);
+				part_model = new Vector();
+				part_model.add("");//get("Custom"));
+				part_model.add("DateList");
+				part_model.add("HList");
+				part_model.add("Invisible");
+				part_model.add("VList");
+				special_model = new Vector();
+				special_model.add("[Text]");
+				special_model.add("[link]");
+				special_model.add("[/link]");
+				special_model.add("[icon]");
+				special_model.add("[num]");
+				special_model.add("[parent():_]");
+				special_model.add("[parent(Top):_]");
+				special_model.add("[parent(All'_'):_]");
+				Vector elements = gatherer.c_man.msm.getAssignedElements();
+				for(int i = 0; i < elements.size(); i++) {
+					 special_model.add("[" + ((ElementWrapper)elements.get(i)).toString() + "]");
+				}
+				Collections.sort(special_model);
+				// Create
+				add = new JButton(get("Add"));
+				add.setEnabled(false);
+				blank_pane = new JPanel();
+				button_group = new ButtonGroup();
+				card_layout = new CardLayout();
+				control_pane = new JPanel();
+				editor = new JTextArea();
+				editor.setCaretPosition(0);
+				editor.setLineWrap(true);
+				editor.setWrapStyleWord(true);
+				editor_label = new JLabel(get("Editor"));
+				editor_label.setHorizontalAlignment(JLabel.CENTER);
+				editor_pane = new JPanel();
+				feature = new JComboBox(feature_model.toArray());
+				feature.setEditable(true);
+				feature_label = new JLabel(get("Feature"));
+				feature_label.setPreferredSize(LABEL_SIZE);
+				format_list = new JList(model);
+				format_list_label = new JLabel(get("Assigned_Formats"));
+				format_list_pane = new JPanel();
+				feature_pane = new JPanel();
+				header_pane = new JPanel();
+				inner_button_pane = new JPanel();
+				inner_state_pane = new JPanel();
+				inner_value_pane = new JPanel();
+				insert = new JButton(get("Insert"));
+				instructions = new JTextArea(get("Instructions"));
+				instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				instructions.setEditable(false);
+				instructions.setLineWrap(true);
+				instructions.setRows(4);
+				instructions.setWrapStyleWord(true);
+				off = new JToggleButton(get("Off"));
+				off.setSelected(false);
+				on = new JToggleButton(get("On"));
+				on.setSelected(true);
+				options_pane = new JPanel();
+				outer_button_pane = new JPanel();
+				part = new JComboBox(part_model);
+				part.setEditable(true);
+				part_label = new JLabel(get("Part"));
+				part_label.setPreferredSize(LABEL_SIZE);
+				part_pane = new JPanel();
+				preview = new JButton(get("Preview"));
+				preview.setEnabled(false);
+				remove = new JButton(get("Remove"));
+				remove.setEnabled(false);
+				special = new JComboBox(special_model);
+				special_label = new JLabel(get("Special"));
+				special_label.setHorizontalAlignment(JLabel.CENTER);
+				special_pane = new JPanel();
+				state_pane = new JPanel();
+				title = new JLabel(get("Title"));
+				title.setHorizontalAlignment(JLabel.CENTER);
+				title.setOpaque(true);
+				value = new JTextField();
+				value_label = new JLabel(get("Value"));
+				value_pane = new JPanel();
+				view_pane = new JPanel();
+				// Connect
+				add.addActionListener(new AddListener());
+				button_group.add(on);
+				button_group.add(off);
+				editor.addKeyListener(new EditorListener());
+				feature.addActionListener(new FeatureListener());
+				format_list.addListSelectionListener(new FormatListListener());
+				insert.addActionListener(new InsertListener());
+				off.addActionListener(new StateListener());
+				on.addActionListener(new StateListener());
+				part.addActionListener(new PartListener());
+				preview.addActionListener(new PreviewListener());
+				remove.addActionListener(new RemoveListener());
+				value.addKeyListener(new ValueListener());
+				// Layout
+				instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
+
+				header_pane.setLayout(new BorderLayout());
+				header_pane.add(title, BorderLayout.NORTH);
+				header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER);
+
+				format_list_label.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+
+				format_list_pane.setLayout(new BorderLayout());
+				format_list_pane.add(format_list_label, BorderLayout.NORTH);
+				format_list_pane.add(new JScrollPane(format_list), BorderLayout.CENTER);
+
+				feature_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+
+				feature_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+				feature_pane.setLayout(new BorderLayout());
+				feature_pane.add(feature_label, BorderLayout.WEST);
+				feature_pane.add(feature, BorderLayout.CENTER);
+
+				part_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+
+				part_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+				part_pane.setLayout(new BorderLayout());
+				part_pane.add(part_label, BorderLayout.WEST);
+				part_pane.add(part, BorderLayout.CENTER);
+
+				options_pane.setLayout(new GridLayout(2,1));
+				options_pane.add(feature_pane);
+				options_pane.add(part_pane);
+
+				inner_state_pane = new JPanel(new GridLayout(1,2));
+				inner_state_pane.add(on);
+				inner_state_pane.add(off);
+
+				state_pane.setLayout(new BorderLayout());
+				state_pane.add(inner_state_pane, BorderLayout.NORTH);
+				state_pane.add(new JPanel(), 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.setLayout(new BorderLayout());
+				value_pane.add(inner_value_pane, BorderLayout.NORTH);
+				value_pane.add(new JPanel(), BorderLayout.CENTER);
+
+				special_pane.setLayout(new GridLayout(3,1));
+				special_pane.add(special_label);
+				special_pane.add(special);
+				special_pane.add(insert);
+
+				editor_pane.setLayout(new BorderLayout());
+				editor_pane.add(editor_label, BorderLayout.NORTH);
+				editor_pane.add(new JScrollPane(editor), BorderLayout.CENTER);
+				editor_pane.add(special_pane, BorderLayout.EAST);
+
+				// Magic for view_pane card layout.
+				view_pane.setLayout(card_layout);
+				view_pane.add(editor_pane, CUSTOM);
+				view_pane.add(state_pane, FLAG);
+				//view_pane.add(value_pane, PARAM);
+
+				inner_button_pane.setLayout(new GridLayout(1,2));
+				inner_button_pane.add(add);
+				inner_button_pane.add(remove);
+
+				outer_button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+				outer_button_pane.setLayout(new GridLayout(1,1));
+				outer_button_pane.add(inner_button_pane);
+				//outer_button_pane.add(preview);
+
+				control_pane.setLayout(new BorderLayout());
+				control_pane.add(options_pane, BorderLayout.NORTH);
+				control_pane.add(view_pane, BorderLayout.CENTER);
+				control_pane.add(outer_button_pane, BorderLayout.SOUTH);
+
+				setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+				setLayout(new BorderLayout());
+				add(header_pane, BorderLayout.NORTH);
+				add(format_list_pane, BorderLayout.CENTER);
+				add(control_pane, BorderLayout.SOUTH);
+				ready = true;
+		  }
+		  public void destroy() {
+		  }
+		  /** Overriden to ensure that the instructions pane is scrolled to the top.
+			*/
+		  public void updateUI() {
+				if(ready) {
+					 // 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 < manager.classifiers.size(); j++) {
+						  feature_model.add(new Entry(manager.classifiers.getClassifier(j)));
+					 }
+					 feature.setModel(new DefaultComboBoxModel(feature_model.toArray()));
+					 if(instructions != null) {
+						  instructions.setCaretPosition(0);
+					 }
+				}
+				super.updateUI();
+		  }
+
+
+
+		  /** Formats the formatting string so that it contains safe characters and isn't enclosed in speech marks etc. (Ironic eh?)
+			* @see java.lang.StringBuffer
+			*/
+		  private String format(String raw) {
+				String safe = null;
+				if(raw != null && raw.length() > 0) {
+					 StringBuffer temp = new StringBuffer(raw);
+					 // Remove quotes at start and end. Look at my wiggly save three lines of code skills.
+					 char start = ' ';
+					 while(temp.length() > 0 && (start = temp.charAt(0)) == '\"' || start == '\'') {
+						  temp.delete(0, 1);
+					 }
+					 int length = 0;
+					 char end = ' ';
+					 while((length = temp.length()) > 0 && (end = temp.charAt(length - 1)) == '\"' || end == '\'') {
+						  temp.delete(length - 1, length);
+					 }
+					 // Now escape quotes within the format string
+					 int quote_index = -1;
+					 while((quote_index = temp.indexOf("\"", quote_index + 1)) != -1) {
+						  temp.replace(quote_index, quote_index + 1, "\\\"");
+						  quote_index = quote_index + 1;
+					 }
+					 // Done.
+					 safe = temp.toString();
+				}
+				return safe;
+		  }
+		  /** Remove safe characters from string replacing them with unsafe ones.
+			* @see java.lang.StringBuffer
+			*/
+		  private String unformat(String safe) {
+				String raw = null;
+				if(safe != null && safe.length() > 0) {
+					 StringBuffer temp = new StringBuffer(safe);
+					 int quote_index = -1;
+					 while((quote_index = temp.indexOf("\\\"")) != -1) {
+						  temp.replace(quote_index, quote_index + 2, "\"");
+					 }
+					 raw = temp.toString();
+				}
+				return raw;
+		  }
+		  /** Listens for clicks on the add button, and if the relevant details are provided adds a new format. */
+		  private class AddListener
+				implements ActionListener {
+				public void actionPerformed(ActionEvent event) {
+					 ignore = true;
+					 Entry entry = (Entry)feature.getSelectedItem();
+					 Object f = entry.getFeature();
+					 String p = (String)part.getSelectedItem();
+					 if(view_type.equals(FLAG)) {
+						  current_format = new Format(f, p, on.isSelected());
+					 }
+					 else {
+						  current_format = new Format(f, p, format(Utility.stripNL(editor.getText())));
+					 }
+					 addFormat(current_format);
+					 add.setEnabled(false);
+					 remove.setEnabled(true);
+					 // Update list selection
+					 format_list.setSelectedValue(current_format, true);
+					 new_entry = false;
+					 ignore = false;
+				}
+		  }
+		  private class EditorListener
+				extends KeyAdapter {
+				public void keyReleased(KeyEvent event) {
+					 String safe = format(editor.getText());
+					 if(!ignore && current_format != null) {
+						  // We have just performed an edit. Immediately update the format and model.
+						  if(safe != null) {
+								current_format.setValue(safe);
+						  }
+						  else {
+								current_format.setValue("");
+						  }
+						  gatherer.c_man.configurationChanged();
+						  model.refresh();
+					 }
+					 Entry entry = (Entry) feature.getSelectedItem();
+					 String name = entry.toString();
+					 if(!(name.length() == 0 && ((String)part.getSelectedItem()).length() == 0) && safe != null && safe.length() != 0 && new_entry) {
+						  add.setEnabled(true);
+					 }
+					 else {
+						  add.setEnabled(false);
+					 }
+				}
+		  }
+		  /** 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 CustomClassifier custom_classifier = null;
+				private String text = null;
+				public Entry(Object object) {
+					 if(object instanceof Classifier) {
+						  classifier = (Classifier)object;
+					 }
+					 if(object instanceof CustomClassifier) {
+						  custom_classifier = (CustomClassifier)object;
+					 }
+					 else if(object instanceof String) {
+						  text = (String)object;
+					 }
+					 else {
+						  text = "";
+					 }
+				}
+				public Entry(String text) {
+					 this.text = 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 CustomClassifier getCustomClassifier() {
+					 return custom_classifier;
+				}
+				public Object getFeature() {
+					 if(classifier != null) {
+						  return classifier;
+					 }
+					 return text;
+				}
+				public String toString() {
+					 if(classifier != null) {
+						  String name = classifier.toString();
+						  return name.substring(9);
+					 }
+					 if(custom_classifier != null) {
+						  String name = custom_classifier.toString();
+						  return name;//.substring(17);
+					 }
+					 return text;
+				}
+		  }
+		  private class FeatureListener
+				implements ActionListener {
+				public void actionPerformed(ActionEvent event) {
+					 if(!ignore) {
+						  current_format = null;
+						  Entry entry = (Entry) feature.getSelectedItem();
+						  String name = entry.toString();
+						  int type = Format.getType(name);
+						  switch(type) {
+						  case Format.FLAG:
+								// Flags first.
+								part.setEnabled(false);
+								part_pane.remove(part);
+								card_layout.show(view_pane, FLAG);
+								view_type = FLAG;
+								add.setEnabled(true); // One of the options must be selected.
+								break;
+						  default:
+								part.setEnabled(true);
+								part_pane.add(part, BorderLayout.CENTER);
+								card_layout.show(view_pane, CUSTOM);
+								view_type = CUSTOM;
+								if(!(name.length() == 0 && ((String)part.getSelectedItem()).length() == 0) && editor.getText().length() != 0) {
+									 add.setEnabled(true);
+								}
+								else {
+									 add.setEnabled(false);
+								}
+						  }
+						  control_pane.updateUI();
+						  new_entry = true;
+					 }
+				}
+		  }
+		  private class FormatListListener
+				implements ListSelectionListener {
+				public void valueChanged(ListSelectionEvent event) {
+					 if(!ignore) {
+						  if(!format_list.isSelectionEmpty()) {
+								ignore = true;
+								current_format = (Format)format_list.getSelectedValue();
+								// Try to match the target, remembering the entries within are Entry's
+								Entry an_entry = new Entry(current_format.getFeature());
+								feature.setSelectedItem(an_entry);
+								// Try to match the part.
+								part.setSelectedItem(current_format.getPart());
+								// Now use type to determine what controls are visible, and what have initial values.
+								switch(current_format.getType()) {
+								case Format.FLAG:
+									 // Flags first.
+									 part.setEnabled(false);
+									 part_pane.remove(part);
+									 card_layout.show(view_pane, FLAG);
+									 view_type = FLAG;
+									 // Initial value
+									 on.setSelected(current_format.getState());
+									 off.setSelected(!current_format.getState());
+									 add.setEnabled(false); // Can only update
+									 break;
+								default:
+									 part.setEnabled(true);
+									 part_pane.add(part, BorderLayout.CENTER);
+									 card_layout.show(view_pane, CUSTOM);
+									 view_type = CUSTOM;
+									 // Initial value
+									 editor.setText(unformat(current_format.getValue()));
+									 add.setEnabled(false);
+								}
+								control_pane.updateUI();
+								ignore = false;
+								preview.setEnabled(true);
+								remove.setEnabled(true);
+								new_entry = false;
+						  }
+						  else {
+								preview.setEnabled(false);
+								remove.setEnabled(false);
+						  }
+					 }
+				}
+		  }
+		  private class InsertListener
+				implements ActionListener {
+				public void actionPerformed(ActionEvent event) {
+					 editor.insert((String)special.getSelectedItem(), editor.getCaretPosition());
+				}
+		  }
+		  private class PartListener
+				implements ActionListener {
+				public void actionPerformed(ActionEvent event) {
+					 if(!ignore) {
+						  current_format = null;
+						  Entry entry = (Entry) feature.getSelectedItem();
+						  String name = entry.toString();
+						  if(!(name.length() == 0 && ((String)part.getSelectedItem()).length() == 0) && editor.getText().length() != 0) {
+								add.setEnabled(true);
+						  }
+						  else {
+								add.setEnabled(false);
+						  }
+						  new_entry = true;
+					 }
+				}
+		  }
+		  private class PreviewListener
+				implements ActionListener {
+				public void actionPerformed(ActionEvent event) {
+				}
+		  }
+		  private class RemoveListener
+				implements ActionListener {
+				public void actionPerformed(ActionEvent event) {
+					 if(!format_list.isSelectionEmpty()) {
+						  removeFormat((Format)format_list.getSelectedValue());
+						  // Change buttons
+						  add.setEnabled(true);
+						  remove.setEnabled(false);
+					 }
+				}
+		  }
+		  private class StateListener
+				implements ActionListener {
+				public void actionPerformed(ActionEvent event) {
+					 if(!ignore && current_format != null) {
+						  // We have just performed an edit. Immediately update the format and model.
+						  current_format.setState(on.isSelected());
+						  model.refresh();
+					 }
+				}
+		  }
+		  private class ValueListener
+				extends KeyAdapter {
+				public void keyReleased(KeyEvent event) {
+					 if(!ignore && current_format != null) {
+						  // We have just performed an edit. Immediately update the format and model.
+						  current_format.setValue(value.getText());
+						  model.refresh();
+					 }
+				}
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/GUI.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/GUI.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/GUI.java	(revision 13666)
@@ -0,0 +1,602 @@
+/**
+ *#########################################################################
+ *
+ * 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:      28/05/02
+ **************************************************************************************/
+import java.awt.AWTEvent;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowEvent;
+import javax.swing.BorderFactory;
+import javax.swing.JCheckBox;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.JTree;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.text.JTextComponent;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreePath;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.cdm.CollectionMeta;
+import org.greenstone.gatherer.util.EmailAddress;
+import org.greenstone.gatherer.util.Utility;
+/** 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.
+* @author John Thompson, Greenstone Digital Library, University of Waikato
+* @version 2.3
+*/
+public class GUI
+	 extends JPanel {
+	 /** A reference to the collection manager, as it is here that all of the other data members and managers reside. */
+	 private CollectionDesignManager manager = null;
+	 /** The controls used to modify the general options. */
+	 private Control controls = 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. */
+	 private DesignTree tree = null;
+	 /** A reference to the Gatherer. */
+	 private Gatherer gatherer = null;
+	 /** The title located just above the content tree. */
+	 private JLabel title = null;
+	 /** The panel containing both the title and the tree. */
+	 private JPanel tree_pane = null;
+	 /** The panel apon which is rendered the currently selected section screen. */
+	 private JPanel view = null;
+	 /** The available subscreens. */
+	 static final public String CONTENTS[] = {"General", "Indexes", "Subcollections", "Languages", "Plugins", "Classifiers", "Formats", "MetadataSets"};
+	 /** The preferred size of the collection design module screen real-estate. */
+	 static final private Dimension SIZE = new Dimension(760, 500);
+	 /** Constructor.
+	  * @see DesignTree
+	  * @see org.greenstone.gatherer.cdm.CollectionDesignManager
+	  */
+	 public GUI(Gatherer gatherer, CollectionDesignManager manager) {
+		  super();
+		  // Assignments
+		  this.gatherer = gatherer;
+		  this.manager = manager;
+		  // Creation
+		  this.title = new JLabel(get("Design_Topics"));
+		  this.tree = new DesignTree();
+		  this.tree_pane = new JPanel();
+		  this.view = getControls();
+		  // Connect
+		  tree.addTreeSelectionListener(new TreeListener());
+		  tree_pane.setLayout(new BorderLayout());
+		  tree_pane.add(title, BorderLayout.NORTH);
+		  tree_pane.add(new JScrollPane(tree), BorderLayout.CENTER);
+		  // Layout
+		  setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
+		  setLayout(new BorderLayout());
+		  add(tree_pane, BorderLayout.WEST);
+		  add(view, BorderLayout.CENTER);
+	 }
+	/** Mark the current set of controls as invalid. If they are needed again in the future new controls will be generate.
+	* @see org.greenstone.gatherer.cdm.GUI.Control
+	*/
+	 public void invalidateControls() {
+		  if(controls != null) {
+				controls.destroy();
+		  }
+		  controls = null;
+	 }
+	/** Force the display to show a certain pane of controls.
+	* @param type A <strong>String</strong> giving the name of the submanager view we wish to display.
+	*/
+	 public void setSelectedView(String type) {
+		  tree.setSelectedView(type);
+	 }
+	/** Overrides the normal updateUI to ensure that the current view also recieves an update message.
+	*/
+	 public void updateUI() {
+		  if(view != null) {
+				view.updateUI();
+		  }
+		  super.updateUI();
+	 }
+	 /**Overridden so we can exit when window is closed
+	  * @param event A <strong>WindowsEvent</strong> that encapsulates all the information gathered about the event that called this method.
+	  * @see org.greenstone.gatherer.cdm.CollectionDesignManager
+	  */
+	 protected void processWindowEvent(WindowEvent event) {
+		  if(event.getID() == WindowEvent.WINDOW_CLOSING) {
+				manager.save();
+				System.exit(0);
+		  }
+	 }
+	 /** 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 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.
+	  */
+	 private 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. Note that argument numbers greater than or equal to 32 are automatically mapped to the formatting String named Farg<I>n</I>.
+	  * @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.
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.Dictionary
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf('.') == -1) {
+				key = "CDM.GUI." + key;
+		  }
+		  return gatherer.dictionary.get(key, args);
+	 }
+	 /** Because the CollectionDesignManager has enough to do, this class is resposible for generating the controls for the general options, all of which are stored in the aforementioned manager.
+	  * @return A <strong>JPanel</strong> containing controls for editing the general options.
+	  */
+	 private JPanel getControls() {
+		  if(controls == null) {
+				controls = new Control();
+		  }
+		  return controls;
+	 }
+	 /** This class represents the visual component of the general options stored in the CollectionDesignManager. */
+	 private class Control
+		  extends JPanel {
+			/** The collection metadata representing the extra or description of the collection. */
+		  private CollectionMeta collection_extra_data = null;
+		  /** The collection metadata representing the name of the collection. */
+		  private CollectionMeta collection_name_data = null;
+		  /** The collection metadata representing the icon file location of the collection. */
+		  private CollectionMeta icon_collection_data = null;
+		  /** The default size of label on this control. */
+		  private Dimension LABEL_SIZE = new Dimension(200,25);
+		  /** The checkbox controlling public access to the collection. */
+		  private JCheckBox access = null;
+		  /** The checkbox controlling the state of the collection. */
+		  private JCheckBox beta = null;
+		  /** The label denoting the collection extra area. */
+		  private JLabel collection_extra_label = null;
+		  /** The label denoting the collection extra language (Default). */
+		  private JLabel collection_extra_language = null;
+		  /** The label denoting the collection name area. */
+		  private JLabel collection_name_label = null;
+		  /** The label denoting the name language (Default). */
+		  private JLabel collection_name_language = null;
+		  /** The label denoting the collection icon area. */
+		  private JLabel icon_collection_label = null;
+		  /** The label denoting the icon language (Default). */
+		  private JLabel icon_collection_language = null;
+		  /** The label which serves as the title of this view. */
+		  private JLabel title = null;
+		  /** The panel containing the access controls. */
+		  private JPanel access_pane = null;
+		  /** The panel containing the state controls. */
+		  private JPanel beta_pane = null;
+		  /** The central pane that will contain the view. */
+		  private JPanel central_pane = null;
+		  /** A panel used to affect internal layout of the collection extra area. */
+		  private JPanel collection_extra_inner_pane = null;
+		  /** The panel containing the collection extra area. */
+		  private JPanel collection_extra_pane = null;
+		  /** A panel used to affect internal layout of the collection name area. */
+		  private JPanel collection_name_inner_pane = null;
+		  /** The panel containing the collection name area. */
+		  private JPanel collection_name_pane = null;
+		  /** A panel used to affect internal layout of the collection icon area. */
+		  private JPanel icon_collection_inner_pane = null;
+		  /** The panel containing the icon area. */
+		  private JPanel icon_collection_pane = null;
+		  /** A text area used to display the inline help for this manager. */
+		  private JTextArea instructions = null;
+		  /** The text field used to edit the collections title. */
+		  private JTextField collection_name = null;
+		  /** The text field used to edit the file name of the collections icon. */
+		  private JTextField icon_collection = null;
+		  /** A text area used to modify the collection description. */
+		  private JTextArea collection_extra = null;
+		  /** Constructor.
+		  * @see org.greenstone.gatherer.cdm.CollectionDesignManager
+		  * @see org.greenstone.gatherer.cdm.CollectionMeta
+		  * @see org.greenstone.gatherer.cdm.CollectionMetaManager
+		  * @see org.greenstone.gatherer.cdm.Language
+		  * @see org.greenstone.gatherer.cdm.LanguageManager
+		  */
+		  public Control() {
+				super();
+				collection_extra_data = manager.collectionmetadatum.getCollectionExtra();
+				collection_name_data = manager.collectionmetadatum.getCollectionName();
+				icon_collection_data = manager.collectionmetadatum.getIconCollection();
+				// Creation.
+				access = new JCheckBox(get("CDM.General.Access"));
+				access.setSelected(manager.public_col);
+				access_pane = new JPanel();
+				beta = new JCheckBox(get("CDM.General.Beta"));
+				beta.setSelected(manager.beta);
+				beta_pane = new JPanel();
+				central_pane = new JPanel();
+				collection_extra = new JTextArea();
+				collection_extra_inner_pane = new JPanel();
+				collection_extra_label = new JLabel(get("CDM.General.Collection_Extra"));
+				collection_extra_label.setHorizontalAlignment(JLabel.CENTER);
+				collection_extra_language = new JLabel();
+				collection_extra_pane = new JPanel();
+				if(collection_extra_data != null) {
+					 collection_extra.setText(collection_extra_data.getValue());
+					 Language language = null;
+					 if((language = collection_extra_data.getLanguage()) != null) {
+						  collection_extra_language.setText(language.toString());
+					 }
+					 else {
+						  collection_extra_language.setText(manager.languages.getDefaultLanguage().toString());
+					 }
+				}
+				collection_name = new JTextField();
+				collection_name_inner_pane = new JPanel();
+				collection_name_label = new JLabel(get("CDM.General.Collection_Name"));
+				collection_name_label.setPreferredSize(LABEL_SIZE);
+				collection_name_language = new JLabel();
+				collection_name_pane = new JPanel();
+				if(collection_name_data != null) {
+					 collection_name.setText(collection_name_data.getValue());
+					 Language language = null;
+					 if((language = collection_name_data.getLanguage()) != null) {
+						  collection_name_language.setText(language.toString());
+					 }
+					 else {
+						  collection_name_language.setText(manager.languages.getDefaultLanguage().toString());
+					 }
+				}
+				icon_collection = new JTextField();
+				icon_collection_inner_pane = new JPanel();
+				icon_collection_label = new JLabel(get("CDM.General.Icon_Collection"));
+				icon_collection_label.setPreferredSize(LABEL_SIZE);
+				icon_collection_language = new JLabel();
+				icon_collection_pane = new JPanel();
+				if(icon_collection_data != null) {
+					 icon_collection.setText(icon_collection_data.getValue());
+					 Language language = null;
+					 if((language = icon_collection_data.getLanguage()) != null) {
+						  icon_collection_language.setText(language.toString());
+					 }
+					 else {
+						  icon_collection_language.setText(manager.languages.getDefaultLanguage().toString());
+					 }
+				}
+				instructions = new JTextArea(get("CDM.General.Instructions"));
+				instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				instructions.setEditable(false);
+				instructions.setLineWrap(true);
+				instructions.setRows(4);
+				instructions.setWrapStyleWord(true);
+				JPanel lower = new JPanel();
+				title = new JLabel(get("CDM.General.Title"));
+				title.setHorizontalAlignment(JLabel.CENTER);
+				title.setOpaque(true);
+				JPanel upper = new JPanel();
+				// Add listeners.
+				access.addActionListener(new AccessListener());
+				beta.addActionListener(new BetaListener());
+				collection_extra.addKeyListener(new ChangeListener(collection_extra_data, collection_extra, "collectionextra"));
+				collection_name.addKeyListener(new ChangeListener(collection_name_data, collection_name, "collectionname"));
+				collection_name.addKeyListener(new CollectionTitleListener());
+				icon_collection.addKeyListener(new ChangeListener(icon_collection_data, icon_collection, "iconcollection"));
+				// Layout
+				instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
+
+				upper.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+				upper.setLayout(new BorderLayout());
+				upper.add(title, BorderLayout.NORTH);
+				upper.add(new JScrollPane(instructions), BorderLayout.CENTER);
+
+				collection_name_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+				collection_name_language.setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
+
+				collection_name_inner_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+				collection_name_inner_pane.setLayout(new BorderLayout());
+				collection_name_inner_pane.add(collection_name);
+
+				collection_name_pane.setLayout(new BorderLayout());
+				collection_name_pane.add(collection_name_label, BorderLayout.WEST);
+				collection_name_pane.add(collection_name_inner_pane, BorderLayout.CENTER);
+				collection_name_pane.add(collection_name_language, BorderLayout.EAST);
+
+				icon_collection_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+				icon_collection_language.setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
+
+				icon_collection_inner_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+				icon_collection_inner_pane.setLayout(new BorderLayout());
+				icon_collection_inner_pane.add(icon_collection, BorderLayout.CENTER);
+
+				icon_collection_pane.setLayout(new BorderLayout());
+				icon_collection_pane.add(icon_collection_label, BorderLayout.WEST);
+				icon_collection_pane.add(icon_collection_inner_pane, BorderLayout.CENTER);
+				icon_collection_pane.add(icon_collection_language, BorderLayout.EAST);
+
+				access_pane.add(access);
+
+				beta_pane.add(beta);
+
+				lower.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
+				lower.setLayout(new GridLayout(6,1));
+				lower.add(manager.creator.getControls());
+				lower.add(manager.maintainer.getControls());
+				lower.add(access_pane);
+				lower.add(beta_pane);
+				lower.add(collection_name_pane);
+				lower.add(icon_collection_pane);
+
+				collection_extra_inner_pane.setLayout(new BorderLayout());
+				collection_extra_inner_pane.add(collection_extra_label, BorderLayout.WEST);
+				collection_extra_inner_pane.add(collection_extra_language, BorderLayout.EAST);
+
+				collection_extra.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
+
+				collection_extra_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
+				collection_extra_pane.setLayout(new BorderLayout());
+				collection_extra_pane.add(collection_extra_inner_pane, BorderLayout.NORTH);
+				collection_extra_pane.add(new JScrollPane(collection_extra), BorderLayout.CENTER);
+
+				central_pane.setLayout(new BorderLayout());
+				central_pane.add(lower, BorderLayout.NORTH);
+				central_pane.add(collection_extra_pane, BorderLayout.CENTER);
+
+				setLayout(new BorderLayout());
+				add(upper, BorderLayout.NORTH);
+				add(central_pane, BorderLayout.CENTER);
+		  }
+		  /** Destructor.
+			*/
+		  public void destroy() {
+		  }
+		  /** We override the updateUI method so that we can ensure we are scrolled to the top of the instructions box first.
+			*/
+		  public void updateUI() {
+				if(instructions != null) {
+					 instructions.setCaretPosition(0);
+				}
+				if(collection_extra != null) {
+					 collection_extra.setCaretPosition(0);
+				}
+				super.updateUI();
+		  }
+		  /** Detect when the collection access changes, and update the configuration as necessary.
+		  * @see org.greenstone.gatherer.cdm.CollectionDesignManager
+		  */
+		  private class AccessListener
+				implements ActionListener {
+				public void actionPerformed(ActionEvent event) {
+					 manager.public_col = access.isSelected();
+				}
+		  }
+		  /** Detect when the collection state changes and update the configuration as necessary.
+		  * @see org.greenstone.gatherer.cdm.CollectionDesignManager
+		  */
+		  private class BetaListener
+				implements ActionListener {
+				public void actionPerformed(ActionEvent event) {
+					 manager.beta = beta.isSelected();
+				}
+		  }
+		  /** This class listens for any changes its registered controls, including enter actions and keys typed, and updates the fields stored in CollectionDesignManager as necessary. */
+		  private class ChangeListener
+				extends KeyAdapter {
+				/** The collection metadata to alter. */
+				private CollectionMeta metadata = null;
+				/** The control we are watching for changes. */
+				private JTextComponent component = null;
+				/** The name of the metadata to monitor. */
+				private String name = null;
+				/** Construstor.
+				* @param metadata The <strong>CollectionMeta</strong> to alter.
+				* @param component The <strong>JTextComponent</strong> we are monitoring for changes.
+				* @param name The name of the metadata as a <strong>String</strong>.
+				*/
+				public ChangeListener(CollectionMeta metadata, JTextComponent component, String name) {
+					 this.component = component;
+					 this.metadata = metadata;
+					 if(metadata != null) {
+						  this.name = metadata.getName().toString();
+					 }
+					 else {
+						  this.name = name;
+					 }
+				}
+				/** Any extension of a KeyAdapter may override this method so we can be informed when a key has been released (ie after the character etc has been added). In this case we want to update the appropriate metadata, however there are three distinct cases to consider:<br>&nbsp;1. A simple update of the value field is all that is necessary,<br>&nbsp;2. The metadata exists but it currently has no language, so we must set the language to default and update the value, or<br>&nbsp;3. The metadata doesn't exist so we'll create a new one with the specified name, default language and new value.<br>This final case is highly unlikely but still possible.
+				* @param event An <strong>Event</strong> containing information about the key release.
+				* @see org.greenstone.gatherer.Gatherer
+				* @see org.greenstone.gatherer.cdm.CollectionDesignManager
+				* @see org.greenstone.gatherer.cdm.CollectionMeta
+				* @see org.greenstone.gatherer.cdm.CollectionMetaManager
+				* @see org.greenstone.gatherer.cdm.Language
+				* @see org.greenstone.gatherer.cdm.LanguageManager
+				* @see org.greenstone.gatherer.collection.CollectionManager
+				*/
+				public void keyReleased(KeyEvent event) {
+					 if(metadata != null) {
+						  Language language = metadata.getLanguage();
+						  if(language == null) {
+								metadata.update(metadata.getName(), manager.languages.getDefaultLanguage(), component.getText());
+						  }
+						  else {
+								metadata.update(metadata.getName(), metadata.getLanguage(), component.getText());
+						  }
+					 }
+					 else {
+						  metadata = new CollectionMeta(manager, name, manager.languages.getDefaultLanguage(), component.getText());
+						  manager.collectionmetadatum.addMetadata(metadata);
+					 }
+					 gatherer.c_man.configurationChanged();
+			   }
+		  }
+		  /** Listens for changes to the collection name and updates the windows title bar appropriately and collection file. */
+		  private class CollectionTitleListener
+				extends KeyAdapter {
+				/** Any extension of a KeyAdapter may override this method so we can be informed when a key has been released (ie after the character etc has been added). When such a change occurs update the main guis title bar to reflect the change and fix the collection name.
+				 * @param event An <strong>Event</strong> containing information about the key release.
+				 */
+				public void keyReleased(KeyEvent event) {
+					 String name = collection_name.getText();
+					 if(name != null && name.length() > 0) {
+						  gatherer.g_man.setTitle(Utility.PROGRAM_NAME + ":\"" + name + "\"");
+						  gatherer.c_man.getCollection().setTitle(name);
+					 }
+				}
+		  }
+	 }
+	 /** 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();
+				root = new DesignNode("Root");
+				this.setModel(new DefaultTreeModel(root));
+				// Now add the design categories.
+				for(int i = 0; i < CONTENTS.length; i++) {
+					 root.add(new DesignNode(CONTENTS[i]));
+				}
+				expandRow(0);
+				setRootVisible(false);
+				setSelectionRow(0);
+		  }
+			/** Set the current view to the one specified.
+			* @param type The name of the desired view as a <strong>String</strong>.
+			* @see org.greenstone.gatherer.Gatherer
+			* @see org.greenstone.gatherer.cdm.GUI.DesignNode
+			*/
+		  public void setSelectedView(String type) {
+				type = gatherer.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 <strong>String</strong>.
+		  */
+		  public String toString() {
+				return 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.MetadataSetManager
+		  * @see org.greenstone.gatherer.cdm.SubcollectionManager
+		  * @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();
+					 // Assure user
+					 // Build and change panes.
+					 remove(view);
+					 view.hasFocus(); // Trigger pending information update events.
+					 if(type.equals("General")) {
+						  view = getControls();
+					 }
+					 else if(type.equals("Indexes")) {
+						  view = manager.indexes.getControls();
+					 }
+					 else if(type.equals("Subcollections")) {
+						  view = manager.subcollections.getControls();
+					 }
+					 else if(type.equals("Languages")) {
+						  view = manager.languages.getControls();
+					 }
+					 else if(type.equals("Plugins")) {
+						  view = manager.plugins.getControls();
+					 }
+					 else if(type.equals("Classifiers")) {
+						  view = manager.classifiers.getControls();
+					 }
+					 else if(type.equals("Formats")) {
+						  view = manager.formats.getControls();
+					 }
+					 else if(type.equals("MetadataSets")) {
+						  view = manager.metadatasets.getControls();
+					 }
+					 add(view, BorderLayout.CENTER);
+					 view.updateUI();
+					 // Ready
+				}
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/Index.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/Index.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/Index.java	(revision 13666)
@@ -0,0 +1,204 @@
+/**
+ *#########################################################################
+ *
+ * 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:      17/11/02
+ **************************************************************************************/
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Vector;
+import org.greenstone.gatherer.cdm.CollectionMeta;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.w3c.dom.Element;
+/** This class encapsulates a single indexing pair.
+* @author John Thompson, Greenstone Digital Library, University of Waikato
+* @version 2.2
+*/
+public class Index
+	 implements Comparable {
+	 /** A refernce to the main manager for access to other sub-managers. */
+	 private CollectionDesignManager manager = null;
+	 /** The level of this index. */
+	 private int level = 0;
+	 /** The sources for data this index is built apon, which are either fully qualified metadata element names or 'text'. */
+	 private Vector sources = null;
+	 /** An element in the index level enumeration. */
+	 static public final int DOCUMENT = 0;
+	 /** An element in the index level enumeration. */
+	 static public final int PARAGRAPH = 1;
+	 /** An element in the index level enumeration. */
+	 static public final int SECTION = 2;
+	 /** An values of items in the index level enumeration. */
+	 static public final String LEVEL[] = {"document","paragraph","section"};
+	 /** Constructor.
+	  * @param level The level of this index as a <strong>String</string>.
+	  * @param metadata The fully qualified name of the metadata this index is built on as a <strong>String</strong>, or <i>null</i> in which case the data defaults to "text".
+	  */
+	 public Index(int level, Vector sources, CollectionDesignManager manager) {
+		  this.level = level;
+		  this.manager = manager;
+		  this.sources = sources;
+		  if(this.sources == null) {
+				this.sources = new Vector();
+				this.sources.add("text");
+		  }
+	 }
+	 /** 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 instanceof Index) {
+				Index index = (Index) object;
+				return toString(false).compareTo(index.toString(false));
+		  }
+		  return toString(false).compareTo(object.toString());
+	 }
+	 /** 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) {
+		  if(compareTo(object) == 0) {
+				return true;
+		  }
+		  return false;
+	 }
+	 /** Method to get the data source of this index.
+	  * @return A <strong>String</string> which is a comma separated list of either fully qualified names of an assigned metadata elements, or "text".
+	  */
+	 public String getData() {
+		  String result = "";
+		  Collections.sort(sources, new IndexComparator());
+		  for(int i = 0; i < sources.size(); i++) {
+				result = result + sources.get(i).toString();
+				if(i < sources.size() - 1) {
+					 result = result + ",";
+				}
+		  }
+		  return result;
+	 }
+	 /** Method to get the value of level.
+	  * @return The value of level as a <strong>String</strong>.
+	  */
+	 public int getLevel() {
+		  return level;
+	 }
+	 /** Method to get the value of metadata.
+	  * @return The value of metadata as an <strong>Vector</strong>.
+	  */
+	 public Vector getMetadata() {
+		  return sources;
+	 }
+	 /** Method to retrieve this indexes name.
+	  * @return A <strong>String</strong>.
+	  */
+	 public String getName() {
+		  if(manager != null) {
+				String name = LEVEL[level] + ":" + getData();
+				Language language = manager.languages.getDefaultLanguage();
+				CollectionMeta metadata = manager.collectionmetadatum.getMetadata(name, language, true);
+				if(metadata != null) {
+					 return metadata.getValue();
+				}
+		  }
+		  return "";
+	 }
+	 /** 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 LEVEL[level] + ":" + getData() + "  \"" + getName() + "\"";
+	 }
+	/** Retrieve a textual representation of this index.
+	* @param show_name <i>true</i> if you want the name of this index, <i>false</i> for the gsdl index reference.
+	*/
+	 public String toString(boolean show_name) {
+		  if(show_name) {
+				return getName();
+		  }
+		  return LEVEL[level] + ":" + getData();
+	 }
+	/** A custom comparator for comparing Indexes. */
+	 private class IndexComparator
+		  implements Comparator {
+		  /** Method to compare two objects, which may be either indexes or strings.
+			* @param object1 One object as an <strong>Object</strong>.
+			* @param object2 Another object as an <strong>Object</strong>.
+			* @return An <i>int</i> which indicates how they compare.
+			* @see java.lang.String
+			*/
+		  public int compare(Object object1, Object object2) {
+				if(object1 instanceof Index && object2 instanceof Index) {
+					 Index index1 = (Index)object1;
+					 Index index2 = (Index)object2;
+					 return index1.toString(false).compareTo(index2.toString(false));
+				}
+				else if(object1 instanceof Index) {
+					 Index index = (Index) object1;
+					 return index.toString(false).compareTo(object2.toString());
+				}
+				else if(object2 instanceof Index) {
+					 Index index = (Index) object2;
+					 return object1.toString().compareTo(index.toString(false));
+				}
+				return object1.toString().compareTo(object2.toString());
+		  }
+		  /** Method to test for the equality of two objects, which may be indexes or strings.
+			* @param object Another object as an <strong>Object</strong>.
+			* @return A <i>boolean</i> which is <i>true</i> if the two objects are equal, <i>false</i> otherwise.
+			*/
+		  public boolean equals(Object object) {
+				if(compareTo(object) == 0) {
+					 return true;
+				}
+				return false;
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/IndexManager.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/IndexManager.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/IndexManager.java	(revision 13666)
@@ -0,0 +1,713 @@
+/**
+ *#########################################################################
+ *
+ * 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:      17/11/02 - Commented
+ **************************************************************************************/
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.util.Collections;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import javax.swing.BorderFactory;
+import javax.swing.DefaultListModel;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.event.ListDataEvent;
+import javax.swing.event.ListDataListener;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.CommandTokenizer;
+import org.greenstone.gatherer.cdm.Index;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.greenstone.gatherer.util.ExclusiveListSelectionListener;
+import org.w3c.dom.Element;
+/** 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 DefaultListModel {
+	 /** A reference to our creator, the collection design manager. */
+	 private CollectionDesignManager manager = null;
+	 /** The controls for editing the indexes. */
+	 private Control controls = null;
+	 /** A reference to ourselves so our inner methods have access. */
+	 private DefaultListModel model = null;
+	 /** A reference to the Gatherer, for access to the Dictionary and messaging purposes. */
+	 private Gatherer gatherer = null;
+	 /** The default index. */
+	 private Index default_index = null;
+	 /** Constructor.
+	 * @param gatherer A reference to the <strong>Gatherer</strong>.
+	 * @param manager A reference to the <strong>CollectionDesignManager</strong>.
+	 */
+	 public IndexManager(Gatherer gatherer, CollectionDesignManager manager) {
+		  super();
+		  this.gatherer = gatherer;
+		  this.manager = manager;
+		  this.model = this;
+	 }
+	 /** 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
+	  */
+	 public void addIndex(Index index) {
+		  if(!contains(index)) {
+				String index_str = index.toString(false).toLowerCase();
+				// Add alphabetically.
+				for(int i = 0; i < size(); i++) {
+					 Index sibling = (Index) get(i);
+					 String sibling_str = sibling.toString(false).toLowerCase();
+					 int position = index_str.compareTo(sibling_str);
+					 // Sibling is before index.
+					 if(position > 0) {
+						  // Carry on.
+					 }
+					 // Index is equal to, or before sibling. Insert it.
+					 else if(position == 0 || position < 0) {
+						  add(i, index);
+						  gatherer.c_man.configurationChanged();
+						  return;
+					 }
+				}
+				// If we got this far, we haven't inserted index, and we are out of model so.
+				addElement(index);
+				gatherer.c_man.configurationChanged();
+		  }
+		  else {
+				JOptionPane.showMessageDialog(manager.gui, get("CDM.IndexManager.Index_Exists"), get("General.Warning"), JOptionPane.WARNING_MESSAGE);
+		  }
+	 }
+	 /** Method to acquire the controls for editing the indexes.
+	  * @return A <strong>JPanel</strong> containing the controls.
+	  * @see org.greenstone.gatherer.cdm.IndexManager.Control
+	  */
+	 public JPanel getControls() {
+		  if(controls == null) {
+				controls = new Control();
+		  }
+		  return controls;
+	 }
+	 /** Method to get the default index.
+	  * @return The default <strong>Index</strong>.
+	  */
+	 public Index getDefault() {
+		  return default_index;
+	 }
+	 /** 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 < size()) {
+				return (Index)get(index);
+		  }
+		  return null;
+	 }
+	 /** Method to retrieve a certain index, given its name.
+	  * @param name The name of the index as a <Strong>String</strong>.
+	  * @return The <strong>Index</strong> that matches name, or <i>null</i> if no such index exists.
+	  */
+	 public Index getIndex(String name) {
+		  ///ystem.err.println("Searching for index " + name);
+		  for(int i = 0; i < size(); i++) {
+				Index index = (Index) get(i);
+				if(index.toString(false).equals(name)) {
+					 ///ystem.err.println("Found.");
+					 return (Index)get(i);
+				}
+		  }
+		  ///ystem.err.println("No such index.");
+		  return null;
+	 }
+	 /** A method to retrieve all of the indexes associated with this manager.
+	  * @return A <strong>Vector</strong> of <strong>Index</strong>es.
+	  */
+	 public Vector getIndexes() {
+		  Vector indexes = new Vector();
+		  for(int i = 0; i < size(); i++) {
+				indexes.add(get(i));
+		  }
+		  Collections.sort(indexes);
+		  return indexes;
+	 }
+	/** Mark the current set of controls, if any, as obsolete and deallocate them. If further need of the controls will cause new controls to be created.
+	* @see org.greenstone.gatherer.cdm.IndexManager.Control
+	*/
+	 public void invalidateControls() {
+		  if(controls != null) {
+				controls.destroy();
+		  }
+		  controls = null;
+	 }
+	 /** Method that attempts to parse an index related command from the given command. If such a command is parsed, it is immediately registered with this manager.
+	  * @param command The <strong>String</strong> to parse.
+	  * @return A <i>boolean</i> which is <i>true</i> if a command was parsed, <i>false</i> otherwise.
+	  * @see org.greenstone.gatherer.cdm.CommandTokenizer
+	  * @see org.greenstone.gatherer.cdm.Index
+	  */
+	 public boolean parse(String command) {
+		  String temp = command.toLowerCase();
+		  if(temp.startsWith("indexes")) {
+				CommandTokenizer ct = new CommandTokenizer(command);
+				ct.nextToken(); // Throw away indexes.
+				while(ct.hasMoreTokens()) {
+					 String entry = ct.nextToken();
+					 if(entry.indexOf(":") != -1) {
+						  String level_str = entry.substring(0, entry.indexOf(":"));
+						  String sources_raw = entry.substring(entry.indexOf(":") + 1);
+						  Vector sources = new Vector();
+						  StringTokenizer st = new StringTokenizer(sources_raw, ",");
+						  while(st.hasMoreTokens()) {
+								String token = st.nextToken();
+								// We may have to replace old : with whatever namespace separator we are using.
+								token = token.replace(':', MSMUtils.NS_SEP);
+								sources.add(token);
+						  }
+						  for(int i = 0; i < Index.LEVEL.length; i++) {
+								if(level_str.equals(Index.LEVEL[i])) {
+									 addIndex(new Index(i, sources, manager));
+								}
+						  }
+					 }
+					 else {
+						  return false;
+					 }
+				}
+				return true;
+		  }
+		  else if(temp.startsWith("defaultindex")) {
+				CommandTokenizer ct = new CommandTokenizer(command);
+				ct.nextToken();
+				String entry = ct.nextToken();
+				if(entry.indexOf(":") != -1) {
+					 String level_str = entry.substring(0, entry.indexOf(":"));
+					 String sources_raw = entry.substring(entry.indexOf(":") + 1);
+					 Vector sources = new Vector();
+					 StringTokenizer st = new StringTokenizer(sources_raw, ",");
+					 while(st.hasMoreTokens()) {
+						  sources.add(st.nextToken());
+					 }
+					 for(int i = 0; i < Index.LEVEL.length; i++) {
+						  if(level_str.equals(Index.LEVEL[i])) {
+								setDefault(new Index(i, sources, manager));
+						  }
+					 }
+				}
+				else {
+					 return false;
+				}
+				return true;
+		  }
+		  return false;
+	 }
+
+	 public void removeAll() {
+		  removeAllElements();
+		  default_index = null;
+		  gatherer.c_man.configurationChanged();
+	 }
+
+	 /** Method to remove a certain index.
+	  * @param index The <Strong>Index</strong> 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
+	  */
+	 public void removeIndex(Index index) {
+		  if(index != null) {
+				String name = index.getName();
+				if(name != null) {
+					 Language default_language = manager.languages.getDefaultLanguage();
+					 CollectionMeta metadata = new CollectionMeta(manager, index, default_language, name);
+					 manager.collectionmetadatum.removeMetadata(metadata);
+				}
+				removeElement(index);
+				if(default_index != null && default_index.equals(index)) {
+					 default_index = null;
+				}
+				gatherer.c_man.configurationChanged();
+		  }
+	 }
+	 /** Method to set the default index.
+	  * @param index The new default <strong>Index</strong>.
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.CollectionManager
+	  */
+	 public void setDefault(Index index) {
+		  default_index = index;
+		  if(index != null && !contains(index)) {
+				addElement(index);
+		  }
+		  gatherer.c_man.configurationChanged();
+	 }
+	 /** Method to print out the contents of this class as a string.
+	  * @return A <strong>String</strong> just as it would appear in the colleciton configuration file.
+	  */
+	 public String toString() {
+		  String text = "";
+		  // First the indexes.
+		  if(size() > 0) {
+				text = "indexes      ";
+				for(int i = 0; i < size(); i++) {
+					 Index index = (Index) get(i);
+					 text = text + index.toString(false);
+					 if(i < size() - 1) {
+						  text = text + " ";
+					 }
+				}
+				// Now the default index if there is one, or just the first index
+				// if there isn't
+				if(default_index != null) {
+					 text = text + "\ndefaultindex " + default_index.toString(false) + "\n";
+				}
+				text = text + "\n";
+		  }
+		  return text;
+	 }
+	 /** 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 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.
+	  */
+	 private 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. Note that argument numbers greater than or equal to 32 are automatically mapped to the formatting String named Farg<I>n</I>.
+	  * @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.
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.Dictionary
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf('.') == -1) {
+				key = "CDM.IndexManager." + key;
+		  }
+		  return gatherer.dictionary.get(key, args);
+	 }
+	 /** This class creates a set of controls for editing the indexes. */
+	 private class Control
+		  extends JPanel {
+			/** The default size of a label on this control. */
+		  private Dimension LABEL_SIZE = new Dimension(120,25);
+		  /** The button used to add a new index. */
+		  private JButton add = null;
+		  /** The button used to clear the default index. */
+		  private JButton clear_default = null;
+		  /** The button used to remove an index. */
+		  private JButton remove = null;
+		  /** The button used to set the default index. */
+		  private JButton set_default = null;
+		  /** The combobox used to adjust what level the new index will built on. */
+		  private JComboBox level = null;
+		  /** The label denoting the default index to be built for this collection. */
+		  private JLabel default_label = null;
+		  /** The label denoting the list of assigned indexes. */
+		  private JLabel index_label = null;
+		  /** The label denoting the control for choosing index level. */
+		  private JLabel level_label = null;
+		  /** The label denoting the name of the index. */
+		  private JLabel name_label = null;
+		  /** The label denoting the list of possible sources for the index. */
+		  private JLabel source_label = null;
+		  /** The title shown at the top of the index controls. */
+		  private JLabel title = null;
+		  /** The list of assigned indexes. */
+		  private JList index_list = null;
+		  /** The list of possible sources on which the index could be built. */
+		  private JList source_list = null;
+		  /** The panel used to display the list of assigned indexes. */
+		  private JPanel assigned_pane = null;
+		  /** The panel which contains the buttons used to edit indexes. */
+		  private JPanel button_pane = null;
+		  /** The panel on which all other panels are displayed. */
+		  private JPanel central_pane = null;
+		  /** The control pane showing the editable controls. */
+		  private JPanel control_pane = null;
+		  /** The edit pane contains the list of possible sources. */
+		  private JPanel edit_pane = null;
+		  /** A panel used to correctly lay out the default index label. */
+		  private JPanel default_pane = null;
+		  /** The panel containing the title label and instructions. */
+		  private JPanel header_pane = null;
+		  /** The lvel panel contains the control for adjusting index level. */
+		  private JPanel level_pane = null;
+		  /** The pane in which the name control is set. */
+		  private JPanel name_pane = null;
+		  /** The scrollpane containing the instructions text area. */
+		  private JScrollPane instructions_scroll = null;
+		  /** A text area containing inline instructions. */
+		  private JTextArea instructions = null;
+		  /** A text field naming the default index. Non-editable. */
+		  private JTextField default_value = null;
+		  /** A text field for controlling the name of the new index. */
+		  private JTextField name = null;
+		  /** A model containing all of the available index sources. */
+		  private Vector source_model = null;
+		  /** Constructor.
+			* @see org.greenstone.gatherer.Configuration
+			* @see org.greenstone.gatherer.Gatherer
+			* @see org.greenstone.gatherer.cdm.IndexManager.Control.AddListener
+			* @see org.greenstone.gatherer.cdm.IndexManager.Control.ClearDefaultListener
+			* @see org.greenstone.gatherer.cdm.IndexManager.Control.NameListener
+			* @see org.greenstone.gatherer.cdm.IndexManager.Control.RemoveListener
+			* @see org.greenstone.gatherer.cdm.IndexManager.Control.SetDefaultListener
+			* @see org.greenstone.gatherer.collection.CollectionManager
+			* @see org.greenstone.gatherer.gui.Coloring
+			* @see org.greenstone.gatherer.msm.MetadataSetManager
+			* @see org.greenstone.gatherer.util.ExclusiveListSelectionListener
+			*/
+		  public Control() {
+				super();
+				source_model = new Vector();
+				source_model.add("text");
+				source_model.addAll(gatherer.c_man.msm.getAssignedElements());
+				//source_model.addAll(gatherer.c_man.msm.getElements());
+				// Creation
+				add = new JButton(get("Add"));
+				add.setEnabled(false);
+				add.setMnemonic(KeyEvent.VK_A);
+				assigned_pane = new JPanel();
+				button_pane = new JPanel();
+				central_pane = new JPanel();
+				control_pane = new JPanel();
+				clear_default = new JButton(get("Clear_Default"));
+				clear_default.setMnemonic(KeyEvent.VK_C);
+				if(default_index == null) {
+					 clear_default.setEnabled(false);
+				}
+				default_label = new JLabel(get("Default_Index"));
+				default_pane = new JPanel();
+				if(default_index != null) {
+					 default_value = new JTextField(default_index.toString(true));
+					 default_value.setCaretPosition(0);
+				}
+				else {
+					 default_value = new JTextField();
+				}
+				edit_pane = new JPanel();
+				header_pane = new JPanel();
+				index_label = new JLabel(get("Indexes"));
+				index_list = new JList(model);
+				instructions = new JTextArea(get("Instructions"));
+				instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				instructions.setEditable(false);
+				instructions.setLineWrap(true);
+				instructions.setRows(5);
+				instructions.setWrapStyleWord(true);
+				level = new JComboBox();
+				level.addItem(get("Document"));
+				level.addItem(get("Paragraph"));
+				level.addItem(get("Section"));
+				level.setEditable(false);
+				level_label = new JLabel(get("Level"));
+				level_label.setPreferredSize(LABEL_SIZE);
+				level_pane = new JPanel();
+				name = new JTextField();
+				name_label = new JLabel(get("Name"));
+				name_label.setPreferredSize(LABEL_SIZE);
+				name_pane = new JPanel();
+				remove = new JButton(get("Remove"));
+				remove.setEnabled(false);
+				remove.setMnemonic(KeyEvent.VK_R);
+				set_default = new JButton(get("Set_Default"));
+				set_default.setEnabled(false);
+				set_default.setMnemonic(KeyEvent.VK_S);
+				source_label = new JLabel(get("Source"));
+				source_list = new JList(source_model);
+				title = new JLabel(get("Title"));
+				title.setHorizontalAlignment(JLabel.CENTER);
+
+				// Listeners
+				add.addActionListener(new AddListener());
+				clear_default.addActionListener(new ClearDefaultListener());
+				remove.addActionListener(new RemoveListener());
+				set_default.addActionListener(new SetDefaultListener());
+				name.addKeyListener(new NameListener());
+				ListListener ll = new ListListener();
+				index_list.addListSelectionListener(ll);
+				source_list.addListSelectionListener(ll);
+				ExclusiveListSelectionListener elsl = new ExclusiveListSelectionListener();
+				elsl.add(index_list);
+				elsl.add(source_list);
+
+				// Layout
+				title.setBorder(BorderFactory.createEmptyBorder(0,0,2,0));
+
+				instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
+
+				header_pane.setLayout(new BorderLayout());
+				header_pane.add(title, BorderLayout.NORTH);
+				header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER);
+
+				name_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+
+				name_pane.setBorder(BorderFactory.createEmptyBorder(4,2,4,2));
+				name_pane.setLayout(new BorderLayout());
+				name_pane.add(name_label, BorderLayout.WEST);
+				name_pane.add(name, BorderLayout.CENTER);
+
+				control_pane.setLayout(new BorderLayout());
+				control_pane.add(source_label, BorderLayout.NORTH);
+				control_pane.add(new JScrollPane(source_list), BorderLayout.CENTER);
+
+				level_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+
+				level_pane.setBorder(BorderFactory.createEmptyBorder(4,2,4,2));
+				level_pane.setLayout(new BorderLayout());
+				level_pane.add(level_label, BorderLayout.WEST);
+				level_pane.add(level, BorderLayout.CENTER);
+
+				edit_pane.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+				edit_pane.setLayout(new BorderLayout());
+				edit_pane.add(name_pane, BorderLayout.NORTH);
+				edit_pane.add(control_pane, BorderLayout.CENTER);
+				edit_pane.add(level_pane, BorderLayout.SOUTH);
+
+				default_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+
+				default_pane.setBorder
+					 (BorderFactory.createCompoundBorder
+					  (BorderFactory.createCompoundBorder
+						(BorderFactory.createEmptyBorder(2,2,2,2),
+						 BorderFactory.createRaisedBevelBorder()),
+						BorderFactory.createEmptyBorder(2,2,2,2)));
+				default_pane.setLayout(new BorderLayout());
+				default_pane.add(default_label, BorderLayout.WEST);
+				default_pane.add(default_value, BorderLayout.CENTER);
+
+				assigned_pane.setLayout(new BorderLayout());
+				assigned_pane.add(index_label, BorderLayout.NORTH);
+				assigned_pane.add(new JScrollPane(index_list), BorderLayout.CENTER);
+				assigned_pane.add(default_pane, BorderLayout.SOUTH);
+
+				central_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
+				central_pane.setLayout(new GridLayout(1,2));
+				central_pane.add(edit_pane);
+				central_pane.add(assigned_pane);
+
+				button_pane.setLayout(new GridLayout(2,2));
+				button_pane.add(add);
+				button_pane.add(remove);
+				button_pane.add(clear_default);
+				button_pane.add(set_default);
+
+				setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+				setLayout(new BorderLayout());
+				add(header_pane, BorderLayout.NORTH);
+				add(central_pane, BorderLayout.CENTER);
+				add(button_pane, BorderLayout.SOUTH);
+		  }
+		  /* Destructor, removes persistant listeners from the Dictionary.
+			*/
+		  public void destroy() {
+		  }
+		  /** We override the updateUI method so that we can ensure we are scrolled to the top of the instructions box first.
+		  * @see org.greenstone.gatherer.Gatherer
+		  * @see org.greenstone.gatherer.collection.CollectionManager
+		  * @see org.greenstone.gatherer.msm.MetadataSetManager
+			*/
+		  public void updateUI() {
+				if(instructions != null) {
+					 instructions.setCaretPosition(0);
+				}
+				// Reload the assigned indexes list.
+				if(source_model != null) {
+					 source_model.clear();
+					 source_model.add("text");
+					 source_model.addAll(gatherer.c_man.msm.getAssignedElements());
+				}
+				// Faster than a NPE its the - 'Super class'.
+				super.updateUI();
+		  }
+		  /** Listens for actions apon the 'add' button in the IndexManager controls, and if detected calls the add method of the manager with a newly created index. */
+		  private class AddListener
+				implements ActionListener {
+				/** Method called when an action is performed on a registered component, and when it does we check if we have enough data to create a new index, and if so we create one.
+				* @param event An <strong>ActionEvent</strong> providing extra information about the event.
+				* @see org.greenstone.gatherer.cdm.CollectionDesignManager
+				* @see org.greenstone.gatherer.cdm.CollectionMeta
+				* @see org.greenstone.gatherer.cdm.CollectionMetaManager
+				* @see org.greenstone.gatherer.cdm.Index
+				* @see org.greenstone.gatherer.cdm.Language
+				* @see org.greenstone.gatherer.cdm.LanguageManager
+				*/
+				public void actionPerformed(ActionEvent event) {
+					 if(!source_list.isSelectionEmpty() && name.getText().length() != 0) {
+						  Object object[] = source_list.getSelectedValues();
+						  Vector sources = new Vector();
+						  for(int i = 0; i < object.length; i++) {
+								sources.add(object[i]);
+						  }
+						  Index index = new Index(level.getSelectedIndex(), sources, manager);
+						  // Before we add the index to the model, we have to add the collection metadata for this.
+						  Language language = manager.languages.getDefaultLanguage();
+						  CollectionMeta metadata = new CollectionMeta(manager, index, language, name.getText());
+						  manager.collectionmetadatum.addMetadata(metadata);
+						  // Finally add index.
+						  addIndex(index);
+					 }
+				}
+		  }
+		  /** Listens for actions apon the 'clear default' button in the IndexManager controls, and if detected calls the setDefault method of the manager with <i>null</i>. */
+		  private class ClearDefaultListener
+				implements ActionListener {
+				/** If called when an action occurs on a registered component, we clear the default index.
+				* @param event An <strong>ActionEvent</strong> containing extra information about the action that occured.
+				*/
+				public void actionPerformed(ActionEvent event) {
+					 setDefault(null);
+					 clear_default.setEnabled(false);
+					 default_value.setText("");
+				}
+		  }
+		  /** Listens for actions apon the 'remove' button in the IndexManager controls, and if detected calls the remove method of the manager with the index selected for removal. */
+		  private class RemoveListener
+				implements ActionListener {
+				/** If called when an action occurs on a registered component, we remove the currently selected index, if there is one.
+				* @param event An <strong>ActionEvent</strong> containing extra information about the action that occured.
+				* @see org.greenstone.gatherer.cdm.Index
+				*/
+				public void actionPerformed(ActionEvent event) {
+					 if(!index_list.isSelectionEmpty()) {
+						  removeIndex((Index)index_list.getSelectedValue());
+						  if(default_index == null) {
+								clear_default.setEnabled(false);
+								default_value.setText("");
+						  }
+					 }
+				}
+		  }
+		  /** Listens for actions apon the 'set default' button in the IndexManager controls, and if detected calls the setDefault method of the manager with the index selected for default. */
+		  private class SetDefaultListener
+				implements ActionListener {
+				/** If called when an action occurs on a registered component, we set the default index to the index currently selected.
+				* @param event An <strong>ActionEvent</strong> containing extra information about the action that occured.
+				* @see org.greenstone.gatherer.cdm.Index
+				*/
+				public void actionPerformed(ActionEvent event) {
+					 setDefault((Index)index_list.getSelectedValue());
+					 if(default_index != null) {
+						  clear_default.setEnabled(true);
+						  default_value.setText(default_index.toString(true));
+						  default_value.setCaretPosition(0);
+					 }
+					 else {
+						  clear_default.setEnabled(false);
+						  default_value.setText("");
+					 }
+				}
+		  }
+		  /** Listens for key presses within the name field, and enabled or disables controls as appropriate. */
+		  private class NameListener
+				extends KeyAdapter {
+				/** Called when a key is released, this is the perfect time to enable the add button if the fields are appropriately set.
+				* @param event A <strong>KeyEvent</strong> containing information about the key released.
+				*/
+				public void keyReleased(KeyEvent event) {
+					 if(source_list.isSelectionEmpty() || name.getText().length() == 0) {
+						  add.setEnabled(false);
+					 }
+					 else {
+						  add.setEnabled(true);
+					 }
+					 if(index_list.isSelectionEmpty()) {
+						  remove.setEnabled(false);
+						  set_default.setEnabled(false);
+					 }
+					 else {
+						  remove.setEnabled(true);
+						  set_default.setEnabled(true);
+					 }
+				}
+		  }
+		  /** Listens for selections within the list on the IndexManager controls, and if a change is detected enables, or disables, controls appropriately. */
+		  private class ListListener
+				implements ListSelectionListener {
+				/** This method is called whenever the source list selection changes. When it does we need to check if the add button should now be enabled.
+				* @param event A <strong>ListSelectionEvent</strong> containing further information about the list selection.
+				*/
+				public void valueChanged(ListSelectionEvent event) {
+					 if(source_list.isSelectionEmpty() || name.getText().length() == 0) {
+						  add.setEnabled(false);
+					 }
+					 else {
+						  add.setEnabled(true);
+					 }
+					 if(index_list.isSelectionEmpty()) {
+						  remove.setEnabled(false);
+						  set_default.setEnabled(false);
+					 }
+					 else {
+						  remove.setEnabled(true);
+						  set_default.setEnabled(true);
+					 }
+				}
+		  }
+	 }
+}
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/Language.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/Language.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/Language.java	(revision 13666)
@@ -0,0 +1,130 @@
+/**
+ *#########################################################################
+ *
+ * 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:      08/05/02
+ * Revised:      17/11/02 - Commented
+ **************************************************************************************/
+
+/** 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 {
+	 /** Is this language the default one. */
+	 private boolean default_language = false;
+	 /** The name of this language. */
+	 private String name = null;
+	 /** The two character code for this language. */
+	 private String value = null;
+	 /** Constructor.
+	  * @param value A <strong>String</strong> representing the code for this language.
+	  * @param name A <strong>String</strong> representing the name of this language.
+	  * @param default_language A <i>boolean</i> which is <i>true</i> if this language is the default one.
+	  */
+	 public Language(String value, String name, boolean default_language) {
+		  this.default_language = default_language;
+		  this.name = name;
+		  this.value = value.substring(0, 2);
+	 }
+	 /** Copy constructor.
+	  * @param language The <strong>Language</strong> we want to copy.
+	  */
+	 public Language(Language language) {
+		  this.default_language = language.isDefault();
+		  this.name = language.toString();
+		  this.value = language.getCode();
+	 }
+	 /** Method to compare two languages for ordering purposes.
+	  * @param object The other language as an <strong>Object</strong>.
+	  * @return An <i>int</i> which indicates order using the same values as in String.compareTo().
+	  * @see java.lang.String#compareTo
+	  */
+	 public int compareTo(Object object) {
+		  return toString().compareTo(object.toString());
+	 }
+	 /** 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) {
+		  if(compareTo(object) == 0) {
+				return true;
+		  }
+		  return false;
+	 }
+	 /** Method to retrieve the code of this language.
+	  * @return A <strong>String</strong> representing the two letter code.
+	  */
+	 public String getCode() {
+		  return value;
+	 }
+	 /** Method to determine if this language is the default one.
+	  * @return A <i>boolean</i> which is <i>true</i> if this language is the default one.
+	  */
+	 public boolean isDefault() {
+		  return default_language;
+	 }
+	 /** Method to set the value of default.
+	  * @param value The new value of default as a <i>boolean</i>.
+	  */
+	 public void setDefault(boolean value) {
+		  this.default_language = default_language;
+	 }
+	 /** Method to display the language code.
+	  * @return A <strong>String</strong> representing the language code.
+	  */
+	 public String toString() {
+		  return name;
+	 }
+}
+
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/LanguageManager.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/LanguageManager.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/LanguageManager.java	(revision 13666)
@@ -0,0 +1,722 @@
+/**
+ *#########################################################################
+ *
+ * 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:      08/05/02
+ * Revised:      17/11/02 - Commented
+ **************************************************************************************/
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import javax.swing.BorderFactory;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.DefaultListModel;
+import javax.swing.ListModel;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.Language;
+/** 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 DefaultListModel {
+	/** A reference to the collection design manager. */
+	 private CollectionDesignManager manager = null;
+	 /** The visual controls for this manager. */
+	 private Control controls = null;
+	 /** A reference to the Gatherer. */
+	 private Gatherer gatherer = null;
+	 /** A reference to this class as a model, for the inner controls class. */
+	 private ListModel 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;
+	 /** Constructor.
+	  * @param gatherer A reference to the <strong>Gatherer</strong>.
+	  * @param manager A reference to the <strong>CollectionDesignManager</strong>.
+	  */
+	 public LanguageManager(Gatherer gatherer, CollectionDesignManager manager) {
+		  super();
+		  this.gatherer = gatherer;
+		  this.known_languages = new LinkedHashMap();
+		  this.manager = manager;
+		  this.model = this;
+		  loadLanguages();
+	 }
+	 /** 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
+	  */
+	 public void addLanguage(Language language) {
+		  if(!contains(language)) {
+				// Add alphabetically.
+				for(int index = 0; index < size(); index++) {
+					 Language sibling = (Language) get(index);
+					 int position = language.compareTo(sibling);
+					 // Sibling is before language.
+					 if(position > 0) {
+						  // Carry on.
+					 }
+					 // Language is equal to, or before sibling. Insert it.
+					 else if(position == 0 || position < 0) {
+						  add(index, language);
+						  gatherer.c_man.configurationChanged();
+						  return;
+					 }
+				}
+				// If we got this far, we haven't inserted language, and we are out of model so.
+				addElement(language);
+				gatherer.c_man.configurationChanged();
+		  }
+	 }
+	 /** Method to retrieve the control for this manager.
+	  * @return A <strong>JPanel</strong> containing the controls.
+	  */
+	 public JPanel getControls() {
+		  if(controls == null) {
+				controls = new Control();
+		  }
+		  return controls;
+	 }
+	 /** Method to retrieve the default language code.
+	  * @return A <strong>Language</strong> containing a two letter code.
+	  */
+	 public Language getDefaultLanguage() {
+		  // If no default is set...
+		  if(default_language == null) {
+				// And we have other assigned languages, use the first one of them.
+				if(size() >= 1) {
+					 default_language = (Language) get(0);
+				}
+				// And we have nothing else, use English.
+				else {
+					 default_language = getLanguage("en", false);
+					 // Remember to add it.
+					 addLanguage(default_language);
+				}
+		  }
+		  return default_language;
+	 }
+	 /** Method to retrieve a certain language object by its code.
+	  * @param code The two letter code of a language, as a <strong>String</strong>.
+	  * @param assigned_only If <i>true</i> only those languages currently having indexes built for them are checked, otherwise the known languages buffer is checked.
+	  * @return The <strong>Language</strong> that matches the given code, or <i>null</i> if no such language exists.
+	  */
+	 public Language getLanguage(String code, boolean assigned_only) {
+		  if(assigned_only) {
+				for(int i = 0; i < size(); i++) {
+					 Language pos = (Language)get(i);
+					 ///ystem.err.println("Comparing " + pos.getCode() + " and " + code);
+					 if(pos.getCode().equals(code)) {
+						  return pos;
+					 }
+				}
+		  }
+		  else {
+				if(known_languages.containsKey(code)) {
+					 return new Language((Language)known_languages.get(code));
+				}
+		  }
+		  return null;
+	 }
+	 /** Method to return a list of the known language codes.
+	  * @return An <strong>ArrayList</strong> containing a series of alphabetically sorted two letter codes.
+	  */
+	 public ArrayList getLanguageCodes() {
+		  ArrayList result = new ArrayList();
+		  Iterator key_iter = known_languages.keySet().iterator();
+		  while(key_iter.hasNext()) {
+				result.add(known_languages.get(key_iter.next()));
+		  }
+		  //for(Enumeration keys = known_languages.keys(); keys.hasMoreElements(); ) {
+		  //	result.add(known_languages.get(keys.nextElement()));
+		  //}
+		  //Collections.sort(result);
+		  return result;
+	 }
+	/** Mark the current set of controls, if any, as obsolete and deallocate them. If further need of the controls will cause new controls to be created.
+	* @see org.greenstone.gatherer.cdm.IndexManager.Control
+	*/
+	 public void invalidateControls() {
+		  if(controls != null) {
+				controls.destroy();
+		  }
+		  controls = null;
+	 }
+
+	 /** Determine if the given language is the current default language.
+	  * @param language The <strong>Language</strong> to test.
+	  * @return <i>true</i> if the language is the default one, <i>false</i> otherwise.
+	  */
+	 public boolean isDefaultLanguage(Language language) {
+		  return (language.equals(default_language));
+	 }
+	 /** This method attempts to parse a language command from the given string. If such a command is parsed, it is immediately added to the list of languages.
+	  * @param command The <strong>String</strong> containing a possible language command.
+	  * @return A <i>boolean</i> which is <i>true</i> if a command was parsed, <i>false</i> otherwise.
+	  * @see org.greenstone.gatherer.cdm.Language
+	  */
+	 public boolean parse(String command) {
+		  String command_lc = command.toLowerCase();
+		  if(command_lc.startsWith("languages")) {
+				StringTokenizer tokenizer = new StringTokenizer(command);
+				tokenizer.nextToken();
+				while(tokenizer.hasMoreTokens()) {
+					 String code = tokenizer.nextToken();
+					 if(known_languages.containsKey(code)) {
+						  Language language = (Language)known_languages.get(code);
+						  addElement(new Language(language));
+					 }
+					 else {
+						  addElement(new Language(code, code, false));
+					 }
+				}
+				return true;
+		  }
+		  if(command_lc.startsWith("defaultlanguage")) {
+				StringTokenizer tokenizer = new StringTokenizer(command);
+				tokenizer.nextToken();
+				if(tokenizer.hasMoreTokens()) {
+					 String code = tokenizer.nextToken();
+					 Language language = getLanguage(code, true);
+					 if(language == null) {
+						  language = new Language(code, (String)known_languages.get(code), true);
+						  addElement(language);
+					 }
+					 else {
+						  language.setDefault(true);
+					 }
+					 setDefault(language);
+				}
+				return true;
+		  }
+		  return false;
+	 }
+	 /** Method to cause the list appearance to update if the selection changes. */
+	 public void refreshAppearance() {
+		  fireContentsChanged(this, 0, size());
+	 }
+	 /** 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
+	  */
+	 public void removeLanguage(Language language) {
+		  removeElement(language);
+		  if(default_language != null && default_language.equals(language)) {
+				default_language = null;
+		  }
+		  gatherer.c_man.configurationChanged();
+	 }
+	 /** 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) {
+		  // Unset existing.
+		  Language old = null;
+		  if(default_language != null) {
+				old = default_language;
+				default_language.setDefault(false);
+				default_language = null;
+		  }
+		  // Now set the new if its not null.
+		  if(language != null) {
+				default_language = language;
+				default_language.setDefault(true);
+		  }
+		  // Now cause the model to refresh any lists that are listening.
+		  int start = 0;
+		  int end = size() - 1;
+		  if(default_language != null && old != null) {
+				int index_default = indexOf(default_language);
+				int index_old = indexOf(old);
+				if(index_default < index_old) {
+					 start = index_default;
+					 end = index_old;
+				}
+				else {
+					 start = index_old;
+					 end = index_default;
+				}
+		  }
+		  else if(default_language != null) {
+				start = end = indexOf(default_language);
+		  }
+		  else {
+				start = end = indexOf(old);
+		  }
+		  fireContentsChanged(this, 0, size());
+		  gatherer.c_man.configurationChanged();
+	 }
+	 /** Method to translate this object into a block of commands as you you expect to find in the collection configuration file.
+	  * @return A <strong>String</string> containing a series of commands.
+	  */
+	 public String toString() {
+		  StringBuffer text = new StringBuffer();
+		  if(size() > 1) {
+				text.append("languages ");
+				for(int i = 0; i < size(); i++) {
+					 Language language = (Language) get(i);
+					 text.append(language.getCode());
+					 if(i < size() - 1) {
+						  text.append(" ");
+					 }
+					 else {
+						  text.append("\n");
+					 }
+				}
+				// Only bother with default language if there is more than one language.
+				if(default_language != null) {
+					 text.append("defaultlanguage ");
+					 text.append(default_language.getCode());
+					 text.append("\n");
+				}
+				text.append("\n");
+		  }
+		  return text.toString();
+	 }
+	 /** 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 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.
+	  */
+	 private 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. Note that argument numbers greater than or equal to 32 are automatically mapped to the formatting String named Farg<I>n</I>.
+	  * @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.
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.Dictionary
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf('.') == -1) {
+				key = "CDM.LanguageManager." + key;
+		  }
+		  return gatherer.dictionary.get(key, args);
+	 }
+	 /** This method loads a series of code->language mappings into known_languages, by reading from the 'languages.dat' file, which is essentially a verbatim copy of the ISO 639 Standard.
+	 * @see org.greenstone.gatherer.cdm.Language
+	  */
+	 private void loadLanguages() {
+		  try {
+				File in_file = new File("languages.dat");
+				FileReader in_reader = new FileReader(in_file);
+				BufferedReader in = new BufferedReader(in_reader);
+				String entry = null;
+				while((entry = in.readLine()) != null) {
+					 if(!entry.startsWith("#")) {
+						  StringTokenizer tokenizer = new StringTokenizer(entry);
+						  String name = tokenizer.nextToken();
+						  String code = tokenizer.nextToken().toLowerCase();
+						  Language language = new Language(code, name, false);
+						  known_languages.put(code, language);
+					 }
+				}
+				in.close();
+		  }
+		  catch (Exception error) {
+				error.printStackTrace();
+		  }
+	 }
+
+	 /** This class represents the visual component of the Language Manager. */
+	 private class Control
+		  extends JPanel {
+		  /** The button to add a new language support. */
+		  private JButton add = null;
+		  /** The button to clear the current default language. */
+		  private JButton clear_default = null;
+		  /** The button to remove a supported language. */
+		  private JButton remove = null;
+		  /** The button to set the current language as the default one. */
+		  private JButton set_default = null;
+		  /** A button to active the translation manager prompt. */
+		  private JButton translate = null;
+		  /** A combobox listing the available supported languages. */
+		  private JComboBox selector = null;
+		  /** The label denoting the default language. */
+		  private JLabel default_language_label = null;
+		  /** The label denoting the language selector. */
+		  private JLabel selector_label = null;
+		  /** The title label of this control view. */
+		  private JLabel title = null;
+		  /** A list of currently supported languages. */
+		  private JList list = null;
+		  /** The pane in which the control buttons are placed. */
+		  private JPanel button_pane = null;
+		  /** The pane onto which all other panes are placed. */
+		  private JPanel central_pane = null;
+		  /** The pane to the left containing editing controls. */
+		  private JPanel control_pane = null;
+		  /** A panel used to correctly layout the default language box. */
+		  private JPanel default_language_pane = null;
+		  /** The display pane contains the title and instruction controls. */
+		  private JPanel display_pane = null;
+		  /** The pane which holds everything the display pane doesn't! */
+		  private JPanel lower_pane = null;
+		  /** The pane containing the selector combobox. */
+		  private JPanel selector_pane = null;
+		  /** A text area displaying inline instructions. */
+		  private JTextArea instructions = null;
+		  /** A description of the language currently selected. */
+		  private JTextArea description = null;
+		  /** The text field showing the currently name of the default language. Non-editable. */
+		  private JTextField default_language_value = null;
+		  /** Constructor.
+			* @see org.greenstone.gatherer.cdm.LanguageManager.Control.AddListener
+			* @see org.greenstone.gatherer.cdm.LanguageManager.Control.ClearDefaultListener
+			* @see org.greenstone.gatherer.cdm.LanguageManager.Control.ListListener
+			* @see org.greenstone.gatherer.cdm.LanguageManager.Control.RemoveListener
+			* @see org.greenstone.gatherer.cdm.LanguageManager.Control.SelectorListener
+			* @see org.greenstone.gatherer.cdm.LanguageManager.Control.SetDefaultListener
+			* @see org.greenstone.gatherer.cdm.LanguageManager.Control.TranslateListener
+			*/
+		  public Control() {
+				super();
+				// Creation.
+				title = new JLabel(get("Title"));
+				title.setHorizontalAlignment(JLabel.CENTER);
+				title.setOpaque(true);
+
+				central_pane = new JPanel();
+
+				control_pane = new JPanel();
+
+				instructions = new JTextArea(get("Instructions"));
+				instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				instructions.setEditable(false);
+				instructions.setLineWrap(true);
+				instructions.setWrapStyleWord(true);
+
+				selector_pane = new JPanel();
+
+				selector_label = new JLabel(get("Selector"));
+				selector = new JComboBox(getLanguageCodes().toArray());
+
+				display_pane = new JPanel();
+
+				list = new JList(model);
+				list.setCellRenderer(new ListRenderer());
+
+				default_language_pane = new JPanel();
+
+				default_language_label = new JLabel(get("Default_Language"));
+				default_language_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+				if(default_language == null) {
+					 default_language_value = new JTextField();
+				}
+				else {
+					 default_language_value = new JTextField(default_language.toString());
+				}
+				default_language_value.setBackground(Color.white);
+				default_language_value.setEditable(false);
+
+				button_pane = new JPanel();
+
+				add = new JButton(get("Add"));
+				add.setMnemonic(KeyEvent.VK_A);
+				if(selector.getSelectedItem() != null) {
+					 add.setEnabled(true);
+				}
+				else {
+					 add.setEnabled(false);
+				}
+
+				remove = new JButton(get("Remove"));
+				remove.setMnemonic(KeyEvent.VK_R);
+				remove.setEnabled(false);
+
+				clear_default = new JButton(get("Clear_Default"));
+				clear_default.setMnemonic(KeyEvent.VK_C);
+				clear_default.setEnabled(false);
+
+				set_default = new JButton(get("Set_Default"));
+				set_default.setMnemonic(KeyEvent.VK_S);
+				set_default.setEnabled(false);
+
+				lower_pane = new JPanel();
+				translate = new JButton(get("Translate"));
+				translate.setMnemonic(KeyEvent.VK_T);
+
+				// Set up and connect listeners.
+				add.addActionListener(new AddListener());
+				clear_default.addActionListener(new ClearDefaultListener());
+				remove.addActionListener(new RemoveListener());
+				selector.addActionListener(new SelectorListener());
+				set_default.addActionListener(new SetDefaultListener());
+				translate.addActionListener(new TranslateListener());
+				list.addListSelectionListener(new ListListener());
+				// Layout components.
+				selector_pane.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
+				selector_pane.setLayout(new BorderLayout());
+				selector_pane.add(selector_label, BorderLayout.WEST);
+				selector_pane.add(selector, BorderLayout.CENTER);
+
+				instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
+
+				control_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+				control_pane.setLayout(new BorderLayout());
+				control_pane.add(new JScrollPane(instructions), BorderLayout.CENTER);
+				control_pane.add(selector_pane, BorderLayout.SOUTH);
+
+				default_language_pane.setBorder
+					 (BorderFactory.createCompoundBorder
+					  (BorderFactory.createCompoundBorder
+						(BorderFactory.createEmptyBorder(5,5,5,5),
+						 BorderFactory.createRaisedBevelBorder()),
+						BorderFactory.createEmptyBorder(2,2,2,2)));
+				default_language_pane.setLayout(new BorderLayout());
+				default_language_pane.add(default_language_label, BorderLayout.WEST);
+				default_language_pane.add(default_language_value, BorderLayout.CENTER);
+
+				display_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,5));
+				display_pane.setLayout(new BorderLayout());
+				display_pane.add(new JScrollPane(list), BorderLayout.CENTER);
+				display_pane.add(default_language_pane, BorderLayout.SOUTH);
+
+				central_pane.setLayout(new GridLayout(1,2));
+				central_pane.add(control_pane);
+				central_pane.add(display_pane);
+
+				button_pane.setLayout(new GridLayout(2,2));
+				button_pane.add(add);
+				button_pane.add(remove);
+				button_pane.add(clear_default);
+				button_pane.add(set_default);
+
+				lower_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
+				lower_pane = new JPanel(new BorderLayout());
+				lower_pane.add(button_pane, BorderLayout.NORTH);
+				lower_pane.add(translate, BorderLayout.CENTER);
+
+				setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+				setLayout(new BorderLayout());
+				add(title, BorderLayout.NORTH);
+				add(central_pane, BorderLayout.CENTER);
+				add(lower_pane, BorderLayout.SOUTH);
+		  }
+		  /** Destructor.
+			*/
+		  public void destroy() {
+		  }
+		  /** We override the updateUI method so that we can ensure we are scrolled to the top of the instructions box first.
+			*/
+		  public void updateUI() {
+				if(instructions != null) {
+					 instructions.setCaretPosition(0);
+				}
+				super.updateUI();
+		  }
+		  /** 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 <strong>ActionEvent</strong>.
+				* @see org.greenstone.gatherer.cdm.Language
+				*/
+				public void actionPerformed(ActionEvent event) {
+					 Language language = (Language)selector.getSelectedItem();
+					 if(language != null) {
+						  addLanguage(new Language(language));
+					 }
+				}
+		  }
+		  /** Listens for actions apon the 'clear default' button in the LanguageManager controls, and if detected calls the setDefault method of the manager with <i>null</i>. */
+		  private class ClearDefaultListener
+				implements ActionListener {
+				/** Clear the default index.
+				* @param event An <strong>ActionEvent</strong>.
+				*/
+				public void actionPerformed(ActionEvent event) {
+					 setDefault(null);
+					 clear_default.setEnabled(false);
+					 default_language_value.setText("");
+				}
+		  }
+		  /** 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) {
+					 if(!list.isSelectionEmpty()) {
+						  removeLanguage((Language)list.getSelectedValue());
+						  if(default_language == null) {
+								clear_default.setEnabled(false);
+								default_language_value.setText("");
+						  }
+					 }
+				}
+		  }
+		  /** Listens for selections wihtin the combobox on the LanguageManager controls, and if a change is detected enables, or disables, controls appropriately. */
+		  private class SelectorListener
+				implements ActionListener {
+				/** Enable or disable controls depeding on selection.
+				* @param event An <strong>ActionEvent</strong>.
+				*/
+				public void actionPerformed(ActionEvent event) {
+					 if(selector.getSelectedItem() != null) {
+						  add.setEnabled(true);
+						  //description.setText((String)known_languages.get(code));
+					 }
+					 else {
+						  add.setEnabled(false);
+						  //description.setText("");
+					 }
+				}
+		  }
+		  /** 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) {
+					 if(!list.isSelectionEmpty()) {
+						  setDefault((Language)list.getSelectedValue());
+						  clear_default.setEnabled(true);
+						  default_language_value.setText(default_language.toString());
+					 }
+				}
+		  }
+		  /** Listens for actions apon the 'translate' button in the LanguageManager controls, and if detected creates a new <strong>TranslationManager</strong> to allow the user to tranlate. */
+		  private class TranslateListener
+				implements ActionListener {
+				/** Create a new translation manager, but remember to clean up after it disposes.
+				* @param event An <strong>ActionEvent</strong>.
+				* @see org.greenstone.gatherer.cdm.TranslationManager
+				*/
+				public void actionPerformed(ActionEvent event) {
+					 TranslationManager tm = new TranslationManager(gatherer, manager);
+					 tm.destroy();
+				}
+		  }
+		  /** Listens for selections within the list on the LanguageManager controls, and if a change is detected enables, or disables, controls appropriately. */
+		  private class ListListener
+				implements ListSelectionListener {
+				/** Enable or disable controls depending on the current list selection.
+				* @param event A <strong>ListSelectionEvent</strong>.
+				*/
+				public void valueChanged(ListSelectionEvent event) {
+					 if(list.isSelectionEmpty()) {
+						  remove.setEnabled(false);
+						  set_default.setEnabled(false);
+					 }
+					 else {
+						  remove.setEnabled(true);
+						  set_default.setEnabled(true);
+					 }
+					 refreshAppearance();
+				}
+		  }
+		  /** Our list cel renderer which renders the default cell just a little different. */
+		  private class ListRenderer
+				extends DefaultListCellRenderer {
+				/** Method to produce the component used to display an entry in the list.
+				 * @param list The <strong>JList</strong> the component will be placed in.
+				 * @param value A value to be displayed for this component, as a <strong>Object</strong>.
+				 * @param index The position in the list it will occupy as an <i>int</i>.
+				 * @param isSelected Whether the user has currently selected this component, as a <i>boolean</i>.
+				 * @param cellHasFocus Whether the component currently has focus, again as a <i>boolean</i>.
+				 * @return A <strong>Component</strong> to be used as the entry in the list.
+				 * @see org.greenstone.gatherer.cdm.Language
+				 */
+				public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+					 Component component = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+					 Language language = (Language) value;
+					 if(language.isDefault() && !isSelected) {
+						  component.setBackground(Gatherer.config.getColor("coloring.workspace_selection_background", false));
+					 }
+					 if(component instanceof JLabel) {
+						  ((JLabel)component).setOpaque(true);
+					 }
+					 return component;
+				}
+		  }
+	 }
+}
+
+
+
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/MetadataSetManager.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/MetadataSetManager.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/MetadataSetManager.java	(revision 13666)
@@ -0,0 +1,382 @@
+/**
+ *#########################################################################
+ *
+ * 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:      16/05/02
+ * Revised:      28/05/02
+ *               17/11/02 - Commented
+ **************************************************************************************/
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.Rectangle;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Vector;
+import javax.swing.BorderFactory;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.ListModel;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.ElementWrapper;
+import org.greenstone.gatherer.msm.MetadataSet;
+import org.greenstone.gatherer.msm.MSMEvent;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.greenstone.gatherer.msm.MSMListener;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+/** Unlike its namesake in the msm package, this class really only knows how to produce a simple visual representation of the currently imported metadata sets. It is also read-only, so should be fairly straight forward.
+* @author John Thompson, Greenstone Digital Library, University of Waikato
+* @version 2.3
+* @see org.greenstone.gatherer.msm.MetadataSetManager
+*/
+public class MetadataSetManager
+	 extends DynamicListModel
+	 implements MSMListener {
+	 /** The visual contols used to review the metadata sets. */
+	 private Control controls = null;
+	 /** A reference to the Gatherer. */
+	 private Gatherer gatherer = null;
+	 /** A reference to ourselves so our inner classes can refer to us. */
+	 private DynamicListModel model = null;
+	 /** Constructor.
+	  * @param gatherer A reference to the <strong>Gatherer</strong>.
+	  * @see org.greenstone.gatherer.collection.CollectionManager
+	  * @see org.greenstone.gatherer.msm.MetadataSetManager
+	  */
+	 public MetadataSetManager(Gatherer gatherer) {
+		  this.gatherer = gatherer;
+		  this.model = this;
+		  Gatherer.c_man.getCollection().msm.addMSMListener(this);
+		  loadMetadataSets();
+	 }
+	 /** Destructor. Remove any references of this class from persistant objects.
+		* @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.CollectionManager
+	  * @see org.greenstone.gatherer.msm.MetadataSetManager
+	  */
+	 public void destroy() {
+		  gatherer.c_man.msm.removeMSMListener(this);
+	 }
+	 /** Called when an element is changed within a set in the MSM, prompting us to refresh our list of elements being shown.
+	  * @param event A <strong>MSMEvent</strong> which encapsulates relevant data about the change.
+		* @see org.greenstone.gatherer.cdm.MetadataSetManager.Control
+	  */
+	 public void elementChanged(MSMEvent event) {
+		  // Get the controls to refresh element list.
+		  if(controls != null) {
+				controls.refreshElementList();
+		  }
+	 }
+	 /** A method for retrieve the controls for this manager.
+	  * @see org.greenstone.gatherer.Dictionary
+	  * @see org.greenstone.gatherer.gui.Coloring
+	  * @see org.greenstone.gatherer.msm.MetadataSetManager
+	  */
+	 public Control getControls() {
+		  if(controls == null) {
+				controls = new Control();
+		  }
+		  return controls;
+	 }
+	 /** A method to invalidate the current set of controls, as they become obselete.
+		* @see org.greenstone.gatherer.cdm.MetadataSetManager.Control
+	  */
+	 public void invalidateControls() {
+		  if(controls != null) {
+				controls.destroy();
+		  }
+		  controls = null;
+	 }
+	 /** Called when a metadata value has undergone significant change.
+	  * @param event A <strong>MSMEvent</strong> which encapsulates relevant data about the change.
+	  */
+	 public void metadataChanged(MSMEvent event) {
+		  // Couldn't care less.
+	 }
+	 /** Called when a set is added or removed from the MSM.
+	  * @param event A <strong>MSMEvent</strong> which encapsulates relevant data about the change.
+	  */
+	 public void setChanged(MSMEvent event) {
+		  // Reload model.
+		  clear();
+		  loadMetadataSets();
+	 }
+	/** Select the selected element, given its name, and return the bounds of the selection. Used during search and replace.
+	* @param element The elements fully qualified name as a <strong>String</strong>.
+	* @return The bounds of the selection as a <strong>Rectangle</strong>.
+	* @see org.greenstone.gatherer.cdm.MetadataSetManager.Control
+	*/
+	 public Rectangle setSelectedElement(String element) {
+		  if(controls != null) {
+				return controls.setSelectedElement(element);
+		  }
+		  return null;
+	 }
+	 /** Prints out the contents of this manager, as they would appear in the collection configuration file.
+	  * @return A <strong>String</strong> containing a block of commands.
+	  * @see org.greenstone.gatherer.cdm.MetadataSetManager.SetWrapper
+	  */
+	 public String toString() {
+		  String text = "";
+		  for(int i = 0; i < size(); i++) {
+				SetWrapper set = (SetWrapper)get(i);
+				text = text + set.toString() + "\n";
+		  }
+		  text = text + "\n";
+		  return text;
+	 }
+	 /** Called when a significant change has occured to a value tree for a certain element, however we take no further action.
+	  * @param event A <strong>MSMEvent</strong> containing information relevant to the event.
+	  */
+	 public void valueChanged(MSMEvent event) {
+	 }
+	 /** Method to retrieve a phrase from the dictionary based on a key.
+	  * @param key A <strong>String</strong> used to find the correct phrase.
+	  * @param args A <strong>String[]</strong> of arguments used in formatting and filling out the phrase.
+	  * @return A <strong>String</strong> containing the correct phrase with the correct formatting.
+	  */
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+	 /** Method to retrieve a phrase from the dictionary based on a key.
+	  * @param key A <strong>String</strong> used to find the correct phrase.
+	  * @return A <strong>String</strong> containing the correct phrase with the correct formatting.
+	  * @see org.greenstone.gatherer.Dictionary
+	  * @see org.greenstone.gatherer.Gatherer
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf(".") == -1) {
+				key = "CDM.MetadataSetManager." + key;
+		  }
+		  return gatherer.dictionary.get(key, args);
+	 }
+	 /** Retrieves the current list of loaded metadata sets, and builds a list model around them.
+	 	* @see org.greenstone.gatherer.Gatherer
+	 	* @see org.greenstone.gatherer.cdm.MetadataSetManager.SetWrapper
+	 	* @see org.greenstone.gatherer.collection.CollectionManager
+	 	* @see org.greenstone.gatherer.msm.MetadataSet
+	 	* @see org.greenstone.gatherer.msm.MetadataSetManager
+	  */
+	 private void loadMetadataSets() {
+		  // We initialize the set_model with wrapped metadata sets. Note that when we call getSets() we also end up adding ourselves as a listener to the metadata set manager.
+		  Vector sets = gatherer.c_man.getCollection().msm.getSets();
+		  for(int i = 0; i < sets.size(); i++) {
+				addElement(new SetWrapper((MetadataSet)sets.get(i)));
+		  }
+	 }
+	 /** This class creates and lays-out the various controls for reviewing the metadata sets, and their commands as they would appear in the collection configuration file. */
+	 private class Control
+		  extends JPanel {
+		  /** The label denoting the element list. */
+		  private JLabel element_label = null;
+		  /** The label denoting the set list. */
+		  private JLabel set_label = null;
+		  /** The title of these controls. */
+		  private JLabel title = null;
+		  /** The list of elements for the choosen set. */
+		  private JList element_list = null;
+		  /** The list of sets in this collection. */
+		  private JList set_list = null;
+		  /** The panel onto which all other panels will be placed. */
+		  private JPanel central_pane = null;
+		  /** The panel onto which the element list will be placed. */
+		  private JPanel element_pane = null;
+		  /** The panel containing the title and instructions. */
+		  private JPanel header_pane = null;
+		  /** The panel containing the set list. */
+		  private JPanel set_pane = null;
+		  /** The text area of inline instructions. */
+		  private JTextArea instructions = null;
+		  /** The element model for the currently selected set. */
+		  private Vector element_model = null;
+		  /* Constructor.
+		  * @see org.greenstone.gatherer.Coloring;
+		  * @see org.greenstone.gatherer.Dictionary
+		  * @see org.greenstone.gatherer.cdm.MetadataSetManager.ListListener
+		  * @see org.greenstone.gatherer.msm.MetadataSetManager
+		  */
+		  public Control() {
+				// Create visual components
+				central_pane = new JPanel();
+				element_label = new JLabel(get("Elements"));
+				element_label.setHorizontalAlignment(JLabel.CENTER);
+				element_label.setOpaque(true);
+				element_list = new JList();
+				element_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+				element_pane = new JPanel();
+				header_pane = new JPanel();
+				instructions = new JTextArea(get("Instructions"));
+				instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				instructions.setEditable(false);
+				instructions.setLineWrap(true);
+				instructions.setRows(5);
+				instructions.setWrapStyleWord(true);
+				set_label = new JLabel(get("Sets"));
+				set_label.setHorizontalAlignment(JLabel.CENTER);
+				set_label.setOpaque(true);
+				set_list = new JList(model);
+				set_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+				set_pane = new JPanel();
+				title = new JLabel(get("Title"));
+				title.setHorizontalAlignment(JLabel.CENTER);
+				title.setOpaque(true);
+				// Add listeners
+				set_list.addListSelectionListener(new ListListener());
+				// Layout
+				instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
+
+				header_pane.setLayout(new BorderLayout());
+				header_pane.add(title, BorderLayout.NORTH);
+				header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER);
+
+				set_pane.setLayout(new BorderLayout());
+				set_pane.add(set_label, BorderLayout.NORTH);
+				set_pane.add(new JScrollPane(set_list), BorderLayout.CENTER);
+
+				element_pane.setLayout(new BorderLayout());
+				element_pane.add(element_label, BorderLayout.NORTH);
+				element_pane.add(new JScrollPane(element_list), BorderLayout.CENTER);
+
+				central_pane.setLayout(new GridLayout(2,1));
+				central_pane.add(set_pane);
+				central_pane.add(element_pane);
+
+				setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+				setLayout(new BorderLayout());
+				add(header_pane, BorderLayout.NORTH);
+				add(central_pane, BorderLayout.CENTER);
+		  }
+		  /** Destructor.
+		  */
+		  public void destroy() {
+		  }
+		  /** Update the element list. */
+		  public void refreshElementList() {
+				element_list.updateUI();
+		  }
+		/** Select the selected element, given its name, and return the bounds of the selection. Used during search and replace.
+		* @param element The elements fully qualified name as a <strong>String</strong>.
+		* @return The bounds of the selection as a <strong>Rectangle</strong>.
+		* @see org.greenstone.gatherer.cdm.MetadataSetManager.Control
+		* @see org.greenstone.gatherer.cdm.MetadataSetManager.Control.ElementWrapper
+		*/
+		  public Rectangle setSelectedElement(String element) {
+				Rectangle bounds = null;
+				// Parse off namespace
+				String namespace = element.substring(0, element.indexOf("."));
+				// Force the set list to show the correct entry.
+				ListModel s_model = set_list.getModel();
+				for(int i = 0; i < s_model.getSize(); i++) {
+					 SetWrapper sw = (SetWrapper) s_model.getElementAt(i);
+					 if(sw.getSet().getNamespace().equals(namespace)) {
+						  set_list.setSelectedValue(sw, true);
+					 }
+				}
+				// Force the element list to show that name.
+				ListModel e_model = element_list.getModel();
+				for(int i = 0; i < e_model.getSize(); i++) {
+					 ElementWrapper ew = (ElementWrapper) e_model.getElementAt(i);
+					 if(ew.name().equals(element)) {
+						  element_list.setSelectedValue(ew, true);
+						  bounds = element_list.getCellBounds(i, i);
+					 }
+				}
+				// Return the bounds of the selected row.
+				return bounds;
+		  }
+		  /** Overriden to ensure the instruction area is scrolled to top.
+		  */
+		  public void updateUI() {
+				if(instructions != null) {
+					 instructions.setCaretPosition(0);
+				}
+				super.updateUI();
+		  }
+
+		  private class ListListener
+				implements ListSelectionListener {
+				public void valueChanged(ListSelectionEvent event) {
+					 if(!set_list.isSelectionEmpty()) {
+						  MetadataSet set = ((SetWrapper)set_list.getSelectedValue()).getSet();
+						  NodeList elements = set.getElements();
+						  element_model = new Vector();
+						  for(int i = 0; i < elements.getLength(); i++) {
+								element_model.add(new ElementWrapper(elements.item(i)));
+						  }
+						  Collections.sort(element_model);
+						  element_list.setListData(element_model);
+					 }
+				}
+		  }
+	 }
+	 /** Provides a convience wrapper around a metadata set, that allows it to appear in the <strong>JList</strong> the same way it would in the collection configuration file. */
+	 private class SetWrapper {
+		  private MetadataSet set = null;
+		  public SetWrapper(MetadataSet set) {
+				this.set = set;
+		  }
+		  public MetadataSet getSet() {
+				return set;
+		  }
+		  public String toString() {
+				String namespace = set.getNamespace();
+				// Watch out for the greenstone set, with its namespace of ""
+				if(namespace == null || namespace.length() == 0) {
+					 namespace = "greenstone";
+				}
+				return "metadataset " + namespace + " \"" + set.getFile().getName() + "\"";
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/ParsingProgress.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/ParsingProgress.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/ParsingProgress.java	(revision 13666)
@@ -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.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.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Toolkit;
+import javax.swing.BorderFactory;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+/** 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(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 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);
+		  show();
+	 }
+	 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/start/gli/src/org/greenstone/gatherer/cdm/PlugIn.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/PlugIn.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/PlugIn.java	(revision 13666)
@@ -0,0 +1,229 @@
+/**
+ *#########################################################################
+ *
+ * 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:        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>
+ * First Coded:  01/05/02
+ * @author John Thompson, Greenstone Digital Libraries
+ * @version 2.1
+ */
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import org.greenstone.gatherer.cdm.Argument;
+import org.greenstone.gatherer.cdm.ArgumentContainer;
+/** 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. */
+// ####################################################################################
+// Optimization                          Saving
+// ####################################################################################
+// Vector -> ArrayList                   + Memory, + Processor (pos. - Processor)
+// ####################################################################################
+public class PlugIn 
+	 extends ArrayList 
+	 implements ArgumentContainer, Comparable, Serializable {
+	 /** A reference to the plugin that this one inherits from. */
+	 private PlugIn super_plugin = null;
+	 /** A string of custom arguments to pass to the plugin. */
+	 private String custom = null;
+	 /** A description of this plugin. */
+	 private String desc = null;
+	 /** The name of the plugin as it would appear in the collect.cfg file. */
+	 private String name = null;
+	 /** Default Constructor.
+	  */
+	 public PlugIn() {
+		  super();
+	 }
+	 /** Constructor.
+	  * @param name The name of this plugin as a <strong>String</strong>.
+	  * @param desc A description of this plugin as a <strong>String</strong>.
+	  * @param super_plugin The super class of this plugin, as a <strong>PlugIn</strong>.
+	  */
+	 public PlugIn(String name, String desc, PlugIn super_plugin) {
+		  super();
+		  this.desc = desc;
+		  this.name = name;
+		  this.super_plugin = super_plugin;
+	 }
+	 /** Method to add an argument to this plugin. Only adds the argument if it isn't already present. 
+	  * @param argument The <strong>Argument</strong> to add.
+	  */
+	 public void addArgument(Argument argument) {
+		  if(!contains(argument)) {
+				add(argument);
+				argument.setOwner(name);
+		  }
+	 }
+	 /** Method to compare two plugins for ordering.
+	  * @param object The plugin we are comparing to, as an <strong>Object</strong>.
+	  * @return An <i>int</i> specifying the plugin order, using values as set out in <strong>String</strong>.
+	  * @see java.lang.String#compareTo
+	  */
+	 public int compareTo(Object object) {
+		  if(object != null && object instanceof PlugIn) {
+				PlugIn plugin = (PlugIn) object;
+				return name.compareTo(plugin.getName());
+		  }
+		  return -1;
+	 }
+	 /** This method produces a deep copy of this plugin. Note that this also creates a new copy of each of the super classes of plugins as well. This is the way it should be, as each assigned plugin may have different values for the higher plugins (such as BasPlug).
+	  * @return A newly created <strong>PlugIn</strong> with the same details and <strong>Argument</strong>s as this one.
+	  */
+	 public PlugIn copy() {
+		  PlugIn copy = null;
+		  if(super_plugin == null) {
+				copy = new PlugIn(name, desc, null);
+		  }
+		  else {
+				copy = new PlugIn(name, desc, super_plugin.copy());
+		  }
+		  for(int i = 0; i < size(); i++) {
+				copy.addArgument(((Argument)get(i)).copy());
+		  }
+		  return copy;
+	 }
+	 /** Method to determine if two plugins are equal.
+	  * @param object The plugin to test against, as an <strong>Object</strong>.
+	  * @return <i>true</i> if the plugin names match, <i>false</i> otherwise.
+	  */
+	 public boolean equals(Object object) {
+		  if(object != null && compareTo(object) == 0) {
+				return true;
+		  }
+		  return false;
+	 }
+	 /** 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();
+		  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 all of the arguments available to a plugin, including both specific and general ones.
+	  * @return A <strong>Hashtable</strong> of arguments, with <name> -> <argument> entries.
+	  */
+	 public ArrayList getArguments() {
+		  ArrayList all_arguments = new ArrayList(this);
+		  Collections.sort(all_arguments);
+		  if(super_plugin != null) {
+				ArrayList super_arguments = super_plugin.getArguments();
+				for(int i = 0; i < super_arguments.size(); i++) {
+					 Object argument = super_arguments.get(i);
+					 if(!all_arguments.contains(argument)) {
+						  all_arguments.add(argument);
+					 }
+				}
+		  }
+		  return all_arguments;
+	 }
+	 /** Method to retrieve a plugins custom argument information.
+	  * @return The custom arguments as a <strong>String</strong>.
+	  */
+	 public String getCustom() {
+		  return custom;
+	 }
+	 /** Method to retrieve a plugins name.
+	  * @return A <strong>String</strong> containing the plugins name.
+	  */
+	 public String getName() {
+		  return name;
+	 }
+	 public void setCustom(String custom) {
+		  this.custom = custom;
+	 }
+	 /** Method to set the value of desc. 
+	  * @param desc The new value of desc as a <strong>String</strong>.
+	  */
+	 public void setDesc(String desc) {
+		  this.desc = desc;
+	 }
+	 /** 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_plugin.
+	  * @param super_plugin The new value of super_plugin as a <strong>PlugIn</strong>, or <i>null</i> if this class has no inheritance. 
+	  */
+	 public void setSuper(PlugIn super_plugin) {
+		  this.super_plugin = super_plugin;
+	 }
+	 /** Method to print out this plugin as it would appear as a command within the collection configuration file.
+	  * @return A <strong>String</strong> containing a single plugin command.
+	  */
+	 public String toString() {
+		  String text = "plugin " + name + " ";
+		  ArrayList arguments = getArguments();
+		  for(int i = 0; i < arguments.size(); i++) {
+				Argument argument = (Argument)arguments.get(i);
+				if(argument.isAssigned()) {
+					 text = text + argument.toString();
+					 if(i < arguments.size() - 1) {
+						  text = text + " ";
+					 }
+				}
+		  }
+		  // Now print custom arguments if any.
+		  if(custom != null) {
+				text = text + " " + custom;
+		  } 
+		  return text;
+	 }		  
+}
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/PlugInManager.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/PlugInManager.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/PlugInManager.java	(revision 13666)
@@ -0,0 +1,984 @@
+/**
+ *#########################################################################
+ *
+ * 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:        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>
+ * First Coded:  01/05/02
+ * @author John Thompson, Greenstone Digital Libraries
+ * @version 2.1
+ */
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.StringReader;
+import java.util.Collections;
+import java.util.Vector;
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.ComboBoxModel;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JScrollPane;
+import javax.swing.JSeparator;
+import javax.swing.JTextArea;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.plaf.basic.BasicArrowButton;
+import org.apache.xerces.parsers.DOMParser;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.Argument;
+import org.greenstone.gatherer.cdm.ArgumentConfiguration;
+import org.greenstone.gatherer.cdm.CommandTokenizer;
+import org.greenstone.gatherer.cdm.DynamicListModel;
+import org.greenstone.gatherer.cdm.PlugIn;
+import org.greenstone.gatherer.util.Utility;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.xml.sax.InputSource;
+/** This class is resposible for maintaining a list of known plug-ins, and importing new plugins using the parser. */
+public class PlugInManager {
+	 /** A reference to the main manager for this module. */
+	 private CollectionDesignManager manager = null;
+	 /** The controls for editing the contents of this manager. */
+	 private Control controls = null;
+	 /** A list of assigned plugins. */
+	 private DynamicListModel assigned = null;
+	 /** A list of those plugins that have not yet been assigned. Begins as a copy of reserve. */
+	 private DynamicListModel available = null;
+	 /** A list of known, but currently unassigned, plug-ins. */
+	 private DynamicListModel reserve = null;
+	 /** A reference to the Gatherer. */
+	 private Gatherer gatherer = null;
+	 /** The current index of the separator. */
+	 private JPanel separator = null;
+	 /** The default size for a label. */
+	 static final private Dimension LABEL_SIZE = new Dimension(140, 20);
+	 /** Constructor.
+	  */
+	 public PlugInManager(Gatherer gatherer, CollectionDesignManager manager) {
+		  this.assigned = new DynamicListModel();
+		  this.gatherer = gatherer;
+		  this.manager = manager;
+		  this.separator = getSeparator();
+		  // Add the movement separator
+		  assigned.addElement(separator);
+		  loadPlugIns();
+		  savePlugIns();
+	 }
+	 /** Method to add a new plugin to reserve.
+	  * @param plugin The new <strong>PlugIn</strong>.
+	  */
+	 public void addPlugIn(PlugIn plugin) {
+		  if(!reserve.contains(plugin)) {
+				reserve.addElement(plugin);
+				available.addElement(plugin);
+		  }
+	 }
+	 /** Method to assign a plugin.
+	  * @param plugin The reserve <strong>PlugIn</strong> to assign.
+	  */
+	 public void assignPlugIn(PlugIn plugin) {
+		  if(!assigned.contains(plugin)) {
+				if(plugin.getName().equals("RecPlug") || plugin.getName().equals("ArcPlug")) {
+					 assigned.addElement(plugin); // Adds after separator
+				}
+				else {
+					 int index = assigned.indexOf(separator);
+					 assigned.add(index, plugin);
+				}
+				// Remove from available
+				available.removeElement(plugin);
+				gatherer.c_man.configurationChanged();
+		  }
+	 }
+	 /** Method to retrieve the control for this manager.
+	  * @return A <strong>JPanel</strong> containing the controls.
+	  */
+	 public JPanel getControls() {
+		  if(controls == null) {
+				controls = new Control();
+		  }
+		  return controls;
+	 }
+	 /** Method to retrieve the named plugin.
+	  * @param name The name of the desired plugin as a <strong>String</strong>.
+	  * @return The requested <strong>PlugIn</strong> or <i>null</i> if no such plugin exists.
+	  */
+	 public PlugIn getPlugIn(String name) {
+		  for(int i = 0; i < reserve.size(); i++) {
+				Object object = reserve.get(i);
+				if(object instanceof PlugIn) {
+					 PlugIn plugin = (PlugIn) object;
+					 if(plugin.getName().equals(name)) {
+						  return plugin;
+					 }
+				}
+		  }
+		  // No success.
+		  return null;
+	 }
+	 /** Method to invalidate controls after a significant change in the system state.
+	  */
+	 public void invalidateControls() {
+		  if(controls != null) {
+				controls.destroy();
+		  }
+		  controls = null;
+	 }
+	 /** Method to load the details of a single plug-in.
+	  * @param plugin The plugin <strong>File</strong> you wish to load.
+	  */
+	 public void loadPlugIn(File plugin) {
+		  Document document = null;
+		  // Run pluginfo on this plugin, and then send the results for parsing.
+		  try {
+				String args[] = null;
+				if(Utility.isWindows()) {
+					 args = new String[4];
+					 if(gatherer.config.perl_path != null) {
+						  args[0] = gatherer.config.perl_path + "Perl.exe";
+					 }
+					 else {
+						  args[0] = "Perl.exe";
+					 }
+					 args[1] = gatherer.config.gsdl_path + "bin" + File.separator + "script" + File.separator + "pluginfo.pl";
+					 args[2] = "-xml";
+					 args[3] = getPlugInName(plugin);
+				}
+				else {
+					 args = new String[3];
+					 args[0] = "pluginfo.pl";
+					 args[1] = "-xml";
+					 args[2] = getPlugInName(plugin);
+				}
+				for(int i = 0; i < args.length; i++) {
+				    ///ystem.out.print(args[i] + " ");
+				}
+				///ystem.out.print("\n");
+				// Create the process.
+				Runtime runtime = Runtime.getRuntime();
+				Process process = runtime.exec(args);
+				//InputStream input_stream = process.getErrorStream();
+				BufferedReader error_in = new BufferedReader(new InputStreamReader(process.getErrorStream()));
+				String line = "";
+				StringBuffer xml = new StringBuffer("");
+				while((line = error_in.readLine()) != null) {
+				    xml.append(line);
+				    xml.append("\n");
+				}
+				line = null;
+				error_in = null;
+				///ystem.out.println("\n");
+				// Then read the xml from the piped input stream.
+				InputSource source = new InputSource(new StringReader(xml.toString()));
+				DOMParser parser = new DOMParser();
+				parser.parse(source);
+				document = parser.getDocument();
+		  }
+		  catch (Exception error) {
+				error.printStackTrace();
+		  }
+		  if(document != null) {
+				parse(document.getDocumentElement());
+		  }
+	 }
+	 /** Method to move a plugin higher in the list order.
+	  * @param plugin The <strong>PlugIn</strong> you want to move.
+	  * @param direction <i>true</i> to move the plugin up, <i>false</i> to move it down.
+	  * @param all <i>true</i> to move to move all the way, <i>false</i> for a single step.
+	  */
+	 public void movePlugIn(PlugIn plugin, boolean direction, boolean all) {
+		  // Can't ever move RecPlug or ArcPlug.
+		  if(plugin.getName().equals("ArcPlug") || plugin.getName().equals("RecPlug")) {
+				JOptionPane.showMessageDialog(manager.gui, get("CDM.Move.Fixed"), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
+				return;
+		  }
+		  if(all) {
+				if(direction) {
+					 assigned.removeElement(plugin);
+					 assigned.add(0, plugin);
+					 gatherer.c_man.configurationChanged();
+				}
+				else {
+					 assigned.removeElement(plugin);
+					 int index = assigned.size() - 1;
+					 boolean found = false;
+					 while(!found) {
+						  Object temp = assigned.get(index);
+						  if(temp instanceof PlugIn) {
+								PlugIn current = (PlugIn) temp;
+								if(current.getName().equals("ArcPlug") || current.getName().equals("RecPlug")) {
+									 index--;
+								}
+								else {
+									 found = true;
+								}
+						  }
+						  else {
+								found = true;
+						  }
+					 }
+					 assigned.add(index, plugin);
+					 gatherer.c_man.configurationChanged();
+				}
+		  }
+		  else {
+				// Try to move the plugin one step in the desired direction.
+				int index = assigned.indexOf(plugin);
+				///ystem.err.println("Index of " + plugin + " = " + index);
+				if(direction) {
+					 index--;
+					 if(index < 0) {
+						  String args[] = new String[1];
+						  args[0] = plugin.getName();
+						  JOptionPane.showMessageDialog(manager.gui, get("CDM.Move.At_Top", args), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
+						  return;
+					 }
+					 assigned.removeElement(plugin);
+					 assigned.add(index, plugin);
+					 gatherer.c_man.configurationChanged(); 
+				}
+				else {
+					 index++;
+					 Object object = assigned.get(index);
+					 if(index == assigned.size()) {
+						  String args[] = new String[1];
+						  args[0] = plugin.getName();
+						  JOptionPane.showMessageDialog(manager.gui, get("CDM.Move.At_Bottom", args), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
+						  // Still not going to move RecPlug or ArcPlug.
+						  return;
+					 }
+					 else if(!(object instanceof PlugIn) || ((PlugIn)object).getName().equals("ArcPlug") || ((PlugIn)object).getName().equals("RecPlug")) {
+						  String args[] = new String[1];
+						  args[0] = plugin.getName();
+						  JOptionPane.showMessageDialog(manager.gui, get("CDM.Move.Cannot", args), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
+						  // Still not going to move RecPlug or ArcPlug.
+						  return;
+					 }
+					 assigned.removeElement(plugin);
+					 assigned.add(index, plugin);
+					 gatherer.c_man.configurationChanged();
+				}
+		  }
+	 }
+
+	 /** This method attempts to parse a plugin command from a command string taken from the collection configuration file. This process is quite complex as not only must the correct plugin be matched by also all of the parameters given must be legal. If such a command is found, the plugin is immediately assigned.
+	  * @param command The coomand <strong>String</strong> that may include plugin information.
+	  * @return <i>true</i> if a plugin command was parsed, <i>false</i> otherwise.
+	  */
+	 public boolean parse(String command) {
+		  String command_lc = command.toLowerCase();
+		  if(command_lc.startsWith("plugin")) {
+				CommandTokenizer tokenizer = new CommandTokenizer(command);
+				if(tokenizer.countTokens() >= 2) {
+					 tokenizer.nextToken(); // Throw away 'plugin'
+					 String name = tokenizer.nextToken();
+					 // Try to locate the plugin with this name.
+					 PlugIn plugin = getPlugIn(name);
+					 // And if successful start to parse the arguments.
+					 if(plugin != null) {
+						  // Take a copy.
+						  plugin = plugin.copy();
+						  String key = null;
+						  while(tokenizer.hasMoreTokens()) {
+								if(key == null) {
+									 key = tokenizer.nextToken();
+								}
+								// Try to retrieve a matching argument.
+								Argument argument = plugin.getArgument(key);
+								if(argument != null) {
+									 // Set as assigned.
+									 argument.setAssigned(true);
+									 // And if the argument is of a parameter type, parse a parameter.
+									 if(argument.getType() != Argument.FLAG && tokenizer.hasMoreTokens()) {
+										  argument.setValue(tokenizer.nextToken());
+									 }
+									 key = null;
+								}
+								// Argument cannot be matched.
+								else {
+									 String cur_key = key;
+									 String value = tokenizer.nextToken();
+									 if(value.startsWith("-")) {
+										  key = value;
+										  value = null;
+									 }
+									 else {
+										  key = null;
+									 }
+									 String custom = plugin.getCustom();
+									 if(custom == null) {
+										  if(value == null) {
+												plugin.setCustom(cur_key);
+										  }
+										  else {
+												plugin.setCustom(cur_key + " " + value);
+										  }
+									 }
+									 else {
+										  if(value == null) {
+												plugin.setCustom(custom + " " + cur_key);
+										  }
+										  else {
+												plugin.setCustom(custom + " " + cur_key + " " + value);
+										  }
+									 }
+								}
+						  }
+						  // Slight tweak. If the plugin is the RecPlug we want to set use_metadata_files by default.
+						  if(plugin.getName().equalsIgnoreCase("RecPlug")) {
+								Argument argument = plugin.getArgument("-use_metadata_files");
+								if(argument != null) {
+									 argument.setAssigned(true);
+								}
+						  }
+						  // Second tweak. If the plugin is the HTMLPlug we want to modify the block expression so our backup files are ignored.
+						  if(plugin.getName().equalsIgnoreCase("HTMLPlug")) {
+								Argument argument = plugin.getArgument("-block_exp");
+								if(argument != null) {
+									 argument.setValue(argument.getDefaultValue() + "|(~$)");
+								}
+						  }
+						  // Add the plugin to our reserve
+						  assignPlugIn(plugin);
+						  return true;
+					 }
+					 else {
+						  //ystem.err.println("Unknown plugin");
+					 }
+				}
+		  }
+		  return false;
+	 }
+	 /** This method removes an assigned plugin. I was tempted to call it unassign, by remove is more consistant. Note that there is no way to remove a plugin from the reserve.
+	  * @param plugin The <strong>PlugIn</strong> to remove.
+	  */
+	 public void removePlugIn(PlugIn plugin) {
+		  assigned.removeElement(plugin);
+		  available.addElement(plugin);
+		  gatherer.c_man.configurationChanged();
+	 }
+	 /** Method to cache the current contents of reserve (known plugins) to file.
+	  */
+	 public void savePlugIns() {
+		  try {
+				FileOutputStream file = new FileOutputStream(Utility.BASE_DIR + "plugins.dat");
+				ObjectOutputStream out = new ObjectOutputStream(file);
+				out.writeObject(reserve);
+				out.close();
+		  }
+		  catch (Exception error) {
+		  }
+	 }
+	 /** Method used to determine the number of plugins that have been assigned.
+	  * @return An <i>int</i> which is the number of plugins.
+	  */
+	 public int size() {
+		  return assigned.size();
+	 }
+	 /** Method to print out a block of plugin commands, much like you'd find in a collection configuration file.
+	  * @return A <strong>String</strong> containing a series of plugin commands separated by new lines.
+	  */
+	 public String toString() {
+		  String text = "";
+		  for(int i = 0; i < assigned.size(); i++) {
+				Object object = assigned.get(i);
+				if(object instanceof PlugIn) {
+					 PlugIn plugin = (PlugIn) object;
+					 text = text + plugin.toString() + "\n";
+				}
+		  }
+		  text = text + "\n";
+		  return text;
+	 }
+	 /* Retrieve a phrase from the dictionary based on a certain key.
+	  * @param key The search <strong>String</strong>.
+	  * @return The matching phrase from the Dictionary.
+	  */
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+	 /* Retrieve a phrase from the dictionary based on a certain key and arguments.
+	  * @param key The search <strong>String</strong>.
+	  * @param args A <strong>String[]</strong> of arguments used to complete and format the choosen phrase.
+	  * @return The matching phrase from the Dictionary.
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf(".") == -1) {
+				key = "CDM.PlugInManager." + key;
+		  }
+		  return gatherer.dictionary.get(key, args);
+	 }	 
+	 /** Method to extract just the plugins name from a file object.
+	  * @param plugin The <strong>File</strong> which references a certain plugin.
+	  * @return A <strong>String</strong> containing just the plugins name, without extension.
+	  */
+	 private String getPlugInName(File plugin) {
+		  String name = plugin.getName();
+		  if(name.indexOf(".") != -1) {
+				name = name.substring(0, name.indexOf("."));
+		  }
+		  return name;
+	 }
+	 /** Method to retrieve the CData value from a node. Requires a search for the #text node.
+	  * @param node The <strong>Node</strong> whose value we wish to find.
+	  * @return The value of node as a <strong>String</strong>, or <i>null</i> if no value exists.
+	  */
+	 private String getValue(Node node) {
+		  if(node.hasChildNodes()) {
+				Node text = node.getFirstChild();
+				//ystem.err.println("Value of " + node.getNodeName() + " = " + text.getNodeValue());
+				return text.getNodeValue();
+		  }
+		  return node.getNodeValue();
+	 }
+	 /** Method to initially load information from the standard plug-ins within the gsdl Perl library.
+	  */
+	 private void loadPlugIns() {
+		  // Attempt to restore the cached file.
+		  try {
+				FileInputStream file = new FileInputStream(Utility.BASE_DIR + "plugins.dat");
+				ObjectInputStream input = new ObjectInputStream(file);
+				reserve = (DynamicListModel) input.readObject();
+				available = reserve.shallowCopy();
+		  }
+		  catch (Exception error) {
+		  }
+		  if(reserve == null) {
+				available = new DynamicListModel();
+				reserve = new DynamicListModel();
+				reserve.setAutoOrder(true);
+				// Retrieve the gsdl home directory...
+				String directory = gatherer.config.gsdl_path;
+				directory = directory + "perllib" + File.separator + "plugins" + File.separator;
+				loadPlugIns(new File(directory));
+		  }
+	 }
+	 /** Method to load plug-in information from a specified directory. Of course no plug-ins may be found at this location.
+	  * @param directory A <strong>File</strong> indicating the directory to be scanned for plug-ins.
+	  */
+	 private void loadPlugIns(File directory) {
+		  File files[] = directory.listFiles();
+		  if(files != null) {
+				// Create a progress indicator.
+				ParsingProgress progress = new ParsingProgress(get("CDM.PlugInManager.Parsing.Title"), get("CDM.PlugInManager.Parsing.Message"), files.length);
+				for(int i = 0; i < files.length; i++) {
+					 // We only want to check Perl Modules.
+					 if(files[i].getName().endsWith(".pm")) {
+						  loadPlugIn(files[i]);
+					 }
+					 progress.inc();
+				}
+				progress.dispose();
+		  }
+	 }
+
+	 private PlugIn parse(Node root) {
+		  PlugIn plugin = new PlugIn();
+		  String node_name = null;
+		  for(Node node = root.getFirstChild(); node != null; 
+				node = node.getNextSibling()) {
+				node_name = node.getNodeName();
+				if(node_name.equals("Name")) {
+					 String name = getValue(node);
+					 // We can save ourselves some processing time if a plugin with this name already exists in our manager. If so retrieve it and return it.
+					 PlugIn existing = getPlugIn(name);
+					 if(existing != null) {
+						  return existing;
+					 }
+					 plugin.setName(name);
+				}
+				else if(node_name.equals("Desc")) {
+					 plugin.setDesc(getValue(node));
+				}
+				// Parse the multitude of arguments.
+				else if(node_name.equals("Arguments")) {
+					 for(Node arg = node.getFirstChild(); arg != null; arg = arg.getNextSibling()) {
+						  node_name = arg.getNodeName();
+						  // An option.
+						  if(node_name.equals("Option")) {
+								Argument argument = new Argument();
+								// If its an option we parse the multitude of details an options might have.
+								for(Node det = arg.getFirstChild(); det != null; det = det.getNextSibling()) {
+									 node_name = det.getNodeName();
+									 if(node_name.equals("Name")) {
+										  argument.setName(getValue(det));
+									 }
+									 else if(node_name.equals("Desc")) {
+										  argument.setDesc(getValue(det));
+									 }
+									 else if(node_name.equals("Type")) {
+										  argument.setType(getValue(det));
+									 }
+									 else if(node_name.equals("Default")) {
+										  argument.setDefault(getValue(det));
+									 }
+									 else if(node_name.equals("List")) {
+										  // Two final loops are required to parse lists.
+										  for(Node value = det.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 = getValue(subvalue);
+														  }
+														  else if(node_name.equals("Desc")) {
+																desc = getValue(subvalue);
+														  }
+													 }
+													 if(key != null) {
+														  argument.addOption(key, desc);
+													 }
+												}
+										  }
+									 }
+									 else if(node_name.equals("Required")) {
+										  String v = getValue(det);
+										  if(v != null && v.equals("yes")) {
+												argument.setRequired(true);
+										  }
+									 }
+								}
+								plugin.addArgument(argument);
+						  }
+						  // A super plugin class.
+						  else if(node_name.equals("PlugInfo")) {
+								PlugIn super_plugin = parse(arg);
+								plugin.setSuper(super_plugin);
+						  }
+					 }
+				}
+		  } 
+		  if(plugin.getName() != null) {
+				addPlugIn(plugin);
+				return plugin;
+		  }
+		  return null;
+	 }
+
+	 /** A class which provodes controls for assigned and editing plugins. */
+	 private class Control
+		  extends JPanel {
+		  /** Button for adding plugins. */
+		  private JButton add = null;
+		  /** Button for configuring the selected plugin. */
+		  private JButton configure = null;
+		  /** Buttom to move an assinged plugin as low in the order as possible. */
+		  private JButton move_bottom = null;
+		  /** Button to move an assigned plugin one position lower in the order. */
+		  private JButton move_down = null;
+		  /** Button to move an assigned plugin as high in the order as possible. */
+		  private JButton move_top = null;
+		  /** Button to move an assigned plugin one position higher in the order. */
+		  private JButton move_up = 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 = 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;
+		  /** The title of this view. */
+		  private JLabel title = 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 title label and instructions sit. */
+		  private JPanel header_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;
+		  /** The text area containing instructions on the use of this control. */
+		  private JTextArea instructions = null;
+		  /** Constructor.
+			*/
+		  public Control() {
+				Object plugins[] = reserve.toArray();
+				Vector plugin_model = new Vector();
+				for(int i = 0; i < plugins.length; i++) {
+					 plugin_model.add(((PlugIn)plugins[i]).getName());
+				}
+				Collections.sort(plugin_model);
+				// Create
+				add = new JButton(get("Add"));
+				add.setMnemonic(KeyEvent.VK_A);
+				button_pane = new JPanel();
+				central_pane = new JPanel();
+				configure = new JButton(get("Configure"));
+				configure.setMnemonic(KeyEvent.VK_C);
+				header_pane = new JPanel();
+				instructions = new JTextArea(get("Instructions"));
+				instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				instructions.setEditable(false);
+				instructions.setLineWrap(true);
+				instructions.setRows(5);
+				instructions.setWrapStyleWord(true);
+				move_bottom = new JButton();
+				JLabel move_bottom_label = new JLabel(get("Move_Bottom"));
+				move_bottom_label.setHorizontalAlignment(JLabel.CENTER);
+				move_bottom_label.setPreferredSize(LABEL_SIZE);
+				move_bottom.setLayout(new BorderLayout());
+				move_bottom.add(new JLabel(Utility.getImage("arrow-bottom.gif")), BorderLayout.WEST);
+				move_bottom.add(move_bottom_label, BorderLayout.CENTER);
+				move_bottom.add(new JLabel(Utility.getImage("arrow-bottom.gif")), BorderLayout.EAST);
+				move_bottom.setMnemonic(KeyEvent.VK_B);
+				move_down = new JButton();
+				JLabel move_down_label = new JLabel(get("Move_Down"));
+				move_down_label.setHorizontalAlignment(JLabel.CENTER);
+				move_down_label.setPreferredSize(LABEL_SIZE);
+				move_down.setLayout(new BorderLayout());
+				move_down.add(new JLabel(Utility.getImage("arrow-down.gif")), BorderLayout.WEST);
+				move_down.add(move_down_label, BorderLayout.CENTER);
+				move_down.add(new JLabel(Utility.getImage("arrow-down.gif")), BorderLayout.EAST);
+				move_down.setMnemonic(KeyEvent.VK_D);
+				move_top = new JButton();
+				JLabel move_top_label = new JLabel(get("Move_Top"));
+				move_top_label.setHorizontalAlignment(JLabel.CENTER);
+				move_top_label.setPreferredSize(LABEL_SIZE);
+				move_top.setLayout(new BorderLayout());
+				move_top.add(new JLabel(Utility.getImage("arrow-top.gif")), BorderLayout.WEST);
+				move_top.add(move_top_label, BorderLayout.CENTER);
+				move_top.add(new JLabel(Utility.getImage("arrow-top.gif")), BorderLayout.EAST);
+				move_top.setMnemonic(KeyEvent.VK_T);
+				move_up = new JButton();
+				JLabel move_up_label = new JLabel(get("Move_Up"));
+				move_up_label.setHorizontalAlignment(JLabel.CENTER);
+				move_up_label.setPreferredSize(LABEL_SIZE);
+				move_up.setLayout(new BorderLayout());
+				move_up.add(new JLabel(Utility.getImage("arrow-up.gif")), BorderLayout.WEST);
+				move_up.add(move_up_label, BorderLayout.CENTER);
+				move_up.add(new JLabel(Utility.getImage("arrow-up.gif")), BorderLayout.EAST);
+				move_up.setMnemonic(KeyEvent.VK_U);
+				movement_pane = new JPanel();
+				plugin = new JComboBox(available);
+				//plugin.setEditable(true);
+				plugin.setSelectedIndex(0);
+				plugin_label = new JLabel(get("PlugIn"));
+				plugin_list = new JList(assigned);
+				plugin_list.setCellRenderer(new ListRenderer());
+				plugin_list_label = new JLabel(get("Assigned"));
+				plugin_list_label.setHorizontalAlignment(JLabel.CENTER);
+				plugin_list_label.setOpaque(true);
+				plugin_list_pane = new JPanel();
+				plugin_pane = new JPanel();
+				remove = new JButton(get("Remove"));
+				remove.setMnemonic(KeyEvent.VK_R);
+				title = new JLabel(get("Title"));
+				title.setHorizontalAlignment(JLabel.CENTER);
+				title.setOpaque(true);
+				// Listeners
+				add.addActionListener(new AddListener());
+				configure.addActionListener(new ConfigureListener());
+				MoveListener ml = new MoveListener();
+				move_bottom.addActionListener(ml);
+				move_down.addActionListener(ml);
+				move_top.addActionListener(ml);
+				move_up.addActionListener(ml);
+				remove.addActionListener(new RemoveListener());
+				plugin_list.addMouseListener(new ClickListener());
+				// Layout
+				title.setBorder(BorderFactory.createEmptyBorder(0,0,2,0));
+
+				instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
+
+				header_pane.setLayout(new BorderLayout());
+				header_pane.add(title, BorderLayout.NORTH);
+				header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER);
+
+				plugin_list_label.setBorder(BorderFactory.createEmptyBorder(0,2,0,2));
+
+				movement_pane.setLayout(new GridLayout(4,1));
+				movement_pane.add(move_top);
+				movement_pane.add(move_up);
+				movement_pane.add(move_down);
+				movement_pane.add(move_bottom);
+
+				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);
+				plugin_list_pane.add(movement_pane, BorderLayout.EAST);
+
+				plugin_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+
+				plugin_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+				plugin_pane.setLayout(new GridLayout(1,2));
+				plugin_pane.add(plugin_label);
+				plugin_pane.add(plugin);
+
+				// Scope these mad bordering skillz.
+				JPanel temp = new JPanel(new BorderLayout());
+				temp.setBorder
+					 (BorderFactory.createCompoundBorder
+					  (BorderFactory.createEmptyBorder(5,0,5,0),
+						BorderFactory.createCompoundBorder
+						(BorderFactory.createTitledBorder(get("Controls")),
+						 BorderFactory.createEmptyBorder(2,2,2,2))));
+																	 
+				temp.add(plugin_pane, BorderLayout.NORTH);
+				temp.add(button_pane, BorderLayout.SOUTH);
+
+				central_pane.setLayout(new BorderLayout());
+				central_pane.add(plugin_list_pane, BorderLayout.CENTER);
+				central_pane.add(temp, BorderLayout.SOUTH);
+
+				button_pane.setLayout(new GridLayout(3,1));
+				button_pane.add(add);
+				button_pane.add(configure);
+				button_pane.add(remove);
+
+				setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+				setLayout(new BorderLayout());
+				add(header_pane, BorderLayout.NORTH);
+				add(central_pane, BorderLayout.CENTER);
+				//add(button_pane, BorderLayout.SOUTH);
+		  }
+		  /** Method which acts like a destructor, tidying up references to persistant objects.
+			*/
+		  public void destroy() {
+		  }
+		  /** This method is overridden in some control classes to allow for the updating of collection configuration when the focus is lost to another view. In this case however the updates are asynchronous and so no 'has the configuration changed without the user updating' check is needed.
+			* @return <i>true</i> if this control has focus, <i>false</i> otherwise.
+			*/
+		  public boolean hasFocus() {
+				return super.hasFocus();
+		  }
+		  /** This method is overridden to ensure the instructions are scrolled to top, before the super classes updateUI() is called.
+			*/
+		  public void updateUI() {
+				if(instructions != null) {
+					 instructions.setCaretPosition(0);
+				}
+				super.updateUI();
+		  }
+		  /** This class listens for actions upon the add button in the controls, and if detected calls the <i>assignPlugIn()</i> method.
+			*/
+		  private class AddListener
+				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) {
+					 PlugIn new_plugin = null;
+					 Object object = plugin.getSelectedItem();
+					 if(object instanceof PlugIn) {
+						  PlugIn target = (PlugIn)object;
+						  new_plugin = target.copy();
+					 }
+					 else {
+						  new_plugin = new PlugIn(object.toString(), "", null);
+					 }
+					 object = null;
+					 // Automatically chain to configuration. This ensures required arguments are filled out.
+					 ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, new_plugin);
+					 if(ac.display()) {
+						  assignPlugIn(new_plugin);
+						  plugin_list.setSelectedValue(new_plugin, true);
+					 }
+					 ac = null;
+					 new_plugin = null;
+					 plugin.setSelectedIndex(0);
+				}
+		  }
+		  /** 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()) {
+						  Object object = plugin_list.getSelectedValue();
+						  if(object instanceof PlugIn) {
+								ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, (PlugIn)object);
+								if(ac.display()) {
+									 assigned.refresh();
+								}
+						  }
+					 }
+				}
+		  }
+		  /** 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) {
+					 if(value instanceof JPanel) {
+						  return (JPanel) value;
+					 }
+					 else {
+						  return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+					 }
+				}
+		  }
+		  /** 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()) {
+								Object object = plugin_list.getSelectedValue();
+								if(object instanceof PlugIn) {
+									 ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, (PlugIn)object);
+									 if(ac.display()) {
+										  assigned.refresh();
+									 }
+								}
+						  }
+					 }
+				}
+		  }
+		  /** 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_top) {
+									 movePlugIn(plugin, true, true);
+								}
+								else if(event.getSource() == move_up) {
+									 movePlugIn(plugin, true, false);
+								}
+								else if(event.getSource() == move_down) {
+									 movePlugIn(plugin, false, false);
+								}
+								else {
+									 movePlugIn(plugin, false, true);
+								}
+								plugin_list.setSelectedValue(plugin, true);
+						  }
+					 }
+				}
+		  }
+		  /** 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) {
+					 if(!plugin_list.isSelectionEmpty()) {
+						  Object object = plugin_list.getSelectedValue();
+						  if(object instanceof PlugIn) {
+								removePlugIn((PlugIn)object);
+						  }
+					 }
+				}
+		  }
+	 }
+	 /** Creates a list separator.
+	  * Code courtesy of Farwell, Paul. Contact <a href="mailto:PFarwell@Kronos.com">PFarwell@Kronos.com</a>
+	  */
+	 static 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)));
+		  _sepPanel.add(new JPopupMenu.Separator());
+		  _sepPanel.add(Box.createRigidArea(new Dimension(0, 4)));
+		  return _sepPanel;
+	 }
+}
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/SubIndex.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/SubIndex.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/SubIndex.java	(revision 13666)
@@ -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.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:      17/11/02 - Commented
+ **************************************************************************************/
+import java.util.Collections;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import org.greenstone.gatherer.cdm.Subcollection;
+import org.greenstone.gatherer.cdm.SubcollectionManager;
+/** The <strong>SubIndex</strong> class is essentially a <strong>Vector</strong> with some extra added magic to make it print out properly.
+* @author John Thompson, Greenstone Digital Library, University of Waikato
+* @version 2.1
+*/
+public class SubIndex
+	 extends Vector
+	 implements Comparable {
+	 /** Default Constructor.
+	  */
+	 public SubIndex() {
+		  super();
+	 }
+	 /** Copy Constructor.
+	  * @param original The <strong>Vector</strong> used to initially fill the SubIndex.
+	  */
+	 public SubIndex(Vector original) {
+		  super(original);
+	 }
+	 /** Parsed data Constructor.
+	  * @param raw A <strong>String</strong> containing a comma separated list of subcollection names.
+	  * @param manager A reference to the <strong>SubcollectionManager</strong> via which we retrieve the required Subcollections.
+	  */
+	 public SubIndex(String raw, SubcollectionManager manager) {
+		  super();
+		  StringTokenizer tokenizer = new StringTokenizer(raw, ",");
+		  while(tokenizer.hasMoreTokens()) {
+				String name = tokenizer.nextToken();
+				Subcollection sub = manager.getSubcollection(name);
+				if(sub != null) {
+					 add(sub);
+				}
+		  }
+	 }
+	 /** Method to compare two subindexes.
+	  * @param object The other subindex to compare to, as an <strong>Object</strong>.
+	  * @return An <i>int</i> which is greater than, equal to or less than zero if the this object is before, equal to, or after the target object respectively.
+	  */
+	 public int compareTo(Object object) {
+		  SubIndex index = (SubIndex) object;
+		  return toString().compareTo(index.toString());
+	 }
+	 /** Method to determine if this subindex contains a certain subcollection.
+	  * @param name The name, as a <strong>String</strong>, of the subcollection you are checking for.
+	  * @return A <i>boolean</i> which is <i>true</i> if this index contains the named subcollection, <i>false</i> otherwise.
+	  */
+	 public boolean containsSubcollection(String name) {
+		  for(int i = 0; i < size(); i++) {
+				Subcollection sub = (Subcollection) get(i);
+				if(sub.getName().equals(name)) {
+					 return true;
+				}
+		  }
+		  return false;
+	 }
+	 /** Method to check two subindexes for equality.
+	  * @param object The other subindex to compare to, as an <strong>Object</strong>.
+	  * @return A <i>boolean</i> which is <i>true</i> if the subindexes are equal, <i>false</i> otherwise.
+	  */
+	 public boolean equals(Object object) {
+		  if(compareTo(object) == 0) {
+				return true;
+		  }
+		  return false;
+	 }
+	 /** Method to generate a comma separated list from a subindex vector.
+	  * @return A <strong>String</strong> representing this subindex.
+	  */
+	 public String toString() {
+		  String text = "";
+		  for(int i = 0; i < size(); i++) {
+				Object object = get(i);
+				Subcollection sub = (Subcollection) get(i);
+				text = text + sub.getName();
+				if(i < size() - 1) {
+						  text = text + ",";
+				}
+		  }
+		  return text;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/SubIndexes.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/SubIndexes.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/SubIndexes.java	(revision 13666)
@@ -0,0 +1,78 @@
+/**
+ *#########################################################################
+ *
+ * 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:      17/11/02 - Commented
+ **************************************************************************************/
+import java.util.Vector;
+import javax.swing.DefaultListModel;
+import org.greenstone.gatherer.cdm.SubIndex;
+/** Not to be confused with the SubIndex class, SubIndexes holds a Vector of SubIndex objects.
+* @author John Thompson, Greenstone Digital Library, University of Waikato
+* @version 2.2
+*/
+public class SubIndexes
+	 extends DefaultListModel {
+	 public void changed() {
+		  fireContentsChanged(this, 0, getSize() - 1);
+	 }
+	 /** Method to display the contents of this class as an entry in the collection configuration file. The line contains the key word, then a space separated series of index entries.
+	  * @return A <strong>String</strong> representing this collection of indexes.
+	  */
+	 public String toString() {
+		  String text = "indexsubcollections  ";
+		  for(int i = 0; i < size(); i++) {
+				text = text + ((SubIndex)get(i)).toString();
+				if(i < size() - 1) {
+					 text = text + " ";
+				}
+		  }
+		  text = text + "\n";
+		  return text;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/Subcollection.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/Subcollection.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/Subcollection.java	(revision 13666)
@@ -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.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:      17/11/02 - Commenting
+ **************************************************************************************/
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.w3c.dom.Element;
+/** This class encapsulates one subcollection entry in the collection configuration file.
+* @author John Thompson, Greenstone Digital Library, University of Waikato
+* @version 2.3
+*/
+public class Subcollection
+	 implements Comparable {
+	 /** A <i>boolean</i> which is <i>true</i> if the condition is an include one, <i>false</i> otherwise. */
+	 private boolean include = true;
+	 /** 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 element = null;
+	 /** A String containing a Perl expression which is used as the filter for this subcollection. */
+	 private String exp = 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;
+	 /** Constructor.
+	  * @param name A <strong>String</strong> which is a unique identifier of a subcollection.
+	  * @param pattern A <strong>String</strong> containing the inclusion, the element to filter, a Perl expression which is used as the filter for this subcollection, and a series of argument flags.
+	  */
+	 public Subcollection(String name, String pattern) {
+		  this.name = name;
+		  // Have to do some work on pattern.
+		  // Remove quote marks.
+		  if(pattern.startsWith("\"") || pattern.startsWith("'")) {
+				pattern = pattern.substring(1, pattern.length() - 1);
+		  }
+		  // Test for exclusion
+		  if(pattern.startsWith("!")) {
+				this.include = false;
+				pattern = pattern.substring(1, pattern.length());
+		  }
+		  else {
+				this.include = true;
+		  }
+		  if(pattern.indexOf("/") != -1) {
+				// Now element (which may be Filename)
+				this.element = pattern.substring(0, pattern.indexOf("/"));
+				if(this.element.toLowerCase().equals("filename")) {
+					 this.element = null;
+				}
+				// Extract Perl expression
+				if(pattern.indexOf("/") != pattern.lastIndexOf("/")) {
+					 this.exp = pattern.substring(pattern.indexOf("/") + 1,
+															pattern.lastIndexOf("/"));
+					 this.flags = pattern.substring(pattern.lastIndexOf("/") + 1);
+				}
+				else {
+					 this.exp = pattern.substring(pattern.indexOf("/") + 1);
+				}
+		  }
+		  else {
+				// Hmmm. Well I don't know what this is but it isn't a proper subcollection definition. Can't really 'return null' or something. So I'll just not set include, element, exp and flag expressions.
+		  }
+	 }
+	 /** Constructor.
+	  * @param name A <strong>String</strong> which is a unique identifier of a subcollection.
+	  * @param include A <i>boolean</i> which is <i>true</i> if the condition is an include one, <i>false</i> otherwise.
+	  * @param exp A <strong>String</strong> containing a Perl expression which is used as the filter for this subcollection.
+	  */
+	 public Subcollection(String name, boolean include, String exp, String flags) {
+		  this.element = null;
+		  this.exp = exp;
+		  this.flags = flags;
+		  this.include = include;
+		  this.name = name;
+	 }
+	 /** Constructor.
+	  * @param name A <strong>String</strong> which is a unique identifier of a subcollection.
+	  * @param include A <i>boolean</i> which is <i>true</i> if the condition is an include one, <i>false</i> otherwise.
+	  * @param element 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.
+	  * @param exp A <strong>String</strong> containing a Perl expression which is used as the filter for this subcollection.
+	  * @param flags A <strong>String</strong> of flags to be taken into account when matching the expression.
+	  */
+	 public Subcollection(String name, boolean include, String element, String exp, String flags) {
+		  this.element = element;
+		  this.exp = exp;
+		  this.flags = flags;
+		  this.include = include;
+		  this.name = name;
+	 }
+	 /** Method to compare two subcollections.
+	  * @param object The other subcollection to compare to, as an <strong>Object</strong>.
+	  * @return An <i>int</i> which is greater than, equal to or less than zero if the this object is before, equal to, or after the target object respectively.
+	  */
+	 public int compareTo(Object object) {
+		  Subcollection sub = (Subcollection) object;
+		  return getName().compareTo(sub.getName());
+	 }
+	 /** Method to check two subcollections for equality.
+	  * @param object The other subcollection to compare to, as an <strong>Object</strong>.
+	  * @return A <i>boolean</i> which is <i>true</i> if the subcollections are equal, <i>false</i> otherwise.
+	  */
+	 public boolean equals(Object object) {
+		  if(compareTo(object) == 0) {
+				return true;
+		  }
+		  return false;
+	 }
+	 /** Method to get the value of element.
+	  * @return The value of element as an <strong>String</strong>.
+	  */
+	 public String getElement() {
+		  return element;
+	 }
+	 /** Method to get the value of expression.
+	  * @return The value of exp as a <strong>String</strong>.
+	  */
+	 public String getExpression() {
+		  return exp;
+	 }
+	 /** Method to get the value of flags.
+	  * @return The value of flags as a <strong>String</strong>.
+	  */
+	 public String getFlags() {
+		  return flags;
+	 }
+	 /** Method to get the value of include.
+	  * @param boolean The value of include as a <i>boolean</i>.
+	  */
+	 public boolean getInclude() {
+		  return include;
+	 }
+	 /** Method to get the value of name.
+	  * @param String The value of name as a <strong>String</string>.
+	  */
+	 public String getName() {
+		  return name;
+	 }
+	 /** Method to get the name of the source of the strings used in pattern matching.
+	  * @return A <strong>String</strong> which is either the fully qualified name of a metadata element, or "Filename".
+	  */
+	 public String getSource() {
+		  if(element != null) {
+				return element;
+		  }
+		  return "Filename";
+	 }
+	 /** Method to display the contents of this class as it would appear in the collection configuration file.
+	  * @return A <strong>String</strong> which could be used as a subcollection entry in collect.cfg.
+	  */
+	 public String toString() {
+		  String text = "subcollection        ";
+		  text = text + name + " ";
+		  text = text + "\"";
+		  if(!include) {
+				text = text + "!";
+		  }
+		  if(element != null) {
+				text = text + element;
+		  }
+		  else {
+				text = text + "Filename";
+		  }
+		  text = text + "/";
+		  text = text + exp;
+		  text = text + "/";
+		  if(flags != null) {
+				text = text + flags;
+		  }
+		  text = text + "\"\n";
+		  return text;
+	 }
+
+	 /** Update certain fields of this subcollection.
+	  * @param name A <strong>String</strong> which is a unique identifier of a subcollection.
+	  * @param source 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.
+	  * @param exp A <strong>String</strong> containing a Perl expression which is used as the filter for this subcollection.
+	  * @param include A <i>boolean</i> which is <i>true</i> if the condition is an include one, <i>false</i> otherwise.
+	  * @param flags A <strong>String</strong> of flags to be taken into account when matching the expression.
+		*/
+	 public void update(String name, String source, String exp, boolean include, String flags) {
+		  this.name = name;
+		  this.element = source;
+		  this.exp = exp;
+		  this.include = include;
+		  this.flags = flags;
+	 }
+
+	 /** Method to update the name of a metadata element, if it changes.
+	  * @param old_name The current name of the element as a <strong>String</strong>.
+	  * @param new_name The new name of the element as a <strong>String</strong>.
+	  */
+	 public void updateElement(String old_name, String new_name) {
+		  if(element.equals(old_name)) {
+				element = new_name;
+		  }
+	 }
+}
+
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/SubcollectionManager.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/SubcollectionManager.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/SubcollectionManager.java	(revision 13666)
@@ -0,0 +1,874 @@
+/**
+ *#########################################################################
+ *
+ * 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:      02/05/02
+ * Revised:      17/11/02 - Commented
+ **************************************************************************************/
+import java.awt.BorderLayout;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+import javax.swing.BorderFactory;
+import javax.swing.ButtonGroup;
+import javax.swing.DefaultListModel;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.JToggleButton;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.Subcollection;
+import org.greenstone.gatherer.cdm.SubIndex;
+import org.greenstone.gatherer.cdm.SubIndexes;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.util.ExclusiveListSelectionListener;
+import org.w3c.dom.Element;
+/** This class maintains a list of subcollections within our collection, and also records which of these subcollections we are building indexes for.
+* @author John Thompson, Greenstone Digital Library, University of Waikato
+* @version 2.1
+*/
+public class SubcollectionManager
+	 extends DefaultListModel {
+	 /** The controls used to edit the settings of this manager. */
+	 private Control controls = null;
+	 /** A reference to this class so we can use it as a model in our inner classes. */
+	 private DefaultListModel model = null;
+	 /** The default index for the subcollections. */
+	 private DefaultSubIndex default_index = null;
+	 /** A reference to the Gatherer. */
+	 private Gatherer gatherer = null;
+	 /** A hashtable of subcollections, with mappings from name to subcollection. */
+	 private Hashtable subcollections = null;
+	 /** A vector-type structure of subcollection indexes. */
+	 private SubIndexes subindexes = null;
+	 /** A vector containing all of the subcollection commands that are unresolved, or in other words require that all 'subcollection <name> "<exp>"' to have been previously parsed before we can be certain their references will make sense. */
+	 private ArrayList unresolved = null;
+	 /** Constructor.
+		* @param gatherer A reference to the <Strong>Gatherer</strong>.
+		* @see org.greenstone.gatherer.cdm.SubIndexes
+	  */
+	 public SubcollectionManager(Gatherer gatherer) {
+		  super();
+		  this.gatherer = gatherer;
+		  this.model = this;
+		  this.subcollections = new Hashtable();
+		  this.subindexes = new SubIndexes();
+		  this.unresolved = new ArrayList();
+	 }
+	 /** Method to add a subindex.
+	  * @param subindex A <strong>SubIndex</strong>.
+		* @see org.greenstone.gatherer.Gatherer
+		* @see org.greenstone.gatherer.collection.CollectionManager
+	  */
+	 public void addSubIndex(SubIndex subindex) {
+		  if(!subindexes.contains(subindex)) {
+				subindexes.addElement(subindex);
+				gatherer.c_man.configurationChanged();
+		  }
+	 }
+	 /** Method to add a new subcollection. Adds it to both the underlying list model and the hashtable mapping names to subcollections.
+	  * @param sub The <strong>Subcollection</strong> to add.
+	  * @return A <i>boolean</i> indicating if the addition was successful (<i>true</i>) or not (<i>false</i>).
+		* @see org.greenstone.gatherer.Gatherer
+		* @see org.greenstone.gatherer.collection.CollectionManager
+	  */
+	 public boolean addSubcollection(Subcollection sub) {
+		  if(!contains(sub)) {
+				addElement(sub);
+				subcollections.put(sub.getName(), sub);
+				gatherer.c_man.configurationChanged();
+				return true;
+		  }
+		  return false;
+	 }
+	 /** A method to add a new subcollection, by specifying its name, metadata element if applicable and Perl expression to filter pages into or out of this collection.
+	  * @param name A <>>String</>> which is a unique identifier of a subcollection.
+	  * @param include A <i>boolean</i> indicating whether this is an inclusion filter (<i>true</i>) or an exclusion one (<i>false</i>).
+	  * @param element An <>>Element</>> which is either the metadata whose value should be matched against the given expression, or <i>null</i> if you wish to match against the file name.
+	  * @param exp A <>>String</>> containing a Perl expression which is used as the filter for this subcollection.
+	  * @param flags A <strong>String<strong> listing any special flags to be applied when matching the expression.
+	  * @return A <i>boolean</i> with a value of <i>true</i> if the addition was successful.
+		* @see org.greenstone.gatherer.cdm.Subcollection
+	  */
+	 public boolean addSubcollection(String name, boolean include, String element, String exp, String flags) {
+		  Subcollection sub = null;
+		  if(element != null) {
+				sub = new Subcollection(name, include, element, exp, flags);
+		  }
+		  else {
+				sub = new Subcollection(name, include, exp, flags);
+		  }
+		  return addSubcollection(sub);
+	 }
+	/** Refresh all derived components using this manager as a model.
+	*/
+	 public void changed() {
+		  fireContentsChanged(this, 0, getSize() - 1);
+	 }
+	 /** Method to retrieve the controls for this manager.
+	  * @return A <Strong>Control</strong> object which contains the controls used to edit the subcollection data.
+	  */
+	 public Control getControls() {
+		  if(controls == null) {
+				controls = new Control();
+		  }
+		  return controls;
+	 }
+	 /** Method to retrieve the default index.
+	  * @return A <strong>DefaultSubIndex</strong> object.
+	  */
+	 public DefaultSubIndex getDefaultSubIndex() {
+		  return default_index;
+	 }
+	 /** Method to retrieve a certain subcollection by its name.
+	  * @param name A <strong>String</strong> which is used as the key for finding the matching subcollection.
+	  * @return The requested <strong>Subcollection</strong> or <i>null</i> if no such subcollection exists.
+	  */
+	 public Subcollection getSubcollection(String name) {
+		  return (Subcollection) subcollections.get(name);
+	 }
+	 /** Method to get all of the subindexes set.
+	  * @return A <strong>SubIndexes</strong> object containing all the defined indexes.
+	  */
+	 public SubIndexes getSubIndexes() {
+		  return subindexes;
+	 }
+	 /** Method to get all of the subcollections defined.
+	  * @return A <strong>Vector</strong> of subcollections.
+	  */
+	 public Vector getSubcollections() {
+		  Vector subcollections = new Vector();
+		  for(int i = 0; i < size(); i++) {
+				subcollections.add(get(i));
+		  }
+		  return subcollections;
+	 }
+	/** Mark the current controls, if any, as invalid and deallocate them. Any further use of the controls will requires them being rebuilt.
+	* @see org.greenstone.gatherer.cdm.SubcollectionManager.Control
+	*/
+	public void invalidateControls() {
+		  if(controls != null) {
+				controls.destroy();
+				controls = null;
+		  }
+	 }
+	 /** This method attempts to parse a subcollection related command from the given command string. If such a string is successfully parsed, it is immediately added to the data within this collection.
+	  * @param command The <strong>String</strong> to be parsed.
+	  * @param finished This <i>boolean</i> is usually <i>false</i> when called, unless this parse call is being made -after- the entire collection configuration file has been read in in which case it is <i>true</i>.
+	  * @return A <i>boolean</i> which is <i>true</i> if a command was parsed, <i>false</i> otherwise.
+	  * @see org.greenstone.gatherer.cdm.CommandTokenizer
+	  * @see org.greenstone.gatherer.cdm.DefaultSubIndex
+	  * @see org.greenstone.gatherer.cdm.Subcollection
+	  * @see org.greenstone.gatherer.cdm.SubIndex
+	  */
+	 public boolean parse(String command, boolean finished) {
+		  String temp = command.toLowerCase();
+		  CommandTokenizer tokenizer = new CommandTokenizer(command);
+		  tokenizer.nextToken(); // Throw away head.
+		  if(temp.startsWith("subcollection")) {
+				if(tokenizer.countTokens() >= 2) {
+					 String name = tokenizer.nextToken();
+					 String pattern = tokenizer.nextToken();
+					 addSubcollection(new Subcollection(name, pattern));
+					 return true;
+				}
+		  }
+		  else if(temp.startsWith("indexsubcollections")) {
+				// These entries depend on what subcollections have previously been set, so we cannot safely parse them until after the file is complete.
+				if(!finished) {
+					 unresolved.add(command);
+				}
+				else {
+					 while(tokenizer.hasMoreTokens()) {
+						  addSubIndex(new SubIndex(tokenizer.nextToken(), this));
+					 }
+				}
+				return true;
+		  }
+		  else if(temp.startsWith("defaultsubcollection")) {
+				// These entries depend on what subcollections have previously been set, so we cannot safely parse them until after the file is complete.
+				if(!finished) {
+					 unresolved.add(command);
+				}
+				else {
+					 if(tokenizer.hasMoreTokens()) {
+						  setDefaultSubIndex(new DefaultSubIndex(tokenizer.nextToken(), this));
+					 }
+				}
+				return true;
+		  }
+		  return false;
+	 }
+	 /** Method to remove a certain subindex.
+	  * @param subindex The <strong>SubIndex</strong> you wish to remove.
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.CollectionManager
+	  */
+	 public void removeSubIndex(SubIndex subindex) {
+		  subindexes.removeElement(subindex);
+		  gatherer.c_man.configurationChanged();
+	 }
+	 /** Method to remove all of the subindexes that contain a certain subcollection.
+	  * @param sub The <strong>Subcollection</strong> that you wish to remove.
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.cdm.SubIndex
+	  * @see org.greenstone.gatherer.collection.CollectionManager
+	  */
+	 public void removeSubIndexes(Subcollection sub) {
+		  for(int i = subindexes.size() - 1; i >= 0; i--) {
+				SubIndex subindex = (SubIndex)subindexes.get(i);
+				if(subindex.containsSubcollection(sub.getName())) {
+					 subindexes.removeElement(subindex);
+				}
+		  }
+		  gatherer.c_man.configurationChanged();
+	 }
+	 /** Method to remove the given subcollection.
+	  * @param sub The <strong>Subcollection</strong> you want to remove.
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.CollectionManager
+	  */
+	 public void removeSubcollection(Subcollection sub) {
+		  removeElement(sub);
+		  subcollections.remove(sub);
+		  gatherer.c_man.configurationChanged();
+	 }
+	 /** Method to retry the parsing of commands that were previously unable to be parsed as they referenced subcollections that may not have been instantiated.
+	  */
+	 public void reparseUnresolved() {
+		  for(int i = 0; i < unresolved.size(); i++) {
+				parse((String)unresolved.get(i), true);
+		  }
+		  unresolved.clear();
+	 }
+	 /** Method to set the default subcollection index.
+	  * @param subcollection The <strong>Subcollection</strong> to use as the default index.
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.CollectionManager
+	  */
+	 public void setDefaultSubIndex(DefaultSubIndex subindex) {
+		  this.default_index = subindex;
+		  if(subindex != null) {
+				addSubIndex(subindex.getSubIndex());
+		  }
+		  gatherer.c_man.configurationChanged();
+	 }
+	 /** This method causes the contents of this manager to be converted to a string, which is accomplished by calling <i>toString()</i> on each subcollection, then printing out the contents of the index vector.
+	  * @return A <strong>String</strong> containing a block of configuration commands.
+		* @see org.greenstone.gatherer.cdm.SubIndex
+		* @see org.greenstone.gatherer.cdm.Subcollection
+	  */
+	 public String toString() {
+		  String text = "";
+		  // Retrieve the subcollection names and sort them.
+		  if(subcollections.size() > 0) {
+				Vector names = new Vector(subcollections.keySet());
+				Collections.sort(names);
+				for(int i = 0; i < names.size(); i++) {
+					 Subcollection sub =
+						  (Subcollection) subcollections.get(names.get(i));
+					 text = text + sub.toString();
+				}
+				// Now add a entry, separated by spaces for each subcollection
+				// index.
+				if(subindexes.size() > 0) {
+					 text = text + subindexes.toString();
+				}
+				// Finally add the default subcollection index if necessary.
+				if(default_index != null) {
+					 text = text + default_index.toString();
+				}
+				text = text + "\n";
+		  }
+		  // Otherwise if there were no subcollections, there aren't going to be
+		  // subcollection indexes, nor a default subcollection index are there.
+		  return text;
+	 }
+	 /** Method to retrieve a phrase from the dictionary based on a key.
+	  * @param key A <strong>String</strong> used to find the correct phrase.
+	  * @param args A <strong>String[]</strong> of arguments used in formatting and filling out the phrase.
+	  * @return A <strong>String</strong> containing the correct phrase with the correct formatting.
+	  */
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+	 /** Method to retrieve a phrase from the dictionary based on a key.
+	  * @param key A <strong>String</strong> used to find the correct phrase.
+	  * @return A <strong>String</strong> containing the correct phrase with the correct formatting.
+	  * @see org.greenstone.gatherer.Dictionary
+	  * @see org.greenstone.gatherer.Gatherer
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf(".") == -1) {
+				key = "CDM.SubcollectionManager." + key;
+		  }
+		  return gatherer.dictionary.get(key, args);
+	 }
+	 /** This class creates a JPanel containing serveral more controls used for editing subcollection information. */
+	 private class Control
+		  extends JPanel {
+			/** <i>true</i> if the current selection has changed. */
+		  private boolean changed = false;
+		  /** Button to add a subcollection. */
+		  private JButton add = null;
+		  /** Button to add a subindex. */
+		  private JButton add_index = null;
+		  /** Button to clear the default subindex. */
+		  private JButton clear_default = null;
+		  /** Button to remove a subcollection. */
+		  private JButton remove = null;
+		  /** Button to remove a subindex. */
+		  private JButton remove_index = null;
+		  /** Button to set the default subindex. */
+		  private JButton set_default = null;
+		  /** Button to cause an update of the subcollections. */
+		  private JButton update = null;
+		  /** A combobox allowing you to choose which field the data for matching should be taken from. Includes text body and filename, as well as all assigned metadata elements. */
+		  private JComboBox source = null;
+		  /** The list of assigned subcollections. */
+		  private JList subcollection_list = null;
+		  /** The list of subcollections available for the creation of subindexes. */
+		  private JList subcollection_list_2 = null;
+		  /** The list of assigned subindexes. */
+		  private JList subindexes_list = null;
+		  /** The label denoting the list of subindexes. */
+		  private JLabel subindexes_label = null;
+		  /** The panel containing the subcollection controls. */
+		  private JPanel subcollection_pane = null;
+		  /** The panel containing the subindex controls. */
+		  private JPanel subindex_pane = null;
+		  /** The tabbed pane used to store the subcollection and subindex controls. */
+		  private JTabbedPane tabbed_pane = null;
+		  /** The area used to display inline instructions. */
+		  private JTextArea instructions = null;
+		  /** The field displaying the name of the default subindex. */
+		  private JTextField default_value = null;
+		  /** A field used for specifying flags for the PERL expression matching, such as 'i' for case insensitive. */
+		  private JTextField flags = null;
+		  /** The pattern the source text must match. */
+		  private JTextField match = null;
+		  /** The name of this subcollection. */
+		  private JTextField name = null;
+		  /** When this button is selected the filter matching files are excluded. */
+		  private JToggleButton exclude = null;
+		  /** When this button is selected the filter matching files are included. */
+		  private JToggleButton include = null;
+		  /** The existing subcollection whose details you are reviewing, if any. */
+		  private Subcollection current = null;
+			/** Constructor, creates the outer parts of the view, then calls two methods in turn to create the subcollection controls and subindex controls.
+			*/
+		  public Control() {
+				// Create
+				JPanel border_pane = new JPanel();
+				JPanel header_pane = new JPanel();
+				instructions = new JTextArea(get("Instructions"));
+				instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				instructions.setEditable(false);
+				instructions.setLineWrap(true);
+				instructions.setRows(5);
+				instructions.setWrapStyleWord(true);
+				tabbed_pane = new JTabbedPane();
+				JLabel title = new JLabel(get("Title"));
+				title.setHorizontalAlignment(JLabel.CENTER);
+				createSubcollection();
+				createSubindex();
+				// Add listeners
+				// Layout
+				instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
+				header_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+				header_pane.setLayout(new BorderLayout());
+				header_pane.add(title, BorderLayout.NORTH);
+				header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER);
+				tabbed_pane.addTab(get("Subcollection_Controls"), subcollection_pane);
+				tabbed_pane.addTab(get("Subindex_Controls"), subindex_pane);
+				border_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
+				border_pane.setLayout(new BorderLayout());
+				border_pane.add(tabbed_pane, BorderLayout.CENTER);
+				setLayout(new BorderLayout());
+				add(header_pane, BorderLayout.NORTH);
+				add(border_pane, BorderLayout.CENTER);
+		  }
+			/** Create the subcollection controls.
+			* @see org.greenstone.gatherer.Gatherer
+			* @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.AddListener
+			* @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.ListListener
+			* @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.RemoveListener
+			* @see org.greenstone.gatherer.collection.CollectionManager
+			* @see org.greenstone.gatherer.msm.MetadataSetManager
+			*/
+		  public void createSubcollection() {
+				// Create
+				add = new JButton(get("Add"));
+				add.setMnemonic(KeyEvent.VK_A);
+				JPanel button_pane = new JPanel();
+				JPanel button_pane_1 = new JPanel();
+				JPanel button_pane_3 = new JPanel();
+				exclude = new JToggleButton(get("Exclude"));
+				exclude.setMnemonic(KeyEvent.VK_X);
+				flags = new JTextField();
+				JLabel flags_label = new JLabel(get("Flags"));
+				include = new JToggleButton(get("Include"));
+				include.setMnemonic(KeyEvent.VK_I);
+				JLabel inclusive_label = new JLabel(get("Inclusive"));
+				JPanel inclusive_pane = new JPanel();
+				match = new JTextField();
+				JLabel match_label = new JLabel(get("Match"));
+				name = new JTextField();
+				JLabel name_label = new JLabel(get("Name"));
+				remove = new JButton(get("Remove"));
+				remove.setMnemonic(KeyEvent.VK_R);
+				Vector source_model = gatherer.c_man.msm.getAssignedElements();
+				source_model.add(0, "Filename");
+				source = new JComboBox(source_model);
+				JLabel source_label = new JLabel(get("Source"));
+				subcollection_list = new JList(model);
+				subcollection_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+				subcollection_pane = new JPanel();
+				ButtonGroup bg = new ButtonGroup();
+				bg.add(include);
+				bg.add(exclude);
+				include.setSelected(true);
+				JPanel subcollection_list_pane = new JPanel();
+				JLabel subcollection_list_label = new JLabel(get("Assigned"));
+
+				// Add listeners
+				add.addActionListener(new AddListener());
+				remove.addActionListener(new RemoveListener());
+				subcollection_list.addListSelectionListener(new ListListener());
+
+				// Layout
+				inclusive_pane.setLayout(new GridLayout());
+			   inclusive_pane.add(include);
+				inclusive_pane.add(exclude);
+				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);
+				button_pane_1.add(source_label);
+				button_pane_1.add(source);
+				button_pane_1.add(match_label);
+				button_pane_1.add(match);
+				button_pane_1.add(inclusive_label);
+				button_pane_1.add(inclusive_pane);
+				button_pane_1.add(flags_label);
+				button_pane_1.add(flags);
+				button_pane_3.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+				button_pane_3.setLayout(new GridLayout(1,2));
+				button_pane_3.add(add);
+				button_pane_3.add(remove);
+				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);
+		  }
+			/** Create the subindex controls.
+			 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.AddSubIndexListener
+			 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.ClearDefaultListener
+			 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.ChangeListener
+			 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.RemoveSubIndexListener
+			 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.SetDefaultListener
+			 * @see org.greenstone.gatherer.util.ExclusiveListListener
+			 */
+		  public void createSubindex() {
+				// Creation
+				add_index = new JButton(get("Add_Subindex"));
+				add_index.setMnemonic(KeyEvent.VK_A);
+				JPanel button_pane_2 = new JPanel();
+				clear_default = new JButton(get("Clear_Default_Subindex"));
+				clear_default.setMnemonic(KeyEvent.VK_C);
+				if(default_index == null) {
+					 clear_default.setEnabled(false);
+				}
+				JLabel default_label = new JLabel(get("Default_Subindex"));
+				JPanel default_pane = new JPanel();
+				if(default_index == null) {
+					 default_value = new JTextField();
+				}
+				else {
+					 default_value = new JTextField(default_index.getSubIndex().toString());
+				}
+				JPanel subindex_inner_pane_1 = new JPanel();
+				JPanel subindex_inner_pane_2 = new JPanel();
+				remove_index = new JButton(get("Remove_Subindex"));
+				remove_index.setMnemonic(KeyEvent.VK_R);
+				set_default = new JButton(get("Set_Default_Subindex"));
+				set_default.setMnemonic(KeyEvent.VK_S);
+				JLabel subcollection_label = new JLabel(get("Subcollection"));
+				subcollection_list_2 = new JList(model);
+				JPanel list_2_pane = new JPanel();
+				subindex_pane = new JPanel();
+				JLabel subindexes_label = new JLabel(get("Subindexes"));
+				subindexes_list = new JList(subindexes);
+				subindexes_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+				JPanel subindexes_pane = new JPanel();
+
+				// Add listeners
+				ChangeListener cl = new ChangeListener();
+				ExclusiveListSelectionListener ell = new ExclusiveListSelectionListener();
+				ell.add(subcollection_list_2);
+				ell.add(subindexes_list);
+				add_index.addActionListener(new AddSubIndexListener());
+				clear_default.addActionListener(new ClearDefaultListener());
+				exclude.addActionListener(cl);
+				include.addActionListener(cl);
+				remove_index.addActionListener(new RemoveSubIndexListener());
+				set_default.addActionListener(new SetDefaultListener());
+				source.addActionListener(cl);
+				flags.addKeyListener(cl);
+				match.addKeyListener(cl);
+				name.addKeyListener(cl);
+
+				// Layout
+				list_2_pane.setLayout(new BorderLayout());
+				list_2_pane.add(subcollection_label, BorderLayout.NORTH);
+				list_2_pane.add(new JScrollPane(subcollection_list_2), BorderLayout.CENTER);
+				subindexes_pane.setLayout(new BorderLayout());
+				subindexes_pane.add(subindexes_label, BorderLayout.NORTH);
+				subindexes_pane.add(new JScrollPane(subindexes_list), BorderLayout.CENTER);
+				subindex_inner_pane_2.setLayout(new GridLayout(2,1));
+				subindex_inner_pane_2.add(list_2_pane);
+				subindex_inner_pane_2.add(subindexes_pane);
+				default_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+				default_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createRaisedBevelBorder()), BorderFactory.createEmptyBorder(2,2,2,2)));
+				default_pane.setLayout(new BorderLayout());
+				default_pane.add(default_label, BorderLayout.WEST);
+				default_pane.add(default_value, BorderLayout.CENTER);
+				subindex_inner_pane_1.setLayout(new BorderLayout());
+				subindex_inner_pane_1.add(subindex_inner_pane_2, BorderLayout.CENTER);
+				subindex_inner_pane_1.add(default_pane, BorderLayout.SOUTH);
+				button_pane_2.setLayout(new GridLayout(2,2));
+				button_pane_2.add(add_index);
+				button_pane_2.add(remove_index);
+				button_pane_2.add(clear_default);
+				button_pane_2.add(set_default);
+				subindex_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+				subindex_pane.setLayout(new BorderLayout());
+				subindex_pane.add(subindex_inner_pane_1, BorderLayout.CENTER);
+				subindex_pane.add(button_pane_2, BorderLayout.SOUTH);
+		  }
+		  /** Method to unregister any listeners to avoid memory leaks.
+			*/
+		  public void destroy() {
+		  }
+		  /** We have overriden this method to provide completely different functionality, given that our JPanel will never actually have focus. We call this method in GUI on the view we are about to replace, and this method checks if a change has occured and if so updates the current object.
+			* @return A <i>boolean</i> which is always <i>false</i>.
+			* @see org.greenstone.gatherer.msm.ElementWrapper
+			*/
+		  public boolean hasFocus() {
+				// If we have a current metadata open, and something has changed then save the change.
+				if(changed && current != null) {
+					 String n = name.getText();
+					 String s = null;
+					 Object o = source.getSelectedItem();
+					 if(o instanceof ElementWrapper) {
+						  ElementWrapper e = (ElementWrapper)o;
+						  s = e.toString();
+					 }
+					 String e = match.getText();
+					 String f = flags.getText();
+					 if(n != null && n.length() > 0 && (s == null || s.length() > 0) && e != null && e.length() > 0) {
+						  current.update(n, s, e, include.isSelected(), f);
+						  int index = model.indexOf(current);
+						  changed();
+						  subindexes.changed();
+						  if(default_index != null) {
+								default_value.setText(default_index.getSubIndex().toString());
+						  }
+					 }
+					 changed = false;
+				}
+				return false;
+		  }
+		  /** Overriden to ensure the instructions are scrolled to top.
+		  */
+		  public void updateUI() {
+				if(instructions != null) {
+					 instructions.setCaretPosition(0);
+				}
+				super.updateUI();
+		  }
+		  /** 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 AddListener
+				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
+				 * @see org.greenstone.gatherer.msm.ElementWrapper
+				 */
+				public void actionPerformed(ActionEvent event) {
+					 String n = name.getText();
+					 String s = null;
+					 Object o = source.getSelectedItem();
+					 if(o instanceof ElementWrapper) {
+						  ElementWrapper e = (ElementWrapper)o;
+						  s = e.toString();
+					 }
+					 String e = match.getText();
+					 String f = flags.getText();
+					 if(n != null && n.length() > 0 && (s == null || s.length() > 0) && e != null && e.length() > 0) {
+						  Subcollection sub = new Subcollection(n, include.isSelected(), s, e, f);
+						  addSubcollection(sub);
+					 }
+					 changed = false;
+				}
+		  }
+		  /** Listens for actions apon the 'add subindex' button in the SubcollectionManager controls, and if detected calls the addSubindex method of the manager with a newly created subindex. */
+		  private class AddSubIndexListener
+				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 series of subcollections selected, and if so build an new subindex based apon them.
+				 * @param event An <strong>ActionEvent</strong> containing information about the event.
+				 * @see org.greenstone.gatherer.cdm.SubIndex
+				 */
+				public void actionPerformed(ActionEvent event) {
+					 if(!subcollection_list_2.isSelectionEmpty()) {
+						  Vector selected = new Vector();
+						  Object raw[] = subcollection_list_2.getSelectedValues();
+						  for(int i = 0; i < raw.length; i++) {
+								selected.add(raw[i]);
+						  }
+						  addSubIndex(new SubIndex(selected));
+					 }
+				}
+		  }
+		  /** This class listens for any key entry in a text field, selection change in a combobox or button click, and when detected sets the changed flag to true. Its also convenient to use this class to test if the add button should be active yet. */
+		  public class ChangeListener
+				extends KeyAdapter
+				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 record that somethings changed, then validate the controls.
+				 * @param event An <strong>ActionEvent</strong> containing information about the event.
+				 */
+				public void actionPerformed(ActionEvent event) {
+					 changed = true;
+					 validate();
+				}
+				/** Any inheritor of KeyAdapter can override this method so we can be informed when an key has been type in one of our target controls. In this case we want to record that somethings changed, then validate the controls.
+				 * @param event An <strong>KeyEvent</strong> containing information about the event.
+				 */
+				public void keyPressed(KeyEvent event) {
+					 changed = true;
+					 validate();
+				}
+				/** Method to validate the current editor values, and enable or disable controls based on said values. */
+				private void validate() {
+					 if(changed && name.getText().length() > 0 && match.getText().length() > 0) {
+						  add.setEnabled(true);
+					 }
+					 else {
+						  add.setEnabled(false);
+					 }
+				}
+		  }
+		  /** Listens for actions apon the 'clear default subindex' button in the SubcollectionManager controls, and if detected calls the setDefaultSubIndex() method of the manager with <i>null</i>. */
+		  private class ClearDefaultListener
+				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 clear the default subindex.
+				 * @param event An <strong>ActionEvent</strong> containing information about the event.
+				 */
+				public void actionPerformed(ActionEvent event) {
+					 setDefaultSubIndex(null);
+					 clear_default.setEnabled(false);
+					 default_value.setText("");
+				}
+		  }
+		  /** 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 ListListener
+				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
+				 * @see org.greenstone.gatherer.msm.ElementWrapper
+				 */
+				public void valueChanged(ListSelectionEvent event) {
+					 // If we have a previous collection and the users changed something, but not added, then update subcollection.
+					 if(changed && current != null) {
+						  String n = name.getText();
+						  String s = null;
+						  Object o = source.getSelectedItem();
+						  if(o instanceof ElementWrapper) {
+								ElementWrapper e = (ElementWrapper)o;
+								s = e.toString();
+						  }
+						  String e = match.getText();
+						  String f = flags.getText();
+						  if(n != null && n.length() > 0 && (s == null || s.length() > 0) && e != null && e.length() > 0) {
+								current.update(n, s, e, include.isSelected(), f);
+								int index = model.indexOf(current);
+								changed();
+								subindexes.changed();
+								if(default_index != null) {
+									 default_value.setText(default_index.getSubIndex().toString());
+								}
+						  }
+					 }
+					 // Now load the new entry.
+					 if(!subcollection_list.isSelectionEmpty()) {
+						  current = (Subcollection) subcollection_list.getSelectedValue();
+						  flags.setText(current.getFlags());
+						  include.setSelected(current.getInclude());
+						  exclude.setSelected(!current.getInclude());
+						  match.setText(current.getExpression());
+						  name.setText(current.getName());
+						  String s = current.getSource();
+						  int pos = 0;
+						  Object value = source.getItemAt(pos);
+						  while(value != null) {
+								if(value instanceof ElementWrapper) {
+									 ElementWrapper e = (ElementWrapper) value;
+									 if(e.toString().equals(s)) {
+										  source.setSelectedIndex(pos);
+										  value = null;
+									 }
+									 else {
+										  pos++;
+										  value = source.getItemAt(pos);
+									 }
+								}
+								else if(value.toString().equals(s)) {
+									 source.setSelectedIndex(pos);
+									 value = null;
+								}
+								else {
+									 pos++;
+									 value = source.getItemAt(pos);
+								}
+						  }
+						  // Can't add one thats already there.
+						  add.setEnabled(false);
+						  // You can remove it though...
+						  remove.setEnabled(true);
+					 }
+					 else {
+						  flags.setText("");
+						  include.setSelected(true);
+						  match.setText("");
+						  name.setText("");
+						  source.setSelectedIndex(0);
+						  remove.setEnabled(false);
+					 }
+					 // Have to do this after so we don't get called when nothings actually changed.
+					 changed = 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 RemoveListener
+				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 sub_col = (Subcollection)subcollection_list.getSelectedValue();
+						  removeSubIndexes(sub_col);
+						  removeSubcollection(sub_col);
+					 }
+				}
+		  }
+		  /** Listens for actions apon the 'remove subindex' button in the SubcollectionManager controls, and if detected calls the removeSubIndex method of the manager with the SubIndex selected for removal. */
+		  private class RemoveSubIndexListener
+				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 subindex selected, and if so remove it.
+				 * @param event An <strong>ActionEvent</strong> containing information about the event.
+				 * @see org.greenstone.gatherer.cdm.SubIndex
+				 */
+				public void actionPerformed(ActionEvent event) {
+					 if(!subindexes_list.isSelectionEmpty()) {
+						  removeSubIndex((SubIndex)subindexes_list.getSelectedValue());
+					 }
+				}
+		  }
+		  /** Listens for actions apon the 'set default subindex' button in the SubcollectionManager controls, and if detected calls the setDefaultSubIndex method of the manager with the SubIndex selected for default. */
+		  private class SetDefaultListener
+				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 subindex selected, and if so set it as default.
+				 * @param event An <strong>ActionEvent</strong> containing information about the event.
+				 * @see org.greenstone.gatherer.cdm.DefaultSubIndex
+				 * @see org.greenstone.gatherer.cdm.SubIndex
+				 */
+				public void actionPerformed(ActionEvent event) {
+					 if(!subindexes_list.isSelectionEmpty()) {
+						  setDefaultSubIndex(new DefaultSubIndex((SubIndex)subindexes_list.getSelectedValue()));
+						  clear_default.setEnabled(true);
+						  default_value.setText(default_index.getSubIndex().toString());
+					 }
+				}
+		  }
+	 }
+}
+
+
+
+
+
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/TranslationManager.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/TranslationManager.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/TranslationManager.java	(revision 13666)
@@ -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.
+ *
+ * <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:      22/05/02
+ * Revised:      17/11/02 - Commented
+ **************************************************************************************/
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.GridLayout;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.util.ArrayList;
+import java.util.Collections;
+import javax.swing.BorderFactory;
+import javax.swing.DefaultListModel;
+import javax.swing.ListSelectionModel;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JTextArea;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableColumn;
+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.Language;
+import org.greenstone.gatherer.cdm.LanguageManager;
+/** 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 TranslationManager
+	 extends JDialog {
+	/** A reference to our creator, the CollectionDesignManager. */
+	 private CollectionDesignManager manager = null;
+	/** The currently selected collection metadata. */
+	 private CollectionMeta current = null;
+	/** A listener for selection changes in the feature list. */
+	 private FeatureListener features_listener = null;
+	/** A reference to the Gatherer, for access to the Dictionary and messaging purposes. */
+	 private Gatherer gatherer = null;
+	/** The button used to close the translation dialog. */
+	 private JButton close_button = null;
+	/** A reference to the dialog so that our inner classes can interact with it. */
+	private JDialog dialog = null;
+	/** The label denoting the features list. */
+	private JLabel features_label = null;
+	/** The label denoting the language table. */
+	private JLabel languages_label = null;
+	/** The label denoting the original text area. */
+	private JLabel original_label = null;
+	/** The label denoting the original language field */
+	private JLabel original_language_label = null;
+	/** The label denoting the translated text area. */
+	private JLabel translation_label = null;
+	/** The label denoting the translated language field. */
+	private JLabel translation_language_label = null;
+	/** A list of the various features that have collection metadata associated with them. */
+	private JList features_list = null;
+	/** The base panel. */
+	private JPanel content_pane = null;
+	/** The right panel. */
+	private JPanel control_pane = null;
+	/** The panel the features list is shown in. */
+	private JPanel features_pane = null;
+	/** The panel the languages table is shown in. */
+	private JPanel languages_pane = null;
+	/** The panel the original text is shown in. */
+	private JPanel original_pane = null;
+	/** The panel the original language field is shown in. */
+	private JPanel original_header_pane = null;
+	/** The panel the translation text is shown in. */
+	private JPanel translation_pane = null;
+	/** The panel the translation language field is shown in. */
+	private JPanel translation_header_pane = null;
+	/** The table used to show the languages supported by the collection. */
+	private JTable languages_table = null;
+	/** The text area displaying the original text (in the default language). */
+	private JTextArea original = null;
+	 /** The text area displaying the translated text (in the selected language). */
+	 private JTextArea translation = null;
+	/** The language currently selected. */
+	private Language current_language = null;
+	/** The proxy model to the language manager which serves as the basis for the table. */
+	private TableProxy languages_model = null;
+	/** The default size of the features list. */
+	static final private Dimension FEATURE_SIZE = new Dimension(200, 400);
+	/** The default size of the translation dialog. */
+	static final private Dimension SIZE = new Dimension(800, 450);
+	/** Constructor.
+	* @param gatherer A reference to the <strong>Gatherer</strong>.
+	* @param manager A reference to the <strong>CollectionDesignManager</strong>.
+	* @see org.greenstone.gatherer.Configuration
+	* @see org.greenstone.gatherer.cdm.CollectionMeta
+	* @see org.greenstone.gatherer.cdm.TranslationManager.TableProxy
+	*/
+	 public TranslationManager(Gatherer gatherer, CollectionDesignManager manager) {
+		  super();
+		  this.dialog = this;
+		  this.gatherer = gatherer;
+		  this.manager = manager;
+		  this.languages_model = new TableProxy();
+		  // Create the features model. Basically we want one string entry for each unique name in the metadata.
+		  ArrayList features_model = new ArrayList();
+		  for(int i = 0; i < manager.collectionmetadatum.size(); i++) {
+				CollectionMeta metadata = (CollectionMeta) manager.collectionmetadatum.get(i);
+				Object object = metadata.getName();
+				String name = null;
+				if(object instanceof Index) {
+					 name = ((Index)object).toString(false);
+				}
+				else {
+					 name = object.toString();
+				}
+				if(!features_model.contains(name)) {
+					 features_model.add(name);
+				}
+		  }
+		  Collections.sort(features_model);
+		  // Create components...
+		  setModal(true);
+		  setSize(SIZE);
+		  close_button = new JButton(get("General.Close"));
+		  content_pane = (JPanel) getContentPane();
+		  control_pane = new JPanel();
+		  features_label = new JLabel(get("Affected_Features"));
+		  features_label.setHorizontalAlignment(JLabel.CENTER);
+		  features_list = new JList(features_model.toArray());
+		  features_listener = new FeatureListener();
+		  features_pane = new JPanel();
+		  features_pane.setPreferredSize(FEATURE_SIZE);
+		  languages_table = new JTable(languages_model);
+		  languages_table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+		  languages_label = new JLabel(get("Assigned_Languages"));
+		  languages_label.setHorizontalAlignment(JLabel.CENTER);
+		  languages_pane = new JPanel();
+		  original = new JTextArea();
+		  original.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  original.setEditable(false);
+		  original.setFont(new Font("Arial Unicode MS", Font.PLAIN, 10));
+		  original_header_pane = new JPanel();
+		  original_label = new JLabel(get("Default_Text"));
+		  original_label.setHorizontalAlignment(JLabel.CENTER);
+		  original_language_label = new JLabel("");
+		  original_pane = new JPanel();
+		  translation = new JTextArea();
+		  translation.setEnabled(false);
+		  translation.setFont(new Font("Arial Unicode MS", Font.PLAIN, 10));
+		  translation_header_pane = new JPanel();
+		  translation_label = new JLabel(get("Translation"));
+		  translation_label.setHorizontalAlignment(JLabel.CENTER);
+		  translation_language_label = new JLabel("");
+		  translation_pane = new JPanel();
+		  // Add listeners...
+		  close_button.addActionListener(new CloseListener());
+		  translation.addKeyListener(new TranslationListener());
+		  features_list.addListSelectionListener(features_listener);
+		  features_list.addListSelectionListener(languages_model);
+		  ListSelectionModel languages_selection_model = languages_table.getSelectionModel();
+		  languages_selection_model.addListSelectionListener(new TableListener());
+		  // Layout...
+		  features_pane.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+		  features_pane.setLayout(new BorderLayout());
+		  features_pane.add(features_label, BorderLayout.NORTH);
+		  features_pane.add(new JScrollPane(features_list), BorderLayout.CENTER);
+		  languages_label.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+		  languages_pane.setLayout(new BorderLayout());
+		  languages_pane.add(languages_label, BorderLayout.NORTH);
+		  languages_pane.add(new JScrollPane(languages_table), BorderLayout.CENTER);
+		  original_header_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+		  original_header_pane.setLayout(new BorderLayout());
+		  original_header_pane.add(original_label, BorderLayout.WEST);
+		  original_header_pane.add(original_language_label, BorderLayout.EAST);
+		  original_pane.setLayout(new BorderLayout());
+		  original_pane.add(original_header_pane, BorderLayout.NORTH);
+		  original_pane.add(new JScrollPane(original), BorderLayout.CENTER);
+		  translation_header_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+		  translation_header_pane.setLayout(new BorderLayout());
+		  translation_header_pane.add(translation_label, BorderLayout.WEST);
+		  translation_header_pane.add(translation_language_label, BorderLayout.EAST);
+		  translation_pane.setLayout(new BorderLayout());
+		  translation_pane.add(translation_header_pane, BorderLayout.NORTH);
+		  translation_pane.add(new JScrollPane(translation), BorderLayout.CENTER);
+		  control_pane.setLayout(new GridLayout(3,1));
+		  control_pane.add(languages_pane);
+		  control_pane.add(original_pane);
+		  control_pane.add(translation_pane);
+		  content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		  content_pane.setLayout(new BorderLayout());
+		  content_pane.add(features_pane, BorderLayout.WEST);
+		  content_pane.add(control_pane, BorderLayout.CENTER);
+		  content_pane.add(close_button, BorderLayout.SOUTH);
+		  // Display...
+		  Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
+		  for (int i = 0; i < languages_model.getColumnCount() - 1; i++) {
+				TableColumn column = languages_table.getColumnModel().getColumn(i);
+				column.setMinWidth(0);
+				column.setMaxWidth(screen_size.width);
+				column.setPreferredWidth((SIZE.width - FEATURE_SIZE.width) / 6);
+		  }
+		  setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+		  show();
+	 }
+	 /** Destructor
+	  */
+	 public void destroy() {
+		  dialog = null;
+	 }
+	 /** Retrieve a phrase from the dictionary based on a certain key.
+	  * @param key The search <strong>String</strong>.
+	  * @return The matching phrase from the Dictionary as a <strong>String</strong>.
+	  */
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+	 /** Retrieve a phrase from the dictionary based on a certain key and certain arguments.
+	  * @param key The search <strong>String</strong>.
+	  * @param args A <strong>String[]</strong> used to complete and format the returned phrase.
+	  * @return The matching phrase from the Dictionary as a <strong>String</strong>.
+	  * @see org.greenstone.gatherer.Dictionary
+	  * @see org.greenstone.gatherer.Gatherer
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf(".") == -1) {
+				key = "CDM.TranslationManager." + key;
+		  }
+		  return gatherer.dictionary.get(key, args);
+	 }
+	 /** Listens for actions apon the close button. */
+	 private class CloseListener
+		  implements ActionListener {
+		  /** Closes the dialog. Any implementation of an ActionListener must include this method so we can be informed when an action has occured.
+			* @param event An <Strong>ActionEvent</strong> containing details about the action.
+			*/
+		  public void actionPerformed(ActionEvent event) {
+				dialog.dispose();
+		  }
+	 }
+	 /** Listens to selections within the feature list. */
+	 private class FeatureListener
+		  implements ListSelectionListener {
+		/** Called whenever the selection changes in the registered list, which requires us to create a new TableProxy.
+		* @param event A <strong>ListSelectionEvent</strong> containing more information about the list selection change.
+		* @see org.greenstone.gatherer.cdm.CollectionMeta
+		* @see org.greenstone.gatherer.cdm.Language
+		*/
+		  public void valueChanged(ListSelectionEvent event) {
+				// Try to find the default language value for this feature.
+				String name = (String) features_list.getSelectedValue();
+				Language language = manager.languages.getDefaultLanguage();
+				CollectionMeta metadata = manager.collectionmetadatum.getMetadata(name, language, true);
+				if(metadata != null && metadata.getValue() != null && metadata.getValue().length() != 0) {
+					 if(!metadata.getLanguage().equals(language)) {
+						  original_label.setText(get("Existing_Text"));
+					 }
+					 else {
+						  original_label.setText(get("Default_Text"));
+					 }
+					 original.setText(metadata.getValue());
+					 original_language_label.setText(metadata.getLanguage().toString());
+				}
+				else {
+					 original_label.setText(get("No_Text"));
+					 original.setText("");
+				}
+		  }
+	 }
+	 /** Listens for selections within the languages table. */
+	 private class TableListener
+		  implements ListSelectionListener {
+		/** Called whenever the selection changes in the registered list, which requires us to update several parts of the dialog.
+		* @param event A <strong>ListSelectionEvent</strong> containing more information about the list selection change.
+		* @see org.greenstone.gatherer.cdm.CollectionMeta
+		* @see org.greenstone.gatherer.cdm.Language
+		*/
+		  public void valueChanged(ListSelectionEvent event) {
+				if (event.getValueIsAdjusting()) return;
+				ListSelectionModel lsm = (ListSelectionModel)event.getSource();
+				if (!lsm.isSelectionEmpty()) {
+					 int row = lsm.getMinSelectionIndex();
+					 current = languages_model.getMetadata(row);
+					 if(current != null) {
+						  if (current.getValue() != null) {
+								translation.setText(current.getValue());
+						  }
+						  else {
+								translation.setText("");
+						  }
+						  current_language = current.getLanguage();
+					 }
+					 else {
+						  current_language = (Language) languages_model.getValueAt(row, 1);
+						  translation.setText("");
+					 }
+					 features_listener.valueChanged(null);
+					 translation_language_label.setText(current_language.toString());
+					 translation.setEnabled(true);
+				}
+		  }
+	 }
+	 /** A AbstractTableModel extension based upon a vector of CollectionMeta, which can also listen to a list for selection changes. */
+	 private class TableProxy
+		  extends AbstractTableModel
+		  implements ListSelectionListener {
+			/** Called when the contents of a cell changes.
+			*/
+		  public void cellChanged() {
+				fireTableDataChanged();
+		  }
+		  /** Returns the most specific superclass for all the cell values in the column.
+			* @param column An <i>int</i> specifying which columns class to be determined.
+			* @return The columns <strong>Class</strong>.
+			*/
+        public Class getColumnClass(int column) {
+				return String.class;
+		  }
+		  /** Returns the number of columns in the model.
+			* @return An <i>int</i> specifying the number of columns.
+			*/
+		  public int getColumnCount() {
+				if(!features_list.isSelectionEmpty()) {
+					 return 2;
+				}
+				return 0;
+		  }
+        /** Returns the name of the column at columnIndex.
+			* @param column An <i>int</i> specifying the column whose name you are interesting in.
+			* @return The name of the column as a <strong>String</strong>.
+			*/
+		  public String getColumnName(int column) {
+				String name = null;
+				switch(column) {
+				case 0:
+					 name = get("Language");
+					 break;
+				case 1:
+					 name = get("Text");
+					 break;
+				}
+				return name;
+		  }
+		  /** Retrieve the collection metadata from the specified row.
+		  * @param row An <i>int</i> indicating the row in question.
+		  * @see org.greenstone.gatherer.cdm.Language
+		  * @see org.greenstone.gatherer.cdm.LanguageManager
+		  */
+		  public CollectionMeta getMetadata(int row) {
+				String name = (String) features_list.getSelectedValue();
+				Language language = (Language) getValueAt(row, 0);
+				return manager.collectionmetadatum.getMetadata(name, language, false);
+		  }
+        /** Returns the number of rows in the model.
+			* @return An <i>int</i> specifying the number of rows in the table, which is exactly the number of languages assigned to this collection.
+			* @see org.greenstone.gatherer.cdm.LanguageManager
+			*/
+		  public int getRowCount() {
+				return manager.languages.size();
+		  }
+		  /** Returns the value for the cell at column and row.
+			* @param row The desired row as an <i>int</i>.
+			* @param column The desired column as an <i>int</i>.
+			* @return The value at the row, column reference.
+			* @see org.greenstone.gatherer.cdm.CollectionMeta
+			* @see org.greenstone.gatherer.cdm.Language
+			* @see org.greenstone.gatherer.cdm.LanguageManager
+			*/
+		  public Object getValueAt(int row, int column) {
+				if(!features_list.isSelectionEmpty()) {
+					 // First of all find the Language that matches the row and the current feature name, because in any case you'll need them.
+					 Language language = (Language)manager.languages.get(row);
+					 String feature_name = (String)features_list.getSelectedValue();
+					 // Also try to locate the collection level metadata that matches.
+					 CollectionMeta metadata = manager.collectionmetadatum.getMetadata(feature_name, language, false);
+					 // Now we do subtly different things depending on the column.
+					 switch(column) {
+					 case 0: // The Language. Easiest case.
+						  return language;
+					 case 1: // The value of the metadata. Needs us to retrieve the value for a certain feature and language.
+						  if(metadata != null) {
+								return metadata.getValue();
+						  }
+					 }
+					 // If all else fails, return an empty string and hope the class caster doesn't explode.
+				}
+				return "";
+		  }
+        /** Returns true if the cell at row and column is editable.
+			* @param row The row of the cell as an <i>int</i>.
+			* @param column The column of the cell also as an <i>int</i>.
+			*/
+		  public boolean isCellEditable(int rowIndex, int columnIndex) {
+				return false;
+		  }
+        /** Sets the value in the cell at columnIndex and rowIndex to aValue.
+			*/
+		  public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+		  }
+		  /** Any implementation of <i>ListSelectionListener</i> must include this method so we can be informed when the list selection has changed.
+			* @param event A <strong>ListSelectionEvent</strong> containing information about the selection change.
+			*/
+		  public void valueChanged(ListSelectionEvent event) {
+				fireTableStructureChanged();
+		  }
+	 }
+	 /** This provides a custom renderer that colours the background of the default language cell green, and the foreground of currently unready metadata rows red. */
+	 private class TableRenderer
+		  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) {
+				Component component = null;
+				// Create the component.
+				if(value instanceof String || value instanceof Language) {
+					 JLabel label = new JLabel(value.toString());
+					 label.setOpaque(true);
+					 component = label;
+				}
+				else {
+					 JCheckBox check = new JCheckBox("", ((Boolean)value).booleanValue());
+					 JPanel pane = new JPanel(new BorderLayout());
+					 pane.add(check, BorderLayout.CENTER);
+					 component = pane;
+				}
+				// Check for default property
+				Language language = (Language)languages_model.getValueAt(row, 1);
+				if(language.isDefault()) {
+					 if(isSelected) {
+						  component.setBackground(Gatherer.config.getColor("coloring.collection_selection_background", false));
+					 }
+					 else {
+						  component.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+					 }
+				}
+				else {
+					 if(isSelected) {
+						  component.setBackground(table.getSelectionBackground());
+					 }
+					 else {
+						  component.setForeground(Color.white);
+					 }
+				}
+				// Check for readiness
+				Boolean ready = (Boolean)languages_model.getValueAt(row, 0);
+				if(!ready.booleanValue()) {
+					 component.setForeground(Color.red);
+				}
+				else {
+					 component.setForeground(Color.black);
+				}
+				return component;
+		  }
+	 }
+	/** Listens for actions within the translation text field and immediately updates the collection metadata as necessary. */
+	 private class TranslationListener
+		  extends KeyAdapter {
+		 /** This method is called when a key has been released, and is perfect for us to synchronize the contents of the translation field with the collection metadata associated with the selected feature and language.
+		 * @param event A <strong>KeyEvent</strong> containing more detail about the key released.
+		 * @see org.greenstone.gatherer.cdm.CollectionMeta
+		 * @see org.greenstone.gatherer.cdm.CollectionMetaManager
+		 * @see org.greenstone.gatherer.cdm.Index
+		 */
+		  public void keyReleased(KeyEvent event) {
+				if(current == null) {
+					 String name = (String)features_list.getSelectedValue();
+					 Index index = manager.indexes.getIndex(name);
+					 if(index == null) {
+						  current = new CollectionMeta(manager, name, current_language, translation.getText());
+					 }
+					 else {
+						  current = new CollectionMeta(manager, index, current_language, translation.getText());
+					 }
+					 manager.collectionmetadatum.addMetadata(current);
+				}
+				else {
+					 current.update(current.getName(), current.getLanguage(), translation.getText());
+				}
+				languages_model.cellChanged();
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/custom/CustomAZList.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/custom/CustomAZList.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/custom/CustomAZList.java	(revision 13666)
@@ -0,0 +1,767 @@
+package org.greenstone.gatherer.cdm.custom;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.Classifier;
+import org.greenstone.gatherer.cdm.ClassifierManager;
+import org.greenstone.gatherer.cdm.CustomClassifier;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.Metadata;
+import org.greenstone.gatherer.msm.MetadataSet;
+import org.greenstone.gatherer.msm.MetadataSetManager;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.valuetree.GValueModel;
+import org.greenstone.gatherer.valuetree.GValueNode;
+import org.w3c.dom.*;
+/** Provides the functionality for a custom AZList, including a GUI for configuration of this classifier. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+final public class CustomAZList
+	 implements CustomClassifier {
+	 /** When this the control dialog is disposed, should we go ahead a add this custom AZ list (by processing all file records and building a new hierarchy)? */
+	 private boolean process = false;
+	 /** A reference to the Gatherer for access to the Collection and MetadataSetManager. */
+	 private Gatherer gatherer = null;
+	 /** A mapping from a String pattern to a specific GValueNode within the hidden hierarchy. */
+	 private Hashtable mappings = null;
+	 /** The button used to cancel the dialog. */
+	 private JButton cancel = null;
+	 /** The button used to confirm and close the dialog. */
+	 private JButton ok = null;
+	 /** The dialog which contains the controls for configuring this custom classifier. */
+	 private JDialog controls = null;
+	 /** The checkbox used to indicate whether there is a name given for the classifier button (in the Greenstone collections menubar). */
+	 private JCheckBox buttonname_label = null;
+	 /** The checkbox used to indicate that the final classifier should be sorted in some way. */
+	 private JCheckBox sort_label = null;
+	 /** The control allowing you to choose the assigned metadata this classifier should be based on. */
+	 private JComboBox metadata = null;
+	 /** The metadata the final classifier should be sorted by. */
+	 private JComboBox sort = null;
+	 /** A field for entering the button name. */
+	 private JTextField buttonname = null;
+	 /** A field which provides a clear indication of the current ranges selected for your custom classifier. */
+	 private JTextField separators_preview = null;
+	 /** An array of togglebuttons showing what separations are available. */
+	 private JToggleButton separators[] = null;
+	 /** A private dictionary for this custom classifier. */
+	 private ResourceBundle dictionary = null;
+	 /** The name of the hidden metadata. We at least luck out in that we don't need a live reference to the metadata, because the user can never change it (or if they do its their own stinking fault). */
+	 private String hidden_mde_name = null;
+	 /** The name of this pseudo-classifier. */
+	 final static public String NAME = "CustomAZList";
+	 /** The size of a label. */
+	 final static private Dimension LABEL_SIZE = new Dimension(200,25);
+	 /** The size of the controls for this pseudo-classifier. */
+	 final static private Dimension SIZE = new Dimension(550,400);
+	 /** An array of values for the separators. */
+	 final static private String VALUES[] = {"Numbers", "A", "B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
+	 /** The same array as above, except as integer values (note that "Numbers" becomes "#"). */
+	 static public int INT_VALUES[] = {'#','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
+	 /** A third array which is almost the same as the others (can anyone else say poor code reuse) but subsitutes "#" for "Numbers". */
+	 static public String STRING_VALUES[] = {"#","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
+	 /** Default Constructor. Needed to load this class dynamically. */
+	 public CustomAZList() {}
+	 /** Constructor.
+	  * @param gatherer A reference to the <strong>Gatherer</strong>.
+	  */
+	 public CustomAZList(Gatherer gatherer) {
+		  this.gatherer = gatherer;
+	 }
+	 /** Used to compare this classifier to another classifier for the purposes of ordering.
+	  * @param object The other classifier as an <strong>Object</strong>.
+	  * @see org.greenstone.gatherer.cdm.Classifier
+	  * @see org.greenstone.gatherer.cdm.CustomClassifier
+	  */
+	 public int compareTo(Object object) {
+		  if(object instanceof Classifier) {
+				Classifier classifier = (Classifier) object;
+				return NAME.compareTo(classifier.getName());
+		  }
+		  else if(object instanceof CustomClassifier) {
+				CustomClassifier classifier = (CustomClassifier) object;
+				return NAME.compareTo(classifier.getName());
+		  }				
+		  return NAME.compareTo(object.toString());	
+	 }
+	 /** Ensure that the dialog can be correctly garbage collected. */
+	 public void destroy() {
+		  controls = null;
+	 }
+	 /** Produce a new copy of this custom classifier. Remember that what the classifier manager does is create instances of all possible classifiers, then as they are assigned creates and assigns copies of the original reserve. This way we only have to parse arguments once. 
+	  * @return A new <strong>CustomClassifier</strong> which is a copy of this one.
+	  * @see org.greenstone.gatherer.Gatherer
+	  */
+	 public CustomClassifier copy() {
+		  return new CustomAZList(gatherer);
+	 }
+	 /** Show the controls for configuring this pseudo-classifier. 
+	  * @param show <i>true</i> to actually display the configuration dialog on screen, <i>false</i> to do everything except show the control and process the data (useful for setting the control up and/or reloading custom classifiers from collect.cfg).
+	  * @see org.greenstone.gatherer.Configuration
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.cdm.custom.CustomAZList.ButtonNameListener
+	  * @see org.greenstone.gatherer.cdm.custom.CustomAZList.CancelListener
+	  * @see org.greenstone.gatherer.cdm.custom.CustomAZList.OKListener
+	  * @see org.greenstone.gatherer.cdm.custom.CustomAZList.SeparatorListener
+	  * @see org.greenstone.gatherer.cdm.custom.CustomAZList.SortListener
+	  * @see org.greenstone.gatherer.collection.CollectionManager
+	  * @see org.greenstone.gatherer.msm.ElementWrapper
+	  * @see org.greenstone.gatherer.msm.MetadataSetManager
+	  */
+	 public boolean display(boolean show) {
+		  if(controls == null) {
+				Vector elements = gatherer.c_man.getCollection().msm.getAssignedElements();
+				// Creation
+				controls = new JDialog();
+				controls.setModal(true);
+				controls.setSize(SIZE);
+				controls.setTitle(get("Title_JDialog"));
+				JPanel content_pane = (JPanel) controls.getContentPane();
+				JPanel upper_pane = new JPanel();
+				JPanel metadata_pane = new JPanel();
+				JLabel metadata_label = new JLabel(get("Metadata_JLabel"));
+				metadata_label.setPreferredSize(LABEL_SIZE);
+				metadata = new JComboBox(elements);
+				JPanel buttonname_pane = new JPanel();
+				buttonname_label = new JCheckBox(get("Buttonname_JCheckBox"));
+				buttonname_label.setPreferredSize(LABEL_SIZE);
+				buttonname = new JTextField();
+				buttonname.setBackground(Color.lightGray);
+				buttonname.setEnabled(false);
+				JPanel sort_pane = new JPanel();
+				sort_label = new JCheckBox(get("Sort_JLabel"));
+				sort = new JComboBox(elements);
+				JPanel separations_pane = new JPanel();
+				JLabel separations_label = new JLabel(get("Separations_JLabel"));
+				separations_label.setPreferredSize(LABEL_SIZE);
+				separators_preview = new JTextField();
+				separators_preview.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				separators_preview.setEnabled(false); // View only.
+				separators_preview.setForeground(Color.black);
+				JPanel lower_pane = new JPanel();
+				JPanel button_pane = new JPanel();
+				ok = new JButton(get("OK_JButton"));
+				cancel = new JButton(get("Cancel_JButton"));
+				// Connection
+				buttonname_label.addActionListener(new ButtonNameListener());
+				cancel.addActionListener(new CancelListener());
+				ok.addActionListener(new OKListener());
+				sort_label.addActionListener(new SortListener());
+				// The Toggle Button block. Done all at once so we don't end up with three for loops.
+				JPanel center_pane = new JPanel();
+				center_pane.setLayout(new GridLayout(3, 9));
+				separators = new JToggleButton[VALUES.length];
+				SeparatorListener sl = new SeparatorListener();
+				for(int i = 0; i < VALUES.length; i++) {
+					 separators[i] = new JToggleButton(get(VALUES[i]));
+					 separators[i].addActionListener(sl);
+					 if(i != 0) {
+						  center_pane.add(separators[i]);
+					 }
+					 else {
+						  JLabel temp = new JLabel(get(VALUES[0]));
+						  temp.setHorizontalAlignment(JLabel.CENTER);
+						  center_pane.add(temp);
+					 }
+				}
+				separators_preview.setText(getPreview(true));
+				// Layout
+				metadata_pane.setBorder(BorderFactory.createEmptyBorder(1,0,1,0));
+				metadata_pane.setLayout(new BorderLayout());
+				metadata_pane.add(metadata_label, BorderLayout.WEST);
+				metadata_pane.add(metadata, BorderLayout.CENTER);
+				
+				buttonname_pane.setBorder(BorderFactory.createEmptyBorder(1,0,1,0));
+				buttonname_pane.setLayout(new BorderLayout());
+				buttonname_pane.add(buttonname_label, BorderLayout.WEST);
+				buttonname_pane.add(buttonname, BorderLayout.CENTER);
+				
+				sort_pane.setBorder(BorderFactory.createEmptyBorder(1,0,1,0));
+				sort_pane.setLayout(new BorderLayout());
+				sort_pane.add(sort_label, BorderLayout.WEST);
+				sort_pane.add(sort, BorderLayout.CENTER);
+
+				upper_pane.setBorder(BorderFactory.createEmptyBorder(0,0,4,0));
+				upper_pane.setLayout(new GridLayout(3, 1));
+				upper_pane.add(metadata_pane);
+				upper_pane.add(buttonname_pane);
+				upper_pane.add(separations_label);
+				
+				separations_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,0,5,0), BorderFactory.createRaisedBevelBorder()));
+				separations_pane.setLayout(new BorderLayout());
+				separations_pane.add(separators_preview, BorderLayout.CENTER);
+				
+				lower_pane.setLayout(new GridLayout(2,1));
+				lower_pane.add(separations_pane);
+				lower_pane.add(button_pane);
+				
+				button_pane.setLayout(new GridLayout(1,2));
+				button_pane.add(ok);
+				button_pane.add(cancel);
+				
+				content_pane.setBorder(BorderFactory.createEmptyBorder(4,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(lower_pane, BorderLayout.SOUTH);
+				// Display
+				Dimension screen_size = Gatherer.config.screen_size;
+				controls.setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+				screen_size = null;
+				if(show) {
+					 controls.show();
+					 // Create the new metadata, hierarchy etc.
+					 if(process) {
+						  process((ElementWrapper)metadata.getSelectedItem(), getPreview(false));
+						  return true;
+					 }
+					 return false;
+				}
+				else {
+					 return true;
+				}
+				// We do everything -except- display the control.
+		  }
+		  else {
+				process = false;
+				controls.show();
+				if(process) {
+					 process((ElementWrapper)metadata.getSelectedItem(), getPreview(false));
+					 return true;
+				}
+				return false;
+		  }
+	 }
+	 /** Determine if this classifier and another given classifier are equal.
+	  * @param object The classifier to check against for equality, as an <strong>Object</strong>.
+	  * @see org.greenstone.gatherer.cdm.CustomClassifier
+	  */
+	 public boolean equals(Object object) {
+		  if(object instanceof CustomClassifier) {
+				CustomClassifier classifier = (CustomClassifier) object;
+				if(getCommand().equalsIgnoreCase(classifier.getCommand())) {
+					 return true;
+				}
+				return false;
+		  }
+		  else {
+				if(getCommand().equalsIgnoreCase(object.toString())) {
+					 return true;
+				}
+				return false;
+		  }
+	 }
+	 /** Method to return this pseudo-classifier represented as a String.
+	  * @return A <strong>String</strong>.
+	  */
+	 public String getCommand() {
+		  StringBuffer text = new StringBuffer("classify ");
+		  text.append("Hierarchy");
+		  text.append(" -metadata ");
+		  text.append(hidden_mde_name); // @TODO
+		  if(buttonname_label.isSelected()) {
+				text.append(" -buttonname \"");
+				text.append(buttonname.getText());
+				text.append("\"");
+		  }
+		  text.append(" -hfile ");
+		  text.append(hidden_mde_name + ".txt");
+		  text.append(" -hlist_at_top");
+		  text.append("\n");
+		  return text.toString();
+	 }
+	 /** Retrieve the custom command, a command line that overrides and replaces some other 'actual' classifier.
+	  * @param index The number of the classifer this one is replacing.
+	  */
+	 public String getCustomCommand(int index) {
+		  StringBuffer text = new StringBuffer("customclassifier ");
+		  text.append(NAME);
+		  text.append(" -replaces CL");
+		  text.append(index);
+		  text.append(" -separations ");
+		  text.append(getPreview(false));
+		  return text.toString();
+	 }
+	 /** Get the name of this custom classifier.
+	  * @return The name as a <strong>String</strong>.
+	  */
+	 public String getName() {
+		  return NAME;
+	 }
+	 /** Process a record by adding hidden metadata as necessary.
+	  * @param record The <strong>FileNode</strong> to be edited.
+	  * @see org.greenstone.gatherer.msm.ElementWrapper
+	  */
+	 public void process(FileNode record) {
+		  ElementWrapper element = (ElementWrapper) metadata.getSelectedItem();
+		  if(element != null) {
+				addMetadata(0L, record, element);
+		  }
+	 }
+	 /** Recreate a CustomAZList given several parameters including the real classifier created during custom design.
+	  * @param classifier The real <strong>Classifier</strong>.
+	  * @param separations A <strong>String</strong> representing the choosen separations.
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.cdm.Argument
+	  * @see org.greenstone.gatherer.collection.CollectionManager
+	  * @see org.greenstone.gatherer.msm.ElementWrapper
+	  * @see org.greenstone.gatherer.msm.MetadataSetManager
+	  * @see org.greenstone.gatherer.valuetree.GValueModel
+	  * @see org.greenstone.gatherer.valuetree.GValueNode
+	  */
+	 public void recreate(Classifier classifier, String separations) {
+		  // Rebuild controls
+		  display(false);
+		  // Calculate original element.
+		  hidden_mde_name = classifier.getArgument("metadata").getValue();
+		  ElementWrapper hidden_mde = gatherer.c_man.getCollection().msm.getElement(hidden_mde_name);
+		  String mde_name = (hidden_mde_name.substring(MetadataSetManager.HIDDEN.length() + 1)).replace('_','.');
+		  ElementWrapper mde = gatherer.c_man.getCollection().msm.getElement(mde_name);
+		  // Set metadata element combobox.
+		  metadata.setSelectedItem(mde);
+		  // Set button name.
+		  String bn = classifier.getArgument("buttonname").getValue();
+		  if(bn != null) {
+				buttonname_label.setSelected(true);
+				buttonname.setBackground(Color.white);
+				buttonname.setEnabled(true);
+				buttonname.setText(bn);
+		  }
+		  // Set sort element.
+		  String sort_mde_name = classifier.getArgument("sort").getValue();
+		  ElementWrapper sort_mde = gatherer.c_man.getCollection().msm.getElement(sort_mde_name);
+		  if(sort_mde != null) {
+				sort_label.setSelected(true);
+				sort.setBackground(Color.white);
+				sort.setEnabled(true);
+				sort.setSelectedItem(sort_mde);
+		  }
+		  // Recover value tree.
+		  GValueModel model = gatherer.c_man.getCollection().msm.getValueTree(hidden_mde);
+		  // For each token in the tokenizer, set toggle buttons and recover node.
+		  StringTokenizer tokenizer = new StringTokenizer(separations, ",");
+		  mappings = new Hashtable();
+		  while(tokenizer.hasMoreTokens()) {
+				String key = tokenizer.nextToken();
+				for(int j = 1; j < STRING_VALUES.length; j++) {
+					 if(key.startsWith(STRING_VALUES[0])) {
+						  j = STRING_VALUES.length;
+					 }
+					 else if(key.startsWith(STRING_VALUES[j])) {
+						  separators[j].setSelected(true);
+						  j = STRING_VALUES.length;
+					 }
+				}
+				// Rebuild mappings hashtable for this pattern. Add it if not present.
+				GValueNode node = model.addValue(key);
+				// If the key is simple, ie "C", then add the mapping "C"->node
+				if(node == null) {
+					 // Do nothing.
+				}
+				else if(key.indexOf("-") == -1) {
+					 mappings.put(key, node);
+				}
+				// If the key is more complex, say "D-L", then we add mappings for all string values so "D"->node, "E"->node, ... "L"->node. This is miles eaiser to do here, than when you are trying to match a records metadata ie matchin "D-L" to "Igloos are cool". Note that it is guarantee that the keys are all of the same length, ie "A-L", "MA-ML", "MMA-STF", "STFA-ZZZZ".
+				else {
+					 String start = key.substring(0, key.indexOf("-"));
+					 String end = key.substring(key.indexOf("-") + 1);
+					 for(key = start; key != null && key.compareTo(end) <= 0; key = increment(key)) {
+						  ///ystem.err.println("Adding " + key + " -> " + node);
+						  mappings.put(key, node);	
+					 }
+				}
+		  }
+		  separators_preview.setText(getPreview(true));
+	 }
+	 /** Sets the value of Gatherer, for those classes loaded dynamically.
+	  * @param gatherer A reference to the <strong>Gatherer</strong>.
+	  */
+	 public void setGatherer(Gatherer gatherer) {
+		  this.gatherer = gatherer;
+	 }
+
+	 public void setManager(ClassifierManager manager) {
+	 }
+
+	 /** Translate this object into a string such as you would find in the collection configuration file.
+	  * @return A <strong>String</strong> representation.
+	  */
+	 public String toString() {
+		  StringBuffer text = new StringBuffer("classify ");
+		  text.append(NAME);
+		  text.append(" -metadata ");
+		  text.append(metadata.getSelectedItem().toString());
+		  if(buttonname_label.isSelected()) {
+				text.append(" -buttonname \"");
+				text.append(buttonname.getText());
+				text.append("\"");
+		  }
+		  text.append(" -separations ");
+		  text.append(getPreview(false));
+		  return text.toString();
+	 }
+	 /** Add a pertinant piece of metadata to the given record. */
+	 private void addMetadata(long id, FileNode record, ElementWrapper element) {
+		  // Add custom metadata based on target metadata. No recursion.
+		  ArrayList temp_value = Gatherer.c_man.getCollection().gdm.getMetadata(record.getFile(), element);
+		  boolean found = false; // Only want to add the custom classifier metadata once.
+		  for(int i = 0; !found && i < temp_value.size(); i++) {
+				String metadata_value = (String)temp_value.get(i);
+				for(Enumeration keys = mappings.keys(); metadata_value != null && keys.hasMoreElements(); ) {
+					 String key = (String)keys.nextElement();
+					 // Try to match the value and the pattern. Remember to check for any case, ie key is '#' and metadata_value starts with anything other than a character.
+					 if(metadata_value.toUpperCase().startsWith(key) || (key.equals("#") && !Character.isLetter(metadata_value.charAt(0)))) {
+						  GValueNode node = (GValueNode) mappings.get(key);
+						  if(node != null) { // And it shouldn't.
+								Metadata metadata = new Metadata(node);
+								//record.addMetadata(id, metadata, MetaEditPromptBox.ACCUMULATE_ALL, false, 1);
+								Gatherer.c_man.getCollection().msm.fireMetadataChanged(0, record, null, metadata);
+								found = true;
+						  }
+					 }
+				}
+		  }
+	 } 
+	 /** Create a separation preview String from the currently selected toggle buttons.
+	  * @param spaces <i>true</i> if the returned String should contain spaces for readability, <i>false</i> if we mean to process it and spaces would just make that more difficult.
+	  * @return A <strong>String</strong> representing the current separation state, such as "#, A-L, M-Z".
+	  */
+	 private String getPreview(boolean spaces) {
+		  String sep_sep = ",";
+		  if(spaces) {
+				sep_sep = ", ";
+		  }
+		  StringBuffer preview = new StringBuffer(get(VALUES[0]));
+		  for(int i = 1; i < separators.length - 1; i++) {
+				if(separators[i].isSelected()) {
+					 // Special case, where we specifically avoid #-#, A...
+					 if(i == 1) {
+						  preview.append(sep_sep);
+						  preview.append(get(VALUES[i]));
+					 }
+					 // Check previous value. We don't want ...A-L, M-M, N...
+					 else if(separators[i - 1].isSelected()) {
+						  preview.append(sep_sep);
+						  preview.append(get(VALUES[i]));
+					 }
+					 // Otherwise ..-VALUE[i-1], VALUE[i]...
+					 else {
+						  preview.append("-");
+						  preview.append(get(VALUES[i-1]));
+						  preview.append(sep_sep);
+						  preview.append(get(VALUES[i]));
+					 }
+				}
+		  }
+		  // Special case of "...-Y,Z" 
+		  if(separators[separators.length - 1].isSelected()) {
+				preview.append("-");
+				preview.append(get(VALUES[VALUES.length - 2]));
+				preview.append(sep_sep);
+				preview.append(get(VALUES[VALUES.length - 1]));
+		  }
+		  // Otherwise "...-Z"
+		  else {
+				preview.append("-");
+				preview.append(get(VALUES[VALUES.length - 1]));
+		  }				
+		  return preview.toString();
+	 } 
+	 /** Load the custom argument dictionary if necessary, then retrieve the requested phrase.
+	  * @param key A key <strong>String</strong> which maps to the phrase to retrieve.
+	  * @return A phrase as a <strong>String</strong>.
+	  * @see org.greenstone.gatherer.Dictionary
+	  * @see org.greenstone.gatherer.Gatherer
+	  */
+	 private String get(String key) {
+		  if(dictionary == null) {
+				dictionary = ResourceBundle.getBundle("org.greenstone.gatherer.cdm.custom." + NAME, Gatherer.config.getLocale("general.locale", false));
+		  }
+		  return dictionary.getString(key);
+	 }
+	 /** Listens to the buttonname checkbox, and enable buttonname appropriately when action detected. */
+	 private class ButtonNameListener
+		  implements ActionListener {
+		  /** When an action is performed on a registered control, this method is called which either enables or disables the buttonname field depending on the buttonname checkbox.
+			* @param event An <strong>ActionEvent</strong> containing information about the action performed.
+			*/
+		  public void actionPerformed(ActionEvent event) {
+				if(buttonname_label.isSelected()) {
+					 buttonname.setBackground(Color.white);
+					 buttonname.setEnabled(true);
+				}
+				else {
+					 buttonname.setBackground(Color.lightGray);
+					 buttonname.setEnabled(false);
+				}					 
+		  }
+	 }
+	 /** Listens to the cancel button, and disposes appropriately when action detected. */
+	 private class CancelListener
+		  implements ActionListener {
+		  /** If the cancel button is pressed then we should dispose of the dialog without processing any records.
+			* @param event An <strong>ActionEvent</strong> containing information about the action performed.
+			*/
+		  public void actionPerformed(ActionEvent event) {
+				process = false;
+				controls.dispose();
+		  }
+	 }
+	 /** Listens to the ok button, and sets process to true then disposes appropriately when action detected. */
+	 private class OKListener
+		  implements ActionListener {
+		  /** If the ok button is pressed then we should dispose of the dialog after processing all records.
+			* @param event An <strong>ActionEvent</strong> containing information about the action performed.
+			*/
+		  public void actionPerformed(ActionEvent event) {
+				process = true;
+				controls.dispose();
+		  }
+	 }
+	 /** Listens for the toggling of a separator value, and updates the separator preview field. */
+	 private class SeparatorListener
+		  implements ActionListener {
+		  /** When one of the separator buttons is toggled we update the separator preview field.
+			* @param event An <strong>ActionEvent</strong> containing information about the action performed.
+			*/
+		  public void actionPerformed(ActionEvent event) {
+				separators_preview.setText(getPreview(true));
+		  }
+	 }
+	 /** Listens to the sort checkbox, and enables/disables sort appropriately when action detected. */
+	 private class SortListener
+		  implements ActionListener {
+		  /** If this checkbox is actioned, enabled or disable the sort control based on whether we are checked (selected) or not.
+			* @param event An <strong>ActionEvent</strong> containing information about the action performed.
+			*/
+		  public void actionPerformed(ActionEvent event) {
+				if(sort_label.isSelected()) {
+					 sort.setBackground(Color.white);
+					 sort.setEnabled(true);
+				}
+				else {
+					 sort.setBackground(Color.lightGray);
+					 sort.setEnabled(false);
+				}					 
+		  }
+	 }
+	 /** Display a progress bar while creating the required hidden system hierarchy. 
+	  * @param element An <strong>ElementWrapper</strong> containing the metadata element we want to build a custom classifier on.
+	  * @param state A <strong>String</strong> representing the currently selected separators, of the form "#,A-L,MA-Ml,MM-MZ,N-Z". */
+	 private void process(ElementWrapper element, String state) {
+		  // Create a new progress bar dialog, using these divisions:
+		  // 33% - Creation and removal of old metadata tree.
+		  // 33% - Creation of new metadata tree, 33 / <number of separations>.
+		  // 33% - Allocation of metadata to records, 33 / <number of files>.
+		  // Hopefully the previous dialog should have already vanished (its dispose() caused by the process click).
+		  ProgressDialog pd = new ProgressDialog("Custom Classifier Creation", "Preparing for operation.");
+		  // Step 1: Create the new dummy element and add it if necessary.
+		  pd.setText("Creating dummy metadata element.");
+		  MetadataSet hidden_mds = gatherer.c_man.getCollection().msm.getSet(MetadataSetManager.HIDDEN);
+		  Element hidden_e = hidden_mds.getElement(element.toString().replace('.','_'));
+		  boolean found = true;
+		  ElementWrapper hidden_mde = null;
+		  if(hidden_mde != null) {
+				hidden_mde = new ElementWrapper(hidden_e);
+		  }
+		  else {
+				hidden_mde = hidden_mds.addElement(element.toString().replace('.','_'));
+				found = false;
+		  }
+		  hidden_mde_name = hidden_mde.toString();
+		  pd.increase(1,2,20);
+		  // Step 2: Remove any existing value tree for this element. Wastefull I know but I don't want to lag for too long, and this is the quickest way.
+		  pd.setText("Removing any existing hierarchy.");
+		  if(found) {
+				hidden_mds.removeValueTree(hidden_mde);
+		  }
+		  pd.increase(1,2,20);
+		  // Step 3: Create a value tree for this element.
+		  pd.setText("Creating new hierary root.");
+		  GValueModel value_tree = gatherer.c_man.getCollection().msm.getValueTree(hidden_mde);
+		  pd.increase(5, 5, 5);
+		  // Step 4: Build the single level value hierarchy using state's value. Here a hashtable mapping string patterns to value nodes is built.
+		  pd.setText("Creating separations.");
+		  StringTokenizer tokenizer = new StringTokenizer(state, ",");
+		  int separator_count = tokenizer.countTokens();
+		  mappings = new Hashtable();
+		  for(int i = 0; i < separator_count; i++) {
+				String key = tokenizer.nextToken();
+				GValueNode node = value_tree.addValue(key);
+				// If the key is simple, ie "C", then add the mapping "C"->node
+				if(key.indexOf("-") == -1) {
+					 mappings.put(key, node);
+				}
+				// If the key is more complex, say "D-L", then we add mappings for all string values so "D"->node, "E"->node, ... "L"->node. This is miles eaiser to do here, than when you are trying to match a records metadata ie matchin "D-L" to "Igloos are cool". Note that it is guarantee that the keys are all of the same length, ie "A-L", "MA-ML", "MMA-STF", "STFA-ZZZZ".
+				else {
+					 String start = key.substring(0, key.indexOf("-"));
+					 String end = key.substring(key.indexOf("-") + 1);
+					 for(key = start; key != null && key.compareTo(end) <= 0; key = increment(key)) {
+						  mappings.put(key, node);	
+					 }
+				}
+				// Each iteration.
+				pd.increase(1, separator_count, 25);
+		  }
+		  // Step 5: Recurse the entire tree, adding the appropriate values where necessary (overwriting any existing value for this element).
+		  pd.setText("Allocating metadata to records.");
+		  int document_count = gatherer.c_man.getCollection().getDocumentCount();
+		  TreeModel record_tree = gatherer.c_man.getRecordSet();
+		  FileNode records[] = ArrayTools.add(null, (FileNode)record_tree.getRoot());
+		  while(records != null) {
+				if(records[0].isLeaf()) {
+					 addMetadata(0L, records[0], element);
+					 // Each iteration.
+					 pd.increase(1, document_count, 50);
+				}
+				else {
+					 // Add all children to records at once hopefully.
+					 FileNode children[] = new FileNode[records[0].getChildCount()];
+					 for(int i = 0; i < children.length; i++) {
+						  children[i] = (FileNode) records[0].getChildAt(i);
+					 }
+					 records = ArrayTools.add(records, children);
+				}
+				records = ArrayTools.tail(records);
+		  }
+		  // Step 6: Done.
+		  pd.dispose();
+	 }
+	 /** A dialog window used to show the progress of processing the file records in terms of adding hidden metadata. */
+	 private class ProgressDialog
+		  extends JDialog {
+		  /** The current value represented by the progress bar (where value is double and the progress bar shows an int). */
+		  private double value = 0.0;
+		  /** The default size of this dialog. */
+		  private Dimension dialog_size = new Dimension(500,100);
+		  /** The label explaining what action is currently happening (1 of 5 steps). */
+		  private JLabel label = new JLabel();
+		  /** The progress bar itself. */
+		  private JProgressBar bar = new JProgressBar();
+		  /** Constructor.
+			* @param t The title for this dialog as a <strong>String</strong>.
+			* @param l The initial label for the progress bar also a <strong>String</strong>.
+			*/
+		  public ProgressDialog(String t, String l) {
+				super();
+				setModal(false);
+				setSize(dialog_size);
+				setTitle(t);
+				// Create
+				JPanel content_pane = (JPanel) getContentPane();
+				label.setText(l);
+				bar.setMaximum(100);
+				bar.setMinimum(0);
+				bar.setValue(0);
+				// Connect
+				// Layout
+				content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+				content_pane.setLayout(new BorderLayout());
+				content_pane.add(label, BorderLayout.NORTH);
+				content_pane.add(bar, BorderLayout.CENTER);
+				// Display
+				Dimension screen_size = Gatherer.config.screen_size;
+				setLocation((screen_size.width - dialog_size.width) / 2, (screen_size.height - dialog_size.height) / 2);
+				screen_size = null;
+				show();
+		  }
+		  /** Increase the progress bar by a certain ammount.
+			* @param item An <i>int</i> indicating what item number this is.
+			* @param out_of An <i>int</i> detailing the number of items expected in total for this phase.
+			* @param total The maximum value of the progress bar as an <i>int</i>.
+			*/
+		  public void increase(int item, int out_of, int total) {
+				value = value + (((double) item / (double) out_of) * (double)total);
+				int int_value = (int) value;
+				///ystem.err.println("Value is " + value + " which rounds to " + int_value);
+				if(int_value != bar.getValue()) {
+					 bar.setValue(int_value);
+				}
+		  }
+		  /** Set the message shown in the progress bar.
+			* @param l The new progress bar label as a <strong>String</strong>.
+			*/
+		  public void setText(String l) {
+				label.setText(l);
+		  }
+	 }
+	 /** The String equivelent of int++, this method increments the value of a String by one letter at a time.
+	  * @param str The <strong>String</strong> to be incremented.
+	  * @return A <strong>String</strong> whose 'checksum' value (adding the INT_VALUE[] of the letters together) is one greater than the initial String, while still containing only those values in STRING_VALUE[].
+	  */
+	 public String increment(String str) {
+		  ///ystem.err.print("Incrementing " + str + " -> ");
+		  char chars[] = str.toCharArray();
+		  boolean found = false;
+		  int pos = str.length() - 1;
+		  while(found == false && pos >= 0) {
+				if((int)chars[pos] + 1 <= INT_VALUES[26]) {
+					 if((int)chars[pos] == INT_VALUES[0]) { // Anything else symbol
+						  chars[pos] = (char) INT_VALUES[1];
+					 }
+					 else {
+						  chars[pos] = (char)((int)chars[pos] + 1);
+					 }
+					 found = true;
+				}  
+				else {
+					 chars[pos] = (char)INT_VALUES[1];
+					 pos--;
+				}
+		  }
+		  // If we haven't found it yet, return null.
+		  if(!found) {
+				return null;
+		  }
+		  ///ystem.err.println(String.valueOf(chars));
+		  return String.valueOf(chars);
+	 }
+}
+
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/cdm/custom/CustomAZList.properties
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/cdm/custom/CustomAZList.properties	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/cdm/custom/CustomAZList.properties	(revision 13666)
@@ -0,0 +1,33 @@
+A:A
+B:B
+Buttonname_JCheckBox:Button name
+C:C
+Cancel_JButton:Cancel
+D:D
+E:E
+F:F
+G:G
+H:H
+I:I
+J:J
+K:K
+L:L
+M:M
+Metadata_JComboBox:Select metadata
+N:N
+Numbers:#
+O:O
+OK_JButton:Create Classifier
+P:P
+Q:Q
+R:R
+S:S
+Separations_JLabel:Allocate separations:
+T:T
+Title_JDialog:Custom AZList Classifier Configuration
+U:U
+V:V
+W:W
+X:X
+Y:Y
+Z:Z
Index: /tags/start/gli/src/org/greenstone/gatherer/checklist/CheckList.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/checklist/CheckList.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/checklist/CheckList.java	(revision 13666)
@@ -0,0 +1,238 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+package org.greenstone.gatherer.checklist;
+/**************************************************************************************
+ * Title:        Gatherer
+ * Description:  The Gatherer: a tool for gathering and enriching a digital collection.
+ * Company:      The University of Waikato
+ * Written:      14/08/02
+ * Revised:      
+ **************************************************************************************/
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import org.greenstone.gatherer.checklist.Entry;
+/** 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
+ */ 
+// ####################################################################################
+// Optimization                          Saving
+// ####################################################################################
+// Vector -> ArrayList                   + Processor
+// ####################################################################################
+public class CheckList
+	 extends JList {
+	 /** The border used when a list row is not in focus. */
+	 protected static Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
+	 /** Constructor. */
+	 public CheckList() {
+		  super();
+		  setCellRenderer(new CellRenderer());
+		  setModel(new DefaultListModel());
+		  setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+		  addMouseListener(new CheckListListener());
+	 }
+	 /** Constructor.
+	  * @param list_data An <strong>ArrayList</strong> of entries for this checklist.
+	  * @see org.greenstone.gatherer.checklist.CheckList.Entry
+	  */
+	 public CheckList(ArrayList list_data) {
+		  super();
+		  // Create a new model.
+		  DefaultListModel model = new DefaultListModel();
+		  for(int i = 0; i < list_data.size(); i++) {
+				Entry entry = new Entry(list_data.get(i));
+				String name = entry.toString();
+				int index = 0;
+				boolean found = false;
+				while(index < model.size() && !found) {
+					 Object sibling = model.getElementAt(index);
+					 if(name.compareTo(sibling.toString()) <= 0) {
+						  model.add(index, entry);
+						  found = true;
+					 }
+					 index++;
+				}
+				if(!found) {
+					 model.addElement(entry);
+				}
+		  }
+		  setModel(model);
+		  setCellRenderer(new CellRenderer());
+		  addMouseListener(new CheckListListener());
+		  setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+	 }
+
+	 /** Constructor. */
+	 public CheckList(ListModel data_model) {
+		  super(data_model);
+		  setCellRenderer(new CellRenderer());
+		  addMouseListener(new CheckListListener());
+		  setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+	 }
+
+	 public void addEntry(Entry entry) {
+		  DefaultListModel model = (DefaultListModel) getModel();
+		  String name = entry.toString();
+		  int index = 0;
+		  boolean found = false;
+		  while(index < model.size() && !found) {
+				Object sibling = model.getElementAt(index);
+				if(name.compareTo(sibling.toString()) <= 0) {
+					 model.add(index, entry);
+					 found = true;
+				}
+				index++;
+				sibling = null;
+		  }
+		  if(!found) {
+				model.addElement(entry);
+		  }		  
+		  name = null;
+		  model = null;
+	 }
+
+	 public Entry get(int index) {
+		  DefaultListModel model = (DefaultListModel) getModel();
+		  return (Entry) model.get(index);
+	 }
+
+	 /** 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.CheckList.Entry
+	  */
+	 public ArrayList getSelected() {
+		  ArrayList result = new ArrayList();
+		  DefaultListModel model = (DefaultListModel) getModel();
+		  int size = model.size();
+		  for(int i = 0; i < size; i++) {
+				Entry entry = (Entry) model.get(i);
+				if(entry.isSelected()) {
+					 result.add(entry.getObject());
+				}
+		  }
+		  return result;
+	 }
+
+	 public boolean isSelected(int index) {
+		  DefaultListModel model = (DefaultListModel) getModel();
+		  Entry entry = (Entry) model.get(index);
+		  return entry.isSelected();
+	 }
+
+	 public int getEntryCount() {
+		  return getModel().getSize();
+	 }
+
+	 /** Checks the entries in the list whose name appear in the given array.
+	  * @param names The name of entries to be checked as a <strong>String[]</strong>.
+	  * @see org.greenstone.gatherer.checklist.CheckList.Entry
+	  */
+	 public void setSelected(String names[]) {
+		  DefaultListModel model = (DefaultListModel) getModel();
+		  int size = model.size();
+		  for(int i = 0; i < size; i++) {
+				Entry entry = (Entry) model.get(i);
+				for(int j = 0; names != null && j < names.length; j++) {
+					 if(entry.toString().equals(names[j])) {
+						  entry.setSelected(true);
+					 }
+				}
+		  }		  
+	 }
+	 /** A custom list cell renderer for producing rows which contain clickable check boxes. */
+	 protected class CellRenderer 
+		  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(is_selected ? list.getSelectionBackground() : list.getBackground());
+				checkbox.setForeground(is_selected ? list.getSelectionForeground() : list.getForeground());
+				checkbox.setEnabled(list.isEnabled());
+				checkbox.setFont(list.getFont());
+				checkbox.setFocusPainted(false);
+				checkbox.setBorderPainted(true);
+				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 CheckListListener 
+		  extends MouseAdapter {
+		  private Entry previous_checkbox = null;
+		  /** 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) {
+				JList list = (JList) e.getSource();
+				int index = list.locationToIndex(e.getPoint());
+				Entry checkbox = (Entry)list.getModel().getElementAt(index);
+				// If this is the same checkbox as was recently selected, change the tick.
+				if(list.isSelectedIndex(index) && checkbox == previous_checkbox) {
+					 if(!checkbox.isFixed()) {
+						  checkbox.setSelected(!checkbox.isSelected());
+					 }
+					 checkbox.grabFocus();
+				}
+				// Otherwise the selection has just changed, so select the new checkbox
+				else if(list.isSelectedIndex(index)) {
+					 previous_checkbox = checkbox;
+				}
+				else {
+					 previous_checkbox = null;
+				}
+		  }
+	 }
+}
+
Index: /tags/start/gli/src/org/greenstone/gatherer/checklist/Entry.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/checklist/Entry.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/checklist/Entry.java	(revision 13666)
@@ -0,0 +1,77 @@
+package org.greenstone.gatherer.checklist;
+
+import javax.swing.JCheckBox;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.msm.MetadataSet;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.greenstone.gatherer.util.Utility;
+import org.w3c.dom.Element;
+/** An Entry encapsulates a single row of the list, both its check box and the object the row represents. */
+public class Entry
+	 extends JCheckBox {
+	 /** 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 Entry(Object object) {
+		  super(object.toString());
+		  this.object = object;
+		  // We also build a special tool tip for metadata sets.
+		  if(object instanceof MetadataSet) {
+				MetadataSet set = (MetadataSet) object;
+				// Build tooltip
+				StringBuffer tip = new StringBuffer(Gatherer.dictionary.get("NewCollectionPrompt.Set_Contains"));
+				tip.append(":\n");
+				for(int i = 0; i < set.size(); i++) {
+					 Element element = set.getElement(i);
+					 tip.append(MSMUtils.getIdentifier(element));
+					 if(i < set.size() - 1) {
+						  tip.append(", ");
+					 }
+				}
+				setToolTipText(Utility.formatHTMLWidth(tip.toString(), 60));
+		  }
+	 }
+
+	 /** Constructor. */
+	 public Entry(String text, boolean is_selected) {
+		  super(text);
+		  setSelected(is_selected);
+	 }
+
+	 /** 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/start/gli/src/org/greenstone/gatherer/collection/BuildOptions.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/collection/BuildOptions.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/collection/BuildOptions.java	(revision 13666)
@@ -0,0 +1,417 @@
+package org.greenstone.gatherer.collection;
+
+import java.io.*;
+import java.lang.ref.*;
+import java.util.*;
+import org.apache.xerces.parsers.DOMParser;
+import org.greenstone.gatherer.Configuration;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.Argument;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.Utility;
+import org.w3c.dom.*;
+import org.xml.sax.InputSource;
+/** Build options uses the argument list found in config.xml and the current settings from the loaded collection configuration to represent the options the user wants to use during import and build. If there are no arguments stored in config.xml, or if the user indicates the argument are out of date, this class tries to parse new ones. */
+public class BuildOptions {
+	 /** The root element of the build argument tree. */
+	 private Element build_arguments_element;
+	 /** The root element of the build values tree. */
+	 private Element build_values_element;
+	 /** The root element of the import argument tree. */
+	 private Element import_arguments_element;
+	 /** The root element of the import values tree. */
+	 private Element import_values_element;
+	 /** A cache of previously created build arguments. */
+	 private Hashtable build_arguments_cache = new Hashtable();
+	 /** A cache of previously created import arguments. */
+	 private Hashtable import_arguments_cache = new Hashtable();
+	 /** 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";
+	 /** When constructing a BuildOptions object we first try to retrieve the valid arguments from config.xml. If that fails we then try to parse the arguments noticed when calling import.pl -xml and buildcol.pl -xml. If that also fails, we load the default arguments from the xml template library. */
+	 public BuildOptions(Element build_values_element, Element import_values_element) {
+		  // Try to retrieve the arguments for import and build.
+		  build_arguments_element = Gatherer.config.getArguments("buildcol.pl");
+		  import_arguments_element = Gatherer.config.getArguments("import.pl");
+		  // If that fails try to reconstruct the arguments
+		  if(build_arguments_element == null || import_arguments_element == null) {
+				build_arguments_element = loadArguments("buildcol.pl");
+				import_arguments_element = loadArguments("import.pl");
+				// And if that too fails, load the default argument templates
+				if(build_arguments_element == null || import_arguments_element == null) {
+					 Document build_document = Utility.parse("xml" + File.separator + "buildcol.xml", true);
+					 build_arguments_element = build_document.getDocumentElement();
+					 build_document = null;
+					 Document import_document = Utility.parse("xml" + File.separator + "import.xml", true);
+					 import_arguments_element = import_document.getDocumentElement();
+					 import_document = null;
+					 ///atherer.println("Loaded default BO arguments from templates.");
+				}
+				else {
+					 ///atherer.println("Loaded BO arguments from scripts.");
+				}
+				// By now we should definately have the arguments. However the reason we are here is because they are not stored in the config.xml file, to make sure they are stored now.
+				Gatherer.config.setArguments(build_arguments_element);
+				Gatherer.config.setArguments(import_arguments_element);
+		  }
+		  else {
+				Gatherer.println("Loaded BO arguments from config.xml");
+		  }
+		  // Now take a note of the values too.
+		  this.build_values_element = build_values_element;
+		  this.import_values_element = import_values_element;
+	 }
+
+	 /** Retrieve the arguments associated with a certain type of action, ie import or build. */
+	 public String[] getArguments(boolean build) {
+		  String arguments[] = null;
+		  NodeList argument_list = null;
+		  if(build) {
+				argument_list = build_values_element.getElementsByTagName(ARGUMENT);
+		  }
+		  else {
+				argument_list = import_values_element.getElementsByTagName(ARGUMENT);
+		  }
+		  for(int i = 0; i < argument_list.getLength(); i++) {
+				String[] temp = new String[2];
+				Element argument = (Element) argument_list.item(i);
+				ArrayTools.add(arguments, argument.getAttribute(NAME));
+				String value = MSMUtils.getValue(argument);
+				if(value != null && value.length() > 0) {
+					 ArrayTools.add(arguments, value);
+				}
+		  }
+		  return arguments;
+	 }
+
+	 /** Retrieve the indexth argument belonging to build. */
+	 public Argument getBuildArgument(int index) {
+		  Argument argument = null;
+		  // Try to find the argument in the cache.
+		  SoftReference reference = (SoftReference) build_arguments_cache.get(new Integer(index));
+		  if(reference != null) {
+				argument = (Argument) reference.get();
+		  }
+		  // Otherwise generate a new argument.
+		  if(argument == null) {
+				argument = getArgument(build_arguments_element, index);
+		  }
+		  return argument;
+	 }
+
+	 /** Retrieve the number of arguments involved in building. */
+	 public int getBuildArgumentCount() {
+		  NodeList build_options = build_arguments_element.getElementsByTagName(OPTION);
+		  return build_options.getLength();
+	 }
+
+	 /** Retrieve the value of a certain build argument. */
+	 public String getBuildValue(String name) {
+		  return getValue(build_values_element, name, false);
+	 }
+
+	 /** Determine if the named argument value is enabled or disabled. */
+	 public boolean getBuildValueEnabled(String name) {
+		  boolean result = false;
+		  String value = getValue(build_values_element, name, true);
+		  if(value != null && value.length() > 0) {
+				result = (value.equalsIgnoreCase(TRUE));
+		  }
+		  return result;
+	 }
+
+	 /** Retrieve all of the build values as a String array ready to added to the buildcol.pl call. */
+	 public String[] getBuildValues() {
+		  return getValues(build_values_element);
+	 }
+
+	 /** Retrieve the indexth argument belonging to import. */
+	 public Argument getImportArgument(int index) {
+		  Argument argument = null;
+		  // Try to find the argument in the cache.
+		  SoftReference reference = (SoftReference) import_arguments_cache.get(new Integer(index));
+		  if(reference != null) {
+				argument = (Argument) reference.get();
+		  }
+		  // Otherwise generate a new argument.
+		  if(argument == null) {
+				argument = getArgument(import_arguments_element, index);
+		  }
+		  return argument;
+	 }
+
+	 /** Retrieve the number of arguments involved in importing. */
+	 public int getImportArgumentCount() {
+		  NodeList import_options = import_arguments_element.getElementsByTagName(OPTION);
+		  return import_options.getLength();
+	 }
+
+	 /** Retrieve the value of a certain build argument. */
+	 public String getImportValue(String name) {
+		  return getValue(import_values_element, name, false);
+	 }
+
+	 /** Determine if the named argument value is enabled or disabled. */
+	 public boolean getImportValueEnabled(String name) {
+		  boolean result = false;
+		  String value = getValue(import_values_element, name, true);
+		  if(value != null && value.length() > 0) {
+				result = (value.equalsIgnoreCase(TRUE));
+		  }
+		  return result;
+	 }
+
+	 /** Retrieve all of the import arguments in a form ready to be sent out to a shell process. */
+	 public String[] getImportValues() {
+		  return getValues(import_values_element);
+	 }
+
+	 /** Set the value of a build argument. */
+	 public void setBuildValue(String name, boolean enable, String value) {
+		  setValue(build_values_element, name, enable, value);
+	 }
+
+	 /** Set the value of a build argument. */
+	 public void setImportValue(String name, boolean enable, String value) {
+		  setValue(import_values_element, name, enable, value);
+	 }	 
+
+	 /** Remove the given build value. */
+	 public void removeBuildValue(String name) {
+		  removeValue(build_values_element, name);
+	 }
+
+	 /** Remove the given import value. */
+	 public void removeImportValue(String name) {
+		  removeValue(import_values_element, name);
+	 }
+
+	 /** Retrieve the indexth element from the given set of arguments. */
+	 private Argument getArgument(Element arguments_element, int index) {
+		  Argument argument = null;
+		  try {
+				NodeList option_list = arguments_element.getElementsByTagName(OPTION);
+				if(0 <= index && index < option_list.getLength()) {
+					 // Retrieve the appropriate argument
+					 Element option = (Element) option_list.item(index);
+					 // Iterate through this option elements children, making note of any details we find.
+					 argument = new Argument();
+					 for(Node node = option.getFirstChild(); node != null; node = node.getNextSibling()) {
+						  String node_name = node.getNodeName();
+						  if(node_name.equals("Name")) {
+								argument.setName(MSMUtils.getValue(node));
+						  }
+						  else if(node_name.equals("Desc")) {
+								argument.setDesc(MSMUtils.getValue(node));
+						  }
+						  else if(node_name.equals("Type")) {
+								argument.setType(MSMUtils.getValue(node));
+						  }
+						  else if(node_name.equals("Default")) {
+								argument.setDefault(MSMUtils.getValue(node));
+						  }
+						  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 = MSMUtils.getValue(subvalue);
+												}
+												else if(node_name.equals("Desc")) {
+													 desc = MSMUtils.getValue(subvalue);
+												}
+										  }
+										  if(key != null) {
+												argument.addOption(key, desc);
+										  }
+									 }
+								}
+						  }
+						  else if(node_name.equals("Required")) {
+								String v = MSMUtils.getValue(node);
+								if(v != null && v.equals("yes")) {
+									 argument.setRequired(true);
+								}
+						  }
+					 }
+				}
+		  }
+		  catch (Exception error) {
+				Gatherer.println("Error in BuildOptions.getArgument(): " + error);
+				Gatherer.printStackTrace(error);
+		  }
+		  return argument;
+	 }
+
+	 private String getValue(Element arguments_element, String name, boolean is_enabled) {
+		  String result = null;
+		  try {
+				NodeList arguments = arguments_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 = MSMUtils.getValue(argument_element);
+								if(argument_value != null) {
+									 result = argument_value;
+								}
+								argument_value = null;
+						  }
+					 }
+					 argument_element = null;
+				}
+				arguments = null;
+		  }
+		  catch (Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+		  return result;
+	 }
+
+	 private String[] getValues(Element arguments_element) {
+		  ArrayList values = new ArrayList();
+		  try {
+				NodeList arguments = arguments_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 = MSMUtils.getValue(argument_element);
+						  // 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) {
+				Gatherer.printStackTrace(error);
+		  }
+		  return ArrayTools.arrayListToStringArray(values);
+	 }
+
+	 private Element loadArguments(String filename) {
+		  Element arguments_element = null;
+		  // Run the required program.
+		  /** @todo - I never finished implementing this. Have to test that the perl script handles being loaded in this way.
+		  try {
+				String args[] = new String[3];
+				args[0] = Gatherer.config.perl_path;
+				args[1] = filename;
+				args[2] = "-xml";
+				// Create the process.
+				Runtime runtime = Runtime.getRuntime();
+				Process process = runtime.exec(args);
+				//InputStream input_stream = process.getErrorStream();
+				InputSource source = new InputSource(new InputStreamReader(process.getErrorStream()));
+				DOMParser parser = new DOMParser();
+				parser.parse(source);
+				Document document = parser.getDocument();
+				arguments_element = document.getDocumentElement();
+		  }
+		  catch (Exception error) {
+				Gatherer.println("Error in BuildOptions.loadArguments(): " + error);
+				Gatherer.printStackTrace(error);
+		  }
+		  */
+		  return arguments_element;
+	 }
+
+	 /** Set the state of some build or import argument. Note that value may be either a single String, and ArrayList of Strings or null. If enable is false then any existing argument for the named argument is disabled. */
+	 public void setValue(Element arguments_element, String name, boolean enable, String value) {
+		  ///ystem.err.println("Set value: " + (arguments_element == build_values_element ? "Build" : "Import") + ", " + name + ", " + enable + ", " + value);
+		  try {
+				Document document = arguments_element.getOwnerDocument();
+				NodeList arguments = arguments_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));
+					 }
+					 arguments_element.appendChild(argument_element);
+				}
+				arguments = null;
+				document = null;
+				// Make sure the collection knows to save.
+				Gatherer.c_man.getCollection().setSaved(false);
+		  }
+		  catch (Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+	 }
+
+	 /** Remove the named value from the given arguments element. */
+	 private void removeValue(Element arguments_element, String name) {
+		  try {
+				NodeList arguments = arguments_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)) {
+						  arguments_element.removeChild(argument_element);
+						  found = true;
+					 }
+					 argument_element = null;
+				}
+				arguments = null;
+		  }
+		  catch (Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/collection/Collection.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/collection/Collection.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/collection/Collection.java	(revision 13666)
@@ -0,0 +1,442 @@
+package org.greenstone.gatherer.collection;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.collection.BuildOptions;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.GDMManager;
+import org.greenstone.gatherer.msm.MetadataSetManager;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.greenstone.gatherer.util.Utility;
+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 BuildOptions. */
+	 public BuildOptions build_options;
+	 /** A reference to the Collection Design Manager. */
+	 public CollectionDesignManager cdm;
+	 /** A reference to the Greenstone Directory Metadata Manager. */
+	 public GDMManager gdm;
+	 /** A reference to the Metadata Set Manager. */
+	 public MetadataSetManager msm;
+	 /** <i>true</i> if the currently loaded collection has been saved since the last significant change, <i>false</i> otherwise. */
+	 private boolean saved = false;
+	 /** The collectio configuration file for this collection. */
+	 private CollectionConfiguration collect_cfg;
+	 /** 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";
+	 /** The name of the build element. */
+	 static final private String BUILD = "Build";
+	 /** The name of the built attribute. */
+	 static final private String BUILT = "built";
+	 /** 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" + File.separator + "template.col";
+	 /** The name of the directory mappings element. */
+	 static final private String DIRECTORY_MAPPINGS = "DirectoryMappings";
+	 /** The name of the file attribute. */
+	 static final private String FILE = "file";
+	 /** 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 mapping element. */
+	 static final private String MAPPING = "Mapping";
+	 /** The name of the name attribute. */
+	 static final private String NAME = "name";
+	 /** The name of the true value. */
+	 static final private String TRUE = "true";
+	 /** Constructor. */
+	 public Collection(File collection_xml) {
+		  this.file = collection_xml;
+		  // Try to load this collections details.
+		  document = Utility.parse(collection_xml, false);
+		  // If that fails load the default settings for a collection.
+		  if(document == null) {
+				document = Utility.parse(COLLECTION_XML_TEMPLATE, true);
+		  }
+		  // Point the Configuration class at our gatherer config arguments.
+		  Gatherer.config.setCollectionConfiguration(document);
+		  // We also attempt to parse the collection configuration file.
+		  collect_cfg = new CollectionConfiguration(new File(collection_xml.getParentFile(), Utility.CONFIG_DIR));
+		  // Finally create all of the child managers that are directly dependant on a collection
+		  build_options = new BuildOptions(getBuildValues(), getImportValues());		  
+	 }
+	 /** Add a special directory mapping. */
+	 public boolean addDirectoryMapping(String name, File file) {
+		  boolean result = false;
+		  try {
+				Element document_element = document.getDocumentElement();
+				Element directory_mappings_element = (Element) MSMUtils.getNodeFromNamed(document_element, DIRECTORY_MAPPINGS);
+				// Ensure the name isn't already in use.
+				boolean found = false;
+				NodeList mappings = directory_mappings_element.getElementsByTagName(MAPPING);
+				for(int i = 0; !found && i < mappings.getLength(); i++) {
+					 Element mapping_element = (Element) mappings.item(i);
+					 if(mapping_element.getAttribute(NAME).equalsIgnoreCase(name)) {
+						  found = true;
+					 }
+					 mapping_element = null;
+				}
+				// Otherwise add the mapping.
+				if(!found) {
+					 Element mapping_element = document.createElement(MAPPING);
+					 mapping_element.setAttribute(NAME, name);
+					 mapping_element.setAttribute(FILE, file.toString());
+					 directory_mappings_element.appendChild(mapping_element);
+					 result = true;
+					 mapping_element = null;
+				}
+				mappings = null;
+				directory_mappings_element = null;
+				document_element = null;
+				saved = false;
+		  }
+		  catch (Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+		  return result;
+	 }
+
+	 /** Destructor. 
+	  * @see org.greenstone.gatherer.collection.CollectionModel */
+	 public void destroy() {
+		  cdm.destroy();
+		  gdm.destroy();
+		  msm.destroy();
+		  Gatherer.config.setCollectionConfiguration(null);
+		  cdm = null;
+		  document = null;
+		  gdm = null;
+		  msm = null;
+	 }
+	 /** Determine whether this collection has been successfully built in the past.
+	  * @return <i>true</i> if the collection has been built, <i>false</i> otherwise.
+	  */
+	 public boolean getBuilt() {
+		  return get(BUILT);
+	 }
+	 /** Calculates the number of documents in this collection. */
+	 public int getDocumentCount() {
+		  return getCount((TreeNode)Gatherer.c_man.getRecordSet().getRoot(), false);
+	 }
+	 /** Retrieve the description of this collection.
+	  * @return The description as a <strong>String</strong>.
+	  */
+	 public String getDescription() {
+		  return collect_cfg.getDescription();
+	 }
+	 /** Retrieve a specific directory mapping associated with this collection.
+	  * @param name The name of the mapping to retrieve as a <strong>String</strong>.
+	  * @return The <strong>File</strong> this name maps to, or <i>null</i> if no such mapping.
+	  */
+	 public File getDirectoryMapping(String name) {
+		  File result = null;
+		  try {
+				Element document_element = document.getDocumentElement();
+				Element directory_mappings_element = (Element) MSMUtils.getNodeFromNamed(document_element, DIRECTORY_MAPPINGS);
+				// Ensure the name isn't already in use.
+				boolean found = false;
+				NodeList mappings = directory_mappings_element.getElementsByTagName(MAPPING);
+				for(int i = 0; !found && i < mappings.getLength(); i++) {
+					 Element mapping_element = (Element) mappings.item(i);
+					 if(mapping_element.getAttribute(NAME).equalsIgnoreCase(name)) {
+						  result = new File(MSMUtils.getValue(mapping_element));
+						  found = true;
+					 }
+					 mapping_element = null;
+				}
+				mappings = null;
+				directory_mappings_element = null;
+				document_element = null;
+		  }
+		  catch(Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+		  return result;
+	 }
+	 /** Retrieve the special directory mappings associated with this collection.
+	  * @return A <strong>HashMap</strong> containing mappings from names to directories.
+	  */
+	 public HashMap getDirectoryMappings() {
+		  HashMap special_directories = new HashMap();
+		  try {
+				Element document_element = document.getDocumentElement();
+				Element directory_mappings_element = (Element) MSMUtils.getNodeFromNamed(document_element, DIRECTORY_MAPPINGS);
+				// Ensure the name isn't already in use.
+				boolean found = false;
+				NodeList mappings = directory_mappings_element.getElementsByTagName(MAPPING);
+				for(int i = 0; !found && i < mappings.getLength(); i++) {
+					 Element mapping_element = (Element) mappings.item(i);
+					 String name = mapping_element.getAttribute(NAME);
+					 File file = new File(mapping_element.getAttribute(FILE));
+					 special_directories.put(name, file);
+					 file = null;
+					 name = null;
+					 mapping_element = null;
+				}
+				mappings = null;
+				directory_mappings_element = null;
+				document_element = null;
+		  }
+		  catch(Exception error) {
+				Gatherer.printStackTrace(error);
+		  }		  
+		  return special_directories;
+	 }
+	 /** Retrieve the authors email for this collection.
+	  * @return The email as a <strong>String</strong>.
+	  */
+	 public String getEmail() {
+		  return collect_cfg.getCreator();
+	 }
+	 /** Counts the number of folders used in the current record set. */
+	 public int getFolderCount() {
+		  return getCount((TreeNode)Gatherer.c_man.getRecordSet().getRoot(), true);
+	 }
+	 /** Determine if this collection has had an import action run upon it since the last major change.
+	  * @return <i>true</i> if an import has occured, <i>false</i> otherwise.
+	  */
+	 public boolean getImported() {
+		  return get(IMPORTED);
+	 }
+	 /** 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;
+	 }
+	 /** Retrieve the title of this collection.
+	  * @return The title as a <strong>String</strong>.
+	  */
+	 public String getTitle() {
+		  return collect_cfg.getName();
+	 }
+	 /** 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.
+	  */
+	 public File removeDirectoryMapping(String name) {
+		  File file = null;
+		  try {
+				Element document_element = document.getDocumentElement();
+				Element directory_mappings_element = (Element) MSMUtils.getNodeFromNamed(document_element, DIRECTORY_MAPPINGS);
+				// Ensure the name isn't already in use.
+				boolean found = false;
+				NodeList mappings = directory_mappings_element.getElementsByTagName(MAPPING);
+				for(int i = 0; !found && i < mappings.getLength(); i++) {
+					 Element mapping_element = (Element) mappings.item(i);
+					 if(mapping_element.getAttribute(NAME).equalsIgnoreCase(name)) {
+						  file = new File(MSMUtils.getValue(mapping_element));
+						  directory_mappings_element.removeChild(mapping_element);
+						  found = true;
+					 }
+					 mapping_element = null;
+				}
+				mappings = null;
+				directory_mappings_element = null;
+				document_element = null;
+				saved = false;
+		  }
+		  catch(Exception error) {
+				Gatherer.printStackTrace(error);
+		  }	
+		  return file;
+	 }
+	 /** Save this xml document to the given file. */
+	 public void save() {
+		  Utility.export(document, file);
+	 }
+	 /** Set the value of built to the given value.
+	  * @param value The new value for built, <i>true</i> if the collection has been built successfully, <i>false</i> otherwise.
+	  */
+	 public void setBuilt(boolean value) {
+		  set(BUILT, value);
+		  saved = false;
+	 }
+	 /** 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) {
+		  collect_cfg.setName(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 collect_cfg.getName();
+	 }
+	 /** 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(NAME).equalsIgnoreCase(BUILT)) {
+								String value = MSMUtils.getValue(argument_element);
+								if(value.equalsIgnoreCase(TRUE)) {
+									 result = true;
+								}
+								found = true;
+								value = null;
+						  }
+					 }
+					 argument_element = null;
+				}
+				arguments = null;
+				document_element = null;
+		  }
+		  catch (Exception error) {
+				Gatherer.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) MSMUtils.getNodeFromNamed(document_element, BUILD_CONFIG);
+				build_values_element = (Element) MSMUtils.getNodeFromNamed(build_config_element, BUILD);
+				build_config_element = null;
+				document_element = null;
+		  }
+		  catch (Exception error) {
+				Gatherer.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 folders) {
+		  int count = 0;
+		  File file = ((FileNode)node).getFile();
+		  if(file.isFile() && !folders) {
+				count++;
+		  }
+		  else if(file.isDirectory() && folders) {
+				count++;
+		  }
+		  for(int i = 0; i < node.getChildCount(); i++) {
+				count = count + getCount(node.getChildAt(i), folders);
+		  }
+		  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) MSMUtils.getNodeFromNamed(document_element, BUILD_CONFIG);
+				import_values_element = (Element) MSMUtils.getNodeFromNamed(build_config_element, IMPORT);
+				build_config_element = null;
+				document_element = null;
+		  }
+		  catch (Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+		  return import_values_element;
+	 }
+
+	 /** Set the value of a collection argument. */
+	 private void set(String name, boolean 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(NAME).equalsIgnoreCase(BUILT)) {
+								// Strip any current value nodes.
+								while(argument_element.hasChildNodes()) {
+									 argument_element.removeChild(argument_element.getFirstChild());
+								}
+								// Append new value
+								argument_element.appendChild(document.createTextNode(value ? "true" : "false"));
+						  }
+					 }
+					 argument_element = null;
+				}
+				arguments = null;
+				document_element = null;
+		  }
+		  catch (Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/collection/CollectionConfiguration.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/collection/CollectionConfiguration.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/collection/CollectionConfiguration.java	(revision 13666)
@@ -0,0 +1,158 @@
+package org.greenstone.gatherer.collection;
+
+import java.io.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.CommandTokenizer;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.greenstone.gatherer.util.Utility;
+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 CollectionConfiguration {
+
+	 private Element creator_element;
+	 private Element description_element;
+	 private Element maintainer_element;
+	 private Element name_element;
+	 private String creator;
+	 private String description;
+	 private String maintainer;
+	 private String name;
+
+	 public CollectionConfiguration(File file) {
+		  try {
+				String filename = file.getName().toLowerCase();
+				if(filename.endsWith(".xml")) {
+					 
+				}
+				else if(filename.endsWith(".cfg")) {
+					 FileReader fr = new FileReader(file);
+					 BufferedReader br = new BufferedReader(fr);
+					 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 + next_line;
+									 }
+									 next_line = null;
+								}
+								CommandTokenizer tokenizer = new CommandTokenizer(command);
+								if(tokenizer.countTokens() >= 2) {
+									 String temp = tokenizer.nextToken();
+									 if(temp.equalsIgnoreCase("creator")) {
+										  creator = tokenizer.nextToken();
+									 }
+									 else if(temp.equalsIgnoreCase("maintainer")) {
+										  maintainer = tokenizer.nextToken();
+									 }
+									 else if(temp.equalsIgnoreCase("collectionmeta")) {
+										  temp = tokenizer.nextToken();
+										  if(temp.equalsIgnoreCase("collectionname")) {
+												temp = tokenizer.nextToken();
+												if(temp.startsWith("[") && temp.endsWith("]")) {
+													 String language = temp.substring(temp.indexOf("=") + 1, temp.length() - 1);
+													 if(name == null || language.equalsIgnoreCase(Gatherer.dictionary.getLanguage())) {
+														  name = Utility.decodeGreenstone(tokenizer.nextToken()); 
+													 }
+												}
+												else if(name == null) {
+													 name = Utility.decodeGreenstone(temp);
+												}
+												if(name != null && name.startsWith("\"") && name.endsWith("\"")) {
+													 name = name.substring(1, name.length() - 1);
+												}
+										  }
+										  else if(temp.equalsIgnoreCase("collectionextra")) {
+												temp = tokenizer.nextToken();
+												///ystem.err.println("Read: " + temp);
+												if(temp.startsWith("[") && temp.endsWith("]")) {
+													 String language = temp.substring(temp.indexOf("=") + 1, temp.length() - 1);
+													 ///ystem.err.println("Try to match " + language + " to " + Gatherer.dictionary.getLanguage());
+													 if(description == null || language.equalsIgnoreCase(Gatherer.dictionary.getLanguage())) {
+														  description = Utility.decodeGreenstone(tokenizer.nextToken());
+														  ///ystem.err.println("Found language match, or first match: " + description);
+													 }
+												}
+												else if(description == null) {
+													 description = Utility.decodeGreenstone(temp);
+													 ///ystem.err.println("Found first match: " + description);
+												}
+												if(description != null && description.startsWith("\"") && description.endsWith("\"")) {
+													 description = description.substring(1, description.length() - 1);
+												}
+										  }
+									 }
+									 temp = null;
+								}
+								tokenizer = null;
+						  }
+					 }
+					 command = null;
+					 br.close();
+					 br = null;
+					 fr.close();
+					 fr = null;
+				}
+				///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) {
+				Gatherer.println("Error in CollectionConfiguration.<init>(): " + error);
+				Gatherer.printStackTrace(error);
+		  }
+	 }
+
+	 public String getCreator() {
+		  String result = "";
+		  if(creator_element != null) {
+				result = MSMUtils.getValue(creator_element);
+		  }
+		  else if(creator != null) {
+				result = creator;
+		  }
+		  return result;
+	 }
+
+	 public String getDescription() {
+		  String result = "";
+		  if(description_element != null) {
+				result = MSMUtils.getValue(description_element);
+		  }
+		  else if(description != null) {
+				result = description;
+		  }
+		  return result;
+	 }
+
+	 public String getMaintainer() {
+		  String result = "";
+		  if(maintainer_element != null) {
+				result = MSMUtils.getValue(maintainer_element);
+		  }
+		  else if(maintainer != null) {
+				result = maintainer;
+		  }
+		  return result;
+	 }
+
+	 public String getName() {
+		  String result = "Error";
+		  if(name_element != null) {
+				result = MSMUtils.getValue(name_element);
+		  }
+		  else if(name != null) {
+				result = name;
+		  }
+		  return result;
+	 }
+
+	 public void setName(String name) {
+		  /** @todo */
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/collection/CollectionManager.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/collection/CollectionManager.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/collection/CollectionManager.java	(revision 13666)
@@ -0,0 +1,1176 @@
+package org.greenstone.gatherer.collection;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.io.*;
+import java.lang.Class;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.Message;
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.cdm.CommandTokenizer;
+import org.greenstone.gatherer.collection.Collection;
+import org.greenstone.gatherer.collection.SaveCollectionTask;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.file.FileSystemModel;
+import org.greenstone.gatherer.gui.LockFileDialog;
+import org.greenstone.gatherer.gui.MetaEditPane;
+import org.greenstone.gatherer.gui.NewCollectionMetadataPrompt;
+import org.greenstone.gatherer.msm.GDMManager;
+import org.greenstone.gatherer.msm.MetadataSet;
+import org.greenstone.gatherer.msm.MetadataSetManager;
+import org.greenstone.gatherer.msm.MSMEvent;
+import org.greenstone.gatherer.msm.MSMListener;
+import org.greenstone.gatherer.msm.MSMProfiler;
+import org.greenstone.gatherer.msm.MSMUtils;
+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.undo.UndoManager;
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.MetadataXML;
+import org.greenstone.gatherer.util.SynchronizedTreeModelTools;
+import org.greenstone.gatherer.util.Utility;
+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, MSMListener {
+	 /** A reference to the metadata set manager.
+	  * @deprecated
+	  */
+	 public MetadataSetManager msm;
+	 /** A reference to the undo manager. Although only one instance is shared between all collections, the undo queues are emptied between each. */
+	 public UndoManager undo;
+	 /** Are we currently in the process of building? */
+	 private boolean building = false;
+	 /** Are we currently in the process of importing? */
+	 private boolean importing = false;
+	 /** The collection this manager is managing! */
+	 private Collection collection = null;
+	 /** An inner class listener responsible for noting tree changes and resetting saved when they occur. */
+	 private FMTreeModelListener fm_tree_model_listener = null;
+	 /** The monitor resposible for parsing the build process. */
+	 private GShellProgressMonitor build_monitor = null;
+	 /** The monitor resposible for parsing the copy process. */
+	 private GShellProgressMonitor copy_monitor = null;
+	 /** The monitor resposible for parsing the import process. */
+	 private GShellProgressMonitor import_monitor = null;
+	 /** The collection_model. */
+	 private FileSystemModel collection_model = null;
+	 /** The workspace model. This becomes invalid on a collection change. */
+	 private FileSystemModel workspace_model = null;
+	 /** The name of the standard lock file. */
+	 static final public String LOCK_FILE = "gatherer.lck";
+	 /** Constructor. */
+	 public CollectionManager() {
+		  // Initialisation.
+		  this.building = false;
+		  this.importing = false;
+		  this.collection = null;
+		  this.undo = new UndoManager();
+	 }
+	 /** Add a special directory mapping.
+	  * @param name The name for this directory mapping as a <strong>String</strong>.
+	  * @param file The directory this mapping maps to as a <strong>File</strong>.
+	  */
+	 public void addDirectoryMapping(String name, File file) {
+		  if(ready()) {
+				// Update the information stored in the collection
+				collection.addDirectoryMapping(name, file);
+				// Now update the tree
+				FileSystemModel model = (FileSystemModel) Gatherer.g_man.collection_pane.getWorkspaceTree().getModel();
+				FileNode parent = (FileNode) model.getRoot();
+				FileNode target = new FileNode(file, name);
+				SynchronizedTreeModelTools.insertNodeInto(model, parent, target);
+		  }
+	 }
+	 /** 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.Message
+	  * @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() {
+		  Gatherer.println("Building collection");
+		  building = true;
+
+		  String args[];
+		  if(Utility.isWindows()) {
+		      args = new String[4];
+				args[0] = Gatherer.config.perl_path;
+		      args[1] = "-S";
+		      args[2] = Gatherer.config.getScriptPath() + "buildcol.pl";
+		      args[3] = collection.getName();
+		  }
+		  else {
+		      args = new String[2];
+		      args[0] = Gatherer.config.getScriptPath() + "buildcol.pl";
+		      args[1] = collection.getName();
+		  }
+		  args = ArrayTools.add(args, collection.build_options.getBuildValues());
+		  GShell shell = new GShell(args, GShell.BUILD, Message.BUILDING, this, build_monitor, GShell.GSHELL_BUILD);
+		  shell.addGShellListener(Gatherer.g_man.create_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) {
+				return collection.getBuilt();
+		  }
+		  return false;
+	 }
+	 /** 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() {
+		  // Remove the lock on this file, then remove the collection.
+		  File lock_file = new File(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator + LOCK_FILE);
+		  lock_file.delete();
+		  collection.msm.destroy();
+		  collection = null;
+		  collection_model = null;
+		  workspace_model = null;
+		  undo.clear();
+		  Gatherer.config.setCollectionConfiguration(null);
+		  Gatherer.g_man.collectionChanged(false);
+	 }
+
+	 /** Method that is called whenever something has changed in the configuration of this collection. */
+	 public void configurationChanged() {
+		  if(collection != null) {
+				collection.setSaved(false);
+		  }
+	 }
+
+	 /** 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 colection 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. */
+	 public void createCollection(String description, String email, String name, String title, File base_collection_directory, ArrayList metadata_sets) {
+		  try {
+				// Create a progress monitor.
+				ProgressMonitor progress = new ProgressMonitor(Gatherer.g_man, get("Creating_New"), "mkcol.pl", 0, 7);
+				// Create the new collection.
+				makeCollection(description, email, name, title);
+				progress.setProgress(1);
+ 
+				// ACTIVE_DIR/gimport/
+				String a_dir = Utility.getCollectionDir(Gatherer.config.gsdl_path) + name + File.separator;
+				
+				// Has to be done before creating greenstone directory metadata manager.
+				File gimport_dir_temp = new File(Utility.getImportDir(a_dir)+"temp.dat");
+				File gimport_dir = gimport_dir_temp.getParentFile();
+				gimport_dir.mkdirs();
+				if(progress != null) {
+					 progress.setNote(get("Gimport_Created"));
+				}
+				
+				File gcache_dir_temp = new File(Utility.getCacheDir(a_dir)+"temp.dat");
+				File gcache_dir = gcache_dir_temp.getParentFile();
+				gcache_dir.mkdirs();
+				if(progress != null) {
+					 progress.setNote(get("Gcache_Created"));
+				}
+				
+				progress.setProgress(2);
+
+				// Now create the collection object around the directory.
+				collection = new Collection(new File(a_dir, name + ".col"));
+				collection.msm = new MetadataSetManager();
+				msm = collection.msm; // Legacy
+				collection.msm.load();
+				// Import default metadata sets if any.
+				for(int i = 0; metadata_sets != null && i < metadata_sets.size(); i++) {
+					 MetadataSet metadata_set = (MetadataSet) metadata_sets.get(i);
+					 collection.msm.importMDS(metadata_set.getFile(), false);
+				}
+
+				// Before we create the CollectionDesignManager we have to check if we are basing it upon some other collection.
+				if(base_collection_directory != null) {
+					 // If so our first step is to correctly generate an import profile for our collection from this base collection.
+					 // 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 = new File(base_collection_directory, Utility.METADATA_DIR);
+					 if(base_metadata.exists()) {
+						  File[] possible_metadata_sets = base_metadata.listFiles();
+						  for(int i = 0; possible_metadata_sets != null && i < possible_metadata_sets.length; i++) {
+								String filename = possible_metadata_sets[i].getName();
+								if(filename.endsWith(".mds")) {
+									 ///ystem.err.println("Found a metadata set. Importing: " + possible_metadata_sets[i].getAbsolutePath());
+									 collection.msm.importMDS(possible_metadata_sets[i], false);
+								}									
+						  }
+					 }
+					 // If no sets were imported, then create a new metadata with this new collections name. Note that if this is one of the 'big five' collections then I already know the importing mappings as well.
+					 boolean skip_import_phase = false;
+					 if(collection.msm.getSets().size() == 0) {
+						  CollectionConfiguration col_con = new CollectionConfiguration(new File(base_collection_directory, Utility.CONFIG_DIR));
+						  // If the source collection is one of the 'big five' then we know what the metadata set is.
+						  String collection_name = col_con.getName();
+						  if(collection_name.equals(Utility.COLLECTION_DLS)) {
+								// Add the dls.mds
+								collection.msm.importMDS(new File(Utility.METADATA_DIR + Utility.DLS_MDS), false);
+								// Add the mappings
+								collection.msm.profiler.addAction(base_collection_directory.getAbsolutePath(), "AZList", "dls.AZList");
+								collection.msm.profiler.addAction(base_collection_directory.getAbsolutePath(), "Keyword", "dls.Keyword");
+								collection.msm.profiler.addAction(base_collection_directory.getAbsolutePath(), "Language", "dls.Language");
+								collection.msm.profiler.addAction(base_collection_directory.getAbsolutePath(), "Organization", "dls.Organization");
+								collection.msm.profiler.addAction(base_collection_directory.getAbsolutePath(), "Subject", "dls.Subject");
+								collection.msm.profiler.addAction(base_collection_directory.getAbsolutePath(), "Title", "dls.Title");
+								// Skip the import phase
+								skip_import_phase = true;
+						  }
+						  // Prompt the user so that they can choose at least one initial metadata set. We're sneaky here and just create a ncm_prompt
+						  else {
+								NewCollectionMetadataPrompt ncm_prompt = new NewCollectionMetadataPrompt();
+								// If cancelled then they really do mean to start a collection with no metadata sets.
+								if(!ncm_prompt.isCancelled()) {
+									 ArrayList initial_sets = ncm_prompt.getSets();
+									 for(int i = 0; initial_sets != null && i < initial_sets.size(); i++) {
+										  MetadataSet metadata_set = (MetadataSet) initial_sets.get(i);
+										  collection.msm.importMDS(metadata_set.getFile(), false);
+										  metadata_set = null;
+									 }
+									 initial_sets = null;
+								}
+								ncm_prompt.dispose();
+								ncm_prompt = null;
+						  }
+					 }
+					 // Do a dry metadata import run over the entire base collection, recording profile mappings. We do this by finding the archive files, and then iterating over them using the GreenstoneArchiveParser to retrieve metadata from them. We then process the importing of new metadata elements using the selectElement prompt used in a file action metadata import. However the big change is that we don't actually import any metadata, just create importing profiles.
+					 File base_archives = new File(base_collection_directory, Utility.ARCHIVE_DIR);
+					 if(!skip_import_phase && base_archives.exists()) {
+						  ///ystem.err.println("Found archives directory.");
+					 }
+					 // Failing that we do a dummy run over the files in the collection.
+					 else if(!skip_import_phase) {
+						  ///ystem.err.println("No archives directory. Searching files for metadata.xml information.");
+						  // Find the import directory
+						  File base_import = new File(base_collection_directory, Utility.IMPORT_DIR);
+						  if(!base_import.exists()) {
+								base_import = new File(base_collection_directory, Utility.OLD_IMPORT_DIR);
+						  }
+						  if(base_import.exists()) {
+								searchForMetadata(base_import);
+						  }
+						  // And if that fails then we must have been asked by Satan himself to build the very digital collections of hell, because they don't match any goodly greenstone collection I have ever seen, so you can't blame me if I can't import them.
+					 }
+					 // Now we update our collect.cfg
+					 updateCollectionCFG(new File(base_collection_directory, Utility.CONFIG_DIR), new File(a_dir, Utility.CONFIG_DIR), description, email, title);
+				}
+
+				collection.cdm = new CollectionDesignManager();
+				collection.gdm = new GDMManager();
+				
+				progress.setProgress(3);
+
+				// Has to be done after creating metadata set manager.
+				File gmeta_dir_temp = new File(getCollectionMetadata()+"temp.dat");
+				File gmeta_dir = gmeta_dir_temp.getParentFile();
+				gmeta_dir.mkdirs();
+				if(progress != null) {
+					 progress.setNote("GMeta created");
+				}
+				progress.setProgress(4);
+
+				progress.setProgress(6);
+				// Register ourselves as being interested in what the msm has to say.
+				collection.msm.addMSMListener(this);
+				// Create a lock file.
+				File lock_file = new File(a_dir, LOCK_FILE);
+				FileOutputStream out = new FileOutputStream(lock_file);
+				out.write(LOCK_FILE.getBytes());
+				out.close();
+				out = null;
+				progress.setProgress(7);
+				String args[] = new String[1];
+				args[0] = name;
+				progress.setNote(get("Session_Ready", args));
+				progress.close();
+		  }
+		  catch (Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+		  // Done.
+		  if(Gatherer.g_man != null) {
+				workspace_model = null;
+				Gatherer.g_man.collectionChanged(ready());
+		  }
+	 }
+
+	 public void createLockFile(File destination) {
+		  try {
+				Document default_lockfile = Utility.parse("xml" + File.separator + LOCK_FILE, true);
+				String user_name = System.getProperty("user.name");
+				Element person_element = (Element) MSMUtils.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) MSMUtils.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) MSMUtils.getNodeFromNamed(default_lockfile.getDocumentElement(), "Date");
+				date_element.appendChild(default_lockfile.createTextNode(date_time));
+				date_element = null;
+				date_time = null;
+				Utility.export(default_lockfile, destination);
+		  }
+		  catch (Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+	 }
+
+	 /** Method that is called whenever an element within a set is changed or modified. We want to mark the collection so that it needs saving again.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  * @see org.greenstone.gatherer.collection.Collection
+	  */
+	 public void elementChanged(MSMEvent event) {
+		  // This means the state of the collections has changed, so we should set saved to false.
+		  collection.setSaved(false);
+	 }
+	 /** Used to retrieve the build options associated with the currently loaded collection. If none yet exist, default ones are created.
+	  * @return A <strong>BuildOptions</strong> object containing the build options for the current collection.
+	  * @see org.greenstone.gatherer.collection.Collection
+	  */
+	 public BuildOptions getBuildOptions() {
+		  return collection.build_options;
+	 }
+
+	 /** Retrieve the current collection.
+	  * @return The <strong>Collection</strong> itself.
+	  */
+	 public Collection getCollection() {
+		  return collection;
+	 }
+	 /** Constructs the absolute filename of the collection archive directory, which should resemble "$GSDLHOME/collect/&lt;col_name&gt;/archive/"
+	  * @return A <strong>String</strong> containing the filename.
+	  * @see org.greenstone.gatherer.Configuration
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.Collection
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public String getCollectionArchive() {
+		  return Utility.getArchiveDir(Gatherer.config.gsdl_path, collection.getName());
+	 }
+	 /** Constructs the absolute filename of the collection building directory, which should resemble "$GSDLHOME/collect/&lt;col_name&gt;/building/"
+	  * @return A <strong>String</strong> containing the filename.
+	  * @see org.greenstone.gatherer.Configuration
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.Collection
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public String getCollectionBuild() {
+		  return Utility.getBuildDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator);
+	 }
+	 /** Constructs the absolute filename of the collection cache directory, which should resemble "$GSDLHOME/collect/&lt;col_name&gt;/gcache/"
+	  * @return A <strong>String</strong> containing the filename.
+	  * @see org.greenstone.gatherer.Configuration
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.Collection
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public String getCollectionCache() {
+		  return Utility.getCacheDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator);
+	 }
+	 /** Constructs the absolute filename of the collection config file, which should resemble "$GSDLHOME/collect/&lt;col_name&gt;/etc/collect.cfg"
+	  * @return A <strong>String</strong> containing the filename.
+	  * @see org.greenstone.gatherer.Configuration
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.Collection
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public String getCollectionConfig() {
+		  return Utility.getConfigDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator);
+	 }
+
+	 /** Constructs the absolute filename of the collection directory, which should resemble "$GSDLHOME/collect/&lt;col_name&gt;"
+	  * @return A <strong>String</strong> containing the directory name.
+	  * @see org.greenstone.gatherer.Configuration
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.Collection
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public String getCollectionDirectory() {
+		  return Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator;
+	 }
+
+	 /** Constructs the absolute filename of the collection etc directory, which should resemble "$GSDLHOME/collect/&lt;col_name&gt;/etc/"
+	  * @return A <strong>String</strong> containing the filename.
+	  * @see org.greenstone.gatherer.Configuration
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.Collection
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public String getCollectionEtc() {
+		  return Utility.getEtcDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator);
+	 }
+	 /** Constructs the absolute filename of the collection file, which should resemble "$GSDLHOME/collect/&lt;col_name&gt;/&lt;col_name&gt;.col"
+	  * @return A <strong>String</strong> containing the filename.
+	  * @see org.greenstone.gatherer.Configuration
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.Collection
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public String getCollectionFilename() {
+		  return Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator + collection.getName() + ".col";
+	 }
+	 /** Constructs the absolute filename of the collection import directory, which should resemble "$GSDLHOME/collect/&lt;col_name&gt;/gimport/"
+	  * @return A <strong>String</strong> containing the filename.
+	  * @see org.greenstone.gatherer.Configuration
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.Collection
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public String getCollectionImport() {
+		  return Utility.getImportDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator);
+	 }
+	 /** Constructs the absolute filename of the collection index directory, which should resemble "$GSDLHOME/collect/&lt;col_name&gt;/index/"
+	  * @return A <strong>String</strong> containing the filename.
+	  * @see org.greenstone.gatherer.Configuration
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.Collection
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public String getCollectionIndex() {
+		  return Utility.getIndexDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator);
+	 }
+	 /** Constructs the absolute filename of the collection metadata directory, which should resemble "$GSDLHOME/collect/&lt;col_name&gt;/metadata/"
+	  * @return A <strong>String</strong> containing the filename.
+	  * @see org.greenstone.gatherer.Configuration
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.Collection
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public String getCollectionMetadata() {
+		  return Utility.getMetadataDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator);
+	 }
+
+	 public String getCollectionOldImport() {
+		  return Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator + Utility.OLD_IMPORT_DIR;
+	 }
+
+	 /** This method either returns the title of the current collection, or a placeholder string of 'No Collection'.
+	  * @return A <strong>String</strong> which represents what we wish to display for a collection title.
+	  * @see org.greenstone.gatherer.collection.Collection
+	  */
+	 public String getCollectionTitle() {
+		  if(collection != null) {
+				return collection.getTitle();
+		  }
+		  return get("Collection.No_Collection");
+	 }
+
+	 /** Retrieve the record set (tree model) associated with the current collection. */
+	 public TreeModel getRecordSet() {
+		  if(collection_model == null && collection != null) {
+				// Check if the gimport directory exists, and if so use it.
+				File gimport_directory = new File(getCollectionImport());
+				if(gimport_directory.exists()) {
+					 // Generate a new FileSystemModel based on the collection gimport directory.
+					 collection_model = new FileSystemModel(new FileNode(gimport_directory, false));
+				}
+				else {
+					 ///ystem.err.println("No gimport directory exists.");
+					 // Otherwise default to the import directory. If it doesn't exist, there aint much more I can do.
+					 // Generate a new FileSystemModel based on the collection import directory.
+					 collection_model = new FileSystemModel(new FileNode(new File(getCollectionOldImport()), false));
+				}
+				// Ensure that the manager is a change listener for the tree.
+				if(fm_tree_model_listener == null) {
+					 fm_tree_model_listener = new FMTreeModelListener();
+				}
+				collection_model.addTreeModelListener(fm_tree_model_listener);
+		  }
+		  return collection_model;
+	 }
+	 /** Create and return the model behind the workspace tree. Quite an extensive method, as it must first map known greenstone collections, then the local file system and finally any public or private download workspaces. */
+	 public TreeModel getWorkspace() {
+		  if(workspace_model != null) {
+				return workspace_model;
+		  }
+		  // Create the workspace tree.
+		  FileNode workspace_root = new FileNode("ABS_ROOT");
+		  workspace_model = new FileSystemModel(workspace_root);
+		  // Create and add Greenstone collections node.
+		  // Starting at the collection directory of gsdl...
+		  File start = new File(Utility.getCollectionDir(Gatherer.config.gsdl_path));
+		  FileNode world_root = new FileNode(get("Tree.World"));
+		  workspace_root.insert(world_root);
+		  // For each of the children directories, which are collections...
+		  File cols[] = start.listFiles();
+		  ArrayTools.sort(cols);
+		  // We add their import and gimport directories, but only if its not our current collection.
+		  for(int i = 0; cols != null && i < cols.length; i++) {
+				if(collection == null || !(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName()).equals(cols[i].getAbsolutePath())) {
+					 File dirs[] = cols[i].listFiles();
+					 ArrayTools.sort(dirs);
+					 File import_dir = new File(cols[i], "gimport");
+					 if(!import_dir.exists()) {
+						  import_dir = new File(cols[i], "import");
+					 }
+					 if(import_dir.exists()) {
+						  FileNode collection_root = new FileNode(import_dir, cols[i].getName(), true);
+						  world_root.insert(collection_root);
+						  collection_root = null;
+					 }
+					 import_dir = null;
+				}
+		  }
+		  // Create Local File space.
+		  // Get all the available roots mounted on the system.
+		  File roots[] = File.listRoots();
+		  // If there is just one root use it as the tree root (linux)
+		  if(roots != null) {
+				FileNode file_root;
+				String name = get("Tree.Root");
+				if(roots.length == 1) {
+					 file_root = new FileNode(roots[0], name);
+					 workspace_root.insert(file_root);
+				}
+				// Otherwise build a dummy node which has these nodes as
+				// children.
+				else {
+					 file_root = new FileNode(name);
+					 workspace_root.insert(file_root);
+					 // Hopefully this does an alphabetic sort.
+					 ArrayTools.sort(roots);
+					 for(int i = 0; i < roots.length; i++) {
+						  FileNode child_root = new FileNode(roots[i]);
+						  file_root.insert(child_root);
+						  child_root = null;
+					 }
+				}
+				name = null;
+				file_root = null;
+		  }
+		  // If mirroring is enabled show the public and private caches.
+		  if(Gatherer.config.get("workflow.mirror", false)) {
+				// Add Public workspace
+				FileNode public_root = new FileNode(new File(Utility.CACHE_DIR), get("Tree.Public"));
+				workspace_root.insert(public_root);
+				// Add Private workspace if a collection has been loaded.
+				if(ready()) {
+					 FileNode private_root = new FileNode(new File(getCollectionCache()), get("Tree.Private"));
+					 workspace_root.insert(private_root);
+				}
+		  }
+		  // Finally we retrieve and map any predefined special directories.
+		  if(ready()) {
+				HashMap mappings = collection.getDirectoryMappings();
+				for(Iterator names = mappings.keySet().iterator(); names.hasNext(); ) {
+					 String name = (String) names.next();
+					 File file = (File) mappings.get(name);
+					 FileNode special_root = new FileNode(file, name);
+					 //workspace_root.insert(special_root);
+					 SynchronizedTreeModelTools.insertNodeInto(workspace_model, workspace_root, special_root);
+				}
+		  }
+		  return workspace_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.Message
+	  * @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() {
+		  if(!saved()) {
+				// Force save.
+				try {
+					 SaveCollectionTask save_task = new SaveCollectionTask(collection);
+					 save_task.setImportAfter(true);
+					 save_task.start();
+				}
+				catch(Exception error) {
+					 Gatherer.printStackTrace(error);
+				}
+		  }
+		  else {
+				importing = true;
+				String args[];
+				if(Utility.isWindows()) {
+					 args = new String[6];
+					 args[0] = Gatherer.config.perl_path;
+					 args[1] = "-S";
+					 args[2] = Gatherer.config.getScriptPath() + "import.pl";
+					 args[3] = "-importdir";
+					 args[4] = getCollectionImport();
+					 args[5] = collection.getName();
+				}
+				else {
+					 args = new String[4];
+					 args[0] = Gatherer.config.getScriptPath() + "import.pl";
+					 args[1] = "-importdir";
+					 args[2] = getCollectionImport();
+					 args[3] = collection.getName();
+				}
+				args = ArrayTools.add(args, collection.build_options.getImportValues());
+				GShell shell = new GShell(args, GShell.IMPORT, Message.BUILDING, this, import_monitor, GShell.GSHELL_IMPORT);
+				shell.addGShellListener(Gatherer.g_man.create_pane);
+				shell.start();
+		  }
+	 }
+	 /** 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.Message
+	  * @see org.greenstone.gatherer.collection.Collection
+	  * @see org.greenstone.gatherer.msm.MetadataSetManager
+	  * @see org.greenstone.gatherer.msm.MSMListener
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public boolean loadCollection(String location) {
+		  ///ystem.err.println("Load Collection '" + location + "'");
+		  String[] args2 = new String[1];
+		  args2[0] = location;
+		  boolean result = false;
+		  // Check we have actually been given a .col file.
+		  if(location.endsWith(".col")) {
+				File collection_file = new File(location);
+				// Ensure that the directory exists.
+				File collection_directory = collection_file.getParentFile();
+				if(collection_directory.exists()) {
+					 String name = collection_directory.getName();
+					 File lock_file = new File(collection_file.getParentFile(), LOCK_FILE);
+					 // Now determine if a lock already exists on this collection.
+					 int choice = LockFileDialog.YES_OPTION;
+					 if(lock_file.exists()) {
+						  LockFileDialog dialog = new LockFileDialog(Gatherer.g_man, name, lock_file);
+						  choice = dialog.getChoice();
+					 }
+					 if(choice == LockFileDialog.YES_OPTION) {
+						  try {
+								if(lock_file.exists()) {
+									 lock_file.delete();
+								}
+								// Create a lock file.
+								createLockFile(lock_file);
+								// Open the collection file
+								collection = new Collection(collection_file);
+								collection.msm = new MetadataSetManager();
+								msm = collection.msm; // Legacy
+								collection.msm.load();
+								collection.cdm = new CollectionDesignManager();
+								collection.gdm = new GDMManager();
+								// Tell everyone that it worked.
+								Gatherer.println(get("Loading_Successful", name));
+								// Now we need to hook up classes that depend on messages from the metadata set manager to keep their content fresh.
+								collection.msm.addMSMListener(this);
+								// We're done. Let everyone know.
+								if(Gatherer.g_man != null) {
+									 workspace_model = null;
+									 Gatherer.g_man.collectionChanged(ready());
+								}
+								result = true;
+						  } catch (Exception error) {
+								// There is obviously no existing collection present.
+								Gatherer.printStackTrace(error);
+								JOptionPane.showMessageDialog(Gatherer.g_man, get("Cannot_Open", args2), get("General.Error"), JOptionPane.ERROR_MESSAGE);
+						  }
+					 }
+					 lock_file = null;
+				}
+				else {
+					 JOptionPane.showMessageDialog(Gatherer.g_man, get("CollectionManager.File_Not_Found", args2), get("General.Error"), JOptionPane.ERROR_MESSAGE);
+				}
+				collection_directory = null;
+		  }
+		  else {
+				JOptionPane.showMessageDialog(Gatherer.g_man, get("Not_Col_File", args2), get("General.Error"), JOptionPane.ERROR_MESSAGE);
+				Gatherer.println("Not a Gatherer Collection.");
+		  }
+		  args2 = null;
+		  return result;
+	 }
+
+	 public void makeCollection(String description, String email, String name, String title) {
+		  // Run the mkcol command.
+		  String command[];
+		  if(Utility.isWindows()) {
+				if(description == null || email == null || title == null) {
+					 command = new String[4];
+				}
+				else {
+					 command = new String[10];
+				}
+				command[0] = Gatherer.config.perl_path;
+				command[1] = "-S";
+				command[2] = Gatherer.config.getScriptPath() + "mkcol.pl";
+				if(description == null || email == null || title == null) {
+					 command[3] = name;
+				}
+				else {
+					 command[3] = "-title";
+					 command[4] = title;
+					 command[5] = "-creator";
+					 command[6] = email;
+					 command[7] = "-about";
+					 command[8] = description;
+					 command[9] = name;
+				}
+		  }
+		  else {
+				if(description == null || email == null || title == null) {
+					 command = new String[2];
+					 command[0] = "mkcol.pl";
+					 command[1] = name;
+				}
+				else {
+					 command = new String[8];
+					 command[0] = "mkcol.pl";
+					 command[1] = "-title";
+					 command[2] = title;
+					 command[3] = "-creator";
+					 command[4] = email;
+					 command[5] = "-about";
+					 command[6] = description;
+					 command[7] = name;
+				}
+		  }
+		  GShell process = new GShell(command, GShell.NEW, Message.COLLECT, this, null, GShell.GSHELL_NEW);
+		  process.addGShellListener(this);
+		  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) {
+	 }
+	 /** Called whenever the metadata value changes in some way, such as the addition of a new value. We want to mark the collection so that it needs saving again.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  * @see org.greenstone.gatherer.collection.Collection
+	  */
+	 public void metadataChanged(MSMEvent event) {
+		  // Again this change means we need to save the collection again.
+		  collection.setSaved(false);
+	 }
+	 /** 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) {
+		  ///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("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.ERROR) {
+				// Finish import.
+				collection.setImported(true);
+				buildCollection();
+		  }
+		  // If we were running a build, now is when we move files across.
+		  else if(event.getType() == GShell.BUILD && event.getStatus() != GShell.ERROR) {
+				///ystem.err.println("Installing collection.");
+				installCollection();
+				collection.setBuilt(true);
+				if(Gatherer.g_man != null) {
+					 workspace_model = null;
+					 Gatherer.g_man.collectionChanged(ready());
+				}
+				JOptionPane.showMessageDialog(Gatherer.g_man, get("Preview_Ready"), get("Preview_Ready_Title"), JOptionPane.INFORMATION_MESSAGE);
+		  }
+		  else if(event.getType() == GShell.BUILD && event.getStatus() == GShell.ERROR) {
+				JOptionPane.showMessageDialog(Gatherer.g_man, get("Preview_Ready_Failed"), get("Preview_Ready_Title"), JOptionPane.ERROR_MESSAGE);
+		  }
+	 }
+	 /** 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.
+	  */
+	 public boolean ready() {
+		  if(collection != null) {
+				return true;
+		  }
+		  return false;
+	 }
+	 /** Called to refresh the models upon which the trees are based.
+	  * @see org.greenstone.gatherer.collection.Collection
+	  */
+	 public void refreshTrees() {
+	 }
+	 /** 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 copy monitor with the copy monitor created in CreatePane.
+	  * @param monitor A <strong>GShellProgressMonitor</strong> which we will use as the copy monitor.
+	  */
+	 public void registerCopyMonitor(GShellProgressMonitor monitor) {
+		  copy_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;
+	 }
+	 /** Remove a previously assigned special directory mapping.
+	  * @param name The symbolic name of the special directory mapping to remove as a <strong>String</strong>.
+	  * @return The <strong>File</strong> of the mapping removed.
+	  */
+	 public File removeDirectoryMapping(FileNode target) {
+		  File file = null;
+		  if(ready()) {
+				// Remove from collection, remembering file
+				file = collection.removeDirectoryMapping(target.toString());
+				// Update tree.
+				FileSystemModel model = (FileSystemModel) Gatherer.g_man.collection_pane.getWorkspaceTree().getModel();
+				SynchronizedTreeModelTools.removeNodeFromParent(model, target);
+		  }
+		  return 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 a collection by serializing it to file.
+	  * @param close_after <i>true</i> to cause the Gatherer to close the collection once save is complete, <i>false</i> otherwise.
+	  * @param exit_after <i>true</i> to cause the Gatherer to exit once save is complete, <i>false</i> otherwise.
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.Message
+	  * @see org.greenstone.gatherer.gui.GUIManager
+	  * @see org.greenstone.gatherer.gui.GConfigPane
+	  * @see org.greenstone.gatherer.collection.Collection
+	  */
+	 public void saveCollection(boolean close_after, boolean exit_after) {
+		  try {
+				SaveCollectionTask save_task = new SaveCollectionTask(collection, close_after, exit_after);
+				save_task.start();
+		  }
+		  catch(Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+	 }
+	 /** Saves the current collection to a new filename, then restores the original collection. Finally opens the collection copy.
+	  * @param name The name collection name.
+	  */
+	 public void saveCollectionAs(String name) {
+		  // We need to do this in a separate thread so create a SaveCollectionAsTask
+		  try {
+				SaveCollectionTask save_task = new SaveCollectionTask(collection, name);
+				save_task.start();
+		  }
+		  catch(Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+	 }
+
+	 /** Method that is called whenever the metadata set collection changes in some way, such as the addition of a new set or the merging of two sets. We want to mark the collection so that it needs saving again.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  * @see org.greenstone.gatherer.collection.Collection
+	  */
+	 public void setChanged(MSMEvent event) {
+		  // Invalidate saved
+		  collection.setSaved(false);
+	 }
+
+	 /** Updates the given workspace tree model to reference the private cache of the currently loaded collection. */
+	 public void updatePrivateWorkspace(DefaultTreeModel model) {
+		  // Add Private workspace if a collection has been loaded.
+		  if(ready() && !Gatherer.config.get("workflow.mirror", true)) {
+				FileNode root = (FileNode)model.getRoot();
+				// Remove old private workspace
+				FileNode old = (FileNode)model.getChild(root, 2);
+				model.removeNodeFromParent(old);
+				// Create and insert new.
+				FileNode private_workspace = new FileNode(new File(getCollectionCache()), get("Tree.Private"));
+				model.insertNodeInto(private_workspace, root, 2);
+		  }
+	 }
+	 /** Called whenever the value tree of an metadata element changes in some way, such as the addition of a new value. We want to mark the collection so that it needs saving again.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  * @see org.greenstone.gatherer.collection.Collection
+	  */
+	 public void valueChanged(MSMEvent event) {
+		  collection.setSaved(false);
+	 }
+	 /** Used to retrive a value from the dictionary based on the key.
+	  * @param key A <strong>String</strong> indicating what value to retrieve.
+	  * @return A <strong>String</strong> representing the value.
+	  */
+	 private String get(String key) {
+		  return get(key, (String[])null);
+	 }
+
+	 /** Used to retrive a value from the dictionary based on the key. */
+	 private String get(String key, String arg) {
+		  String[] args = new String[1];
+		  args[0] = arg;
+		  return get(key, args);
+	 }
+
+	 /** Used to retrive a value from the dictionary based on the key, and an array of arguments.
+	  * @param key A <strong>String</strong> indicating what value to retrieve.
+	  * @param args A <strong>String[]</strong> of arguments to be inserted into the phrase.
+	  * @return A <strong>String</strong> representing the value.
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf('.') == -1) {
+				key = "CollectionManager." + key;
+		  }
+		  return Gatherer.dictionary.get(key, args);
+	 }
+	 /** 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 void installCollection() {
+		  Gatherer.println("Build complete. Moving files.");
+		  File index_dir = new File(getCollectionIndex(), "temp.txt");
+		  index_dir = index_dir.getParentFile();
+		  Gatherer.println("Index = " + index_dir.getAbsolutePath());
+		  if(index_dir.exists()) {
+				Utility.delete(index_dir);
+		  }
+		  File build_dir = new File(getCollectionBuild(), "temp.txt");
+		  build_dir = build_dir.getParentFile();
+		  Gatherer.println("Build = " + build_dir.getAbsolutePath());
+		  build_dir.renameTo(index_dir);
+		  File new_build = new File(getCollectionBuild(), "temp.txt");
+		  new_build = new_build.getParentFile();
+		  new_build.mkdir();
+	 }
+	 /** Creates and dispatches a message given the initial details.
+	  * @param level An <i>int</i> indicating the message level for this message.
+	  * @param message A <strong>String</strong> which contains the payload of this message.
+	  * @see org.greenstone.gatherer.Log
+	  * @see org.greenstone.gatherer.Message
+	  */
+	 private void message(int level, String message) {
+		  Message msg = new Message(Message.COLLECT, level, message);
+		  if(Gatherer.g_man != null) {
+				Gatherer.log.add(msg);
+		  } else {
+				Gatherer.println(msg.toString());
+		  }
+	 }
+
+	 private boolean searchArchivesForMetadata(File archive_directory) {
+		  /** @todo - ensure GreenstoneArchiveParser works as expected. */
+		  return true;
+	 }
+
+	 private boolean searchForMetadata(File current_file) {
+		  boolean cancelled = false;
+		  if(current_file.isFile() && current_file.getName().equals(Utility.METADATA_XML)) {
+				cancelled = collection.msm.searchForMetadata(null, new FileNode(current_file), false, true); // A dummy run only.
+		  }
+		  else {
+				File[] children_files = current_file.listFiles();
+				for(int i = 0; !cancelled && children_files != null && i < children_files.length; i++) {
+					 cancelled = searchForMetadata(children_files[i]);
+				}
+		  }
+		  return cancelled;
+	 }
+
+	 private void updateCollectionCFG(File base_cfg, File new_cfg, String description, String email, String title) {
+		  boolean first_name = true;
+		  boolean first_extra = true;
+		  String collection_path = (base_cfg.getParentFile().getParentFile()).getAbsolutePath();
+
+		  HashMap mappings = collection.msm.profiler.getActions(collection_path);
+
+		  // 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 FileReader(base_cfg));
+				BufferedWriter out = new BufferedWriter(new FileWriter(new_cfg, false)); // Overwrite whats there.
+				String command = null;
+				while((command = in.readLine()) != null) {
+					 // 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;
+						  }
+					 }
+					 ///ystem.err.println("Read: " + command);
+					 // Now we've finished parsing a line, determine what to do with it.
+					 String command_lc = command.toLowerCase();
+					 // We replace the creator string with our own.
+					 if(command_lc.startsWith(Utility.CFG_CREATOR)) {
+						  write(out, Utility.CFG_CREATOR + " " + email);
+					 }
+					 else if(command_lc.startsWith(Utility.CFG_MAINTAINER)) {
+						  write(out, Utility.CFG_MAINTAINER + " " + email);
+					 }
+					 else if(command_lc.startsWith(Utility.CFG_COLLECTIONMETA_COLLECTIONNAME)) {
+						  if(first_name) {
+								write(out, Utility.CFG_COLLECTIONMETA_COLLECTIONNAME + " \"" + title + "\"");
+								first_name = false;
+						  }
+					 }
+					 else if(command_lc.startsWith(Utility.CFG_COLLECTIONMETA_COLLECTIONEXTRA)) {
+						  if(first_extra) {
+								write(out, Utility.CFG_COLLECTIONMETA_COLLECTIONEXTRA + " \"" + description + "\"");
+								first_extra = false;
+						  }
+					 }
+					 else {
+						  // Replace mapping strings
+						  if(mappings != null) {
+								for(Iterator keys = mappings.keySet().iterator(); keys.hasNext(); ) {
+									 String target = (String) keys.next();
+									 String replacement = (String) mappings.get(target);
+									 command = command.replaceAll(target, replacement);
+								}
+								// See if the command line contains any of the things that need changing.
+								String hfile = null;
+								String metadata = null;
+								CommandTokenizer tokenizer = new CommandTokenizer(command);
+								while(tokenizer.hasMoreTokens()) {
+									 String token = tokenizer.nextToken();
+									 if(token.equals(Utility.CFG_CLASSIFY_HFILE)) {
+										  hfile = tokenizer.nextToken();
+									 }
+									 else if(token.equals(Utility.CFG_CLASSIFY_METADATA)) {
+										  metadata = tokenizer.nextToken();
+									 }
+								}
+								tokenizer = null;
+								// Replace the hfile if we found it
+								if(hfile != null && metadata != null) {
+									 String result = (String) mappings.get(metadata);
+									 if(result == null) {
+										  result = metadata;
+									 }
+									 command = command.replaceAll(hfile, result + ".txt");
+								}
+								hfile = null;
+								metadata = null;
+						  }
+						  write(out, command);
+					 }
+				}
+				in.close();
+				in = null;
+				out.flush();
+				out.close();
+				out = null;
+		  }
+		  catch(Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+		  // All done, I hope.
+	 }
+
+	 private void write(BufferedWriter out, String message)
+		  throws Exception {
+		  ///ystem.err.println("Writing: " + message);
+		  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);
+				}
+		  }
+		  /** 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);
+				}
+		  }
+		  /** 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);
+				}
+		  }
+		  /** 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/start/gli/src/org/greenstone/gatherer/collection/DeleteCollectionPrompt.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/collection/DeleteCollectionPrompt.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/collection/DeleteCollectionPrompt.java	(revision 13666)
@@ -0,0 +1,322 @@
+package org.greenstone.gatherer.collection;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.Collection;
+import org.greenstone.gatherer.util.ArrayTools;
+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 JDialog {
+	 /** The currently selected collection for deletion. */
+	 private Collection collection = null;
+	 /** The model behind the list. */
+	 private DefaultListModel list_model = null;
+	 /** A reference to ourself so any inner-classes get 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;
+	 /** The size of the delete prompt screen. */
+	 public static final Dimension SIZE = new Dimension(500, 500);
+	 /** Constructor.
+	  * @see org.greenstone.gatherer.collection.DeleteCollectionPrompt.CloseButtonListener
+	  * @see org.greenstone.gatherer.collection.DeleteCollectionPrompt.CollectionListListener
+	  * @see org.greenstone.gatherer.collection.DeleteCollectionPrompt.ConfirmationCheckBoxListener
+	  * @see org.greenstone.gatherer.collection.DeleteCollectionPrompt.OKButtonListener
+	  */
+	 public DeleteCollectionPrompt() {
+		  super();
+		  this.close_button = new JButton(get("General.Close", null));
+		  this.confirmation = new JCheckBox(get("Confirm_Delete", null));
+		  this.details = new JTextArea();
+		  this.details_label = new JLabel(get("Collection_Details", null));
+		  this.list = new JList();
+		  this.list_label = new JLabel(get("Collection_List", null));
+		  this.list_model = new DefaultListModel();
+		  this.ok_button = new JButton(get("General.OK", null));
+		  this.prompt = this;
+		  this.setModal(true);
+		  this.setSize(SIZE);
+		  this.setTitle(get("Title", null));
+		  close_button.addActionListener(new CloseButtonListener());
+		  confirmation.addActionListener(new ConfirmationCheckBoxListener());
+		  confirmation.setEnabled(false);
+		  confirmation.setSelected(false);
+		  details.setFont(Gatherer.config.getFont("general.tooltip_font", false));
+		  details.setText(get("No_Collection", null));
+		  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() {
+		  close_button = null;
+		  confirmation = null;
+		  details = null;
+		  details_label = null;
+		  list_model.clear();
+		  list_model = null;
+		  list = null;
+		  ok_button = null;
+		  prompt = null;
+	 }
+	 /** This method causes the modal prompt to be displayed. */
+	 public void 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 = Gatherer.config.screen_size;
+		  this.setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+		  this.show();
+	 }
+	 /** 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,get("Successful_Delete", args),get("Successful_Title", null),JOptionPane.INFORMATION_MESSAGE);
+		  }
+		  else {
+				JOptionPane.showMessageDialog(prompt,get("Failed_Delete", args),get("Failed_Title", null),JOptionPane.WARNING_MESSAGE);
+		  }
+	 }
+	 /** Retrieves a phrase from the <strong>Dictionary</strong> in <strong>Gatherer</strong>.
+	  * @param key A <strong>String</strong> used to match against a specific phrase in the dictionary.
+	  * @see org.greenstone.gatherer.Dictionary
+	  * @see org.greenstone.gatherer.Gatherer
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf(".") == -1) {
+				key = "DeleteCollectionPrompt." + key;
+		  }
+		  return Gatherer.dictionary.get(key, args);
+	 }
+	 /** Attempts to load the given collection. Currently uses simple
+	  * serialization of the collection class.
+	  * @param location The path to the serialized collection.
+	  */
+	 public Collection loadCollection(File file) {
+		  Collection col = null;
+		  try {
+				FileInputStream fis = new FileInputStream(file);
+				BufferedInputStream bin = new BufferedInputStream(fis);
+				ObjectInputStream input = new ObjectInputStream(bin);
+				col = (Collection) input.readObject();
+				input.close();
+				input = null;
+				bin.close();
+				bin = null;
+				fis.close();
+				fis = null;
+		  } 
+		  catch (Exception error) {
+				error.printStackTrace();
+		  }
+		  return col;
+	 }
+	 /** 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.
+		  String collect_directory_name = Utility.getCollectionDir(Gatherer.config.gsdl_path);
+		  File collect_directory = new File(collect_directory_name);
+		  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++) {
+					 File children[] = collections[i].listFiles();
+					 for(int j = 0; children != null && j < children.length; j++) {
+						  if(children[j].getAbsolutePath().endsWith(".col")) {
+								Collection col = loadCollection(children[j]);
+								// If we've actually loaded 
+								if(col != null) {
+									 list_model.addElement(col);
+								}
+						  }
+					 }
+				}
+		  }
+		  // 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) {
+				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) {
+				if(!list.isSelectionEmpty()) {
+					 confirmation.setEnabled(true);
+					 collection = (Collection) list.getSelectedValue();
+					 args = new String[4];
+					 args[0] = collection.getTitle();
+					 args[1] = collection.getName();
+					 args[2] = collection.getEmail();
+					 args[3] = collection.getDescription();
+					 details.setText(get("Details", args));
+				}
+				else {
+					 confirmation.setEnabled(false);
+					 details.setText(get("No_Collection", null));
+				}
+		  }
+	 }
+	 /** A check box listener so we can tell if the users selected confirm. */
+	 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) {
+				if(confirmation.isSelected()) {
+					 ok_button.setEnabled(true);
+				}
+				else {
+					 ok_button.setEnabled(false);
+				}
+		  }
+	 }		  
+	 /** 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.
+				File delete_me = new File(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator);
+				if(Utility.delete(delete_me)) {
+					 resultPrompt(true);
+					 list_model.removeElement(collection);
+					 details.setText(get("No_Collection", null));
+					 confirmation.setEnabled(false);
+					 confirmation.setSelected(false);
+					 ok_button.setEnabled(false);
+					 collection = null;
+				}
+				else {
+					 resultPrompt(false);
+				}
+		  }
+	 }
+}
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/collection/Job.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/collection/Job.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/collection/Job.java	(revision 13666)
@@ -0,0 +1,513 @@
+package org.greenstone.gatherer.collection;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.WGet;
+import org.greenstone.gatherer.gui.GProgressBar;
+import org.greenstone.gatherer.util.GURL;
+import org.greenstone.gatherer.util.Utility;
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.0
+ */
+public class Job
+	 implements ActionListener {
+	 
+	 private boolean clobber;
+    private boolean debug;
+	 private boolean higher_directories;
+	 private boolean no_parents;
+	 private boolean other_hosts; 
+	 private boolean page_requisites; 
+	 private boolean quiet;
+
+	 private GProgressBar progress;
+
+	 private GURL initial = null;
+	 private GURL url = null;
+
+	 private TreeModel model;
+
+	 private int depth;
+	 private int previous_state;
+	 private int state;
+
+	 private String current_url;
+	 private String destination;
+	 private String proxy_pass;
+	 private String proxy_user;
+
+	 private Vector encountered_urls;
+	 private Vector failed_urls;
+
+	 private WGet mummy;
+
+	 public static int COMPLETE = 0;
+	 public static int PAUSED   = 1;
+    public static int RUNNING  = 2;
+    public static int STOPPED  = 3;
+
+	 /**
+	  */
+	 public Job(TreeModel model, boolean clobber, boolean debug, boolean no_parents, boolean other_hosts, boolean page_requisites, boolean quiet, GURL initial, int depth, String destination, String proxy_pass, String proxy_user, WGet mummy, boolean simple) {
+		  this.model = model;
+
+		  this.debug = debug;
+		  this.clobber = clobber;
+		  this.no_parents = no_parents;
+		  this.other_hosts = other_hosts;
+		  this.page_requisites = page_requisites;
+		  this.quiet = quiet;
+		  this.initial = initial;
+		  this.depth = depth;
+		  this.destination = destination;
+		  this.proxy_pass = proxy_pass;
+		  this.proxy_user = proxy_user;
+		  this.mummy = mummy;
+
+		  progress = new GProgressBar(this, initial.toString(), simple);
+
+		  encountered_urls = new Vector();
+		  failed_urls = new Vector();
+
+		  previous_state = STOPPED;
+		  state = STOPPED;
+	 }
+
+	 /** Depending on which button on the progress bar was pushed,
+	  * this method will affect the state of the Job and perhaps make
+	  * calls to wget.class if necessary.
+	  * @param event The ActionEvent fired from within the GProgressBar
+	  * which we must respond to.
+	  */
+	 public void actionPerformed(ActionEvent event) {
+		// The action 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.action) {
+				previous_state = state;
+				if(state == RUNNING) {
+					 state = PAUSED;
+				}
+				else {
+					 state = RUNNING;
+					 mummy.resumeThread();
+				}
+		  }
+		  else if (event.getSource() == progress.cancel) {
+				state = STOPPED; // Should already be stopped.
+				mummy.deleteJob(this);
+		  }
+	 }
+
+	 /** Called by the WGet native code to inform us of a new download starting.
+	  * @param url The url that is being downloaded, as a String.
+	  */
+	 public void addDownload(String raw_url) {
+		  if(!encountered_urls.contains(raw_url)) {
+				encountered_urls.add(raw_url);
+		  }
+		  // Regardless create a new GURL
+		  current_url = raw_url;
+		  url = new GURL(raw_url);
+		  progress.addDownload(raw_url);
+	 }
+
+	 /** Used to advise the Job of a newly parsed link. Its up to Job
+	  * to decide if it already knows about this url, and if not to
+	  * update its progress bar.
+	  * @param url The url in question as a String.
+	  * @param type Whether the link is an internal or external link.
+	  * @return A boolean indicating if the url was added.
+	  */
+	 public boolean addLink(String raw_url, int type) {
+		///ystem.out.println("addLink("+url+", "+type+")");
+		  if(!encountered_urls.contains(raw_url)) {
+				// Add it to the urls we've seen.
+				encountered_urls.add(raw_url);
+				// Add it the to links for the current GURL.
+
+				// Add it to the progress file count.
+				progress.increaseFileCount();
+				return true;
+		  }
+		  // Regardless add it to the children links of the current GURL
+		  initial.addLink(raw_url);
+
+		  // We've seen it before. Don't count it again.
+		  return false;
+	 }
+
+	 public void callWGet() {
+		  // Build parameter string
+		  String command = "wget ";
+
+		  // Parse arguments into array.
+		  // Always:
+		  // rewrite links to be local if possible - NOOOOOO,
+		  // output a debug file and debug messages,
+		  // run quietly.
+		  //command = command + "-k ";
+
+		  if(destination != null) {
+			 command = command + "-P " + destination + " ";
+		  }
+
+		  if(depth < 0) {
+				// Infinite recursion
+				command = command + "-r ";
+		  }
+		  else if (depth == 0) {
+				// Just this page.
+		  }
+		  else if (depth > 0) {
+				// Recursion to the specified depth.
+				command = command + "-r -l" + depth + " ";
+		  }
+
+		  if(!clobber || previous_state == Job.PAUSED) {
+				command = command + "-nc -c ";
+		  }
+
+		  if(proxy_user != null) {
+				command = command + "--proxy-user=" + proxy_user 
+					 + " --proxy-passwd=" + proxy_pass + " ";
+		  }
+		  
+		  if(page_requisites) {
+				command = command + "-p ";
+		  }
+
+		  if(other_hosts) {
+				command = command + "-H ";
+		  }
+
+		  // Finally tell it the site to download.
+		  command = command + initial.toString();
+
+		  if(previous_state == Job.COMPLETE) {
+				progress.mirrorBegun(true);
+		  }
+		  else {
+				progress.mirrorBegun(false);
+		  }		  
+
+		  // Run it
+		  try {
+				Gatherer.println("Cmd: " + command);
+				Runtime rt = Runtime.getRuntime();
+				Process prcs = rt.exec(command);
+				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;
+				while ((line = br.readLine()) != null) {
+					 Gatherer.println(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) {
+						  Gatherer.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("'"));
+								// Remove the destination guff
+								if(destination != null) {
+									 new_url = new_url.substring(destination.length());
+								}
+								addDownload("http:/" + new_url);
+						  }
+					 }
+					 // If line contains "saved [<size>]" set currently 
+					 // downloading url to "Download Complete".
+					 else if(line.lastIndexOf(") - `") != -1) {
+						  if(!ignore_for_robots) {
+								// Download complete
+								downloadComplete();
+						  }
+						  else {
+								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
+						  Gatherer.println("Already there.");
+						  String new_url = 
+								line.substring(line.indexOf("`") + 1,
+													line.lastIndexOf("'"));
+						  // Remove the destination guff
+						  if(destination != null) {
+								new_url = new_url.substring(destination.length());
+						  }
+						  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) {
+									 Gatherer.println("Error.");
+									 downloadFailed();
+								}
+								else {
+									 ignore_for_robots = false;
+								}
+						  }
+					 }
+				}
+				// Now display final message based on exit value
+				prcs.waitFor();
+		  } catch (Exception ioe) {
+				//message(Utility.ERROR, ioe.toString());
+				Gatherer.printStackTrace(ioe);
+		  }
+		  // If we've got to here and the state isn't STOPPED then the
+		  // job is complete.
+		  if(state == Job.RUNNING) {
+				progress.mirrorComplete();
+				previous_state = state;
+				state = Job.COMPLETE;
+		  }
+    }
+
+	 /** The most important part of the Job class, this method is
+	  * responsible for calling the WGet native methods used to 
+	  * mirror the indicated url. By this stage all the variables
+	  * necessary should be set and we need only build up the
+	  * parameter string and make the call.
+	  */
+	 public void callWGetNative() {
+		  Vector args = new Vector();
+
+		  // Let the GProgressBar know we're starting, just in case
+		  // the user hasn't told us to. If this is the second time the
+		  // urls downloaded and the first attempt was successful (ie 
+		  // the previous job was complete), then we have the case where 
+		  // the user is forcing us to remirror. Reset all the values etc
+		  // if this is the case then reset the variables.
+		  // Note that this can cause the result line to look something 
+		  // like this.
+		  // Downloaded 12 of 12 files (8 warnings, 0 errors).
+		  // The warnings would be something like, 'File already downloaded'
+		  // but the total number of files and the file successfully 
+		  // downloaded will be correct.
+		  if(previous_state == Job.COMPLETE) {
+				progress.mirrorBegun(true);
+		  }
+		  else {
+				progress.mirrorBegun(false);
+		  }
+
+		  // Parse arguments into array.
+		  args.add(Utility.BASE_DIR + "wget");
+		  //args.add("-k");
+		  args.add("-d");
+		  args.add("-o");
+		  args.add("debug.txt");
+		  
+		  if(destination != null) {
+			 args.add("-P");
+			 args.add(destination);
+		  }
+
+		  if(depth < 0) {
+				// Infinite recursion
+				args.add("-r");
+		  }
+		  else if (depth == 0) {
+				// Just this page.
+		  }
+		  else if (depth > 0) {
+				// Recursion to the specified depth.
+				args.add("-r");
+				args.add("-l");
+				args.add("" + depth + ""); // Hacky
+		  }
+
+		  if(!clobber || previous_state == PAUSED) {
+				args.add("-nc");
+				args.add("-c");
+		  }
+
+		  if(proxy_user != null) {
+				args.add("--proxy-user=" + proxy_user);
+				args.add("--proxy-passwd=" + proxy_pass);
+		  }
+		  
+		  if(page_requisites) {
+				args.add("-p");
+		  }
+
+		  if(quiet) {
+			 args.add("-q");
+		  }
+
+		  if(other_hosts) {
+			 args.add("-H");
+		  }
+
+		  args.add(initial.toString());
+
+		  Gatherer.println("Calling wget ");
+		  for(Enumeration e = args.elements(); e.hasMoreElements();) {
+				Gatherer.println(e.nextElement() + " ");
+		  }
+		  Gatherer.println("");
+
+		  // Run home to mummy.
+		  int value = mummy.wget(args.size(), args.toArray(), debug);
+
+		  // If we've got to here and the state isn't STOPPED then the job is complete.
+		  if(state == RUNNING) {
+				progress.mirrorComplete();
+				previous_state = state;
+				state = COMPLETE;
+		  }
+	 }
+
+	 /** Called by the WGet native code when the current download is 
+	  * completed. In turn all download listeners are informed.
+	  */
+	 public void downloadComplete() {
+		  progress.downloadComplete();
+		  /* @todo
+			  model.add(url.getURL(), destination);
+		  */
+		  url = null;
+		  current_url = null;
+	 }
+	 
+	 /** Called by the WGet native code when the requested download returns
+	  * a status code other than 200.
+	  */
+	 public void downloadFailed() {
+		  ///ystem.out.println("downloadFailed("+current_url+")");
+		  failed_urls.add(current_url); // Its the current url thats failed.
+		  progress.downloadFailed();
+	 } 
+	 
+	 /**
+	  */
+	 public void downloadWarning() {
+		  progress.downloadWarning();
+	 }
+
+	 /** 
+	  * @return A String representing the currently downloading url.
+	  */
+	 public String getCurrent() {
+		  return current_url;
+	 }
+
+	 /** 
+	  * @return A String representing the initial urls host (root node
+	  * of tree that we are mirroring).
+	  */
+	 public String getHost() {
+		  return url.getHost();
+	 }
+
+  /**
+	* @return Returns the progress bar associated with this job.
+	*/
+  public GProgressBar 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 Job 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 == Job.STOPPED || state == Job.PAUSED || 
+			  state == Job.COMPLETE) {
+				return true;
+		  }
+		  return false;
+	 }
+
+	 /** A convinence call.
+	  * @return A String representing the url of the initial url (root node of the mirrored tree).
+	  */
+	 public String toString() {
+		  return initial.toString();
+	 }
+
+	 /** 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/start/gli/src/org/greenstone/gatherer/collection/LoadCollectionBox.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/collection/LoadCollectionBox.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/collection/LoadCollectionBox.java	(revision 13666)
@@ -0,0 +1,70 @@
+package org.greenstone.gatherer.collection;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.event.*;
+import java.io.*;
+import javax.swing.*;
+import javax.swing.filechooser.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.util.Utility;
+import org.outerj.pollo.util.*;
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.1
+ */
+public class LoadCollectionBox {
+
+	 private JFileChooser chooser = null;
+	 public LoadCollectionBox() {
+	 }
+
+	 public String getFileName() {
+		  String defaultPath = Utility.getCollectionDir(Gatherer.config.gsdl_path);
+		  chooser = new JFileChooser(new File(defaultPath));
+		  chooser.setDialogTitle(Gatherer.dictionary.get("SaveCollectionBox.Title"));
+		  ExtensionFileFilter filter1 = new ExtensionFileFilter(".col", Gatherer.dictionary.get("General.File_Description"));
+		  chooser.setFileFilter(filter1);
+		  chooser.setAcceptAllFileFilterUsed(false);
+		  int return_val = chooser.showOpenDialog(null);
+		  if(return_val == JFileChooser.APPROVE_OPTION) {
+				return chooser.getSelectedFile().getAbsolutePath();
+		  }
+		  else {
+				return null;
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/collection/SaveCollectionBox.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/collection/SaveCollectionBox.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/collection/SaveCollectionBox.java	(revision 13666)
@@ -0,0 +1,182 @@
+package org.greenstone.gatherer.collection;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Gatherer;
+/** Provides a prompt allowing the user some choice in whether a collection saves. */
+public class SaveCollectionBox
+	 extends JDialog
+	 implements ActionListener{
+	 /** What option the user has choosen. */
+	 private int result = 0;
+	 /** Button to cancel prompt, no save. */
+	 private JButton cancel = null;
+	 /** Button for no save. */
+	 private JButton no = null;
+	 /** Button to save. */
+	 private JButton yes = null;
+	 /** A reference to ourselves so our inner classes can dispose of us. */
+	 private SaveCollectionBox myself = null;
+	 /** Result value if the user has choosen cancel. */
+	 static final public int SAVE_CANCEL  = 0;
+	 /** Result value if the user has choosen no. */
+	 static final public int SAVE_NO      = 1;
+	 /** Result value if the user has choosen yes. */
+	 static final public int SAVE_YES     = 2;
+	 /** Construtor. */
+	 public SaveCollectionBox() {
+		  super(Gatherer.g_man);
+		  this.myself = this;
+		  result = SAVE_CANCEL;
+		  // Dialog setup
+		  this.setModal(true);
+		  this.setTitle(get("Title"));
+		  this.setSize(360,100);
+	 }
+	 /** 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 see what button the users clicked, set the appropriate result then dispose of the dialog. */
+	 public void actionPerformed(ActionEvent event) {
+		  if(event.getSource() == yes) {
+				result = SAVE_YES;
+				this.dispose();
+		  } else if(event.getSource() == no) {
+				result = SAVE_NO;
+				this.dispose();
+		  } else if(event.getSource() == cancel) {
+				result = SAVE_CANCEL;
+				this.dispose();
+		  }
+	 }
+	 /** Destructor. */
+	 public void destroy() {
+		  cancel = null;
+		  no.removeActionListener(this);
+		  no = null;
+		  yes.removeActionListener(this);
+		  yes = null;
+		  myself = null;
+		  rootPane = null;
+	 }
+	 /** Displays the prompt by first building the controls, then waits for a user selection.
+	  * @param name The name of the current collection as a <strong>String</strong>.
+	  */
+	 public int getUserOption(String name) {
+		  JPanel content_pane = (JPanel) this.getContentPane();
+		  content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		  content_pane.setLayout(new GridLayout(2,1));
+
+		  String args[] = new String[1];
+		  args[0] = name;
+		  JLabel save_label = new JLabel(get("Label", args));
+		  content_pane.add(save_label);
+		  JPanel button_pane = new JPanel(new GridLayout(1,3));
+		  content_pane.add(button_pane);
+		  // We add both mnemonics and key listener so that the 'y' of yes is underlined, but pressing just [Y] (rather than [CTL]-[Y]) performs a systematic click.
+		  yes = new JButton(get("General.Yes"));
+		  yes.addActionListener(this);
+		  KeyListenerImpl key_listener = new KeyListenerImpl(); 
+		  yes.addKeyListener(key_listener);
+		  yes.setMnemonic(KeyEvent.VK_Y);
+		  button_pane.add(yes);
+		  no = new JButton(get("General.No"));
+		  no.addActionListener(this);
+		  no.addKeyListener(key_listener);
+		  no.setMnemonic(KeyEvent.VK_N);
+		  button_pane.add(no);
+		  cancel = new JButton(get("General.Cancel"));
+		  cancel.addActionListener(this);
+		  cancel.addKeyListener(key_listener);
+		  cancel.setMnemonic(KeyEvent.VK_C);
+		  button_pane.add(cancel);
+		  // Center on screen.
+		  Dimension dlgSize = getSize();
+		  Dimension frmSize = Gatherer.g_man.getSize();
+		  Point loc = Gatherer.g_man.getLocation();
+		  setLocation((frmSize.width - dlgSize.width) / 2 + loc.x, (frmSize.height - dlgSize.height) / 2 + loc.y);
+		  show();
+		  // Deallocate things we allocated here.
+		  yes.removeKeyListener(key_listener);
+		  no.removeKeyListener(key_listener);
+		  cancel.removeKeyListener(key_listener);
+		  key_listener = null;
+		  content_pane = null;
+		  args = null;
+		  save_label = null;
+		  button_pane = null;
+		  dlgSize = null;
+		  frmSize = null;
+		  loc = null;
+		  return result;
+	 }
+	 /** Method to retrieve a phrase from the dictionary based of a key.
+	  * @param key A <strong>String</strong> used to find the correct phrase.
+	  * @return A <strong>String</strong> containing the correct phrase with the correct formatting.
+	  */
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+	 /** Method to retrieve a phrase from the dictionary based of a key and including arguments.
+	  * @param key A <strong>String</strong> used to find the correct phrase.
+	  * @param args A <strong>String[]</strong> of arguments used in formatting and filling out the phrase.
+	  * @return A <strong>String</strong> containing the correct phrase with the correct formatting.
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf('.') == -1) {
+				key = "SaveCollectionBox." + key;
+		  }
+		  return Gatherer.dictionary.get(key, args);
+	 }
+	 /** Listens for key presses when the focus is on one of the buttons. Note that the key pressed needn't be the one associated with the button in focus. */
+	 private class KeyListenerImpl
+		  extends KeyAdapter {
+		  /** Any extension of KeyAdapter can override this method so that we can be informed whenever a key is released (ie after a keyTyped event). In this case we map the key press to an appropriate click on one of the buttons (not necessarily the one the key release was detected on).
+			* @param event A <strong>KeyEvent</strong> containing details about the key release event.
+			*/
+		  public void keyReleased(KeyEvent event) {
+				if(event.getKeyCode() == KeyEvent.VK_Y) {
+					 yes.doClick(10);
+				}
+				else if(event.getKeyCode() == KeyEvent.VK_N) {
+					 no.doClick(10);
+				}
+				else if(event.getKeyCode() == KeyEvent.VK_C) {
+					 cancel.doClick(10);
+				}
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/collection/SaveCollectionTask.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/collection/SaveCollectionTask.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/collection/SaveCollectionTask.java	(revision 13666)
@@ -0,0 +1,326 @@
+package org.greenstone.gatherer.collection;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.Message;
+import org.greenstone.gatherer.collection.Collection;
+import org.greenstone.gatherer.gui.GUIManager;
+import org.greenstone.gatherer.undo.UndoManager;
+import org.greenstone.gatherer.util.Utility;
+/** The actually saving of a collection must run in a thread other than the AWTEvent thread, or else the save progress box will never get updated. To that end this class provides a threaded save method, which saves the various parts of the collection to the appropriate disk location. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class SaveCollectionTask
+	 extends Thread {
+	 private boolean close_after = false;
+	 /** Should we exit the Gatherer once this save is complete. */
+	 private boolean exit_after = false;
+	 /** Do we run the import scripts once this save is complete. */
+	 private boolean import_after = false;
+	 /** The current collection. */
+	 private Collection collection = null;
+	 /** The filename of the collection we are saving. */
+	 private String name = null;
+	 static final private int CLOSE_COLLECTION     = 0;
+	 static final private int COLLECTION_COPIED    = 1;
+	 static final private int COLLECTION_SAVED     = 2;
+	 static final private int COLLECTION_CFG_SAVED = 3;
+	 static final private int COPY_COLLECTION      = 4;
+	 static final private int MAKE_COLLECTION      = 5;
+	 static final private int METADATA_SAVED       = 6;
+	 static final private int METADATA_XML_SAVED   = 7;
+	 static final private int OPEN_COLLECTION      = 8;
+	 static final private int RESTORE_COLLECTION   = 9;
+	 /** Constructor.
+	  * @param name The filename of the collection we are saving as.
+	  */
+	 public SaveCollectionTask(Collection collection) {
+		  this.collection = collection;
+	 }
+	 /** Constructor.
+	  * @param exit_after <i>true</i> to cause the Gatherer to exit once save is complete, <i>false</i> otherwise.
+	  */
+	 public SaveCollectionTask(Collection collection, boolean close_after, boolean exit_after) {
+		  this.close_after = close_after;
+		  this.collection = collection;
+		  this.exit_after = exit_after;
+	 }
+	 /** Constructor.
+	  * @param name The filename of the collection we are saving as.
+	  */
+	 public SaveCollectionTask(Collection collection, String name) {
+		  this.collection = collection;
+		  this.name = name;
+	 }
+	 /** <p>This method, when created in a forked process by start(), performs the actions necessary to save a collection. If this is a regular save it saves the state of the current collection, ensuring all files, metadata files, and configuration files are written to disk. If, instead, this is a "Save As" action then there as several more steps involved:</p>
+	  * <p>1. Perform a regular collection save on what we will later refer to as the origin collection.</p>
+	  * <p>2. Call CollectionManager.makeCollection() to create the collection structure to save into (copied collection).</p>
+	  * <p>3. Copy files from the origin to the copied collections (except special collection files ending with ~).</p>
+	  * <p>4. Restore origin collection by undoing file copy actions and removing the ~ from the end of collection files.</p>
+	  * <p>5. Close the origin collection.</p>
+	  * <p>6. Open the copied collection.</p>
+	  * <p>Of course all of this takes a while, and depends on several other bits of code to work properly.</p>.
+	  * @see org.greenstone.gatherer.collection.Collection
+	  * @see org.greenstone.gatherer.collection.CollectionModel
+	  * @see org.greenstone.gatherer.gui.GUIManager
+	  * @see org.greenstone.gatherer.gui.GConfigPane
+	  * @see org.greenstone.gatherer.msm.MetadataSetManager
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public void run() {
+		  // Change cursor to hourglass.
+		  Gatherer.g_man.wait(true);
+		  // Create progress monitor box. It will display itself as necessary.
+		  ProgressMonitor spd = new ProgressMonitor(Gatherer.g_man, Gatherer.dictionary.get("SaveProgressDialog.Title", collection.getName()), null, 0, 100);
+		  spd.setMillisToDecideToPopup(100);
+		  spd.setMillisToPopup(100);
+		  // 0. Force all remaining metadata.xml files to load.
+		  // 1. Perform a regular collection save on what we will later refer to as the origin collection.
+		  ///ystem.err.println("1. Save origin.");
+		  String tmp_loc = Gatherer.c_man.getCollectionFilename();
+		  String args[] = new String[1];
+		  args[0] = collection.getName() + ".col";
+		  try {
+				// Block until all of the metadata files have been read in.
+				collection.gdm.waitUntilComplete();
+				// Write out the metadata xml files. The destroy below is meant to do this, but never does.
+				collection.gdm.save();
+				
+				spd.setProgress(getValue(METADATA_XML_SAVED));
+				File file = new File(tmp_loc);
+				// Create backup
+				if(file.exists()) {
+					 File backup = new File(tmp_loc + "~");
+					 backup.deleteOnExit();
+					 if(!file.renameTo(backup)) {
+						  Gatherer.println("Error in CollectionManager.load(): FileNotRenamedException");
+					 }
+				}
+				// Carry on.
+				collection.save();
+				spd.setProgress(getValue(COLLECTION_SAVED));
+				// Write out the collection configuration file.
+				Gatherer.g_man.config_pane.saveConfiguration();
+				spd.setProgress(getValue(COLLECTION_CFG_SAVED));
+				// Write out the metadata files.
+				Gatherer.c_man.msm.save();
+				spd.setProgress(getValue(METADATA_SAVED));
+				// Clean-up
+				spd.setProgress(100);
+				///atherer.g_man.collectionChanged(Gatherer.c_man.ready());
+				collection.setSaved(true);
+		  } 
+		  catch (Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+		  // Now we check whether we've finished, or is this a Save As action, in which case we've got miles to go.
+		  if(name != null) {
+				// 2. Call CollectionManager.makeCollection() to create the collection structure to save into (copied collection).
+				///ystem.err.println("2. Make copy.");
+				Gatherer.c_man.createCollection(null, null, name, null, null, null);
+				spd.setProgress(getValue(MAKE_COLLECTION));
+				// 3. Copy files from the origin to the copied collections (except special collection files ending with ~).
+				// As part of this we must rename origin.col to copy.col
+				///ystem.err.println("3. Copy origin.");
+				ArrayList files = new ArrayList();
+				File collection_file = new File(Gatherer.c_man.getCollectionFilename());
+				File copied_dir = new File(Utility.getCollectionDir(Gatherer.config.gsdl_path) + name);
+				files.add(collection_file.getParentFile());
+				while(files.size() > 0) {
+					 File file = (File) files.get(0);
+					 files.remove(0);
+					 if(file.isDirectory()) {
+						  File children[] = file.listFiles();
+						  for(int i = 0; i < children.length; i++) {
+								files.add(children[i]);
+						  }
+						  children = null;
+					 }
+					 else {
+						  // Rename origin.col file.
+						  if(file.equals(collection_file)) {
+								File copied_file = new File(copied_dir, name + ".col");
+								copy(collection_file, copied_file);
+								copied_file = null;
+						  }
+						  // Exclude *~ files from certain locations and lock.tmp file.
+						  else if(!file.getName().endsWith("~") && !file.getName().equals(CollectionManager.LOCK_FILE)) {
+								StringTokenizer origin = new StringTokenizer(file.getAbsolutePath(), File.separator);
+								StringTokenizer destin = new StringTokenizer(copied_dir.getAbsolutePath(), File.separator);
+								while(destin.hasMoreTokens()) {
+									 origin.nextToken();
+									 destin.nextToken();
+								}
+								File copied_file = new File(copied_dir.getAbsolutePath());
+								while(origin.hasMoreTokens()) {
+									 copied_file = new File(copied_file, origin.nextToken());
+								}
+								copy(file, copied_file);
+								copied_file = null;
+								origin = null;
+								destin = null;
+						  }
+					 }
+					 file = null;
+				}
+				spd.setProgress(getValue(COPY_COLLECTION));
+				// 4. Restore origin collection by undoing file copy actions and removing the ~ from the end of collection files.
+				///ystem.err.println("4. Restore origin.");
+				Gatherer.c_man.undo.undoAll();
+				///ystem.err.println(" - UndoAll complete.");
+				// Recurse collection tree restoring *~
+				files.clear(); // Should be empty anyway.
+				files.add(collection_file.getParentFile());
+				while(files.size() > 0) {
+					 File file = (File) files.get(0);
+					 files.remove(0);
+					 if(file.isDirectory()) {
+						  File children[] = file.listFiles();
+						  for(int i = 0; i < children.length; i++) {
+								files.add(children[i]);
+						  }
+						  children = null;
+					 }
+					 else if(file.getName().endsWith("~")) {
+						  String filename = file.getAbsolutePath();
+						  File original_file = new File(filename.substring(0, filename.length() - 1));
+						  ///ystem.err.println("Renaming " + filename);
+						  if(!file.renameTo(original_file)) {
+								Gatherer.println("Error in SaveCollectionTask.run(): FileRenameException");
+						  }
+					 }
+				}
+				///ystem.err.println(" - Restore *~ complete.");
+				spd.setProgress(getValue(RESTORE_COLLECTION));
+				// 5. Close the origin collection.
+				///ystem.err.println("5. Close origin.");
+				collection.setSaved(true);
+				Gatherer.c_man.closeCollection();
+				spd.setProgress(getValue(CLOSE_COLLECTION));
+				// 6. Open the copied collection.	
+				///ystem.err.println("6. Open copy.");
+				Gatherer.c_man.loadCollection(copied_dir.getAbsolutePath() + File.separator + name + ".col");
+				spd.setProgress(getValue(OPEN_COLLECTION));
+				copied_dir = null;
+		  }
+		  spd.close();
+		  spd = null;
+		  tmp_loc = null;
+		  args = null;
+		  // Reset undo queue.
+		  if(Gatherer.c_man.ready()) {
+				Gatherer.c_man.undo.clear();
+		  }
+		  Gatherer.g_man.wait(false);
+
+		  // Now we are finished action any necessary action.
+		  if(import_after) {
+				Gatherer.c_man.importCollection();
+		  }
+		  if(close_after) {
+				Gatherer.c_man.closeCollection();
+		  }
+		  ///ystem.err.println("Save Complete.");
+		  if(exit_after) {
+				Gatherer.self.exit();
+		  }
+	 }
+
+	 public void setImportAfter(boolean state) {
+		  import_after = true;
+	 }
+
+	 private void copy(File source, File destination) {
+		  ///ystem.err.println("Copy: " + source.getAbsolutePath());
+		  ///ystem.err.println("  to: " + destination.getAbsolutePath());
+		  try {
+				destination.getParentFile().mkdirs();
+				FileInputStream f_in = new FileInputStream(source);
+				FileOutputStream f_out = new FileOutputStream(destination);
+				byte data[] = new byte[Utility.BUFFER_SIZE];
+				int data_size = 0;
+				while((data_size = f_in.read(data, 0, Utility.BUFFER_SIZE)) != -1) {
+					 f_out.write(data, 0, data_size);
+				}
+				f_in.close();
+				f_out.close();
+		  }
+		  catch (Exception exception) {
+				Gatherer.printStackTrace(exception);
+		  }
+	 }
+
+	 private int getValue(int reference) {
+		  double multiplier;
+		  if(name == null) {
+				multiplier = 1.0;
+		  }
+		  else {
+				multiplier = 0.25;
+		  }
+		  switch(reference) {
+		  // Standard Save 
+		  case COLLECTION_SAVED:
+				return (int)((double)70 * multiplier);
+		  case COLLECTION_CFG_SAVED:
+		  case METADATA_SAVED:
+		  case METADATA_XML_SAVED:
+				return (int)((double)10 * multiplier);
+		  // Save As
+		  case MAKE_COLLECTION:
+				return 5;
+		  case COPY_COLLECTION:
+				return 30;
+		  case RESTORE_COLLECTION:
+				return 30;
+		  case CLOSE_COLLECTION:
+				return 10;
+		  case OPEN_COLLECTION:
+				return 10;
+		  }
+		  return 0;
+	 }
+}
+
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/file/FileAlreadyExistsException.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/file/FileAlreadyExistsException.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/file/FileAlreadyExistsException.java	(revision 13666)
@@ -0,0 +1,11 @@
+package org.greenstone.gatherer.file;
+
+import java.lang.Exception;
+
+public class FileAlreadyExistsException
+	 extends Exception {
+
+	 public FileAlreadyExistsException() {
+		  super();
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/file/FileAssociation.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/file/FileAssociation.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/file/FileAssociation.java	(revision 13666)
@@ -0,0 +1,83 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+package org.greenstone.gatherer.file;
+/**************************************************************************************
+ * Title:        Gatherer
+ * Description:  The Gatherer: a tool for gathering and enriching a digital collection.
+ * Company:      The University of Waikato
+ * Written:      20/10/02
+ * Revised:      
+ **************************************************************************************/
+/** The file association class remembers both a certain file extension and the command used to open this type of file. 
+ * @author John Thompson
+ * @version 2.3
+ */
+public class FileAssociation {
+	 /** The file extension, most likely three or four letters. */
+	 private String extension;
+	 /** The command string, which may include %1 which should be replaced with the target files name. */
+	 private String command;
+	 public FileAssociation(String extension, String command) {
+		  this.command = command;
+		  this.extension = extension;
+	 }
+	 /** Retrieve the command from this association.
+	  * @return The command as a <strong>String</strong>.
+	  */
+	 public String getCommand() {
+		  return command;
+	 }
+	 /** Retrieve the extension from this association.
+	  * @return The extension as a <strong>String</strong>.
+	  */
+	 public String getExtension() {
+		  return extension;
+	 }
+	 /** Set the command for this file association.
+	  * @param command The new command as a <strong>String</strong>.
+	  */
+	 public void setCommand(String command) {
+		  this.command = command;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/file/FileAssociationManager.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/file/FileAssociationManager.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/file/FileAssociationManager.java	(revision 13666)
@@ -0,0 +1,197 @@
+package org.greenstone.gatherer.file;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.io.*;
+import java.lang.*;
+import java.nio.charset.*;
+import java.util.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.FileAssociationDialog;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.WinRegistry;
+import org.w3c.dom.*;
+/** Provides a manager for relating a filetype to a command to open that filetype, and an optional icon. Under windows this will attempt to leverage the Windows Registry. If this fails, or under other platforms, the user will be prompted to enter the required details manually. This information will then be stored for any further sessions of the Gatherer. Of course the ability to edit these settings must also be provided. */
+public class FileAssociationManager 
+	 extends HashMap {
+	 
+	 static private final File ASSOC_FILE = new File(Utility.BASE_DIR, "associations.xml");
+
+	 public FileAssociationManager() {
+		  // Attempt to load any previous file associations
+		  if(ASSOC_FILE.exists()) {
+				load();
+		  }
+	 }
+
+	 public void destroy() {
+		  save();
+	 }
+
+	 public String getCommand(File file) {
+		  String command = null;
+		  String filename = file.toString();
+		  // Determine extension
+		  int index = -1;
+		  if((index = filename.lastIndexOf(".")) != -1) {
+				String extension = filename.substring(index + 1);
+				command = getCommand(file, extension);
+		  }
+		  return command;
+	 }
+
+	 public String getCommand(File file, String extension) {
+		  // We first check to see if we already know the answer to how to run this program.
+		  String command = (String) get(extension);
+		  if(command != null) {
+				command = command + " " + file.getAbsolutePath();
+		  }
+		  // If not, and we are on windows, try the registry.
+		  if(command == null && Utility.isWindows()) {
+				command = WinRegistry.openCommand(file.getAbsolutePath());
+		  }
+		  // Failing all that prompt the user to select the program to open this with.
+		  if(command == null) {
+				FileAssociationDialog dialog = new FileAssociationDialog(this);
+				command = dialog.display(extension);
+				dialog.destroy();
+				dialog = null;
+				if(command != null) {
+					 put(extension, command);
+					 command = command + " " + file.getAbsolutePath();
+				}
+		  }
+		  ///ystem.err.println("Get command: " + extension + " = " + command);
+		  return command;
+	 }
+
+	 public String getCommandImmediately(String extension) {
+		  return (String) get(extension);
+	 }
+
+	 public void edit() {
+		  FileAssociationDialog dialog = new FileAssociationDialog(this);
+		  dialog.display(null);
+		  dialog.destroy();
+		  dialog = null;		  
+	 }
+
+	 private void load() {
+		  // Read in and parse the document.
+		  Document document = Utility.parse(ASSOC_FILE, false);
+		  if(document != null) {
+				// Recover all the entry nodes of the association root.
+				for(Node entry_n = document.getDocumentElement().getFirstChild(); entry_n != null; entry_n = entry_n.getNextSibling()) {
+					 if(entry_n.getNodeName().equals("Entry")) {
+						  Element entry_e = (Element) entry_n;
+						  String extension = entry_e.getAttribute("extension");
+						  String command = MSMUtils.getValue(entry_e);
+						  put(extension, command);
+						  extension = null;
+						  command = null;
+						  entry_e = null;
+					 }
+				}
+		  }
+	 }
+
+	 private void save() {
+		  // Only save if there is something to save.
+		  if(size() > 0) {
+				StringBuffer assoc = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+				assoc.append("<!DOCTYPE Associations [\n");
+				assoc.append("  <!ELEMENT Associations (Entry*)>\n");
+				assoc.append("  <!ELEMENT Entry (#PCDATA)>\n");
+				assoc.append("  <!ATTLIST Entry\n");
+				assoc.append("            extension CDATA #REQUIRED>\n");
+				assoc.append("]>\n");
+				assoc.append("\n");
+				assoc.append("<Associations>\n");
+				for(Iterator keys = keySet().iterator(); keys.hasNext(); ) {
+					 String extension = (String) keys.next();
+					 String command = (String) get(extension);
+					 assoc.append("\t<Entry extension=\"");
+					 assoc.append(extension);
+					 assoc.append("\">");
+					 assoc.append(command);
+					 assoc.append("</Entry>\n");
+				}
+				assoc.append("</Associations>");
+
+				String assoc_str = assoc.toString();
+				assoc = null;
+				try {
+					 FileOutputStream fos = new FileOutputStream(ASSOC_FILE);
+					 OutputStreamWriter osw = new OutputStreamWriter(fos, Charset.forName("UTF-8"));
+					 int position = 0;
+					 int BLOCK_SIZE = 1024;
+					 // Write x block sized chunks to file.
+					 while(position + BLOCK_SIZE < assoc_str.length()) {
+						  osw.write(assoc_str, position, BLOCK_SIZE);
+						  position = position + BLOCK_SIZE;
+					 }
+					 // Write the remainder of the buffer.
+					 if(position < assoc_str.length()) {
+						  osw.write(assoc_str, position, assoc_str.length() - position);
+					 }
+					 osw.flush();
+					 osw.close();
+					 osw = null;
+					 fos.close();
+					 fos = null;
+					 assoc_str = null;
+				}
+				catch (Exception error) {
+					 Gatherer.printStackTrace(error);
+				}
+		  }
+	 }
+
+	 public void setCommand(String extension, String command) {
+		  ///ystem.err.println("Set command: " + extension + " = " + command);
+		  if(command == null || command.length() == 0) {
+				remove(extension);
+		  }
+		  else {
+				put(extension, command);
+		  }
+	 }
+}
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/file/FileFilter.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/file/FileFilter.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/file/FileFilter.java	(revision 13666)
@@ -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/start/gli/src/org/greenstone/gatherer/file/FileJob.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/file/FileJob.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/file/FileJob.java	(revision 13666)
@@ -0,0 +1,158 @@
+package org.greenstone.gatherer.file;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import javax.swing.tree.*;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.file.FileSystemModel;
+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;
+
+	 public boolean folder_level = false;
+	 /** true if this should generate an undo event, false for a redo one. */
+	 public boolean undo = true;
+	 /** true if this job should generate an undo event of any kind. */
+	 public boolean undoable = 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;
+	 /** 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.
+	  * @param undo true if this job some create an undo job when actioned, false for a redo job.
+	  * @param undoable true if this job can generate undo or redo jobs, false otherwise.
+	  */
+	 public FileJob(long id, DragComponent source, FileNode orig, DragComponent target, FileNode dest, byte type, boolean undo, boolean undoable) {
+		  this.id = id;
+		  this.source = source;
+		  this.target = target;
+		  this.type = type;
+		  this.undo = undo;
+		  this.undoable = undoable;
+		  ///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());
+				///ystem.err.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;
+		  default:
+				text.append("unknown ");
+		  }
+		  FileNode origin = getOrigin();
+		  if(origin != null) {
+				text.append(origin.getFile().getAbsolutePath());
+		  }
+		  else {
+				text.append("ERROR!");
+		  }
+		  text.append(" -> ");
+		  FileNode destination = getDestination();
+		  if(destination != null) {
+				text.append(destination.getFile().getAbsolutePath());
+		  }	  
+		  else {
+				text.append("Recycle Bin");
+		  }
+		  return text.toString();
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/file/FileManager.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/file/FileManager.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/file/FileManager.java	(revision 13666)
@@ -0,0 +1,155 @@
+package org.greenstone.gatherer.file;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.io.File;
+import javax.swing.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.file.FileQueue;
+import org.greenstone.gatherer.gui.NewFolderPrompt;
+import org.greenstone.gatherer.gui.tree.DragTree;
+import org.greenstone.gatherer.undo.UndoManager;
+import org.greenstone.gatherer.util.DragComponent;
+import org.greenstone.gatherer.util.SynchronizedTreeModelTools;
+/** Manages the moving of files within a separate thread. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class FileManager {
+	 /** Not only the queue of files to be moved, but also the object that moves them. */
+	 private FileQueue queue = null;
+	 /** Constructor.
+	  * @see org.greenstone.gatherer.file.FileQueue
+	  */
+	 public FileManager() {
+		  queue = new FileQueue(false);
+		  queue.start();
+	 }
+
+	 /** Given the arguments, 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) {
+		  byte type = 0;
+		  // If source and target are the same we are moving
+		  if(source == target) {
+				type = FileJob.MOVE;
+		  }
+		  // If source and target are different
+		  else {
+				// If target is the UndoManager, we're deleting
+				if(target instanceof UndoManager) {
+					 // If the source is the workspace then display an error message. Workspace is read only.
+					 if(source.toString().equals("Workspace")) {
+						  JOptionPane.showMessageDialog(Gatherer.g_man, Gatherer.dictionary.get("FileActions.Read_Only"), Gatherer.dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+						  return;
+					 }
+					 // Normal delete. Go ahead.
+					 else {
+						  type = FileJob.DELETE;
+					 }
+				}
+				// Otherwise we are copying
+				else {
+					 type = FileJob.COPY;
+				}
+		  }
+		  Task task = new Task(System.currentTimeMillis(), source, source_nodes, target, target_node, type);
+		  SwingUtilities.invokeLater(task);
+	 }
+
+	 /** Retrieves the file queue object. */
+	 public FileQueue getQueue() {
+		  return queue;
+	 }
+
+	 public void newFolder(DragTree tree, FileNode parent_node) {
+		  // Ask the user for the directories name.
+		  NewFolderPrompt new_folder_prompt = new NewFolderPrompt(parent_node);
+		  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()) {
+					 JOptionPane.showMessageDialog(Gatherer.g_man, Gatherer.dictionary.get("FileActions.Folder_Already_Exists", name), Gatherer.dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+				}
+				// Otherwise create it.
+				else {
+					 folder_file.mkdirs();
+					 FileNode folder_node = new FileNode(folder_file);
+					 SynchronizedTreeModelTools.insertNodeInto(model, parent_node, folder_node);
+					 folder_node = null;
+				}
+				folder_file = null;
+				model = null;
+		  }
+		  name = null;
+	 }
+
+	 private class Task
+		  implements Runnable {
+		  private byte type;
+		  private DragComponent source;
+		  private DragComponent target;
+		  private FileNode target_node;
+		  private FileNode[] source_nodes;
+		  private long id;
+		  public Task(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, and calculate progress bar size.
+				queue.calculateSize(source_nodes);
+				// Now we queue the job(s). Note that this may fail if a read only file is encountered and we have been asked to delete.
+				for(int i = 0; source_nodes != null && i < source_nodes.length; i++) {
+					 queue.addJob(id, source, source_nodes[i], target, target_node, type, true, true, true);
+				}
+		  }
+	 }
+}
+
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/file/FileNode.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/file/FileNode.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/file/FileNode.java	(revision 13666)
@@ -0,0 +1,340 @@
+package org.greenstone.gatherer.file;
+
+import java.io.File;
+import java.util.*;
+import javax.swing.filechooser.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.file.FileFilter;
+import org.greenstone.gatherer.file.FileSystemModel;
+import org.greenstone.gatherer.util.ArrayTools;
+
+public class FileNode
+	 implements MutableTreeNode {
+
+	 static final private int FALSE   = 0;
+	 static final private int TRUE    = 1;
+	 static final private int UNKNOWN = 2;
+
+	 private ArrayList children;
+	 private boolean children_readonly = true;
+	 private boolean readonly = true;
+	 private File file;
+	 private FileSystemModel model;
+	 private int allows_children = UNKNOWN;
+	 private MutableTreeNode parent;
+	 private String title;
+
+	 public FileNode(File file) {
+		  ///ystem.err.println("New FileNode(" + file.getAbsolutePath() + ")");
+		  this.file = file;
+	 }
+
+	 public FileNode(File file, boolean readonly) {
+		  this(file);
+		  this.children_readonly = readonly;
+		  this.readonly = readonly;
+	 }
+
+	 public FileNode(File file, FileSystemModel model) {
+		  this(file);
+		  this.model = model;
+	 }
+
+	 public FileNode(File file, FileSystemModel model, boolean readonly) {
+		  this(file, readonly);
+		  this.model = model;
+	 }
+
+	 public FileNode(File file, FileSystemModel model, String title) {
+		  this(file, model);
+		  this.title = title;
+	 }
+
+	 public FileNode(File file, String title) {
+		  this(file);
+		  this.title = title;
+	 }
+
+	 public FileNode(File file, String title, boolean readonly) {
+		  this(file, readonly);
+		  this.title = title;
+	 }
+
+	 public FileNode(File file, FileSystemModel model, String title, boolean readonly) {
+		  this(file, model, readonly);
+		  this.title = title;
+	 }
+
+	 /** The special 'dummy' root node, that is not based on a particular file, but instead holds several special directory mappings. */
+	 public FileNode(String title) {
+		  this.children = new ArrayList();
+		  this.title = title;
+	 }
+
+	 /** Returns the children of the receiver as an Enumeration. */
+	 public Enumeration children() {
+		  return new FileEnumeration();
+	 }
+
+    /** Compare two filenodes for equality. */
+    public boolean equals(FileNode node) {
+		  boolean result = false;
+		  if(node != null) {
+				if(file != null) {
+					 result = (file.equals(node.getFile()));
+				}
+				else {
+					 result = toString().equals(node.toString());
+				}
+		  }
+		  return result;
+    }
+
+    /** Returns true if the receiver allows children. We have to cache the result of this call to prevent unceasing missing disk messages being thrown if the removable media was, um, removed after directory mapped. */
+    public boolean getAllowsChildren() {
+		  if(readonly) {
+				if(allows_children == UNKNOWN) {
+					 // If the file is non-null but doesn't exist (as is the case for removable media), return true anyway.
+					 if(file != null) {
+						  if(FileSystemView.getFileSystemView().isFileSystemRoot(file)) {
+								allows_children = TRUE;
+						  }
+						  else if(file.exists() && file.isDirectory()) {
+								allows_children = TRUE;
+						  }
+						  // Any mapped directories always allow children.
+						  else if(getParent() != null && getParent().getParent() == null) {
+								allows_children = TRUE;
+						  }
+						  else {
+								allows_children = FALSE;
+						  }
+					 }
+					 // Allows children is always true for dummy nodes.
+					 else {
+						  allows_children = TRUE;
+					 }
+				}
+				return (allows_children == TRUE);
+		  }
+		  else {
+				return (file == null || file.isDirectory());
+		  }
+    }
+    
+	 /** Returns the child TreeNode at index childIndex. */
+	 public TreeNode getChildAt(int index) {
+		  TreeNode result = null;
+		  map();
+		  if(0 <= index && index < children.size()) {
+				result = (TreeNode) children.get(index);
+		  }
+		  else {
+				result = new DefaultMutableTreeNode("Error");
+		  }
+		  return result;
+	 }
+
+	 /** Returns the number of children TreeNodes the receiver contains. */
+	 public int getChildCount() {
+		  int size = 0;
+		  // We don't automatically map if this is a system root, or we risk the 50,000 Disk not found error messages of death.
+		  if(FileSystemView.getFileSystemView().isFileSystemRoot(file)) {
+		      size = 1; // Size is always non-zero for a system root
+		  }
+		  else {
+		      map();
+		  }
+		  ///ystem.err.println(this + ".getChildCount() = " + children.size());
+		  if(children != null) {
+				size = children.size();
+		  }
+		  return size;
+	 }
+
+	 public File getFile() {
+		  return file;
+	 }
+
+	 /** Returns the index of node in the receivers children. */
+	 public int getIndex(TreeNode node) {
+		  map();
+		  return children.indexOf(node);
+	 }
+
+	 /** Returns the parent TreeNode of the receiver. */
+	 public TreeNode getParent() {
+		  return parent;
+	 }
+
+	 /** 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 void insert(MutableTreeNode child) {
+		  insert(child, children.size());
+	 }
+
+	 /** Adds child to the receiver at index. */
+	 public void insert(MutableTreeNode child, int index) {
+		  ///ystem.err.println("Insert " + child + " in " + this + " at index " + index);
+		  //map();
+		  try {
+				children.add(index, child);
+				// Set parent and model.
+				FileNode new_child = (FileNode) child;
+				new_child.setModel(model);
+				new_child.setParent(this);
+				new_child.setReadOnly(readonly);
+		  }
+		  catch(Exception error) {
+				error.printStackTrace();
+		  }
+	 }
+
+	 /** Returns true if the receiver is a leaf. */
+	 public boolean isLeaf() {
+		  return !getAllowsChildren();
+	 }
+
+	 public boolean isReadOnly() {
+		  return readonly;
+	 }
+
+	 public void map() {
+		  // Only map if there are no children.
+		  if(children == null && file != null && getAllowsChildren()) {
+				///ystem.err.println("Map: " + this);
+				children = new ArrayList();
+				File[] files = file.listFiles();
+				if(files != null && files.length > 0) {
+					 ArrayTools tools = new ArrayTools();
+					 // Apply the filters set in the model.
+					 FileFilter[] filters = model.getFilters();
+					 for(int i = 0; filters != null && i < filters.length; i++) {
+						  files = tools.filter(files, filters[i].filter, filters[i].exclude);
+					 }
+					 // Sort the remaining files.
+					 tools.sort(files, true);
+					 // Now add them to children.
+					 for(int i = 0; i < files.length; i++) {
+						  FileNode child = new FileNode(files[i], model, children_readonly);
+						  child.setParent(this);
+						  children.add(child);
+					 }
+				}
+				model.nodeStructureChanged(this);
+		  }
+		  else {
+			  ///ystem.err.println("Can't map: " + this + ". No file or doesn't allow children.");
+		  }
+	 }
+
+	 /** Removes the child at index from the receiver. */
+	 public void remove(int index) {
+		  if(0 <= index && index < children.size()) {
+				children.remove(index);
+		  }
+	 }
+
+	 /** Removes node from the receiver. */
+	 public void remove(MutableTreeNode node){
+		  int index = getIndex(node);
+		  if(index != -1) {
+				children.remove(index);
+		  }
+	 }
+
+	 /** Removes the receiver from its parent. */
+	 public void removeFromParent() {
+		  parent.remove(this);
+		  parent = null;
+	 }
+
+	 public void setChildrenReadOnly(boolean children_readonly) {
+		  this.children_readonly = children_readonly;
+	 }
+
+	 public void setFile(File file) {
+		  this.file = file;
+	 }
+
+	 public void setModel(FileSystemModel model) {
+		  this.model = model;
+	 }
+
+	 public void setParent(MutableTreeNode parent) {
+		  this.parent = parent;
+	 }
+
+	 public void setReadOnly(boolean readonly) {
+		  this.readonly = readonly;
+	 }
+
+	 /** Resets the user object of the receiver to object. */
+	 public void setUserObject(Object object) {
+		  try {
+				file = (File) object;
+				title = null;
+		  }
+		  catch(Exception error) {
+				error.printStackTrace();
+		  }
+	 }
+
+	 public String toString() {
+		  if(title == null) {
+		    if(FileSystemView.getFileSystemView().isFileSystemRoot(file)) {
+			  title = file.getAbsolutePath();
+			}
+			else {
+				title = file.getName();
+			}
+		  }
+		  return title;
+	 }
+
+	 /** Unmap this nodes children. */
+	 public void unmap() {
+		  // You cannot unmap nodes that have no file basis.
+		  if(file != null) {
+				///ystem.err.println("Unmap: " + this);
+				children = null;
+		  }
+		  else {
+				///ystem.err.println("No file for " + this + " - can't unmap.");
+		  }
+	 }
+
+	 private class FileEnumeration
+		  implements Enumeration {
+		  private int index = 0;
+		  /** Tests if this enumeration contains more elements. */
+		  public boolean hasMoreElements() {
+				return (index < children.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 < children.size()) {
+					 result = children.get(index);
+					 index++;
+				}
+				return result;
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/file/FileOpenActionListener.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/file/FileOpenActionListener.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/file/FileOpenActionListener.java	(revision 13666)
@@ -0,0 +1,100 @@
+package org.greenstone.gatherer.file;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.event.*;
+import java.io.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.file.FileNode;
+/** 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.collection.FileRecord
+	  * @see org.greenstone.gatherer.tree.GTree
+	  */ 
+	 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.self.spawnApplication(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/start/gli/src/org/greenstone/gatherer/file/FileQueue.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/file/FileQueue.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/file/FileQueue.java	(revision 13666)
@@ -0,0 +1,749 @@
+package org.greenstone.gatherer.file;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.file.FileJob;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.gui.LongProgressBar;
+import org.greenstone.gatherer.gui.SmudgyLabel;
+import org.greenstone.gatherer.gui.tree.DragTree;
+import org.greenstone.gatherer.msm.GDMManager;
+import org.greenstone.gatherer.undo.UndoManager;
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.DragComponent;
+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
+    implements TreeSelectionListener {
+	 /** When someone requests the movement queue to be dumped this cancel flag is set to true. */
+	 private boolean cancel_action = false;
+	 /** A temporary mapping from currently existing FileNode folder to their equivelent FileNode folder within the undo managers tree. */
+	 private HashMap completed_folder_mappings = new HashMap();
+	 /** true to cause this file queue to return from run() as soon as there are no jobs left on the queue. Useful for undo jobs which must occur before a specific action. */
+	 private boolean return_immediately = false;
+	 /** We are only allowed to wait under specific circumstances. */
+	 private boolean wait_allowed = true;
+	 /** true if the user has selected yes to all from a file 'clash' dialog. */
+	 private boolean yes_to_all = false;
+	 /** A temporary mapping from currently existing FileNodes to the potential FileNode folder within the undo managers tree. */
+	 private HashMap recycle_folder_mappings = new HashMap();
+	 /** A label explaining the current moving files status. */
+	 private SmudgyLabel file_status = null;
+	 /** A label explaining the status of this job. */
+	 private JLabel job_status = null;
+	 /** A list containing a queue of waiting movement jobs. */
+	 //private LinkedList queue;
+	 private ArrayList queue;
+	 /** A progress bar which shows how many bytes, out of the total size of bytes, has been moved. */
+	 private LongProgressBar progress = null;
+	 /** The last piece of text shown on the file status label, just incase we are displaying a very temporary message. */
+	 private String previous = null;
+	 /** Constructor.
+	  * @param return_immediately true to cause this file queue to return from run() as soon as there are no jobs left on the queue.
+	  * @see org.greenstone.gatherer.Configuration
+	  * @see org.greenstone.gatherer.gui.Coloring
+	  * @see org.greenstone.gatherer.gui.LongProgressBar
+	  */
+	 public FileQueue(boolean return_immediately) {
+		  this.return_immediately = return_immediately;
+		  this.queue = new ArrayList();//LinkedList();
+		  String args[] = new String[2];
+		  args[0] = "0";
+		  args[1] = "0";
+		  file_status = new SmudgyLabel(get("Selected", args));
+		  job_status = new JLabel(get("No_Activity"));
+		  progress = new LongProgressBar();
+		  progress.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  progress.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+		  progress.setString(get("No_Activity"));
+		  progress.setStringPainted(true);
+		  args = null;
+	 }
+
+	 /** Requeue an existing job into the queue.
+	  * @param job A previously created FileJob.
+	  */
+	 synchronized public void addJob(FileJob job, int position) {
+		  job.done = true; // Ensure that the requeued job is marked as done.
+		  queue.add(position, job);
+		  notify();
+	 }
+
+	 /** 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.
+	  * @param undo true if this job should generate undo jobs, false for redo ones.
+	  * @param undoable true if this job can generate undo or redo jobs at all, false otherwise.
+	  */
+	 public void addJob(long id, DragComponent source, FileNode child, DragComponent target, FileNode parent, byte type, boolean undo, boolean undoable, boolean folder_level) {
+		  addJob(id, source, child, target, parent, type, undo, undoable, folder_level, -1);
+	 }
+	 synchronized public void addJob(long id, DragComponent source, FileNode child, DragComponent target, FileNode parent, byte type, boolean undo, boolean undoable, boolean folder_level, int position) {
+		  FileJob job = new FileJob(id, source, child, target, parent, type, undo, undoable);
+		  job.folder_level = folder_level;
+		  ///ystem.err.println("Adding job: " + job);
+		  if(position != -1 && position <= queue.size() + 1) {
+				queue.add(position, job);
+		  }
+		  else {
+				queue.add(job);
+		  }
+		  notify();
+	 }
+
+	 public void calculateSize(FileNode[] files) {
+		  progress.reset();
+		  progress.setString(get("FileActions.Calculating_Size"));
+		  progress.setIndeterminate(true);
+		  Vector remaining = new Vector();
+		  for(int i = 0; i < files.length; i++) {
+				remaining.add(files[i]);
+		  }
+		  while(remaining.size() > 0) {
+				FileNode node = (FileNode)remaining.remove(0);
+				if(node.isLeaf()) {
+					 progress.addMaximum(node.getFile().length());
+				}
+				else {
+					 for(int i = 0; i < node.getChildCount(); i++) {
+						  remaining.add(node.getChildAt(i));
+					 }
+				}
+		  }
+		  progress.setString(get("No_Activity"));
+		  progress.setIndeterminate(false);
+	 }
+
+	 /** This method is called to cancel the job queue at the next available moment. */
+	 public void cancelAction() {
+		  cancel_action = true;
+	 }
+	 /** Access to the file state label. */
+	 public JLabel getFileStatus() {
+		  return file_status;
+	 }
+	 /** Access to the job state label. */	 
+	 public JLabel getJobStatus() {
+		  return job_status;
+	 }
+	 /** Access to the progress bar. */
+	 public LongProgressBar getProgress() {
+		  return progress;
+	 }
+	 /** Prevent the progress bar updating momentarily, while the progress bar size is re-adjusted. */
+	 public void pause() {
+		  progress.setIndeterminate(true);
+	 }
+	 /** The run method exists in every thread, and here it is used to work its way through the queue of Jobs. If no jobs are waiting and it cans, it waits until a job arrives. If a job is present then it is either COPIED or DELETED, with the records being copied or removed as necessary, and directories being recursed through. Finally the user can press cancel to cause the loop to prematurely dump the job queue then wait.
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.CollectionManager
+	  * @see org.greenstone.gatherer.file.FileJob
+	  * @see org.greenstone.gatherer.file.FileNode
+	  * @see org.greenstone.gatherer.gui.LongProgressBar
+	  * @see org.greenstone.gatherer.msm.MetadataSetManager
+	  * @see org.greenstone.gatherer.undo.UndoManager
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public void run() {
+		  super.setName("FileQueue");
+		  while(!Gatherer.self.exit) {
+				try {
+					 // Retrieve the next job
+					 int position = queue.size() - 1;
+					 FileJob job = removeJob(position);
+					 if(job != null) {
+						  ///ystem.err.println("Found job: " + job);
+						  // The user can cancel this individual action at several places, so keep track if the state is 'ready' for the next step.
+						  boolean ready = true; 
+						  FileNode origin_node = job.getOrigin();
+						  FileNode destination_node = job.getDestination();
+						  FileSystemModel source_model = (FileSystemModel)job.source.getTreeModel();
+						  FileSystemModel target_model = (FileSystemModel)job.target.getTreeModel();
+						  if(destination_node == null) {
+								// Retrieve the root node of the target model instead. A delete, or course, has no target file so all deleted files are added to the root of the Recycle Bin model.
+								destination_node = (FileNode) target_model.getRoot();
+						  }
+						  // Extract common job details.
+						  File source_file = origin_node.getFile();
+						  File target_file = null;
+						  // Determine the target file for a copy or move.
+						  if(job.type == FileJob.COPY || job.type == FileJob.MOVE) {
+								target_file = new File(destination_node.getFile(), source_file.getName());
+						  }
+						  // To copy a file, copy it then add any metadata found at the source. If this file was already in our collection then we must ensure the lastest version of its metadata.xml has been saved to disk. To copy a directory simply create the directory at the destination, then add all of its children files as new jobs.
+						  if((job.type == FileJob.COPY || job.type == FileJob.MOVE) && !job.done) {
+								///ystem.err.println("Copy/Move: " + origin_node);
+								FileNode new_node = null;
+								// Check if file exists, and action as necessary. Be aware the user can choose to cancel the action all together (where upon ready becomes false).
+								if(target_file.exists()) {
+									 // We've previously been told
+									 if(yes_to_all) {
+										  // Remove the old file and tree entry.
+										  target_file.delete();
+										  ready = true;
+									 }
+									 else {
+										  ///atherer.println("Opps! This filename already exists. Give the user some options.");
+										  Object[] options = { get("General.Yes"), get("Yes_To_All"), get("General.No"), get("General.Cancel") };
+										  int result = JOptionPane.showOptionDialog(Gatherer.g_man, get("File_Exists", target_file.getName()), get("General.Warning"), JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[0]);
+										  switch(result) {
+										  case 1: // Yes To All
+												yes_to_all = true;
+										  case 0: // Yes
+												// Remove the old file and tree entry.
+												if(destination_node != null) {
+													 TreePath destination_path = new TreePath(destination_node.getPath());
+													 FileNode temp_target_node = new FileNode(target_file, target_model, true);
+													 TreePath target_path = destination_path.pathByAddingChild(temp_target_node);
+													 SynchronizedTreeModelTools.removeNodeFromParent(target_model, target_model.getNode(target_path));
+													 target_path = null;
+													 temp_target_node = null;
+													 destination_path = null;
+												}
+												target_file.delete();
+												ready = true;
+												break;
+										  case 3: // No To All
+												cancel_action = true;
+										  case 2: // No
+										  default:
+												ready = false;
+										  }
+									 }
+								}
+								// We proceed with the copy/move if the ready flag is still set. If it is that means there is no longer any existing file of the same name.
+								if(ready) {
+									 // update status area
+									 String args[] = new String[1];
+									 args[0] = "" + (queue.size() + 1) + "";
+									 job_status.setText(get("Jobs", args));
+									 if(job.type == FileJob.COPY) {
+										  args[0] = Utility.formatPath("FileActions.Copying", source_file.getAbsolutePath(), file_status.getSize().width);
+										  file_status.setText(get("Copying", args));
+									 }
+									 else {
+										  args[0] = Utility.formatPath("FileActions.Moving", source_file.getAbsolutePath(), file_status.getSize().width);
+										  file_status.setText(get("Moving", args));
+									 }
+									 args = null;
+									 file_status.setToolTipText(Utility.formatHTMLWidth(file_status.getText(), 80));
+									 // If source is a file
+									 if(source_file.isFile()) {
+										  // copy the file. If anything goes wrong the copy file should throw the appropriate exception. No matter what exception is thrown (bar an IOException) we display some message, perhaps take some action, then cancel the remainder of the pending file jobs. No point in being told your out of hard drive space for each one of six thousand files eh?
+										  try {
+												copyFile(source_file, target_file, progress);
+										  }
+										  // If we can't find the source file, then the most likely reason is that the file system has changed since the last time it was mapped. Warn the user that the requested file can't be found, then force a refresh of the source folder involved.
+										  catch(FileNotFoundException fnf_exception) {
+												Gatherer.printStackTrace(fnf_exception);
+												cancel_action = true;
+												// Show warning.
+												JOptionPane.showMessageDialog(Gatherer.g_man, get("File_Not_Found_Message", source_file.getName()), get("File_Not_Found_Title"), JOptionPane.ERROR_MESSAGE);
+												// Force refresh of source folder.
+												source_model.refresh(new TreePath(((FileNode)origin_node.getParent()).getPath()));
+										  }
+										  catch(FileAlreadyExistsException fae_exception) {
+												Gatherer.printStackTrace(fae_exception);
+												cancel_action = true;
+												// Show warning.
+												JOptionPane.showMessageDialog(Gatherer.g_man, get("File_Already_Exists_Message", target_file.getName()), get("File_Already_Exists_Title"), JOptionPane.ERROR_MESSAGE);
+												// Nothing else can be done by the Gatherer.
+										  }
+										  catch(InsufficientSpaceException is_exception) {
+												Gatherer.printStackTrace(is_exception);
+												cancel_action = true;
+												// Show warning. The message body of the expection explains how much more space is required for this file copy.
+												JOptionPane.showMessageDialog(Gatherer.g_man, get("Insufficient_Space_Message", is_exception.getMessage()), get("Insufficient_Space_Title"), JOptionPane.ERROR_MESSAGE);
+												// Nothing else can be done by the Gatherer. In fact if we are really out of space I'm not even sure we can quit safely.
+										  }
+										  catch(UnknownFileErrorException ufe_exception) {
+												Gatherer.printStackTrace(ufe_exception);
+												cancel_action = true;
+												// Show warning
+												JOptionPane.showMessageDialog(Gatherer.g_man, get("Unknown_File_Error_Message"), get("Unknown_File_Error_Title"), JOptionPane.ERROR_MESSAGE);
+												// Nothing else we can do.
+										  }
+										  catch(IOException exception) {
+												// Can't really do much about this.
+												Gatherer.printStackTrace(exception);
+										  }
+										  // If not cancelled
+										  if(!cancel_action) {
+												// Step one is to create a dummy FileNode. Its important it has the correct structure so getPath works.
+												FileNode new_record = new FileNode(target_file);
+												SynchronizedTreeModelTools.insertNodeInto(target_model, destination_node, new_record);
+										      new_node = new_record;
+
+										      // create undo job
+												if(job.undoable) {
+													 job.undoable = false;
+													 if(job.type == FileJob.COPY) {
+														  // A copy is undone with a delete, so it doesn't really matter where the file originally came from (we're not moving it back there, but into the recycle bin). You may also notice we don't make use of the target parent record. This is because no undo action needs this information, and even if it did it could simply ask for records parent!
+														  Gatherer.c_man.undo.addUndo(job.ID(), UndoManager.FILE_COPY, null, null, job.target, new_record, job.undo);
+													 }
+													 else {
+														  // Movements however do need a source and source parent so the file can be moved back to the correct place.
+														  Gatherer.c_man.undo.addUndo(job.ID(), UndoManager.FILE_MOVE, job.source, (FileNode)origin_node.getParent(), job.target, new_record, job.undo);
+													 }
+												}
+												new_record = null;
+										  }
+									 }
+									 // Else
+									 else if(source_file.isDirectory()) {
+										  // create new record
+										  FileNode directory_record = new FileNode(target_file);
+										  ///ystem.err.println("Directory record = " + directory_record + " (" + target_file.getAbsolutePath() + ")");
+										  SynchronizedTreeModelTools.insertNodeInto(target_model, destination_node, directory_record);
+										  // Why is this not happening eh?
+										  directory_record.setParent(destination_node);
+										  if(!target_file.exists()) {
+									         // make the directory
+												target_file.mkdirs();
+												new_node = directory_record;
+										      // create undo job
+												if(job.undoable) {
+													 job.undoable = false;
+													 if(job.type == FileJob.COPY) {
+														  // A copy is undone with a delete, so it doesn't really matter where the file originally came from (we're not moving it back there, but into the recycle bin). You may also notice we don't make use of the target parent record. This is because no undo action needs this information, and even if it did it could simply ask for records parent!
+														  Gatherer.c_man.undo.addUndo(job.ID(), UndoManager.FILE_COPY, null, null, job.target, directory_record, job.undo);
+													 }
+													 else {
+														  // Movements however do need a source and source parent so the file can be moved back to the correct place.
+														  Gatherer.c_man.undo.addUndo(job.ID(), UndoManager.FILE_MOVE, job.source, (FileNode)origin_node.getParent(), job.target, directory_record, job.undo);
+													 }
+												}
+										  }
+										  // Else inform the users that a directory already exists and files will be copied into it
+										  else {
+												JOptionPane.showMessageDialog(null, get("Directory_Exists", target_file.toString()), get("General.Warning"), JOptionPane.WARNING_MESSAGE);
+										  }
+										  // Queue non-filtered child files for copying. If this directory already existed, the child records will have to generate the undo jobs, as we don't want to entirely delete this directory if it already existed.
+										  FileNode child_record = null;
+										  // In order to have a sane copy proceedure (rather than always copying last file first as it used to) we always add the child node at the position the parent was removed from. Consider the file job 'a' at the end of the queue which generates three new jobs 'b', 'c' and 'd'. The resulting flow should look like this.
+										  // -- Starting queue                   ...[a]
+										  // remove(position) = 'a'              ...
+										  // add(position, 'b')                  ...[b]
+										  // add(position, 'c')                  ...[c][b]
+										  // add(position, 'd')                  ...[d][c][b]
+										  // Next loop
+										  // remove(position) = 'b'              ...[d][c]
+										  for(int i = 0; i < origin_node.getChildCount(); i++) {
+												child_record = (FileNode) origin_node.getChildAt(i);
+												addJob(job.ID(), job.source, child_record, job.target, directory_record, job.type, job.undo, false, false, position);
+										  }
+										  child_record = null;
+										  directory_record = null;
+									 }
+									 // The file wasn't found!
+									 else {
+										  cancel_action = true;
+										  // Show warning.
+										  JOptionPane.showMessageDialog(Gatherer.g_man, get("File_Not_Found_Message", source_file.getName()), get("File_Not_Found_Title"), JOptionPane.ERROR_MESSAGE);
+										  // Force refresh of source folder.
+										  source_model.refresh(new TreePath(((FileNode)origin_node.getParent()).getPath()));
+									 }
+									 
+									 // We can't have been cancelled, and we must have created a new FileNode during the above phase, before we can handle metadata.
+									 if(!cancel_action && new_node != null) {
+										  /* Time to handle any existing metadata. */
+										  // If the directory came from inside our collection...
+										  if (job.source.toString().equals("Collection")) {
+												///ystem.err.println("Move within collection...");
+												GDMManager gdm = Gatherer.c_man.getCollection().gdm;
+										      // we just retrieve the metadata attached to the origin node...
+												ArrayList existing_metadata = gdm.getMetadata(source_file);
+												///ystem.err.println("Existing metadata for " + origin_node + ": " + gdm.toString(existing_metadata));
+										      // then assign this remainder to the new folder.
+												///ystem.err.println("New metadata: " + gdm.toString(existing_metadata));
+												gdm.addMetadata(new_node, existing_metadata);
+												existing_metadata = null;
+												gdm = null;
+										  }
+										  // If it came from the recycle bin retrieve the metadata from there, once again remembering to account for inherited metadata
+										  else if (job.source.toString().equals("Undo")) {
+												GDMManager gdm = Gatherer.c_man.getCollection().gdm;
+												// Retrieve metadata from the recycle bin
+												ArrayList existing_metadata = Gatherer.c_man.undo.getMetadata(source_file);
+												// then assign this remainder to the new folder.
+												gdm.addMetadata(new_node, existing_metadata);
+												existing_metadata = null;
+												gdm = null;
+										  }
+										  // Otherwise if it came from the workspace use the MSMs parsers to search for folder level metadata (such as metadata.xml or marc records).
+										  else if (job.source.toString().equals("Workspace")) {
+												cancel_action = Gatherer.c_man.getCollection().msm.searchForMetadata(new_node, origin_node, source_file.isDirectory());
+										  }
+									 }
+									 new_node = null;
+
+								}
+						  }
+						  // If we haven't been cancelled, and we've been asked to delete a directory/file, or perhaps as part of a move, we delete the file. This involves removing any existing metadata and then copying the file to the recycled bin (for a delete only), then deleting the file. When deleting a directory record from the tree (or from the filesystem for that matter) we must ensure that all of the descendant records have already been removed. If we fail to do this the delete will fail, or you will be bombarded with hundreds of 'Parent node of null not allowed' error messages. Also be aware that if the user has cancelled just this action, because of say a name clash, then we shouldn't do any deleting of any sort dammit.
+						  if(!cancel_action && ready && (job.type == FileJob.DELETE || job.type == FileJob.MOVE)) {
+								///ystem.err.print("Delete/Move: " + origin_node + " -> ");
+								// If the source is an empty directory or a file. Don't do anything to the root node of a tree.
+								File[] child_list = source_file.listFiles();
+								if(source_file.isFile() || (child_list != null && (child_list.length == 0 || (child_list.length == 1 && child_list[0].getName().equals(Utility.METADATA_XML))) && origin_node.getParent() != null)) {
+									 ///ystem.err.println("File or empty directory.");
+									 // Delete any metadata.xml still in the directory.
+									 if(child_list != null && child_list.length == 1) {
+										  child_list[0].delete();
+									 }
+
+									 ///ystem.err.println("Origin is file or is directory and is empty.");
+									 // update status area
+									 String args[] = new String[1];
+									 args[0] = "" + (queue.size() + 1) + "";
+									 job_status.setText(get("Jobs", args));
+									 args[0] = Utility.formatPath("FileActions.Deleting", source_file.getAbsolutePath(), file_status.getSize().width);
+									 file_status.setText(get("Deleting", args));
+									 args = null;
+									 file_status.setToolTipText(Utility.formatHTMLWidth(file_status.getText(), 80));
+									 // Remove its metadata
+									 ArrayList metadatum = null;
+									 if(job.source == Gatherer.c_man.undo) {
+										  Gatherer.c_man.undo.addMetadata(target_file, metadatum);
+									 }
+									 else {
+										  metadatum= Gatherer.c_man.getCollection().gdm.removeMetadata(origin_node.getFile());
+									 }
+									 // determine it parent node
+									 FileNode parent_record = (FileNode)origin_node.getParent();
+									 // Remove from model
+									 SynchronizedTreeModelTools.removeNodeFromParent(source_model, origin_node);
+									 // If we are deleting
+									 File recycled_file = null;
+									 FileNode recycled_parent = null;
+									 if(job.type == FileJob.DELETE) {
+										  // See if this record already has a previous recycle folder noted in the recycle folder mappings.
+										  recycled_parent = (FileNode) recycle_folder_mappings.get(origin_node);
+										  if(recycled_parent != null) {
+												recycle_folder_mappings.remove(origin_node);
+										  }
+										  else {
+												recycled_parent = (FileNode) Gatherer.c_man.undo.getTreeModel().getRoot();
+										  }
+										  // This may be a directory which we have already added previously.
+										  if(completed_folder_mappings.containsKey(origin_node)) {
+												FileNode recycled_record = (FileNode) completed_folder_mappings.get(origin_node);
+										      // Replace the temporary directory record in the undo tree with this one.
+										      SynchronizedTreeModelTools.replaceNode(Gatherer.c_man.undo.getTreeModel(), recycled_record, origin_node);
+												origin_node.setFile(recycled_record.getFile());
+										  }
+										  else {
+										      // copy the file to the recycle bin
+												recycled_file = new File(recycled_parent.getFile(), origin_node.toString());
+												// If the file already exists, delete it.
+												if(recycled_file.exists()) {
+													 recycled_file.delete();
+												}
+												recycled_file.deleteOnExit();
+												copyFile(source_file, recycled_file, progress);
+												origin_node.setFile(recycled_file);
+										      // Add the node to the appropriate place in the UndoManagers tree model. Unfortunately this one does have the possibility of altering the GUI (if the removeNodeFromParent above hasn't occured yet), so we must put it on the queue.
+										      SynchronizedTreeModelTools.insertNodeInto(Gatherer.c_man.undo.getTreeModel(), recycled_parent, origin_node);
+										  }
+										  Gatherer.c_man.undo.addMetadata(source_file, metadatum);
+									 }
+									 // delete the source file
+									 Utility.delete(source_file);
+									 // create undo job as necessary. File move would have been handled above.
+									 if(job.undoable) {
+										  job.undoable = false;
+										  // The target is null, indicating that we moved this file to the recycle bin. The UndoManager will replace null with 'this'.
+										  Gatherer.c_man.undo.addUndo(job.ID(), UndoManager.FILE_DELETE, job.source, parent_record, null, origin_node, job.undo);
+									 }
+									 recycled_parent = null;
+									 recycled_file = null;
+									 //metadatum = null;
+								}
+								// Else the source is a directory and it has children remaining
+								else if(child_list != null && child_list.length > 0) {
+									 ///ystem.err.print("Nonempty directory -> ");
+									 ///ystem.err.println("Directory is non-empty. Remove children first.");
+									 FileNode recycle_folder_record = null;
+									 // Don't worry about all this for true file move actions.
+									 if(job.type == FileJob.DELETE) {
+										  // See if this record already has a previous recycle folder noted in the recycle folder mappings.
+										  FileNode parent = (FileNode) recycle_folder_mappings.get(origin_node);
+										  if(parent != null) {
+												recycle_folder_mappings.remove(origin_node);
+										  }
+										  else {
+												parent = (FileNode) Gatherer.c_man.undo.getTreeModel().getRoot();
+										  }
+										  // We must add the folder node to our undo manager tree now, so we'll have something to add children to. We use a copy of the directory file record.
+										  File recycle_folder = new File(parent.getFile(), origin_node.toString());
+										  recycle_folder.deleteOnExit();
+										  recycle_folder.mkdirs();
+										  recycle_folder_record = new FileNode(recycle_folder);
+										  // Add this node to the undo tree model.
+										  SynchronizedTreeModelTools.insertNodeInto(Gatherer.c_man.undo.getTreeModel(), parent, recycle_folder_record);
+										  // We add an entry to the complete mappings to ensure this directory isn't added again
+										  completed_folder_mappings.put(origin_node, recycle_folder_record);
+										  ///ystem.err.println("Added completed directories mapping " + origin_node); 
+										  // queue all of its children, (both filtered and non-filtered), but for deleting only. Don't queue jobs for a current move event, as they would be queued as part of copying. I have no idea way, per sec, however the children within the origin node are always invalid during deletion (there are several copies of some nodes?!?). I'll check that each child is only added once. 
+										  ///ystem.err.println("Directory has " + origin_node.getChildCount() + " children.");
+										  ///ystem.err.println("Directory actually has " + child_list.length + " children.");
+										  origin_node.unmap();
+										  origin_node.map();
+										  ///ystem.err.println("Directory has " + origin_node.getChildCount() + " children.");
+										  ///ystem.err.println("Directory actually has " + child_list.length + " children.");
+										  for(int i = 0; i < origin_node.getChildCount(); i++) {
+												FileNode child_record = (FileNode) origin_node.getChildAt(i);
+												addJob(job.ID(), job.source, child_record, job.target, destination_node, FileJob.DELETE, job.undo, false, false, position);
+												if(recycle_folder_record != null) {
+													 recycle_folder_mappings.put(child_record, recycle_folder_record);
+												}
+										  }
+									 }
+									 // Requeue a delete job -after- the children have been dealt with. Remember I've reversed the direction of the queue so sooner is later. Te-he. Also have to remember that we have have followed this path to get here for a move job: Copy Directory -> Queue Child Files -> Delete Directory (must occur after child files) -> Queue Directory.
+									 // One special case. Do not requeue root nodes. Don't requeue jobs marked as done.
+									 if(origin_node.getParent() != null && !job.done) {
+										  ///ystem.err.println("Requeue");
+										  job.type = FileJob.DELETE; // You only requeue jobs that are deletes, as directories must be inspected before children, but deleted after.
+										  addJob(job, position);
+									 }
+									 else {
+										  ///ystem.err.println("I've already done this job twice. I refuse to requeue it again!!!");
+									 }
+								}
+						  }
+						  job = null;
+						  source_file = null;
+						  target_file = null;
+						  origin_node = null;
+						  // We can only break out of the while loop if we are out of files, or if the action was cancelled.
+						  if(cancel_action) {
+								// Empty queue
+								clearJobs();
+								cancel_action = false;
+						  }
+						  // Debugging pause.
+						  ///ystem.err.println("Job complete.");
+					 }
+					 else {
+						  synchronized(this) {
+								///ystem.err.println("Queue size = " + queue.size());
+								// Force the trees to refresh (but only if there is something on screen!)
+								if(Gatherer.g_man != null) {
+									 Gatherer.g_man.refreshTrees();
+								}
+								// Reset status area
+								job_status.setText(get("No_Selection"));
+								file_status.setText(get("No_Activity"));
+								progress.reset();
+								progress.setString(get("No_Activity"));
+								yes_to_all = false;			
+								completed_folder_mappings.clear();
+								recycle_folder_mappings.clear();
+								// Now wait if applicable.
+								if(return_immediately) {
+									 return;
+								}
+								///ystem.err.println("Waiting");
+								wait();
+						  }
+					 }
+				}
+				catch (Exception error) {
+					 Gatherer.printStackTrace(error); 
+				}
+		  }
+	 }
+	 /** A second lock is necessary to prevent the thread waiting, because its notify occured momentarily before it waited. If the flag is set then the thread can't wait, but loops around. This may chew processor time so should only be used if you are certain files are about to be placed on the queue.
+	  * @param wait_allowed The new state of the wait_allowed flag, as a boolean.
+	  */
+	 public void setWaitAllowed(boolean wait_allowed) {
+		  this.wait_allowed = wait_allowed;
+	 }
+	 /** Restore the progress bar so that it updates normally.
+	  * @see org.greenstone.gatherer.gui.LongProgressBar
+	  */
+	 synchronized public void unpause() {
+		  progress.setIndeterminate(false);
+		  if(previous != null) {
+				progress.setString(previous);
+				previous = null;
+		  }
+	 }
+	 /** Called when the user makes some selection in one of the trees we are listening to. From this we update the status details. */
+	 public void valueChanged(TreeSelectionEvent event) {
+		  JTree tree = (JTree) event.getSource();
+		  if(tree.getSelectionCount() > 0) {
+				TreePath selection[] = tree.getSelectionPaths();
+				int file_count = 0;
+				int dir_count = 0;
+				for(int i = 0; i < selection.length; i++) {
+					 TreeNode record = (TreeNode) selection[i].getLastPathComponent();
+					 if(record.isLeaf()) {
+						  file_count++;
+					 }
+					 else {
+						  dir_count++;
+					 }
+					 record = null;
+				}
+				selection = null;
+				String args[] = new String[2];
+				args[0] = "" + file_count + "";
+				args[1] = "" + dir_count + "";
+				job_status.setText(get("Selected", args));
+				args = null;
+		  }
+		  tree = null;
+	 }
+
+	 synchronized private void clearJobs() {
+		  queue.clear();
+	 }
+
+	 /** 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, LongProgressBar progress) 
+		  throws FileAlreadyExistsException, FileNotFoundException, InsufficientSpaceException, IOException, UnknownFileErrorException {
+		  if(source.isDirectory()) {
+				destination.mkdirs();
+		  }
+		  else {
+				// Check if the origin file exists.
+				if(!source.exists()) {
+					 throw(new FileNotFoundException());
+				}
+				// Check if the destination file does not exist.
+				if(destination.exists()) {
+					 throw(new FileAlreadyExistsException());
+				}
+				File dirs = destination.getParentFile();
+				dirs.mkdirs();
+				// Copy the file.
+				FileInputStream f_in = new FileInputStream(source);
+				FileOutputStream f_out = new FileOutputStream(destination);
+				byte data[] = new byte[Utility.BUFFER_SIZE];
+				int data_size = 0;
+				while((data_size = f_in.read(data, 0, Utility.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);
+						  }
+					 }
+					 if(progress != null) {
+						  progress.addValue(data_size);
+					 }
+				}
+				// 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(!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();
+				}
+		  }
+	 }
+	 /** Retrieve a phrase from the dictionary based on the key.
+	  * @param key The key index as a String.
+	  * @return The desired phrase also as a String.
+	  */
+	 private String get(String key) {
+		  return get(key, (String[])null);
+	 }
+	 /** Retrieve a phrase from the dictionary based on the key, and taking into account the given argument.
+	  * @param key The key index as a String.
+	  * @param args A String which is the argument to be added to the phrase.
+	  * @return The desired phrase also as a String.
+	  */
+	 private String get(String key, String arg) {
+		  String args[] = new String[1];
+		  args[0] = arg;
+		  return get(key, args);
+	 }
+	 /** Retrieve a phrase from the dictionary based on the key, and taking into account the given arguments.
+	  * @param key The key index as a String.
+	  * @param args A String[] of arguments to be added to the phrase.
+	  * @return The desired phrase also as a String.
+	  * @see org.greenstone.gatherer.Dictionary
+	  * @see org.greenstone.gatherer.Gatherer
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf('.') == -1) {
+				key = "FileActions." + key;
+		  }
+		  return Gatherer.dictionary.get(key, args);
+	 }
+
+	 private FileJob removeJob(int position) {
+		  FileJob job = null;
+		  if(queue.size() > 0) {
+				job = (FileJob) queue.remove(position);
+		  }
+		  return job;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/file/FileSystemModel.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/file/FileSystemModel.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/file/FileSystemModel.java	(revision 13666)
@@ -0,0 +1,244 @@
+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.Gatherer;
+import org.greenstone.gatherer.file.FileFilter;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.file.FileOpenActionListener;
+import org.greenstone.gatherer.gui.tree.DragTree;
+import org.greenstone.gatherer.util.SynchronizedTreeModelTools;
+
+public class FileSystemModel
+	 extends DefaultTreeModel 
+	 implements TreeExpansionListener, TreeWillExpandListener {
+
+	 private DragTree tree;
+	 private FileFilter current_filter;
+	 private FileFilter[] filters;
+	 static private FileFilter[] default_filters = { new FileFilter("\\..*", true), new FileFilter("metadata\\.xml", true) };
+
+	 public FileSystemModel(FileNode root) {
+		  super(root);
+		  current_filter = null;
+		  filters = null;
+		  tree = null;
+		  root.setModel(this);
+		  root.map();
+	 }
+
+	 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) {
+		  ///ystem.err.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)) {
+				///ystem.err.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
+					 FileNode stale_node = (FileNode) path.getPathComponent(i);
+					 ///ystem.err.print("Searching for '" + stale_node + "': ");
+					 // Locate the fresh node by searching current's children. Remember to ensure that current is mapped.
+					 current.map();
+					 boolean found = false;
+					 for(int j = 0; !found && j < current.getChildCount(); j++) {
+						  FileNode child_node = (FileNode) current.getChildAt(j);
+						  ///ystem.err.print(child_node + " ");
+						  if(stale_node.equals(child_node)) {
+								found = true;
+								current = child_node;
+								///ystem.err.println("Found!");
+						  }
+						  child_node = null;
+					 }
+					 // If no match is found, then set current to null and exit.
+					 if(!found) {
+						  current = null;
+						  ///ystem.err.println("Not Found!");
+					 }
+					 // Repeat as necessary
+				}
+		  }
+		  ///ystem.err.println("Returning node: " + new TreePath(current.getPath()));
+		  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 mapDirectory(File directory, String title) {
+		  FileNode node = new FileNode(directory, this, title, true);
+		  SynchronizedTreeModelTools.insertNodeInto(this, (FileNode)root, node);
+	 }
+
+	 /** Used to refresh the contents of the FileNode indicated by the tree path. While the refresh itself is a piece of the proverbial, the restoring of expanded folders afterwards is a nightmare, mainly because all of the tree paths are no longer valid (remember that refresh involves throwing away the node currents children and remapping them).
+	  * @param path The TreePath to the node to be refreshed.
+	  */
+	 public void refresh(TreePath path) {
+		  // If no path is set, take the path to the root node (ie update the whole tree)
+		  if(path == null) {
+				///ystem.err.println("Refresh entire tree.");
+				path = new TreePath(((FileNode)root).getPath());
+		  }
+		  else {
+				///ystem.err.println("Refresh: " + path.getLastPathComponent());
+		  }
+		  // Only a valid action if this model is currently being displayed in a tree.
+		  if(tree != null) {
+				// Retrieve the error node.
+				FileNode node = (FileNode) path.getLastPathComponent();
+				// If this error node is a dummy node (ie has no associated file) we can't unmap it, so we iterate through its children refreshing each in turn.
+				if(node.getFile() == null) {
+					 for(int i = 0; i < node.getChildCount(); i++) {
+						  FileNode child = (FileNode) node.getChildAt(i);
+						  refresh(new TreePath(child.getPath()));
+						  child = null;
+					 }
+				}
+				// Otherwise we refresh this node.
+				else {
+					 // Record all of the expanded paths under this node. How come getExpandedDescendants returns more results each time.
+					 Enumeration old_tree_paths = tree.getExpandedDescendants(path);
+					 // Refresh the tree structure.
+					 node.unmap();
+					 node.map();
+					 // Fire the appropriate event.
+					 nodeStructureChanged(node);
+					 // Then (painfully) restore the expanded paths. Note that the paths stored in the enumeration no longer exist, so I have to restore by node matching.
+					 //counter = 0;
+					 ///ystem.err.println("After:");
+					 while(old_tree_paths != null && old_tree_paths.hasMoreElements()) {
+						  //counter++;
+						  FileNode current_node = node;
+						  TreePath old_tree_path = (TreePath) old_tree_paths.nextElement();
+						  ///ystem.err.println(counter + ". " + old_tree_path);
+						  TreePath new_tree_path = new TreePath(path.getPath()); // Why isn't there a treepath copy constructor!
+						  boolean not_found = false;
+						  while(!not_found && old_tree_path.getPathCount() > new_tree_path.getPathCount()) {
+								// Retrieve the new node in the old tree path
+								FileNode old_path_node = (FileNode) old_tree_path.getPathComponent(new_tree_path.getPathCount());
+								// Ensure the current node is mapped
+								current_node.map();
+								// Now attempt to match it to a child of the new paths last node.
+								boolean found = false;
+								for(int i = 0; !found && i < current_node.getChildCount(); i++) {
+									 FileNode target = (FileNode) current_node.getChildAt(i);
+									 ///ystem.err.println("Comparing " + old_path_node.toString() + " with " + target);
+									 if(target.toString().equals(old_path_node.toString())) {
+										  current_node = target;
+										  found = true;
+									 }
+									 target = null;
+								}
+								old_path_node = null;
+								// If we found a match, we add that to the new Tree Path and continue.
+								if(found) {
+									 ///ystem.err.println("Found a match!");
+									 new_tree_path = new_tree_path.pathByAddingChild(current_node);
+								}
+								// We also have to record if we were unable to find a match in the current nodes children.
+								else {
+									 ///ystem.err.println("Node not found.");
+									 not_found = true;
+								}
+						  }
+						  old_tree_path = null;
+						  // If we've got this far, and haven't hit a not found, then we can assume we have the appropriate path, and ask the program to expand the new tree path
+						  if(!not_found) {
+								tree.expandPath(new_tree_path);
+								///ystem.err.println(" -> Expanded " + new_tree_path);
+						  }
+						  else {
+								///ystem.err.println(" -> Cannot Expand " + new_tree_path);
+						  }
+						  new_tree_path = null;
+						  current_node = null;
+					 }
+					 node = null;
+				}
+		  }
+		  else {
+				///ystem.err.println("No Tree!");
+		  }
+	 }
+
+	 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 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.map();
+		  nodeStructureChanged(node);
+		  // Restore the cursor.
+		  Gatherer.g_man.wait(false);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/file/InsufficientSpaceException.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/file/InsufficientSpaceException.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/file/InsufficientSpaceException.java	(revision 13666)
@@ -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/start/gli/src/org/greenstone/gatherer/file/UnknownFileErrorException.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/file/UnknownFileErrorException.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/file/UnknownFileErrorException.java	(revision 13666)
@@ -0,0 +1,11 @@
+package org.greenstone.gatherer.file;
+
+import java.lang.Exception;
+
+public class UnknownFileErrorException
+	 extends Exception {
+
+	 public UnknownFileErrorException() {
+		  super();
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/AboutDialog.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/AboutDialog.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/AboutDialog.java	(revision 13666)
@@ -0,0 +1,151 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+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.Utility;
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3c
+ */
+public class AboutDialog
+	 extends JDialog {
+	 private AboutDialog self;
+	 private JButton close_button;
+
+	 static final private Dimension SIZE = new Dimension(600, 325);
+	 static final private int ICON_SIZE = 65;
+
+	 public AboutDialog(JFrame parent) {
+		  super(parent, get("Title"), true);
+		  this.self = this;
+		  setSize(SIZE);
+		  
+		  JPanel content_pane = (JPanel) getContentPane();
+		  JPanel upper_pane = new JPanel();
+		  ImageIcon icon = Utility.getImage("medgath.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(get("Title_One"));
+		  JLabel title_two_label = new JLabel(Utility.PROGRAM_NAME + " " + Utility.PROGRAM_VERSION);
+		  JLabel title_three_label = new JLabel(get("Title_Two"));
+		  JLabel copyright_label = new JLabel(get("Copyright"));
+		  JTextArea text = new JTextArea();
+		  text.setLineWrap(true);
+		  text.setWrapStyleWord(true);
+		  JPanel button_pane = new JPanel();
+		  close_button = new JButton(get("General.Close"));
+
+		  // Connection
+		  close_button.addActionListener(new CloseButtonListener());
+
+		  // Layout
+		  icon_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,10));
+
+		  title_pane.setLayout(new GridLayout(4,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);
+		  
+		  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(get("Java_Req"));
+		  text.append("\n");
+		  text.append(get("Java_Req_One"));
+		  text.append("\n");
+		  text.append(get("Java_Req_Two"));
+		  text.append("\n\n");
+		  text.append("*****" + get("Acknowledgement") + "*****");
+		  text.append("\n\n");
+		  text.append(get("Item0"));
+		  text.append("\n\n");
+		  text.append(get("Item1"));
+		  text.append("\n\n");
+		  text.append(get("Item2"));
+		  text.append("\n\n");
+		  text.append(get("Item3"));
+		  text.append("\n\n");
+		  text.append("*****" + get("Thanks") + "*****");
+		  text.append("\n\n");
+		  text.append(get("Item4"));
+		  text.append("\n\n");
+		  text.append(get("Item5"));
+		  text.append("\n\n");
+		  text.append(get("Item6"));
+		  text.append("\n\n");
+		  text.append(get("Item7"));
+		  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);
+		  show();
+	 }
+
+	 private class CloseButtonListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				self.hide();
+				self.dispose();
+		  }
+	 }
+
+	 static private String get(String key) {
+		  if(key.indexOf(".") == -1) {
+				key = "AboutDialog." + key;
+		  }
+		  return Gatherer.dictionary.get(key);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/BorderFactory.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/BorderFactory.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/BorderFactory.java	(revision 13666)
@@ -0,0 +1,104 @@
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import org.greenstone.gatherer.gui.border.TitledBorder;
+/** Gatherers own version of the javax.swing.BorderFactory which has two major differences: firstly the titled borders returned are org.greenstone.gatherer.gui.border.TitledBorders which are aware who their parents are and are -not- ever shared. The second difference is that I haven't been so much of a biarch as to use a private contructor so as prevent any other programmer in the world from extending my class. Jaded? Me? Nah.
+ * @author John Thompson, Digital Library, University of Waikato.
+ * @version 2.3
+ */
+public class BorderFactory {
+	 /** Creates a beveled border of the specified type, using brighter shades of the component's current background color for highlighting, and darker shading for shadows. */
+	 static public Border createBevelBorder(int type) {
+		  return javax.swing.BorderFactory.createBevelBorder(type);
+	 }
+	 /** Creates a beveled border of the specified type, using the specified highlighting and shadowing. */
+	 static public Border createBevelBorder(int type, Color highlight, Color shadow) {
+		  return javax.swing.BorderFactory.createBevelBorder(type, highlight, shadow);
+	 }
+	 /** Creates a beveled border of the specified type, using the specified colors for the inner and outer highlight and shadow areas. */
+	 static public Border createBevelBorder(int type, Color highlightOuter, Color highlightInner, Color shadowOuter, Color shadowInner) {
+		  return javax.swing.BorderFactory.createBevelBorder(type, highlightOuter, highlightInner, shadowOuter, shadowInner);
+	 }
+	 /** Creates a compound border with a null inside edge and a null outside edge. */
+	 static public CompoundBorder createCompoundBorder() {
+		  return javax.swing.BorderFactory.createCompoundBorder();
+	 }
+	 /** Creates a compound border specifying the border objects to use for the outside and inside edges. */
+	 static public CompoundBorder createCompoundBorder(Border outsideBorder, Border insideBorder) {
+		  return javax.swing.BorderFactory.createCompoundBorder(outsideBorder, insideBorder);
+	 }
+	 /** Creates an empty border that takes up no space. */
+	 static public Border createEmptyBorder() {
+		  return javax.swing.BorderFactory.createEmptyBorder();
+	 }
+	 /** Creates an empty border that takes up space but which does no drawing, specifying the width of the top, left, bottom, and right sides. */
+	 static public Border createEmptyBorder(int top, int left, int bottom, int right) {
+		  return javax.swing.BorderFactory.createEmptyBorder(top, left, bottom, right);
+	 }
+	 /** Creates a border with an "etched" look using the component's current background color for highlighting and shading. */
+	 static public Border createEtchedBorder() {
+		  return javax.swing.BorderFactory.createEtchedBorder();
+	 }
+	 /** Creates a border with an "etched" look using the specified highlighting and shading colors. */
+	 static public Border createEtchedBorder(Color highlight, Color shadow) {
+		  return javax.swing.BorderFactory.createEtchedBorder(highlight, shadow);
+	 }
+	 /** Creates a border with an "etched" look using the component's current background color for highlighting and shading. */
+	 static public Border createEtchedBorder(int type) {
+		  return javax.swing.BorderFactory.createEtchedBorder(type);
+	 }
+	 /** Creates a border with an "etched" look using the specified highlighting and shading colors. */
+	 static public Border createEtchedBorder(int type, Color highlight, Color shadow) {
+		  return javax.swing.BorderFactory.createEtchedBorder(type, highlight, shadow);
+	 }
+	 /** Creates a line border withe the specified color. */
+	 static public Border createLineBorder(Color color) {
+		  return javax.swing.BorderFactory.createLineBorder(color);
+	 }
+	 /** Creates a line border with the specified color and width. */
+	 static public Border createLineBorder(Color color, int thickness) {
+		  return javax.swing.BorderFactory.createLineBorder(color, thickness);
+	 }
+	 /** Creates a border with a lowered beveled edge, using brighter shades of the component's current background color for highlighting, and darker shading for shadows. */
+	 static public Border createLoweredBevelBorder() {
+		  return javax.swing.BorderFactory.createLoweredBevelBorder();
+	 }
+	 /** Creates a matte-look border using a solid color. */
+	 static public MatteBorder createMatteBorder(int top, int left, int bottom, int right, Color color) {
+		  return javax.swing.BorderFactory.createMatteBorder(top, left, bottom, right, color);
+	 }
+	 /** Creates a matte-look border that consists of multiple tiles of a specified icon. */
+	 static public MatteBorder createMatteBorder(int top, int left, int bottom, int right, Icon tileIcon) {
+		  return javax.swing.BorderFactory.createMatteBorder(top, left, bottom, right, tileIcon);
+	 }
+	 /** Creates a border with a raised beveled edge, using brighter shades of the component's current background color for highlighting, and darker shading for shadows. */
+	 static public Border createRaisedBevelBorder() {
+		  return javax.swing.BorderFactory.createRaisedBevelBorder();
+	 }
+	 /** Creates a new title border with an empty title specifying the border object, using the default text position (sitting on the top line) and default justification (leading) and using the default font, and text color. */
+	 static public org.greenstone.gatherer.gui.border.TitledBorder createTitledBorder(Border border) {
+		  return new org.greenstone.gatherer.gui.border.TitledBorder(border);
+	 }
+	 /** Adds a title to an existing border, specifying the text of the title, using the default positioning (sitting on the top line) and default justification (leading) and using the default font and text color determined by the current look and feel. */
+	 static public org.greenstone.gatherer.gui.border.TitledBorder createTitledBorder(Border border, String title) {
+		  return new org.greenstone.gatherer.gui.border.TitledBorder(border, title);
+	 }
+	 /** Adds a title to an existing border, specifying the text of the title along with its positioning, using the default font and text color determined by the current look and feel. */
+	 static public org.greenstone.gatherer.gui.border.TitledBorder createTitledBorder(Border border, String title, int justification, int position) {
+		  return new org.greenstone.gatherer.gui.border.TitledBorder(border, title, justification, position);
+	 }
+	 /** Adds a title to an existing border, specifying the text of the title along with its positioning and font, using the default text color determined by the current look and feel. */
+	 static public org.greenstone.gatherer.gui.border.TitledBorder createTitledBorder(Border border, String title, int justification, int position, Font font) {
+		  return new org.greenstone.gatherer.gui.border.TitledBorder(border, title, justification, position, font);
+	 }
+	 /** Adds a title to an existing border, specifying the text of the title along with its positioning, font, and color. */
+	 static public org.greenstone.gatherer.gui.border.TitledBorder createTitledBorder(Border border, String title, int justification, int position, Font font, Color color) {
+		  return new org.greenstone.gatherer.gui.border.TitledBorder(border, title, justification, position, font, color);
+	 }
+	 /** Creates a new title border specifying the text of the title, using the default border (etched), using the default text position (sitting on the top line) and default justification (leading) and using the default font and text color determined by the current look and feel. */
+	 static public org.greenstone.gatherer.gui.border.TitledBorder createTitledBorder(String title) {
+		  return new org.greenstone.gatherer.gui.border.TitledBorder(title);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/BrowsingPane.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/BrowsingPane.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/BrowsingPane.java	(revision 13666)
@@ -0,0 +1,376 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import calpa.html.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.net.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.util.GURL;
+import org.greenstone.gatherer.util.Utility;
+/** This class provides browser-like functionality, with all the standard buttons. The only tricky bit is that the bookmarks are collection specific.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class BrowsingPane
+	 extends JPanel {
+	 private Bookmarks bookmarks = null;
+	 private CalHTMLPane view_pane = null;
+	 private CalHTMLPreferences preferences = null;
+	 private int back_count = 0;
+	 private int forward_count = 0;
+	 private JButton back_button = null;
+	 private JButton bookmarks_button = null; // Collection bookmarks.
+	 private JButton forward_button = null;
+	 private JButton go_button = null;
+	 private JButton home_button = null;
+	 private JButton refresh_button = null;
+	 private JButton reload_button = null;
+	 private JButton stop_button = null;
+	 private JLabel status_label = null;
+	 private JTextField address_field = null;
+	 private Observer observer = null;
+	 private String args[] = null;
+	 static final String BOOKMARKS_FILE = "bookmarks.txt";
+	 public BrowsingPane() {
+		  super();
+		  // Initialization
+		  bookmarks = new Bookmarks(); // Empty until collection loaded.
+		  observer = new Observer();
+		  preferences = new CalHTMLPreferences();
+		  preferences.setHomeURL((new GURL(Gatherer.config.getString("general.home_page", false))).getURL());
+		  // Creation
+		  //   Controls
+		  JPanel button_pane = new JPanel();
+		  JPanel left_button_pane = new JPanel();
+		  back_button = new JButton("", Utility.getImage("back.gif"));
+		  back_button.setEnabled(false);
+		  back_button.setToolTipText(get("Back"));
+		  refresh_button = new JButton("", Utility.getImage("reload.gif"));
+		  refresh_button.setEnabled(false);
+		  refresh_button.setToolTipText(get("Reload"));
+		  bookmarks_button = new JButton("", Utility.getImage("bookmark.gif"));
+		  bookmarks_button.setToolTipText(get("Bookmarks"));
+		  home_button = new JButton("", Utility.getImage("home.gif"));
+		  home_button.setToolTipText(get("Home"));
+		  JPanel address_pane = new JPanel();
+		  address_field = new JTextField(Gatherer.config.getString("general.home_page", false));
+		  JPanel right_button_pane = new JPanel();
+		  go_button = new JButton("", Utility.getImage("go.gif"));
+		  go_button.setToolTipText(get("Go"));
+		  stop_button = new JButton("", Utility.getImage("stop.gif"));
+		  stop_button.setEnabled(false);
+		  stop_button.setToolTipText(get("Stop"));
+		  forward_button = new JButton("", Utility.getImage("forward.gif"));
+		  forward_button.setEnabled(false);
+		  forward_button.setToolTipText(get("Forward"));
+		  //   Calpa Pane stuff
+		  view_pane = new CalHTMLPane(preferences, observer, "VIEW_PANE");
+		  //   Status bar
+		  status_label = new JLabel(get("Ready"));
+		  // Connection
+		  address_field.addActionListener(new AddressFieldListener());
+		  back_button.addActionListener(new BackButtonListener());
+		  bookmarks_button.addActionListener(new BookMarksButtonListener());
+		  forward_button.addActionListener(new ForwardButtonListener());
+		  go_button.addActionListener(new GoButtonListener());
+		  home_button.addActionListener(new HomeButtonListener());
+		  refresh_button.addActionListener(new RefreshButtonListener());
+		  stop_button.addActionListener(new StopButtonListener());
+		  // Layout
+		  left_button_pane.setLayout(new GridLayout(1,3));
+		  left_button_pane.add(back_button);
+		  left_button_pane.add(bookmarks_button);
+		  left_button_pane.add(home_button);
+
+		  address_pane.setBorder(BorderFactory.createEmptyBorder(10,5,10,5));
+		  address_pane.setLayout(new BorderLayout());
+		  address_pane.add(address_field, BorderLayout.CENTER);
+
+		  right_button_pane.setLayout(new GridLayout(1,3));
+		  right_button_pane.add(go_button);
+		  right_button_pane.add(stop_button);
+		  right_button_pane.add(forward_button);
+
+		  button_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		  button_pane.setLayout(new BorderLayout());
+		  button_pane.add(left_button_pane, BorderLayout.WEST);
+		  button_pane.add(address_pane, BorderLayout.CENTER);
+		  button_pane.add(right_button_pane, BorderLayout.EAST);
+
+		  setLayout(new BorderLayout());
+		  add(button_pane, BorderLayout.NORTH);
+		  add(new JScrollPane(view_pane), BorderLayout.CENTER);
+		  add(status_label, BorderLayout.SOUTH);
+	 }
+	 /** Some actions, such as getting the HTML to render properly without throwing sixty bazillion NPE's, can only occur after the frame has been drawn to screen. To this end we have this method so we can action things -after- the frame draw.
+	  */
+	 public void afterDisplay() {
+		  view_pane.goHome();
+	 }
+
+	 /** Called when a significant change occurs to the currently loaded collection.
+	  * @param ready <i>true</i> if there is a collection ready to be accessed.
+	  */
+	 public void collectionChanged(boolean ready) {
+		  // Reload the bookmarks associated with this collection.
+		  if(ready) {
+				bookmarks.load();
+		  }
+		  else {
+				bookmarks.clear();
+		  }
+	 }
+
+	 /** If some external class has possibly changed the state of the browsing pane then the controls should be repolled to determine which are still valid.
+	  */
+	 public void controlsChanged() {
+	 }
+
+	 /** Retrieves the current address entered in the address Textfield.
+	  * @return A <strong>String</strong> representing the currently entered address.
+	  */
+	 public String getCurrentURL() {
+		  return address_field.getText();
+	 }
+
+
+	 /** Retrieves a key from the Dictionary, using no extra arguments.
+	  * @param key A <strong>String</strong> which maps to a certain phrase from the Dictionary.
+	  * @return The <strong>String</strong> that matches the key or an error message if no match was found.
+	  */
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+
+	 /** Retrieves a key from the Dictionary, providing extra arguments to be inserted using a String array.
+	  * @param key A <strong>String</strong> which maps to a certain phrase from the Dictionary.
+	  * @param args A <strong>String[]</strong> containing further arguments (such as formatting instructions and variable values) to be taken into account when Dictionary creates the return String.
+	  * @return The <strong>String</strong> that matches the key or an error message if no match was found.
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf('.') == -1) {
+				key = "Browser." + key;
+		  }
+		  return Gatherer.dictionary.get(key,args);
+	 }
+/** Called to validate the status of the controls. Disables those that are no longer applicable or restores those that have come back into scope of usage.
+	  * @param update_address <i>true</i> if this pollControls call should update the address bar, <i>false</i> otherwise.
+	  */
+	 private void validateControls() {
+		  back_button.setEnabled(back_count > 0);
+		  forward_button.setEnabled(forward_count > 0);
+	 }
+
+	 private class AddressFieldListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				// Attempt to create a GURL
+				GURL url = new GURL(address_field.getText());
+				address_field.setText(url.getURL().toString());
+				if(url.valid()) {
+					 // Now load document
+					 view_pane.showHTMLDocument(url.getURL());					 
+					 back_count++;
+					 forward_count = 0;
+				}
+				validateControls();
+		  }
+	 }
+	 
+	 private class BackButtonListener 
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				view_pane.goBack();
+				back_count--;
+				forward_count++;
+				validateControls();
+		  }
+	 }
+
+	 private class Bookmarks
+		  extends JDialog {
+
+		  private DefaultListModel data = null;
+
+		  public Bookmarks() {
+				data = new DefaultListModel();
+		  }
+
+		  public void clear() {
+				data.removeAllElements();
+				// Re-add the "Add Bookmark" entry.
+				//add
+		  }
+
+		  public void load() {
+				// Clear existing
+				data.removeAllElements();
+				// Determine the file to load from...
+				File bookmarks = new File(Gatherer.c_man.getCollectionDirectory() + BOOKMARKS_FILE);
+				if(bookmarks.exists()) {
+					 // Read in file line at a time adding to bookmarks.
+				}
+		  }
+
+		  public int count() {
+				return data.size();
+		  }
+
+		  private class Entry {
+				public String title = null;
+				public URL url = null;
+				public Entry(String title, String url_raw) {
+					 this.title = title;
+					 try {
+						  url = new URL(url_raw);
+					 }
+					 catch(Exception error) {
+
+					 }
+				}
+				public String toString() {
+					 return title;
+				}
+		  }
+	 }
+
+	 private class BookMarksButtonListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				
+		  }
+	 }
+	 
+	 private class ForwardButtonListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				view_pane.goForward();
+				back_count++;
+				forward_count--;
+				validateControls();
+		  }
+	 }
+	 
+	 private class GoButtonListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				// Attempt to create a GURL
+				GURL url = new GURL(address_field.getText());
+				address_field.setText(url.getURL().toString());
+				if(url.valid()) {
+					 // Now load document
+					 view_pane.showHTMLDocument(url.getURL());	
+					 back_count++;
+					 forward_count = 0;
+				}
+				validateControls();
+		  }
+	 }
+	 
+	 private class HomeButtonListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				address_field.setText(Gatherer.config.getString("general.home_page", false));
+				view_pane.goHome();
+				back_count++;
+				forward_count = 0;
+				validateControls();
+		  }
+	 }
+	 
+	 private class RefreshButtonListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				view_pane.reloadDocument();
+				validateControls();
+		  }
+	 }
+
+	 private class StopButtonListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				view_pane.stopAll();
+				validateControls();
+		  }
+	 }
+
+	 private class Observer
+		  extends DefaultCalHTMLObserver {
+		  public void linkActivatedUpdate(CalHTMLPane pane, URL url, String target_frame, String j_name) {
+				address_field.setText(url.toString());
+				back_count++;
+				validateControls();
+		  }
+		  public void linkFocusUpdate(CalHTMLPane pane, URL url) {
+				///ystem.err.println("Link in focus " + url.toString());
+				args = new String[1];
+				args[0] = url.toString();
+				status_label.setText(get("Follow"));
+				args = null;
+		  }
+		  public void statusUpdate(CalHTMLPane pane, int state, URL url, int value, String message) {
+				switch(state) {
+				case 11:
+					 // Can only stop if somethings happening.
+					 stop_button.setEnabled(true);
+					 args = new String[1];
+					 args[0] = url.toString();
+					 status_label.setText(get("Loading", args));
+					 args = null;
+					 break;
+				case 14:
+					 // All done.
+					 stop_button.setEnabled(false);
+					 // Rendering complete.
+					 status_label.setText(get("Ready"));
+					 go_button.setEnabled(true);
+					 stop_button.setEnabled(false);
+					 refresh_button.setEnabled(true);
+					 // Update mirror pane
+					 Gatherer.g_man.mirror_pane.setURL(url.toString());
+					 break;
+				case 74:
+					 address_field.setText(url.toString());
+				default:
+					 ///ystem.err.println(state + ": " + url + " \"" + message + "\"");
+				}
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/BuildOptions.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/BuildOptions.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/BuildOptions.java	(revision 13666)
@@ -0,0 +1,283 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.io.*;
+import java.util.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.Utility;
+/** This data-only class contains all of the import and build options which persist between sessions, which currently is all of them. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class BuildOptions 
+	 implements Serializable {
+	 /** Do we include empty classifications? */
+	 public boolean allclassifications = false;
+	 /** Have we set an archive directory? */
+	 public boolean archivedir = false;
+	 /** Have we set a build directory? */
+	 public boolean builddir = false;
+	 /** Do we want debug information? */
+	 public boolean debug = false;
+	 /** Have we set a collect directory? */
+	 public boolean collectdir = false;
+	 /** Do we want the build process to create images as it goes along? */
+	 public boolean create_images = false;
+	 /** Have we set a groupsize value? */
+	 public boolean groupsize = false;
+	 /** Do we want the contents of the archive directory zipped? */
+	 public boolean gzip = false;
+	 /** Have we set an import directory? */
+	 public boolean importdir = false;
+	 /** Have we selected to build the collection on certain indexes? */
+	 public boolean index = false;
+	 /** Do we explicitly want to keep the archives dir? */
+	 public boolean keepold = false;
+	 /** Have we set a maxdocs value? */
+	 public boolean maxdocs = false;
+	 /** Have we selected a certain mode to build in? */
+	 public boolean mode = false;
+	 /** Do we build the indexes, but store no compressed text? */
+	 public boolean notext = false;
+	 /** Have we decided on a OID type? */
+	 public boolean oidtype = false;
+	 /** Have we set an out file? */
+	 public boolean out = false;
+	 /** Do we explicitly want to remove the archives dir? */
+	 public boolean removeold = false;
+	 /** Have we choosen a metadata element to sort on? */
+	 public boolean sortmeta = false;
+	 /** Have we set a verbosity value? */
+	 public boolean verbosity = false;
+	 /** How many documents to a hash group in the archive? */
+	 public int groupsize_value = 1;
+	 /** What is the maximum number of documents to process? */
+	 public int maxdocs_value = 1;
+	 /** What is the desired level of verbosity? */
+	 public byte verbosity_value = 0;
+	 /** The archive directory. */
+	 public String archivedir_value = "";
+	 /** The building directory. */
+	 public String builddir_value = "";
+	 /** The collect directory. */
+	 public String collectdir_value = "";
+	 /** The import directory. */
+	 public String importdir_value = "";
+	 /** The build mode. */
+	 public String mode_value = "";
+	 /** The OID generation method. */
+	 public String oidtype_value = "";
+	 /** The name of the file to write std_err to. */
+	 public String out_value = "";
+	 /** The name of the metadata element to sort the collection by. */ 
+	 public String sortmeta_value = "";
+	 /** The names of classifiers to be indexes for. */
+	 public String[] index_value = null;
+	 /** Element of argument type enumeration. */
+	 static final public byte BUILD_ARGS = 0;
+	 /** Element of argument type enumeration. */
+	 static final public byte IMPORT_ARGS = 1;
+	 /** Element of option type enumeration. */
+	 static final public byte ALLCLASSIFICATIONS = 0;
+	 /** Element of option type enumeration. */
+	 static final public byte ARCHIVEDIR = 1;
+	 /** Element of option type enumeration. */
+	 static final public byte BUILDDIR = 2;
+	 /** Element of option type enumeration. */
+	 static final public byte DEBUG = 3;
+	 /** Element of option type enumeration. */
+	 static final public byte COLLECTDIR = 4;
+	 /** Element of option type enumeration. */
+	 static final public byte CREATEIMAGES = 5;
+	 /** Element of option type enumeration. */
+	 static final public byte GROUPSIZE = 6;
+	 /** Element of option type enumeration. */
+	 static final public byte GZIP = 7;
+	 /** Element of option type enumeration. */
+	 static final public byte IMPORTDIR = 8;
+	 /** Element of option type enumeration. */
+	 static final public byte INDEX = 9;
+	 /** Element of option type enumeration. */
+	 static final public byte KEEPOLD = 10;
+	 /** Element of option type enumeration. */
+	 static final public byte MAXDOCS = 11;
+	 /** Element of option type enumeration. */
+	 static final public byte MODE = 12;
+	 /** Element of option type enumeration. */
+	 static final public byte NOTEXT = 13;
+	 /** Element of option type enumeration. */
+	 static final public byte OIDTYPE = 14;
+	 /** Element of option type enumeration. */
+	 static final public byte OUT = 15;
+	 /** Element of option type enumeration. */
+	 static final public byte REMOVEOLD = 16;
+	 /** Element of option type enumeration. */
+	 static final public byte SORTMETA = 17;
+	 /** Element of option type enumeration. */
+	 static final public byte VERBOSITY = 18;
+	 /** This constructor initializes values by using the current configuration and collect if there is one.
+	  */
+	 public BuildOptions() {
+		  collectdir_value = Utility.getCollectionDir(Gatherer.config.gsdl_path);
+		  // If we have a collection open gets its details.
+		  if(Gatherer.c_man.ready()) {
+				archivedir_value = Gatherer.c_man.getCollectionArchive();
+				builddir_value = Gatherer.c_man.getCollectionBuild();
+				importdir_value = Gatherer.c_man.getCollectionImport();
+		  }
+	 }
+	 /** This method returns a copy of this current <strong>BuildOptions</strong> object. Tried using stupid <i>Clonable</i> interface but it didn't work.
+	  * @return A <strong>BuildOptions</strong> object with the same settings as this one.
+	  */
+	 public BuildOptions copy() {
+		  BuildOptions options = new BuildOptions();
+		  options.allclassifications = allclassifications;
+		  options.archivedir = archivedir;
+		  options.builddir = builddir;
+		  options.debug = debug;
+		  options.collectdir = collectdir;
+		  options.create_images = create_images;
+		  options.groupsize = groupsize;
+		  options.gzip = gzip;
+		  options.importdir = importdir;
+		  options.index = index;
+		  options.keepold = keepold;
+		  options.maxdocs = maxdocs;
+		  options.mode = mode;
+		  options.notext = notext;
+		  options.oidtype = oidtype;
+		  options.out = out;
+		  options.removeold = removeold;
+		  options.sortmeta = sortmeta;
+		  options.verbosity = verbosity;
+		  options.groupsize_value = groupsize_value;
+		  options.maxdocs_value = maxdocs_value;
+		  options.verbosity_value = verbosity_value;
+		  options.archivedir_value = archivedir_value;
+		  options.builddir_value = builddir_value;
+		  options.collectdir_value = collectdir_value;
+		  options.importdir_value = importdir_value;
+		  options.mode_value = mode_value;
+		  options.oidtype_value = oidtype_value;
+		  options.out_value = out_value;
+		  options.sortmeta_value = sortmeta_value;
+		  options.index_value = index_value;
+		  return options;
+	 }
+	 /** When called this method returns the required arguments selected by the user. Only those arguments that are selected are returned, and even then some are never returned (i.e -out which is handled within the GShells instead).
+	  * @param type The type of process that will recieve these arguments as a <strong>byte</strong>.
+	  * @return A <strong>String[]</strong> containing the arguments and any required parameters as set by the user.
+	  */
+	 public String[] getArguments(byte type) {
+		  ArrayList arguments = new ArrayList();
+		  if(allclassifications && type == BUILD_ARGS) {
+				arguments.add("-allclassifications");
+		  }
+		  if(archivedir) {
+				arguments.add("-archivedir");
+				arguments.add(archivedir_value);
+		  }
+		  if(builddir && type == BUILD_ARGS) {
+				arguments.add("-builddir");
+				arguments.add(builddir_value);
+		  }
+		  if(debug) {
+				arguments.add("-debug");
+		  }
+		  if(collectdir) {
+				arguments.add("-collectdir");
+				arguments.add(collectdir_value);
+		  }
+		  if(create_images && type == BUILD_ARGS) {
+				arguments.add("-create_images");
+		  } 
+		  if(groupsize && type == IMPORT_ARGS) {
+				arguments.add("-groupsize");
+				arguments.add(String.valueOf(groupsize_value));
+		  }
+		  if(gzip && type == IMPORT_ARGS) {
+				arguments.add("-gzip");
+		  }
+		  // Always ignore importdir eh?
+		  if(false && importdir && type == IMPORT_ARGS) {
+				arguments.add("-importdir");
+				arguments.add(importdir_value);
+		  }
+		  if(index && type == BUILD_ARGS) {
+				arguments.add("-index");
+				StringBuffer temp = new StringBuffer("");
+				for(int i = 0; i < index_value.length; i++) {
+					 temp.append(index_value[i]);
+					 temp.append(",");
+				}
+				// Remember to remove extra ','
+				arguments.add(temp.substring(0, temp.length() - 1));
+		  }
+		  if(keepold) {
+				arguments.add("-keepold");
+		  }
+		  if(maxdocs) {
+				arguments.add("-maxdocs");
+				arguments.add(String.valueOf(maxdocs_value));
+		  }
+		  if(mode && type == BUILD_ARGS) {
+				arguments.add("-mode");
+				arguments.add(mode_value);
+		  }
+		  if(notext && type == BUILD_ARGS) {
+				arguments.add("-no_text");
+		  }
+		  if(oidtype && type == IMPORT_ARGS) {
+				arguments.add("-OIDtype");
+				arguments.add(oidtype_value);
+		  }
+		  // Never do out as its handled by the GShell.
+		  if(removeold && type == IMPORT_ARGS) {
+				arguments.add("-removeold");
+		  }
+		  if(sortmeta && type == IMPORT_ARGS) {
+				arguments.add("-sortmeta");
+				arguments.add(sortmeta_value);
+		  }
+		  if(verbosity) {
+				arguments.add("-verbosity");
+				arguments.add(String.valueOf(verbosity_value));
+		  }
+		  return ArrayTools.arrayListToStringArray(arguments);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/CollectionPane.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/CollectionPane.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/CollectionPane.java	(revision 13666)
@@ -0,0 +1,758 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+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.Gatherer;
+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.gui.Filter;
+import org.greenstone.gatherer.gui.GComboBox;
+import org.greenstone.gatherer.gui.tree.DragTree;
+import org.greenstone.gatherer.undo.UndoManager;
+import org.greenstone.gatherer.util.DragComponent;
+import org.greenstone.gatherer.util.DragGroup;
+import org.greenstone.gatherer.util.TreeSynchronizer;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.WinRegistry;
+/** 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 CollectionPane
+	 extends JPanel
+	 implements ActionListener, FocusListener {
+	 /** 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 DragTree collection_tree         =  null;
+	 /** The tree showing the available source workspace. */
+	 private DragTree workspace_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 collection model which is used to build, and hold the data of, the collection tree. */
+	 private TreeModel collection    = null;
+	 /** The GTree model used as the data source for the workspace tree. */
+	 private TreeModel workspace          =  null;
+	 /** The button used to cancel all pending file queue jobs. */
+	 private JButton cancel_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;
+	 /** Text fragment arguments used to fill in phrases returned from the dictionary. */
+	 private String args[]                 =  null;
+	 /** Ensures that expansion and selection events between collection trees based on the same model are synchronized. */
+	 private TreeSynchronizer collection_tree_sync = null;
+	 /** Ensures that expansion and selection events between workspace trees based on the same model are synchronized. */
+	 private TreeSynchronizer workspace_tree_sync = null;
+	 /** The button used to delete files, which also doubles as a drop target for files from the Trees. */
+	 private UndoManager bin_button            =  null;
+	 /** The default size of a label in the interface. */
+	 static final private Dimension LABEL_SIZE = new Dimension(100,30);
+	 /** The default size of a special mapping dialog. */
+	 static final Dimension DIALOG_SIZE = new Dimension(400, 120);
+	 /** 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);
+	 /* Constructor.
+	  * @param tree_sync Ensures that expansion events between like trees are synchronized.
+	  * @see org.greenstone.gatherer.file.FileManager
+	  * @see org.greenstone.gatherer.file.FileQueue
+	  */
+	 public CollectionPane(TreeSynchronizer workspace_tree_sync, TreeSynchronizer collection_tree_sync) {
+		  this.group = new DragGroup();
+		  this.file_queue = Gatherer.f_man.getQueue();
+		  this.collection_tree_sync = collection_tree_sync;
+		  this.workspace_tree_sync = workspace_tree_sync;
+
+		  // Create components.
+		  cancel_action = new JButton(Utility.getImage("big_stop.gif"));
+		  cancel_action.addActionListener(this);
+		  cancel_action.setEnabled(false);
+		  cancel_action.setMinimumSize(MIN_SIZE);
+		  cancel_action.setPreferredSize(MIN_SIZE);
+
+		  new_folder = new JButton(Utility.getImage("folder.gif"));
+		  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() == bin_button) {
+				if(!bin_button.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, bin_button, 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();
+					 FileNode node = (FileNode) path.getLastPathComponent();
+					 if(node.getAllowsChildren()) {
+						  Gatherer.f_man.newFolder(collection_tree, node);
+					 }
+					 else {
+						  error = true;
+					 }
+				}
+				else {
+					 error = true;
+				}
+				if(error) {
+					 JOptionPane.showMessageDialog(Gatherer.g_man, Gatherer.dictionary.get("FileActions.No_Parent_For_New_Folder"), Gatherer.dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
+				}
+		  }
+		  else if(event.getSource() == cancel_action) {
+				file_queue.cancelAction();
+		  }
+	 }
+	 /** Called whenever a significant change occurs in the current collections state, such as a new collection being loaded or the current one being closed. Several actions must occur in the GUI to indicate this change to the user, such as en/disabling the collection tree.
+	  * @param ready <i>true</i> if a collection is loaded and ready to be modified, <i>false</i> otherwise.
+	  * @see org.greenstone.gatherer.Configuration
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.CollectionManager
+	  * @see org.greenstone.gatherer.gui.Coloring
+	  * @see org.greenstone.gatherer.gui.Filter
+	  * @see org.greenstone.gatherer.util.TreeSynchronizer
+	  */
+	 public void collectionChanged(boolean ready) {
+		  // Try to retrieve the collections record set.
+		  collection = Gatherer.c_man.getRecordSet();
+		  if(collection != null) {
+				args = new String[1];
+				args[0] = Gatherer.c_man.getCollection().getName();
+				collection_label.setText(get("Collection", args));
+				collection_tree.setModel(collection);
+				collection_tree.repaint();
+				collection_tree.setRootVisible(true);
+				collection_filter.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
+		  }
+		  else {
+				String args[] = new String[1];
+				args[0] = get("Collection.No_Collection");
+				collection_label.setText(get("Collection", args));
+				args = null;
+				collection_tree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode("Error")));
+				collection_tree.setRootVisible(false);
+				collection_filter.setBackground(Color.lightGray);
+		  }
+		  
+		  collection_tree.setEnabled(ready);
+		  collection_filter.setEnabled(ready);
+
+		  // Change the label at the top of collection tree.
+		  setEnabled(collection_label, ready, Gatherer.config.getColor("coloring.collection_heading_foreground", false), Gatherer.config.getColor("coloring.collection_heading_background", false));
+		  // Ensure that this tree view of the collection record set is synchronized with any others.
+		  collection_tree_sync.add(collection_tree);
+
+		  workspace = Gatherer.c_man.getWorkspace();
+		  workspace_tree.setModel(workspace);
+		  workspace_tree_sync.add(workspace_tree);
+		  
+		  // Enable or disable the control buttons
+		  bin_button.setEnabled(ready);
+		  cancel_action.setEnabled(ready);
+		  new_folder.setEnabled(ready);
+	 }
+	 /** Generates the pane on controls used to 'collect' files into the collection. Resposible for creating, connecting and laying out these controls. */
+	 public void display() {
+		  // Create Components.
+		  KeyListenerImpl key_listener = new KeyListenerImpl();
+		  MouseListenerImpl mouse_listener = new MouseListenerImpl();
+		  this.addKeyListener(key_listener);
+
+		  // 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(get("Workspace"));
+		  workspace_label.setOpaque(true);
+		  workspace_label.setBackground(Gatherer.config.getColor("coloring.workspace_heading_background", false));
+		  workspace_label.setForeground(Gatherer.config.getColor("coloring.workspace_heading_foreground", false));
+
+		  workspace = Gatherer.c_man.getWorkspace();
+		  workspace_tree = new DragTree("Workspace", workspace, null);
+		  group.add(workspace_tree);
+		  workspace_tree.addFocusListener(this);
+		  workspace_tree.addKeyListener(key_listener);
+		  workspace_tree.addMouseListener(mouse_listener);
+		  workspace_tree.addMouseListener(Gatherer.g_man.foa_listener);
+		  workspace_tree.addTreeExpansionListener(Gatherer.g_man.foa_listener);
+		  workspace_tree.addTreeSelectionListener(file_queue);
+		  workspace_tree.putClientProperty("JTree.lineStyle", "Angled");
+		  workspace_tree.setBackgroundNonSelectionColor(Gatherer.config.getColor("coloring.workspace_tree_background", false));
+		  workspace_tree.setTextNonSelectionColor(Gatherer.config.getColor("coloring.workspace_tree_foreground", false));
+		  workspace_tree.setBackgroundSelectionColor(Gatherer.config.getColor("coloring.workspace_selection_background", false));
+		  workspace_tree.setTextSelectionColor(Gatherer.config.getColor("coloring.workspace_selection_foreground", false));
+		  workspace_tree.setRootVisible(false);
+
+		  workspace_scroll = new JScrollPane(workspace_tree);
+
+		  workspace_filter = Gatherer.g_man.getFilter(workspace_tree);
+		  workspace_filter.setBackground(Gatherer.config.getColor("coloring.workspace_heading_background", false));
+		  // Change the default colours of this filters combobox.
+		  GComboBox fcb = workspace_filter.getComboBox();
+		  fcb.setBackgroundNonSelectionColor(Gatherer.config.getColor("coloring.workspace_tree_background", false));
+		  fcb.setTextNonSelectionColor(Gatherer.config.getColor("coloring.workspace_tree_foreground", false));
+		  fcb.setBackgroundSelectionColor(Gatherer.config.getColor("coloring.workspace_selection_background", false));
+		  fcb.setTextSelectionColor(Gatherer.config.getColor("coloring.workspace_selection_foreground", false));
+		  fcb = null;
+
+		  // Collection Tree
+		  collection_pane = new JPanel();
+		  collection_pane.setMinimumSize(MIN_SIZE);
+		  collection_pane.setPreferredSize(TREE_SIZE);
+		  collection_pane.setSize(TREE_SIZE);
+
+		  args = new String[1];
+		  args[0] = get("Collection.No_Collection");
+		  collection_label = new JLabel(get("Collection", args));
+		  collection_label.setOpaque(true);
+
+		  collection = Gatherer.c_man.getRecordSet();
+		  if(collection != null) {
+				collection_tree = new DragTree("Collection", collection, null);
+				collection_tree.setEnabled(true);
+				collection_tree.setRootVisible(true);
+		  }
+		  else {
+				collection_tree = new DragTree("Collection", null);
+				collection_tree.setEnabled(false);
+				collection_tree.setRootVisible(false);
+		  }
+		  group.add(collection_tree);
+		  collection_tree.addFocusListener(this);
+		  collection_tree.addKeyListener(key_listener);
+		  collection_tree.addMouseListener(mouse_listener);
+		  collection_tree.addMouseListener(Gatherer.g_man.foa_listener);
+		  collection_tree.addTreeSelectionListener(file_queue);
+		  collection_tree.addTreeExpansionListener(Gatherer.g_man.foa_listener);
+		  collection_tree.putClientProperty("JTree.lineStyle", "Angled");
+		  collection_tree.setBackgroundNonSelectionColor(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  collection_tree.setTextNonSelectionColor(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+		  collection_tree.setBackgroundSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
+		  collection_tree.setTextSelectionColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
+
+		  collection_scroll = new JScrollPane(collection_tree);
+
+		  collection_filter = Gatherer.g_man.getFilter(collection_tree);
+		  if(collection != null) {
+				collection_filter.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
+		  }
+		  else {
+				collection_filter.setBackground(Color.lightGray);
+		  }
+		  // Change the default colours of this filters combobox.
+		  fcb = collection_filter.getComboBox();
+		  fcb.setBackgroundNonSelectionColor(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  fcb.setTextNonSelectionColor(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+		  fcb.setBackgroundSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
+		  fcb.setTextSelectionColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
+		  fcb = null;
+
+		  tree_pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
+
+		  // Status pane
+		  control_pane = new JPanel();
+
+		  JPanel inner_pane = new JPanel();
+		  inner_pane.setSize(STATUS_SIZE);
+
+		  JPanel file_pane = new JPanel();
+		  file_pane.setBackground(Color.white);
+		  //JPanel job_pane = new JPanel();
+		  //job_pane.setBackground(Color.white);
+		  JPanel progress_pane = new JPanel();
+		  progress_pane.setBackground(Color.white);
+		  JLabel file_status = file_queue.getFileStatus();
+		  //JLabel job_status = job_queue.getJobStatus();
+
+		  JProgressBar progress = file_queue.getProgress();
+
+		  JPanel button_pane = new JPanel();
+
+		  bin_button = Gatherer.c_man.undo;
+		  bin_button.addActionListener(this);
+		  bin_button.setEnabled(false);
+		  bin_button.setMinimumSize(MIN_SIZE);
+		  bin_button.setPreferredSize(MIN_SIZE);
+		  group.add(bin_button);
+		  
+		  // 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);
+		  collection_pane.add(collection_scroll, BorderLayout.CENTER);
+		  collection_pane.add(collection_filter, BorderLayout.SOUTH);
+
+		  tree_pane.add(workspace_pane, JSplitPane.LEFT);
+		  tree_pane.add(collection_pane, JSplitPane.RIGHT);
+		  tree_pane.setDividerLocation(TREE_SIZE.width - 10);
+
+		  //job_pane.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
+		  //job_pane.setLayout(new BorderLayout());
+		  //job_pane.add(job_status, BorderLayout.CENTER);
+
+		  file_pane.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
+		  file_pane.setLayout(new BorderLayout());
+		  file_pane.add(file_status, BorderLayout.CENTER);
+
+		  progress_pane.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
+		  progress_pane.setLayout(new BorderLayout());
+		  progress_pane.add(progress, 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(job_pane);
+		  inner_pane.add(file_pane);
+		  inner_pane.add(progress_pane);
+
+		  button_pane.add(cancel_action);
+		  button_pane.add(new_folder);
+		  button_pane.add(bin_button);
+
+		  control_pane.setLayout(new BorderLayout());
+		  //control_pane.add(new_folder, BorderLayout.WEST);
+		  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);
+	 }
+	 /** This method ensures that a certain tree path is visible and selected within the collection tree, expanding nodes if necessary. If the method is successful the bounds of the new selection are returned. */
+	 public Rectangle expandPath(TreePath path) {
+		  collection_tree.setImmediate(true);
+		  collection_tree.scrollPathToVisible(path);
+		  collection_tree.setSelectionPath(path);
+		  collection_tree.setImmediate(false);
+		  return collection_tree.getRowBounds(collection_tree.getRowForPath(path));
+	 }
+	 /** 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) {
+	 }
+	 /** Retrieve a list of the currently selected file records in the active tree. */
+	 public FileNode[] getSelected() {
+		  TreePath paths[] = collection_tree.getSelectionPaths();
+		  FileNode records[] = null;
+		  if(paths != null) {
+				records = new FileNode[paths.length];
+				for(int i = 0; i < records.length; i++) {
+					 records[i] = (FileNode) paths[i].getLastPathComponent();
+				}
+		  }
+		  return records;
+	 }
+
+	 public String getSelectionDetails() {
+		  return collection_tree.getSelectionDetails();
+	 }
+
+	 public DragTree getWorkspaceTree() {
+		  return workspace_tree;
+	 }
+
+	 public void refreshTrees() {
+		  collection_tree.refresh(null);
+	 }
+
+	 /** Retrieve a phrase from the dictionary based on the key.
+	  * @param key A <strong>String</strong> used to uniquely identify the phrase to be retrieved.
+	  */
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+	 /** Retrieve a phrase from the dictionary based on the key, and filled in using text fragments from an arguments array.
+	  * @param key A <strong>String</strong> used to uniquely identify the phrase to be retrieved.
+	  * @param args A <strong>String[]</strong> used as parameters to be inserted in the phrase retrieved.
+	  * @see org.greenstone.gatherer.Dictionary
+	  * @see org.greenstone.gatherer.Gatherer
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf('.') == -1) {
+				key = "Collection." + key;
+		  }
+		  return Gatherer.dictionary.get(key, args);
+	 }
+	 /** Used to set the enabled state, and hence the colouring, of the two tree labels.
+	  * @param label The <strong>JLabel</strong> to be affected.
+	  * @param state <i>true</i> for enabled, i.e. when a collection is ready, <i>false</i> otherwise.
+	  * @param foreground The <strong>Color</strong> to make the foreground text of the label when enabled.
+	  * @param background The <strong>Color</strong> to make the background of the label when enabled.
+	  */
+	 private void setEnabled(JLabel label, boolean state, Color foreground, Color background) {
+		  ///ystem.err.println("Setting the label color to state " + state);
+		  if(state) {
+				label.setBackground(background);
+				label.setForeground(foreground);
+		  }
+		  else {
+				label.setBackground(Color.lightGray);
+				label.setForeground(Color.black);
+		  }
+		  label.repaint();
+		  ///ystem.err.println("Color is now " + label.getBackground());
+	 }
+	 /** When a user right-clicks within the trees on the collection pane view they are presented with a small popup menu of context based options. This class provides such functionality.
+	  */
+	 private class GPopupMenu
+		  extends JPopupMenu
+		  implements ActionListener {
+		  /** The tree over which the right click action occured. */
+		  private DragTree tree = null;
+		  /** The file record over which the right click action occured, if any. */
+		  private FileNode node = null;
+		  /** A menu item enabled if a delete action is appropriate in the menus current context. */
+		  private JMenuItem delete = null;
+		  /** A menu item enabled if a special directory mapping is appropriate in the menus current context. */
+		  private JMenuItem map = null;
+		  /** A menu item enabled if a new folder action is appropriate in the menus current context. */
+		  private JMenuItem new_folder = null;
+		  /** A menu item enabled if a show meta-audit dialog action is appropriate in the menus current context. */
+		  private JMenuItem show_metaaudit = null;
+		  /** A menu item allowing a user to unmap a special directory, if and only if a special directory is selected. */
+		  private JMenuItem unmap = null;
+		  /** Constructor. */
+		  public GPopupMenu(DragTree tree, MouseEvent event) {
+				super();
+				this.tree = tree;
+				TreePath path = tree.getClosestPathForLocation(event.getX(), event.getY());
+				node = (FileNode)path.getLastPathComponent();
+				// Set Options based on selection and tree
+				if(tree.getSelectionCount() != 0 && tree == collection_tree) {
+					 show_metaaudit = new JMenuItem(get("Menu.Metadata_View") + " " + collection_tree.getSelectionDetails(), KeyEvent.VK_V);
+					 show_metaaudit.addActionListener(this);
+					 add(show_metaaudit);
+				}
+				if(tree == collection_tree && node != null && node.getFile() != null && node.getFile().isDirectory() && !node.isReadOnly()) {
+					 new_folder = new JMenuItem(get("New_Folder"), KeyEvent.VK_N);
+					 new_folder.addActionListener(this);
+					 add(new_folder);
+					 add(new JSeparator());
+				}
+				if(node == null || (node != null && !node.isReadOnly())) {
+					 delete = new JMenuItem(get("Delete"), KeyEvent.VK_D);
+					 delete.addActionListener(this);
+					 add(delete);
+				}
+				if(tree == workspace_tree && node != null && !node.isLeaf()) {
+					 String node_name = node.toString();
+					 FileNode root = (FileNode) tree.getModel().getRoot();
+					 if(!node_name.equals(get("Tree.World")) && !node_name.equals(get("Tree.Root")) && !node_name.equals(get("Tree.Public")) && !node_name.equals(get("Tree.Private"))) {
+						  // You can unmap 1st level nodes.
+						  if(root.getIndex(node) != -1) {
+								unmap = new JMenuItem(get("MappingPrompt.Unmap"), KeyEvent.VK_U);
+								unmap.addActionListener(this);
+								add(unmap);
+						  }
+						  // Or map any other level directories.
+						  else {
+								map = new JMenuItem(get("MappingPrompt.Map"), KeyEvent.VK_M);
+								map.addActionListener(this);
+								add(map);
+						  }
+					 }
+				}
+				show(tree, event.getX(), event.getY());
+		  }
+		  /** Called whenever one of the menu items is actioned apon, this method then causes the appropriate effect. */
+		  public void actionPerformed(ActionEvent event) {
+				if(event.getSource() == delete) {
+					 // Retrieve the selection. Of course this gets a bit tricky as the user may have right clicked over a node not in the current selection, in which case we remove only that node.
+					 TreePath[] selection_paths = tree.getSelectionPaths();
+					 if(selection_paths != null) {
+						  FileNode[] source_nodes = new FileNode[selection_paths.length];
+						  boolean found = false;
+						  for(int i = 0; i < selection_paths.length; i++) {
+								source_nodes[i] = (FileNode) selection_paths[i].getLastPathComponent();
+								if(node != null) {
+									 found = found || source_nodes[i].equals(node);
+								}
+						  }
+						  if(node != null && !found) {
+								source_nodes = null;
+								source_nodes = new FileNode[1];
+								source_nodes[0] = node;
+						  }
+						  // Fire a delete action
+						  Gatherer.f_man.action(tree, source_nodes, bin_button, null);
+						  source_nodes = null;
+					 }
+					 selection_paths = null;
+				}
+				else if(event.getSource() == map && node != null) {
+					 MappingPrompt mp = new MappingPrompt(node.getFile());
+					 mp.destroy();
+					 mp = null;
+				}
+				else if(event.getSource() == new_folder && node != null) {
+					 Gatherer.f_man.newFolder(tree, node);
+				}
+				else if(event.getSource() == show_metaaudit) {
+					 Gatherer.g_man.showMetaAuditBox();
+				}
+				else if(event.getSource() == unmap && node != null) {
+					 Gatherer.c_man.removeDirectoryMapping(node);
+				}
+		  }
+		  /** Retrieve a phrase from the dictionary based on the key.
+			* @param key A <strong>String</strong> used to uniquely identify the phrase to be retrieved.
+			*/
+		  private String get(String key) {
+				return get(key, null);
+		  }
+		  /** Retrieve a phrase from the dictionary based on the key, and filled in using text fragments from an arguments array.
+			* @param key A <strong>String</strong> used to uniquely identify the phrase to be retrieved.
+			* @param args A <strong>String[]</strong> used as parameters to be inserted in the phrase retrieved.
+			* @see org.greenstone.gatherer.Dictionary
+			* @see org.greenstone.gatherer.Gatherer
+			*/
+		  private String get(String key, String args[]) {
+				if(key.indexOf('.') == -1) {
+					 key = "CollectionPopupMenu." + key;
+				}
+				return Gatherer.dictionary.get(key, args);
+		  }
+	 }
+	 /** This class listens for certain key presses, such as [Enter] or [Delete], and responds appropriately. */
+	 private class KeyListenerImpl
+		  extends KeyAdapter {
+		  /** 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, bin_button, 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.isFile()) {
+								Gatherer.self.spawnApplication(file);
+						  }
+					 }
+				}
+		  }
+	 }
+
+	 /** This provides a small prompt for gathering addition details about a special directory mapping such as its symbolic name. */
+	 private class MappingPrompt
+		  extends JDialog 
+		  implements ActionListener, KeyListener {
+		  private boolean cancelled = false;
+		  private JButton cancel_button = null;
+		  private JButton ok_button = null;
+		  private JTextField name_field = null;
+		  public MappingPrompt(File file) {
+				super(Gatherer.g_man);
+				setModal(true);
+				setSize(DIALOG_SIZE);
+				setTitle(get("MappingPrompt.Title"));
+				// Creation
+				JPanel content_pane = (JPanel) getContentPane();
+				JPanel center_pane = new JPanel();
+				JPanel file_pane = new JPanel();
+				JLabel file_label = new JLabel(get("MappingPrompt.File"));
+				file_label.setPreferredSize(LABEL_SIZE);
+				JLabel file_field = new JLabel(file.getAbsolutePath());
+				JPanel name_pane = new JPanel();
+				JLabel name_label = new JLabel(get("MappingPrompt.Name"));
+				name_label.setPreferredSize(LABEL_SIZE);
+				name_field = new JTextField(file.getName());
+				JPanel button_pane = new JPanel();
+				ok_button = new JButton(get("General.OK"));
+				ok_button.setEnabled(name_field.getText().length() > 0);
+				cancel_button = new JButton(get("General.Cancel"));
+				// Connection
+				cancel_button.addActionListener(this);
+				ok_button.addActionListener(this);
+				name_field.addKeyListener(this);
+				// Layout
+				file_pane.setLayout(new BorderLayout());
+				file_pane.add(file_label, BorderLayout.WEST);
+				file_pane.add(file_field, BorderLayout.CENTER);
+				
+				name_pane.setLayout(new BorderLayout());
+				name_pane.add(name_label, BorderLayout.WEST);
+				name_pane.add(name_field, BorderLayout.CENTER);
+
+				center_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+				center_pane.setLayout(new GridLayout(2,1,5,5));
+				center_pane.add(file_pane);
+				center_pane.add(name_pane);
+
+				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 = Gatherer.config.screen_size;
+				setLocation((screen_size.width - DIALOG_SIZE.width) / 2, (screen_size.height - DIALOG_SIZE.height) / 2);
+				show();
+				// If not cancelled create mapping.
+				if(!cancelled) {
+					 Gatherer.c_man.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) {
+		  }
+	 }
+	 /** This class listens for mouse clicks and responds right mouse button clicks (popup menu). */
+	 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 mouseClicked(MouseEvent event) {
+				if(SwingUtilities.isRightMouseButton(event)) {
+					 new GPopupMenu((DragTree)event.getSource(), event);
+				}
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/Coloring.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/Coloring.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/Coloring.java	(revision 13666)
@@ -0,0 +1,134 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+package org.greenstone.gatherer.gui;
+/**************************************************************************************
+ * Title:        Gatherer
+ * Description:  The Gatherer: a tool for gathering and enriching a digital collection.
+ * Company:      The University of Waikato
+ * Written:        /  /02
+ * Revised:      03/10/02 - Commented
+ **************************************************************************************/
+import java.awt.Color;
+import java.io.Serializable;
+/** The coloring object is part of the Gatherers configuration, and stores the various colours used to render parts of the interface. In general these colours fall into three groups, those for the workspace, those for the collection and all other colour components.
+ * @author John Thompson
+ * @version 2.3
+ */
+public class Coloring 
+	 implements Serializable {
+	 /** The color of a buttons background. */
+	 public Color button_background;
+	 /** The color of a buttons foreground. */
+	 public Color button_foreground;
+	 /** The background color used to indicate that a button has been clicked or selected. */
+	 public Color button_selected_background;
+	 /** The foreground color used to indicate that a button has been clicked or selected. */
+	 public Color button_selected_foreground;
+	 /** The color used for the background of the collection label. */
+	 public Color collection_heading_background   = null;
+	 /** The color used for the text of the collection label. */
+	 public Color collection_heading_foreground   = null;
+	 /** The color used for the background of controls in the collection that are non-editable. */
+	 public Color collection_noneditable_background = null;
+	 /** The color used for the foreground of controls in the collection that are non-editable. */
+	 public Color collection_noneditable_foreground = null;
+	 /** The color used for the background of a selection from the collection. */
+	 public Color collection_selection_background = null;
+	 /** The color used for the text of a selection from the collection. */
+	 public Color collection_selection_foreground = null;
+	 /** The color used for the background of a collection oriented component. */
+	 public Color collection_tree_background      = null;
+	 /** The color used for the text of a collection oriented component. */
+	 public Color collection_tree_foreground      = null;	 
+	 /** The color used for the background of an error state oriented component. */
+	 public Color error_background;
+	 /** The color used for the text of an error state oriented component. */
+	 public Color error_foreground;
+	 /** The color used for the background (behind the slider) part of a scroll bar. */
+	 public Color scrollbar_background;
+	 /** The color usef for the foreground (slider and arrows) parts of a scroll bar. */
+	 public Color scrollbar_foreground;
+	 /** The color used for the background of the workspace label. */
+	 public Color workspace_heading_background    = null;
+	 /** The color used for the text of the workspace label. */
+	 public Color workspace_heading_foreground    = null;
+	 /** The color used for the background of a selection from the workspace. */
+	 public Color workspace_selection_background  = null;
+	 /** The color used for the text of a selection from the workspace. */
+	 public Color workspace_selection_foreground  = null;
+	 /** The color used for the background of a workspace oriented component. */
+	 public Color workspace_tree_background       = null;
+	 /** The color used for the text of a workspace oriented component. */
+	 public Color workspace_tree_foreground       = null;
+	 /** Constructor. Uses default colors. 
+	  */
+	 public Coloring() {
+		  // Default Values.
+		  // Collection
+		  collection_heading_background = new Color(176, 208, 176);  
+		  collection_heading_foreground = Color.black;
+		  collection_selection_background = new Color(128, 180, 216);
+		  collection_selection_foreground = Color.black;
+		  collection_tree_background = new Color(224, 240, 224);
+		  collection_tree_foreground = Color.black;	 
+		  collection_noneditable_background = Color.lightGray;
+		  collection_noneditable_foreground = Color.black;
+		  // Other
+		  button_background = Color.white;
+		  button_foreground = Color.black;
+		  button_selected_background = new Color(128, 180, 216);
+		  button_selected_foreground = Color.white;
+		  error_background = new Color(250, 180, 180);
+		  error_foreground = Color.red;
+		  scrollbar_background = Color.lightGray;
+		  scrollbar_foreground = Color.white;
+		  // Workspace
+		  workspace_heading_background = new Color(128, 180, 216);
+		  workspace_heading_foreground = Color.black;
+		  workspace_selection_background = new Color(176, 208, 176);
+		  workspace_selection_foreground = Color.black;
+		  workspace_tree_background = new Color(218, 237, 252);
+		  workspace_tree_foreground = Color.black;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/ComboArea.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/ComboArea.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/ComboArea.java	(revision 13666)
@@ -0,0 +1,203 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.text.*;
+import jp.gr.java_conf.tame.swing.combobox.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.SmarterTextArea;
+import org.greenstone.gatherer.util.Utility;
+/** Combines the idea of a combobox with a text area so that multiline entries can be displayed properly. Basically takes a JCombobox, (or in this case a SteppedComboBox that allows us to control the popup window that appears), butchers out the JTextField editor while retaining the button and the data model, then uses a JTextArea for the editor instead. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class ComboArea
+	 extends JPanel {
+	 /** Should the listener ignore any change events fired (most likely as a result of the listener in the first place). */
+	 private boolean ignore = false;
+	 /** The combobox we are going to utilize. */
+	 private SteppedComboBox combobox = null;
+	 /** The text area involved. Not quite a JTextArea, the smarter part is that is allows coloring contrary to the UIManager settings. */
+	 private SmarterTextArea text_area = null;
+	 /** Create a new ComboArea demarked by a particular label. The label is given here so that it fits nicely with the text area and button.
+	  * @param text The label text to be shown above text area as a <strong>String</strong>.
+	  * @param label_size The <strong>Dimension</strong> to use for the label.
+	  * @see jp.gr.java_conf.tame.swing.combobox.SteppedComboBox
+	  * @see org.greenstone.gatherer.gui.ComboArea.ComboAreaListener
+	  * @see org.greenstone.gatherer.gui.ComboArea.Renderer
+	  */
+	 public ComboArea(String text, Dimension label_size) {
+		  // Creation
+		  JPanel title_pane = new JPanel();
+		  title_pane.setOpaque(false);
+		  JLabel label = new JLabel(text);
+		  label.setOpaque(false);
+		  label.setPreferredSize(label_size);
+		  JPanel text_pane = new JPanel();
+		  text_area = new SmarterTextArea();
+		  text_area.setRows(3);
+		  JPanel button_pane = new JPanel();
+		  Dimension button_size = new Dimension(label_size.height, label_size.height);
+		  button_pane.setMaximumSize(button_size);
+		  button_pane.setMinimumSize(button_size);
+		  button_pane.setPreferredSize(button_size);
+		  button_pane.setSize(button_size);
+		  combobox = new SteppedComboBox(Gatherer.self, button_size);
+		  combobox.setDependant(text_area);
+		  combobox.setPreferredSize(label_size);
+		  combobox.setRenderer(new Renderer());
+		  // Connection
+		  combobox.addActionListener(new ComboAreaListener());
+		  // Layout
+		  title_pane.setLayout(new BorderLayout());
+		  title_pane.add(label, BorderLayout.WEST);
+
+		  button_pane.setLayout(new BorderLayout());
+		  button_pane.add(combobox.getButton(), BorderLayout.CENTER);
+
+		  text_pane.setLayout(new BorderLayout());
+		  text_pane.add(new JScrollPane(text_area), BorderLayout.CENTER);
+		  text_pane.add(button_pane, BorderLayout.EAST);
+
+		  setLayout(new BorderLayout());
+		  add(title_pane, BorderLayout.NORTH);
+		  add(text_pane, BorderLayout.CENTER);
+	 }
+	 /** Add an element to our combobox model. Remember to tell the listeners to ignore this action unless you want an infinite loop.
+	  * @param item The <strong>Object</strong> to add.
+	  */
+	 public void add(Object item) {
+		  ignore = true;
+		  combobox.add(item.toString());
+		  ignore = false;
+	 }
+	 /** Clear the combobox model.
+	  */
+	 public void clear() {
+		  combobox.clear();
+	 }
+	 /** Retrieve the text currently displayed in the text area.
+	  * @return A <strong>String</strong> containing the required text.
+	  */
+	 public String getText() {
+		  return text_area.getText();
+	 }
+	 /** Retrieve a reference to the text area.
+	  * @return A <strong>JTextComponent</strong> reference.
+	  */
+	 public JTextComponent getTextComponent() {
+		  return text_area;
+	 }
+	 /** Change the selected item in the combobox to the one given. If such an object doesn't exist in the model, ignore it. Notice that this time we don't ignore, as we want a selection to update the text field.
+	  * @param item The <strong>Object</strong> that we want to select from the combobox.
+	  */
+	 public void setSelectedItem(Object item) {
+		  combobox.setSelectedItem(item);
+	 }
+	 /** Set the text shown in the text area to the value provided. Note that this has no effect on the combobox, nor will this value be stored in the model.
+	  * @param text The <strong>String</strong> to display.
+	  */
+	 public void setText(String text) {
+		  text_area.setText(text);
+	 }
+	 /** This clas listens for changes in the selected item in the combobox and if applicable updates the text area to match. */
+	 private class ComboAreaListener
+		  implements ActionListener {
+		  /** Whenever a new object is selected from the combobox list, determine if this is an appropriate time to update the text area and if so do so.
+			* @param event An <strong>ActionEvent</strong> encompassing all the relevant data about an action having been performed.
+			*/
+		  public void actionPerformed(ActionEvent event) {
+				Object object = combobox.getSelectedItem();
+				if(object != null && !ignore) {
+					 text_area.setText(object.toString());
+				}
+		  }
+	 }
+	 /** This renderer is used to ensure that the labels shown in the combobox drop-down list are both correct in colouring and legible. The later is important as the entry itself may actually span several lines. */
+	 private class Renderer
+		  extends DefaultListCellRenderer {
+		  /** Retrieve the component used to 'rubberstamp' the desired entry in the combobox.
+			* @param list The <strong>JList</strong> this component will be renderer in.
+			* @param value The <strong>Object</strong> whose value should be represented by the component returned.
+			* @param index An <i>int</i> giving the objects index in the list of objects.
+			* @param isSelected <i>true</i> if this object is currently selected, <i>false</i> otherwise.
+			* @param cellHasFocus <i>true</i> if this object is currently in focus, <i>false</i> otherwise.
+			* @see org.greenstone.gatherer.util.Utility
+			*/
+		  public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+				JLabel temp = null;
+				if(value != null) {
+					 // Only show a single line by removing new lines.
+					 StringBuffer text = new StringBuffer(Utility.stripNL((String)value));
+					 // Generate prototype label
+					 temp = (JLabel) super.getListCellRendererComponent(list, text.toString(), index, isSelected, cellHasFocus);
+					 // Trim down the value string so it fits nicely. Start by shortening it to the number of characters determined from the smarter text area.
+					 int preferred_characters = text_area.calculateColumnCount();
+					 if(preferred_characters > 3 && text.length() > preferred_characters) {
+						  text.delete(preferred_characters - 3, text.length());
+						  text.append("...");
+					 }
+					 temp.setText(text.toString());
+					 // If we are still too long, shorten by one character at a time until it fits
+					 while(temp.getPreferredSize().width > text_area.getSize().width && text.length() > 4) {
+						  // Remove the last four characters and mark as being chopped
+						  text.delete(text.length() - 4, text.length());
+						  text.append("...");
+						  // Assign new string, rinse and repeat.
+						  temp.setText(text.toString());
+					 }
+				}
+				else {
+					 temp = (JLabel) super.getListCellRendererComponent(list, "", index, isSelected, cellHasFocus);
+				}
+				// Colouring should be the same as the dependant we are based on.
+				if(isSelected) {
+					 temp.setBackground(text_area.getSelectionColor());
+					 temp.setForeground(text_area.getSelectedTextColor());
+				}
+				else {
+					 temp.setBackground(text_area.getBackground());
+					 temp.setForeground(text_area.getForeground());
+				}
+				return temp;
+		  } 
+	 }
+}
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/CreatePane.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/CreatePane.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/CreatePane.java	(revision 13666)
@@ -0,0 +1,559 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.BuildOptions;
+import org.greenstone.gatherer.collection.Collection;
+import org.greenstone.gatherer.gui.OptionsPane;
+import org.greenstone.gatherer.shell.GBasicProgressMonitor;
+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;
+/** 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>
+ * <center><table width=80% border=2 cellspacing=0 cellpadding=2><tr><td align=center colspan=4>
+ * The (i)mport and/or (b)uild options supported:</td></tr> 
+ * <tr background=black><font color=white><td>Script</td><td>Associated Argument</td><td>Control</td><td>Comments</td></font></tr>
+ * <tr><td>b</td><td>-allclassifications</td><td>JCheckBox</td><td>&nbsp;</td></tr>
+ * <tr><td>i/b</td><td>-archivedir</td><td>JTextField</td><td>&nbsp;</td></tr>
+ * <tr><td>b</td><td>-builddir</td><td>JTextField</td><td>&nbsp;</td></tr>
+ * <tr><td>i/b</td><td>-debug</td><td>JCheckBox</td><td>&nbsp;</td></tr>
+ * <tr><td>i/b</td><td>-collectdir</td><td>JTextField</td><td>&nbsp;</td></tr>
+ * <tr><td>b</td><td>-create_images</td><td>JCheckBox</td><td>&nbsp;</td></tr>
+ * <tr><td>i</td><td>-groupsize</td><td>JSpinner </td><td>&nbsp;</td></tr>
+ * <tr><td>i</td><td>-gzip</td><td>JCheckBox</td><td>&nbsp;</td></tr>
+ * <tr><td>i</td><td>-importdir</td><td>JTextField</td><td>&nbsp;</td></tr>
+ * <tr><td>b</td><td>-index</td><td>GCheckList</td><td>&nbsp;</td></tr>
+ * <tr><td>i/b</td><td>-keepold</td><td>JCheckBox</td><td>sanity check removeold</td></tr>
+ * <tr><td>i/b</td><td>-maxdocs</td><td>JSpinner</td><td>&nbsp;</td></tr>
+ * <tr><td>b</td><td>-mode</td><td>JComboBox</td><td>"all", "compress_text", "infodb", "build_index"</td></tr>
+ * <tr><td>b</td><td>-no_text</td><td>JCheckBox</td><td>&nbsp;</td></tr>
+ * <tr><td>i</td><td>-OIDtype</td><td>JComboBox</td><td>"hash","incremental"</td></tr>
+ * <tr><td>i/b</td><td>-out</td><td>JTextField</td><td>&nbsp;</td></tr>
+ * <tr><td>i</td><td>-removeold</td><td>JCheckBox</td><td>sanity check keepold</td></tr>
+ * <tr><td>i</td><td>-sortmeta</td><td>JComboBox</td><td>&nbsp;</td></tr>
+ * <tr><td>i/b</td><td>-verbosity</td><td>JSpinner</td><td>1, 3</td></tr>
+ * </table></center>
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class CreatePane
+	 extends JPanel 
+	 implements GShellListener {
+	 /** 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;
+	 /** A card layout is used to store the separate configuration and progress panes. */
+	 private CardLayout card_layout = null;
+	 /** This monitor tracks the build processes progress. */
+	 private GShellProgressMonitor build_monitor = null;
+	 /** This monitor tracks the copy processes progress. */
+	 private GShellProgressMonitor copy_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 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 copy progress bar gets some special treatment so... */
+	 private JLabel progress_copy_label = null;
+	 /** The label alongside the import progress bar gets some special treatment so... */
+	 private JLabel progress_import_label = null;
+	 /** 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;
+	 /** This pane is the one that is updated to show the requested options view. */
+	 private JPanel target_pane = null;
+	 /** The scrolling pane the log is inside. */
+	 private JScrollPane scroll_log = null;
+	 private JScrollPane scroll_pane;
+	 /** The log for the current process. */
+	 private JTextArea process_log = null;
+	 /** The message log for the entire session. */
+	 private JTextArea message_log = new JTextArea();
+	 /** 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 size of the buttons at the bottom of the screen. */
+	 static private Dimension BUTTON_SIZE = new Dimension(386, 50);
+	 /** The size of the labels on the progress pane. */
+	 static private Dimension LABEL_SIZE = new Dimension(140, 25);
+	 /** 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";
+	 /** 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.GBasicProgressMonitor
+	  * @see org.greenstone.gatherer.shell.GBuildProgressMonitor
+	  * @see org.greenstone.gatherer.shell.GImportProgressMonitor
+	  * @see org.greenstone.gatherer.shell.GShellProgressMonitor
+	  */
+	 public CreatePane() {
+		  this.target_pane = new JPanel(new BorderLayout());
+		  Collection collection = Gatherer.c_man.getCollection();
+		  if(collection != null) {
+				this.options_pane = new OptionsPane(target_pane, message_log, collection.build_options);
+		  }
+		  // Create components
+		  card_layout = new CardLayout();
+		  // Control Pane
+		  control_pane = new JPanel();
+		  args = new String[1];
+		  args[0] = "0";
+		  document_count = new JLabel(get("Document_Count", args));
+		  tree = new OptionTree();
+		  // Progress Pane
+		  progress_pane = new JPanel();
+
+		  progress_copy_label = new JLabel(get("Copy_Progress"));
+		  progress_copy_label.setForeground(Color.black);
+		  progress_copy_label.setHorizontalAlignment(JLabel.LEFT);
+		  progress_copy_label.setPreferredSize(LABEL_SIZE);
+		  progress_copy_label.setMinimumSize(LABEL_SIZE);
+		  progress_copy_label.setSize(LABEL_SIZE);
+
+		  copy_monitor = new GBasicProgressMonitor();
+		  Gatherer.c_man.registerCopyMonitor(copy_monitor);
+
+		  progress_import_label = new JLabel(get("Import_Progress"));
+		  progress_import_label.setForeground(Color.black);
+		  progress_import_label.setHorizontalAlignment(JLabel.LEFT);
+		  progress_import_label.setPreferredSize(LABEL_SIZE);
+		  progress_import_label.setMinimumSize(LABEL_SIZE);
+		  progress_import_label.setSize(LABEL_SIZE);
+
+		  import_monitor = new GImportProgressMonitor(); //GBasicProgressMonitor();
+		  Gatherer.c_man.registerImportMonitor(import_monitor);
+
+		  progress_build_label = new JLabel(get("Build_Progress"));
+		  progress_build_label.setForeground(Color.black);
+		  progress_build_label.setHorizontalAlignment(JLabel.LEFT);
+		  progress_build_label.setPreferredSize(LABEL_SIZE);
+		  progress_build_label.setMinimumSize(LABEL_SIZE);
+		  progress_build_label.setSize(LABEL_SIZE);
+
+		  build_monitor = new GBuildProgressMonitor((GImportProgressMonitor)import_monitor); //GBasicProgressMonitor();
+		  Gatherer.c_man.registerBuildMonitor(build_monitor);
+
+		  // Buttons.
+		  build_button = new JButton(get("Build_Collection"));
+		  build_button.addActionListener(new BuildButtonListener());
+		  build_button.setPreferredSize(BUTTON_SIZE);
+		  cancel_button = new JButton(get("Cancel_Build"));
+		  cancel_button.addActionListener(new CancelButtonListener());
+		  cancel_button.setEnabled(false);
+		  cancel_button.setPreferredSize(BUTTON_SIZE);
+	 }
+	 /** 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 collectionChanged(boolean ready) {
+		  ///ystem.err.println("Collection changed... ");
+		  if(Gatherer.c_man != null && Gatherer.c_man.ready()) {
+				this.options_pane = new OptionsPane(target_pane, message_log, Gatherer.c_man.getCollection().build_options);
+		  }
+	 }
+	 /** This method is called to actually layout the components.
+	  * @see org.greenstone.gatherer.Configuration
+	  * @see org.greenstone.gatherer.Gatherer
+	  */
+	 public void display() {
+		  // Build control_pane
+		  JPanel stats_area = new JPanel();
+		  stats_area.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createTitledBorder(get("Statistics_Title"))));
+		  stats_area.setLayout(new GridLayout(1,1));
+		  stats_area.add(document_count);
+		 
+		  JPanel left = new JPanel();
+		  left.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
+		  left.setLayout(new BorderLayout());
+		  left.add(tree, BorderLayout.CENTER);
+
+		  JPanel right = new JPanel();
+		  right.setBorder(BorderFactory.createEmptyBorder(0,0,5,5));
+		  right.setLayout(new BorderLayout());
+		  scroll_pane = new JScrollPane(target_pane);
+		  right.add(scroll_pane, BorderLayout.CENTER);
+
+		  JPanel options_area = new JPanel();
+		  options_area.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createTitledBorder(get("Options_Title"))));
+		  options_area.setLayout(new BorderLayout());
+		  options_area.add(left, BorderLayout.WEST);
+		  options_area.add(right, BorderLayout.CENTER);
+
+		  control_pane.setLayout(new BorderLayout());
+		  control_pane.add(options_area, BorderLayout.CENTER);
+		  //control_pane.add(stats_area, BorderLayout.SOUTH);
+
+		  // Build progress_pane
+		  JPanel copy_pane = new JPanel();
+		  copy_pane.setLayout(new BorderLayout());
+		  copy_pane.add(progress_copy_label, BorderLayout.WEST);
+		  copy_pane.add(copy_monitor.getProgress(), BorderLayout.CENTER);
+
+		  JPanel import_pane = new JPanel();
+		  import_pane.setLayout(new BorderLayout());
+		  import_pane.add(progress_import_label, BorderLayout.WEST);
+		  import_pane.add(import_monitor.getProgress(), BorderLayout.CENTER);
+
+		  JPanel build_pane = new JPanel();
+		  build_pane.setLayout(new BorderLayout());
+		  build_pane.add(progress_build_label, BorderLayout.WEST);
+		  build_pane.add(build_monitor.getProgress(), BorderLayout.CENTER);	  
+
+		  JPanel bar_area = new JPanel();
+		  bar_area.setBorder(BorderFactory.createEmptyBorder(10,10,5,10));
+
+		  bar_area.setLayout(new GridLayout(2,2,10,5));
+		  bar_area.add(import_pane);
+		  bar_area.add(build_pane);
+
+
+		  progress_pane.setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
+		  progress_pane.setLayout(new BorderLayout());
+		  progress_pane.add(bar_area, BorderLayout.NORTH);
+
+		  // Main pane
+		  main_pane = new JPanel(card_layout);
+		  main_pane.add(control_pane, CONTROL);
+		  main_pane.add(progress_pane, PROGRESS);
+
+		  // Buttons
+		  JPanel button_pane = new JPanel();
+		  button_pane.setBorder(BorderFactory.createEmptyBorder(5,10,10,10));
+		  button_pane.setLayout(new GridLayout(1,2));
+		  button_pane.add(build_button);
+		  button_pane.add(cancel_button);
+
+		  this.setLayout(new BorderLayout());
+		  this.add(main_pane, BorderLayout.CENTER);
+		  this.add(button_pane, BorderLayout.SOUTH);
+	 }
+	 /** 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(!processing) {
+				card_layout.show(main_pane, CONTROL);
+				//args = new String[1];
+				//if(Gatherer.c_man.ready()) {
+				//	 args[0] = String.valueOf(Gatherer.c_man.getCollection().getDocumentCount());
+				//}
+				//else {
+				//args[0] = "0";
+				//}
+				//document_count.setText(get("Document_Count", args));
+		  }
+		  // Refresh the set of controls.
+		  TreePath path = tree.getSelectionPath();
+		  tree.clearSelection();
+		  tree.setSelectionPath(path);
+	 }
+	 /** Method to acquire the progress monitor associated with builds.
+	  * @return The build <strong>GShellProgressMonitor</strong>.
+	  */
+	 public GShellProgressMonitor getBuildProgress() {
+		  return build_monitor;
+	 }
+	 /** Method to acquire the progress monitor associated with copying.
+	  * @return The copying <strong>GShellProgressMonitor</strong>.
+	  */
+	 public GShellProgressMonitor getCopyProgress() {
+		  return copy_monitor;
+	 }
+	 /** Method to acquire the progress monitor associated with import.
+	  * @return The import <strong>GShellProgressMonitor</strong>.
+	  */
+	 public GShellProgressMonitor getImportProgress() {
+		  return import_monitor;
+	 }
+
+	 /** We are informed when this view pane loses focus so we can update build options. */
+	 public void loseFocus() {
+		  tree.valueChanged(null);
+	 }
+
+	 /** 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) {
+		  ///ystem.err.println("Recieved message: " + event.getMessage());
+		  String text = event.getMessage();
+		  message_log.append(text + "\n");
+		  if(process_log != null) {
+				process_log.append(text + "\n");
+				process_log.setCaretPosition(process_log.getCaretPosition() + text.length() + 1);
+				//scroll_log.getVerticalScrollBar().setValue(process_log.getHeight() - process_log.getVisibleRect().height);
+		  }
+	 }
+	 /** 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) {
+		  if(event.getType() == GShell.BUILD) {
+				processing = false;
+				cancel_button.setEnabled(false);
+				build_button.setEnabled(true);
+				card_layout.show(main_pane, CONTROL);
+		  }
+	 }
+	 /** This method retrieves a phrase from the dictionary based apon the key.
+	  * @param key A <strong>String</strong> used as a reference to the correct phrase.
+	  * @return A phrase, matching the key, as a <strong>String</strong>.
+	  */
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+	 /** This method retrieves a phrase from the dictionary based apon the key and arguments.
+	  * @param key A <strong>String</strong> used as a reference to the correct phrase.
+	  * @param args A <strong>String[]</strong> whose contents are often substituted into the phrase before it is returned.
+	  * @return A phrase, matching the key and constructed using the arguments, as a <strong>String</strong>.
+	  * @see org.greenstone.gatherer.Dictionary
+	  * @see org.greenstone.gatherer.Gatherer
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf(".") == -1) {
+				key = "CreatePane." + key;
+		  }
+		  return Gatherer.dictionary.get(key, args);
+	 }
+	 /** This class serves as the listener for actions on the build button. */
+	 private class BuildButtonListener
+		  implements ActionListener {
+		  /** This method causes a call to be made to CollectionManager.importCollection(), which then imports and builds the collection as necessary.
+			* @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) {
+				// First we force the build options to be updated if we haven't already.
+				tree.valueChanged(null);
+				// Now go about building.
+				build_button.setEnabled(false);
+				cancel_button.setEnabled(true);
+				// Create a new process log, and place it.
+				if(scroll_log != null) {
+					 progress_pane.remove(scroll_log);
+				}
+				process_log = new JTextArea();
+				scroll_log = new JScrollPane(process_log);
+				progress_pane.add(scroll_log, BorderLayout.CENTER);
+				// Change the view.
+				processing = true;
+				card_layout.show(main_pane, PROGRESS);
+				// Reset the stop flag in all the process monitors, just incase.
+				((GBuildProgressMonitor)build_monitor).reset();
+				copy_monitor.setStop(false);
+				import_monitor.setStop(false);
+				// Set removeold automatically.
+				if(Gatherer.c_man.ready() && !Gatherer.c_man.built()) {
+					 Gatherer.c_man.getCollection().build_options.setImportValue("removeold", true, null);
+				}
+				// Call CollectionManagers method to build collection.
+				Gatherer.c_man.importCollection();
+		  }
+	 }
+	 /** 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(true);
+				cancel_button.setEnabled(false);
+				card_layout.show(main_pane, CONTROL);
+				// Set the stop flag in all the process monitor.
+				build_monitor.setStop(true);
+				copy_monitor.setStop(true);
+				import_monitor.setStop(true);
+				// Set removeold automatically.
+				if(Gatherer.c_man.ready()) { // and it should be.
+					 Gatherer.c_man.getCollection().build_options.setImportValue("removeold", true, null);
+				}
+		  }
+	 }
+	 /** 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();
+				addTreeSelectionListener(this);
+				getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+				setRootVisible(false);
+				setToggleClickCount(1);
+				// Create tree.
+				building = new OptionTreeNode(get("Build"));
+				importing = new OptionTreeNode(get("Import"));
+				log = new OptionTreeNode(get("Log"));
+				options = new OptionTreeNode(get("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();
+					 node = (OptionTreeNode)path.getLastPathComponent();
+				}
+				if(previous_pane != null) {
+					 //target_pane.remove(previous_pane);
+					 options_pane.update(previous_pane);
+					 previous_pane = null;
+				}
+				if(node != null && node.equals(building)) {
+					 previous_pane = options_pane.buildBuild();
+					 //target_pane.add(previous_pane, BorderLayout.CENTER);
+				}
+				else if(node != null && node.equals(importing)) {
+					 previous_pane = options_pane.buildImport();
+					 //target_pane.add(previous_pane, BorderLayout.CENTER);
+				}
+				else {
+					 previous_pane = options_pane.buildLog();
+					 //target_pane.add(previous_pane, BorderLayout.CENTER);
+				}
+				scroll_pane.setViewportView(previous_pane);
+				previous_pane.validate();
+		  }
+	 }
+	 /** 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;
+		  /** 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 equivelent.
+			* @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;
+		  }
+		  /** 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;
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/EditorDialog.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/EditorDialog.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/EditorDialog.java	(revision 13666)
@@ -0,0 +1,106 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+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 JDialog 
+	 implements ActionListener {
+	 /** 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,400);
+	 /** Constructor.*/
+	 public EditorDialog() {
+	 }
+	 /** 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);
+		  setTitle(Gatherer.dictionary.get("General.Edit"));
+		  // Create
+		  cancel = new JButton(Gatherer.dictionary.get("General.Cancel"));
+		  ok = new JButton(Gatherer.dictionary.get("General.OK"));
+		  text = new JTextArea(value);
+		  text.setCaretPosition(value.length());
+		  text.setEditable(true);
+		  text.setLineWrap(true);
+		  text.setWrapStyleWord(true);
+		  // Listeners
+		  cancel.addActionListener(this);
+		  ok.addActionListener(this);
+		  // Layout
+		  JPanel button_pane = new JPanel();
+		  button_pane.setLayout(new GridLayout(1,2));
+		  button_pane.add(ok);
+		  button_pane.add(cancel);
+		  
+		  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 = Gatherer.config.screen_size;
+		  setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+		  show();
+		  return result;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/FileAssociationDialog.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/FileAssociationDialog.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/FileAssociationDialog.java	(revision 13666)
@@ -0,0 +1,288 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.file.FileAssociationManager;
+import org.greenstone.gatherer.gui.GComboBox;
+import org.greenstone.gatherer.util.Utility;
+import org.outerj.pollo.util.*;
+/** The file association allows the entry of new file associations and the modification of existing ones. This is done via a list of known extensions, and two fields to fill out relevant details. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class FileAssociationDialog
+	 extends JDialog {
+	 /** <i>true</i> iff this addition action been cancelled by the user. */
+	 private boolean cancelled = false;
+	 /** <i>true</i> iff we should ignore any current changes to the extension list. */
+	 private boolean ignore = false;
+	 /** <i>true</i> iff the extension has not changed recently, but the command has. */
+	 private boolean save_required = false;
+	 /** A reference to ourselves so that our inner classes can dispose of us. */
+	 private FileAssociationDialog self;
+	 /** A reference to the manager in charge of storing all the file association information. */
+	 private FileAssociationManager manager;
+	 /** The button used to open a file browser for simplier executable selection. */
+	 private JButton browse;
+	 /** The button used to cancel this dialog without commiting any changes. */
+	 private JButton cancel;
+	 /** The button used to hide this dialog after updating or adding file associations as necessary. */
+	 private JButton ok;
+	 /** The combobox used to select what extension you wish to change. */
+	 private GComboBox extension;
+	 /** A field for entering the command string. */
+	 private JTextField command;
+	 /** The extension last chosen from the combobox. This way we can determine if the extension has been modified by the user. */
+	 private String previous_extension;
+	 /** The default size of a label. */
+	 static final private Dimension LABEL_SIZE = new Dimension(150, 25);
+	 /** The default size for the dialog. */
+	 static final private Dimension SIZE = new Dimension(600, 150);
+	 /** Create a new file association dialog.
+	  * @param manager A reference to the <strong>FileAssociationManager</strong> so we can determine what extensions are already associated.
+	  * @see org.greenstone.gatherer.Configuration
+	  * @see org.greenstone.gatherer.gui.Coloring
+	  */
+	 public FileAssociationDialog(FileAssociationManager manager) {
+	     super(Gatherer.g_man);
+		  this.manager = manager;
+		  this.self = this;
+		  
+		  // Creation
+		  setModal(true);
+		  setSize(SIZE);
+		  setTitle(get("Title"));
+		  JPanel content_pane = (JPanel) getContentPane();
+		  content_pane.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
+		  JPanel extension_pane = new JPanel();
+		  extension_pane.setOpaque(false);
+		  JLabel extension_label = new JLabel(get("Extension"));
+		  extension_label.setPreferredSize(LABEL_SIZE);
+		  extension = new GComboBox();
+		  extension.setEditable(true);
+		  extension.setPreferredSize(LABEL_SIZE);
+		  for(Iterator extensions = manager.keySet().iterator(); extensions.hasNext(); ) {
+				extension.add((String)extensions.next());
+		  }
+		  JPanel command_pane = new JPanel();
+		  command_pane.setOpaque(false);
+		  JLabel command_label = new JLabel(get("Command"));
+		  command_label.setPreferredSize(LABEL_SIZE);
+		  JPanel inner_pane = new JPanel();
+		  inner_pane.setOpaque(false);
+		  command = new JTextField();
+		  command.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  command.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
+		  command.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
+		  if(extension.count() > 0) {
+				command.setText(manager.getCommandImmediately((String)extension.get(0)));
+		  }
+		  browse = new JButton(get("Browse"));
+		  browse.setBackground(Gatherer.config.getColor("coloring.button_background", false));
+		  browse.setPreferredSize(LABEL_SIZE);
+		  JPanel button_pane = new JPanel();
+		  button_pane.setOpaque(false);
+		  ok = new JButton(get("General.OK"));
+		  ok.setBackground(Gatherer.config.getColor("coloring.button_background", false));
+		  cancel = new JButton(get("General.Cancel"));
+		  cancel.setBackground(Gatherer.config.getColor("coloring.button_background", false));
+		  // Connection
+		  browse.addActionListener(new BrowseListener());
+		  cancel.addActionListener(new CancelListener());
+		  ok.addActionListener(new OKListener());
+		  extension.addItemListener(new ExtensionListener());
+		  command.addKeyListener(new CommandListener());
+		  // Layout
+		  extension_pane.setLayout(new BorderLayout());
+		  extension_pane.add(extension_label, BorderLayout.WEST);
+		  extension_pane.add(extension, BorderLayout.EAST);
+
+		  inner_pane.setLayout(new BorderLayout());
+		  inner_pane.add(command, BorderLayout.CENTER);
+		  inner_pane.add(browse, BorderLayout.EAST);
+
+		  command_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+		  command_pane.setLayout(new GridLayout(2,1));
+		  command_pane.add(command_label);
+		  command_pane.add(inner_pane);
+
+		  button_pane.setLayout(new GridLayout(1,2,2,2));
+		  button_pane.add(ok);
+		  button_pane.add(cancel);
+		  
+		  content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		  content_pane.setLayout(new BorderLayout());
+		  content_pane.add(extension_pane, BorderLayout.NORTH);
+		  content_pane.add(command_pane, BorderLayout.CENTER);
+		  content_pane.add(button_pane, BorderLayout.SOUTH);
+
+		  Dimension screen_size = Gatherer.config.screen_size;
+		  setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	 }
+	 /** Destructor to ensure dialog gets garbage collected. */
+	 public void destroy() {
+		  self = null;
+		  manager = null;
+		  browse = null;
+		  cancel = null;
+		  ok = null;
+		  extension = null;
+		  command = null;
+		  previous_extension = null;
+	 }
+	 /** Redisplay the dialog, ensuring that the details (or lack thereof) for a certain extension is apparent.
+	  * @param new_extension The extension code as a <strong>String</strong>.
+	  */
+	 public String display(String new_extension) {
+		  if(new_extension != null) {
+				int index = extension.add(new_extension);
+				extension.setSelectedIndex(index);
+		  }
+		  else {
+
+		  }
+		  show();
+		  if(save_required) {
+				manager.setCommand((String)extension.getSelectedItem(), (String)command.getText());
+				save_required = false;
+		  }
+		  if(cancelled) {
+				return null;
+		  }
+		  return command.getText();
+	 }
+
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+
+	 private String get(String key, String args[]) {
+		  if(key.indexOf(".") == -1) {
+				key = "FileAssociationDialog." + key;
+		  }
+		  return Gatherer.dictionary.get(key, args);
+	 }	 
+
+	 /** 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 BrowseListener 
+		  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(Utility.BASE_DIR));
+				chooser.setDialogTitle(get("Browse_Title"));
+				chooser.setFileFilter(new ExtensionFileFilter(".bat", get("Batch_File")));
+				chooser.setFileFilter(new ExtensionFileFilter(".com", get("Command_File")));
+				chooser.setFileFilter(new ExtensionFileFilter(".exe", get("Executable_File")));
+				chooser.setAcceptAllFileFilterUsed(true);
+				int return_val = chooser.showOpenDialog(null);
+				if(return_val == JFileChooser.APPROVE_OPTION) {
+					 command.setText(chooser.getSelectedFile().getAbsolutePath());
+					 save_required = true;
+				}
+		  }
+	 }
+	 /** Listens for actions apon the cancel button, and if detected disposes of the dialog without saving changes. */
+	 private class CancelListener
+		  implements ActionListener {
+		  /** Listens for actions apon the cancel button, and if detected disposes of the dialog without saving changes. 
+			* @param event An <strong>ActionEvent</strong> containing further information about the action.
+			*/
+		  public void actionPerformed(ActionEvent event) {
+				cancelled = true;
+				save_required = false;
+				self.dispose();
+		  }
+	 }
+	 /** If any changes occur to the command field, mark it as needing saving before we can change extensions, or dispose of this dialog (other than cancelling. */
+	 private class CommandListener
+		  extends KeyAdapter {
+		  /** Whenever we detect a new character has been typed, note that we need to update this association in the manager. 
+			* @param event A <strong>KeyEvent</strong> containing information about the key typed event.
+			*/
+		  public void keyTyped(KeyEvent event) {
+				save_required = true;
+		  }
+	 }
+	 /** Whenever the user selects an extension, we should fill out the command field with whatever value has been previously entered for the command (if any). */
+	 private class ExtensionListener
+		  implements ItemListener {
+		  /** This method is called whenever the selection in the extension list changes, so that we can save any old details, then load up the information for the new selection.
+			* @param event An <strong>ItemEvent</strong> encompassing everything you ever wanted to know about the list selectio, but were afraid to ask.
+			* @see org.greenstone.gatherer.file.FileAssociationManager
+			*/
+		  public void itemStateChanged(ItemEvent event) {
+				String ext = (String) extension.getSelectedItem();
+				if(!ignore && ext != null && ext.length() > 0) {
+					 ignore = true;
+					 // Save the previous extension if necessary
+					 if(save_required && previous_extension != null) {
+						  manager.setCommand(previous_extension, command.getText());
+						  save_required = false;
+					 }
+					 previous_extension = manager.getCommandImmediately((String)extension.getSelectedItem());
+					 if(previous_extension != null) {
+						  command.setText(previous_extension);
+					 }
+					 else {
+						  command.setText("");
+					 }
+					 ignore = false;
+				}
+		  }
+	 }
+	 /** Listen for clicks on the ok button, and dispose when detected. */
+	 private class OKListener
+		  implements ActionListener {
+		  /** When a click on OK is detected, save the current information, then dispose.
+			* @param event An <strong>ActionEvent</strong> with details about the button press.
+			*/
+		  public void actionPerformed(ActionEvent event) {
+				if(save_required) {
+					 manager.setCommand(extension.getSelectedItem().toString(), command.getText());
+					 save_required = false;
+				}
+				self.dispose();
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/FileProgress.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/FileProgress.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/FileProgress.java	(revision 13666)
@@ -0,0 +1,46 @@
+package org.greenstone.gatherer.gui;
+
+import java.awt.BorderLayout;
+
+import javax.swing.JPanel;
+
+import org.greenstone.gatherer.gui.LongProgressBar;
+
+public class FileProgress
+	 extends JPanel {
+
+	 private LongProgressBar progress;
+
+	 public FileProgress() {
+		  super();
+		  // Initialization
+
+		  // Creation
+		  progress = new LongProgressBar();
+		  // Connection
+
+		  // Layout
+		  setLayout(new BorderLayout());
+		  add(progress, BorderLayout.CENTER);
+	 }
+
+	 public void addValue(int data_size) {
+		  progress.addValue(data_size);
+	 }
+
+	 public void setIndeterminate(boolean state) {
+		  progress.setIndeterminate(state);
+	 }
+
+	 public void setMaximum(long size) {
+		  progress.setMaximum(size);
+	 }
+
+	 public void setString(String label) {
+		  progress.setString(label);
+	 }
+
+	 public void setValue(int value) {
+		  progress.setValue(value);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/Filter.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/Filter.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/Filter.java	(revision 13666)
@@ -0,0 +1,347 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+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.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 CollectionPane and the MetaEditPane are virtually the same.</p>
+ * <p>The regular expression typed can uses '*' as a wildcard character (equivelent 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 filter 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 enabled/diable 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,25);
+	 /** Preprogrammed default filters. */
+	 static final private String DEFAULTS[] = {"^.*\\.html?$", "^.*\\.xml$", "^.*\\.txt$", "(^.*\\.jpe?g$)|(^.*\\.png$)|(^.\\.gif$)"};
+	 /** 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) {
+				this.others = new ArrayList();
+		  }
+		  else {
+				this.others = others;
+		  }
+		  this.others.add(this);
+		  this.this_filter = this;
+		  this.tree = tree;
+		  // Create components.
+		  combobox = new GComboBox();
+		  combobox.add(new Entry());
+		  for(int i = 0; i < DEFAULTS.length; i++) {
+				try {
+					 Entry entry = new Entry(get((new Integer(i)).toString(), null), Pattern.compile(DEFAULTS[i]));
+					 combobox.add(entry);
+				}
+				catch (Exception error) {
+					 error.printStackTrace();
+				}
+		  }
+		  combobox.setEditable(true);
+		  label = new JLabel(get("Filter_Tree"));
+		  label.setPreferredSize(SIZE);
+		  // Add listeners.
+		  combobox.addItemListener(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);
+	 }
+	 /** Retrieve the combobox associated with this filter.
+	  * @return A <strong>GComboBox</strong>.
+	  */
+	 public GComboBox getComboBox() {
+		  return combobox;
+	 }
+
+	 /** Change the background color of the filter. 
+	  * @param color The new background <strong>Color</strong>.
+	  */
+	 public void setBackground(Color color) {
+		  super.setBackground(color);
+	 }
+
+	 /** 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.setEditable(state);
+		  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;
+	 }
+	 /** 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;
+	 }
+	 /** Spawn produces a copy of this filter, which has new controls, but shares listeners wih this filter, and vice versa. Thus we can have two synchronized, but differing sets of controls.
+	  * @param tree_spawn The <strong>JTree</strong> this filter will affect.
+	  * @return A new <strong>Filter</strong> which is in the same run as this filter.
+	  */
+	 public Filter spawn(DragTree tree_spawn) {
+		  Filter filter = new Filter(tree_spawn, others);
+		  filter.setFirst(false); // No spawned copies should generate error messages, but fail silently.
+		  filter.setComboBoxModel(combobox.getModel());
+		  filter.setComboBoxSelection((Entry)combobox.getSelectedItem());
+		  return filter;
+	 }
+	 /** Retrieve a phrase from the dictionary.
+	  * @param key The unique identification <strong>String</strong> of a phrase from the dictionary.
+	  */
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+	 /** Retrieve a phrase from the dictionary, augmenting with the given text fragments
+	  * @param key The unique identification <strong>String</strong> of a phrase from the dictionary.
+	  * @param args A <strong>String[]</strong> of arguments to be used to fill out parameter fields in the phrase returned.
+	  * @see org.greenstone.gatherer.Dictionary
+	  * @see org.greenstone.gatherer.Gatherer
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf(".") == -1) {
+				key = "Filter." + key;
+		  }
+		  return Gatherer.dictionary.get(key, args);
+	 }
+	 /** 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 ItemListener {
+		  /** 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>ItemEvent</strong> containing more information about the change performed.
+			* @see org.greenstone.gatherer.gui.Filter.Entry
+			*/
+		  public void itemStateChanged(ItemEvent event) {
+				if(!ignore) {
+					 ignore = true;
+					 if(event.getStateChange() == ItemEvent.SELECTED) {
+						  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, starting with All Files.
+									 if(temp_str.equals(get("All_Files"))) {
+									 }
+									 // HTM & HTML
+									 else if(temp_str.equals(get("0"))) {
+									 }
+									 // XML
+									 else if(temp_str.equals(get("1"))) {
+									 }
+									 // Text files
+									 else if(temp_str.equals(get("2"))) {
+									 }
+									 // Images
+									 else if(temp_str.equals(get("3"))) {
+									 }
+									 else {
+										  entry = new Entry((String)temp, Pattern.compile(encode((String)temp)));
+										  //combobox.removeItem(temp);
+										  //int position = combobox.add(entry);
+										  //combobox.setSelectedIndex(position);
+									 }
+								}
+								else {
+									 entry = (Entry) temp;
+								}
+								if(entry != null) {
+									 setFilter(entry.getPattern());
+									 // Synchronize other controls.
+									 /*
+									 for(int i = 0; i < others.size(); i++) {
+										  Filter sibling = (Filter) others.get(i);
+										  if(sibling != this_filter) {
+												sibling.setComboBoxSelection((Entry)entry);
+										  }
+									 }
+									 */
+								}
+								// 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, get("Invalid_Pattern"), get("General.Error"), JOptionPane.ERROR_MESSAGE);
+								}
+						  }
+					 }
+					 ignore = false;
+				}
+		  }
+	 }
+	 /** 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 = get("All_Files");
+				}
+				else {
+					 result = pattern.pattern();
+				}
+				return result;
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/GComboBox.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/GComboBox.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/GComboBox.java	(revision 13666)
@@ -0,0 +1,283 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.plaf.basic.*;
+import org.greenstone.gatherer.Gatherer;
+
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version
+ */
+public class GComboBox
+	 extends JComboBox {
+
+	 private Color background = null;
+	 private Color foreground = null;
+	 private Color selection_background = null;
+	 private Color selection_foreground = null;
+
+	 private Model model;
+
+	 public GComboBox() {
+		  super();
+		  init();
+	 }
+
+	 public GComboBox(Gatherer gatherer) {
+		  this();
+	 }
+
+	 public GComboBox(ArrayList data) {
+		  super(data.toArray());
+		  init();
+	 }
+
+	 public GComboBox(ComboBoxModel model) {
+		  super(model);
+		  init();
+	 }
+
+	 public GComboBox(Object data[]) {
+		  super(data);
+		  init();
+	 }
+
+	 public GComboBox(Vector data) {
+		  super(data);
+		  init();
+	 }
+
+	 public int add(Object object) {
+		  return model.add(object);
+	 }
+
+	 public Object get(int index) {
+		  return model.getElementAt(index);
+	 }
+
+	 public int getMaximumRowCount() {
+		  int size = model.getSize();
+		  if(size == 0) {
+				return 1;
+		  }
+		  else if(size < maximumRowCount) {
+				return model.getSize();
+		  }
+		  return maximumRowCount;
+	 }
+
+	 public void clear() {
+		  model.clear();
+	 }
+
+	 public int count() {
+		  return model.getSize();
+	 }
+
+	 public void setBackgroundNonSelectionColor(Color background) {
+		  this.background = background;
+		  setEditor(new Editor());
+		  setRenderer(new Renderer());
+	 }
+
+	 public void setTextNonSelectionColor(Color foreground) {
+		  this.foreground = foreground;
+		  setEditor(new Editor());
+		  setRenderer(new Renderer());
+	 }
+
+	 public void setBackgroundSelectionColor(Color selection_background) {
+		  this.selection_background = selection_background;
+		  setEditor(new Editor());
+		  setRenderer(new Renderer());
+	 }
+
+	 public void setTextSelectionColor(Color selection_foreground) {
+		  this.selection_foreground = selection_foreground;
+		  setEditor(new Editor());
+		  setRenderer(new Renderer());
+	 }
+
+	 public void init() {
+		  this.model = new Model();
+		  ComboBoxModel old_model = (ComboBoxModel) getModel();
+		  setModel(model);
+		  // 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.setBackground(Color.white);
+		  // Initialization
+		  this.background = Gatherer.config.getColor("coloring.collection_tree_background", false);
+		  this.foreground = Gatherer.config.getColor("coloring.collection_tree_foreground", false);
+		  this.selection_background = Gatherer.config.getColor("coloring.collection_selection_background", false);
+		  this.selection_foreground = Gatherer.config.getColor("coloring.collection_selection_foreground", false);
+		  setEditor(new Editor());
+		  setRenderer(new Renderer());
+	 }
+
+	 private class Editor
+		  extends JTextField
+		  implements ComboBoxEditor {
+		  public Editor() {
+				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 < size()) {
+					 String sibling = getElementAt(position).toString().toLowerCase();
+					 int order = extension_str.compareTo(sibling);
+					 // If we are now less than the sibling, insert here.
+					 if(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 = size();
+					 addElement(extension);
+				}
+				return position;
+		  }
+
+		  public void clear() {
+				removeAllElements();
+		  }
+
+		  public int size() {
+				return getSize();
+		  }
+	 }
+
+	 private class Renderer 
+		  extends JLabel 
+		  implements ListCellRenderer {
+		  public Renderer() {
+		  }
+		  public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+				if(value != null) {
+					 setText(value.toString());
+				}
+				else {
+					 setText("");
+				}
+				setBackground(isSelected ? selection_background : background);
+				setForeground(isSelected ? selection_foreground : foreground);
+				setOpaque(true);
+				return this;
+		  }
+	 }
+
+	 private class UI
+		  extends BasicComboBoxUI {
+		  public UI() {
+				super();
+		  }
+
+		  protected ComboPopup createPopup() {
+				BasicComboPopup popup = new BasicComboPopup( comboBox ) {
+						  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 setBackground(Color background) {
+				arrowButton.setBackground(background);
+		  }
+	 }
+}
+
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/GConfigPane.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/GConfigPane.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/GConfigPane.java	(revision 13666)
@@ -0,0 +1,114 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.CollectionDesignManager;
+import org.greenstone.gatherer.msm.ElementWrapper;
+/** This serves as the Collection configuration pane and came in two flavors.<BR>
+ * The lower tech version has now been made redundant.<BR>
+ * The higher tech, and finally implemented, version uses a tree to allow a user to navigate through the various regions of the config file and further allows them to interactively design and modify such gsdl elements as classifiers and plugins.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.2
+ */
+public class GConfigPane 
+	 extends JPanel {
+	 /** The collection manager is responsible for parsing in, and allowing the editing of, a single collections configuration file. */
+	 private CollectionDesignManager cdm = null;
+	 /** The constructor. */
+	 public GConfigPane() {
+	 }
+	 /** This method is called whenever the state of the current collection
+	  * changes.
+	  * @param ready <i>true</i> if a collection is loaded and ready, <i>false</i> otherwise.
+	  */
+	 public void collectionChanged(boolean ready) {
+		  ///atherer.println("CollectionChanged(" + ready + ")");
+		  if(ready) {
+				String filename = Gatherer.c_man.getCollectionConfig();
+				if(cdm != null && cdm.getFilename().equals(filename)) {
+					 return;
+				}
+				else {
+					 if(cdm != null) {
+						  cdm.destroy();
+						  cdm = null;
+					 }
+					 // Create a new config manager.
+					 cdm = new CollectionDesignManager();
+					 // Parse the configuration file.
+					 cdm.parse(filename);
+					 // Display it.
+					 cdm.display(this);
+				}
+		  }
+		  else {
+				if(cdm != null) {
+					 cdm.destroy();
+					 cdm = null;
+				}
+		  }
+	 }
+	 /** Called to cause the components to lay themselves out and be displayed.
+	  */
+	 public void display() {
+		  // Layout
+		  this.setLayout(new BorderLayout());
+	 }
+	 public void gainFocus() {
+		  cdm.gainFocus();
+	 }
+	 public ArrayList getIndexes() {
+		  return cdm.getIndexes();
+	 }
+
+	 public ArrayList getLanguageCodes() {
+		  return cdm.languages.getLanguageCodes();
+	 }
+
+	 public Rectangle setSelectedElement(ElementWrapper element) {
+		  return cdm.setSelectedElement(element.getName());
+	 }
+	 public void saveConfiguration() {
+		  if(cdm != null) {
+				cdm.save();
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/GEditorPane.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/GEditorPane.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/GEditorPane.java	(revision 13666)
@@ -0,0 +1,291 @@
+/**
+ *#########################################################################
+ *
+ * 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.Font;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import javax.swing.JButton;
+import javax.swing.JEditorPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.event.UndoableEditEvent;
+import javax.swing.event.UndoableEditListener;
+import javax.swing.undo.CannotRedoException;
+import javax.swing.undo.CannotUndoException;
+import javax.swing.undo.UndoManager;
+import org.greenstone.gatherer.Gatherer;
+/** A JEditorPane subclass that internally supports the undoable interface
+ * and allows a designer to specify if the component should recieve focus
+ * on a tab event.
+ */
+public class GEditorPane
+	 extends JEditorPane 
+	 implements ActionListener, FocusListener, UndoableEditListener {
+
+	 private boolean focusable = true;
+	 
+	 private File file = null;
+
+	 private Gatherer gatherer = null;
+
+	 private JButton redo_button = null;
+	 private JButton undo_button = null;
+
+	 private JEditorPane editor  = null;
+
+	 private UndoManager undo    = null;
+
+	 /** This constructor simply sets whether this pane is focusable.
+	  * @param focusable A Boolean indicating whether this component should
+	  * be focusable.
+	  */
+	 public GEditorPane(boolean focusable) {
+		  this.focusable = focusable;
+	 }
+
+	 /** This constructor sets up the initial JEditorPane settings, and
+	  * creates the necessary classes to support undo actions.
+	  * @param gatherer A reference to Gatherer for purposes of messaging
+	  * and dictionary.
+	  */
+	 public GEditorPane(Gatherer gatherer) {
+		  this.gatherer = gatherer;
+		  //this.setContentType("text/html");
+		  this.setEnabled(true);
+		  this.setFont(new Font("Courier New", Font.PLAIN, 12));
+		  // Undo support.
+		  undo = new UndoManager();
+		  // Create components.
+		  redo_button = new JButton(gatherer.dictionary.get("UndoManager.Redo"));
+		  redo_button.addActionListener(this);
+		  redo_button.setEnabled(false);
+		  undo_button = new JButton(gatherer.dictionary.get("UndoManager.Undo"));
+		  undo_button.addActionListener(this);
+		  undo_button.setEnabled(false);
+	 }
+
+	 /** This initially calls GEditorPane(focusable), but then uses
+	  * the given file to find the initial content of this pane. Moreover
+	  * it will now respond to loss of focus events by saving the document
+	  * content to this file.
+	  * this pane is focusable.
+	  * @param file A File to be used as a data source/destination.
+	  * @param focusable A Boolean indicating whether this component should
+	  * be focusable.
+	  */
+	 public GEditorPane(File file, boolean focusable) {
+		  this(focusable);
+		  loadFile(file);
+		  this.addFocusListener(this);
+	 }
+
+	 /** This initially calls GEditorPane(gatherer), but then sets whether
+	  * this pane is focusable.
+	  * @param gatherer A reference to Gatherer for purposes of messaging
+	  * and dictionary.
+	  * @param focusable A Boolean indicating whether this component should
+	  * be focusable.
+	  */
+	 public GEditorPane(Gatherer gatherer, boolean focusable) {
+		  this(gatherer);
+		  this.focusable = focusable;
+	 }
+
+	 /** This initially calls GEditorPane(focusable), but then sets 
+	  * the initial content for this panel.
+	  * this pane is focusable.
+	  * @param content A String indicating the initial content of this pane.
+	  * @param focusable A Boolean indicating whether this component should
+	  * be focusable.
+	  */
+	 public GEditorPane(String content, boolean focusable) {
+		  this(focusable);
+		  this.setText(content);
+	 }
+
+	 /** This initially calls GEditorPane(gatherer, focusable), but then sets 
+	  * the initial content for this panel.
+	  * this pane is focusable.
+	  * @param gatherer A reference to Gatherer for purposes of messaging
+	  * and dictionary.
+	  * @param content A String indicating the initial content of this pane.
+	  * @param focusable A Boolean indicating whether this component should
+	  * be focusable.
+	  */
+	 public GEditorPane(Gatherer gatherer, String content, boolean focusable) {
+		  this(gatherer, focusable);
+		  this.setText(content);
+	 }
+
+	 /** This initially calls GEditorPane(gatherer, focusable), but then uses
+	  * the given file to find the initial content of this pane. Moreover
+	  * it will now respond to loss of focus events by saving the document
+	  * content to this file.
+	  * this pane is focusable.
+	  * @param gatherer A reference to Gatherer for purposes of messaging
+	  * and dictionary.
+	  * @param file A File to be used as a data source/destination.
+	  * @param focusable A Boolean indicating whether this component should
+	  * be focusable.
+	  */
+	 public GEditorPane(Gatherer gatherer, File file, boolean focusable) {
+		  this(gatherer, focusable);
+		  loadFile(file);
+		  this.addFocusListener(this);
+	 }
+
+	 /** Any implementation of ActionListener must include this method so we
+	  * can be informed whenever an action has occured.
+	  * @param event An ActionEvent.
+	  */
+	 public void actionPerformed(ActionEvent event) {
+		  try {
+				if(event.getSource() == redo_button) {
+					 undo.redo();
+				}
+				else {
+					 undo.undo();
+				}
+		  }
+		  catch (CannotRedoException error) {
+				error.printStackTrace();
+		  }
+		  catch (CannotUndoException error) {
+				error.printStackTrace();
+		  }
+		  // Update controls to reflect change.
+		  redo_button.setEnabled(undo.canRedo());
+		  undo_button.setEnabled(undo.canUndo());
+	 }		  
+
+	 /** Any implementation of FocusListener must include this method so we
+	  * can be notified when focus is gained.
+	  * @param event A FocusEvent.
+	  */
+	 public void focusGained(FocusEvent event) {
+	 }
+
+	 /** Any implementation of FocusListener must include this method so we
+	  * can be notified when focus is lost.
+	  * @param event A FocusEvent.
+	  */
+	 public void focusLost(FocusEvent event) {
+		  if(file != null) {
+				// Save the document to file.
+				try {
+					 FileOutputStream out = new FileOutputStream(file);
+					 out.write(this.getText().getBytes());
+					 out.close();
+				}
+				catch (Exception error) {
+					 error.printStackTrace();
+				}
+		  }
+	 }
+
+	 /** Retrieves the redo button for this edit pane.
+	  * @return A JButton.
+	  */
+	 public JButton getRedoButton() {
+		  return redo_button;
+	 }
+
+	 /** Retrieves the undo button for this edit pane.
+	  * @return A JButton.
+	  */
+	 public JButton getUndoButton() {
+		  return undo_button;
+	 }
+
+	 /** This method is called by any window manager to determine if this
+	  * particular component is focusable.
+	  * @return A Boolean specifying if this component is focus traversable.
+	  * @deprecated
+	  */
+	 /** public boolean isFocusTraversable() {
+		  return focusable;
+		  }
+	 */
+
+	 /** Loads the contents of the specified file into the document.
+	  * @param file The target File.
+	  */
+    public void loadFile(File file) {
+	// Load the file.
+	gatherer.debug("Opening config file " + file.getAbsolutePath());
+	try {
+	    FileInputStream in = new FileInputStream(file);
+	    int character = -1;
+	    String content = "";
+	    while((character = in.read()) != -1) {
+		content = content + (char)character;
+				}
+	    in.close();
+	    this.file = file;
+	    this.setText(content);
+	}
+	catch (Exception error) {
+	    //error.printStackTrace();
+	    gatherer.debug("Error: No Such File.");
+	}
+    }
+
+	 /** Any implementation of Undoable must include this method so we can
+	  * be informed when an undoable event has occured.
+	  * @param event An UndoableEditEvent.
+	  */
+	 public void undoableEditHappened(UndoableEditEvent event) {
+		  if(undo != null) {
+				undo.addEdit(event.getEdit());
+				// Update controls to reflect change.
+				redo_button.setEnabled(undo.canRedo());
+				undo_button.setEnabled(undo.canUndo());
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/GProgressBar.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/GProgressBar.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/GProgressBar.java	(revision 13666)
@@ -0,0 +1,427 @@
+/**
+ *#########################################################################
+ *
+ * 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.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.GridLayout;
+import java.awt.Image;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+import javax.swing.border.BevelBorder;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.Job;
+import org.greenstone.gatherer.util.Utility;
+
+public class GProgressBar
+	 extends JPanel 
+	 implements ActionListener {
+
+	 private boolean simple = false;
+
+	 private Dimension bar_size = new Dimension(520, 15);
+
+	 private Gatherer gatherer;
+
+	 private ImageIcon busy_bar;
+	 private ImageIcon ready_bar;
+
+	 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 JLabel 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 Job owner;
+
+	 public JButton action;
+	 public JButton cancel;
+
+	 //public GProgressBar(Gatherer gatherer, WGet owner, String initial_url) {
+	 //	  this.gatherer = gatherer;
+	 public GProgressBar(Job 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.setMinimumSize(Utility.PROGRESS_BAR_SIZE);
+		  //this.setSize(Utility.PROGRESS_BAR_SIZE);
+		  //this.setMaximumSize(Utility.PROGRESS_BAR_SIZE);
+		  //this.setAlignmentY(Component.LEFT_ALIGNMENT);
+		  //this.setHorizontalAlignment(JLabel.LEFT);
+
+		  this.current_action = Job.STOPPED;
+		  
+		  inner_pane = new JPanel(new BorderLayout());
+		  inner_pane.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
+
+		  action = new JButton(Utility.getImage("vcrplay.gif"));
+		  //action.setToolTipText(get("Action_Tip"));
+		  action.setToolTipText("Start current download");
+		  action.addActionListener(this);
+		  action.addActionListener(owner);
+
+		  center_pane = new JPanel(new GridLayout(3,1));
+
+		  main_status = new JLabel();
+
+		  current_status = new JLabel();
+		  
+		  results_status = new JLabel();
+
+		  progress = new JProgressBar();
+		  progress.setString("Waiting to start");
+		  progress.setStringPainted(true);
+		  progress.setMinimum(0);
+		  progress.setMaximum(0);
+		  progress.setEnabled(false);
+		  inner_pane.add(progress, BorderLayout.CENTER);
+
+		  center_pane.add(main_status);
+		  center_pane.add(current_status);
+		  center_pane.add(results_status);
+
+		  cancel = new JButton(Utility.getImage("vcrstop.gif"));
+		  //cancel.setToolTipText(get("Cancel_Tip"));
+		  cancel.setToolTipText("Cancel current download");
+		  cancel.addActionListener(owner);
+		  cancel.addActionListener(this);
+
+		  inner_pane.add(center_pane, BorderLayout.NORTH);
+
+		  this.add(action, BorderLayout.WEST);
+		  this.add(inner_pane, BorderLayout.CENTER);
+		  this.add(cancel, BorderLayout.EAST);
+
+		  // Make the labels, etc update.
+		  refresh();
+	 }
+
+	 public void actionPerformed(ActionEvent event) {
+		  if(event.getSource() == action) {
+				if(current_action == Job.RUNNING) {
+					 current_action = Job.STOPPED;
+					 action.setIcon(Utility.getImage("vcrplay.gif"));
+					 action.setToolTipText("Start current download");
+					 cancel.setEnabled(true);
+				}
+				else {
+					 current_action = Job.RUNNING;
+					 action.setIcon(Utility.getImage("vcrpause.gif"));
+					 action.setToolTipText("Pause current download");
+					 cancel.setEnabled(false);
+				}
+		  }
+	 }
+
+	 /** 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.
+	  * @param size The size of the file as an Int.
+	  */
+	 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 GProgressBar 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());
+		  progress.setString("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 Dimension getPerferredSize() {
+		  return Utility.PROGRESS_BAR_SIZE;
+	 }
+
+	 /** When a link to be downloaded is located, the increaseTotalCount
+	  * method is called. In this way the total count shows the most
+	  * accurate remaining number of files to be downloaded.
+	  */
+	 public void increaseFileCount() {
+		  total_count++;
+		  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) {
+		  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 = Job.RUNNING;
+		  action.setIcon(Utility.getImage("vcrpause.gif"));
+		  action.setToolTipText("Pause current download");
+		  cancel.setEnabled(false);
+		  if(simple) {
+				progress.setIndeterminate(true);
+		  }
+	 }	
+
+	 /** Once a mirroring task is complete, is the Job 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 = Job.COMPLETE;
+		  current_url = null;
+		  if(simple) {
+				progress.setIndeterminate(false);
+		  }
+		  progress.setValue(progress.getMaximum());
+		  progress.setString("Mirroring Complete.");
+
+		  action.setIcon(Utility.getImage("vcrfastforward.gif"));
+		  action.setToolTipText("Restart current download");
+		  cancel.setEnabled(true);
+		  this.updateUI();
+	 }
+
+	 /** When called this method updates the GProgressBar 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 + " bytes");
+					 progress.setStringPainted(true);
+				}
+		  }
+		  refresh();
+	 }
+
+	 /** Retrieve a String from the dictionary using no arguments.
+	  * @param key The String which acts as a key mapping for the 
+	  * ResourceBundle.
+	  * @return A String which is the value for the given key.
+	  */
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+
+	 /** Retrieve a String from the dictionary using the given arguments.
+	  * @param key The String which acts as a key mapping for the 
+	  * ResourceBundle.
+	  * @param args A String array of arguments to be filled out inside the
+	  * dictionary value.
+	  * @return A String which is the value for the given key.
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf('.') == -1) {
+				return gatherer.dictionary.get("GProgressBar."+key, args);
+		  }
+		  return gatherer.dictionary.get(key, args);
+	 }
+
+	 /** The given parameter is taken as the number of bytes and is 
+	  * formatted into a strings such as:
+	  *   45 bytes
+	  * 1.21 Kbytes
+	  * 2.12 Mbytes
+	  * etc
+	  * @param size The number to be formatted, in bytes, as a Long.
+	  * @return A String which contains the size formatting into a
+	  * nice little number - unit label.
+	  */
+	 private String formatMetric(long size) {
+		  if(size > 1024) {
+				return (size / 1024) + " Kbytes";
+		  }
+		  return size + " bytes";
+	 }
+
+	 /** Causes the two labels associated with this GProgressBar 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(get("Main_Status", args1));
+		  main_status.setText("Mirroring " + args1[0] + ".");
+
+		  if(current_url != null) {
+				// Refresh the current label contents.
+				String args2[] = new String[1];
+				args2[0] = current_url;
+				
+				String cstext = "Downloading " + args2[0];
+				current_status.setText(Utility.trim(cstext, 50));
+		  }
+		  else if(current_action == Job.STOPPED 
+					 || current_action == Job.PAUSED) {
+				current_status.setText("Waiting for user action.");
+		  } 
+		  else {
+				current_status.setText("Mirroring 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("Downloaded " + args3[0] + " of " + 
+										 args3[1] + " files (" + args3[2] + 
+										 " warnings, " + args3[3] + " errors)");
+
+		  this.updateUI();
+	 }
+}
+
+
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/GPrompt.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/GPrompt.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/GPrompt.java	(revision 13666)
@@ -0,0 +1,159 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.util.Utility;
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.1
+ */
+public class GPrompt
+	 extends JDialog
+	 implements ActionListener {
+
+	 private JButton close;
+
+	 private JPanel content_pane;
+
+	 // Static
+	 static private Dimension SIZE      = new Dimension(420, 140);
+	 static private Dimension TEXT_SIZE = new Dimension(380, 60);
+
+	 public GPrompt(Dialog owner, String title, String message, String left_image, String right_image) {
+		  super(owner);
+		  build_dialog(title, message, left_image, right_image);
+	 }
+
+	 public GPrompt(Frame owner, String title, String message, String left_image, String right_image) {
+		  super(owner);
+		  build_dialog(title, message, left_image, right_image);
+	 }
+
+	 public void actionPerformed(ActionEvent event) {
+		  if(event.getSource() == close) {
+				// Check the show setting.
+				this.dispose();
+		  }
+	 }
+	 
+	 public void destroy() {
+		  close = null;
+		  content_pane = null;
+	 }
+
+	 public void display() {		  
+		  this.show();
+	 }
+
+	 /** This private method creates and lays out the components within this
+	  * dialog box based on its arguments.
+	  * @param message A String content to be displayed.
+	  * @param left_name The name of the left image as a String.
+	  * @param right_name The name of the right image as a String.
+	  */
+	 private void build_dialog(String title, String message, String left_name, String right_name) {
+		  this.setModal(true);
+		  this.setSize(SIZE);
+		  this.setTitle(title);
+
+		  // Create components
+		  content_pane = (JPanel) this.getContentPane();
+		  content_pane.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
+
+		  JLabel image_left_label = null;
+		  if(left_name != null) {
+				ImageIcon image_left = Utility.getImage(left_name);
+				image_left_label = new JLabel(image_left);
+				image_left_label.setOpaque(false);
+		  }
+
+		  JPanel text_pane = new JPanel();
+		  text_pane.setOpaque(false);
+
+		  JTextArea text = new JTextArea(message);
+		  text.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  text.setColumns(40);
+		  text.setEditable(false);
+		  text.setLineWrap(true);
+		  text.setRows(3);
+		  text.setWrapStyleWord(true);
+
+		  JLabel image_right_label = null;
+		  if(right_name != null) {
+				ImageIcon image_right = Utility.getImage(right_name);
+				image_right_label = new JLabel(image_right);
+				image_right_label.setOpaque(false);
+		  }
+
+		  close = new JButton(get("General.Close"));
+		  close.addActionListener(this);
+		  close.setBackground(Gatherer.config.getColor("coloring.button_background", false));
+
+		  // Layout components
+		  text_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
+		  text_pane.setLayout(new BorderLayout());
+		  text_pane.add(text, BorderLayout.CENTER);
+
+		  content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		  content_pane.setLayout(new BorderLayout());
+		  if(image_left_label != null) {
+				content_pane.add(image_left_label, BorderLayout.WEST);
+		  }
+		  content_pane.add(text_pane, BorderLayout.CENTER);
+		  content_pane.add(close, BorderLayout.SOUTH);
+		  if(image_right_label != null) {
+				content_pane.add(image_right_label, BorderLayout.EAST);
+		  }
+		  // Locate dialog on screen.
+		  Dimension screen_size = Gatherer.config.screen_size;
+		  this.setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	 }
+
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+
+	 private String get(String key, String args[]) {
+		  if(key.indexOf(".") == -1) {
+				key = "GPrompt."+key;
+		  }
+		  return Gatherer.dictionary.get(key, args);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/GTextArea.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/GTextArea.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/GTextArea.java	(revision 13666)
@@ -0,0 +1,96 @@
+/**
+ *#########################################################################
+ *
+ * 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.JTextArea;
+
+public class GTextArea
+	 extends JTextArea {
+	 
+	 boolean tab_action                               = true;
+
+	 static final public boolean INSERT_TAB_CHARACTER = true;
+	 static final public boolean FOCUS_NEXT_COMPONENT = false;
+
+	 /** Default constructor that simply calls superclass constructor.
+	  * @param content A String specifying the initial content of this text
+	  * component.
+	  */
+	 public GTextArea(String content) {
+		  super(content);
+	 }
+
+	 /** Constructor which also takes an argument specifying how this TextArea 
+	  * should respond to tab key presses.
+	  * @param content A String specifying the initial content of this text
+	  * component.
+	  * @param tab_action A Boolean indicating the desired tab effect.
+	  */
+	 public GTextArea(String content, boolean tab_action) {
+		  super(content);
+		  this.tab_action = tab_action;
+	 }
+
+	 /** Called to determine whether this TextArea is handling tab presses 
+	  * internally (INSERT_TAB_CHARACTER) or whether the focus manager should
+	  * handle them (FOCUS_NEXT_COMPONENT).
+	  * @return A Boolean indicating if the tab key presses are being managed
+	  * internally, ie should tab traversal be disabled.
+	  * @deprecated
+	  */
+	 /** public boolean isManagingFocus() {
+		  return tab_action;
+		  }
+	 */
+
+	 /** Sets how the TextArea should respond to tab key presses.
+	  * @param tab_action A Boolean indicating the desired tab effect.
+	  */
+	 public void setTabAction(boolean tab_action) {
+		  this.tab_action = tab_action;
+	 }
+}
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/GUIManager.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/GUIManager.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/GUIManager.java	(revision 13666)
@@ -0,0 +1,926 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.datatransfer.*;
+import java.awt.event.*;
+import java.io.*;
+import java.lang.*;
+import java.net.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.plaf.*;
+import javax.swing.text.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.Collection;
+import org.greenstone.gatherer.collection.DeleteCollectionPrompt;
+import org.greenstone.gatherer.collection.LoadCollectionBox;
+import org.greenstone.gatherer.collection.SaveCollectionBox;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.file.FileOpenActionListener;
+import org.greenstone.gatherer.gui.AboutDialog;
+import org.greenstone.gatherer.gui.BrowsingPane;
+import org.greenstone.gatherer.gui.CollectionPane;
+import org.greenstone.gatherer.gui.CreatePane;
+import org.greenstone.gatherer.gui.Filter;
+import org.greenstone.gatherer.gui.GConfigPane;
+import org.greenstone.gatherer.gui.MenuBar;
+import org.greenstone.gatherer.gui.MetaEditPane;
+import org.greenstone.gatherer.gui.MirrorPane;
+import org.greenstone.gatherer.gui.OpenCollectionDialog;
+import org.greenstone.gatherer.gui.OptionsBox;
+import org.greenstone.gatherer.gui.Preferences;
+import org.greenstone.gatherer.gui.PreviewPane;
+import org.greenstone.gatherer.gui.messages.MessagePane;
+import org.greenstone.gatherer.gui.metaaudit.MetaAuditFrame;
+import org.greenstone.gatherer.gui.tree.DragTree;
+import org.greenstone.gatherer.help.HelpFrame;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.Metadata;
+import org.greenstone.gatherer.sarm.SearchAndReplace;
+import org.greenstone.gatherer.shell.GShell;
+import org.greenstone.gatherer.util.TreeSynchronizer;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.valuetree.GValueNode;
+/** 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 {
+	 /** The browsing pane behaves much like an internet browser, or at least will some day. */
+	 public BrowsingPane browser_pane = null;
+	 /** The collection pane is more like a file manager where you drag files from one tree to another. */
+	 public CollectionPane collection_pane = null;
+	 /** The create pane contains scripting options for importing and building collections into libraries. */
+	 public CreatePane create_pane = null;
+
+	 public FileOpenActionListener foa_listener = new FileOpenActionListener();
+
+	 /** The configuration pane allows you to edit the design of the library in terms of the collection configuration file. */
+	 public GConfigPane config_pane = null;
+	 /** A reference to the currently instantiated help window, if any. */
+	 public HelpFrame help = null;
+	 /** The menu bar. */
+	 public MenuBar menu_bar = null;
+	 /** The message pane is optional and contains the log of messages sent. */
+	 public MessagePane message_pane = null;
+	 
+	 public MetaAuditFrame meta_audit;
+	 /** The metaedit pane is used to assign, edit and remove metadata from files within the collection. */
+	 public MetaEditPane metaedit_pane = null;
+	 /** The mirror pane contains controls for mirroring interent sites. */
+	 public MirrorPane mirror_pane = null;
+	 /** The preview pane contains a preview of your build collection. */
+	 public PreviewPane preview_pane = null;
+	 /** Are certain panes currently locked? */
+	 private boolean locked = false;
+	 /** The size of the Gatherer window. */
+	 private Dimension size = null;
+	 /** The filters used to dynamically filter the trees at user request. */
+	 private HashMap filters = new HashMap();
+	 /** The panel within the window that other components are placed on. */
+	 private JPanel content_pane = null;
+	 /** The dummy export pane. */
+	 private JPanel export_pane = new JPanel();
+	 /** 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 reference to any existing search and replace module/dialog. */
+	 private SearchAndReplace sar = null;
+	 /** A threaded tab changer to try and avoid NPE on exit. */
+	 private TabUpdater tab_updater = null;
+	 /** The thread group this manager, and hence its child graphical rendering threads, belong to. In a vain attempts to make the Dictionary work across threads.
+	  * @see org.greenstone.gatherer.Dictionary
+	  */
+	 private ThreadGroup thread_group = null;
+	 /** Ensures that expansion events between like collection trees are synchronized. */
+	 private TreeSynchronizer collection_tree_sync = null;
+	 /** Ensures that expansion events between like workspace trees are synchronized. */
+	 private TreeSynchronizer workspace_tree_sync = null;
+	 /**Constructor. Enable window events and arranges all other components.
+	  * @param size The intial <strong>Dimension</strong> of the screen.
+	  * @param graphic The default <strong>GraphicsConfiguration</strong> for this platform.
+	  */
+	 public GUIManager(Dimension size) {
+		  super();
+		  // Initialization
+		  this.help = new HelpFrame();
+		  this.size = size;
+		  this.collection_tree_sync = new TreeSynchronizer();
+		  this.workspace_tree_sync = new TreeSynchronizer();
+		  // Make the Tool tip hang around for a rediculous amount of time.
+		  ToolTipManager.sharedInstance().setDismissDelay(10000);
+		  // Get a reference to the main thread group. Create a new thread, which defaults into the same thread group, then get its thread group. Easy.
+		  Thread bob = new Thread();
+		  thread_group = bob.getThreadGroup();
+		  // Set up some other UI stuff. (fonts handled in Gatherer.main())
+		  UIManager.put("FileChooser.lookInLabelText", Gatherer.dictionary.get("SaveCollectionBox.Look_In"));
+		  UIManager.put("FileChooser.filesOfTypeLabelText", Gatherer.dictionary.get("SaveCollectionBox.Files_Of_Type"));
+		  UIManager.put("FileChooser.fileNameLabelText", Gatherer.dictionary.get("SaveCollectionBox.File_Name"));
+	 }
+	 /** 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) {
+		  boolean cont = true;
+		  Object esrc = event.getSource();
+		  // *************
+		  // File Options.
+		  // *************
+		  if(esrc == menu_bar.file_associations) {
+				Gatherer.assoc_man.edit();
+		  }
+		  else if(esrc == menu_bar.file_close) {
+				if(!Gatherer.c_man.saved()) {
+					 cont = showSaveCollectionBox(true, false);
+				}
+				if(cont) {
+					 tab_pane.setSelectedComponent(collection_pane);
+				}
+		  }
+		  else if(esrc == menu_bar.file_delete) {
+				DeleteCollectionPrompt dcp = new DeleteCollectionPrompt();
+				dcp.display();
+				dcp.destroy();
+				dcp = null;
+				System.gc();
+		  }
+		  else if(esrc == menu_bar.file_exit) {
+				exit();
+		  }
+        else if(esrc == menu_bar.file_new) {
+				if(!Gatherer.c_man.saved()) {
+					 cont = showSaveCollectionBox(true, false);
+				}
+				if(cont) {
+					 try {
+						  while(Gatherer.c_man.ready()) {
+								wait(10);
+						  }
+					 }
+					 catch(Exception error) {
+					 }
+					 showNewCollectionPrompt();
+				}
+		  }
+		  else if(esrc == menu_bar.file_open) {
+				if(!Gatherer.c_man.saved()) {
+					 cont = showSaveCollectionBox(true, false);
+				}
+				if(cont) {
+					 try {
+						  while(Gatherer.c_man.ready()) {
+								wait(10);
+						  }
+					 }
+					 catch(Exception error) {
+					 }
+					 if(!showLoadCollectionBox()) {
+						  collectionChanged(false);
+					 }
+				}
+		  }
+		  else if(esrc == menu_bar.file_options) {
+		  		new Preferences();
+		  }
+		  else if(esrc == menu_bar.file_save) {
+				Gatherer.c_man.saveCollection(false, false);
+		  }
+		  else if(esrc == menu_bar.file_save_as) {
+				String name = JOptionPane.showInputDialog(this, "Enter new collection filename.");
+				if(name != null) {
+					 Gatherer.c_man.saveCollectionAs(name);
+				}
+		  }
+		  // *************
+		  // 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 cut command
+					 cce.printStackTrace();
+				}
+		  }
+		  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
+					 cce.printStackTrace();
+				}
+		  }
+		  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 cut command
+					 cce.printStackTrace();
+				}
+		  }
+		  else if(esrc == menu_bar.edit_search) {
+				if(sar != null) {
+					 sar.dispose();
+				}
+				sar = new SearchAndReplace(false);
+		  }
+		  else if(esrc == menu_bar.edit_replace) {
+				if(sar != null) {
+					 sar.dispose();
+				}
+				sar = new SearchAndReplace(true);
+		  }
+		  // *************
+		  // Tools Options.
+		  // *************
+		  else if(esrc == menu_bar.tools_size) {
+				FileNode records[] = metaedit_pane.getSelectedNode();
+				if(records != null && records.length > 0) {
+					 ArrayList metadatum = Gatherer.c_man.getCollection().gdm.getMetadata(records[0].getFile());
+					 if(metadatum.size() >= 4) {
+						  Metadata metadata = (Metadata) metadatum.get(0);
+						  ElementWrapper ew = metadata.getElement();
+
+						  int SIZE = 5000;
+						  Object[] array = new Object[SIZE];  
+						  Runtime.getRuntime().gc();  
+						  long start = Runtime.getRuntime().freeMemory();
+						  for (int i = 0; i < SIZE; i++) {
+								array[i] = ew.copy();
+						  }
+						  Runtime.getRuntime().gc();
+						  long end = Runtime.getRuntime().freeMemory();
+						  long difference = (( start -  end ) / SIZE);
+						  ///ystem.out.println(difference + " bytes used." ); 						  
+					 }
+				}
+		  }
+		  // *************
+		  // Help Options.
+		  // *************
+		  else if(esrc == menu_bar.help_about) {
+				new AboutDialog(this);
+		  }
+		  else if(esrc == menu_bar.help_browse) {
+				help.setView("3.0");
+		  }
+		  else if(esrc == menu_bar.help_build) {
+				help.setView("8.0");
+		  }
+		  else if(esrc == menu_bar.help_collect) {
+				help.setView("5.0"); 
+		  }
+		  else if(esrc == menu_bar.help_design) {
+				help.setView("7.0"); 
+		  }
+		  else if(esrc == menu_bar.help_general) {
+				help.setView(""); 
+		  }
+		  else if(esrc == menu_bar.help_metaedit) {
+				help.setView("6.0");
+		  }
+		  else if(esrc == menu_bar.help_mirror) {
+				help.setView("4.0"); 
+		  }
+		  else if(esrc == menu_bar.help_preview) {
+				help.setView("9.0");
+		  }
+		  // *****************
+		  // Metadata Options.
+		  // *****************
+		  else if(esrc == menu_bar.metadata_add) {
+				Gatherer.c_man.getCollection().msm.importMDS();
+		  }
+		  else if(esrc == menu_bar.metadata_edit) {
+				showEditMetadataBox();
+		  }
+		  else if(esrc == menu_bar.metadata_export) {
+				Gatherer.c_man.getCollection().msm.exportMDS();
+		  }
+		  else if(esrc == menu_bar.metadata_view) {
+				showMetaAuditBox();
+		  }
+		  else if(esrc == menu_bar.tools_log) {
+				showLogBox();
+		  }
+	 }
+	 /** 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(Gatherer.config.get("workflow.mirror", true)) {
+				browser_pane.afterDisplay();
+		  }
+		  metaedit_pane.afterDisplay();
+	 }
+	 /** Once a collection has been made available to Gatherer, either by its creation or by it being reloaded, we need to inform all the visual components to update necessary data components (such as tree models), enable certain controls that depend on a collection being accessible, and refresh themselves.
+	  * @param ready <i>true</i> if the collection is ready for editing, <i>false</i> otherwise.
+	  */
+	 public void collectionChanged(final boolean ready) {
+		  collection_tree_sync.clear(); // Clear any mappings in the tree synchronizers as being old news.
+		  workspace_tree_sync.clear();
+		  if(Gatherer.config.get("workflow.mirror", true)) {
+				mirror_pane.collectionChanged(ready);
+		  }
+		  menu_bar.collectionChanged(ready); // Inform the menu bar that the collections changed.
+		  collection_pane.collectionChanged(ready); // Used to update the collection workspace.
+		  metaedit_pane.collectionChanged(ready); // Very important that metaedit pane shows current collection and is listening to latest msm.
+		  config_pane.collectionChanged(ready); // Also important config pane is listening to latest msm.
+		  create_pane.collectionChanged(ready); // Used to indicate a new BuildOptions model should be loaded.
+		  // Force tree model updates.
+		  Gatherer.c_man.refreshTrees();
+		  if(!locked) {
+				// Now enable tabs as necessary. Do this on event queue to prevent crazy NPEs
+				if(tab_updater == null) {
+					 tab_updater = new TabUpdater(tab_pane, ready);
+				}
+				else {
+					 tab_updater.setReady(ready);
+				}
+				SwingUtilities.invokeLater(tab_updater);
+		  }
+		  // Finally display the collection name in the title bar.
+		  if(ready) {
+				this.setTitle(Utility.PROGRAM_NAME + ":\"" + Gatherer.c_man.getCollection().getTitle() + "\"");
+		  }
+		  else {
+				this.setTitle(Utility.PROGRAM_NAME + ": " + get("Collection.No_Collection"));
+		  }
+		  // Now is a good time to force a garbage collect.
+		  ///ystem.err.println("Calling garbage collection.");
+		  System.gc();
+	 }
+	 /** 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);
+				if(Gatherer.c_man.ready()) {
+					 this.setTitle(Utility.PROGRAM_NAME + ":\"" + Gatherer.c_man.getCollection().getTitle() + "\"");
+				}
+				else {
+					 this.setTitle(Utility.PROGRAM_NAME + ": " + get("Collection.No_Collection"));
+				}
+				// Pretty corner icon
+				this.setIconImage(Utility.getImage("gatherer_small.gif").getImage());
+				// BorderLayout for the main screen. I'll try my best to avoid t
+				// hese 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());
+				content_pane.add(menu_bar, BorderLayout.NORTH);	
+				// 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(Gatherer.config.getFont("general.font", false));
+
+				// May have to play with the order in which tabs are added.
+				if(Gatherer.config.get("workflow.browse", true)) {
+					 browser_pane = new BrowsingPane();
+					 tab_pane.addTab(get("Browser"), Utility.getImage("browsing.gif"), browser_pane);
+					 tab_pane.setEnabledAt(tab_pane.indexOfComponent(browser_pane), Gatherer.config.get("workflow.browse", false));
+				}
+				
+				if(Gatherer.config.get("workflow.mirror", true)) {
+					 mirror_pane = new MirrorPane(workspace_tree_sync);
+					 mirror_pane.display();
+					 tab_pane.addTab(get("Mirroring"), Utility.getImage("mirroring.gif"), mirror_pane);
+					 tab_pane.setEnabledAt(tab_pane.indexOfComponent(mirror_pane), Gatherer.config.get("workflow.mirror", false));
+				}				
+
+				if(Gatherer.config.get("workflow.gather", true)) {
+					 collection_pane = new CollectionPane(workspace_tree_sync, collection_tree_sync);
+					 collection_pane.display();
+					 tab_pane.addTab(get("Collection"), Utility.getImage("collection.gif"), collection_pane);
+					 tab_pane.setEnabledAt(tab_pane.indexOfComponent(collection_pane), Gatherer.config.get("workflow.gather", false));
+				}
+
+				if(Gatherer.config.get("workflow.enrich", true)) {
+					 metaedit_pane = new MetaEditPane(collection_tree_sync);
+					 metaedit_pane.display();
+					 tab_pane.addTab(get("MetaEdit"), Utility.getImage("metaedit.gif"), metaedit_pane);
+					 tab_pane.setEnabledAt(tab_pane.indexOfComponent(metaedit_pane), false);
+				}
+				
+				if(Gatherer.config.get("workflow.design", true)) {
+					 config_pane = new GConfigPane();
+					 config_pane.display();
+					 tab_pane.addTab(get("Build"), Utility.getImage("build.gif"), config_pane);
+					 tab_pane.setEnabledAt(tab_pane.indexOfComponent(config_pane), false);
+				}
+				
+				if(Gatherer.config.get("workflow.export", true)) {
+					 tab_pane.addTab(get("Export"), Utility.getImage("export.gif"), export_pane);
+					 tab_pane.setEnabledAt(tab_pane.indexOfComponent(export_pane), false);
+				}
+				
+				if(Gatherer.config.get("workflow.create", true)) {
+					 create_pane = new CreatePane();
+					 create_pane.display();
+					 tab_pane.addTab(get("Create"), Utility.getImage("build session.gif"), create_pane);
+					 tab_pane.setEnabledAt(tab_pane.indexOfComponent(create_pane), false);
+				}
+				
+				if(Gatherer.config.get("workflow.preview", true)) {
+					 preview_pane = new PreviewPane();
+					 preview_pane.display();
+					 tab_pane.addTab(get("Preview"), Utility.getImage("final.gif"), preview_pane);
+					 tab_pane.setEnabledAt(tab_pane.indexOfComponent(preview_pane), false);
+				}
+
+				// Find the first tab that is enabled and select that.
+				boolean found = false;
+				for(int i = 0; !found && i < tab_pane.getTabCount(); i++) {
+					 if(tab_pane.isEnabledAt(i)) {
+						  tab_pane.setSelectedIndex(i);
+						  found = true;
+					 }
+				}
+
+				content_pane.add(tab_pane, BorderLayout.CENTER);
+				// Drive a sessionReady event to update all controls to reflect current collection status.
+				collectionChanged(Gatherer.c_man.ready());
+		  }
+		  catch (Exception e) {
+				Gatherer.printStackTrace(e);
+				// The GUI failing to build is a app killer
+				e.printStackTrace();
+				System.exit(1);
+		  }
+	 }
+	 /** When called this method ensures that all the things needing saving are saved before Gatherer.exit() is called. This includes a save collection prompt if necessary.
+	  */
+	 public void exit() {
+		  boolean cont = true;
+		  if(Gatherer.c_man.ready() && !Gatherer.c_man.saved()) {
+				cont = showSaveCollectionBox(false, true);
+		  }
+		  else {
+				help.destroy();
+				help = null;
+				Gatherer.self.exit();
+		  }
+	 }
+	 /** Retrieve the filter, or if one already exists, spawn a linked copy. */
+	 public Filter getFilter(DragTree tree) {
+		  Filter filter = (Filter) filters.get(tree.getModel());
+		  if(filter == null) {
+				filter = new Filter(tree, null);
+				filters.put(tree.getModel(), filter);
+				return filter;
+		  }
+		  return filter.spawn(tree);
+	 }
+
+	 public Component getSelectedView() {
+		  return tab_pane.getSelectedComponent();
+	 }
+	 /** 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 collection_pos = tab_pane.indexOfComponent(collection_pane);
+				int metaedit_pos = tab_pane.indexOfComponent(metaedit_pane);
+				int config_pos = tab_pane.indexOfComponent(config_pane);
+				tab_pane.setEnabledAt(collection_pos, !lock);
+				tab_pane.setEnabledAt(metaedit_pos, !lock);
+				tab_pane.setEnabledAt(config_pos, !lock);
+		  }
+		  else {
+				int config_pos = tab_pane.indexOfComponent(config_pane);
+				tab_pane.setEnabledAt(config_pos, !lock);
+		  }
+	 }
+
+	 public void refreshTrees() {
+		  collection_pane.refreshTrees();
+		  //metaedit_pane.refreshTrees();
+	 }
+
+	 /** Allows the system to programatically set the selected tab. 
+	  * @param component The view you wish to make visable in the tab pane as a <strong>Component</strong>.
+	  */
+	 public void setSelectedView(Component component) {
+		  tab_pane.setSelectedComponent(component);
+	 }
+
+	 /** Specifies whether a certain tab is enabled or not. */
+	 public void setTabEnabled(String rawname, boolean state) {
+		  // Retrieve the dictionary based name.
+		  String name = get(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 == preview_pane) {
+					 tab_pane.setEnabledAt(index, state && Gatherer.c_man != null && Gatherer.c_man.ready() && Gatherer.c_man.built());
+				}
+				else if(component == metaedit_pane || component == config_pane || component == export_pane || component == create_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);
+					 }
+				}
+		  }
+	 }
+
+	 /** When the edit metadata option is choosen from the menu, this method is called to ensure we only edit the metadata if there is metadata loaded.
+	  */
+	 public void showEditMetadataBox() {
+		  if(Gatherer.c_man.getCollection() != null) {
+				Gatherer.c_man.getCollection().msm.editMDS();
+		  }
+	 }
+	 /** When the load collection option is choosen this method is called to produce the modal file load prompt.
+	  */
+	 public boolean showLoadCollectionBox() {
+		  boolean result = false;
+		  //LoadCollectionBox load_collection_box = new LoadCollectionBox();
+		  File file;
+		  if(Gatherer.config.gsdl_path != null) {
+				file = new File(Utility.getCollectionDir(Gatherer.config.gsdl_path));
+		  }
+		  else {
+				file = new File(Utility.BASE_DIR);
+		  }
+		  OpenCollectionDialog chooser = new OpenCollectionDialog(file);
+		  String filename = chooser.getFileName();
+		  // User can cancel action.
+		  if(filename != null) {
+				result = Gatherer.c_man.loadCollection(filename);
+		  }
+		  return result;
+	 }
+	 /** When called this method causes the Log class in Gatherer to display a nice dialog box which contains the log.
+	  */
+	 public void showLogBox() {
+		  Gatherer.log.display();
+	 }
+	 /** When called this method causes the MetaAuditBox class in CollectionManager to display a nice dialog box which contains all the metadata assigned in the collection.
+	  */
+	 public void showMetaAuditBox() {
+		  if(meta_audit == null) {
+				FileNode records[] = metaedit_pane.getSelectedNode();
+				if(records == null) {
+					 records = collection_pane.getSelected();
+				}
+				if(records != null) {
+					 wait(true);
+					 meta_audit = new MetaAuditFrame(collection_tree_sync, records);
+				}
+		  }
+		  if(meta_audit != null) {
+				wait(true);
+				meta_audit.display();
+		  }
+		  wait(false);
+	 }
+	 /** This method is used to open the new collection box on the screen.
+	  */
+	 public void showNewCollectionPrompt() {
+		  NewCollectionMetadataPrompt ncm_prompt = null;
+		  // Create the collection details prompt from new collection prompt
+		  NewCollectionDetailsPrompt ncd_prompt = new NewCollectionDetailsPrompt();
+		  // If no previous collection was indicated as a model design, then show the metadata selection prompt from new collection prompt
+		  if(!ncd_prompt.isCancelled() && (ncd_prompt.getBase() == null || ncd_prompt.getBase().length() == 0)) {
+				ncm_prompt = new NewCollectionMetadataPrompt();
+		  }
+		  // Create the new collection (if not cancelled) in a new thread.
+		  if(!ncd_prompt.isCancelled() && (ncm_prompt == null || !ncm_prompt.isCancelled())) {
+				// Create new collection.
+				CreationTask task = new CreationTask(ncd_prompt, ncm_prompt);
+				SwingUtilities.invokeLater(task);
+				// Close prompt.
+		  }
+		  // Done
+		  ncd_prompt = null;
+		  ncm_prompt = null;
+	 }
+	 private class CreationTask
+		  implements Runnable {
+		  private NewCollectionDetailsPrompt ncd_prompt = null;
+		  private NewCollectionMetadataPrompt ncm_prompt = null; 
+		  public CreationTask(NewCollectionDetailsPrompt ncd_prompt, NewCollectionMetadataPrompt ncm_prompt) {
+				this.ncd_prompt = ncd_prompt;
+				this.ncm_prompt = ncm_prompt;
+		  }
+
+		  public void run() {
+				if(ncm_prompt == null) {
+					 Gatherer.c_man.createCollection(ncd_prompt.getDescription(), ncd_prompt.getEmail(), ncd_prompt.getName(), ncd_prompt.getTitle(), ncd_prompt.getBase(), null);
+				}
+				else {
+					 Gatherer.c_man.createCollection(ncd_prompt.getDescription(), ncd_prompt.getEmail(), ncd_prompt.getName(), ncd_prompt.getTitle(), null, ncm_prompt.getSets());
+				}
+				ncd_prompt.dispose();
+				ncd_prompt = null;
+				if(ncm_prompt != null) {
+					 ncm_prompt.dispose();
+					 ncm_prompt = null;
+				}
+		  }
+	 }
+
+	 /** This method is used to open the options box on the screen.
+	  */
+	 public void showOptionsBox() {
+		  new OptionsBox();
+	 }
+	 /** This method is used to open the save collection box/prompt on the screen.
+	  * @return A <i>boolean</i> which is <i>true</i> if the collection was saved successfully, <i>false</i> otherwise.
+	  */
+	 public boolean showSaveCollectionBox(boolean close_after, boolean exit_after) {
+		  SaveCollectionBox save_collection_box = new SaveCollectionBox();
+		  Rectangle bounds = save_collection_box.getBounds();
+		  int result = save_collection_box.getUserOption(Gatherer.c_man.getCollection().getName());
+		  switch(result) {
+		  case SaveCollectionBox.SAVE_YES:
+				Gatherer.c_man.saveCollection(close_after, exit_after);
+				content_pane.paintImmediately(bounds);
+				return true;
+		  case SaveCollectionBox.SAVE_NO:
+				// Close collection.
+				if(close_after) {
+					 tab_pane.setSelectedComponent(collection_pane);
+					 Gatherer.c_man.closeCollection();
+				}
+				if(exit_after) {
+					 Gatherer.self.exit();
+				}
+				return true;
+		  default:
+				return false;
+		  }
+	 }
+	 /** 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 == create_pane) {
+					 create_pane.loseFocus();
+				}
+		  }
+		  menu_bar.tabSelected(tab_pane.getSelectedIndex());
+		  if(tab_pane.getSelectedIndex() == tab_pane.indexOfComponent(collection_pane)) {
+				menu_bar.metadata_view.setEnabled(true);
+		  }
+		  else if(tab_pane.getSelectedIndex() == tab_pane.indexOfComponent(metaedit_pane)) {
+				metaedit_pane.gainFocus();
+				menu_bar.metadata_view.setEnabled(true);
+		  }
+		  else if(tab_pane.getSelectedIndex() == tab_pane.indexOfComponent(config_pane)) {
+				config_pane.gainFocus();
+				menu_bar.metadata_view.setEnabled(false);
+		  }
+		  else if(tab_pane.getSelectedIndex() == tab_pane.indexOfComponent(create_pane)) {
+				create_pane.gainFocus();
+				menu_bar.metadata_view.setEnabled(false);
+		  }
+		  else if(tab_pane.getSelectedIndex() == tab_pane.indexOfComponent(preview_pane)) {
+				config_pane.saveConfiguration();
+				preview_pane.gainFocus();
+				menu_bar.metadata_view.setEnabled(false);
+		  }
+		  else {
+				menu_bar.metadata_view.setEnabled(false);
+		  }
+		  previous_pane = (JPanel) tab_pane.getSelectedComponent();
+	 }
+
+	 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;
+	 }
+
+	 public void workflowUpdate(String raw, boolean state) {
+		  WorkflowUpdater task = new WorkflowUpdater(raw, state);
+		  SwingUtilities.invokeLater(task);
+		  task = null;
+	 }
+
+	 /** Retrieves a phrase from the Dictionary based on the key.
+	  * @param key A <strong>String</strong> uniquely identifying a phrase from the Dictionary.
+	  * @return The desired phrase as a <strong>String</strong>.
+	  * @see org.greenstone.gatherer.Dictionary
+	  */
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+	 /** Retrieves a phrase from the Dictionary based on the key and including the arguments.
+	  * @param key A <strong>String</strong> uniquely identifying a phrase from the Dictionary.
+	  * @param args A <strong>String[]</strong> of arguments available to be inserted into the phrase.
+	  * @return The desired phrase as a <strong>String</strong>.
+	  * @see org.greenstone.gatherer.Dictionary
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf('.') == -1) {
+				key = "GUI." + key;
+		  }
+		  return Gatherer.dictionary.get(key, args);
+	 }
+	 /** Called to determine if we should wait for a thread to finish before continuing. We wait for threads if they are named: GSHELL_BUILD, GSHELL_IMPORT, or GSHELL_NEW.
+	  * @return <i>true</i> if we should wait for a thread, <i>false</i> if it is safe to continue.
+	  */
+	 private boolean waitForThread() {
+		  Thread active[] = new Thread[thread_group.activeCount()];
+		  int size = thread_group.enumerate(active);
+		  for(int i = 0; i < size; i++) {
+				if(active[i].getName().equals(GShell.GSHELL_BUILD) ||
+					active[i].getName().equals(GShell.GSHELL_IMPORT) ||
+					active[i].getName().equals(GShell.GSHELL_NEW)) {
+					 return true;
+				}
+		  }
+		  return false;
+	 }
+
+
+	 /**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 fred 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 browse_pos = -1;
+		  private int mirror_pos = -1;
+		  private int config_pos = -1;
+		  private int create_pos = -1;
+		  private int export_pos = -1;
+		  private int metaedit_pos = -1;
+		  private int preview_pos = -1;
+		  private JTabbedPane tab_pane = null;
+		  public TabUpdater(JTabbedPane tab_pane, boolean ready) {
+				this.ready = ready;
+				this.tab_pane = tab_pane;
+				browse_pos = tab_pane.indexOfComponent(browser_pane);
+				mirror_pos = tab_pane.indexOfComponent(mirror_pane);
+				metaedit_pos = tab_pane.indexOfComponent(metaedit_pane);
+				config_pos = tab_pane.indexOfComponent(config_pane);
+				export_pos = tab_pane.indexOfComponent(export_pane);
+				create_pos = tab_pane.indexOfComponent(create_pane);
+				preview_pos = tab_pane.indexOfComponent(preview_pane);
+		  }
+		  public void run() {
+				if(browse_pos != -1) {
+					 if(ready) {
+						  tab_pane.setEnabledAt(browse_pos, Gatherer.config.get("workflow.browse", false));
+					 }
+					 else {
+						  tab_pane.setEnabledAt(browse_pos, Gatherer.config.get("workflow.browse", true));
+					 }
+				}
+				if(mirror_pos != -1) {
+					 if(ready) {
+						  tab_pane.setEnabledAt(mirror_pos, Gatherer.config.get("workflow.mirror", false));
+					 }
+					 else {
+						  tab_pane.setEnabledAt(mirror_pos, Gatherer.config.get("workflow.mirror", true));
+					 }
+				}
+				if(metaedit_pos != -1) {
+					 tab_pane.setEnabledAt(metaedit_pos, ready && Gatherer.config.get("workflow.enrich", false));
+				}
+				if(config_pos != -1) {
+					 tab_pane.setEnabledAt(config_pos, ready && Gatherer.config.get("workflow.design", false));
+				}
+				if(export_pos != -1) {
+					 tab_pane.setEnabledAt(export_pos, ready && Gatherer.config.get("workflow.export", false));
+				}
+				if(create_pos != -1) {
+					 tab_pane.setEnabledAt(create_pos, ready && Gatherer.config.get("workflow.create", false));
+				}
+				if(preview_pos != -1) {
+					 tab_pane.setEnabledAt(preview_pos, Gatherer.c_man != null && Gatherer.c_man.built() && Gatherer.config.get("workflow.preview", false));
+				}
+		  }
+		  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/start/gli/src/org/greenstone/gatherer/gui/LockFileDialog.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/LockFileDialog.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/LockFileDialog.java	(revision 13666)
@@ -0,0 +1,183 @@
+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.msm.MSMUtils;
+import org.greenstone.gatherer.util.Utility;
+import org.w3c.dom.*;
+
+public class LockFileDialog
+	 extends JDialog {
+
+	 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, 225);
+	 static final private int ICON_SIZE = 30;
+	 static final private JTextField FIELD = new JTextField("Dummy");
+
+	 public LockFileDialog(JFrame parent, String name, File lock_file) {
+		  super(parent, get("Title"), true);
+		  setSize(SIZE);
+		  this.self = this;
+		  // Parse the lock file, but do so quietly so that if the XML is poorly formed it doesn't show exception.
+		  document = Utility.parse(lock_file, false);
+		  // Creation
+		  JPanel content_pane = (JPanel) getContentPane();
+		  JPanel upper_pane = new JPanel();
+		  ImageIcon icon = Utility.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(get("General.Warning"));
+		  JLabel title_two_label = new JLabel(get("Lockfile_Message_One"));
+		  JPanel central_pane = new JPanel();
+		  JPanel name_pane = new JPanel();
+		  JLabel name_label = new JLabel(get("Name"));
+		  name_label.setPreferredSize(LABEL_SIZE);
+		  MyLabel name_field = new MyLabel(name);
+		  JPanel person_pane = new JPanel();
+		  JLabel person_label = new JLabel(get("User"));
+		  person_label.setPreferredSize(LABEL_SIZE);
+		  MyLabel person_field = new MyLabel(getValue("User"));
+		  JPanel machine_pane = new JPanel();
+		  JLabel machine_label = new JLabel(get("Machine"));
+		  machine_label.setPreferredSize(LABEL_SIZE);
+		  MyLabel machine_field = new MyLabel(getValue("Machine"));
+		  JPanel created_pane = new JPanel();
+		  JLabel created_label = new JLabel(get("Date"));
+		  created_label.setPreferredSize(LABEL_SIZE);
+		  MyLabel created_field = new MyLabel(getValue("Date"));
+		  JLabel central_label = new JLabel(get("Lockfile_Message_Two"));
+		  JPanel button_pane = new JPanel();
+		  ok_button = new JButton(get("General.OK"));
+		  cancel_button = new JButton(get("General.Cancel"));
+		  // 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 GridLayout(2,1,0,5));
+		  title_pane.add(title_one_label);
+		  title_pane.add(title_two_label);
+
+		  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() {
+		  show();
+		  return choice;
+	 }
+
+	 private String getValue(String name) {
+		  String value = "";
+		  if(document != null) {
+				try {
+					 Element value_element = (Element) MSMUtils.getNodeFromNamed(document.getDocumentElement(), name);
+					 value = MSMUtils.getValue(value_element);
+				}
+				catch (Exception error) {
+				}
+		  }
+		  else {
+				value = get("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.hide();
+				self.dispose();
+		  }
+	 }
+
+	 private class MyLabel
+		  extends JLabel {
+		  public MyLabel(String text) {
+				super(text);
+				setBackground(FIELD.getBackground());
+				setBorder(FIELD.getBorder());
+				setOpaque(true);
+		  }
+	 }
+
+	 static public void main(String[] args) {
+		  JFrame frame = new JFrame();
+		  frame.setSize(640,480);
+		  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+		  frame.show();
+		  LockFileDialog dialog = new LockFileDialog(frame, "Test", new File(args[0]));
+		  int choice = dialog.getChoice();
+	 }
+
+	 static private String get(String key) {
+		  if(key.indexOf(".") == -1) {
+				key = "LockFileDialog." + key;
+		  }
+		  return Gatherer.dictionary.get(key);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/LongProgressBar.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/LongProgressBar.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/LongProgressBar.java	(revision 13666)
@@ -0,0 +1,242 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.math.BigInteger;
+import javax.swing.JProgressBar;
+import javax.swing.SwingUtilities;
+/** 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
+ * @version 2.3c
+ */
+final public class LongProgressBar
+	 extends JProgressBar {
+	 private BigInteger cur_value = null;
+	 private BigInteger max_value = null;
+	 private BigInteger min_value = null;
+	 /** The previous percentage value. */
+	 private int previous = -1;
+	 private SafeSetIndeterminate safe_set_indeterminate = null;
+	 private SafeSetString safe_set_string = null;
+	 private SafeSetValue safe_set_value = null;
+	 public LongProgressBar() {
+		  super(0, 100);
+		  cur_value = BigInteger.ZERO;
+		  min_value = BigInteger.ZERO;
+		  max_value = BigInteger.ZERO;
+	 }
+
+	 public void addMaximum(int size) {
+		  ///ystem.err.println("Add maximum " + size);
+		  if(size > 0) {
+				max_value = max_value.add(new BigInteger((new Integer(size)).toString()));
+				update();
+		  }
+	 }
+
+	 public void addMaximum(long size) {
+		  ///ystem.err.println("Add maximum " + size);
+		  if(size > 0) {
+				max_value = max_value.add(new BigInteger((new Long(size)).toString()));
+				update();
+		  }
+	 }
+
+	 public void addValue(int size) {
+		  ///ystem.err.println("Add value " + size);
+		  if(size > 0) {
+				cur_value = cur_value.add(new BigInteger((new Integer(size)).toString()));
+				update();
+		  }
+	 }
+
+	 public void addValue(long size) {
+		  ///ystem.err.println("Add value " + size);
+		  if(size > 0) {
+				cur_value = cur_value.add(new BigInteger((new Long(size)).toString()));
+				update();
+		  }
+	 }
+
+	 public void refreshString() {
+		  safeSetString(previous + "%");
+	 }
+
+	 public void reset() {
+		  cur_value = BigInteger.ZERO;
+		  max_value = BigInteger.ZERO;
+		  previous = -1;
+		  update();
+	 }
+
+	 public void setIndeterminate(boolean state) {
+		  if(safe_set_indeterminate == null) {
+				safe_set_indeterminate = new SafeSetIndeterminate(state);
+		  }
+		  else {
+				safe_set_indeterminate.setState(state);
+		  }
+		  SwingUtilities.invokeLater(safe_set_indeterminate);		  
+	 }
+
+	 public void setMaximum(int size) {
+		  ///ystem.err.println("Add maximum " + size);
+		  if(size > 0) {
+				max_value = new BigInteger((new Integer(size)).toString());
+				update();
+		  }
+	 }
+
+	 public void setMaximum(long size) {
+		  ///ystem.err.println("Add maximum " + size);
+		  if(size > 0) {
+				max_value = new BigInteger((new Long(size)).toString());
+				update();
+		  }
+	 }
+
+	 public void setString(String label) {
+	 	  safeSetString(label);
+	 }
+	 
+	 public void setValue(int size) {
+		  ///ystem.err.println("Set value " + size);
+		  cur_value = new BigInteger((new Integer(size)).toString());
+		  update();
+	 }
+
+	 public void setValue(long size) {
+		  ///ystem.err.println("Set value " + size);
+		  cur_value = new BigInteger((new Long(size)).toString());
+		  update();
+	 }
+
+	 /** This method is an unsafe way to set the progress bar to be indeterminate, -unless- it is called from the Event Queue. */
+	 public void unsafeSetIndeterminate(boolean state) {
+		  super.setIndeterminate(state);
+	 }
+
+	 public void unsafeSetString(String label) {
+		  super.setString(label);
+	 }
+
+	 public void unsafeSetValue(int value) {
+		  ///ystem.err.println("Set value: " + value);
+		  super.setValue(value);
+	 }
+
+	 private void update() {
+		  int percentage = -1;
+		  if(cur_value.equals(BigInteger.ZERO) || max_value.equals(BigInteger.ZERO)) {
+				percentage = 0;
+		  }
+		  else {
+				BigInteger tmp_value = cur_value.multiply(new BigInteger("100"));
+				BigInteger per_value = tmp_value.divide(max_value);
+				percentage = per_value.intValue();
+				if(percentage > 100) {
+					 percentage = 100;
+				}
+		  }
+		  if(percentage != previous) {
+				///ystem.err.println("Progress bar status: value = " + getValue());
+				previous = percentage;
+				safeSetValue(percentage);
+				safeSetString(percentage + "%");
+		  }
+	 }
+	 /** Change the string displayed on the progress bar.
+	  * @param label The name progress bar label as a <strong>String</strong>.
+	  * Original code: Tad Frysinger (TeamB)
+	  */
+	 private void safeSetString(String label) {
+		  if(safe_set_string == null) {
+				safe_set_string = new SafeSetString(label);
+		  }
+		  else {
+				safe_set_string.setLabel(label);
+		  }
+		  SwingUtilities.invokeLater(safe_set_string);  
+	 }
+	 
+	 /** Increase the value of the progress bar.
+	  * @param ammount The ammount to increase as an <i>int</i>.
+	  * Original code: Tad Frysinger (TeamB)
+	  */
+	 private void safeSetValue(final int ammount) {
+		  // Update progress bar,
+		  if(safe_set_value == null) {
+				safe_set_value = new SafeSetValue(ammount);
+		  }
+		  else {
+				safe_set_value.setValue(ammount);
+		  }
+		  SwingUtilities.invokeLater(safe_set_value);  
+	 }
+
+	 private class SafeSetIndeterminate 
+		  implements Runnable {
+		  private boolean value;
+		  public SafeSetIndeterminate(boolean value) {
+				this.value = value;
+		  }
+		  public void run() {
+				unsafeSetIndeterminate(value);
+		  }
+		  synchronized public void setState(boolean value) {
+				this.value = value;
+		  }
+	 }
+
+	 private class SafeSetString 
+		  implements Runnable {
+		  private String label = null;
+		  public SafeSetString(String label) {
+				this.label = label;
+		  }
+		  public void run() {
+				unsafeSetString(label);
+		  }
+		  synchronized public void setLabel(String label) {
+				this.label = label;
+		  }
+	 }
+
+	 private class SafeSetValue 
+		  implements Runnable {
+		  private int value = -1;
+		  public SafeSetValue(int value) {
+				this.value = value;
+		  }
+		  public void run() {
+				unsafeSetValue(value);
+		  }
+		  synchronized public void setValue(int value) {
+				this.value = value;
+		  }
+	 }
+}
+
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/MenuBar.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/MenuBar.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/MenuBar.java	(revision 13666)
@@ -0,0 +1,398 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.util.Utility;
+/** 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 {
+	 /** The icon to be displayed alongside the context choosen help file. */
+	 private int current_tab          = -1;
+	 private JMenu file               = null;
+	 private JMenu edit               = null;
+	 private JMenu metadata           = null;
+	 private JMenu tools              = null;
+	 private JMenu log                = null;
+	 private JMenu window             = null;
+	 private JMenu source             = null;
+	 private JMenu level              = null; 
+	 public JMenu help                = null;
+	 public JMenuItem file_associations;
+	 public JMenuItem file_close      = null;
+	 public JMenuItem file_delete     = null;
+	 public JMenuItem file_exit       = null;
+	 public JMenuItem file_new        = null;
+	 public JMenuItem file_open       = null;
+	 public JMenuItem file_options    = null;
+	 public JMenuItem file_save       = null;
+	 public JMenuItem file_save_as;
+	 public JMenuItem edit_copy;
+	 public JMenuItem edit_cut;
+	 public JMenuItem edit_paste;
+	 public JMenuItem edit_undo       = null;
+	 public JMenuItem edit_redo       = null;
+	 public JMenuItem edit_replace = null;
+	 public JMenuItem edit_search = null;
+	 public JMenuItem metadata_add    = null;
+	 public JMenuItem metadata_edit   = null;
+	 public JMenuItem metadata_export = null;
+	 public JMenuItem metadata_view   = null;
+	 public JMenuItem tools_log       = null;
+	 public JMenuItem tools_size      = null;
+	 public JMenuItem help_about;
+	 public JMenuItem help_browse;
+	 public JMenuItem help_build;
+	 public JMenuItem help_collect;
+	 public JMenuItem help_design;
+	 public JMenuItem help_export;
+	 public JMenuItem help_general;
+	 public JMenuItem help_metaedit;
+	 public JMenuItem help_mirror ;
+	 public JMenuItem help_preview;
+
+	 public MenuBar(MenuListener menu_listener) {
+
+		  file = new JMenu(get("File"));
+		  file.setMnemonic(KeyEvent.VK_F);
+		  this.add(file);
+
+		  file_associations = new JMenuItem(get("File_Associations"), KeyEvent.VK_A);
+		  file_associations.addActionListener(Gatherer.g_man);	  
+
+		  file_close = new JMenuItem(get("File_Close"), KeyEvent.VK_C);
+		  file_close.addActionListener(Gatherer.g_man);
+		  file_close.setEnabled(false);
+
+		  file_delete = new JMenuItem(get("File_Delete"), KeyEvent.VK_D);
+		  file_delete.addActionListener(Gatherer.g_man);
+
+		  file_exit = new JMenuItem(get("File_Exit"), KeyEvent.VK_X);
+		  file_exit.addActionListener(Gatherer.g_man);
+
+		  file_new = new JMenuItem(get("File_New"), KeyEvent.VK_N);
+		  file_new.addActionListener(Gatherer.g_man);
+
+		  file_open = new JMenuItem(get("File_Open"), KeyEvent.VK_O);
+		  file_open.addActionListener(Gatherer.g_man);
+
+		  file_options = new JMenuItem(get("File_Options"), KeyEvent.VK_P);
+		  file_options.addActionListener(Gatherer.g_man);	  
+
+		  file_save = new JMenuItem(get("File_Save"), KeyEvent.VK_S);
+		  file_save.addActionListener(Gatherer.g_man);
+		  file_save.setEnabled(false);
+
+		  file_save_as = new JMenuItem(get("File_Save_As"), KeyEvent.VK_A);
+		  file_save_as.addActionListener(Gatherer.g_man);
+		  file_save_as.setEnabled(false);		  
+
+		  // Layout file menu
+		  file.add(file_new);
+		  file.add(file_open);
+		  file.add(file_save);
+		  //file.add(file_save_as);
+		  file.add(file_close);
+		  //file.add(new JSeparator());
+		  //file.add(file_delete);
+		  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(get("Edit"));
+		  edit.setMnemonic(KeyEvent.VK_E);
+		  this.add(edit);
+
+		  edit_copy = new JMenuItem(get("Edit_Copy") + " (ctrl-c)", KeyEvent.VK_C);
+		  edit_copy.addActionListener(Gatherer.g_man);
+		  
+		  edit_cut = new JMenuItem(get("Edit_Cut") + " (ctrl-x)", KeyEvent.VK_X);
+		  edit_cut.addActionListener(Gatherer.g_man);
+
+		  edit_paste = new JMenuItem(get("Edit_Paste") + " (ctrl-v)", KeyEvent.VK_V);
+		  edit_paste.addActionListener(Gatherer.g_man);
+
+		  edit_undo = new JMenuItem(get("Edit_Undo"), KeyEvent.VK_U);
+		  edit_undo.setEnabled(false);
+
+		  edit_redo = new JMenuItem(get("Edit_Redo"), KeyEvent.VK_D);
+		  edit_redo.setEnabled(false);
+
+		  edit_search = new JMenuItem(get("Edit_Search"), KeyEvent.VK_S);
+		  edit_search.addActionListener(Gatherer.g_man);
+
+		  edit_replace = new JMenuItem(get("Edit_Replace"), KeyEvent.VK_R);
+		  edit_replace.addActionListener(Gatherer.g_man);
+
+		  edit.add(edit_copy);
+		  edit.add(edit_cut);
+		  edit.add(edit_paste);
+		  //edit.add(new JSeparator());
+		  //edit.add(edit_undo);
+		  //edit.add(edit_redo);
+		  edit.add(new JSeparator());
+		  edit.add(edit_search);
+		  edit.add(edit_replace);
+
+		  // Metadata menu
+		  metadata = new JMenu(get("Metadata"));
+		  metadata.setEnabled(false);
+		  metadata.setMnemonic(KeyEvent.VK_M);
+
+		  metadata_add = new JMenuItem(get("Metadata_Add"), KeyEvent.VK_A);
+		  metadata_add.addActionListener(Gatherer.g_man);
+
+		  metadata_edit = new JMenuItem(get("Metadata_Edit"), KeyEvent.VK_E);
+		  metadata_edit.addActionListener(Gatherer.g_man);
+
+		  metadata_export = new JMenuItem(get("Metadata_Export"), KeyEvent.VK_X);
+		  metadata_export.addActionListener(Gatherer.g_man);
+
+		  metadata_view = new JMenuItem(get("Metadata_View") + " " + get("FileActions.No_Selection"), KeyEvent.VK_V);
+		  metadata_view.addActionListener(Gatherer.g_man);			
+
+		  metadata.add(metadata_add);
+		  metadata.add(metadata_edit);
+		  metadata.add(metadata_export);
+		  metadata.add(metadata_view);
+		  this.add(metadata);
+
+			// Tools menu
+		  tools = new JMenu(get("Tools"));
+
+		  tools_log = new JMenuItem(get("Tools_Log"), KeyEvent.VK_L);
+		  tools_log.addActionListener(Gatherer.g_man);
+
+		  tools_size = new JMenuItem("Calculate Record Size", KeyEvent.VK_S);
+		  tools_size.addActionListener(Gatherer.g_man);
+
+		  tools.add(tools_log);
+		  tools.add(tools_size);
+		  //this.add(tools);
+
+		  // Help menu
+		  help = new JMenu(get("Help"));
+		  //help.addMenuListener(menu_listener);
+		  help.setIcon(Utility.HELP_ICON);
+
+		  help_about = new JMenuItem(get("Help_About"));
+		  help_about.addActionListener(Gatherer.g_man);
+
+		  help_browse = new JMenuItem(get("GUI.Browser"), Utility.BLANK_ICON);
+		  help_browse.addActionListener(Gatherer.g_man);
+
+		  help_build = new JMenuItem(get("GUI.Create"), Utility.BLANK_ICON);
+		  help_build.addActionListener(Gatherer.g_man);
+
+		  help_collect = new JMenuItem(get("GUI.Collection"), Utility.BLANK_ICON);
+		  help_collect.addActionListener(Gatherer.g_man);
+
+		  help_design = new JMenuItem(get("GUI.Build"), Utility.BLANK_ICON);
+		  help_design.addActionListener(Gatherer.g_man);
+
+		  help_export = new JMenuItem(get("GUI.Export"), Utility.BLANK_ICON);
+		  help_export.addActionListener(Gatherer.g_man);
+
+		  help_general = new JMenuItem(get("Source.General"));
+		  help_general.addActionListener(Gatherer.g_man);
+
+		  help_metaedit = new JMenuItem(get("GUI.MetaEdit"), Utility.BLANK_ICON);
+		  help_metaedit.addActionListener(Gatherer.g_man);
+
+		  help_mirror = new JMenuItem(get("GUI.Mirroring"), Utility.BLANK_ICON);
+		  help_mirror.addActionListener(Gatherer.g_man);
+
+		  help_preview = new JMenuItem(get("GUI.Preview"), Utility.BLANK_ICON);
+		  help_preview.addActionListener(Gatherer.g_man);
+
+		  // Layout help
+		  help.add(help_general);
+		  help.add(new JSeparator());
+		  if(Gatherer.config.get("workflow.browse", true)) {
+				help.add(help_browse);
+		  }
+		  if(Gatherer.config.get("workflow.mirror", true)) {
+				help.add(help_mirror);
+		  }
+		  if(Gatherer.config.get("workflow.gather", true)) {
+				help.add(help_collect);
+		  }
+		  if(Gatherer.config.get("workflow.enrich", true)) {
+				help.add(help_metaedit);
+		  }
+		  if(Gatherer.config.get("workflow.design", true)) {
+				help.add(help_design);
+		  }
+		  if(Gatherer.config.get("workflow.export", true)) {
+				help.add(help_export);
+		  }
+		  if(Gatherer.config.get("workflow.create", true)) {
+				help.add(help_build);
+		  }
+		  if(Gatherer.config.get("workflow.preview", true)) {
+				help.add(help_preview);
+		  }
+		  help.add(new JSeparator());
+		  help.add(help_about);
+		  this.add(Box.createHorizontalGlue());
+		  this.add(help);
+	 }
+
+	 public void collectionChanged(boolean ready) {
+		  file_close.setEnabled(ready);
+		  file_save.setEnabled(ready);
+		  file_save_as.setEnabled(ready);
+		  metadata.setEnabled(ready);
+		  tools.setEnabled(ready);
+		  if(ready) {
+				Gatherer.c_man.undo.registerRedoSource(edit_redo);
+				Gatherer.c_man.undo.registerUndoSource(edit_undo);
+		  }
+	 }
+
+	 public void setMetaAuditSuffix(String metaaudit_suffix) {
+		  ///ystem.err.println("Set metadata view suffix: " + metaaudit_suffix);
+		  metadata_view.setText(get("Menu.Metadata_View") + " " + metaaudit_suffix);
+	 }
+
+	 /** Set the enabled state of one of the help menu items, based on its 'tabs' current state. Note that this method should only be called from the AWTEvent thread. */
+	 public void tabEnabled(int tab_index, boolean state) {
+		  JMenuItem selected = help.getItem(tab_index + 2); // Remember general and separator items
+		  selected.setEnabled(state);
+	 }
+
+	 /** 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(Utility.BLANK_ICON);
+				}
+		  }
+		  current_tab = tab_index + 2;
+		  selected = help.getItem(current_tab);
+		  if(selected != null) {
+				selected.setIcon(Utility.HELP_ICON);
+		  }
+		  selected = null;
+	 }
+	 
+	 /** Retrieves a key from the Dictionary, using no extra arguments.
+	  * @param key A String which maps to a certain phrase from the Dictionary.
+	  * @return The String the matches the key or an error String if no match
+	  * found.
+	  */
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+
+	 /** Retrieves a key from the Dictionary, providing extra arguments to
+	  * be inserted using a String array.
+	  * @param key A String which maps to a certain phrase from the Dictionary.
+	  * @param args A String array containing further arguments (such as
+	  * formatting instructions and variable values) to be taken into account
+	  * when Dictionary creates the return String.
+	  * @return The String the matches the key or an error String if no match
+	  * found.
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf('.') == -1) {
+				key = "Menu." + key;
+		  }
+		  return Gatherer.dictionary.get(key, args);
+	 }
+
+	 private class NonFocusMenu
+		  extends JMenu {
+        public NonFocusMenu(String name) {
+				super(name);
+            setFocusPainted(false);
+        }
+        
+        public boolean isFocusable(){
+            return false;
+        }
+        
+        public void requestFocus(){
+		  }
+
+        public boolean requestFocus(boolean t){
+				return false;
+		  }
+
+		  public void setFocusable(boolean f) {
+		  }
+	 }
+
+	 private class NonFocusMenuItem
+		  extends JMenuItem {
+        public NonFocusMenuItem(String name, int key) {
+				super(name, key);
+            setFocusPainted(false);
+        }
+        
+        public boolean isFocusable(){
+            return false;
+        }
+        
+        public void requestFocus(){
+		  }
+
+        public boolean requestFocus(boolean t){
+				return false;
+		  }
+
+		  public void setFocusable(boolean f) {
+		  }
+		  
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/MetaEditPane.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/MetaEditPane.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/MetaEditPane.java	(revision 13666)
@@ -0,0 +1,824 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+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 javax.swing.table.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.file.FileOpenActionListener;
+import org.greenstone.gatherer.gui.Filter;
+import org.greenstone.gatherer.gui.GComboBox;
+import org.greenstone.gatherer.gui.MetaEditPrompt;
+import org.greenstone.gatherer.gui.WarningDialog;
+import org.greenstone.gatherer.gui.table.GTableModel;
+import org.greenstone.gatherer.gui.table.TableCellRenderer;
+import org.greenstone.gatherer.gui.tree.DragTree;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.Metadata;
+import org.greenstone.gatherer.msm.MSMEvent;
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.DragGroup;
+import org.greenstone.gatherer.util.TreeSynchronizer;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.XORToggleButtonGroup;
+import org.greenstone.gatherer.valuetree.GValueTree;
+import org.greenstone.gatherer.valuetree.GValueModel;
+import org.w3c.dom.Element;
+/** Provides a view of controls for the editing of metadata. It makes use of several other important components such as a GTree, GTable and GValueTree. While much of the gui content is left to these components, the MetaEditPane is resposible for actioning metadata edit requests, listing for mouse clicks within its scope and other data functionality (such as providing a list of the selected files).
+* @author John Thompson, Greenstone Digital Libraries, University of Waikato
+* @version 2.3b
+*/
+public class MetaEditPane
+	extends JPanel
+	implements ActionListener, ListSelectionListener, TreeModelListener, TreeSelectionListener {
+	/** <i>true</i> if the selection has changed since the last time it was asked for, <i>false</i> otherwise. */
+	public boolean has_changed = false;
+	/** The GValueTree graphically shows the available metadata that has been previously assigned, and provides controls for adding, updating and removing metadata, depending on the users selections in the other important components. */
+	public GValueTree tree = null;
+	 /** If only files are selected, then show folder is not available. */
+	 private boolean show_folder_enabled = false;
+	/** The layout manager used to display either the GTable (when records are selected) or a placeholder panel with the immortal words 'No Record Selected'. */
+	private CardLayout card_layout = null;
+	/** The layout manager used to display either the GValueTree (when records are selected) or a placeholder panel with the immortal words 'No Record Selected'. */
+	private CardLayout card_layout2 = null;
+	/** Used to dynamically filter the collection tree at user request. Note that this is synchronized with the collection tree filter in the Gather view. */
+	private Filter filter = null;
+	/** The data model behind the GTable, to which we hold a reference for convenient access. */
+	private GTableModel model = null;
+	/** The currently reported selection. Note that this may actually be incorrect, but if so the changed flag will be set, and the selection will be updated the next time it is needed. */
+	private FileNode records[] = null;
+	/** Records which of the three GTable views is currently being shown, so we can determine what view to change to next (as they cycle). */
+	private int current_table_view;
+	/** The mode is determined by the metadata edit action choosen. */
+	private int mode;
+	/** The button, which when clicked, adds metadata to the selected records. */
+	private JButton add;
+	/** The button, which when clicked, removes the selected metadata from the selected records. */
+	private JButton remove;
+	/** The button, which when clicked, changes the currently shown GTable view. */
+	private JButton table_view;
+	/** The button, which when clicked, updates the selected metadata from the selected records. */
+	private JButton update;
+	/** The label at the top of the collection tree, which shows the collection name. */
+	private JLabel collection_label;
+	/** The panel in which the metadata value card layout resides. */
+	private JPanel control_pane;
+	/** The panel in which the metadata table card layout resides. */
+	private JPanel table_card_pane;
+	/** The panel the table is added to. */
+	private JPanel table_pane;
+	 /** An icon showing the current state of the table build. */
+	 private JProgressBar activity_bar;
+	/** The splitpane dividing the collection tree and the metadata based controls. */
+	private JSplitPane external_split;
+	/** Divides the metadata table and the value tree controls. */
+	private JSplitPane main_split_pane;
+	/** A reference to the metadata table, via its superclass. */
+	private JTable table;
+	/** The label shown at the top of the metadata table detailing the current selection statistics. */
+	private JTextField table_label;
+	 /** The button to control whether assigned metadata is shown. */
+	 private JToggleButton assigned_metadata_view;
+	 /** The button to control whether unassigned metadata is shown. */
+	 private JToggleButton unassigned_metadata_view;
+	/** A reference to the collection tree. */
+	public DragTree collection_tree;
+	/** The currently selected metadata determined by listening to every second list selection event from the metadata table. */
+	private Metadata selected_metadata;
+	/** Listens for right clicks over the collection tree. */
+	private RightButtonListener right_button_listener = null;
+	/** A temporary storage array from Strings passed to the dictionary to be inserted in the phrase returned. */
+	private String args[];
+	/** Provide synchronization between the collection trees in this view and the collection pane view. */
+	private TreeSynchronizer tree_sync = null;
+
+ 	static private Dimension CONTROL_SIZE = new Dimension(560, 240);
+	 static private Dimension LABEL_SIZE = new Dimension(75, 25);
+	static private Dimension MINIMUM_SIZE = new Dimension(100, 100);
+	static private Dimension TABLE_SIZE = new Dimension(560, 25);
+	static private Dimension TREE_SIZE = new Dimension(250, 500);
+	/** An element of the Mode type enumeration, indicating we are adding metadata (ie no metadata rows are selected in the metadata table). */
+	static private int ADD = 0;
+	/** An element of the Mode type enumeration, indicating we are editing existing metadata (ie some row is selected in the metadata table). */
+	static private int EDIT = 1;
+	/** The name of the panel containing the metadata table. */
+	static final private String CARD_ONE  = "Card One";
+	/** The name of the panel containing the placeholder for the metadata table. */
+	static final private String CARD_ZERO = "Card Zero";
+	/** The name of the panel containing the placeholder for the value tree. */
+	static final private String TOOLS_OFF = "Tools Off";
+	/** The name of the panel containing the value tree. */
+	static final private String TOOLS_ON  = "Tools On";
+	/** Constructor.
+	* @param tree_sync The <strong>TreeSynchronizer</strong> to be used on the collection tree.
+	* @see org.greenstone.gatherer.Configuration
+	* @see org.greenstone.gatherer.gui.table.GTable
+	* @see org.greenstone.gatherer.valuetree.GValueTree
+	*/
+	public MetaEditPane(TreeSynchronizer tree_sync) {
+		  this.current_table_view = GTableModel.SHOW_FILE;
+		  this.tree = null;
+		  this.tree_sync = tree_sync;
+
+		  add = new JButton(get("Add"));
+		  add.addActionListener(this);
+		  add.setEnabled(false);
+		  add.setMnemonic(KeyEvent.VK_A);
+
+		  update = new JButton(get("Update"));
+		  update.addActionListener(this);
+		  update.setEnabled(false);
+		  update.setMnemonic(KeyEvent.VK_U);
+
+		  remove = new JButton(get("Remove"));
+		  remove.addActionListener(this);
+		  remove.setEnabled(false);
+		  remove.setMnemonic(KeyEvent.VK_R);
+
+		  tree = new GValueTree(this, CONTROL_SIZE.width, CONTROL_SIZE.height, add, update, remove);
+		  tree.setRootVisible(false);
+	 }
+	/** Called whenever an action occurs on one of our registered buttons.
+	* @param event An <strong>ActionEvent</strong> containing information about the event.
+	* @see org.greenstone.gatherer.collection.CollectionManager
+	* @see org.greenstone.gatherer.gui.table.GTableModel
+	* @see org.greenstone.gatherer.msm.ElementWrapper
+	* @see org.greenstone.gatherer.msm.MetadataSetManager
+	* @see org.greenstone.gatherer.msm.MSMEvent
+	* @see org.greenstone.gatherer.valuetree.GValueTree
+	*/
+    public void actionPerformed(ActionEvent event) {
+		  Object esrc = event.getSource();
+		  if(esrc == add) {
+				// Check the new metadata is valid
+				ElementWrapper element = tree.getSelectedMetadataElement();
+				String value = tree.getSelectedValue();
+				if(records != null && element != null && value != null) {
+					 // Check the records, and if they are folders then display the warning.
+					 if(!records[0].isLeaf()) {
+						  WarningDialog dialog = new WarningDialog("warning.DirectoryLevelMetadata", true);
+						  if(dialog.display() == JOptionPane.OK_OPTION) {
+								Gatherer.c_man.getCollection().msm.addMetadata(System.currentTimeMillis(), records, element, value);
+						  }
+						  dialog.dispose();
+						  dialog = null;
+					 }
+					 else {
+						  Gatherer.c_man.getCollection().msm.addMetadata(System.currentTimeMillis(), records, element, value);
+					 }
+				}
+				// Slight hack. Used to do this automatically if a value was added to the GValueModel, however this caused a Garbage Collection loop with the latest incarnation of FileQueue, so I've removed it and I'll manually call the value tree update here.
+				tree.valueChanged(new MSMEvent(this, 0, element, null, null));
+				// Else bad metadata.
+		  }
+		  else if(esrc == update) {
+				// You can only update if there is a selected_metadata and
+				// you have valid values in all fields.
+				ElementWrapper element = tree.getSelectedMetadataElement();
+				String value = tree.getSelectedValue();
+				if(selected_metadata != null && records != null && element != null && value != null) {
+					 // If the selected_metadata is at directory level then this is actually an add with Replace set.
+					 if(selected_metadata.isFileLevel()) {
+						  selected_metadata = Gatherer.c_man.getCollection().msm.updateMetadata(System.currentTimeMillis(), selected_metadata, records, value, -1);
+					 }
+					 else {
+						  Gatherer.c_man.getCollection().msm.addMetadata(System.currentTimeMillis(), records, element, value, MetaEditPrompt.OVERWRITE_ALL);
+					 }
+				}
+				// Slight hack. Used to do this automatically if a value was added to the GValueModel, however this caused a Garbage Collection loop with the latest incarnation of FileQueue, so I've removed it and I'll manually call the value tree update here.
+				tree.valueChanged(new MSMEvent(this, 0, element, null, null));
+		  }
+		  else if(esrc == remove) {
+				if(selected_metadata != null && records != null) {
+					 Gatherer.c_man.getCollection().msm.removeMetadata(System.currentTimeMillis(), selected_metadata, records);
+				}
+		  }
+		  else if(esrc == assigned_metadata_view || esrc == unassigned_metadata_view) {
+				model.changeView();
+		  }
+		  validateControls();
+	 }
+	/** 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.
+	* @see org.greenstone.gatherer.gui.table.GTableModel
+	*/
+	 public void afterDisplay() {
+		  external_split.setDividerLocation(0.3);
+		  if(table != null) {
+				Dimension table_size = table.getPreferredSize();
+				TableColumnModel column_model = table.getColumnModel();
+
+				TableColumn inherited_column = column_model.getColumn(0);
+				inherited_column.setPreferredWidth(20);
+				inherited_column.setCellRenderer(new TableCellRenderer(model));
+
+				TableColumn element_column = column_model.getColumn(1);
+				element_column.setPreferredWidth(table_size.width / 4);
+				element_column.setCellRenderer(new TableCellRenderer(model));
+
+				TableColumn value_column = column_model.getColumn(2);
+				value_column.setPreferredWidth(((3 * table_size.width) / 4) - 15);
+				value_column.setCellRenderer(new TableCellRenderer(model));
+		  }
+		  model.fireTableDataChanged();
+	 }
+	/** Called whenever a significant change has occured in the state of the currently loaded collection.
+	* @param ready <i>true</i> if there is a collection currently ready to be editing, <i>false</i> otherwise.
+	* @see org.greenstone.gatherer.collection.CollectionManager
+	* @see org.greenstone.gatherer.collection.CollectionModel
+	* @see org.greenstone.gatherer.tree.GTree
+	* @see org.greenstone.gatherer.util.TreeSynchronizer
+	*/
+	 public void collectionChanged(boolean ready) {
+	     if(ready) {
+				TreeModel collection_model = Gatherer.c_man.getRecordSet();
+				args = new String[1];
+				args[0] = Gatherer.c_man.getCollection().getName();
+				collection_label.setText(get("Collection.Collection", args));
+				// Update label coloring.
+				collection_label.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
+				collection_label.setForeground(Gatherer.config.getColor("coloring.collection_heading_foreground", false));
+				collection_tree.setModel(collection_model);
+				// Update tree coloring.
+				collection_tree.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				collection_tree.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+				// Register our msm dependant components (or correctly their models) with msm.
+				if(model != null) {
+					 Gatherer.c_man.getCollection().msm.addMSMListener(model);
+				}
+				tree.setElementModel(Gatherer.c_man.getCollection().msm.getElementModel());
+	     }
+		  else {
+				collection_label.setText(get("Collection.No_Collection"));
+				collection_label.setBackground(Color.lightGray);
+				collection_label.setForeground(Color.black);
+				collection_tree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode(get("Collection.No_Collection"))));
+		  }
+		  collection_tree.setRootVisible(ready);
+
+		  filter.setEnabled(ready);
+		  // Ensure that this collection tree view is synchronized with any others.
+		  tree_sync.add(collection_tree);
+	 }
+	/** Used to create, connect and layout the components to be shown on this control panel.
+	* @see org.greenstone.gatherer.Gatherer
+	* @see org.greenstone.gatherer.collection.CollectionManager
+	* @see org.greenstone.gatherer.collection.CollectionModel
+	* @see org.greenstone.gatherer.file.FileOpenActionListener
+	* @see org.greenstone.gatherer.gui.Filter
+	* @see org.greenstone.gatherer.gui.GComboBox
+	* @see org.greenstone.gatherer.gui.table.GTableModel
+	* @see org.greenstone.gatherer.tree.GTree
+	* @see org.greenstone.gatherer.tree.GTreeModel
+	* @see org.greenstone.gatherer.valuetree.GValueTree
+	*/
+	 public void display() {
+		  right_button_listener = new RightButtonListener();
+		  // Creation
+		  JPanel collection_pane = new JPanel(new BorderLayout());
+		  collection_pane.setMinimumSize(MINIMUM_SIZE);
+		  collection_pane.setPreferredSize(TREE_SIZE);
+
+		  external_split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
+
+		  ///atherer.println("\tCreating collection_label");
+		  args = new String[1];
+		  args[0] = get("Collection.No_Collection");
+		  collection_label = new JLabel(get("Collection.Collection"));
+		  collection_label.setOpaque(true);
+
+
+		  DragGroup group = new DragGroup();
+		  TreeModel collection_model = Gatherer.c_man.getRecordSet();
+		  if(collection_model != null) {
+				collection_tree = new DragTree("Collection", collection_model, null);
+				collection_model.addTreeModelListener(this);
+		  }
+		  else {
+				collection_tree = new DragTree("Collection", null);
+		  }
+		  group.add(collection_tree);
+		  collection_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
+		  collection_tree.putClientProperty("JTree.lineStyle", "Angled");
+		  collection_tree.addMouseListener(Gatherer.g_man.foa_listener);
+		  collection_tree.addMouseListener(right_button_listener);
+		  collection_tree.addTreeSelectionListener(this);
+		  collection_tree.addTreeExpansionListener(Gatherer.g_man.foa_listener);
+		  collection_tree.setLargeModel(true);
+		  collection_tree.setRootVisible(true);
+
+		  JScrollPane collection_scroll = new JScrollPane(collection_tree);
+
+		  filter = Gatherer.g_man.getFilter(collection_tree);
+		  filter.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
+		  // Change the default colours of this filters combobox.
+		  GComboBox fcb = filter.getComboBox();
+		  fcb.setBackgroundNonSelectionColor(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  fcb.setTextNonSelectionColor(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+		  fcb.setBackgroundSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
+		  fcb.setTextSelectionColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
+		  fcb = null;
+
+		  // Connection
+
+		  // 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);
+		  collection_pane.add(collection_scroll, BorderLayout.CENTER);
+		  collection_pane.add(filter, BorderLayout.SOUTH);
+
+		  // Main pane
+		  //main_pane = new JPanel(new BorderLayout());
+		  //main_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+
+		  main_split_pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
+		  main_split_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		  main_split_pane.setDividerSize(8);
+
+		  // Thumbnail - Currently disabled.
+		  // At least until I figure out how to render thumbnails off screen,
+		  // which possibly may happen with the discovery of CalpaHTML.
+		  /*
+		  thumbnail_pane = new JPanel(new BorderLayout());
+
+		  gatherer.debug("\tCreating thumbnail_label");
+		  thumbnail_label = new JLabel(get("Thumbnail"));
+		  thumbnail_label.setHorizontalAlignment(JLabel.CENTER);
+
+		  gatherer.debug("\tCreating thumbnail_view_pane");
+		  thumbnail_view_pane = new JPanel(new FlowLayout(FlowLayout.CENTER));
+		  thumbnail_scroll = new JScrollPane(thumbnail_view_pane);
+
+		  thumbnail_pane.add(thumbnail_label, BorderLayout.NORTH);
+		  thumbnail_pane.add(thumbnail_scroll, BorderLayout.CENTER);
+		  */
+
+		  // Metadata Table. In order to achieve what Ian envisions I'm going
+		  // to have to do a tricky. The table itself will sit in a stacked
+		  // CardLayout. Card zero will be a see-through JPanel with a message
+		  // smack bang in the center, something like "No Metadata". If any
+		  // page of the table would appear to have no metadata this card will
+		  // be swapped to the front.
+
+		  table_pane = new JPanel();
+		  table_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+
+		  JPanel table_title_pane = new JPanel();
+
+		  ///atherer.println("\tCreating metadata_label");
+		  table_label = new JTextField(get("No_File"));
+		  table_label.setBackground(Color.white);
+		  table_label.setEditable(false);
+
+		  activity_bar = new JProgressBar();
+		  activity_bar.setPreferredSize(LABEL_SIZE);
+		  activity_bar.setString(get("Ready"));
+		  activity_bar.setStringPainted(true);
+		  activity_bar.setValue(activity_bar.getMaximum());
+
+		  card_layout = new CardLayout();
+
+		  table_card_pane = new JPanel();
+
+		  JPanel table_pane_zero = new JPanel();
+		  table_pane_zero.setOpaque(false);
+
+		  JLabel no_metadata_message = new JLabel(get("No_Metadata"));
+		  no_metadata_message.setHorizontalAlignment(JLabel.CENTER);
+		  no_metadata_message.setOpaque(false);
+		  no_metadata_message.setVerticalAlignment(JLabel.CENTER);
+
+		  JPanel table_pane_one = new JPanel();
+
+		  JPanel view_pane = new JPanel();
+
+		  JLabel view_label = new JLabel(get("View"));
+		  view_label.setPreferredSize(LABEL_SIZE);
+
+		  JPanel view_button_pane = new JPanel();
+
+		  assigned_metadata_view = new JToggleButton(get("View_Assigned"), Utility.OFF_ICON);
+		  assigned_metadata_view.setSelectedIcon(Utility.ON_ICON);
+		  assigned_metadata_view.setSelected(true);
+		  assigned_metadata_view.addActionListener(this);
+		  unassigned_metadata_view = new JToggleButton(get("View_Unassigned"), Utility.OFF_ICON);
+		  unassigned_metadata_view.setSelectedIcon(Utility.ON_ICON);
+		  unassigned_metadata_view.setSelected(true);
+		  unassigned_metadata_view.addActionListener(this);
+		  XORToggleButtonGroup view_group = new XORToggleButtonGroup();
+		  view_group.add(assigned_metadata_view);
+		  view_group.add(unassigned_metadata_view);
+
+		  ///atherer.println("\tCreating metadata_table");
+		  table = new JTable();
+		  model = new GTableModel(table, assigned_metadata_view, unassigned_metadata_view, activity_bar);
+		  table.setModel(model);
+		  table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+		  table.getSelectionModel().addListSelectionListener(this);
+		  table.setColumnSelectionAllowed(false);
+
+		  JScrollPane table_scroll = new JScrollPane(table);
+		  table_scroll.getViewport().setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  table_scroll.setOpaque(true);
+
+		  // Control pane
+		  ///atherer.println("\tCreating Metadata Controls");
+
+		  control_pane = new JPanel();
+		  control_pane.setBorder(BorderFactory.createLoweredBevelBorder());
+		  control_pane.setMinimumSize(MINIMUM_SIZE);
+		  control_pane.setSize(CONTROL_SIZE);
+		  control_pane.setPreferredSize(CONTROL_SIZE);
+
+		  card_layout2 = new CardLayout();
+
+		  JPanel tools_off_pane = new JPanel();
+
+		  JLabel tools_off_label = new JLabel(get("Tools_Off"));
+		  tools_off_label.setHorizontalAlignment(JLabel.CENTER);
+		  tools_off_label.setOpaque(false);
+		  tools_off_label.setVerticalAlignment(JLabel.CENTER);
+
+		  JPanel tools_on_pane = new JPanel();
+		  tools_on_pane.setMinimumSize(MINIMUM_SIZE);
+		  tools_on_pane.setSize(TABLE_SIZE);
+		  tools_on_pane.setPreferredSize(TABLE_SIZE);
+
+		  // Layout.
+
+		  // Metaedit controls
+		  tools_off_pane.setLayout(new BorderLayout());
+		  tools_off_pane.add(tools_off_label, BorderLayout.CENTER);
+
+		  tools_on_pane.setLayout(new BorderLayout());
+		  tools_on_pane.add(tree, BorderLayout.CENTER);
+
+		  control_pane.setLayout(card_layout2);
+		  control_pane.add(tools_off_pane, TOOLS_OFF);
+		  control_pane.add(tools_on_pane, TOOLS_ON);
+
+		  // Table components
+		  table_title_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+		  table_title_pane.setLayout(new BorderLayout());
+		  //table_title_pane.setLayout(new GridLayout(1,2,5,0));
+		  table_title_pane.add(table_label, BorderLayout.CENTER);
+		  //table_title_pane.add(activity_bar);
+
+		  table_pane_zero.setLayout(new BorderLayout());
+		  table_pane_zero.add(no_metadata_message, BorderLayout.CENTER);
+
+		  table_pane_one.setLayout(new BorderLayout());
+		  table_pane_one.add(table_scroll, BorderLayout.CENTER);
+
+		  table_card_pane.setLayout(card_layout);
+		  table_card_pane.add(table_pane_zero, CARD_ZERO);
+		  table_card_pane.add(table_pane_one, CARD_ONE);
+
+		  view_button_pane.setLayout(new GridLayout(1,2,5,0));
+		  view_button_pane.add(assigned_metadata_view);
+		  view_button_pane.add(unassigned_metadata_view);
+
+		  view_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+		  view_pane.setLayout(new BorderLayout());
+		  view_pane.add(view_label, BorderLayout.WEST);
+		  view_pane.add(view_button_pane, BorderLayout.CENTER);
+
+		  table_pane.setLayout(new BorderLayout());
+		  table_pane.add(table_title_pane, BorderLayout.NORTH);
+		  table_pane.add(table_card_pane, BorderLayout.CENTER);
+		  table_pane.add(view_pane, BorderLayout.SOUTH);
+
+		  //main_split_pane.add(control_pane, JSplitPane.TOP);
+		  //main_split_pane.add(table_pane, JSplitPane.BOTTOM);
+		  main_split_pane.add(table_pane, JSplitPane.TOP);
+		  main_split_pane.add(control_pane, JSplitPane.BOTTOM);
+		  main_split_pane.setDividerLocation(200);
+
+		  external_split.add(collection_pane, JSplitPane.LEFT);//BorderLayout.WEST);
+		  //this.add(main_pane, BorderLayout.CENTER);
+		  external_split.add(main_split_pane, JSplitPane.RIGHT);//BorderLayout.CENTER);
+
+		  this.setLayout(new BorderLayout());
+		  this.add(external_split, BorderLayout.CENTER);
+	 }
+	/** Ensures a certain tree path is expanded, visible and selected within the collection tree.
+	* @param path The <strong>TreePath</strong> to make visible.
+	* @see org.greenstone.gatherer.tree.GTree
+	*/
+	 public void expandPath(TreePath path) {
+		  collection_tree.expandPath(path);
+		  collection_tree.setSelectionPath(path);
+	 }
+	/** Called to inform this control panel that it has just gained focus as an effect of the user clicking on its tab.
+	* @see org.greenstone.gatherer.tree.GTree
+	*/
+	 public void gainFocus() {
+		  // Use this opportunity to update the table model etc.
+		  valueChanged(new TreeSelectionEvent(this, null, false, null, null));
+		  tree.setElementModel(Gatherer.c_man.getCollection().msm.getElementModel());
+	 }
+	 /** Used to determine if this class contains a reference to an existing file record that matches the presumtively new record, and if one is found, returns it. Note that there is no need to search the metadata table model, as any file record that exists there must also exist in the records selection.
+	 * @param new_record The <strong>FileNode</strong> which may or may not be the first occurance of a certain record.
+	 * @return The matching <strong>FileNode</strong> if there is one, or <i>null</i>.
+	 */
+	 public FileNode getAnyExistingRecord(FileNode new_record) {
+		  FileNode match = null;
+		  for(int i = 0; records != null && i < records.length && match == null; i++) {
+				if(records[i].equals(new_record)) {
+					 match = records[i];
+				}
+		  }
+		  return match;
+	 }
+
+	/** Retrieve the currently selected records.
+	* @return A <strong>FileNode[]</strong> containing the current, and up to date, selection.
+	*/
+    public FileNode[] getSelectedNode() {
+		  return records;
+    }
+
+	/** Retrieve the currently selected metadata.
+	* @return The <strong>Metadata</strong> in question.
+	*/
+	public Metadata getSelectedMetadata() {
+		  return selected_metadata;
+	 }
+
+	 public void setSelection(File file) {
+		  collection_tree.setSelection(file);
+	 }
+
+	/** Determine the bounds of the selected metadata within the table, used during search and replace actions.
+	* @param metadata The <strong>Metadata</strong> to search for.
+	*/
+	 public Rectangle setSelectedMetadata(Metadata metadata) {
+		  return model.setSelectedMetadata(metadata);
+	 }
+
+	 public void refreshTrees() {
+		  collection_tree.refresh(null); // Refresh entire tree.
+	 }
+
+	/* Called when nodes have been modified, but the model hasn't changed.
+	* @param event Everything you ever wanted to know about model changes in one tidy <strong>TreeModelEvent</strong> package.
+	*/
+	 public void treeNodesChanged(TreeModelEvent event) {
+		  has_changed = true;
+	 }
+
+	 /* Called when nodes have been added to the model.
+	  * @param event Everything you ever wanted to know about model changes in one tidy <strong>TreeModelEvent</strong> package.
+	  */
+	 public void treeNodesInserted(TreeModelEvent event) {
+		  has_changed = true;
+	 }
+
+	 /* Called when nodes have been removed from the model.
+	  * @param event Everything you ever wanted to know about model changes in one tidy <strong>TreeModelEvent</strong> package.
+	  */
+	 public void treeNodesRemoved(TreeModelEvent event) {
+		  has_changed = true;
+	 }
+
+	 /** Called when nodes have been rearranged within the model.
+	  * @param event Everything you ever wanted to know about model changes in one tidy <strong>TreeModelEvent</strong> package.
+	  */
+	 public void treeStructureChanged(TreeModelEvent event) {
+		  has_changed = true;
+	 }
+	/** Called to ensure that if the tree model has changed in some way, the view has been updated.
+	* @see org.greenstone.gatherer.tree.GTree
+	*/
+	 public void updateTree() {
+		  if(has_changed) {
+				tree.updateUI();
+				has_changed = false;
+		  }
+	 }
+
+	 /** This method enables or diables the various controls based upon the state of the system. This method should be called after every change which could affect the GUI.
+	  */
+	 public void validateControls() {
+		  validateMetadataTable();
+		  // Validate card_layout_2
+		  if(records != null) {
+				card_layout2.show(control_pane, TOOLS_ON);
+		  }
+		  else {
+				card_layout2.show(control_pane, TOOLS_OFF);
+		  }
+
+		  tree.validateControls();
+	 }
+
+	 /** Validate the metadata table area, and if no metadata is available display the no metadata panel. */
+	 public void validateMetadataTable() {
+		  // Validate card_layout
+		  if(records != null && model.getRowCount() > 0) {
+				card_layout.show(table_card_pane, CARD_ONE);
+		  }
+		  else {
+				card_layout.show(table_card_pane, CARD_ZERO);
+		  }
+	 }
+
+	 /** Another in a long list of listeners, this one is called whenever the
+	  * selection within the JTable changes. When it does we load the new data
+	  * and set the selected_metadata if applicable (ie the metadata is non-
+	  * empty).
+	  * @param event The <strong>ListSelectionEvent</strong> which contains all the information about the event that has been fired.
+	  * @see org.greenstone.gatherer.gui.table.GTableModel
+	  * @see org.greenstone.gatherer.valuetree.GValueTree
+	  */
+	 public void valueChanged(ListSelectionEvent event) {
+		  // We have a SINGLE_SELECTION model set so there is at most one
+		  // selection. Get the offending row.
+		  int selected = table.getSelectedRow();
+		  selected_metadata = model.getMetadataAtRow(selected);
+		  if(selected_metadata != null) { // Check something is selected.
+				tree.setCommon(model.isCommon(selected));
+				tree.setFileLevel(selected_metadata.isFileLevel());
+				tree.setSelectedMetadataElement(selected_metadata.getElement());
+				tree.setSelectedValue(selected_metadata.getValue());
+		  }
+	 }
+
+	 /** 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.
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.FileNode
+	  * @see org.greenstone.gatherer.gui.GUIManager
+	  * @see org.greenstone.gatherer.gui.MenuBar
+	  * @see org.greenstone.gatherer.gui.table.GTableModel
+	  * @see org.greenstone.gatherer.msm.MetadataSetManager
+	  * @see org.greenstone.gatherer.tree.GTree
+	  * @see org.greenstone.gatherer.util.ArrayTools
+	  */
+	 public void valueChanged(TreeSelectionEvent event) {
+		  ///ystem.err.print("We just detected a value changed event.");
+		  if(Gatherer.g_man.getSelectedView() == this) {
+				if(collection_tree.getSelectionCount() > 0) {
+					 records = null;
+					 TreePath paths[] = collection_tree.getSelectionPaths();
+					 int files = 0;
+					 int dirs = 0;
+					 ///ystem.err.println("Selected " + paths.length + " files.");
+					 for(int i = 0; i < paths.length; i++) {
+						  FileNode record = (FileNode) paths[i].getLastPathComponent();
+						  records = ArrayTools.add(records, record);
+					 }
+
+					 table_label.setText(Gatherer.g_man.collection_pane.getSelectionDetails());
+					 
+					 // Remove old model from msm
+					 Gatherer.c_man.getCollection().msm.removeMSMListener(model);
+					 // Create new model (which will add itself to msm).
+					 model = new GTableModel(table, assigned_metadata_view, unassigned_metadata_view, activity_bar, records);
+					 table.setModel(model);
+				}
+				else {
+					 ///ystem.err.println("No node selected!");
+					 records = null;
+					 // Remove old model from msm
+					 if(Gatherer.c_man.ready()) {
+						  Gatherer.c_man.getCollection().msm.removeMSMListener(model);
+					 }
+					 // Create new model (which will add itself to msm).
+					 model = new GTableModel(table, assigned_metadata_view, unassigned_metadata_view, activity_bar);
+					 table.setModel(model);
+				}
+				table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
+				if(table != null) {
+					 Dimension table_size = table.getPreferredSize();
+					 TableColumnModel column_model = table.getColumnModel();
+
+					 TableColumn inherited_column = column_model.getColumn(0);
+					 inherited_column.setPreferredWidth(20);
+					 inherited_column.setCellRenderer(new TableCellRenderer(model));
+					 
+					 TableColumn element_column = column_model.getColumn(1);
+					 element_column.setPreferredWidth(TABLE_SIZE.width / 4);
+					 element_column.setCellRenderer(new TableCellRenderer(model));
+					 
+					 TableColumn value_column = column_model.getColumn(2);
+					 value_column.setPreferredWidth(((3 * TABLE_SIZE.width) / 4) - 15);
+					 value_column.setCellRenderer(new TableCellRenderer(model));
+				}
+				validateControls();
+		  }
+	 }
+	/** Retrieve a phrase from the Dictionary based on the given key.
+	* @param key The <strong>String</strong> which maps to the phrase to retrieve.
+	* @return The desired phrase as a <strong>String</strong>, or possibly an error message if no such phrase exists.
+	*/
+	 private String get(String key) {
+	     return get(key, null);
+	 }
+	/** Retrieve a phrase from the Dictionary based on the given key and filled in with the given arguments.
+	* @param key The <strong>String</strong> which maps to the phrase to retrieve.
+	* @param args A <strong>String[]</strong> of arguments to be inserted in the phrase.
+	* @return The desired phrase as a <strong>String</strong>, or possibly an error message if no such phrase exists.
+	* @see org.greenstone.gatherer.Dictionary
+	* @see org.greenstone.gatherer.Gatherer
+	*/
+    private String get(String key, String args[]) {
+		  if(key.indexOf('.') == -1) {
+				key = "MetaEdit." + key;
+		  }
+		  return Gatherer.dictionary.get(key,args);
+    }
+
+	 /** A listener for right mouse button clicks over the collection tree. */
+	 private class RightButtonListener
+		  extends MouseAdapter {
+		/** Called whenever a mouse click occurs (right or left) over a target component.
+		* @param event A <strong>MouseEvent</strong> containing further information about the mouse click action.
+		* @see org.greenstone.gatherer.gui.MetaEditPane.RightButtonMenu
+		*/
+		  public void mouseClicked(MouseEvent event) {
+				if(SwingUtilities.isRightMouseButton(event)) {
+					 new RightButtonMenu(event);
+				}
+		  }
+	 }
+	/** Provides a popup menu to display when a right mouse button click is detected over the collection tree. */
+	 private class RightButtonMenu
+		  extends JPopupMenu
+		  implements ActionListener {
+		/** Constructor.
+		* @param event The <strong>MouseEvent</strong> that triggered the creation of this menu. Used to determine where the menu will be located.
+		*/
+		  public RightButtonMenu(MouseEvent event) {
+				super();
+				// Creation
+				JMenuItem show_metaaudit = new JMenuItem(get("Menu.Metadata_View") + " " + collection_tree.getSelectionDetails(), KeyEvent.VK_V);
+				show_metaaudit.addActionListener(this);
+				add(show_metaaudit);
+				// Display
+				show(collection_tree, event.getX(), event.getY());
+				show_metaaudit = null;
+				args = null;
+
+		  }
+		/** Called whenever a user clicks on the single menu item, view all assigned metadata.
+		* @param event An <strong>ActionEvent</strong> containing further information about the action.
+		* @see org.greenstone.gatherer.Gatherer
+		* @see org.greenstone.gatherer.gui.GUIManager
+		*/
+		  public void actionPerformed(ActionEvent event) {
+				Gatherer.g_man.showMetaAuditBox();
+		  }
+	 }
+
+}
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/MetaEditPrompt.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/MetaEditPrompt.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/MetaEditPrompt.java	(revision 13666)
@@ -0,0 +1,341 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.Configuration;
+/** Displays a dynamic prompt to allow the user to choose how metadata is to be added, updated or removed from target FileNodes. The prompt changes depending on the action requested, the file nodes encountered and the number of file nodes in the selection. */
+public class MetaEditPrompt
+	 extends JDialog 
+	 implements ActionListener {
+
+	 private boolean multiple_selection = false;
+
+	 private int type;
+	 private int value;
+
+	 private JButton accumulate_b;
+	 private JButton accumulate_all_b;
+	 private JButton cancel_b;
+	 private JButton skip_b;
+	 private JButton overwrite_b;
+	 private JButton overwrite_all_b;
+	 private JButton remove_b;
+	 private JButton remove_all_b;
+	 private JButton update_b;
+	 private JButton update_all_b;
+
+	 private JLabel title;
+
+	 private JTextArea text;
+
+	 private JPanel button_row;
+	 private JPanel content_pane;
+
+	 static private Dimension SIZE    = new Dimension(400, 280);
+
+	 // Prompt Types
+	 static public int ADD_PROMPT      =  0;
+	 static public int REMOVE_PROMPT   =  1;
+	 static public int UPDATE_PROMPT   =  2;
+
+	 // Generic prompt values.
+	 static public int CONFIRM         =  0;
+	 static public int CANCEL          =  1;
+	 static public int SKIP            =  2;
+
+	 // Values for the different add action prompts.
+	 static public int ACCUMULATE      =  3;
+	 static public int ACCUMULATE_ALL  =  4;
+	 static public int OVERWRITE       =  5;
+	 static public int OVERWRITE_ALL   =  6;
+
+	 // Values for the different update action prompts.
+	 static public int UPDATE          =  7;
+	 static public int UPDATE_ALL      =  8;
+	 static public int UPDATE_ONCE     =  9;
+
+	 // Values for the different remove action prompts.
+	 static public int REMOVE          = 10;
+	 static public int REMOVE_ALL      = 11;
+
+	 public MetaEditPrompt(int type, boolean multiple_selection) {
+		  super(Gatherer.g_man); // Needed for modal response!
+		  this.multiple_selection = multiple_selection;
+		  this.setFont(Gatherer.config.getFont("general.font", false));
+		  this.setModal(true);
+		  this.setSize(SIZE);
+		  this.type = type;
+		  if(type == ADD_PROMPT) {
+				this.setTitle(get("Add_Title"));
+				title = new JLabel(get("Add_Title"));
+		  }
+		  else if(type == REMOVE_PROMPT) {
+				this.setTitle(get("Remove_Title"));
+				title = new JLabel(get("Remove_Title"));
+		  }
+		  else {
+				this.setTitle(get("Update_Title"));
+				title = new JLabel(get("Update_Title"));
+		  }
+		  title.setOpaque(false);
+
+		  content_pane = (JPanel)this.getContentPane();
+		  content_pane.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
+		  content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+
+		  // Set up some preset components.
+		  text = new JTextArea();
+		  text.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  text.setEditable(false);
+
+		  button_row = new JPanel();
+		  button_row.setOpaque(false);
+
+		  accumulate_b = new JButton(get("Accumulate"));
+		  accumulate_b.addActionListener(this);
+		  accumulate_b.setBackground(Gatherer.config.getColor("coloring.button_background", false));
+		  accumulate_b.setMnemonic(KeyEvent.VK_A);
+
+		  accumulate_all_b = new JButton(get("Accumulate_All"));
+		  accumulate_all_b.addActionListener(this);
+		  accumulate_all_b.setBackground(Gatherer.config.getColor("coloring.button_background", false));
+		  accumulate_all_b.setMnemonic(KeyEvent.VK_D);
+
+		  cancel_b = new JButton(get("Cancel"));
+		  cancel_b.addActionListener(this);
+		  cancel_b.setBackground(Gatherer.config.getColor("coloring.button_background", false));
+		  cancel_b.setMnemonic(KeyEvent.VK_C);
+
+		  skip_b = new JButton(get("Skip"));
+		  skip_b.addActionListener(this);
+		  skip_b.setBackground(Gatherer.config.getColor("coloring.button_background", false));
+		  skip_b.setMnemonic(KeyEvent.VK_S);
+
+		  overwrite_b = new JButton(get("Overwrite"));
+		  overwrite_b.addActionListener(this);
+		  overwrite_b.setBackground(Gatherer.config.getColor("coloring.button_background", false));
+		  overwrite_b.setMnemonic(KeyEvent.VK_R);
+
+		  overwrite_all_b = new JButton(get("Overwrite_All"));
+		  overwrite_all_b.addActionListener(this);
+		  overwrite_all_b.setBackground(Gatherer.config.getColor("coloring.button_background", false));
+		  overwrite_all_b.setMnemonic(KeyEvent.VK_E);
+
+		  remove_b = new JButton(get("Remove"));
+		  remove_b.addActionListener(this);
+		  remove_b.setBackground(Gatherer.config.getColor("coloring.button_background", false));
+		  remove_b.setMnemonic(KeyEvent.VK_R);
+
+		  remove_all_b = new JButton(get("Remove_All"));
+		  remove_all_b.addActionListener(this);
+		  remove_all_b.setBackground(Gatherer.config.getColor("coloring.button_background", false));
+		  remove_all_b.setMnemonic(KeyEvent.VK_A);
+
+		  update_b = new JButton(get("Update"));
+		  update_b.addActionListener(this);
+		  update_b.setBackground(Gatherer.config.getColor("coloring.button_background", false));
+		  update_b.setMnemonic(KeyEvent.VK_U);
+
+		  update_all_b = new JButton(get("Update_All"));
+		  update_all_b.addActionListener(this);
+		  update_all_b.setBackground(Gatherer.config.getColor("coloring.button_background", false));
+		  update_all_b.setMnemonic(KeyEvent.VK_A);
+	 }
+
+	 public void actionPerformed(ActionEvent event) {
+		  Object esrc = event.getSource();
+		  if(esrc == accumulate_b) {
+				value = ACCUMULATE;
+		  }
+		  else if(esrc == accumulate_all_b) {
+				value = ACCUMULATE_ALL;
+		  }
+		  else if(esrc == cancel_b) {
+				value = CANCEL;
+		  }
+		  else if(esrc == skip_b) {
+				value = SKIP;
+		  }		  
+		  else if(esrc == overwrite_b) {
+				value = OVERWRITE;
+		  }
+		  else if(esrc == overwrite_all_b) {
+				value = OVERWRITE_ALL;
+		  }
+		  else if(esrc == remove_b) {
+				value = REMOVE;
+		  }
+		  else if(esrc == remove_all_b) {
+				value = REMOVE_ALL;
+		  }
+		  else if(esrc == update_b) {
+				value = UPDATE;
+		  }
+		  else if(esrc == update_all_b) {
+				value = UPDATE_ALL;
+		  }
+		  this.dispose();
+	 }
+
+	 public int display(String f, String k, String v) {
+		  String args[] = new String[1];
+
+		  content_pane.setLayout(new BorderLayout());
+
+		  content_pane.add(title, BorderLayout.NORTH);
+
+		  JPanel middle_pane = new JPanel(new BorderLayout());
+		  middle_pane.setOpaque(false);
+		  middle_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createLoweredBevelBorder()));
+
+		  args[0] = f;
+		  text.append(get("File", args));
+		  text.append("\n");
+		  args[0] = k;
+		  text.append(get("Key", args));
+		  text.append("\n");
+		  args[0] = v;
+		  text.append(get("Value", args));
+		  text.append("\n");
+		  
+		  button_row.setLayout(new GridLayout(4,1,2,2));
+
+		  // Add the components
+		  middle_pane.add(new JScrollPane(text), BorderLayout.CENTER);
+
+		  button_row.add(remove_b);
+		  if(multiple_selection) {
+				button_row.add(remove_all_b);
+		  }
+		  else {
+				button_row.add(new JPanel());
+		  }
+		  button_row.add(skip_b);
+		  button_row.add(cancel_b);
+
+		  content_pane.add(title, BorderLayout.NORTH);
+		  content_pane.add(middle_pane, BorderLayout.CENTER);
+		  content_pane.add(button_row, BorderLayout.SOUTH);
+
+		  text.setCaretPosition(0);
+
+		  Rectangle frame_bounds = Gatherer.g_man.getBounds();
+		  this.setLocation(frame_bounds.x + ((frame_bounds.width - SIZE.width) / 2), frame_bounds.y + ((frame_bounds.height - SIZE.height) / 2));
+		  show();
+		  return value;
+	 }
+
+	 public int display(String f, String k, String o_v, String n_v) {
+		  String args[] = new String[1];
+		  
+		  content_pane.setLayout(new BorderLayout());
+		  
+		  content_pane.add(title, BorderLayout.NORTH);
+		  
+		  JPanel middle_pane = new JPanel(new BorderLayout());
+		  middle_pane.setOpaque(false);
+		  middle_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createLoweredBevelBorder()));
+		  		  
+		  args[0] = f;
+		  text.append(get("File", args));
+		  text.append("\n");
+		  args[0] = k;
+		  text.append(get("Key", args));
+		  text.append("\n");
+		  args[0] = o_v;
+		  text.append(get("Old_Value", args));
+		  text.append("\n");
+		  args[0] = n_v;
+		  text.append(get("New_Value", args));
+		  text.append("\n");
+
+		  if(type == ADD_PROMPT) {
+				button_row.setLayout(new GridLayout(3,2,2,2));
+		  }
+		  else {
+				button_row.setLayout(new GridLayout(2,2,2,2));
+		  }
+		  
+		  // Add the components
+		  middle_pane.add(new JScrollPane(text), BorderLayout.CENTER);
+
+		  if(type == ADD_PROMPT) {
+				button_row.add(accumulate_b);
+				if(multiple_selection) {
+					 button_row.add(accumulate_all_b);
+				}
+				else {
+					 button_row.add(new JPanel());
+				}
+				button_row.add(overwrite_b);
+				if(multiple_selection) {
+					 button_row.add(overwrite_all_b);
+				}
+				else {
+					 button_row.add(new JPanel());
+				}
+				button_row.add(skip_b);
+				button_row.add(cancel_b);
+		  }
+		  else {
+				button_row.add(update_b);
+				if(multiple_selection) {
+					 button_row.add(update_all_b);
+				}
+				else {
+					 button_row.add(new JPanel());
+				}
+				button_row.add(skip_b);
+				button_row.add(cancel_b);
+		  }
+
+		  content_pane.add(title, BorderLayout.NORTH);
+		  content_pane.add(middle_pane, BorderLayout.CENTER);
+		  content_pane.add(button_row, BorderLayout.SOUTH);
+
+		  text.setCaretPosition(0);
+
+		  Rectangle frame_bounds = Gatherer.g_man.getBounds();
+		  this.setLocation(frame_bounds.x + ((frame_bounds.width - SIZE.width) / 2), frame_bounds.y + ((frame_bounds.height - SIZE.height) / 2));
+		  show();
+		  return value;
+	 }
+
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+
+	 private String get(String key, String args[]) {
+		  if(key.indexOf(".") == -1) {
+				key = "MetaEditPrompt." + key;
+		  }
+		  return Gatherer.dictionary.get(key, args);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/MirrorPane.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/MirrorPane.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/MirrorPane.java	(revision 13666)
@@ -0,0 +1,376 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.Message;
+import org.greenstone.gatherer.WGet;
+import org.greenstone.gatherer.file.FileSystemModel;
+import org.greenstone.gatherer.gui.Filter;
+import org.greenstone.gatherer.gui.GComboBox;
+import org.greenstone.gatherer.gui.tree.DragTree;
+import org.greenstone.gatherer.util.DragGroup;
+import org.greenstone.gatherer.util.GURL;
+import org.greenstone.gatherer.util.TreeSynchronizer;
+import org.greenstone.gatherer.util.Utility;
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.1
+ */
+public class MirrorPane
+	 extends JPanel
+	 implements ActionListener {
+
+	 private ButtonGroup destination_folder_options;
+	 private DragTree workspace_tree = null;
+	 private FileSystemModel model = null;
+	 /** The filter currently applied to the workspace tree. */
+	 private Filter workspace_filter = null;
+
+	 private ImageIcon thumbnail;
+
+	 private JButton download;
+	 private JButton view_selector;
+
+	 private JCheckBox download_hidden;
+	 private JCheckBox higher_directories;
+	 private JCheckBox infinite;
+	 private JCheckBox overwrite_existing;
+	 private JCheckBox remove_failed;
+	 private JCheckBox same_host;
+
+	 private JScrollPane list_scroll;
+	 private JScrollPane workspace_scroll;
+
+	 private JTextField download_depth;
+	 private JTextField number_downloads;
+	 private JTextField number_each_host;
+	 private JTextField source_url;
+
+	 private JToggleButton destination_private;
+	 private JToggleButton destination_shared;
+
+
+	 /** Ensures that expansion and selection events between workspace trees based on the same model are synchronized. */
+	 private TreeSynchronizer tree_sync = null;
+	 /** A reference to the object that provides JNI ability. */
+	 private WGet getter;
+	 /** The default size of a label in the interface. */
+	 static final private Dimension LABEL_SIZE = new Dimension(100,30);
+	 /** The default size of the tree in the interface. */
+	 static final private Dimension TREE_SIZE = new Dimension(250, 430);
+
+	 public MirrorPane(TreeSynchronizer workspace_tree_sync) {
+		  this.tree_sync = workspace_tree_sync;
+		  getter = new WGet();
+		  getter.start();
+	 }
+
+	 public void actionPerformed(ActionEvent event) {
+		  Object event_source = event.getSource();
+		  if(event_source == download) {
+				// Check we have a valid url.
+				GURL target_gurl = new GURL(source_url.getText());
+				if(target_gurl.getURL() != null) {
+					 // Update configuration settings.
+					 Gatherer.config.set("mirroring.page_requisites", false, download_hidden.isSelected());
+					 Gatherer.config.set("mirroring.no_parents", false, !higher_directories.isSelected());
+					 Gatherer.config.set("mirroring.clobber", false, overwrite_existing.isSelected());
+					 Gatherer.config.set("mirroring.remove_failed", false, remove_failed.isSelected());
+					 Gatherer.config.set("mirroring.other_hosts", false, !same_host.isSelected());
+					 // Depth
+					 if(infinite.isSelected()) {
+						  Gatherer.config.setInt("mirroring.depth", false, -1);
+					 }
+					 else if(download_depth.getText().length() > 0){
+						  //Gatherer.println("Download_depth = " + download_depth.getText().trim());
+						  Gatherer.config.setInt("mirroring.depth", false, Integer.parseInt(download_depth.getText().trim()));
+					 }
+
+					 // Queue download
+					 if(destination_shared.isSelected()) {
+						  getter.newJob(new GURL(source_url.getText()), model, Utility.CACHE_DIR);
+					 }
+					 else {
+						  getter.newJob(new GURL(source_url.getText()), model, Gatherer.c_man.getCollectionCache());
+					 }
+				}
+				// Otherwise indicate to the user that they've done something
+				// wrong.
+				else {
+					 // Error message box.
+					 String args[] = new String[1];
+					 args[0] = source_url.getText();
+					 message(Message.ERROR, get("Malformed_URL", args));
+					 // Colour source_url red
+					 source_url.setForeground(Color.red);
+				}
+
+		  }
+		  else if(event_source == source_url) {
+				// They've typed something. Change colour back to black
+				source_url.setForeground(Color.black);
+		  }
+	 }
+
+	 public void collectionChanged(boolean ready) {
+		  // Some buttons are only enabled if a collection is open.
+		  if(ready) {
+				destination_private.setEnabled(true);
+		  }
+		  else {
+				destination_shared.setSelected(true);
+				destination_private.setEnabled(false);
+		  }
+		  // Retrieve appropriate workspace
+		  model = (FileSystemModel) Gatherer.c_man.getWorkspace();
+		  workspace_tree.setModel(model);
+		  tree_sync.add(workspace_tree);
+	 }
+
+	 public void display() {
+		  this.setLayout(new BorderLayout());
+
+		  // Create
+		  JPanel tree_pane = new JPanel(new BorderLayout());
+		  tree_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		  tree_pane.setMinimumSize(TREE_SIZE);
+		  tree_pane.setSize(TREE_SIZE);
+		  tree_pane.setPreferredSize(TREE_SIZE);
+
+		  //Gatherer.println("\tCreating tree_label");
+		  JLabel tree_label = new JLabel(get("Workspace_Tree"));
+
+		  //Gatherer.println("\tCreating public tree");
+		  model = (FileSystemModel) Gatherer.c_man.getWorkspace();
+		  workspace_tree = new DragTree("Workspace_Mirror", model, null);
+		  workspace_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
+		  workspace_tree.putClientProperty("JTree.lineStyle", "Angled");
+		  workspace_tree.setBackgroundNonSelectionColor(Gatherer.config.getColor("coloring.workspace_tree_background", false));
+		  workspace_tree.setTextNonSelectionColor(Gatherer.config.getColor("coloring.workspace_tree_foreground", false));
+		  workspace_tree.setRootVisible(false);
+		  workspace_tree.setBackgroundSelectionColor(Gatherer.config.getColor("coloring.workspace_selection_background", false));
+		  workspace_tree.setTextSelectionColor(Gatherer.config.getColor("coloring.workspace_selection_foreground", false));
+
+  		  // Add to a dummy drag-group.
+  		  DragGroup group = new DragGroup();
+  		  group.add(workspace_tree);
+  		  group = null;
+
+		  workspace_filter = Gatherer.g_man.getFilter(workspace_tree);
+		  workspace_filter.setBackground(Gatherer.config.getColor("coloring.workspace_heading_background", false));
+		  // Change the default colours of this filters combobox.
+		  GComboBox fcb = workspace_filter.getComboBox();
+		  fcb.setBackgroundNonSelectionColor(Gatherer.config.getColor("coloring.workspace_tree_background", false));
+		  fcb.setTextNonSelectionColor(Gatherer.config.getColor("coloring.workspace_tree_foreground", false));
+		  fcb.setBackgroundSelectionColor(Gatherer.config.getColor("coloring.workspace_selection_background", false));
+		  fcb.setTextSelectionColor(Gatherer.config.getColor("coloring.workspace_selection_foreground", false));
+		  fcb = null;
+
+		  tree_pane.add(tree_label, BorderLayout.NORTH);
+		  tree_pane.add(new JScrollPane(workspace_tree), BorderLayout.CENTER);
+		  tree_pane.add(workspace_filter, BorderLayout.SOUTH);
+
+		  // Create control_pane
+		  JPanel control_pane = new JPanel(new BorderLayout());
+
+		  //Gatherer.println("\tCreating control_label");
+		  JLabel control_label = new JLabel(get("Download_Controls"));
+		  control_label.setHorizontalAlignment(JLabel.CENTER);
+		  control_label.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+
+		  //central_pane = new JPanel(new GridLayout(7,1));
+		  JPanel central_pane = new JPanel();
+		  central_pane.setLayout(new BoxLayout(central_pane, BoxLayout.Y_AXIS));
+
+		  //Gatherer.println("\tCreating source_url_pane");
+		  JPanel source_url_pane = new JPanel(new BorderLayout());
+		  JLabel source_url_label = new JLabel(get("Source_URL"));
+		  source_url_label.setPreferredSize(LABEL_SIZE);
+		  source_url = new JTextField("");
+		  source_url_pane.add(source_url_label, BorderLayout.WEST);
+		  source_url_pane.add(source_url, BorderLayout.CENTER);
+
+
+		  //Gatherer.println("\tCreating download_depth");
+		  JPanel download_depth_pane = new JPanel(new FlowLayout(FlowLayout.LEFT));
+		  JLabel download_depth_label = new JLabel(get("Download_Depth"));
+		  // Default depth. Its an int so we'll do some magic handwaving to magic it into a String. Alakazam.
+		  download_depth = new JTextField(Utility.getDepthString(6));
+		  infinite = new JCheckBox("Infinite");
+		  download_depth_pane.add(download_depth_label);
+		  download_depth_pane.add(download_depth);
+		  download_depth_pane.add(infinite);
+
+		  //Gatherer.println("\tCreating destination_folder");
+		  JPanel destination_folder_pane = new JPanel(new FlowLayout(FlowLayout.LEFT));
+		  JLabel destination_folder_label = new JLabel(get("Destination_Folder"));
+		  destination_folder_options = new ButtonGroup();
+		  destination_private = new JToggleButton(get("Destination_Private"));
+		  destination_private.setEnabled(Gatherer.c_man != null && Gatherer.c_man.ready());
+		  destination_private.setIcon(Utility.OFF_ICON);
+		  destination_private.setSelectedIcon(Utility.ON_ICON);
+		  destination_private.setSelected(false);
+		  destination_private.addActionListener(this);
+		  destination_folder_options.add(destination_private);
+		  destination_shared = new JToggleButton(get("Destination_Shared"));
+		  destination_shared.setIcon(Utility.OFF_ICON);
+		  destination_shared.setSelectedIcon(Utility.ON_ICON);
+		  destination_shared.setSelected(true);
+		  destination_shared.addActionListener(this);
+		  destination_folder_options.add(destination_shared);
+		  destination_folder_pane.add(destination_folder_label);
+		  destination_folder_pane.add(destination_private);
+		  destination_folder_pane.add(destination_shared);
+
+		  //Gatherer.println("\tCreating download_hidden");
+		  download_hidden = new JCheckBox(get("Download_Hidden"));
+		  // Why the friken heil is the horizontal alignment called Y?
+		  download_hidden.setAlignmentY(Component.LEFT_ALIGNMENT);
+		  download_hidden.setSelected(Gatherer.config.get("mirroring.page_requisites", false));
+
+		  //Gatherer.println("\tCreating higher_directories");
+		  higher_directories = new JCheckBox(get("Higher_Directories"));
+		  higher_directories.setSelected(!Gatherer.config.get("mirroring.no_parents", false));
+
+		  //Gatherer.println("\tCreating same_host");
+		  same_host = new JCheckBox(get("Same_Host"));
+		  same_host.setSelected(!Gatherer.config.get("mirroring.other_hosts", false));
+
+		  //Gatherer.println("\tCreating overwrite");
+		  overwrite_existing = new JCheckBox(get("Overwrite_Existing"));
+		  overwrite_existing.setSelected(Gatherer.config.get("mirroring.overwrite", false));
+
+		  JLabel further_options = new JLabel(get("Further_Options"));
+		  further_options.setHorizontalAlignment(JLabel.LEFT);
+
+		  central_pane.add(source_url_pane);
+		  central_pane.add(download_depth_pane);
+		  central_pane.add(destination_folder_pane);
+
+		  JPanel three_mid = new JPanel(new GridLayout(5,1));
+
+		  three_mid.add(download_hidden);
+		  three_mid.add(higher_directories);
+		  three_mid.add(same_host);
+		  three_mid.add(overwrite_existing);
+		  three_mid.add(further_options);
+
+		  central_pane.add(three_mid);
+
+		  //Gatherer.println("\tCreating thumbnail");
+		  thumbnail = new ImageIcon(Utility.RES_DIR + "no_thumbnail.gif");
+		  JLabel thumbnail_holder = new JLabel(thumbnail);
+		  // Default thumbnail size.
+		  //thumbnail_holder.setSize(Gatherer.config.getDimension("mirroring.thumbnail_size", false));
+		  thumbnail_holder.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+
+		  JPanel lower_pane = new JPanel(new BorderLayout());
+		  lower_pane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED), get("Download_List_Configuration")));
+
+		  remove_failed = new JCheckBox(get("Remove_Failed"));
+		  remove_failed.setSelected(Gatherer.config.get("mirroring.remove_failed", false));
+
+		  //Gatherer.println("\tCreating download_button");
+		  download = new JButton(get("Download"));
+		  download.addActionListener(this);
+		  download.setHorizontalAlignment(JLabel.CENTER);
+		  JPanel download_pane = new JPanel(new BorderLayout());
+
+		  lower_pane.add(remove_failed, BorderLayout.NORTH);
+		  lower_pane.add(download_pane, BorderLayout.CENTER);
+
+		  control_pane.add(control_label, BorderLayout.NORTH);
+		  control_pane.add(central_pane, BorderLayout.WEST);
+		  //control_pane.add(thumbnail_holder, BorderLayout.CENTER);
+		  control_pane.add(lower_pane, BorderLayout.SOUTH);
+
+		  // Create list_pane
+		  JPanel list_pane = new JPanel(new BorderLayout());
+		  list_pane.setPreferredSize(new Dimension(Gatherer.g_man.getSize().width, Gatherer.g_man.getSize().height / 4));
+
+		  download_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		  download_pane.add(download);
+
+		  //Gatherer.println("\tCreating list");
+		  list_scroll = getter.getJobList();
+
+		  //list_pane.add(download_pane, BorderLayout.NORTH);
+		  list_pane.add(list_scroll, BorderLayout.CENTER);
+
+		  // Add to content
+		  JPanel temp_pane = new JPanel(new BorderLayout());
+		  this.add(tree_pane, BorderLayout.WEST);
+		  this.add(control_pane, BorderLayout.CENTER);
+		  //temp_pane.add(control_pane, BorderLayout.NORTH);
+		  //temp_pane.add(list_pane, BorderLayout.CENTER);
+		  this.add(list_pane, BorderLayout.SOUTH);
+	 }
+
+	 public void setURL(String url) {
+		  source_url.setText(url);
+	 }
+
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+
+	 private String get(String key, String args[]) {
+		  if(key.indexOf('.') == -1) {
+				key = "Mirroring." + key;
+		  }
+		  return Gatherer.dictionary.get(key,args);
+	 }
+
+	 /** Creates and dispatches a message given the initial details.
+	  * @param level An int indicating the message level for this message.
+	  * @param message A String which contains the payload of this message.
+	  */
+	 private void message(int level, String message) {
+		  Message msg = new Message(Message.MIRRORING, level, message);
+		  if(Gatherer.g_man != null) {
+				Gatherer.g_man.message_pane.show(msg);
+		  } else {
+				Gatherer.println(msg.toString());
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/NewCollectionDetailsPrompt.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/NewCollectionDetailsPrompt.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/NewCollectionDetailsPrompt.java	(revision 13666)
@@ -0,0 +1,496 @@
+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.Gatherer;
+import org.greenstone.gatherer.collection.CollectionConfiguration;
+import org.greenstone.gatherer.util.Utility;
+
+public class NewCollectionDetailsPrompt
+	 extends JDialog {
+	 private boolean cancelled;
+	 private File base_final;
+	 private JButton create_button;
+	 private JComboBox base_collection;
+	 private JDialog self;
+	 private JTextArea description;
+	 private JTextField address;
+	 private JTextField host;
+	 private JTextField title;
+	 private RestrictedTextField file;
+	 private String description_final;
+	 private String email_final;
+	 private String name_final;
+	 private String title_final;
+	 static private Dimension label_size = new Dimension(230, 25);
+	 /** The size of this new collection dialog box. */
+	 static private Dimension size = new Dimension(700, 350);
+	 static private int FILENAME_SIZE = 8;
+
+	 /** Constructor.
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public NewCollectionDetailsPrompt() {
+		  super(Gatherer.g_man);
+		  this.cancelled = true;
+		  this.self = this;
+		  // Setup
+		  setJMenuBar(new SimpleMenuBar("2.1"));
+		  setModal(true);
+		  setSize(size);
+		  setTitle(get("Title"));
+
+		  // Model building. Build a model of all of the collections in the gsdl collect directory with the appropriate directories and hardcode the big five.
+		  Vector base_collection_model = new Vector();
+		  // Dummy item
+		  File gsdl_collection_directory = new File(Utility.getCollectionDir(Gatherer.config.gsdl_path));
+		  File[] possible_collections = gsdl_collection_directory.listFiles();
+		  for(int i = 0; possible_collections != null && i < possible_collections.length; i++) {
+				// The simpliest case is if the directory etc/collect.cfg file and a metadata/ in it. Thus it can easily be built upon.
+				File collect_cfg_file = new File(possible_collections[i], Utility.CONFIG_DIR);
+				File metadata_directory = new File(possible_collections[i], Utility.META_DIR);
+				if(collect_cfg_file.exists()) {
+					 CollectionConfiguration collect_cfg = new CollectionConfiguration(collect_cfg_file);
+					 String collection_name = collect_cfg.getName();
+					 // Even if there is no metadata directory we add it if its one of the 'big five' that we know how to handle.
+					 if(metadata_directory.exists() || collection_name.equals(Utility.COLLECTION_DLS)) { /** @todo - the other big five */
+						  // Add to model.
+						  Item item = new Item(possible_collections[i], collection_name);
+						  if(!base_collection_model.contains(item)) {
+								base_collection_model.add(item);
+						  }
+					 }
+					 // Else not a collection we know how to retrieve the metadata set for.
+				}
+				// Else not a collection at all. Someones pulling a fast one.
+		  }
+		  // Sort the result.
+		  Collections.sort(base_collection_model);
+		  base_collection_model.add(0, new Item(null, get("NewCollection")));
+		  // Creation.
+		  JPanel content_pane = (JPanel) getContentPane();
+		  content_pane.setOpaque(true);
+		  JPanel upper_pane = new JPanel();
+		  upper_pane.setOpaque(false);
+		  JLabel instructions_label = new JLabel(get("Instructions"));
+		  instructions_label.setOpaque(false);
+		  JPanel title_pane = new JPanel();
+		  title_pane.setOpaque(false);
+		  JLabel title_label = new JLabel(get("Collection_Title"));
+		  title_label.setOpaque(false);
+		  title = new JTextField();
+		  JPanel name_pane = new JPanel();
+		  name_pane.setOpaque(false);
+		  JLabel name_label = new JLabel(get("Collection_Name"));
+		  name_label.setOpaque(false);
+		  JPanel file_pane = new JPanel();
+		  file_pane.setOpaque(false);
+		  file = new RestrictedTextField(new RestrictedTextDocument(FILENAME_SIZE), "", FILENAME_SIZE);
+		  JLabel file_label = new JLabel(".col");
+		  file_label.setOpaque(false);
+		  JPanel email_pane = new JPanel();
+		  email_pane.setOpaque(false);
+		  JLabel email_label = new JLabel(get("Collection_Email"));
+		  email_label.setOpaque(false);
+		  JPanel host_pane = new JPanel();
+		  host_pane.setOpaque(false);
+		  JPanel address_pane = new JPanel();
+		  address_pane.setOpaque(false);
+		  address = new JTextField();
+		  JLabel at_label = new JLabel("@");
+		  host = new JTextField();
+		  JPanel center_pane = new JPanel();
+		  center_pane.setOpaque(false);
+		  JPanel description_pane = new JPanel();
+		  description_pane.setOpaque(false);
+		  JLabel description_label = new JLabel(get("Collection_Description"));
+		  description_label.setOpaque(false);
+		  description = new JTextArea();
+		  description.setRows(5);
+
+		  JPanel bottom_pane = new JPanel();
+		  // Base Collection
+		  JPanel base_collection_pane = new JPanel();
+		  JLabel base_collection_label = new JLabel(get("Base_Collection"));
+		  base_collection = new JComboBox(base_collection_model);
+		  JButton base_collection_browse = new JButton(get("General.Browse"));
+
+		  JPanel button_pane = new JPanel();
+		  button_pane.setOpaque(false);
+		  create_button = new JButton(get("General.OK"));
+		  create_button.setMnemonic(KeyEvent.VK_O);
+		  JButton cancel_button = new JButton(get("General.Cancel"));
+		  cancel_button.setMnemonic(KeyEvent.VK_C);
+		  ColorListener email_color_listener = new ColorListener(address, host);
+		  // Connection
+		  base_collection_browse.addActionListener(new BrowseListener());
+		  cancel_button.addActionListener(new CancelListener());
+		  create_button.addActionListener(new CreateListener());
+		  address.addKeyListener(email_color_listener);
+		  description.addKeyListener(new ColorListener(description));
+		  description.addKeyListener(new DescriptionListener());
+		  file.addKeyListener(new ColorListener(file));
+		  host.addKeyListener(email_color_listener);
+		  title.addKeyListener(new ColorListener(title));
+		  title.getDocument().addDocumentListener(new TitleListener());
+		  // Layout
+		  title_label.setPreferredSize(label_size);
+
+		  title_pane.setLayout(new BorderLayout());
+		  title_pane.add(title_label, BorderLayout.WEST);
+		  title_pane.add(title, BorderLayout.CENTER);
+
+		  file_pane.setLayout(new BorderLayout());
+		  file_pane.add(file, BorderLayout.WEST);
+		  file_pane.add(file_label, BorderLayout.CENTER);
+
+		  name_label.setPreferredSize(label_size);
+
+		  name_pane.setLayout(new BorderLayout());
+		  name_pane.add(name_label, BorderLayout.WEST);
+		  name_pane.add(file_pane, BorderLayout.CENTER);
+
+		  email_label.setPreferredSize(label_size);
+
+		  address_pane.setLayout(new BorderLayout());
+		  address_pane.add(address, BorderLayout.CENTER);
+		  address_pane.add(at_label, BorderLayout.EAST);
+
+		  host_pane.setLayout(new GridLayout(1,2));
+		  host_pane.add(address_pane);
+		  host_pane.add(host);
+
+		  email_pane.setLayout(new BorderLayout());
+		  email_pane.add(email_label, BorderLayout.WEST);
+		  email_pane.add(host_pane, BorderLayout.CENTER);
+
+		  upper_pane.setLayout(new GridLayout(4,1));
+		  upper_pane.add(instructions_label);
+		  upper_pane.add(title_pane);
+		  upper_pane.add(name_pane);
+		  upper_pane.add(email_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());
+		  base_collection_pane.add(base_collection_label, BorderLayout.NORTH);
+		  base_collection_pane.add(base_collection, BorderLayout.CENTER);
+		  base_collection_pane.add(base_collection_browse, BorderLayout.EAST);
+
+		  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.CENTER);
+		  bottom_pane.add(button_pane, BorderLayout.SOUTH);
+
+		  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 = Gatherer.config.screen_size;
+		  setLocation((screen_size.width - size.width) / 2, (screen_size.height - size.height) / 2);
+		  show();
+	 }
+
+	 public boolean isCancelled() {
+		  return cancelled;
+	 }
+
+	 public File getBase() {
+		  return base_final;
+	 }
+
+	 public String getDescription() {
+		  return description_final;
+	 }
+
+	 public String getEmail() {
+		  return email_final;
+	 }
+
+	 public String getName() {
+		  return name_final;
+	 }
+
+	 public String getTitle() {
+		  return title_final;
+	 }
+
+	 /** Gets a phrase from the dictionary based on key.
+	  * @param key A <strong>String</strong> which serves as the unique identifier of a phrase.
+	  * @return The desired phrase as a <strong>String</strong> or at least a meaningful error message.
+	  */
+	 private String get(String key) {
+		  if(key.indexOf(".") == -1) {
+				key = "NewCollectionPrompt." + key;
+		  }
+		  return Gatherer.dictionary.get(key);
+	 }
+
+	 private class BrowseListener 
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				File file;
+				if(Gatherer.config.gsdl_path != null) {
+					 file = new File(Utility.getCollectionDir(Gatherer.config.gsdl_path));
+				}
+				else {
+					 file = new File(Utility.BASE_DIR);
+				}
+				// Show OpenCollectionPrompt.
+				OpenCollectionDialog chooser = new OpenCollectionDialog(file);
+				file = chooser.getSelectedFile();
+				if(file != null) {
+					 file = file.getParentFile();
+					 CollectionConfiguration collect_cfg = new CollectionConfiguration(new File(file, Utility.META_DIR));
+					 Item item = new Item(file, collect_cfg.getName());
+					 base_collection.addItem(item);
+					 base_collection.setSelectedItem(item);
+				}			
+		  }
+	 }
+
+	 private class CancelListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				cancelled = true;
+				self.dispose();
+		  }
+	 }
+
+	 private class ColorListener
+		  extends KeyAdapter {
+		  private JTextComponent component1;
+		  private JTextComponent component2;
+		  public ColorListener(JTextComponent component) {
+				this.component1 = component;
+				this.component2 = null;
+		  }
+		  public ColorListener(JTextComponent component1, JTextComponent component2) {
+				this.component1 = component1;
+				this.component2 = component2;
+		  }
+		  public void keyPressed(KeyEvent event) {
+				component1.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+				component1.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				if(component2 != null) {
+					 component2.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+					 component2.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				}
+		  }
+	 }
+
+	 private class CreateListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				// Validate.
+				title_final = title.getText();
+				if(title_final.length() == 0) {
+					 GPrompt err_msg = new GPrompt(self, get("Error"), get("Title_Error"), "error.gif", null);
+					 err_msg.display();
+					 err_msg.destroy();
+					 err_msg = null;
+					 title.setForeground(Gatherer.config.getColor("coloring.error_foreground", false));
+					 title.setBackground(Gatherer.config.getColor("coloring.error_background", false));
+					 return;
+				}
+				name_final = file.getText();
+				if(name_final.length() > 0) {
+					 // Determine if this filename is already in use.
+					 File collection_directory = new File(Utility.getCollectionDir(Gatherer.config.gsdl_path));
+					 File children[] = collection_directory.listFiles();
+					 for(int i = 0; children != null && i < children.length; i++) {
+						  if(children[i].getName().equals(name_final)) {
+								GPrompt err_msg = new GPrompt(self, get("Error"), get("Name_Error"), "error.gif", null);
+								err_msg.display();
+								err_msg.destroy();
+								err_msg = null;
+								file.setForeground(Gatherer.config.getColor("coloring.error_foreground", false));
+								file.setBackground(Gatherer.config.getColor("coloring.error_background", false));
+								return;
+						  }
+					 }
+				}
+				else {
+					 GPrompt err_msg = new GPrompt(self, get("Error"), get("Name_Error"), "error.gif", null);
+					 err_msg.display();
+					 err_msg.destroy();
+					 err_msg = null;
+					 file.setForeground(Gatherer.config.getColor("coloring.error_foreground", false));
+					 file.setBackground(Gatherer.config.getColor("coloring.error_background", false));
+					 return;
+				}
+				email_final = address.getText() + "@" + host.getText();
+				if(email_final.length() == 0 || email_final.startsWith("@") || email_final.endsWith("@")) {
+					 GPrompt err_msg = new GPrompt(self, get("Error"), get("Email_Error"), "error.gif", null);
+					 err_msg.display();
+					 err_msg.destroy();
+					 err_msg = null;
+					 address.setForeground(Gatherer.config.getColor("coloring.error_foreground", false));
+					 address.setBackground(Gatherer.config.getColor("coloring.error_background", false));
+					 host.setForeground(Gatherer.config.getColor("coloring.error_foreground", false));
+					 host.setBackground(Gatherer.config.getColor("coloring.error_background", false));
+					 return; 
+				}
+				description_final = description.getText();
+				if(description_final.length() == 0) {
+					 GPrompt err_msg = new GPrompt(self, get("Error"), get("Description_Error"), "error.gif", null);
+					 err_msg.display();
+					 err_msg.destroy();
+					 err_msg = null;
+					 description.setForeground(Gatherer.config.getColor("coloring.error_foreground", false));
+					 description.setBackground(Gatherer.config.getColor("coloring.error_background", false));
+					 return;
+				}
+				description_final = Utility.encodeGreenstone(description_final);
+				// 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 File file;
+		  private String name;
+		  public Item(File file, String name) {
+				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() {
+				return name;
+		  }
+	 }
+
+	 private class RestrictedTextField 
+		  extends JTextField {
+		  public RestrictedTextField(RestrictedTextDocument document, String value, int cols) {
+				super(document, "", cols);
+		  }
+		  protected Document createDefaultModel() {
+				return new RestrictedTextDocument(11);
+		  }
+	 }
+
+	 private class RestrictedTextDocument 
+		  extends PlainDocument {
+		  private char block[];
+		  private int cols;
+		  private int current;
+		  public RestrictedTextDocument(int cols) {
+				super();
+				this.cols = cols;
+				this.current = 0;
+		  }
+		  public void blockChar(char c) {
+				if(block == null) {
+					 block = new char[1];
+					 block[0] = c;
+				}
+				else {
+					 char temp[] = block;
+					 block = new char[temp.length + 1];
+					 System.arraycopy(temp, 0, block, 0, temp.length);
+					 block[temp.length] = c;
+					 temp = null;
+				}
+		  }
+		  public void insertString(int offs, String str, AttributeSet a) 
+				throws BadLocationException {
+				// Remove any blocked characters.
+				StringBuffer temp = new StringBuffer(str);
+				for(int i = 0; block != null && i < block.length; i++) {
+					 for(int j = temp.length() - 1; j >= 0; j--) {
+						  if(temp.charAt(j) == block[i]) {
+								temp.deleteCharAt(j);
+						  }
+					 }
+				}
+				str = temp.toString();
+				if(cols == -1 || str.length() + current <= cols) {
+					 super.insertString(offs, str, a);
+					 current = current + str.length();
+				}
+		  }
+		  public void remove(int offs, int len)
+				throws BadLocationException {
+				super.remove(offs, len);
+				current = current - len;
+		  }
+	 }
+
+	 private class TitleListener
+		  implements DocumentListener {
+		  /** Gives notification that an attribute or set of attributes changed. */
+		  public void changedUpdate(DocumentEvent e) {
+				updateFilename();
+		  }
+          
+		  /** Gives notification that there was an insert into the document. */
+		  public void insertUpdate(DocumentEvent e) {
+				updateFilename();
+		  }
+          
+		  /** Gives notification that a portion of the document has been removed. */
+		  public void removeUpdate(DocumentEvent e) {
+				updateFilename();
+		  }
+
+		  private void updateFilename() {
+				String current_name = file.getText();
+				String current_title = title.getText();
+				StringBuffer temp = new StringBuffer("");
+				int i = 0;
+				while(i < current_title.length() && temp.length() < 8) {
+					 if(current_title.charAt(i) != ' ') {
+						  temp.append(Character.toLowerCase(current_title.charAt(i)));
+					 }
+					 i++;
+				}
+				String result = temp.toString();
+				if(current_name.startsWith(result) || result.startsWith(current_name)) {
+					 file.setText(result);
+				}
+		  }
+	 }
+
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/NewCollectionMetadataPrompt.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/NewCollectionMetadataPrompt.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/NewCollectionMetadataPrompt.java	(revision 13666)
@@ -0,0 +1,186 @@
+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.Gatherer;
+import org.greenstone.gatherer.checklist.CheckList;
+import org.greenstone.gatherer.checklist.Entry;
+import org.greenstone.gatherer.gui.GUIManager;
+import org.greenstone.gatherer.gui.SimpleMenuBar;
+import org.greenstone.gatherer.cdm.ElementWrapper;
+import org.greenstone.gatherer.msm.MetadataSet;
+import org.greenstone.gatherer.msm.MetadataSetManager;
+import org.greenstone.gatherer.util.Utility;
+import org.w3c.dom.*;
+
+public class NewCollectionMetadataPrompt 
+	 extends JDialog {
+
+	 private boolean cancelled = true;
+	 private CheckList sets_list;
+	 private JDialog self;
+	 private JList elements_list;
+	 static private Dimension size = new Dimension(700, 380);
+
+	 public NewCollectionMetadataPrompt() {
+		  super(Gatherer.g_man, true);
+		  this.self = this;
+		  setJMenuBar(new SimpleMenuBar("2.1"));
+		  setModal(true);
+		  setSize(size);
+		  setTitle(get("Title"));
+
+		  // And the remaining metadata sets.
+		  ArrayList sets = new ArrayList();
+		  // Determine what collections are available.
+		  File metadata_directory = new File(Utility.METADATA_DIR);
+		  File[] possible_mdses = metadata_directory.listFiles();
+		  for(int i = 0; i < possible_mdses.length; i++) {
+				String name = possible_mdses[i].getName();
+				if(name.endsWith(".mds")) {
+					 sets.add(new MetadataSet(possible_mdses[i]));
+				}				
+		  }		  
+
+		  // Creation
+		  JPanel content_pane = (JPanel) getContentPane();
+
+		  JLabel instructions_label = new JLabel(get("Metadata_Instructions"));
+
+		  JPanel center_pane = new JPanel();
+
+		  JPanel sets_list_pane = new JPanel();
+		  JLabel sets_list_label = new JLabel(get("Select_MDS"));
+		  sets_list_label.setOpaque(false);
+		  sets_list = new CheckList(sets);
+
+		  JPanel elements_list_pane = new JPanel();
+		  JLabel elements_list_label = new JLabel(get("Metadata_Elements"));
+		  elements_list = new JList();
+		  elements_list.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  elements_list.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+		  elements_list.setSelectionBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  elements_list.setSelectionForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+
+		  JPanel button_pane = new JPanel();
+		  JButton ok_button = new JButton(get("General.OK"));
+		  JButton cancel_button = new JButton(get("General.Cancel"));
+		  // Connection
+		  ok_button.addActionListener(new OKButtonListener());
+		  cancel_button.addActionListener(new CancelButtonListener());
+		  sets_list.addListSelectionListener(new MetadataListSelectionListener());
+		  // Display
+		  sets_list_pane.setLayout(new BorderLayout());
+		  sets_list_pane.add(sets_list_label, BorderLayout.NORTH);
+		  sets_list_pane.add(new JScrollPane(sets_list), BorderLayout.CENTER);
+
+		  elements_list_pane.setLayout(new BorderLayout());
+		  elements_list_pane.add(elements_list_label, BorderLayout.NORTH);
+		  elements_list_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_list_pane);
+		  center_pane.add(elements_list_pane);
+
+		  button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+		  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(instructions_label, BorderLayout.NORTH);
+		  content_pane.add(center_pane, BorderLayout.CENTER);
+		  content_pane.add(button_pane, BorderLayout.SOUTH);
+		  // Show
+		  Dimension screen_size = Gatherer.config.screen_size;
+		  setLocation((screen_size.width - size.width) / 2, (screen_size.height - size.height) / 2);
+		  show();
+	 }
+
+	 public ArrayList getSets() {
+		  return sets_list.getSelected();
+	 }
+
+	 public boolean isCancelled() {
+		  return cancelled;
+	 }
+
+	 private void determineMetadataElements(MetadataSet extracted_metadata) {
+		  // Hardcoded...
+		  extracted_metadata.addElement("Encoding");
+		  extracted_metadata.addElement("Language");
+		  extracted_metadata.addElement("Source");
+		  extracted_metadata.addElement("Title");
+	 }
+
+	 /** Gets a phrase from the dictionary based on key.
+	  * @param key A <strong>String</strong> which serves as the unique identifier of a phrase.
+	  * @return The desired phrase as a <strong>String</strong> or at least a meaningful error message.
+	  */
+	 private String get(String key) {
+		  if(key.indexOf(".") == -1) {
+				key = "NewCollectionPrompt." + key;
+		  }
+		  return Gatherer.dictionary.get(key);
+	 }
+
+	 private class CancelButtonListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				cancelled = true;
+				self.dispose();
+		  }
+	 }
+
+	 public class MetadataListSelectionListener
+		  implements ListSelectionListener {
+		  public void valueChanged(ListSelectionEvent event) {
+				if(!sets_list.isSelectionEmpty()) {
+					 // Retrieve the selected set.
+					 Entry entry = (Entry) sets_list.getSelectedValue();
+					 MetadataSet set = (MetadataSet) entry.getObject();
+					 entry = null;
+					 // Build a model from its elements.
+					 NodeList elements = set.getElements();
+					 set = null;
+					 Vector elements_model = new Vector();
+					 for(int i = 0; i < elements.getLength(); i++) {
+						  elements_model.add(new ElementWrapper(elements.item(i)));
+					 }
+					 elements = null;
+					 Collections.sort(elements_model);
+					 elements_list.setListData(elements_model);
+					 elements_model = null;
+				}
+				else {
+					 elements_list.setListData(new String[0]);
+				}
+		  }
+	 }
+
+	 public class OKButtonListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				// See if the user has selected no metadata sets, and if so confirm thats what they really want.
+				ArrayList selected_sets = sets_list.getSelected();
+				if(selected_sets.size() == 0) {
+					 WarningDialog dialog = new WarningDialog("warning.NoMetadataSetsSelected", true);
+					 if(dialog.display() == JOptionPane.OK_OPTION) {
+						  // Otherwise we are free to go
+						  self.dispose();
+					 }
+				}
+				else {
+					 self.dispose();
+				}
+		  }
+	 }
+}
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/NewFolderPrompt.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/NewFolderPrompt.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/NewFolderPrompt.java	(revision 13666)
@@ -0,0 +1,81 @@
+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.file.FileNode;
+import org.greenstone.gatherer.gui.GUIManager;
+
+public class NewFolderPrompt
+	 extends JDialog 
+	 implements ActionListener {
+	 private FileNode node;
+	 private JButton cancel_button;
+	 private JButton ok_button;
+	 private JTextField name_field;
+	 private String name;
+	 static final private Dimension LABEL_SIZE = new Dimension(100,25);
+	 static final private Dimension SIZE = new Dimension(300,100);
+	 public NewFolderPrompt(FileNode node) {
+		  super(Gatherer.g_man, Gatherer.dictionary.get("NewFolderPrompt.Title"), true);
+		  this.node = node;
+	 }
+
+	 public void actionPerformed(ActionEvent event) {
+		  if(event.getSource() == ok_button) {
+				name = name_field.getText();
+		  }
+		  else if(event.getSource() == cancel_button) {
+				name = null;
+		  }
+		  dispose();
+	 }
+
+	 public String display() {
+		  setSize(SIZE);
+		  JPanel content_pane = (JPanel) getContentPane();
+		  JPanel name_pane = new JPanel();
+		  JLabel name_label = new JLabel(Gatherer.dictionary.get("NewFolderPrompt.Folder_Name"));
+		  name_label.setPreferredSize(LABEL_SIZE);
+		  name_field = new JTextField(getAutomaticName());
+		  JPanel button_pane = new JPanel();
+		  ok_button = new JButton(Gatherer.dictionary.get("General.OK"));
+		  cancel_button = new JButton(Gatherer.dictionary.get("General.Cancel"));
+		  // Connection
+		  cancel_button.addActionListener(this);
+		  ok_button.addActionListener(this);
+		  // Layout
+		  name_pane.setLayout(new BorderLayout());
+		  name_pane.add(name_label, BorderLayout.WEST);
+		  name_pane.add(name_field, BorderLayout.CENTER);
+
+		  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(name_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);
+		  show();
+		  return name;
+	 }
+
+	 private String getAutomaticName() {
+		  File file = node.getFile();
+		  String default_name = Gatherer.dictionary.get("NewFolderPrompt.Default_Folder_Name");
+		  File temp_file = new File(file, default_name);
+		  int count = 1;
+		  if(temp_file.exists()) {
+				temp_file = new File(file, default_name + " " + count);
+				count++;
+		  }
+		  return temp_file.getName();
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/NumberField.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/NumberField.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/NumberField.java	(revision 13666)
@@ -0,0 +1,37 @@
+package org.greenstone.gatherer.gui;
+
+import javax.swing.*;
+import javax.swing.text.*;
+
+
+public class NumberField 
+	 extends JTextField {
+ 
+	 public NumberField(String text) {
+		  super(text);
+	 }
+ 
+	 protected Document createDefaultModel() {
+		  return new NumberDocument();
+	 }
+ 
+	 static class NumberDocument 
+		  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.isDigit(raw[i])) {
+						  result.append(raw[i]);
+					 }
+				}
+				super.insertString(offs, result.toString(), a);
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/OpenCollectionDialog.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/OpenCollectionDialog.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/OpenCollectionDialog.java	(revision 13666)
@@ -0,0 +1,277 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import java.beans.*;
+import java.io.File;
+import java.io.IOException;
+import java.text.*;
+import java.util.*;
+import javax.accessibility.*;
+import javax.swing.*;
+import javax.swing.filechooser.*;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.CollectionConfiguration;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.util.Utility;
+import org.outerj.pollo.util.*;
+
+public class OpenCollectionDialog 
+	 extends JFileChooser {
+	 static final private ImageIcon LOCKED_COLLECTION_ICON = Utility.getImage("lcolicn.gif");
+	 static final private ImageIcon NORMAL_COLLECTION_ICON = Utility.getImage("ncolicn.gif");
+	 /** The name of the mouse listener that initiates editing on a double click. */ 
+	 static final private String SINGLE_CLICK_LISTENER = "SingleClickListener";
+	 /** Constructor */
+	 public OpenCollectionDialog(File file) {
+		  super(file);
+		  System.err.println("Size = " + getSize());
+		  // Other initialization
+		  setAcceptAllFileFilterUsed(false);
+		  setDialogTitle(Gatherer.dictionary.get("OpenCollectionDialog.Title"));
+		  setFileFilter(new GathererFilter());
+		  setFileSystemView(new GathererFileSystemView());
+		  setFileView(new GathererFileView());
+		  setSize(400,300);
+		  // Stop the annoying renaming
+		  disableRename(this);
+		  // Description accessory
+		  DescriptionPreview accessory = new DescriptionPreview(this);
+		  setAccessory(accessory);
+		  // Move accessory
+		  JPanel accessory_pane = (JPanel) accessory.getParent();
+		  JPanel center_pane = (JPanel) accessory_pane.getParent();
+		  center_pane.add(accessory_pane, BorderLayout.SOUTH);
+		  // Done.
+	 }
+
+	 public String getFileName() {
+		  // Continually loop until the use chooses an appropriate file or cancels.
+		  while(true) {
+				int return_val = showOpenDialog(null);
+				if(return_val == JFileChooser.APPROVE_OPTION) {
+					 File file = getSelectedFile();
+					 if(file != null && file.getName().endsWith(".col")) {
+						  return file.getAbsolutePath();
+					 }
+				}
+				else {
+					 return null;
+				}
+		  }
+	 }
+
+	 /** 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]);
+					 }
+				}
+		  }
+	 } 
+
+	 static public void main(String args[]) {
+		  JFrame frame = new JFrame();
+		  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+		  frame.setSize(800,640);
+		  OpenCollectionDialog chooser = new OpenCollectionDialog(new File("/research/jmt12/gsdl/collect/"));
+		  // Show dialog
+		  int result = chooser.showOpenDialog(frame);
+	 }
+
+	 /* The DescriptionPreview accessory is adapted from the ImagePreview.java (an example used by FileChooserDemo2.java). */
+	 private class DescriptionPreview 
+		  extends JPanel
+		  implements PropertyChangeListener {
+		  private File file = null;
+		  private JTextArea text;
+		  //private JEditorPane text;
+		  public DescriptionPreview(JFileChooser fc) {
+				setName("Description Preview");
+				setPreferredSize(new Dimension(100, 75)); // About three rows.
+
+				text = new JTextArea(Gatherer.dictionary.get("OpenCollectionDialog.No_Description"));
+				//text.setLineWrap(true);
+				//text.setWrapStyleWord(true);
+				//text = new JEditorPane();
+				//text.setText(Gatherer.dictionary.get("OpenCollectionDialog.No_Description"));
+
+				setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+				setLayout(new BorderLayout());
+				add(new JScrollPane(text), BorderLayout.CENTER);
+
+				fc.addPropertyChangeListener(this);
+		  }
+		  /** Whenever a new file or folder is selected we determine what description should be displayed. */
+		  public void propertyChange(PropertyChangeEvent e) {
+				boolean update = false;
+				String prop = e.getPropertyName();
+				//If the directory changed, don't show an image.
+				if (JFileChooser.DIRECTORY_CHANGED_PROPERTY.equals(prop)) {
+					 file = null;
+					 update = true;
+					 
+					 //If a file became selected, find out which one.
+				} else if (JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals(prop)) {
+					 file = (File) e.getNewValue();
+					 update = true;
+				}
+				//Update the description accordingly.
+				if (update) {
+					 if(file == null) {
+						  text.setText(Gatherer.dictionary.get("OpenCollectionDialog.No_Description"));
+					 }
+					 else {
+						  // Build a wrapper around the collection configuration file.
+						  File config_file = new File(file.getParentFile(), Utility.CONFIG_DIR);
+						  if(config_file.exists()) {
+								CollectionConfiguration collect_cfg = new CollectionConfiguration(config_file);
+								text.setText(collect_cfg.getDescription());
+								text.setCaretPosition(0);
+						  }
+					 }
+				}
+		  }  
+	 }
+
+	 /** ImageFilter.java is a 1.4 example used by FileChooserDemo2.java. */
+	 private class GathererFilter 
+		  extends FileFilter {
+  
+		  //Accept all directories and all gif, jpg, tiff, or png files.
+		  public boolean accept(File f) {
+				return (f.isDirectory() || f.getName().toLowerCase().endsWith(".col"));
+		  }
+		  
+		  //The description of this filter
+		  public String getDescription() {
+				return Gatherer.dictionary.get("OpenCollectionDialog.Collection");
+		  }
+	 }
+
+	 private class GathererFileSystemView
+		  extends FileSystemView {
+		  
+		  private FileSystemView default_system_view = FileSystemView.getFileSystemView();
+	
+		  /** Creates a new folder with a default folder name. */
+		  public File createNewFolder(File containingDir) 
+				throws IOException {
+				return default_system_view.createNewFolder(containingDir);
+		  }          
+
+		  /** Gets the list of shown (i.e. */
+		  public File[] getFiles(File dir, boolean useFileHiding) {
+				// Retrieve the files usually returned by the platform specific file system view.
+				File[] files = default_system_view.getFiles(dir, useFileHiding);
+				// Determine if the current dir actually contains a valid greenstone collection. To do this we check for the presence of the file <dir>/etc/collect.cfg and a directory named import or gimport.
+				File collect_cfg_file = new File(dir, Utility.CONFIG_DIR);
+				File import_dir_file = new File(dir, Utility.OLD_IMPORT_DIR);
+				File gimport_dir_file = new File(dir, Utility.IMPORT_DIR);
+				if(collect_cfg_file.exists() && (gimport_dir_file.exists() || import_dir_file.exists())) {
+					 // Create a new dummy collection file.
+					 String name = dir.getName();
+					 File collection_file = new File(dir, name + ".col");
+					 // If this file doesn't already exist.
+					 if(!collection_file.exists()) {
+						  File[] temp = new File[files.length + 1];
+						  System.arraycopy(files, 0, temp, 0, files.length);
+						  temp[files.length] = collection_file;
+						  files = temp;
+						  temp = null;
+					 }
+					 collection_file = null;
+					 name = null;
+				}
+				gimport_dir_file = null;
+				import_dir_file = null;
+				collect_cfg_file = null;
+				return files;
+		  }
+	 }
+
+	 /** A FileView which returns differing icons depending on whether a lock file is present within the collection folder. */
+	 private class GathererFileView
+		  extends FileView {
+		  public String getDescription(File file) {
+				String description = null;
+				if(file.getName().endsWith(".col")) {
+					 if(!lockExists(file)) {
+						  Gatherer.dictionary.get("OpenCollectionDialog.Normal_Collection");
+					 }
+					 else {
+						  Gatherer.dictionary.get("OpenCollectionDialog.Locked_Collection");
+					 }
+				}
+				return description;
+		  }
+		  public Icon getIcon(File file) {
+				Icon icon = null;
+				if(file.getName().endsWith(".col")) {
+					 if(!lockExists(file)) {
+						  icon = NORMAL_COLLECTION_ICON;
+					 }
+					 else {
+						  icon = LOCKED_COLLECTION_ICON;
+					 }
+				}
+				return icon;
+		  }
+		  /** Determine if a lock file exists. */
+		  private boolean lockExists(File file) {
+				File lock_file = new File(file.getParentFile(), CollectionManager.LOCK_FILE);
+				return lock_file.exists();
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/OptionsBox.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/OptionsBox.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/OptionsBox.java	(revision 13666)
@@ -0,0 +1,262 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import org.greenstone.gatherer.Gatherer;
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class OptionsBox
+	 extends JDialog
+	 implements ActionListener, FocusListener {
+
+	 private JButton cancel_button;
+	 private JButton establish_connection;
+	 private JButton ok_button;
+
+	 private JCheckBox use_colours;
+	 private JCheckBox use_proxy;
+
+	 private JLabel proxy_host_label;
+	 private JLabel proxy_port_label;
+
+	 private JTabbedPane tab_pane;
+
+	 private JTextField proxy_host;
+	 private JTextField proxy_port;
+
+	 private JPanel button_pane;
+	 private JPanel connection_pane;
+	 private JPanel content_pane;
+	 private JPanel download_pane;
+	 private JPanel general_pane;
+	 private JPanel proxy_pane;
+	 private JPanel proxy_host_pane;
+	 private JPanel proxy_port_pane;
+
+	 static final private Dimension SIZE = new Dimension(400,300);
+
+	 public OptionsBox() {
+		  super(Gatherer.g_man);
+
+		  this.setModal(true);
+		  this.setTitle(get("Title"));
+		  this.setSize(SIZE);
+
+		  content_pane = (JPanel) this.getContentPane();
+		  content_pane.setLayout(new BorderLayout());
+		  content_pane.setMinimumSize(this.getSize());
+		  content_pane.setSize(this.getSize());
+		  content_pane.setMaximumSize(this.getSize());
+
+		  tab_pane = new JTabbedPane();
+
+		  tab_pane.add(get("General"), buildGeneral());
+		  if(!Gatherer.config.get("workflow.mirror", true)) {
+				tab_pane.add(get("Connection"), buildConnection());
+				tab_pane.add(get("Download"), buildDownload());
+		  }
+
+		  button_pane = new JPanel(new GridLayout(1,2));
+		  button_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+
+		  cancel_button = new JButton(get("General.Cancel"));
+		  cancel_button.addActionListener(this);
+
+		  ok_button = new JButton(get("General.OK"));
+		  ok_button.addActionListener(this);
+
+		  // Add components.
+		  content_pane.add(tab_pane, BorderLayout.CENTER);
+		  button_pane.add(ok_button);
+		  button_pane.add(cancel_button);
+		  content_pane.add(button_pane, BorderLayout.SOUTH);
+
+		  // Final dialog setup & positioning.
+		  // Position the window.
+		  Dimension screen_size = Gatherer.config.screen_size;
+		  setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+		  show();
+	 }
+
+	 public void actionPerformed(ActionEvent event) {
+		  Object esrc = event.getSource();
+		  // OK - Save all settings.
+		  if(esrc == ok_button) {
+				// Update config
+				this.dispose();
+		  }
+		  // Cancel - Ignore settings and close.
+		  else if(esrc == cancel_button) {
+				this.dispose();
+		  }
+		  else if(esrc == use_proxy) {
+				Gatherer.config.set("general.use_proxy", true, use_proxy.isSelected());
+				proxy_host.setEnabled(use_proxy.isSelected());
+				proxy_port.setEnabled(use_proxy.isSelected());
+				establish_connection.setEnabled(use_proxy.isSelected());
+		  }
+		  else if(esrc == establish_connection) {
+				if(use_proxy.isSelected()) {
+					 Gatherer.config.setString("general.proxy_host", true, proxy_host.getText());
+					 Gatherer.config.setString("general.proxy_port", true, proxy_port.getText());
+					 Gatherer.self.setProxy();
+				}
+		  }
+	 }
+
+	 public JPanel buildGeneral() {
+		  general_pane = new JPanel(new GridLayout(2,1));
+		  JPanel color_pane = new JPanel();
+		  use_colours = new JCheckBox(get("Use_Colours"));
+		  // Connection
+		  use_colours.addActionListener(this);
+		  // Layout
+		  color_pane.add(use_colours);
+
+		  general_pane.add(color_pane);
+		  return general_pane;
+	 }
+
+	 public JPanel buildConnection() {
+		  connection_pane = new JPanel(new BorderLayout());
+
+		  proxy_pane = new JPanel(new GridLayout(4,1));
+		  proxy_pane.setBorder(BorderFactory.createTitledBorder(
+			   BorderFactory.createBevelBorder(BevelBorder.LOWERED), 
+				get("Proxy_Configuration")));
+
+		  use_proxy = new JCheckBox(get("Use_Proxy"));
+		  use_proxy.addActionListener(this);
+
+		  establish_connection = new JButton(get("Establish_Connection"));
+		  establish_connection.addActionListener(this);
+
+		  proxy_host_pane = new JPanel(new BorderLayout());
+		  proxy_host_label = new JLabel(get("Proxy_Host"));
+
+		  proxy_port_pane = new JPanel(new BorderLayout());
+		  proxy_port_label = new JLabel(get("Proxy_Port"));
+
+		  if(Gatherer.config.get("general.use_proxy", true)) {
+				use_proxy.setSelected(true);
+
+				proxy_host = new JTextField(Gatherer.config.getString("general.proxy_host", true));
+				proxy_port = new JTextField(Gatherer.config.getString("general.proxy_port", true));
+		  }
+		  else {
+				use_proxy.setSelected(false);
+				proxy_host = new JTextField();
+				proxy_host.setEnabled(false);
+				proxy_port = new JTextField();
+				proxy_port.setEnabled(false);
+
+				establish_connection.setEnabled(false);
+		  }
+
+		  proxy_host.setColumns(40);
+
+		  proxy_host.addActionListener(this);
+		  proxy_host.addFocusListener(this);
+		  proxy_port.addActionListener(this);
+		  proxy_port.addFocusListener(this);
+
+		  // Add lowest layer components
+		  proxy_host_pane.add(proxy_host_label, BorderLayout.WEST);
+		  proxy_host_pane.add(proxy_host, BorderLayout.CENTER);
+
+		  proxy_port_pane.add(proxy_port_label, BorderLayout.WEST);
+		  proxy_port_pane.add(proxy_port, BorderLayout.CENTER);
+
+		  // Add components
+		  proxy_pane.add(use_proxy);
+		  proxy_pane.add(proxy_host_pane);
+		  proxy_pane.add(proxy_port_pane);
+		  proxy_pane.add(establish_connection);
+
+		  // Add to higher layer.
+		  connection_pane.add(proxy_pane, BorderLayout.CENTER);
+
+		  return connection_pane;
+	 }
+
+	 public JPanel buildDownload() {
+		  download_pane = new JPanel(new BorderLayout());
+		  return download_pane;
+	 }
+
+	 public void destroy() {
+		  cancel_button = null;
+		  establish_connection = null;
+		  ok_button = null;
+		  use_colours = null;
+		  use_proxy = null;
+		  proxy_host_label = null;
+		  proxy_port_label = null;
+		  tab_pane = null;
+		  proxy_host = null;
+		  proxy_port = null;
+		  button_pane = null;
+		  connection_pane = null;
+		  content_pane = null;
+		  download_pane = null;
+		  general_pane = null;
+		  proxy_pane = null;
+		  proxy_host_pane = null;
+		  proxy_port_pane = null;	  
+	 }
+
+	 // We have to trap focus changes and change them into action events.
+	 public void focusGained(FocusEvent e) {
+	 }
+	 
+	 public void focusLost(FocusEvent event) {
+		  actionPerformed(new ActionEvent(event.getSource(), event.getID(), ""));
+	 }
+	 
+	 private String get(String key) {
+		  if(key.indexOf(".") == -1) {
+				key = "Options." + key;
+		  }
+		  return Gatherer.dictionary.get(key);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/OptionsPane.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/OptionsPane.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/OptionsPane.java	(revision 13666)
@@ -0,0 +1,464 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.Argument;
+import org.greenstone.gatherer.checklist.CheckList;
+import org.greenstone.gatherer.collection.BuildOptions;
+import org.greenstone.gatherer.collection.Collection;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.util.Utility;
+import org.w3c.dom.*;
+/** 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
+ */
+final public class OptionsPane
+	 extends JPanel {
+	 /** The <strong>BuildOptions</strong> data object contains all the option settings we wish to persist between Gatherer sessions (and thus is stored in <strong>Collection</strong>). */
+	 private BuildOptions build_options = null;
+	 /** This <strong>JPanel</strong> is used to display the varying options panes. */
+	 private JPanel target_pane = null;
+	 /** All process messages are written to this log text area. */
+	 private JTextArea log = null;
+	 static private int BUILD = 0;
+	 static private int IMPORT = 1;
+	 static private Dimension LABEL_SIZE = new Dimension(180, 25);
+	 static private Dimension LOG_SIZE = new Dimension(610, 360);
+	 /** The minimum size of a options pane, to prevent refresh problems around the bottom of shorter panes. */
+	 static private Dimension PANE_SIZE = new Dimension(610, 350);
+	 static private Dimension ROW_SIZE = new Dimension(610, 25);
+	 static private Dimension SPINNER_SIZE = new Dimension(100, 25);
+	 static private String DESCRIPTION_SEP = " + ";
+	 /** 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(JPanel target_pane, JTextArea log, BuildOptions build_options) {
+		  this.log = log;
+		  this.build_options = build_options;
+		  this.target_pane = target_pane;
+	 }
+	 /** This method creates the panel with all the build only options on it.
+	  * @return A <strong>JPanel</strong> which can be used to display all the build only options.
+	  */
+	 public JPanel buildBuild() {
+		  JPanel pane = new JPanel();
+		  pane.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+ 		  int build_argument_count = build_options.getBuildArgumentCount();
+		  pane.setLayout(new GridLayout(build_argument_count, 1, 0, 0));
+		  int total_height = PANE_SIZE.height;
+		  for(int i = 0; i < build_argument_count; i++) {
+				// Retrieve the argument so we know how to format the control.
+				Argument argument = build_options.getBuildArgument(i);
+				// Now attempt to retrieve any existing value for this argument.
+				boolean enabled = build_options.getBuildValueEnabled(argument.getName());
+				String value = build_options.getBuildValue(argument.getName());
+				ArgumentControl argument_control = new ArgumentControl(BUILD, argument, enabled, value);
+				total_height = total_height - argument_control.getPreferredSize().height;
+				pane.add(argument_control);
+		  }
+		  if(total_height > 0) {
+				JPanel filler = new JPanel();
+				filler.setPreferredSize(new Dimension(100, total_height));
+				filler.setSize(filler.getPreferredSize());
+				pane.add(filler);
+		  }
+		  return pane;
+	 }  
+	 /** This method creates the panel with all the import only options on it.
+	  * @return A <strong>JPanel</strong> which can be used to display all the import only options.
+	  */
+	 public JPanel buildImport() {
+		  JPanel pane = new JPanel();
+		  pane.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		  int import_argument_count = build_options.getImportArgumentCount();
+		  pane.setLayout(new GridLayout(import_argument_count, 1, 0, 0));
+		  int total_height = PANE_SIZE.height;
+		  for(int i = 0; i < import_argument_count; i++) {
+				// Retrieve the argument so we know how to format the control.
+				Argument argument = build_options.getImportArgument(i);
+				// Now attempt to retrieve any existing value for this argument.
+				boolean enabled = build_options.getImportValueEnabled(argument.getName());
+				String value = build_options.getImportValue(argument.getName());
+				ArgumentControl argument_control = new ArgumentControl(IMPORT, argument, enabled, value);
+				total_height = total_height - argument_control.getPreferredSize().height;
+				pane.add(argument_control);
+		  }
+		  if(total_height > 0) {
+				JPanel filler = new JPanel();
+				filler.setPreferredSize(new Dimension(100, total_height));
+				filler.setSize(filler.getPreferredSize());
+				pane.add(filler);
+		  }
+		  return pane;
+	 }
+	 /** This method is used to build a panel based on the message log, which is nothing like any of the other panel.
+	  * @return A <strong>JPanel</strong> containing a scrollable text area which represents the shell process message log.
+	  */
+ 	 public JPanel buildLog() {
+		  JPanel pane = new JPanel(new BorderLayout());
+		  /*
+		  // Build a list of the log files available, ordering by last modified. Log files end .log (duh!)
+		  DefaultComboBoxModel model = new DefaultComboBoxModel();
+		  File etc_directory = new File(gatherer.c_man.getCollectionEtc());
+		  File children[] = etc_directory.listFiles();
+		  for(int i = 0; children != null && i < children.length; i++) {
+				if(children[i].getName().endsWith(".log")) {
+					 FileEntry entry = new FileEntry(children[i]);
+					 // We are about to insert it. But where.
+					 boolean found = false;
+					 for(int j = 0; j < model.getSize(); j++) {
+						  FileEntry sibling = (FileEntry) model.getElementAt(i);
+						  int order = entry.compareTo(sibling);
+						  if(order < 0) {
+								model.insertElementAt(entry, j);
+								found = true;
+						  }
+					 }
+					 if(!found) {
+						  model.addElement(entry);
+					 }
+				}
+		  }
+		  JComboBox logs_box = new JComboBox(model);
+		  // If log is empty, reload the most recent log.
+		  if(log.getText().length() == 0 && model.getSize() > 0) {
+				loadLog(model.getElementAt(0));
+		  }
+		  */
+		  pane.add(log, BorderLayout.CENTER);
+		  //pane.add(logs_box, BorderLayout.SOUTH);
+		  return pane;
+	 }
+	 /** 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;
+	 }
+	
+	 public void saveLog() {
+		  /*
+		  try {
+				long name_long = System.currentTimeMillis();
+				String name = name_long + ".log";
+				File;
+				FileOutputStream fos = new FileOutputStream(file);
+		  }
+		  catch(Exception error) {
+		  }
+		  */
+	 }
+
+	 /** Given a panel containing ArgumentControls, update the values associated with them. */
+	 public void update(JPanel panel) {
+		  for(int i = 0; i < panel.getComponentCount(); i++) {
+				Component component = panel.getComponent(i);
+				if(component instanceof ArgumentControl) {
+					 ((ArgumentControl)component).update();
+				}
+		  }
+	 }
+
+	 private class ArgumentControl
+		  extends JPanel {
+		  private Argument argument;
+		  private int type;
+		  private JComponent value_control;
+		  private JCheckBox enabled;
+		  public ArgumentControl(int type, Argument argument, boolean enable, String value) {
+				super();
+				this.argument = argument;
+				this.type = type;
+				String tooltip = Utility.formatHTMLWidth("<html>" + argument.getDesc() + "</html>", 60);
+				// Because of the dynamic order of component creation/connection/layout, we can't really follow that pattern here.
+				setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
+				setLayout(new BorderLayout());
+				setPreferredSize(ROW_SIZE);
+
+				/*
+				JPanel inner_pane = new JPanel();
+				inner_pane.setOpaque(false);
+				*/
+
+				// Try to determine what the value_controls value should be.
+				if(value == null) {
+					 value = argument.getDefaultValue();
+				}
+				// Create a correct value control based on the argument provided.
+				switch(argument.getType()) {
+				case Argument.ENUM:
+					 JComboBox combobox = new JComboBox();
+					 combobox.setEnabled(enable);
+					 combobox.setToolTipText(tooltip);
+					 // Set enabled
+					 if(enable) {
+						  combobox.setBackground(Color.white);
+					 }
+					 else {
+						  combobox.setBackground(Color.lightGray);
+					 }
+					 // Build an option model, wrapping each entry of the list table.
+					 HashMap arg_list = argument.getList();
+					 Iterator it = arg_list.keySet().iterator();
+					 while(it.hasNext()) {
+						  combobox.addItem((String) it.next());
+					 }
+					 // Connect this up first, so that if a value is selected the tooltip updates accordingly.
+					 combobox.addActionListener(new ToolTipUpdater(arg_list));
+					 if(value != null) {
+						  // Set the selected string. However since they are all strings we had best iterate ourselves.
+						  for(int i = 0; i < combobox.getItemCount(); i++) {
+								if(combobox.getItemAt(i).toString().equals(value)) {
+									 combobox.setSelectedIndex(i);
+								}
+						  }
+					 }
+					 // Layout
+					 add(combobox, BorderLayout.CENTER);
+					 // And remember
+					 value_control = combobox;
+					 break;
+				case Argument.FLAG:
+					 // Only need the check box.
+					 value_control = null;
+					 break;
+				case Argument.INTEGER:
+					 // Build a spinner
+					 JSpinner spinner = new JSpinner();
+					 spinner.setEnabled(enable);
+					 spinner.setPreferredSize(SPINNER_SIZE);
+					 spinner.setToolTipText(tooltip);
+					 // Set enabled
+					 JComponent c = spinner.getEditor();
+					 if ( c instanceof JSpinner.DefaultEditor ) {
+						  JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) c;
+						  JFormattedTextField field = editor.getTextField();
+						  field.setEditable(enable);
+						  if(enable) {
+								field.setBackground(Color.white);
+						  }
+						  else {
+								field.setBackground(Color.lightGray);
+						  }
+					 }
+					 // If there was an original value, set it.
+					 if(value != null) {
+						  try {
+								spinner.setValue(new Integer(value));
+						  }
+						  catch (Exception error) {
+						  }
+					 }
+					 // Layout
+					 add(new JLabel(), BorderLayout.CENTER);
+					 add(spinner, BorderLayout.EAST);
+					 // And remember it
+					 value_control = spinner;
+					 break;
+				case Argument.STRING:
+					 // Use a standard text field
+					 JTextField textfield = new JTextField();
+					 textfield.setEnabled(enable);
+					 textfield.setToolTipText(tooltip);
+					 // Set enabled
+					 if(enable) {
+						  textfield.setBackground(Color.white);
+					 }
+					 else {
+						  textfield.setBackground(Color.lightGray);
+					 }
+					 // If there was an original value, set it.
+					 if(value != null) {
+						  textfield.setText(value);
+					 }
+					 // Layout
+					 add(textfield, BorderLayout.CENTER);
+					 // And remember it
+					 value_control = textfield;
+					 break;
+				}
+
+				// If the argument is required, then you don't get a choice of whether it is enabled.
+				if(argument.isRequired()) {
+					 JLabel label = new JLabel(argument.getName());
+					 label.setOpaque(false);
+					 label.setPreferredSize(LABEL_SIZE);
+					 label.setToolTipText(tooltip);
+					 add(label, BorderLayout.WEST);
+				}
+				else {
+					 enabled = new JCheckBox(argument.getName(), enable);
+					 enabled.setOpaque(false);
+					 enabled.setPreferredSize(LABEL_SIZE);
+					 enabled.setToolTipText(tooltip);
+					 // Connect
+					 enabled.addActionListener(new EnabledListener(value_control));
+					 // Layout
+					 add(enabled, BorderLayout.WEST);
+				}
+		  }
+
+		  /** Update the values stored in the collection so as to rememebr the current state of this argument. */
+		  public void update() {
+				String name = argument.getName();
+				boolean enable = true;
+				if(enabled != null) {
+					 enable = enabled.isSelected();
+				}
+				String value = null;
+				if(value_control == null) {
+					 // Flag value, nothing to do.
+				}
+				else if(value_control instanceof JTextField) {
+					 value = ((JTextField)value_control).getText();
+				}
+				else if(value_control instanceof JSpinner) {
+					 value = ((JSpinner)value_control).getValue().toString();
+				}
+				else if(value_control instanceof JComboBox) {
+					 value = (String) ((JComboBox)value_control).getSelectedItem();
+				}
+				// 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.removeBuildValue(name);
+					 }
+					 else {
+						  build_options.removeImportValue(name);
+					 }
+				}
+				// Otherwise update the argument value
+				else {
+					 if(type == BUILD) {
+						  build_options.setBuildValue(name, enable, value);
+					 }
+					 else {
+						  build_options.setImportValue(name, enable, value);
+					 }
+				}
+		  }
+	 }
+
+	 /** 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) {
+				JCheckBox source = (JCheckBox)event.getSource();
+				if(target != null) {
+					 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 {
+		  private HashMap arg_list;
+		  public ToolTipUpdater(HashMap arg_list) {
+				this.arg_list = arg_list;
+		  }
+		  /** 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();
+				String key = (String) source.getSelectedItem();
+				if(arg_list != null) {
+					 String description = (String) arg_list.get(key);
+					 if(description != null) {
+						  description = Utility.formatHTMLWidth(DESCRIPTION_SEP + description, 60);
+						  String original = source.getToolTipText();
+						  if(original == null) {
+								original = "";
+						  }
+						  // Remove any existing extra description.
+						  if(original.indexOf(DESCRIPTION_SEP) != -1) {
+								original = original.substring(0, original.indexOf(DESCRIPTION_SEP));
+						  }
+						  source.setToolTipText(original + description);
+					 }
+				}
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/Preferences.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/Preferences.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/Preferences.java	(revision 13666)
@@ -0,0 +1,375 @@
+package org.greenstone.gatherer.gui;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.checklist.CheckList;
+import org.greenstone.gatherer.checklist.Entry;
+import org.greenstone.gatherer.gui.GUIManager;
+import org.greenstone.gatherer.gui.NumberField;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.XORToggleButtonGroup;
+import org.w3c.dom.*;
+
+public class Preferences
+	 extends JDialog {
+
+	 private CheckList warning_preferences_check_list;
+	 private JButton apply_button;
+	 private JButton cancel_button;
+	 private JButton ok_button;
+	 private JCheckBox use_proxy_checkbox;
+	 private JCheckBox workflow_browse;
+	 private JCheckBox workflow_create;
+	 private JCheckBox workflow_mirror;
+	 private JCheckBox workflow_gather;
+	 private JCheckBox workflow_enrich;
+	 private JCheckBox workflow_design;
+	 private JCheckBox workflow_export;
+	 private JCheckBox workflow_preview;
+	 private JTabbedPane tab_pane;
+	 private JTextField proxy_host_field;
+	 private JTextField proxy_port_field;
+	 private Preferences self;
+
+	 static final Dimension LABEL_SIZE = new Dimension(100, 25);
+	 static final Dimension ROW_SIZE = new Dimension(380, 25);
+	 static final Dimension SIZE = new Dimension(400, 320);
+	 static final String TRUE = "true";
+
+	 public Preferences() {
+		  // Initialize
+		  super(Gatherer.g_man, true);
+		  this.self = this;
+		  setSize(SIZE);
+		  setTitle("Preferences");
+		  // Creation
+		  JPanel content_pane = (JPanel) getContentPane();
+		  tab_pane = new JTabbedPane();
+		  tab_pane.add("Preferences.Workflow", createWorkflowPreferences());
+		  tab_pane.add("Preferences.Connection", createConnectionPreferences());
+		  tab_pane.add("Preferences.Warnings", createWarningPreferences());
+
+		  JPanel button_pane = new JPanel();
+		  ok_button = new JButton("General.OK");
+		  apply_button = new JButton("General.Apply");
+		  cancel_button = new JButton("General.Cancel");
+		  // Connection
+		  Gatherer.dictionary.register(this, null, false);
+		  Gatherer.dictionary.register(tab_pane, null, false);
+		  Gatherer.dictionary.register(ok_button, null, false);
+		  Gatherer.dictionary.register(apply_button, null, false);
+		  Gatherer.dictionary.register(cancel_button, null, false);
+		  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_location.x + ((frame_size.width - SIZE.width) / 2), frame_location.y + ((frame_size.height - SIZE.height)));
+		  setLocation(((frame_size.width - SIZE.width) / 2), ((frame_size.height - SIZE.height)));
+
+		  // Clean up
+		  frame_location = null;
+		  frame_size = null;
+		  cancel_button = null;
+		  ok_button = null;
+		  button_pane = null;
+		  tab_pane = null;
+		  content_pane = null;
+		  show();
+	 }
+
+	 private JPanel createConnectionPreferences() {
+		  boolean currently_enabled = Gatherer.config.get("general.use_proxy", true);
+		  // Creation
+		  JPanel connection_pane = new JPanel();
+		  use_proxy_checkbox = new JCheckBox("Preferences.Connection.Use_Proxy", 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("Preferences.Connection.Proxy_Host");
+		  proxy_host_label.setPreferredSize(LABEL_SIZE);
+		  proxy_host_field = new JTextField(Gatherer.config.getString("general.proxy_host", true));
+		  proxy_host_field.setEnabled(currently_enabled);
+		  JPanel proxy_port_pane = new JPanel();
+		  proxy_port_pane.setPreferredSize(ROW_SIZE);
+		  JLabel proxy_port_label = new JLabel("Preferences.Connection.Proxy_Port");
+		  proxy_port_label.setPreferredSize(LABEL_SIZE);
+		  proxy_port_field = new NumberField(Gatherer.config.getString("general.proxy_port", true));
+		  proxy_port_field.setEnabled(currently_enabled);
+
+		  // Connection
+		  Gatherer.dictionary.register(use_proxy_checkbox, null, false);
+		  Gatherer.dictionary.register(proxy_host_label, null, false);
+		  Gatherer.dictionary.register(proxy_port_label, null, false);
+		  use_proxy_checkbox.addActionListener(new UseProxyListener());
+		  // Layout
+		  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.add(use_proxy_checkbox);
+		  connection_pane.add(proxy_host_pane);
+		  connection_pane.add(proxy_port_pane);
+
+		  return connection_pane;
+	 }
+
+	 /** The warning preferences are controlled through a checklist. */
+	 private JPanel createWarningPreferences() {
+		  // Retrieve all of the warning preferences settings.
+		  HashMap warning_preferences = Gatherer.config.getAll("warning\\..*", true);
+		  warning_preferences_check_list = new CheckList();
+		  for(Iterator keys = warning_preferences.keySet().iterator(); keys.hasNext(); ) {
+				String property = (String) keys.next();
+				String value = (String) warning_preferences.get(property);
+				// Remove 'warning.'
+				String title = Gatherer.dictionary.get(property.substring(8) + ".Title");
+				Entry entry = new Entry(title, value.equalsIgnoreCase(TRUE));
+				entry.setProperty(property);
+				warning_preferences_check_list.addEntry(entry);
+		  }
+		  // Creation
+		  JPanel warning_preferences_pane = new JPanel();
+		  // Connection
+		  // Layout
+		  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 = Utility.parse("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("Preferences.Workflow.Title");
+		  title_label.setPreferredSize(ROW_SIZE);
+		  XORToggleButtonGroup checkbox_group = new XORToggleButtonGroup();
+		  workflow_browse  = new JCheckBox("Preferences.Workflow.Browse",  Gatherer.config.get("workflow.browse", false));
+		  workflow_browse.setPreferredSize(ROW_SIZE);
+		  workflow_mirror  = new JCheckBox("Preferences.Workflow.Mirror",  Gatherer.config.get("workflow.mirror", false));
+		  workflow_mirror.setPreferredSize(ROW_SIZE);
+		  workflow_gather  = new JCheckBox("Preferences.Workflow.Gather",  Gatherer.config.get("workflow.gather", false));
+		  workflow_gather.setPreferredSize(ROW_SIZE);
+		  workflow_enrich  = new JCheckBox("Preferences.Workflow.Enrich",  Gatherer.config.get("workflow.enrich", false));
+		  workflow_enrich.setPreferredSize(ROW_SIZE);
+		  workflow_design  = new JCheckBox("Preferences.Workflow.Design",  Gatherer.config.get("workflow.design", false));
+		  workflow_design.setPreferredSize(ROW_SIZE);
+		  workflow_export  = new JCheckBox("Preferences.Workflow.Export",  Gatherer.config.get("workflow.export", false));
+		  workflow_export.setPreferredSize(ROW_SIZE);
+		  workflow_create  = new JCheckBox("Preferences.Workflow.Create",  Gatherer.config.get("workflow.create", false));
+		  workflow_create.setPreferredSize(ROW_SIZE);
+		  workflow_preview = new JCheckBox("Preferences.Workflow.Preview", Gatherer.config.get("workflow.preview", false));
+		  workflow_preview.setPreferredSize(ROW_SIZE);
+		  JPanel predefined_pane = new JPanel();
+		  JLabel predefined_label = new JLabel("Preferences.Workflow.Predefined.Label");
+		  predefined_label.setPreferredSize(new Dimension(150,25));
+		  JComboBox predefined_combobox = new JComboBox(predefined);
+		  // Connection
+		  checkbox_group.add(workflow_mirror);
+		  checkbox_group.add(workflow_gather);
+		  checkbox_group.add(workflow_enrich);
+		  checkbox_group.add(workflow_design);
+		  checkbox_group.add(workflow_export);
+		  checkbox_group.add(workflow_create);
+		  checkbox_group.add(workflow_preview);
+		  Gatherer.dictionary.register(title_label, null, false);
+		  Gatherer.dictionary.register(workflow_browse, null, false);
+		  Gatherer.dictionary.register(workflow_mirror, null, false);
+		  Gatherer.dictionary.register(workflow_gather, null, false);
+		  Gatherer.dictionary.register(workflow_enrich, null, false);
+		  Gatherer.dictionary.register(workflow_design, null, false);
+		  Gatherer.dictionary.register(workflow_export, null, false);
+		  Gatherer.dictionary.register(workflow_create, null, false);
+		  Gatherer.dictionary.register(workflow_preview, null, false);
+		  Gatherer.dictionary.register(predefined_label, null, false);
+		  predefined_combobox.addActionListener(new PredefinedActionListener());
+		  // Layout
+		  checklist_pane.setLayout(new BoxLayout(checklist_pane, BoxLayout.Y_AXIS));
+		  checklist_pane.add(title_label);
+		  if(Gatherer.config.get("workflow.browse", true)) {
+				checklist_pane.add(workflow_browse);
+		  }
+		  if(Gatherer.config.get("workflow.mirror", true)) {
+				checklist_pane.add(workflow_mirror);
+		  }
+		  if(Gatherer.config.get("workflow.gather", true)) {
+				checklist_pane.add(workflow_gather);
+		  }
+		  if(Gatherer.config.get("workflow.enrich", true)) {
+				checklist_pane.add(workflow_enrich);
+		  }
+		  if(Gatherer.config.get("workflow.design", true)) {
+				checklist_pane.add(workflow_design);
+		  }
+		  if(Gatherer.config.get("workflow.export", true)) {
+				checklist_pane.add(workflow_export);
+		  }
+		  if(Gatherer.config.get("workflow.create", true)) {
+				checklist_pane.add(workflow_create);
+		  }
+		  if(Gatherer.config.get("workflow.preview", true)) {
+				checklist_pane.add(workflow_preview);
+		  }
+		  predefined_pane.setLayout(new BorderLayout());
+		  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;
+	 }
+
+	 public void dispose() {
+		  // Deregister dictionary components
+		  Gatherer.dictionary.deregister(this);
+		  Gatherer.dictionary.deregister(tab_pane);
+		  Gatherer.dictionary.deregister(ok_button);
+		  Gatherer.dictionary.deregister(apply_button);
+		  Gatherer.dictionary.deregister(cancel_button);
+		  // Dispose
+		  super.dispose();
+	 }
+
+	 private class OKButtonListener
+		  implements ActionListener {
+		  private boolean close;
+		  public OKButtonListener(boolean close) {
+				this.close = close;
+		  }
+		  public void actionPerformed(ActionEvent event) {
+				// Submit the various changes.
+				// Connection preferences
+				Gatherer.config.set("general.use_proxy", true, use_proxy_checkbox.isSelected());
+				Gatherer.config.setString("general.proxy_host", true, proxy_host_field.getText());
+				Gatherer.config.setString("general.proxy_port", true, proxy_port_field.getText());
+				Gatherer.setProxy();
+				// Warning preferences
+				for(int i = 0; i < warning_preferences_check_list.getEntryCount(); i++) {
+					 Entry entry = warning_preferences_check_list.get(i);
+					 Gatherer.config.set(entry.getProperty(), true, entry.isSelected());
+				}
+				// Workflow preferences
+				Gatherer.config.set("workflow.browse", false, workflow_browse.isSelected());
+				Gatherer.config.set("workflow.mirror", false, workflow_mirror.isSelected());
+				Gatherer.config.set("workflow.gather", false, workflow_gather.isSelected());
+				Gatherer.config.set("workflow.enrich", false, workflow_enrich.isSelected());
+				Gatherer.config.set("workflow.design", false, workflow_design.isSelected());
+				Gatherer.config.set("workflow.export", false, workflow_export.isSelected());
+				Gatherer.config.set("workflow.create", false, workflow_create.isSelected());
+				Gatherer.config.set("workflow.preview", false, workflow_preview.isSelected());
+				Gatherer.g_man.workflowUpdate("Browser", workflow_browse.isSelected());
+				Gatherer.g_man.workflowUpdate("Mirroring", workflow_mirror.isSelected());
+				Gatherer.g_man.workflowUpdate("Collection", workflow_gather.isSelected());
+				Gatherer.g_man.workflowUpdate("MetaEdit", workflow_enrich.isSelected());
+				Gatherer.g_man.workflowUpdate("Build", workflow_design.isSelected());
+				Gatherer.g_man.workflowUpdate("Export", workflow_export.isSelected());
+				Gatherer.g_man.workflowUpdate("Create", workflow_create.isSelected());
+				Gatherer.g_man.workflowUpdate("Preview", workflow_preview.isSelected());
+				// Hide dialog
+				if(close) {
+					 self.dispose();
+				}
+		  }
+	 }
+
+	 private class CancelButtonListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				self.dispose();
+		  }
+	 }
+
+	 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_browse.setSelected(element.getEnabled("browse"));
+					 workflow_create.setSelected(element.getEnabled("create"));
+					 workflow_mirror.setSelected(element.getEnabled("mirror"));
+					 workflow_gather.setSelected(element.getEnabled("gather"));
+					 workflow_enrich.setSelected(element.getEnabled("enrich"));
+					 workflow_design.setSelected(element.getEnabled("design"));
+					 workflow_export.setSelected(element.getEnabled("export"));
+					 workflow_preview.setSelected(element.getEnabled("preview"));			
+				}
+		  }
+	 }
+
+	 private class UseProxyListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				boolean enabled = use_proxy_checkbox.isSelected();
+				Gatherer.config.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 = element.getFirstChild().getNodeValue(); 
+				}
+				return text;
+		  }
+	 }
+}
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/PreviewPane.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/PreviewPane.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/PreviewPane.java	(revision 13666)
@@ -0,0 +1,248 @@
+package org.greenstone.gatherer.gui;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import calpa.html.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.net.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.util.GURL;
+import org.greenstone.gatherer.util.Utility;
+
+public class PreviewPane 
+	 extends JPanel {
+	 
+	 private CalHTMLPane view   = null;
+	 private int back_count     = 0;
+	 private int forward_count  = 0;
+	 private JButton back       = null;
+	 private JButton forward    = null;
+	 private JButton home       = null;
+	 private JButton reload = null;
+	 private JLabel status      = null;
+	 private String args[]      = null;
+	 private String current_url = null;
+	 private String page_showing = null;
+	 private URL homepage       = null;
+
+	 public PreviewPane() {
+		  // Create components
+		  back = new JButton(get("Back"), Utility.getImage("back.gif"));
+		  back.addActionListener(new BackListener());
+		  back.setEnabled(false);
+
+		  home = new JButton(get("Home"), Utility.getImage("home.gif"));
+		  home.addActionListener(new HomeListener());
+		  home.setEnabled(false);
+
+		  forward = new JButton(get("Forward"), Utility.getImage("forward.gif"));
+		  forward.addActionListener(new ForwardListener());
+		  forward.setEnabled(false);
+
+		  reload = new JButton(get("Reload"), Utility.getImage("reload.gif"));
+		  reload.addActionListener(new ReloadListener());
+		  reload.setEnabled(false);
+
+		  CalHTMLPreferences prefs = new CalHTMLPreferences();
+		  Observer observer = new Observer();
+		  view = new CalHTMLPane(prefs, observer, "Default");
+		  //view.setSize(new Dimension(770, 440));
+
+		  status = new JLabel(get("Ready"));
+	 }
+	 
+	 public void collectionChanged(boolean ready) {
+		  if(ready && Gatherer.c_man.built()) {
+				String url = Gatherer.config.exec_path + "?a=p&p=about&c=" + Gatherer.c_man.getCollection().getName();
+				Gatherer.println("Loading " + url);
+				args = new String[1];
+				args[0] = url;
+				status.setText(get("Loading", args));
+				args = null;
+				view.showHTMLDocument((new GURL(url)).getURL());				
+		  }
+		  validate();
+	 }
+
+	 public void display() {
+		  JPanel control_pane = new JPanel();
+		  control_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+		  control_pane.setLayout(new GridLayout(1,4));
+		  control_pane.add(back);
+		  control_pane.add(reload);
+		  control_pane.add(home);
+		  control_pane.add(forward);
+
+		  JPanel a_panel = new JPanel(new BorderLayout());
+		  a_panel.setSize(new Dimension(770, 440));
+		  a_panel.add(view, BorderLayout.CENTER);
+
+		  setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
+		  setLayout(new BorderLayout());
+		  add(control_pane, BorderLayout.NORTH);
+		  add(a_panel, BorderLayout.CENTER);
+		  add(status, BorderLayout.SOUTH);
+	 }
+
+	 /** This method is called when the user selects the 'Preview' tab from the views bar. Can be used to display a particular page or perform some other relevant tests (ensure internet connection to specified server maybe?)
+	  */
+	 public void gainFocus() {
+		  if(Gatherer.c_man.ready() && Gatherer.c_man.built()) {
+				String url = Gatherer.config.exec_path + "?a=p&p=about&c=" + Gatherer.c_man.getCollection().getName();
+				if(page_showing != null && page_showing.equals(url)) {
+					 view.reloadDocument();
+				}
+				else {
+					 Gatherer.println("Loading " + url);
+					 args = new String[1];
+					 args[0] = url;
+					 status.setText(get("Loading", args));
+					 args = null;
+					 view.showHTMLDocument((new GURL(url)).getURL());
+					 page_showing = url;
+					 homepage = (new GURL(url)).getURL();
+				}
+		  }
+		  validate();
+	 }
+
+	 /** Used to retrieve the phrase that matches the given key from the loaded dictionary. 
+	  */
+	 public String get(String key) {
+		  return get(key, null);
+	 }
+
+	 public String get(String key, String args[]) {
+		  if(key.indexOf(".") == -1) {
+				key = "Browser." + key;
+		  }
+		  return Gatherer.dictionary.get(key, args);
+	 }
+
+	 public void validate() {
+		  if(back_count > 0) {
+				back.setEnabled(true);
+		  }
+		  else {
+				back.setEnabled(false);
+		  }
+		  if(homepage != null) {
+				home.setEnabled(true);
+		  }
+		  else {
+				home.setEnabled(false);
+		  }
+		  if(forward_count > 0) {
+				forward.setEnabled(true);
+		  }
+		  else {
+				forward.setEnabled(false);
+		  }
+		  reload.setEnabled(true);
+	 }
+
+	 private class BackListener 
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				view.goBack();
+				back_count--;
+				forward_count++;
+				validate();
+		  }
+	 }
+
+	 private class ForwardListener 
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				view.goForward();
+				back_count++;
+				forward_count--;
+				validate();
+		  }
+	 }
+
+	 private class HomeListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				if(homepage != null) {
+					 view.showHTMLDocument(homepage);
+					 back_count++;
+					 validate();
+				}
+		  }
+	 }
+
+	 private class ReloadListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				view.reloadDocument();
+		  }
+	 }
+
+	 private class Observer
+		  extends DefaultCalHTMLObserver {
+		  public void linkActivatedUpdate(CalHTMLPane pane, URL url, String target_frame, String j_name) {
+				if(!url.toString().equals(current_url)) {
+					 back_count++;
+					 forward_count = 0;
+					 validate();
+				}
+		  }
+		  public void linkFocusUpdate(CalHTMLPane pane, URL url) {
+				///ystem.err.println("Link in focus " + url.toString());
+				args = new String[1];
+				args[0] = url.toString();
+				status.setText(get("Follow"));
+				args = null;
+		  }
+		  public void statusUpdate(CalHTMLPane pane, int state, URL url, int value, String message) {
+				switch(state) {
+				case 11:
+					 args = new String[1];
+					 args[0] = url.toString();
+					 status.setText(get("Loading", args));
+					 args = null;
+					 break;
+				case 14:
+					 // Rendering complete.
+					 status.setText(get("Ready"));
+					 break;
+				}
+		  }
+	 }
+} 
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/SaveProgressDialog.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/SaveProgressDialog.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/SaveProgressDialog.java	(revision 13666)
@@ -0,0 +1,118 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+package org.greenstone.gatherer.gui;
+/**************************************************************************************
+ * Title:        Gatherer
+ * Description:  The Gatherer: a tool for gathering and enriching a digital collection.
+ * Company:      The University of Waikato
+ * Written:      19/09/02
+ * Revised:      
+ * @author John Thompson, 9826509
+ * @version 2.3
+ **************************************************************************************/
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.lang.Runnable;
+import java.lang.Thread;
+import javax.swing.JDialog;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+import javax.swing.SwingUtilities;
+import org.greenstone.gatherer.Gatherer;
+
+public class SaveProgressDialog
+	 extends Thread {
+	 
+	 private Gatherer gatherer;
+	 private JDialog dialog;
+	 private JProgressBar progress;
+	 static final public int METADATA = 50;
+	 static final public int COLLECTION = 40;
+	 static final public int MISC = 10;
+	 static final private Dimension SIZE = new Dimension(300,30);
+
+	 public SaveProgressDialog(Gatherer gatherer) {
+		  this.gatherer = gatherer;
+		  // Creation
+		  dialog = new JDialog();
+		  dialog.setUndecorated(true);
+		  dialog.setModal(true);
+		  dialog.setSize(SIZE);
+		  JPanel content_pane = (JPanel)dialog.getContentPane();
+		  progress = new JProgressBar();
+		  progress.setMinimum(0);
+		  progress.setMaximum(100);
+		  progress.setString(gatherer.get("SaveProgressDialog.Saving", "0"));
+		  progress.setStringPainted(true);
+		  // Layout
+		  content_pane.setLayout(new BorderLayout());
+		  content_pane.add(progress, BorderLayout.CENTER);
+		  Dimension screen_size = gatherer.config.screen_size;
+		  dialog.setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+	 }
+
+	 public void dispose() {
+		  dialog.dispose();
+	 }
+
+	 public void run() {
+		  dialog.show(); // Modal.
+	 }
+
+	 public void update(final int amount) {
+		  final JProgressBar final_progress = progress;
+		  final Runnable update = new Runnable() {
+					 public void run() {
+						  progress.setValue(final_progress.getValue() + amount);
+					 }
+				};
+		  try {
+				SwingUtilities.invokeLater(update);
+		  }
+		  catch (Exception e) {
+				gatherer.debug(e, "Error in SaveProgressDialog.update(): " + e);
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/SimpleMenuBar.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/SimpleMenuBar.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/SimpleMenuBar.java	(revision 13666)
@@ -0,0 +1,31 @@
+package org.greenstone.gatherer.gui;
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.GUIManager;
+import org.greenstone.gatherer.util.Utility;
+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(Gatherer.dictionary.get("Menu.Help"));
+		  help.setIcon(Utility.HELP_ICON);
+		  
+		  JMenuItem help_help = new JMenuItem(Gatherer.dictionary.get("Menu.Help"));
+		  help_help.addActionListener(this);
+		  
+		  help.add(help_help);
+		  
+		  add(Box.createHorizontalGlue());
+		  add(help);
+	 }
+	 
+	 public void actionPerformed(ActionEvent event) {
+		  Gatherer.g_man.help.setView(page_name);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/SmarterTable.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/SmarterTable.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/SmarterTable.java	(revision 13666)
@@ -0,0 +1,86 @@
+/**
+ *#########################################################################
+ *
+ * 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.Color;
+import java.awt.Component;
+import javax.swing.JTable;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.JTableHeader;
+import javax.swing.table.TableCellRenderer;
+import javax.swing.table.TableColumn;
+
+/** An extension of a JTable that allows for the background, foreground, heading and selection colors to be set in single actions. */
+public class SmarterTable
+	 extends JTable {
+
+	 public void setBackground(Color color) {
+		  super.setBackground(color);
+		  TableCellRenderer renderer = getDefaultRenderer(String.class);
+		  ((DefaultTableCellRenderer)renderer).setBackground(color);
+	 }
+
+	 public void setForeground(Color color) {
+		  super.setForeground(color);
+		  TableCellRenderer renderer = getDefaultRenderer(String.class);
+		  ((DefaultTableCellRenderer)renderer).setForeground(color);
+	 }
+
+	 public void setHeadingBackground(Color color) {
+		  JTableHeader header = getTableHeader();
+		  header.setBackground(color);
+	 }
+
+	 public void setHeadingForeground(Color color) {
+		  JTableHeader header = getTableHeader();
+		  header.setForeground(color);
+	 }
+
+	 public void setSelectionColor(Color color) {
+		  super.setSelectionBackground(color);
+	 }
+	 
+	 public void setSelectedTextColor(Color color) {
+		  super.setSelectionForeground(color);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/SmarterTextArea.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/SmarterTextArea.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/SmarterTextArea.java	(revision 13666)
@@ -0,0 +1,76 @@
+/**
+ *#########################################################################
+ *
+ * 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.JTextArea;
+import javax.swing.text.*;
+
+public class SmarterTextArea
+	 extends JTextArea {
+
+	 private boolean init = true;
+
+	 public SmarterTextArea() {
+		  super();
+	 }
+
+	 public SmarterTextArea(String text, boolean editable) {
+		  super();
+		  if(!editable) {
+				setDocument(new UnchangingDocument());
+		  }
+		  setText(text);
+		  init = false;
+	 }
+
+	 public int calculateColumnCount() {
+		  return (getWidth() / getColumnWidth());
+	 }
+
+	 private class UnchangingDocument 
+		  extends PlainDocument {
+		  public void insertString(int offs, String str, AttributeSet a) 
+				throws BadLocationException {
+				if(init) {
+					 super.insertString(offs, str, a);
+				}
+		  }
+		  public void remove(int offs, int len) {
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/SmarterTextField.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/SmarterTextField.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/SmarterTextField.java	(revision 13666)
@@ -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 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.JTextField;
+
+public class SmarterTextField
+	 extends JTextField {
+	 public int calculateColumnCount() {
+		  return (getWidth() / getColumnWidth());
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/SmarterTree.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/SmarterTree.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/SmarterTree.java	(revision 13666)
@@ -0,0 +1,83 @@
+/**
+ *#########################################################################
+ *
+ * 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.Color;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.TreeModel;
+
+/** An extension of a JTree that allows for the background, foreground and selection colors to be set in single actions. */
+public class SmarterTree
+	 extends JTree {
+
+	 public SmarterTree() {
+		  super();
+	 }
+
+	 public SmarterTree(TreeModel model) {
+		  super(model);
+	 }
+
+	 public void setBackground(Color color) {
+		  super.setBackground(color);
+		  if(cellRenderer != null) {
+				((DefaultTreeCellRenderer)cellRenderer).setBackgroundNonSelectionColor(color);
+		  }
+	 }
+
+	 public void setForeground(Color color) {
+		  super.setForeground(color);
+		  if(cellRenderer != null) {
+				((DefaultTreeCellRenderer)cellRenderer).setTextNonSelectionColor(color);
+		  }
+	 }
+
+	 public void setSelectionColor(Color color) {
+		  ((DefaultTreeCellRenderer)cellRenderer).setBackgroundSelectionColor(color);
+	 }
+	 
+	 public void setSelectedTextColor(Color color) {
+		  ((DefaultTreeCellRenderer)cellRenderer).setTextNonSelectionColor(color);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/SmudgyLabel.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/SmudgyLabel.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/SmudgyLabel.java	(revision 13666)
@@ -0,0 +1,83 @@
+/**
+ *#########################################################################
+ *
+ * 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.lang.Runnable;
+import javax.swing.JLabel;
+import javax.swing.SwingUtilities;
+/** Just like a JLabel, except the text shown is updated using an overwriting runnable so that updates will only occur when process load is moderate. This functionality is currently disabled as it was somehow taking 5% of copy time, and not doing what it was supposed to anyway (the same event apparently can be added to the event queue over and over). */
+public class SmudgyLabel 
+	 extends JLabel {
+	 private SmudgyUpdate update = null;
+	 public SmudgyLabel(String text) {
+		  super(text);
+	 }
+	 public void setText(String text) {
+		  super.setText(text);
+		  /*
+		  if(update == null) {
+				update = new SmudgyUpdate(text);
+		  }
+		  else {
+				update.setText(text);
+		  }
+		  SwingUtilities.invokeLater(update);
+		  */
+	 }
+	 public void setTextImmediately(String text) {
+		  super.setText(text);
+	 }
+	 private class SmudgyUpdate
+		  implements Runnable {
+		  private String text = null;
+		  public SmudgyUpdate(String text) {
+				this.text = text;
+		  }
+		  public void run() {
+				setTextImmediately(text);
+		  }
+		  public void setText(String text) {
+				this.text = text;
+		  }
+	 }
+
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/Splash.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/Splash.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/Splash.java	(revision 13666)
@@ -0,0 +1,74 @@
+/**
+ *#########################################################################
+ *
+ * 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.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Toolkit;
+import javax.swing.BorderFactory;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import org.greenstone.gatherer.util.Utility;
+final public class Splash 
+	 extends JDialog {
+	 private Dimension size = new Dimension(450,450);
+	 public Splash() {
+		  super();
+		  setSize(size);
+		  setUndecorated(true);
+		  JPanel content_pane = (JPanel) getContentPane();
+		  JLabel logo = new JLabel(Utility.getImage("gatherer.gif"));
+		  content_pane.setBorder(BorderFactory.createRaisedBevelBorder());
+		  content_pane.setLayout(new BorderLayout());
+		  content_pane.add(logo, BorderLayout.CENTER);
+		  // Center and display
+		  Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
+		  setLocation((screen_size.width - size.width) / 2, (screen_size.height - size.height) / 2);
+		  show();				
+	 }
+	 /** Destructor. */
+	 public void destroy() {
+		  dispose();
+		  rootPane = null;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/WarningDialog.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/WarningDialog.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/WarningDialog.java	(revision 13666)
@@ -0,0 +1,116 @@
+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.gui.SmarterTextArea;
+import org.greenstone.gatherer.util.Utility;
+
+/** Warn a user that they are about to add folder level metadata. */
+public class WarningDialog
+	 extends JDialog 
+	 implements ActionListener {
+
+	 static final private Dimension SIZE = new Dimension(400,160);
+
+	 private int result = JOptionPane.CANCEL_OPTION;
+	 private JButton cancel_button;
+	 private JButton ok_button;
+	 private JCheckBox show_check;
+	 private String full_property;
+	 private String warning_name;
+
+	 public WarningDialog(String full_property, boolean can_cancel) {
+		  super(Gatherer.g_man, "Warning", true);
+		  // Determine the name of this prompt.
+		  this.full_property = full_property;
+		  warning_name = full_property.substring(full_property.indexOf(".") + 1);
+		  // Now build dialog.
+		  setSize(SIZE);
+		  setTitle(get("Title"));
+		  // Creation
+		  JPanel content_pane = (JPanel) getContentPane();
+		  JPanel text_pane = new JPanel();
+		  JLabel icon_label = new JLabel(Utility.getImage("gatherer_medium.gif"));
+		  SmarterTextArea text_area = new SmarterTextArea(get("Message"), false);
+		  text_area.setCaretPosition(0);
+		  text_area.setLineWrap(true);
+		  text_area.setWrapStyleWord(true);
+		  JPanel bottom_pane = new JPanel();
+		  show_check = new JCheckBox(get("WarningDialog.Dont_Show_Again"), false);
+		  JPanel control_pane = new JPanel();
+		  ok_button = new JButton(get("General.OK"));
+		  cancel_button = new JButton(get("General.Cancel"));
+		  // Connection
+		  ok_button.addActionListener(this);
+		  cancel_button.addActionListener(this);
+		  // Layout
+		  icon_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+
+		  text_pane.setLayout(new BorderLayout());
+		  text_pane.add(icon_label, BorderLayout.WEST);
+		  text_pane.add(new JScrollPane(text_area), BorderLayout.CENTER);
+		  
+		  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
+		  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) {
+		  if(event.getSource() == ok_button) {
+				result = JOptionPane.OK_OPTION;
+		  }
+		  // Store the state of the show message checkbox.
+		  Gatherer.config.set(full_property, true, !show_check.isSelected());
+		  // Done.
+		  dispose();
+	 }
+
+	 public int display() {
+		  ///ystem.err.println("Show " + full_property + ": " + Gatherer.config.get(full_property, false));
+		  if(Gatherer.config.get(full_property, false)) {
+				// We only show if the warning has not been disabled.
+				show();
+		  }
+		  // We are no longer showing this dialog, so result must always be true.
+		  else {
+				result = JOptionPane.OK_OPTION;
+		  }
+		  return result;
+	 }
+
+	 private String get(String key) {
+		  if(key.indexOf(".") == -1) {
+				key = warning_name + "." + key;
+		  }
+		  return Gatherer.dictionary.get(key);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/border/TitledBorder.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/border/TitledBorder.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/border/TitledBorder.java	(revision 13666)
@@ -0,0 +1,46 @@
+package org.greenstone.gatherer.gui.border;
+
+import java.awt.*;
+import javax.swing.border.*;
+
+public class TitledBorder 
+	 extends javax.swing.border.TitledBorder {
+	 /** The parent component of this border, which is not available until the Border has been realized. */
+	 private Component parent;
+	 /** Creates a TitledBorder instance with the specified border and an empty title. */
+	 public TitledBorder(Border border) {
+		  super(border);
+	 }
+	 /** Creates a TitledBorder instance with the specified border and title. */
+	 public TitledBorder(Border border, String title) {
+		  super(border, title);
+	 }
+	 /** Creates a TitledBorder instance with the specified border, title, title-justification, and title-position. */
+	 public TitledBorder(Border border, String title, int justification, int position) {
+		  super(border, title, justification, position);
+	 }
+	 /** Creates a TitledBorder instance with the specified border, title, title-justification, title-position, and title-font. */
+	 public TitledBorder(Border border, String title, int justification, int position, Font font) {
+		  super(border, title, justification, position);
+	 }
+	 /** Creates a TitledBorder instance with the specified border, title, title-justification, title-position, title-font, and title-color. */
+	 public TitledBorder(Border border, String title, int justification, int position, Font font, Color color) {
+		  super(border, title, justification, position, font, color);
+	 }
+	 /** Creates a TitledBorder instance. */   
+	 public TitledBorder(String title) {
+		  super(title);
+	 }
+	 /** Gets the parent of this component. */
+	 public Component getParent() {
+		  return parent;
+	 }
+	 /** Paints the border for the specified component with the specified position and size. */
+	 public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
+		  // We assume that this border belongs to whatever component we paint it on.
+		  parent = c;
+		  // Now we continue normal painting.
+		  super.paintBorder(c, g, x, y, width, height);
+	 }     
+}
+
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/browser/GBrowserEvent.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/browser/GBrowserEvent.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/browser/GBrowserEvent.java	(revision 13666)
@@ -0,0 +1,133 @@
+/**
+ *#########################################################################
+ *
+ * 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.browser;
+
+import java.awt.AWTEvent;
+import javax.swing.JProgressBar;
+import org.greenstone.gatherer.util.GURL;
+
+/** A GBrowserEvent is an event fired by one of Gatherers HTMLViewPane browser
+ * implementations. They come in two flavours; GURL events contain a url
+ * which the message is about and may have an associated message String, while
+ * pure message events contain only a String.
+ */
+public class GBrowserEvent 
+	 extends AWTEvent {
+
+	 /** The url payload of this event. */
+	 private GURL url = null;
+
+	 private JProgressBar progress = null;
+
+	 /** The message payload of this event. */
+	 private String message = null;
+
+	 /** This contructor is used to pass events about GURLs out to its 
+	  * listeners. The source and id are needed by the super class of AWTEvents
+	  * but the url is specific to this class.
+	  * @param source the class Object that fired this event.
+	  * @param id a numeric identifier for this event.
+	  * @param url the GURL about which this event is concerned.
+	  */
+	 public GBrowserEvent(Object source, int id, GURL url) {
+		  super(source, id);
+		  this.url = url;
+	 }
+
+	 /** This contructor is used to pass events about GURLs out to its 
+	  * listeners. The source and id are needed by the super class of AWTEvents
+	  * but the url and message are specific to this class.
+	  * @param source the class Object that fired this event.
+	  * @param id a numeric identifier for this event.
+	  * @param url the GURL about which this event is concerned.
+	  * @param message a message String, the reason for this event.
+	  */
+	 public GBrowserEvent(Object source, int id, GURL url, String message) {
+		  super(source, id);
+		  this.url = url;
+	 }
+
+	 /** This constructor is used to pass message events out to its listeners.
+	  * It is much the same as the first constructor, however instead of a 
+	  * GURL as payload, we instead have a message String.
+	  * @param source the class Object that fired this event.
+	  * @param id a numeric identifier for this event.
+	  * @param message a message String, the reason for this event.
+	  */
+	 public GBrowserEvent(Object source, int id, String message) {
+		  super(source, id);
+		  this.message = message;
+	 }
+
+	 /** Used to get the GURL contained within this event.
+	  * @return a GURL specifying the url this event is concerned with, or null
+	  * if this is a message type event.
+	  */
+	 public GURL getURL() {
+		  return url;
+	 }
+
+	 /** Used to get the String message contained within this event.
+	  * @return a String containing the message for this event, or null if this
+	  * is a GURL type event.
+	  */
+	 public String getMessage() {
+		  return message;
+	 }
+
+	 /** Returns a boolean showing whether it is legal to request this GURLs
+	  * progress bar. All GURLs have progress bars, but only those spawned in
+	  * GHTMLPanes etc will actually have their progress bars updated. Webclient
+	  * does not yet support this functionality but will eventually via the
+	  * DocumentProgressEvent.
+	  * @return A boolean specifying whether this GURL supports ProgressBar
+	  * requests.
+	  */
+	 public boolean hasProgress() {
+		  if(progress != null) {
+				return true;
+		  }
+		  return false;
+	 }
+}
+
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/browser/GBrowserListener.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/browser/GBrowserListener.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/browser/GBrowserListener.java	(revision 13666)
@@ -0,0 +1,56 @@
+/**
+ *#########################################################################
+ *
+ * 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.browser;
+
+import java.util.EventListener;
+import org.greenstone.gatherer.gui.browser.GBrowserEvent;
+
+public interface GBrowserListener 
+	 extends EventListener {
+	 public void actionFailed(GBrowserEvent event);
+	 public void controlsChanged();
+	 public void hyperlinkClick(GBrowserEvent event);
+	 public void renderBegun(GBrowserEvent event);
+	 public void renderComplete(GBrowserEvent event);
+	 public void statusChanged(GBrowserEvent event);
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/browser/GHTMLPane.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/browser/GHTMLPane.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/browser/GHTMLPane.java	(revision 13666)
@@ -0,0 +1,374 @@
+/**
+ *#########################################################################
+ *
+ * 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.browser;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Vector;
+import javax.swing.JEditorPane;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+import javax.swing.JScrollPane;
+import javax.swing.event.EventListenerList;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.util.GURL;
+import org.greenstone.gatherer.util.Utility;
+/**
+ * Class Name:  GHTMLPane
+ * Description: To provide a most basic implementation of the HTMLViewPane. Its
+ *              rendering performance may be poor, but it will fully support all
+ *              methods defined in the interface.
+ */
+public class GHTMLPane
+	 extends JPanel
+	 implements HTMLViewPane, HyperlinkListener, PropertyChangeListener {
+	 
+	 /** follow_links - does the class automatically follow hyperlinks. */
+	 boolean follow_links = true;
+	 /** ready - has the view finished rendering the current URL. */
+	 boolean ready = true;
+	 /** the list of listeners associated with this class. */
+	 EventListenerList listeners = null;
+	 /** gatherer - a reference to the main class of Gatherer for messaging. */
+	 Gatherer gatherer = null;
+	 /** view - the JEditorPane the page content will be rendered on to. */
+	 JEditorPane view = null;
+	 Object control = null;
+	 /** current_page - the URL of the currently shown page. */
+	 GURL current_url = null;
+	 /** back_pages - Vector of pages that have been visited. */
+	 Vector back_pages = null;
+	 /** Vector of pages that have been backed up from. 
+	  *  Reset whenever a new url 'path' is entered.
+	  */
+	 Vector forward_pages = null;
+
+
+	 /** Constructor - collects initial settings, lays out view, renders initial
+	  *  URL.
+	  *  @param gatherer - the main class of Gatherer
+	  */
+	 public GHTMLPane(Gatherer gatherer, Object control) {
+		  this.gatherer = gatherer;
+		  this.control = control;
+		  this.setLayout(new BorderLayout());
+
+		  listeners = new EventListenerList();
+
+		  back_pages = new Vector();
+		  forward_pages = new Vector(); 
+
+		  gatherer.debug("\t\tCreating GHTMLPane");
+		  view = new JEditorPane();
+		  view.setEditable(false);
+		  view.addHyperlinkListener(this);
+		  view.addPropertyChangeListener(this);
+		  this.add(new JScrollPane(view), BorderLayout.CENTER);
+	 }
+
+	 public void addGBrowserListener(GBrowserListener listener) {
+		  listeners.add(GBrowserListener.class, listener);
+	 }
+
+	 public void afterDisplay() {
+		  // Nothing to do. Only realy for embedded apps.
+	 }
+
+	 public boolean back() {
+		  // Add current page to forward
+		  forward_pages.add(0,current_url);
+		  // Back up one page.
+		  current_url = (GURL) back_pages.lastElement();
+		  back_pages.remove(back_pages.size() - 1);
+		  this.setPage(current_url);
+		  return true;
+	 }
+
+	 public boolean canBack() {
+		  if(back_pages.size() > 0 && ready) {
+				return true;
+		  }
+		  return false;
+	 }
+
+	 public boolean canForward() {
+		  if(forward_pages.size() > 0 && ready) {
+				return true;
+		  }
+		  return false;
+	 }
+
+	 public boolean canStop() {
+		  if(!ready) {
+				return true;
+		  }
+		  return false;
+	 }
+
+	 // This code courtesy of Horst (hheister@epal.com) who provides this solution
+	 // to the crap null exception I keep getting when I try to grab the image
+	 // of a rendered HTML.
+	 public BufferedImage capture() {
+		  if(ready) {
+				// Paint to an off screen buffer
+				Dimension size = view.getSize();
+				//Graphics offgraphics = offscreen.getGraphics();
+				BufferedImage offscreen = 
+					 new BufferedImage(size.width, size.height, 
+											 BufferedImage.TYPE_INT_RGB);
+				Graphics2D offgraphics = (Graphics2D) offscreen.getGraphics();
+				// For some reason the clip rect is null for the created image
+				// (usually it is set to the size of the image) so set it.
+				offgraphics.setClip(0, 0, size.width, size.height);
+				offgraphics.setColor(getBackground());
+				offgraphics.fillRect(0, 0, size.width, size.height);
+				// This will display components in the HTML Page
+				view.paint(offgraphics);
+				return offscreen;
+		  }
+		  return null;
+	 }
+		  
+	 public GURL current() {
+		  return current_url;
+	 }
+
+	 public void followHyperlinks(boolean value) {
+		  follow_links = value;
+	 }
+
+	 public boolean forward() {
+		  // Add current page to back
+		  back_pages.add(current_url);
+		  // Show forward page.
+		  current_url = (GURL) forward_pages.firstElement();
+		  forward_pages.remove(0);
+		  setPage(current_url);
+		  return true;
+	 }
+
+	 /** Since you can't add an interface to a component hierarchy this method is required to get a reference of the actual rendering component. 
+	  * @return This HTMLViewPane implementation as a component.
+	  */
+	 public Component getContent() {
+		  return this;
+	 }
+
+	 public JProgressBar getProgress() {
+		  // Currently not available. Will have to do some magic using the
+		  // view.getStream() function.
+		  return null;
+	 }
+
+	 /** When a hyperlink event is fired we handle it in one of several ways,
+	  * based on the event type. Enters and exits get fired off as messages to
+	  * the listeners so they can update their status bars. Clicks also fire
+	  * status changes, but their event messages include the GURLs incase we
+	  * to do something special to them. Furthermore if follow hyperlinks is
+	  * set the browser is responsible for loading up the newly designated url.
+	  * @param event A HyperlinkEvent containing useful data about the event,
+	  * such as the url in question and the position of the mouse. It also is
+	  * marked as one of several types of events including ENTERED and EXITED
+	  * (for mouseovers) and ACTIVATED (clicked).
+	  */
+	 public void hyperlinkUpdate(HyperlinkEvent event) {
+		  Object event_type = event.getEventType();
+		  GURL new_url = new GURL(event.getURL());
+		  // The mouse has been moved over a hyperlink.
+		  if (event_type == HyperlinkEvent.EventType.ENTERED) {
+				fireStatusChange(new GURL(event.getURL()));
+		  } 
+		  else if (event_type == HyperlinkEvent.EventType.EXITED) {
+				fireStatusChange(null);
+		  }
+		  else if (event_type == HyperlinkEvent.EventType.ACTIVATED) {
+				fireHyperlinkClick(new_url);
+				if(follow_links) {
+					 show(new_url);
+				}
+		  }
+	 }
+
+	 public boolean isReady() {
+		  return ready;
+	 }
+
+	 public void propertyChange(PropertyChangeEvent evt) {
+		  if(evt.getPropertyName() == "page") {
+				ready = true;
+				fireRenderComplete(current_url);
+		  }
+	 }
+
+	 public void removeGBrowserListener(GBrowserListener listener) {
+		  listeners.remove(GBrowserListener.class, listener);
+	 }
+
+	 public void setEnabled(boolean value) {
+		  ready = value;
+	 }
+
+	 public boolean show(String filename) {
+		  return show(new GURL("file:"+filename));
+	 }
+
+	 /**
+	  *
+	  * Precondition: ready = true <BR>
+	  */
+	 public boolean show(GURL url) {
+		  if(current_url == null) {
+				fireRenderBegun(url);
+				current_url = url;
+				setPage(current_url);
+				return true;
+		  }
+		  else {
+				// If we are not already showing this url
+				if(!current_url.toString().equals(url.toString())) {
+					 fireRenderBegun(url);
+					 // Save a copy of the current page
+					 back_pages.add(current_url);
+					 current_url = url;
+					 setPage(current_url);
+					 return true;
+				}
+		  }
+		  return false;
+	 }
+
+	 public boolean stop() {
+		  // Unfortunately a JEditorPane is not sophisticated enough to support
+		  // this. Pretty much once you send the page to be rendered only killing
+		  // the thread will stop it, and I'm not sure you can restart the thread
+		  // later.
+		  return false;
+	 }
+
+	 protected void fireActionFailed(GURL url) {
+		  GBrowserEvent event = new GBrowserEvent(this,0,url);
+		  Object[] concerned = listeners.getListenerList();
+		  for(int i = 0; i < concerned.length ; i++) {
+				if(concerned[i] == GBrowserListener.class) {
+					 ((GBrowserListener)concerned[i+1]).actionFailed(event);
+				}
+		  }
+	 }
+
+	 protected void fireControlsChanged() {
+		  Object[] concerned = listeners.getListenerList();
+		  for(int i = 0; i < concerned.length ; i++) {
+				if(concerned[i] == GBrowserListener.class) {
+					 ((GBrowserListener)concerned[i+1]).controlsChanged();
+				}
+		  }
+	 }
+
+	 protected void fireHyperlinkClick(GURL url) {
+		  GBrowserEvent event = new GBrowserEvent(this,0,url);
+		  Object[] concerned = listeners.getListenerList();
+		  for(int i = 0; i < concerned.length ; i++) {
+				if(concerned[i] == GBrowserListener.class) {
+					 ((GBrowserListener)concerned[i+1]).hyperlinkClick(event);
+				}
+		  }
+	 }
+
+	 protected void fireRenderBegun(GURL url) {
+		  GBrowserEvent event = new GBrowserEvent(this,0,url);
+		  Object[] concerned = listeners.getListenerList();
+		  for(int i = 0; i < concerned.length ; i++) {
+				if(concerned[i] == GBrowserListener.class) {
+					 ((GBrowserListener)concerned[i+1]).renderBegun(event);
+				}
+		  }
+	 }
+
+	 protected void fireRenderComplete(GURL url) {
+		  GBrowserEvent event = new GBrowserEvent(this,0,url);
+		  Object[] concerned = listeners.getListenerList();
+		  for(int i = 0; i < concerned.length ; i++) {
+				if(concerned[i] == GBrowserListener.class) {
+					 ((GBrowserListener)concerned[i+1]).renderComplete(event);
+				}
+		  }
+	 }				 
+
+	 protected void fireStatusChange(GURL url) {
+		  GBrowserEvent event = new GBrowserEvent(this,0,url);
+		  Object[] concerned = listeners.getListenerList();
+		  for(int i = 0; i < concerned.length ; i++) {
+				if(concerned[i] == GBrowserListener.class) {
+					 ((GBrowserListener)concerned[i+1]).statusChanged(event);
+				}
+		  }
+	 }
+
+	 private void setPage(GURL url) {
+		  try {
+				view.setPage(url.getURL());
+		  }
+		  catch (IOException e) {
+				Utility.showError(gatherer, "GHTMLPane.setPage()", e);
+		  }
+		  catch (Exception e) {
+				Utility.showError(gatherer, "Arrggg...", e);
+		  }
+	 }
+}
+
+
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/browser/HTMLViewPane.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/browser/HTMLViewPane.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/browser/HTMLViewPane.java	(revision 13666)
@@ -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.browser;
+/**
+ *  @date:        23/11/01
+ */
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.image.BufferedImage;
+import java.net.URL;
+import javax.swing.ImageIcon;
+import javax.swing.JProgressBar;
+import org.greenstone.gatherer.gui.browser.GBrowserListener;
+import org.greenstone.gatherer.util.GURL;
+/** HTMLViewPane provides the interface that all implementations must adhere to. The methods shown are used by Gatherer to interact with the rendered HTML pane, and in turn recieve messages back. */
+public interface HTMLViewPane {
+	 /** Add a GBrowserListener to this browser. 
+	  * @param listener an object which implements the GBrowserListener interface.
+	  */
+	 public void addGBrowserListener(GBrowserListener listener);
+
+	 public void afterDisplay();
+
+  /**
+	* Back tells the browser to display a previous page if there is one. All
+	* implementations of HTMLViewPane should remember pages visited within this
+	* session, and react appropriately to calls to this function. Any caller of
+	* back should then immediately call canBack to determine if the function
+	* should be enabled.
+	* @return value - whether or not the operation was successful
+	*/
+  public boolean back();
+  /**
+	* CanBack is used to determine if there are further pages to 'back' to, and
+	* based on the result whether the functionality should be available
+	*/
+  public boolean canBack();
+  /**
+	* CanForward performs approximately the same duty as canBack except, of
+	* course, in the opposite direction.
+	*/
+  public boolean canForward();
+	 /** 
+	  * CanStop determines whether the stop functionality is available. In general
+	  * you have to be doing something before you can stop it!
+	  */
+	 public boolean canStop();
+  /**
+   * Capture is used to grab a buffered image of the current graphics context of
+   * the HTML pane. Note that this may not actually be feasible in embedded
+   * applications such as Mozilla, as the apllication has a seperate graphics
+   * buffer.
+   * @return img - a buffered image containing a clipped section of the HTML
+   * panes graphics buffer.
+   */
+  public BufferedImage capture();
+  /**
+   * When called this method returns the URL of the resource currently being
+   * displayed (or rendered). If no resource has been requested the return URL
+   * is null. The URL can point to local files, web-based resources etc.
+   * @return url - the GURL of the currently displayed resource.
+   */
+  public GURL current();
+  /**
+   * This method is used to tell the HTML pane whether it should attempt to
+   * follow hyperlinks when a user clicks them. Whether this is set or not the
+   * fetch method should still be called by the HTML pane implementation apon
+   * a hyperlink click.
+   * @param on - whether followHyperlinks is; on (= true) or off.
+   */
+  public void followHyperlinks(boolean value);
+  /**
+	* Forward is a call for the HTMLViewPane implementation to move forward one
+	* page in its browser history. It should react appropriately to calls to this
+	* method and should retain a history of forward pages.
+	* @return value - whether of not the operation was successfull
+	*/
+  public boolean forward();
+	 /** In order to add the class that implements this interface to a component hierarchy you require some way to get at the component. This is that way.
+	  * @return a component reference of this class (as compared to the interface one you started with).
+	  */  
+	 public Component getContent();
+  /**
+   * If called, getProgressBar should return a reference to a JProgress bar. The
+   * HTML pane is then resposible for updating the progress bar for its lifetime
+   * whereapon the caller will dispose of it. If no page is currently being
+   * downloaded/rendered then the call should return null.
+   * @return progress - a JProgressBar indicating the HTML panes progress
+   * towards displaying a url or null.
+   */
+  public JProgressBar getProgress();
+  /** Before attempting to issue futher instructions to the HTML pane, Gatherer must first ensure that its ready. A pane should always be responsive but there are foreseeable times when an interrupt to go to a new page may cause the renderer to become unstable, or perhaps a user is filling out a form and thus shouldn't be pre-empted.
+   * @return <i>true</i> if the pane is ready for further instructions, <i>false</i> if not.
+   */
+  public boolean isReady();
+  /**
+   * SetEnabled is used to temporarily prevent further user interaction with the
+   * pane. This may be caused by certain user requests in other parts of Gatherer
+   * or is called when a modal dialogue is opened by the Gatherer application.
+   * Any implementation of setEnabled should in turn call an equivent method
+   * within its subcomponents and update its appearance to indicate its current
+   * state (ie greyed out boxes or background, wait cursor).
+   * @param on - what state the component should be in; on (= true) or off.
+   */
+  public void setEnabled(boolean value);
+	 /** Remove a GBrowserListener from this browser. 
+	  * @param listener an object which implements the GBrowserListener interface.
+	  */
+	 public void removeGBrowserListener(GBrowserListener listener);
+	 /**
+   * Show, in both of its forms, allows Gatherer to display a certain URL or file
+   * in the HTML pane.
+   * @param filename a string representing a valid local file path.
+	* @param update whether this action should update the history queues.
+   * @return whether a page has been queued to be rendered.
+   */
+  public boolean show(String filename);
+  /**
+   * Show, in both of its forms, allows Gatherer to display a certain URL or file
+   * in the HTML pane.
+   * @param url a url representing a valid URI.
+	* @param update whether this action should update the history queues.
+   * @return whether a page has been queued to be rendered.
+   */
+  public boolean show(GURL url);
+  /**
+   * Stop() kills the current rendering.
+   * @return whether the rendering was successfully killed.
+   */
+  public boolean stop();
+}
+
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/combobox/GComboBox.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/combobox/GComboBox.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/combobox/GComboBox.java	(revision 13666)
@@ -0,0 +1,98 @@
+/**
+ *#########################################################################
+ *
+ * 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.combobox;
+
+import java.awt.event.KeyListener;
+import javax.swing.ComboBoxModel;
+import javax.swing.JComboBox;
+import javax.swing.JTextField;
+import javax.swing.event.DocumentListener;
+/** In order for a JComboBox to perform the way Gatherer requires, ie firing
+ * a DocumentEvent of some form whenever the user edits the content of the
+ * currently selected item, we need to subclass JComboBox and build a version
+ * which adds a DocumentListener to the JTextField within the combobox not to
+ * the combobox itself. The same deal applies for KeyListeners.
+ */
+public class GComboBox
+	 extends JComboBox {
+
+	 private JTextField text;
+
+	 public GComboBox() {
+		  super();
+		  text = (JTextField) this.getEditor().getEditorComponent();
+	 }
+
+	 public GComboBox(ComboBoxModel model) {
+		  super(model);
+		  text = (JTextField) this.getEditor().getEditorComponent();
+	 }	 
+
+	 public void addDocumentListener(DocumentListener listener) {
+		  if(text != null) text.getDocument().addDocumentListener(listener);
+	 }
+
+	 public void addKeyListener(KeyListener listener) {
+		  if(text != null) text.addKeyListener(listener);
+	 }
+
+	 public String getText() {
+		  if(text != null) {
+				return text.getText();
+		  }
+		  GComboBoxModel model = (GComboBoxModel)this.getModel();
+		  return (String)model.getSelectedItem();
+	 }
+
+	 public void setText(String value) {
+		  if(text != null) text.setText(value);
+	 }
+
+	 public void removeDocumentListener(DocumentListener listener) {
+		  if(text != null) text.getDocument().removeDocumentListener(listener);
+	 }
+
+	 public void removeKeyListener(KeyListener listener) {
+		  if(text != null) text.removeKeyListener(listener);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/combobox/GComboBoxModel.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/combobox/GComboBoxModel.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/combobox/GComboBoxModel.java	(revision 13666)
@@ -0,0 +1,147 @@
+/**
+ *#########################################################################
+ *
+ * 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.combobox;
+
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import javax.swing.AbstractListModel;
+import javax.swing.MutableComboBoxModel;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.w3c.dom.Element;
+
+public class GComboBoxModel
+	 extends AbstractListModel
+	 implements MutableComboBoxModel {
+
+	 // Data.
+	 private boolean   isMetadataElement = false;
+
+	 private Hashtable name_to_element   = new Hashtable();
+
+	 private Object    selected_item     = null;
+
+	 private Vector    contents          = new Vector();
+
+	 public GComboBoxModel() {
+	 }
+
+	 public GComboBoxModel(Vector contents) {
+		  this.contents = contents;
+		  Collections.sort(contents);
+	 }
+
+	 public GComboBoxModel(Vector elements, boolean isMetadataElement) {
+		  this.isMetadataElement = isMetadataElement;
+		  for(int i = 0; i < elements.size(); i++) {
+				ElementWrapper element = (ElementWrapper)elements.get(i);
+				contents.add(element.toString());
+				name_to_element.put(element.toString(), element);
+		  }
+		  Collections.sort(contents);
+	 }
+
+	 private boolean contains(Vector vector, Object key) {
+		  for(int i = 0; i < vector.size(); i++) {
+				if(vector.get(i).toString().equals(key.toString())) {
+					 return true;
+				}
+		  }
+		  return false;
+	 }
+
+	 // Methods.
+	 public void addElement(Object obj) {
+		  if(!contents.contains(obj)) {
+				contents.add(obj);
+				Collections.sort(contents);
+				refresh();
+		  }
+	 }
+
+	 public Object getElementAt(int index) {
+		  return contents.get(index);
+	 }
+
+	 public Object getSelectedItem() {
+		  return selected_item;
+	 }
+
+	 public ElementWrapper getSelectedMetadata() {
+		  if(isMetadataElement) {
+				return (ElementWrapper)name_to_element.get(selected_item);
+		  }
+		  return null;
+	 }
+
+	 public int getSize() {
+		  return contents.size();
+	 }
+
+	 public void insertElementAt(Object obj, int index) {
+		  contents.add(index, obj);
+		  fireIntervalAdded(this, index, index);
+	 }
+
+	 public void refresh() {
+		  fireContentsChanged(this, 0, getSize());
+	 }
+
+	 public void removeElement(Object obj) {
+		  int index = contents.indexOf(obj);
+		  contents.remove(index);
+		  fireIntervalRemoved(this, index, index);
+	 }
+
+	 public void removeElementAt(int index) {
+		  contents.remove(index);
+		  fireIntervalRemoved(this, index, index);
+	 }
+
+	 public void setSelectedItem(Object obj) {
+		  selected_item = obj;
+		  int index = contents.indexOf(obj);
+		  fireContentsChanged(this, index, index);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/messages/MessageListModel.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/messages/MessageListModel.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/messages/MessageListModel.java	(revision 13666)
@@ -0,0 +1,190 @@
+package org.greenstone.gatherer.gui.messages;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.util.Hashtable;
+import java.util.Vector;
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 1.1
+ */ 
+import javax.swing.AbstractListModel;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.Message;
+import org.greenstone.gatherer.util.Utility;
+class MessageListModel 
+	 extends AbstractListModel {
+
+	 Hashtable mappings;
+
+	 int current_index;
+
+	 int current_message;
+
+	 int sizes[][] = new int[6][4];
+
+	 Vector data;
+
+	 // Contructor
+    public MessageListModel() {
+		  current_index = 0;
+		  current_message = 0;
+		  data = new Vector();
+		  mappings = new Hashtable();
+		  for(int i = 0; i < 6; i++) {
+				for(int j = 0; j < 4; j++) {
+					 sizes[i][j] = 0;
+				}
+		  }
+    }
+    
+	 // Add a new message in the correct place
+    public synchronized void add(Message message) {
+		  // Add the element to the model
+		  data.add(message);
+		  // Increment the count for that type of message
+		  sizes[message.source][message.level]++;
+		  // An announce to the world that I have changed!
+        fireContentsChanged(this, 0, getSize() - 1);
+    }
+
+    // Return the size of the list
+    public int getSize() {
+		  int size = 0;
+		  // Each each source...
+		  for(int i = 0; i < 6; i++) {
+				// and each level...
+				for(int j = 0; j < 4; j++) {
+					 // If both this source and level are active, add its size
+					 /** @todo reenabled 
+					  * if(gatherer.config.source[i] && gatherer.config.level[j]) {
+					  *	size = size + sizes[i][j];
+					  * }
+					  */
+				}
+		  }
+		  return size;
+    }
+
+	 public int getTotalSize() {
+	  int size = 0;
+		  // Each each source...
+		  for(int i = 0; i < 6; i++) {
+				// and each level...
+				for(int j = 0; j < 4; j++) {
+					 size = size + sizes[i][j];
+				}
+		  }
+		  return size;
+	 }
+
+	 public String getSizeStr() {
+		  return "" + getSize() + "";
+	 }
+
+	 public String getTotalSizeStr() {
+		  return "" + getTotalSize() + "";
+	 }
+
+    // Return a message from the list
+    public Object getElementAt( int index ) {
+		  Integer index_int = new Integer(index);
+		  // Maybe we've already found this message.
+		  if(mappings.containsKey(index_int)) {
+				current_message = ((Integer)mappings.get(index_int)).intValue();
+		  }
+		  // Otherwise we're going to have to search for it.
+		  else {
+				while(index != current_index) {
+					 // Asking for an index lower than the one we're at.
+					 if(index < current_index) {
+						  Message temp;
+						  /*
+						  do {
+								current_message--;
+								temp = (Message)data.get(current_message);
+						  } while(!(gatherer.config.source[temp.source] && 
+									 gatherer.config.level[temp.level]));
+						  // We are now at a new visible message.
+						  */
+						  current_index--;
+					 }
+					 else {
+						  Message temp;
+						  /*
+						  do {
+								current_message++;
+								temp = (Message)data.get(current_message);
+						  } while(!(gatherer.config.source[temp.source] && 
+									 gatherer.config.level[temp.level]));
+						  // We are now at a new visible message.
+						  current_index++;
+						  */
+					 }
+				}
+				// Now that we've found the blighter, add a mapping so its quicker
+				// next time.
+				mappings.put(new Integer(index),new Integer(current_message));
+		  }
+		  return ((Message)data.get(current_message)).toString();
+    }
+
+	 public void refresh() {
+		  if(getSize() > 0) {
+				current_index = 0;
+				// Find the first message that meets the requirements. Its index 0 y'know.
+				current_message = -1;
+				Message temp;
+				/*
+				do {
+					 current_message++;
+					 temp = (Message)data.get(current_message);
+				} while(!(gatherer.config.source[temp.source] && 
+							 gatherer.config.level[temp.level]));	
+				*/	
+				// Reset mappings.
+				mappings.clear();
+				mappings.put(new Integer(current_index), new Integer(current_message));
+				// Let everyone who cares know we've changed.
+				fireContentsChanged(this, 0, getSize() - 1);
+		  }
+		  // Else don't bother doning anything on an empty list!
+	 }
+}
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/messages/MessageListRenderer.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/messages/MessageListRenderer.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/messages/MessageListRenderer.java	(revision 13666)
@@ -0,0 +1,90 @@
+package org.greenstone.gatherer.gui.messages;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.util.StringTokenizer;
+import javax.swing.*;
+import org.greenstone.gatherer.Gatherer;
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 1.1
+ */
+class MessageListRenderer 
+	 extends JLabel 
+	 implements ListCellRenderer {
+
+    // Constructor
+    public MessageListRenderer() {
+    }
+    // This is the only method defined by ListCellRenderer.
+    // We just reconfigure the JLabel each time we're called.
+    public Component getListCellRendererComponent(
+	     JList list,
+		  Object value,            // value to display
+		  int index,               // cell index
+		  boolean isSelected,      // is the cell selected
+		  boolean cellHasFocus) {  // the list and the cell have the focus
+		  // Get the message
+		  String s = value.toString();
+		  setText(s);
+		  // Now parse out the level
+		  StringTokenizer tokenizer = new StringTokenizer(s);
+		  // Throw away source.
+		  tokenizer.nextToken();
+		  // Now add color details based on level
+		  String level = tokenizer.nextToken();
+		  if(level.equals(get("Main"))) {
+				setForeground(Color.black);
+		  } else if (level.equals(get("Event"))) {
+				setForeground(Color.blue);
+		  } else if (level.equals(get("Information"))) {
+				setForeground(Color.gray);
+		  } else {
+				setForeground(Color.red);
+		  }
+		  setEnabled(list.isEnabled());
+		  setFont(list.getFont());
+		  return this;
+    }
+
+	 private String get(String key) {
+		  if(key.indexOf('.') == -1) {
+				key = "Level." + key;
+		  }
+		  return Gatherer.dictionary.get(key);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/messages/MessagePane.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/messages/MessagePane.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/messages/MessagePane.java	(revision 13666)
@@ -0,0 +1,381 @@
+package org.greenstone.gatherer.gui.messages;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import java.util.Date;
+import javax.swing.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.Message;
+import org.greenstone.gatherer.util.Utility;
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 1.3
+ */
+public class MessagePane
+	 extends JPanel
+    implements ActionListener {
+
+	 GridBagConstraints grid_constraints = null;
+
+	 GridBagLayout grid_layout = null;
+
+	 JButton save_messages = null;
+
+	 JLabel level_label = null;
+	 JLabel message_count = null;
+	 JLabel source_label = null;
+
+	 JPanel central_pane = null;
+	 JPanel corner_pane = null;
+	 JPanel count_pane = null;
+	 JPanel horizontal_pane = null;
+	 JPanel level_pane = null;
+	 JPanel source_pane = null;
+	 JPanel vertical_pane = null;
+
+	 JScrollPane scroll_pane = null;
+
+	 JToggleButton level_event = null;
+	 JToggleButton level_error = null;
+	 JToggleButton level_information = null;
+	 JToggleButton level_main = null;
+	 JToggleButton source_browser = null;
+	 JToggleButton source_build = null;
+	 JToggleButton source_general = null;
+	 JToggleButton source_mirroring = null;
+	 JToggleButton source_metaedit = null;
+	 JToggleButton source_session = null;
+
+	 JList message_list = null;
+
+	 MessageListModel model = null;
+
+	 MessageListRenderer renderer = null;
+
+	 String args[];
+
+	 public MessagePane() {
+	 }
+
+	 public void display() {
+		  // Setup main layout managers
+		  grid_layout = new GridBagLayout();
+		  grid_constraints = new GridBagConstraints();
+		  this.setLayout(grid_layout);
+
+		  // Vertical Buttons
+		  source_pane = new JPanel(new BorderLayout());
+		  source_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,3));
+
+		  vertical_pane = new JPanel(new GridLayout(6,1));
+
+		  Gatherer.println("\tCreating source_label");
+		  source_label = new JLabel(get("Source"));
+		  source_label.setHorizontalAlignment(JLabel.CENTER);
+
+		  Gatherer.println("\tCreating source_general");
+		  source_general = new JToggleButton(get("General"), Gatherer.config.get("messages.source_general", false));
+		  source_general.setIcon(Utility.OFF_ICON);
+		  source_general.setSelectedIcon(Utility.ON_ICON);
+		  source_general.setHorizontalTextPosition(JToggleButton.CENTER);
+		  source_general.setVerticalTextPosition(JToggleButton.BOTTOM);
+		  source_general.addActionListener(this);
+
+		  Gatherer.println("\tCreating source_browser");
+		  source_browser = new JToggleButton(get("Browser"), Gatherer.config.get("messages.source_browser", false));
+		  source_browser.setIcon(Utility.OFF_ICON);
+		  source_browser.setSelectedIcon(Utility.ON_ICON);
+		  source_browser.setHorizontalTextPosition(JToggleButton.CENTER);
+		  source_browser.setVerticalTextPosition(JToggleButton.BOTTOM);
+		  source_browser.addActionListener(this);
+
+		  Gatherer.println("\tCreating source_mirroring");
+		  source_mirroring = new JToggleButton(get("Mirroring"), Gatherer.config.get("messages.source_mirroring", false));
+		  source_mirroring.setIcon(Utility.OFF_ICON);
+		  source_mirroring.setSelectedIcon(Utility.ON_ICON);
+		  source_mirroring.setHorizontalTextPosition(JToggleButton.CENTER);
+		  source_mirroring.setVerticalTextPosition(JToggleButton.BOTTOM);
+		  source_mirroring.addActionListener(this);
+
+		  Gatherer.println("\tCreating source_session");
+		  source_session = new JToggleButton(get("Session"), Gatherer.config.get("messages.source_session", false));
+		  source_session.setIcon(Utility.OFF_ICON);
+		  source_session.setSelectedIcon(Utility.ON_ICON);
+	     source_session.setHorizontalTextPosition(JToggleButton.CENTER);
+		  source_session.setVerticalTextPosition(JToggleButton.BOTTOM);
+		  source_session.addActionListener(this);
+
+		  Gatherer.println("\tCreating source_metaedit");
+		  source_metaedit = new JToggleButton(get("Metaedit"), Gatherer.config.get("messages.source_metaedit", false));
+		  source_metaedit.setIcon(Utility.OFF_ICON);
+		  source_metaedit.setSelectedIcon(Utility.ON_ICON);
+		  source_metaedit.setHorizontalTextPosition(JToggleButton.CENTER);
+		  source_metaedit.setVerticalTextPosition(JToggleButton.BOTTOM);
+		  source_metaedit.addActionListener(this);
+
+		  Gatherer.println("\tCreating source_build");
+		  source_build = new JToggleButton(get("Build"), Gatherer.config.get("messages.source_build", false));
+		  source_build.setIcon(Utility.OFF_ICON);
+		  source_build.setSelectedIcon(Utility.ON_ICON);
+		  source_build.setHorizontalTextPosition(JToggleButton.CENTER);
+		  source_build.setVerticalTextPosition(JToggleButton.BOTTOM);
+		  source_build.addActionListener(this);
+
+		  source_pane.add(source_label, BorderLayout.NORTH);
+		  vertical_pane.add(source_general);
+		  vertical_pane.add(source_browser);
+		  vertical_pane.add(source_mirroring);
+		  vertical_pane.add(source_session);
+		  vertical_pane.add(source_metaedit);
+		  vertical_pane.add(source_build);
+		  source_pane.add(vertical_pane, BorderLayout.CENTER);
+
+		  // Central pane
+		  central_pane = new JPanel(new BorderLayout());
+
+		  Gatherer.println("\tCreating message_list");
+		  model = new MessageListModel();
+		  renderer = new MessageListRenderer();
+		  message_list = new JList();
+		  message_list.setModel(model);
+		  message_list.setCellRenderer(renderer);
+
+		  scroll_pane = new JScrollPane(message_list);
+		  central_pane.add(scroll_pane, BorderLayout.CENTER);
+
+		  Gatherer.println("\tCreating message_count");
+		  count_pane = new JPanel(new BorderLayout());
+		  args = new String[2];
+		  args[0] = model.getSizeStr();
+		  args[1] = model.getTotalSizeStr();
+		  message_count = new JLabel(get("Message_Count",args));
+		  message_count.setHorizontalAlignment(JLabel.RIGHT);
+
+		  central_pane.add(scroll_pane, BorderLayout.CENTER);
+		  central_pane.add(message_count, BorderLayout.SOUTH);
+
+		  // Corner area
+		  corner_pane = new JPanel(new BorderLayout());
+		  corner_pane.setBorder(BorderFactory.createEmptyBorder(3,5,5,5));
+
+		  Gatherer.println("\tCreating save_message");
+		  save_messages = new JButton(get("Save_Messages"),
+												new ImageIcon(Utility.RES_DIR+"save.gif"));
+		  save_messages.addActionListener(this);
+
+		  corner_pane.add(save_messages, BorderLayout.CENTER);
+
+		  // Horizontal buttons.
+		  level_pane = new JPanel(new BorderLayout());
+
+		  horizontal_pane = new JPanel(new GridLayout(1,4));
+
+		  Gatherer.println("\tCreating level_label");
+		  level_label = new JLabel(get("Level"));
+		  level_label.setHorizontalAlignment(JLabel.CENTER);
+
+		  Gatherer.println("\tCreating level_main");
+		  level_main = new JToggleButton(get("Main"), Gatherer.config.get("messages.level_main", false));
+		  level_main.setIcon(Utility.OFF_ICON);
+		  level_main.setSelectedIcon(Utility.ON_ICON);
+		  level_main.addActionListener(this);
+
+		  Gatherer.println("\tCreating level_event");
+		  level_event = new JToggleButton(get("Event"), Gatherer.config.get("messages.level_event", false));
+		  level_event.setIcon(Utility.OFF_ICON);
+		  level_event.setSelectedIcon(Utility.ON_ICON);
+		  level_event.addActionListener(this);
+
+		  Gatherer.println("\tCreating level_information");
+		  level_information = new JToggleButton(get("Information"), Gatherer.config.get("messages.level_information", false));
+		  level_information.setIcon(Utility.OFF_ICON);
+		  level_information.setSelectedIcon(Utility.ON_ICON);
+		  level_information.addActionListener(this);
+
+		  Gatherer.println("\tCreating level_error");
+		  level_error = new JToggleButton(get("Error"), Gatherer.config.get("messages.level_error", false));
+		  level_error.setIcon(Utility.OFF_ICON);
+		  level_error.setSelectedIcon(Utility.ON_ICON);
+		  level_error.addActionListener(this);
+
+		  level_pane.add(level_label, BorderLayout.NORTH);
+		  horizontal_pane.add(level_main);
+		  horizontal_pane.add(level_event);
+		  horizontal_pane.add(level_information);
+		  horizontal_pane.add(level_error);
+		  level_pane.add(horizontal_pane, BorderLayout.CENTER);
+
+		  // Terrifying gridbag layout
+		  grid_constraints.fill = GridBagConstraints.BOTH;
+		  grid_layout.setConstraints(source_pane, grid_constraints);
+		  this.add(source_pane);
+		  grid_constraints.weightx = 1.0;
+		  grid_constraints.weighty = 1.0;
+		  grid_constraints.gridwidth = GridBagConstraints.REMAINDER;
+		  grid_layout.setConstraints(central_pane, grid_constraints);
+		  this.add(central_pane);
+		  grid_constraints.weightx = 0.0;
+		  grid_constraints.weighty = 0.0;
+		  grid_constraints.gridwidth = 1;
+		  grid_layout.setConstraints(corner_pane, grid_constraints);
+		  this.add(corner_pane);
+		  grid_constraints.gridwidth = GridBagConstraints.REMAINDER;
+		  grid_layout.setConstraints(level_pane, grid_constraints);
+		  this.add(level_pane);
+	 }
+
+	 public void actionPerformed(ActionEvent event) {
+		  Object source = event.getSource();
+
+		  // Eventually this will dump the messages to a text file, but for now
+		  // I'm using it in testing.
+		  if(source == save_messages) {
+				for(int i = 0; i < 20; i++) {
+					 model.add(Message.random());
+					 message_list.ensureIndexIsVisible(model.getSize() - 1);
+				}
+		  }
+		  // We've been asked to toggle whether we show general messages.
+		  else if(source == source_general) {
+				// Toggle config setting
+				Gatherer.config.set("messages.source_general", false, !Gatherer.config.get("messages.source_general", false));
+				// Inform model something has changed.
+				model.refresh();
+				message_list.ensureIndexIsVisible(model.getSize() - 1);
+		  }
+		  // We've been asked to toggle whether we show browser messages.
+		  else if(source == source_browser) {
+				// Toggle config setting
+				Gatherer.config.set("messages.source_browser", false, !Gatherer.config.get("messages.source_browser", false));
+				// Inform model something has changed.
+				model.refresh();
+				message_list.ensureIndexIsVisible(model.getSize() - 1);
+		  }
+		  // We've been asked to toggle whether we show general messages.
+		  else if(source == source_mirroring) {
+				// Toggle config setting
+				Gatherer.config.set("messages.source_mirroring", false, !Gatherer.config.get("messages.source_mirroring", false));
+				// Inform model something has changed.
+				model.refresh();
+				message_list.ensureIndexIsVisible(model.getSize() - 1);
+		  }
+		  // We've been asked to toggle whether we show session messages.
+		  else if(source == source_session) {
+				// Toggle config setting
+				Gatherer.config.set("messages.source_session", false, !Gatherer.config.get("messages.source_session", false));
+				// Inform model something has changed.
+				model.refresh();
+				message_list.ensureIndexIsVisible(model.getSize() - 1);
+		  }
+		  // We've been asked to toggle whether we show metaedit messages.
+		  else if(source == source_metaedit) {
+				// Toggle config setting
+				Gatherer.config.set("messages.source_metaedit", false, !Gatherer.config.get("messages.source_metaedit", false));
+				// Inform model something has changed.
+				model.refresh();
+				message_list.ensureIndexIsVisible(model.getSize() - 1);
+		  }
+		  // We've been asked to toggle whether we show build messages.
+		  else if(source == source_build) {
+				// Toggle config setting
+				Gatherer.config.set("messages.source_build", false, !Gatherer.config.get("messages.source_build", false));
+				// Inform model something has changed.
+				model.refresh();
+				message_list.ensureIndexIsVisible(model.getSize() - 1);
+		  }
+		  // We've been asked to toggle whether we show main level messages.
+		  else if(source == level_main) {
+				// Toggle config setting
+				Gatherer.config.set("messages.level_main", false, !Gatherer.config.get("messages.level_main", false));
+				// Inform model something has changed.
+				model.refresh();
+				message_list.ensureIndexIsVisible(model.getSize() - 1);
+		  }
+		  // We've been asked to toggle whether we show event level messages.
+		  else if(source == level_event) {
+				// Toggle config setting
+				Gatherer.config.set("messages.level_event", false, !Gatherer.config.get("messages.level_event", false));
+				// Inform model something has changed.
+				model.refresh();
+				message_list.ensureIndexIsVisible(model.getSize() - 1);
+		  }
+		  // We've been asked to toggle whether we show information level messages.
+		  else if(source == level_information) {
+				// Toggle config setting
+				Gatherer.config.set("messages.level_information", false, !Gatherer.config.get("messages.level_information", false));
+				// Inform model something has changed.
+				model.refresh();
+				message_list.ensureIndexIsVisible(model.getSize() - 1);
+		  }
+		  // We've been asked to toggle whether we show error level messages.
+		  else if(source == level_error) {
+				// Toggle config setting
+				Gatherer.config.set("messages.level_error", false, !Gatherer.config.get("messages.level_error", false));
+				// Inform model something has changed.
+				model.refresh();
+				message_list.ensureIndexIsVisible(model.getSize() - 1);
+		  }
+		  // Pretty much no matter what happens we need to get the new size
+		  args = new String[2];
+		  args[0] = model.getSizeStr();
+		  args[1] = model.getTotalSizeStr();
+		  message_count.setText(get("Message_Count",args));
+	 }
+
+	 /** The callback for the message listener. Here all of the messages are
+	  * displayed onto the list.
+	  * @param message The Message to be displayed.
+	  */
+	 public void show(Message message) {
+		  model.add(message);
+		  message_list.ensureIndexIsVisible(model.getSize() - 1);
+	 }
+
+
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+
+	 private String get(String key, String args[]) {
+		  if(key.indexOf('.') == -1) {
+				key = "Messages." + key;
+		  }
+		  return Gatherer.dictionary.get(key, args);
+	 }
+}
+
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/Autofilter.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/Autofilter.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/Autofilter.java	(revision 13666)
@@ -0,0 +1,245 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+package org.greenstone.gatherer.gui.metaaudit;
+/**************************************************************************************
+ * Title:        Gatherer
+ * Description:  The Gatherer: a tool for gathering and enriching a digital collection.
+ * Copyright:    Copyright (c) 2001
+ * Company:      The University of Waikato
+ * Written:        /05/02
+ * Revised:      22/08/02 Revamped, Optimized and Commented.
+ **************************************************************************************/
+
+import java.util.ArrayList;
+/** 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 {
+	 /** <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[] = {"eqeq", "!eq", "<", "<eq", ">", ">eq", "^", "!^", "$", "!$", "?", "!?"};
+	 /** 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();
+					 }
+					 // Perform the match, based on the selected method.
+					 switch(method) {
+					 case 1: // !EQ
+						  pass = !(source.equals(target));
+						  break;
+					 case 2: // <
+						  pass = (source.compareTo(target) < 0);
+						  break;
+					 case 3: // <eq
+						  pass = (source.compareTo(target) <= 0);
+					 break;
+					 case 4: // >
+						  pass = (source.compareTo(target) > 0);
+						  break;
+					 case 5: // >eq
+						  pass = (source.compareTo(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 = source.equals(target);
+						  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/start/gli/src/org/greenstone/gatherer/gui/metaaudit/AutofilterDialog.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/AutofilterDialog.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/AutofilterDialog.java	(revision 13666)
@@ -0,0 +1,383 @@
+package org.greenstone.gatherer.gui.metaaudit;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.metaaudit.Autofilter;
+import org.greenstone.gatherer.gui.metaaudit.Filter;
+import org.greenstone.gatherer.gui.metaaudit.MetaAuditFrame;
+/** 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 JDialog {
+	 /** The filter being edited. */
+	 private Autofilter filter;
+	 /** A reference to ourselves so our inner classes can reference us. */
+	 private AutofilterDialog self;
+	 /** 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;
+	 /** The button used to accept and commit any changes to the autofilter. */
+	 private JButton ok_button = null;
+	 /** A check box used to specify that the given filters should be applied conjunctly. */
+	 private JCheckBox and_check = null;
+	 /** The check box used to specify whether the first filter is case sensitive. */
+	 private JCheckBox first_case = null;
+	 /** The none check is used to disable the second filter. */
+	 private JCheckBox none_check = null;
+	 /** The check box used to specify that the given filters should be applied disjunctly. */
+	 private JCheckBox or_check = 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 JComboBox order = 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, 220);
+	 /** 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);
+		  setSize(SIZE);
+		  setTitle(get("Title"));
+		  // Creation
+		  JPanel content_pane = (JPanel) getContentPane();
+		  JPanel name_pane = new JPanel();
+		  JLabel name_label = new JLabel(get("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(get("eqeq"));
+		  value = new JComboBox();
+		  value.setEditable(false);
+		  JPanel custom_pane = new JPanel();
+		  JPanel first_pane = new JPanel();
+		  first_method = new JComboBox();
+		  first_value = new JComboBox();
+		  first_value.setEditable(true);
+		  first_value.addItem("");
+		  first_value.setSelectedItem("");
+		  first_case = new JCheckBox(get("Case_Sensitive"));
+		  JPanel operator_pane = new JPanel();
+		  JLabel operator_label = new JLabel(get("Operator"));
+		  ButtonGroup operator_group = new ButtonGroup();
+		  and_check = new JCheckBox(get("AND"));
+		  none_check = new JCheckBox(get("None"));
+		  or_check = new JCheckBox(get("OR"));
+		  none_check.setSelected(true);
+		  operator_group.add(none_check);
+		  operator_group.add(and_check);
+		  operator_group.add(or_check);
+		  JPanel second_pane = new JPanel();
+		  second_method = new JComboBox();
+		  second_method.setEnabled(false);
+		  second_value = new JComboBox();
+		  second_value.setEditable(true);
+		  second_value.setEnabled(false);
+		  second_value.addItem("");
+		  second_value.setSelectedItem("");
+		  second_case = new JCheckBox(get("Case_Sensitive"));
+		  JPanel lower_pane = new JPanel();
+		  JPanel order_pane = new JPanel();
+		  JLabel order_label = new JLabel(get("Order"));
+		  order = new JComboBox();
+		  order.addItem(get("Ascending"));
+		  order.addItem(get("Descending"));
+		  // Assign values to method comboboxes.
+		  for(int i = 0; i < Autofilter.METHOD_LIST.length; i++) {
+				first_method.addItem(get(Autofilter.METHOD_LIST[i]));
+				second_method.addItem(get(Autofilter.METHOD_LIST[i]));
+		  }
+		  JPanel button_pane = new JPanel();
+		  cancel_button = new JButton(get("Clear"));
+		  cancel_button.setMnemonic(KeyEvent.VK_C);
+		  ok_button = new JButton(get("Set"));
+		  ok_button.setMnemonic(KeyEvent.VK_S);
+		  // Connection
+		  and_check.addActionListener(new CheckListener(true));
+		  cancel_button.addActionListener(new ButtonListener(false));
+		  none_check.addActionListener(new CheckListener(false));
+		  ok_button.addActionListener(new ButtonListener(true));
+		  or_check.addActionListener(new CheckListener(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_check);
+		  operator_pane.add(and_check);
+		  operator_pane.add(or_check);
+
+		  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.setLayout(new GridLayout(1,2));
+		  order_pane.add(order_label);
+		  order_pane.add(order);
+
+		  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(get("Filter_By_Value"), value_pane);
+		  control.add(get("Custom_Filter"), custom_pane);
+
+		  button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+		  button_pane.setLayout(new GridLayout(1,2));
+		  button_pane.add(ok_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 = Gatherer.config.screen_size;
+		  setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+		  screen_size = null;
+	 }
+	 /** Destructor. */
+	 public void destroy() {
+		  dispose();
+		  cancel_button = null;
+		  ok_button = null;
+		  and_check = null;
+		  first_case = null;
+		  none_check = null;
+		  or_check = null;
+		  second_case = null;
+		  order = 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.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_check.setSelected(true);
+				}
+				else {
+					 if(filter.operation) {
+						  and_check.setSelected(true);
+					 }
+					 else {
+						  or_check.setSelected(true);
+					 }
+					 second_method.setSelectedIndex(filter.method_two);
+					 second_value.setSelectedItem(filter.value_two);
+					 second_case.setSelected(filter.casesense_two);
+				}
+				if(filter.sort) {
+					 order.setSelectedIndex(0);
+				}
+				else {
+					 order.setSelectedIndex(1);
+				}
+		  }
+		  // Display	  
+		  show();
+		  dialog.toFront();
+		  return this.filter;
+	 }
+	 /** Use the given key to retrieve a phrase from the dictionary.
+	  * @param key A <strong>String</strong> which uniquely maps to an entry in the Dictionary.
+	  * @return The <strong>String</strong> to key mapped to.
+	  * @see org.greenstone.gatherer.Dictionary
+	  */
+	 private final String get(String key) {
+		  if(key.indexOf(".") == -1) {
+				key = "Autofilter." + key;
+		  }
+		  return Gatherer.dictionary.get(key, (String[])null);
+	 }
+	 /** 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 return_filter;
+		  /** 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.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(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_check.isSelected()) {
+								if(and_check.isSelected()) {
+									 filter.setOperation(Autofilter.AND);
+								}
+								else {
+									 filter.setOperation(Autofilter.OR);
+								}
+								filter.setFilter(2, second_method.getSelectedIndex(), (String)second_value.getSelectedItem(), second_case.isSelected());
+						  }
+					 }
+					 if(order.getSelectedIndex() == 0) {
+						  filter.setSort(Autofilter.ASCENDING);
+					 }
+					 else {
+						  filter.setSort(Autofilter.DESCENDING);
+					 }
+				}
+				else {
+					 filter = null;
+				}
+				hide();
+		  }
+	 }
+	 /** 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/start/gli/src/org/greenstone/gatherer/gui/metaaudit/Filter.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/Filter.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/Filter.java	(revision 13666)
@@ -0,0 +1,150 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+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;
+import org.greenstone.gatherer.gui.metaaudit.Autofilter;
+/** 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) {
+		  boolean result = true;
+		  for(int i = 0; result && i < filters.length; i++) {
+				if(filters[i] != null && filters[i].active()) {
+					 ArrayList values = (ArrayList) model.getValueAt(row, i);
+					 result = result && filters[i].filter(values);
+				}
+		  }
+		  return result;
+	 }
+	 /** 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);
+		  for (Enumeration enum = tmp.elements();
+				 enum.hasMoreElements(); ) {
+				((TableModelFilterListener)enum.nextElement()).filterChanged(event);
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/HeaderListener.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/HeaderListener.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/HeaderListener.java	(revision 13666)
@@ -0,0 +1,93 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+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:      
+ * @author John Thompson, 9826509
+ * @version 2.3
+ **************************************************************************************/
+import de.qfs.lib.gui.TableModelSorter;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import org.greenstone.gatherer.gui.metaaudit.MetaAuditFrame;
+import org.greenstone.gatherer.gui.metaaudit.MetaAuditTable;
+
+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);
+		  MetaAuditModel 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(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/start/gli/src/org/greenstone/gatherer/gui/metaaudit/HeaderRenderer.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/HeaderRenderer.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/HeaderRenderer.java	(revision 13666)
@@ -0,0 +1,76 @@
+package org.greenstone.gatherer.gui.metaaudit;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import javax.swing.*;
+import javax.swing.table.TableCellRenderer;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.metaaudit.MetaAuditTable;
+import org.greenstone.gatherer.util.Utility;
+/** 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.
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public HeaderRenderer() {
+		  setMargin(new Insets(0,0,0,0));
+		  setIcon(Utility.getImage("filter.gif"));
+		  setSelectedIcon(Utility.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());
+		  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/start/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditFrame.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditFrame.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditFrame.java	(revision 13666)
@@ -0,0 +1,218 @@
+package org.greenstone.gatherer.gui.metaaudit;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.Collection;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.util.TreeSynchronizer;
+/** The MetaAuditFrame provides a table view of all of the metadata assigned to a selection of FileNodes. 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 JDialog 
+	 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 FileNode records[];
+	 /** 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,480);
+	 /** The tolerance used to determine between a column resize, and a request for an AutoFilterDialog. */
+	 static final private int TOLERANCE = 3;
+	 /** Constructor.*/
+	 public MetaAuditFrame(TreeSynchronizer tree_sync, FileNode records[]) {
+		  super();
+		  // Arguments
+		  this.autofilter_dialog = new AutofilterDialog(this);
+		  this.records = records;
+		  this.self = this;
+		  this.table = new MetaAuditTable(this);
+		  // Creation
+		  setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
+		  setSize(SIZE);
+		  setTitle(get("Title"));
+
+		  JPanel content_pane = (JPanel) getContentPane();
+		  JPanel button_pane = new JPanel();
+
+		  JButton close_button = new JButton(get("Close"));
+		  close_button.setMnemonic(KeyEvent.VK_C);
+		  // Connection
+		  close_button.addActionListener(new CloseListener());
+		  tree_sync.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 = Gatherer.config.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();
+		  }
+		  show();
+	 }
+	 /** 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) {
+		  if(event.getSource() instanceof JTree) {
+				TreePath paths[] = Gatherer.g_man.metaedit_pane.collection_tree.getSelectionPaths();
+				if(paths != null) {
+					 records = new FileNode[paths.length];
+					 for(int i = 0; i < paths.length; i++) {
+						  records[i] = (FileNode) 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;
+	 }
+
+	 /** Retrieve a phrase from the Dictionary.
+	  * @param key A <strong>String</strong> which uniquely maps to a phrase.
+	  * @return The desired phrase as a </strong>String</strong>.
+	  * @see org.greenstone.gatherer.Dictionary
+	  */
+	 private String get(String key) {
+		  return Gatherer.dictionary.get("MetaAudit." + key);
+	 }
+	 /** 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 apon the close button, and if detected closes the dialog (storing its current size first). */
+	 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.hide();
+		  }
+	 }
+}
+	 
+
+
+
+
+
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditModel.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditModel.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditModel.java	(revision 13666)
@@ -0,0 +1,179 @@
+package org.greenstone.gatherer.gui.metaaudit;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.util.*;
+import java.io.*;
+import javax.swing.table.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.Metadata;
+import org.greenstone.gatherer.msm.MetadataSetManager;
+import org.greenstone.gatherer.valuetree.GValueNode;
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.1 
+ */
+public class MetaAuditModel
+	 extends AbstractTableModel {
+
+	 private ArrayList elements;
+	 private MetadataTableCache data;
+
+	 public MetaAuditModel(FileNode records[]) {
+		  this.elements = new ArrayList(Gatherer.c_man.getCollection().msm.getElements());
+		  Collections.sort(this.elements);
+		  this.data = new MetadataTableCache(elements.size() + 1);
+		  // Work our way through the record array provided, adding files, skipping blanks and recursively searching directories.
+		  for(int i = 0; records != null && i < records.length; i++) {
+				if(records[i] != null) {
+					 addRecord(records[i]);
+				}
+		  }
+	 }
+	 public Class getColumnClass(int column) {
+		  return ArrayList.class;
+	 }
+	 public int getColumnCount() {
+		  return elements.size() + 1;
+	 }
+	 public String getColumnName(int column) {
+		  String result;
+		  if(column == 0) {
+				result = Gatherer.dictionary.get("AuditTable.File");
+		  }
+		  else {
+				result = elements.get(column - 1).toString();
+		  }
+		  return result;
+	 }
+	 public ArrayList getColumnValues(int column) {
+		  ArrayList column_values = new ArrayList();
+		  if(0 <= column && column < getColumnCount()) {
+				for(int i = 0; i < data.size(); i++) {
+					 ArrayList values = (ArrayList) data.get(i, column);
+					 for(int j = 0; j < values.size(); j++) {
+						  column_values.add(values.get(j).toString());
+					 }
+				}
+		  }
+		  return column_values;
+	 }
+	 public int getRowCount() {
+		  return data.size();
+	 }
+	 public Object getValueAt(int row, int column) {
+		  Object result = "";
+		  if(0 <= row && row < data.size() && 0 <= column && column < elements.size() + 1) {
+				result = data.get(row, column);
+		  }
+		  return result;
+	 }
+
+	 public void reset() {
+	 }
+
+	 private void addRecord(FileNode record) {
+		  if(record.isLeaf()) {
+				File file = record.getFile();
+				data.newRow();
+				data.put(0, file.getName());
+				ArrayList metadatum = Gatherer.c_man.getCollection().gdm.getMetadata(file);
+				for(int i = 0; i < metadatum.size(); i++) {
+					 Metadata metadata = (Metadata) metadatum.get(i);
+					 data.put(elements.indexOf(metadata.getElement()) + 1, metadata.getValueNode());
+				}
+		  }
+		  else {
+				for(int i = 0; i < record.getChildCount(); i++) {
+					 addRecord((FileNode)record.getChildAt(i));
+				}
+		  }
+	 }
+
+	 private class MetadataTableCache {
+		  private ArrayList data;
+		  private ArrayList current_row[];
+		  private int columns;
+		  private RowComparator row_comparator = new RowComparator();
+		  public MetadataTableCache(int columns) {
+				this.columns = columns;
+				this.data = new ArrayList();
+		  }
+
+		  public ArrayList get(int row, int column) {
+				ArrayList array_list[] = (ArrayList[]) data.get(row);
+				return array_list[column];
+		  }
+
+		  public void newRow() {
+				if(current_row != null) {
+					 for(int i = 0; i < columns; i++) {
+						  Collections.sort(current_row[i], row_comparator);
+					 }
+				}
+				current_row = new ArrayList[columns];
+				for(int i = 0; i < columns; i++) {
+					 current_row[i] = new ArrayList();
+				}
+				data.add(current_row);
+		  }
+
+		  public void put(int column, Object value) {
+				current_row[column].add(value);
+		  }
+
+		  public int size() {
+				return data.size();
+		  }
+	 }
+
+	 private class RowComparator
+		  implements Comparator {
+		  public int compare(Object o1, Object o2) {
+				return o1.toString().compareTo(o2.toString());
+		  }
+		  public boolean equals(Object obj) {
+				return toString().equals(obj.toString());
+		  }
+	 }
+}
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditRenderer.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditRenderer.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditRenderer.java	(revision 13666)
@@ -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.
+ *
+ * <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.Component;
+import java.awt.GridLayout;
+import java.util.ArrayList;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTable;
+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/start/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditTable.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditTable.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/metaaudit/MetaAuditTable.java	(revision 13666)
@@ -0,0 +1,204 @@
+package org.greenstone.gatherer.gui.metaaudit;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+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.Gatherer;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.gui.metaaudit.Filter;
+import org.greenstone.gatherer.gui.metaaudit.HeaderListener;
+import org.greenstone.gatherer.gui.metaaudit.HeaderRenderer;
+import org.greenstone.gatherer.gui.metaaudit.MetaAuditFrame;
+import org.greenstone.gatherer.gui.metaaudit.MetaAuditModel;
+import org.greenstone.gatherer.gui.metaaudit.MetaAuditRenderer;
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class MetaAuditTable
+	 extends JTable 
+	 implements TableModelSorterListener {
+
+	 private boolean initial_state;
+
+	 private boolean ready;
+
+	 private Filter filter;
+
+	 private HeaderRenderer header_renderer;
+
+	 private MetaAuditFrame parent_frame;
+
+	 private MetaAuditModel model;
+
+	 private SortedTableHelper helper;
+
+	 static final private int MARGIN = 10;
+
+	 public MetaAuditTable(MetaAuditFrame parent_frame) {
+		  super();
+		  this.header_renderer = new HeaderRenderer();
+		  this.parent_frame = parent_frame;
+		  getTableHeader().addMouseListener(new HeaderListener(parent_frame, this));
+		  setAutoResizeMode(AUTO_RESIZE_OFF);
+		  setDefaultRenderer(ArrayList.class, new MetaAuditRenderer());
+		  ready = true;
+	 }
+
+	 public Filter getFilter() {
+		  return filter;
+	 }
+
+	 public MetaAuditModel getOriginalModel() {
+		  return model;
+	 }
+
+	 public TableModelSorter getSorter() {
+		  return helper.getTableModelSorter();
+	 }
+
+	 public boolean isFiltered(int column) {
+		  if(filter == null) {
+				return false;
+		  }
+		  return filter.isFiltered(column);
+	 }
+
+	 public void newModel(FileNode records[]) {
+		  if(records == null || records.length == 0) {
+				return;
+		  }
+		  wait(true);
+		  initial_state = true;
+		  ///ystem.err.println("Build new Model - should only be called once per click!");
+		  model = new MetaAuditModel(records);
+		  setModel(model);
+		  filter = new Filter(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).setHeaderRenderer(header_renderer);
+		  }
+		  wait(false);
+		  initial_state = false;
+	 }
+
+	 public void tableChanged(TableModelEvent e) {
+		  wait(true);
+		  super.tableChanged(e);
+		  if(ready) {
+				// 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;
+									 }
+									 temp = null;
+								}
+								if(widths[k] == null || longest.length() > widths_value[k]) {
+									 widths_value[k] = longest.length();
+									 widths[k] = data;
+								}
+								longest = null;
+								data = null;
+						  }
+					 }
+				}
+				// Now assign the dimensions we have determined to be the largest.
+				TableCellRenderer renderer = getDefaultRenderer(ArrayList.class);
+				for(int l = 0; l < heights.length; l++) {
+					 if(heights[l] != null) {
+						  Component component = renderer.getTableCellRendererComponent(this, heights[l], false, false, 0, 0);
+						  Dimension size = component.getPreferredSize();
+						  setRowHeight(l, size.height);
+						  size = null;
+						  component = null;
+					 }
+				}
+				heights = null;
+				for(int m = 0; m < widths.length; m++) {
+					 if(widths[m] != null) {
+						  Component component = 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);
+						  size = null;
+						  component = null;
+					 }
+				}
+				widths = null;
+				renderer = null;
+		  }
+		  wait(initial_state);
+	 }
+
+	 public void sortOrderChanged(TableModelSorterEvent event) {
+	 }
+
+	 private void wait(boolean waiting) {
+		  if(parent_frame != null) {
+				parent_frame.wait(waiting);
+		  }
+	 }
+}
+
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/table/GTable.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/table/GTable.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/table/GTable.java	(revision 13666)
@@ -0,0 +1,87 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+package org.greenstone.gatherer.gui.table;
+/**************************************************************************************
+ * Title:        Gatherer
+ * Description:  The Gatherer: a tool for gathering and enriching a digital collection.
+ * Company:      The University of Waikato
+ * Written:        /  /02
+ * Revised:      20/08/02 Commented and Optimized.
+ * @author John Thompson, 9826509
+ * @version 2.3
+ **************************************************************************************/
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JTable;
+import javax.swing.table.TableCellRenderer;
+
+public class GTable
+	 extends JTable {
+	 
+	 private boolean building = false;
+	 private JLabel label = null;
+	 public GTable() {
+		  // First draw the background image - tiled 
+		  label = new JLabel("<HTML><FONT SIZE=5>Building Collection</FONT></HTML>");
+		  //label.setHorizontalAlignment(JLabel.CENTER);
+		  //label.setVerticalAlignment(JLabel.CENTER);
+		  //label.setSize(new Dimension(505, 200));
+	 }
+	 
+	 public synchronized void setBuilding(boolean building) {
+		  this.building = building;
+		  repaint();
+	 }
+
+	 public void paint(Graphics g) {
+		  // Now let the regular paint code do it's work
+		  super.paint(g);
+		  //if(building) {
+				label.paint(g);
+				//}
+	 }	 
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/table/GTableCellEditor.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/table/GTableCellEditor.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/table/GTableCellEditor.java	(revision 13666)
@@ -0,0 +1,128 @@
+/**
+ *#########################################################################
+ *
+ * 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.table;
+
+import java.awt.Component;
+import javax.swing.DefaultCellEditor;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.msm.Metadata;
+import org.greenstone.gatherer.gui.combobox.GComboBox;
+import org.greenstone.gatherer.gui.combobox.GComboBoxModel;
+/** This implementation of the TableCellRenderer interface allows for us
+ * to return a GComboBox with the correct model given a reference to the
+ * original metadata row within the given table. All edit calls, other than
+ * those from the third column, ie the values column, get the default 
+ * editor component.
+ */
+public class GTableCellEditor
+	 extends DefaultCellEditor {
+
+	 private Gatherer        gatherer      = null;
+
+	 private GComboBox      editor       = null;
+
+	 private GComboBoxModel editor_model = null;
+
+	 /** The default constructor simply add the standard new argument, a 
+	  * reference to the Gatherer class.
+	  * @param gatherer A reference to Gatherer for communication and dictionary 
+	  * purposes.
+	  */
+	 public GTableCellEditor(Gatherer gatherer) {
+		  super(new JTextField());
+		  this.gatherer = gatherer;
+	 }
+
+	 /** This method returns the currently selected value of our editor
+	  * GCombobox.
+	  * @return An Object which is the selected items value.
+	  */
+	 public Object getCellEditorValue() {
+		  return editor.getSelectedItem();
+	 }
+
+	 /** Returns a reference to the editor GComboBox.
+	  * @return A Component reference to our editor.
+	  */
+	 public Component getComponent() {
+		  return editor;
+	 }
+
+	 /** This method is called to retrieve the correct editor component for
+	  * a certain row and column within the target JTable. It is here that
+	  * we create the custom GComboBox for each row of the 'values' column
+	  * using a different model for each. If the call comes from any other 
+	  * column (which it shouldn't but what the hell) we let the super
+	  * handle it which returns a plain old JTextField as the editing component.
+	  * @param table The JTable which called this method.
+	  * @param value The initial value of the cell this editor will be used
+	  * for, as an Object. Format this to suit the editor you wish to return.
+	  * @param isSelected A Boolean specifying whether the selected cell
+	  * is currently highlighted in such a way so as to allow the user to
+	  * know it is being edited.
+	  * @param row An Int specifying the cells row.
+	  * @param column An Int specifying the cells column.
+	  * @return A Component which will be placed in the table as the method
+	  * of editing the specified cell.
+	  */
+	 public Component getTableCellEditorComponent(JTable table, Object value,
+																 boolean isSelected, int row,
+																 int column) {
+		  GTableModel model = (GTableModel)table.getModel();
+		  // Create a new GComboBox with a model based on the selected
+		  // records metadata.
+		  Metadata selected_metadata = model.getMetadataAtRow(row);
+		  //editor_model = gatherer.c_man.getCollection().getValueModel
+		  //	(selected_metadata.element);
+		  editor = new GComboBox(editor_model);
+		  editor.setEditable(true);
+		  // Make sure that value is the currently selected option in the 
+		  // editor.
+		  editor.setSelectedItem(value);
+		  // Done.
+		  return editor;
+	 }
+}
+
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/table/GTableModel.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/table/GTableModel.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/table/GTableModel.java	(revision 13666)
@@ -0,0 +1,579 @@
+package org.greenstone.gatherer.gui.table;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.io.File;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.table.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.gui.WarningDialog;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.Metadata;
+import org.greenstone.gatherer.msm.MSMAction;
+import org.greenstone.gatherer.msm.MSMEvent;
+import org.greenstone.gatherer.msm.MSMListener;
+import org.greenstone.gatherer.util.ArrayTools;
+/** Provides the model for a GTable component, filling it with metadata values for the choosen files or folders. The model also provides several different view of this data; assigned folder metadata, assigned file metadata, all assigned metadata, unassigned metadata, and all metadata. It also differentiates between metadata that is common to all of the files or folders, and that which isn't. The building of the actual model is done on a separate thread so that the gui remains responsive, and the gui is intermitantly updated by this thread. Updating of the model is triggered by events recieved from the metadata set manager in terms of new or obsolete metadata. A new model is rebuilt whenever the user selects a different group of files or folders.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3b
+ */
+public class GTableModel 
+	 extends AbstractTableModel 
+	 implements MSMListener {
+	 /** The source for the data currently shown in the table. May be any of the other three metadata lists, or the union of all of them. */
+	 private ArrayList current_metadata    = new ArrayList();
+	 /** The metadata currently assigned at the file level. */
+	 private ArrayList file_metadata       = new ArrayList();
+	 /** The metadata currently assigned at the folder level. */
+	 private ArrayList inherited_metadata  = new ArrayList();
+	 /** The metadata currently unassigned. */
+	 private ArrayList unassigned_metadata = new ArrayList();
+	 /** The file nodes this model is built upon. */
+	 private FileNode[] file_nodes;
+	 /** The current view. */
+	 private int current_view;
+
+	 private JToggleButton assigned_metadata_view;
+	 private JToggleButton unassigned_metadata_view;
+
+	 /** An icon showing the current state of the table build. */
+	 private JProgressBar activity_bar;
+	 /** The table this model is being displayed in. */
+	 private JTable table;
+
+	 private ModelBuilder builder;
+
+	 static final public int SHOW_ALL         = 0;
+	 static final public int SHOW_ASSIGNED    = 1;
+	 static final public int SHOW_FILE        = 2;
+	 static final public int SHOW_INHERITED   = 3; 
+	 static final public int SHOW_UNASSIGNED  = 4;
+	 static final private String[] COLUMN_NAMES = {"", Gatherer.dictionary.get("Metadata.Element"),  Gatherer.dictionary.get("Metadata.Value")};
+
+	 /** The default constructor creates a new empty model with the current view set to an emtpy 'all metadata'. */
+	 public GTableModel(JTable table, JToggleButton assigned_metadata_view, JToggleButton unassigned_metadata_view, JProgressBar activity_bar) {
+		  this.activity_bar = activity_bar;
+		  this.assigned_metadata_view = assigned_metadata_view;
+		  this.builder = null;
+		  this.table = table;
+		  this.unassigned_metadata_view = unassigned_metadata_view;
+		  changeView();
+		  // Register this model with the msm manager.
+		  if(Gatherer.c_man.ready()) {
+				Gatherer.c_man.getCollection().msm.addMSMListener(this); 
+		  }
+	 }
+
+	 /** This constuctor starts by creating an empty model then, using a separate model builder thread, builds a model from the given files. */
+	 public GTableModel(JTable table, JToggleButton assigned_metadata_view, JToggleButton unassigned_metadata_view, JProgressBar activity_bar, FileNode[] file_nodes) {
+		  this(table, assigned_metadata_view, unassigned_metadata_view, activity_bar);
+		  this.file_nodes = file_nodes;
+		  if(file_nodes != null && file_nodes.length > 0) {
+				// Create model builder
+				builder = new ModelBuilder();
+				builder.start();
+		  }
+	 }
+
+	 public void changeView() {
+		  boolean show_assigned = assigned_metadata_view.isSelected();
+		  boolean show_unassigned = unassigned_metadata_view.isSelected();
+		  if(show_assigned && show_unassigned) {
+				changeView(SHOW_ALL);
+		  }
+		  else if(show_assigned) {
+				changeView(SHOW_ASSIGNED);
+		  }
+		  else { // Show unassigned
+				changeView(SHOW_UNASSIGNED);
+		  }
+	 }
+
+	 /** Change the current view by changing the model that the table is currently based on. */
+	 public void changeView(int view) {
+		  current_view = view;
+		  switch(view) {
+		  case SHOW_ASSIGNED:
+				///ystem.err.println("Show assigned");
+				current_metadata = new ArrayList();
+				current_metadata.addAll(file_metadata);
+				current_metadata.addAll(inherited_metadata);
+				Collections.sort(current_metadata);
+				break;
+		  case SHOW_FILE:
+				///ystem.err.println("Show file");
+				current_metadata = file_metadata;
+				break;
+		  case SHOW_INHERITED:
+				///ystem.err.println("Show inherited");
+				current_metadata = inherited_metadata;
+				break;
+		  case SHOW_UNASSIGNED:
+				///ystem.err.println("Show unassigned");
+				current_metadata = unassigned_metadata;
+				break;
+		  default:
+				// SHOW_ALL
+				///ystem.err.println("Show all");
+				// Create a new array from the three other arrays.
+				current_metadata = new ArrayList();
+				current_metadata.addAll(file_metadata);
+				current_metadata.addAll(inherited_metadata);
+				current_metadata.addAll(unassigned_metadata);
+				Collections.sort(current_metadata);
+		  }
+		  // Inform everyone that the model has changed.
+		  fireTableDataChanged();
+	 }  
+
+	 /** Called whenever an element in a set is added, edited or removed from the metadata set manager. We listen for this just incase the name of one of the elements currently shown changes. After that the table will be up to date, as the element references are otherwise live. */
+	 public void elementChanged(MSMEvent event) {
+		  MSMAction profile = event.getProfile();
+		  if(profile != null) {
+				// Retrieve the elements new name (thats hopefully what will be returned by getValue()).
+				String name = profile.getTarget();
+				int row = 0;
+				for( ; row < current_metadata.size(); row++) {
+					 if(getValueAt(row, 0).equals(name)) {
+						  fireTableCellUpdated(row, 0);
+					 }
+				}
+				name = null;
+		  }
+		  profile = null;
+		  event = null;
+	 }
+
+	 /** Returns the number of columns in this table. */
+	 public int getColumnCount() {
+		  return COLUMN_NAMES.length;
+	 }
+
+	 /** Returns the data class of the specified column. */
+	 public Class getColumnClass(int col) {
+		  if(col == 2) {
+				return JButton.class;
+		  }
+		  return String.class;
+	 }
+
+	 /** Retrieves the name of the specified column. */
+	 public String getColumnName(int col) {
+		  return COLUMN_NAMES[col];
+	 }
+
+	 /* Called to retrieve the Metadata record that matches a certain row. Usually caused by the user selectiong a row in the table. It synchronized so that the model doesn't up and change while we're trying to retrieve the indicated element. */
+	 public synchronized Metadata getMetadataAtRow(int row) {
+		  if(0 <= row && row < current_metadata.size()) {
+				return (Metadata) current_metadata.get(row);
+		  }
+		  return null;
+	 }
+
+	 /** Returns the number of rows in this table. */
+	 public int getRowCount() {
+		  return current_metadata.size();
+	 }
+
+	 /** Returns the cell value at a given row and column as an Object. */
+	 public Object getValueAt(int row, int col) {
+		  Object result = "";
+		  if(0 <= row && row < current_metadata.size()) {
+				Metadata m = (Metadata) current_metadata.get(row);
+				if(0 <= col && col < COLUMN_NAMES.length) {
+					 switch(col) {
+					 case 0:
+						  if(!m.isFileLevel()) {
+								result = m.getFile();
+						  }
+						  break;
+					 case 1:
+						  ElementWrapper element = m.getElement();
+						  if(element != null) {
+								result = element.toString();
+						  }
+						  break;
+					 case 2:
+						  result = m.getValue();
+						  break;
+					 case 3:
+						  result = (m.isFileLevel() ? "true" : "false");
+						  break;
+					 }
+				}
+		  }
+		  return result;
+	 }
+	 
+	 /** Allows access to this models current view. */
+	 public int getView() {
+		  return current_view;
+	 }
+
+	 /** Determine if the given metadata is common to all selected file nodes given the context of the current view. */
+	 public boolean isCommon(int row) {
+		  if(0 <= row && row < current_metadata.size()) {
+				Metadata entry = (Metadata) current_metadata.get(row);
+				///ystem.err.println("There are " + file_nodes.length + " selected files.");
+				///ystem.err.println("This metadata is attached to " + entry.getCount() + " of them.");
+				if(entry.getCount() == file_nodes.length) {
+					 return true;
+				}
+		  }
+		  return false;
+	 }
+
+	 /** Whenever there is a metadata change we must determine if there are any changes to our various lists of metadata, and also if there is any need to refresh the table currently being viewed. */
+	 public void metadataChanged(MSMEvent event) {
+		  FileNode file_node = event.getRecord();
+		  ///ystem.err.println("File node effected");
+		  // First check whether this record is one of those that we have showing.
+		  if(file_nodes != null && file_node != null && ArrayTools.contains(file_nodes, file_node)) {
+				Metadata old_data = event.getOldMetadata();
+				Metadata new_data = event.getNewMetadata();
+				// If old metadata has been removed then remove it. Update the unassigned list if necessary (first checking if there are other metadata entries with the same element, and furthermore if the were inherited metadata being supressed).
+				if(old_data != null) {
+					 ///ystem.err.println("Remove: " + old_data);
+					 // Determine the level of this metadata
+					 ArrayList modified_metadata;
+					 if(old_data.isFileLevel()) {
+						  modified_metadata = file_metadata;
+					 }
+					 else {
+						  modified_metadata = inherited_metadata;
+					 }
+					 int index = -1;
+					 if((index = modified_metadata.indexOf(old_data)) != -1) {
+						  Metadata data = (Metadata) modified_metadata.get(index);
+						  data.dec();
+						  // If we just removed the last occurance of this metadata, delete it
+						  if(data.getCount() == 0) {
+								remove(modified_metadata, data);
+								// If there are no further occurances of the element of this entry, add entry to unassigned_metadata.
+								boolean found = false;
+								ElementWrapper element = data.getElement();
+								// Search the current metadata
+								for(int i = 0; i < modified_metadata.size(); i++) {
+									 Metadata sibling = (Metadata) modified_metadata.get(i);
+									 if(sibling.getElement().equals(element)) {
+										  found = true;
+									 }
+								}
+								// And the inherited metadata if we haven't already
+								if(modified_metadata != inherited_metadata) {
+									 for(int i = 0; !found && i < inherited_metadata.size(); i++) {
+										  Metadata sibling = (Metadata) inherited_metadata.get(i);
+										  if(sibling.getElement().equals(element)) {
+												found = true;
+										  }
+									 }
+								}
+								// If we get this far and still haven't found a match then we do something very tricky. We retrieve all of the metadata for the parent file and notice any inherited nodes that were previously overwritten by the metadata entry we removed. The reason we use the parent is that we can't just assume that the GDMDocument changes occured before this method was called. Thus our about-to-be-removed overwritting metadata may still be in effect if we just called getMetadata for this file.
+								if(!found) {
+									 ArrayList parent_metadatum = Gatherer.c_man.getCollection().gdm.getMetadata((file_node.getFile()).getParentFile());
+									 // For each piece of parent metadata
+									 for(int i = parent_metadatum.size(); i > 0; i--) {
+										  Metadata parent_metadata = (Metadata) parent_metadatum.get(i - 1);
+										  // If we found some previously suppressed metadata then add it and say we found something.
+										  if(!inherited_metadata.contains(parent_metadata)) {
+												///ystem.err.println("Restoring overwritten inherited metadata: " + parent_metadata);
+												found = true;
+												parent_metadata.setCount(1);
+												parent_metadata.setFileLevel(false); // Has to be folder level doesn't it.
+												add(inherited_metadata, parent_metadata);
+										  }
+									 }
+									 // Run this getMetadata again to restore all of the file level and source file entries (they would have changed to reflect the parents call.
+									 Gatherer.c_man.getCollection().gdm.getMetadata(file_node.getFile());
+								}
+								// And only then, if we haven't found a substitute, may we add a null metadata.
+								if(!found) {
+									 add(unassigned_metadata, new Metadata(data.getElement()));
+								}
+						  }
+					 }
+				}
+				// If new metadata has been assigned, remove its entry from the unassigned metadata list. Furthermore add the new entry to either the file or folder metadata list depending on its level. Remember to rebuild the common metadata lists.
+				if(new_data != null) {
+					 ///ystem.err.println("Add: " + new_data);
+					 // Create dummy 'unassigned' metadata from the new metadata and remove it from the unassigned list (if its even there)
+					 remove(unassigned_metadata, new Metadata(new_data.getElement()));
+					 // Determine if we are adding the new node at the file or folder level.
+					 ArrayList modified_metadata;
+					 if(new_data.isFileLevel()) {
+						  modified_metadata = file_metadata;
+						  // If its file metadata, and its set to overwrite, then we need to remove any row it would overwrite.
+						  if(new_data.accumulates()) {
+								// All good.
+						  }
+						  else {
+								// Remove any entries in the inherited_metadata that would be overwritten
+								ElementWrapper element = new_data.getElement();
+								for(int i = 0; i < inherited_metadata.size(); i++) {
+									 Metadata sibling = (Metadata) inherited_metadata.get(i);
+									 if(sibling.getElement().equals(element)) {
+										  inherited_metadata.remove(sibling);
+									 }
+								}
+						  }
+					 }
+					 else {
+						  modified_metadata = inherited_metadata;
+					 }
+					 // And add it.
+					 int index = -1;
+					 if((index = modified_metadata.indexOf(new_data)) == -1) {
+						  add(modified_metadata, new_data);
+						  new_data.setCount(1);
+					 }
+					 else {
+						  Metadata data = (Metadata) modified_metadata.get(index);
+						  data.inc();
+						  data = null;
+					 }
+					 modified_metadata = null;
+				}
+				// As a current visible table is most likely affected, update the table component. We do this by calling changeView so as to also update any compound list.
+				changeView(current_view);
+		  }
+		  else {
+				///ystem.err.println("FileNodes = " + file_nodes);
+				///ystem.err.println("FileNode = " + file_node);
+		  }
+	 }
+
+	 /** Called whenever a set is added or removed from the metadata set manager. */
+	 public void setChanged(MSMEvent event) {
+		  // No, don't care. Still don't care. Couldn't care less.
+	 }
+
+	 public Rectangle setSelectedMetadata(Metadata data) {
+		  Rectangle bounds = null;
+		  if(builder.complete) {
+				for(int i = 0; i < getRowCount(); i++) {
+					 if(getMetadataAtRow(i).equals(data)) {
+						  ///ystem.err.println("Found matching metadata at row " + i + " (of " + getRowCount() + " rows)");
+						  ///ystem.err.println("Table shows " + table.getRowCount() + " rows!");
+						  bounds = table.getCellRect(i, 0, true);
+						  table.scrollRectToVisible(bounds);
+						  table.setRowSelectionInterval(i, i);
+					 }
+				}
+		  }
+		  else {
+				builder.selected_metadata = data;
+		  }
+		  return bounds;
+	 }
+
+	 public int size() {
+		  return file_nodes.length;
+	 }
+
+	 /** Called when the value tree of a certain element has changed significantly but, although we display metadata values, we only care about those coming through metadataChanged() events. */
+	 public void valueChanged(MSMEvent event) {
+		  // Don't care. Tra-la-la-la-la.
+	 }
+
+	 /** Alphabetically inserts the new_metadata in the target vector. */
+	 private int add(ArrayList target, Metadata new_metadata) {
+		  int i = 0;
+		  while(i < target.size()) {
+				Metadata current = (Metadata)target.get(i);
+				if(current.compareTo(new_metadata) > 0) {
+					 target.add(i, new_metadata);
+					 return i;
+				}
+				i++;
+		  }
+		  target.add(new_metadata);
+		  return i;
+	 }
+
+	 /** Remove a certain piece of data from a certain vector. */
+	 private void remove(ArrayList target, Metadata old_metadata) {
+		  if(target != null) {
+				for(int i = 0; i < target.size(); i++) {
+					 Metadata current_metadata = (Metadata) target.get(i);
+					 if(current_metadata.equals(old_metadata)) {
+						  target.remove(current_metadata);
+						  return;
+					 }
+				}
+		  }
+	 }
+
+	 private class ModelBuilder
+		  extends Thread {
+
+		  public boolean had_warning = false;
+
+		  public boolean complete = false;
+
+		  public Metadata selected_metadata = null;;
+		  
+		  public void run() {
+				Vector elements = Gatherer.c_man.getCollection().msm.getElements();
+				// Show some visual indication that building is occuring.
+				assigned_metadata_view.setEnabled(false);
+				unassigned_metadata_view.setEnabled(false);
+				activity_bar.setMaximum(file_nodes.length + elements.size());
+				activity_bar.setValue(0);
+				activity_bar.setString(Gatherer.dictionary.get("MetaEdit.Building"));
+				//long start = System.currentTimeMillis();
+				
+				ArrayList known_elements = new ArrayList(); // Elements that have metadata assigned.
+				for(int i = 0; i < file_nodes.length; i++) {
+					 File current_file = file_nodes[i].getFile();
+					 // The current assigned metadata for this file.
+					 ArrayList metadatum = Gatherer.c_man.getCollection().gdm.getAllMetadata(current_file);
+					 for(int j = 0; j < metadatum.size(); j++) {
+						  Metadata data = (Metadata) metadatum.get(j);
+						  // Determine the target list by the metadata level
+						  ArrayList modified_metadata;
+						  if(data.isFileLevel()) {
+								modified_metadata = file_metadata;
+						  }
+						  else {
+								showInheritedMetadataWarning();
+								modified_metadata = inherited_metadata;
+						  }
+						  int index = -1;
+						  // Don't show hidden metadata
+						  // If the given metadata already exists in our list of modified metadata then increment its commonality count.
+						  if((index = modified_metadata.indexOf(data)) != -1) {
+								data = (Metadata) modified_metadata.get(index);
+								///ystem.err.println("Increasing count:" + element);
+								data.inc();
+								// If the table shown is stale, refresh it.
+								if((modified_metadata == file_metadata && current_view == SHOW_FILE) || (modified_metadata == inherited_metadata && current_view == SHOW_INHERITED)) {
+									 fireTableRowsUpdated(index, index);
+								}
+								// We may have to update a compound list
+								else if(current_view == SHOW_ALL || current_view == SHOW_ASSIGNED) {
+									 if((index = current_metadata.indexOf(data)) == -1) {
+										  fireTableRowsUpdated(index, index);
+									 }
+								}
+						  }
+						  // Ensure the metadata's element is in our list of showable elements.
+						  else if(contains(elements, data.getElement())) {
+								///ystem.err.println("Setting count to one: " + element);
+								data.setCount(1);
+								index = add(modified_metadata, data); // Add to assigned metadata.
+								known_elements.add(data.getElement());
+								// If the table shown is stale, refresh it.
+								if((modified_metadata == file_metadata && current_view == SHOW_FILE) || (modified_metadata == inherited_metadata && current_view == SHOW_INHERITED)) {
+									 fireTableRowsInserted(index, index);
+								}
+								// We may have to update a compound list
+								else if(current_view == SHOW_ALL || current_view == SHOW_ASSIGNED) {
+									 if((index = current_metadata.indexOf(data)) == -1) {
+										  index = add(current_metadata, data);
+										  fireTableRowsInserted(index, index);
+									 }
+									 else {
+										  fireTableRowsUpdated(index, index);
+										  
+									 }
+								}
+						  }
+						  else {
+								///ystem.err.println("No.\n***** Cannot match element so it must be hidden, right? *****");
+						  }
+					 }
+					 activity_bar.setValue(activity_bar.getValue() + 1);
+					 Gatherer.g_man.metaedit_pane.validateMetadataTable();
+				}
+				// Add entries for the currently unassigned metadata. You can determine these as the difference between elements and known_elements.
+				for(int k = 0; k < elements.size(); k++) {
+					 // For each key.
+					 ElementWrapper element = (ElementWrapper) elements.get(k);
+					 if(!known_elements.contains(element)) {
+						  Metadata data = new Metadata(element);
+						  int index = add(unassigned_metadata, data);
+						  // Inform everyone that the model has changed, but only if it affects the current view.
+						  if(current_view == SHOW_UNASSIGNED) {
+								fireTableRowsInserted(index, index);
+						  }
+						  else if(current_view == SHOW_ALL) {
+								if((index = current_metadata.indexOf(data)) == -1) {
+									 index = add(current_metadata, data);
+									 fireTableRowsInserted(index, index);
+								}
+								else {
+									 fireTableRowsUpdated(index, index);
+								}
+						  }
+					 }
+					 activity_bar.setValue(activity_bar.getValue() + 1);
+					 Gatherer.g_man.metaedit_pane.validateMetadataTable();
+				}
+				//long end = System.currentTimeMillis();
+				///ystem.err.println("Took " + (end - start) + "ms to build table.");
+				assigned_metadata_view.setEnabled(true);
+				unassigned_metadata_view.setEnabled(true);
+				activity_bar.setValue(activity_bar.getMaximum());
+				activity_bar.setString(Gatherer.dictionary.get("MetaEdit.Ready"));
+				// Finally complete
+				complete = true;
+				// If in the in between we've been asked to select a certain metadata, we action that now.
+				if(selected_metadata != null) {
+					 setSelectedMetadata(selected_metadata);
+				}
+		  }
+
+		  /** For some reason contains doesn't always work. It appear not to use equals() properly, as ElementWrappers need to compare themselves by their string content as other data members are nearly always different even between to ElementWrappers generated from the same DOM Element. */
+		  private boolean contains(Vector elements, ElementWrapper element) {
+				if(element != null) {
+					 for(int i = 0; i < elements.size(); i++) {
+						  if(element.equals(elements.get(i))) {
+								return true;
+						  }
+					 }
+				}
+				return false;
+		  }
+
+		  private void showInheritedMetadataWarning() {
+				if(!had_warning) {
+					 had_warning = true;
+					 Runnable task = new Runnable() {
+								public void run() {
+									 WarningDialog dialog = new WarningDialog("warning.InheritedMetadata", false);
+									 dialog.display();
+									 dialog.dispose();
+									 dialog = null;
+								}
+						  };
+					 SwingUtilities.invokeLater(task);
+				}
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/table/TableCellRenderer.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/table/TableCellRenderer.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/table/TableCellRenderer.java	(revision 13666)
@@ -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.gui.table;
+
+import java.awt.*;
+import java.io.*;
+import javax.swing.*;
+import javax.swing.table.DefaultTableCellRenderer;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.table.GTableModel;
+import org.greenstone.gatherer.msm.Metadata;
+import org.greenstone.gatherer.util.Utility;
+
+public class TableCellRenderer
+	 extends DefaultTableCellRenderer {
+
+	 private GTableModel model = null;
+
+	 public TableCellRenderer(GTableModel model) {
+		  super();
+		  this.model = model;
+	 }
+
+	 /** 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 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>.
+	  * @param hasFocus <i>true</i> if cell has focus, 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.
+	  * @return The default table cell renderer <strong>Component</strong>.
+	  */
+	 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+		  JLabel renderer = null;
+		  if(value instanceof File) {
+				if(value != null) {
+					 if(isSelected && hasFocus) {
+						  Metadata data = model.getMetadataAtRow(row);
+						  Gatherer.g_man.metaedit_pane.setSelection((File)value);
+						  Gatherer.g_man.metaedit_pane.setSelectedMetadata(data);
+					 }
+					 renderer = new JLabel(Utility.getImage("upfolder.gif"));
+				}
+		  }
+		  if(renderer == null) {
+				renderer = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+		  }
+		  // Set up the component
+		  renderer.setOpaque(true);
+		  // Foreground
+		  if(model.isCommon(row)) {
+				renderer.setForeground(Color.black);
+		  }
+		  else {
+				renderer.setForeground(Color.gray);
+		  }
+		  // Background
+		  if(column <= 1) {
+				if(isSelected) {
+					 renderer.setBackground(Gatherer.config.getColor("coloring.workspace_heading_background", true));
+				}
+				else {
+					 renderer.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", true));
+				}
+		  }
+		  else {
+				if(isSelected) {
+					 renderer.setBackground(Gatherer.config.getColor("coloring.workspace_heading_background", true));
+				}
+				else {
+					 renderer.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", true));
+				}
+		  }
+		  // Finally the 3rd column of cells never paint focus.
+		  if(column == 2) {
+				renderer.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
+		  }
+		  return renderer;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/tree/DragTree.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/tree/DragTree.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/tree/DragTree.java	(revision 13666)
@@ -0,0 +1,596 @@
+package org.greenstone.gatherer.gui.tree;
+
+import java.awt.*;
+import java.awt.datatransfer.*;
+import java.awt.dnd.*;
+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.tree.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.file.FileSystemModel;
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.DragComponent;
+import org.greenstone.gatherer.util.DragGroup;
+import org.greenstone.gatherer.util.DragTreeSelectionModel;
+
+public 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 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 identifying name of this Tree. */
+	 private String name;
+	 /** The last tree path the drag was hovered over. */
+	 private TreePath previous_path = 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;
+
+	 public DragTree(String name, String background_name) {
+		  super();
+		  init(name, background_name);
+	 }
+
+	 public DragTree(String name, TreeModel model, String background_name) {
+		  super(model);
+		  init(name, background_name);
+		  // Connection
+		  setModel(model);
+	 }
+
+	 public void init(String name, String background_name) {
+		  // Init
+		  this.name = name;
+		  if(background_name != null) {
+				this.disabled_background = new ImageIcon("background.gif");
+				this.normal_background = new ImageIcon(background_name);
+		  }
+
+		  // Creation
+		  this.putClientProperty("JTree.lineStyle", "Angled");
+		  this.setAutoscrolls(true);
+		  this.setEditable(false);
+		  this.setLargeModel(true);
+		  this.setOpaque(true);
+		  this.setSelectionModel(new DragTreeSelectionModel(this));
+		  // Connection
+		  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);
+
+		  // 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) {
+		  if(event.getDropSuccess()) {
+				// Do whatever I do when the drop is successful.
+		  }
+	 }
+ 	 /** 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) {
+		  // 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);
+		  }
+		  // 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.
+		  if(path != null) {
+				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() + " 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, new Point(5,5), 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()) {
+				// 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(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)) {
+					 ///ystem.err.println("Valid. Painting cues.");
+					 // 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);
+		  event.acceptDrop(drag_action);
+		  // Determine what node we dropped over. The current valid drop path, if any, is stored in previous path.
+		  if(previous_path != null && isValidDrop(previous_path)) {
+				///ystem.err.println("Valid drop.");
+				FileNode target = (FileNode) previous_path.getLastPathComponent();
+				TreePath[] selection = group.getSelection();
+				if(target != 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;
+		  }
+		  else {
+				///ystem.err.println("Not a valid drop.");
+		  }
+		  // Clear up the group.image_ghost
+		  paintImmediately(ra_ghost.getBounds());
+		  event.getDropTargetContext().dropComplete(true);
+	 }
+
+	 /** 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 String getSelectionDetails() {
+		  return ((DragTreeSelectionModel)selectionModel).getDetails();
+	 }
+
+	 public FileSystemModel getTreeModel() {
+		  return (FileSystemModel) getModel();
+	 }
+
+	 /** 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 mapDirectory(File file, String title) {
+		  try {
+				((FileSystemModel)treeModel).mapDirectory(file, title);
+		  }
+		  catch (Exception error) {
+				error.printStackTrace();
+		  }
+	 }
+
+	 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) {
+		  ((FileSystemModel)treeModel).refresh(path);
+	 }
+
+	 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);
+		  clearSelection();
+		  // 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);
+				addTreeExpansionListener(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 String toString() {
+		  return name;
+	 }
+
+	 public void valueChanged(TreeSelectionEvent e) {
+		  if(group == null) {
+				///ystem.err.println("Oh my god, this tree has no group: " + this);
+		  }
+		  else {
+		  	group.grabFocus(this);
+		  }
+		  Gatherer.g_man.menu_bar.setMetaAuditSuffix(getSelectionDetails());
+	 }
+
+	 private boolean isValidDrop(TreePath target_path) {
+		  boolean valid = false;
+		  if(target_path != null) {
+				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;
+		  }
+		  else {
+				if(target_path == null) {
+					 previous_path = null;
+				}
+		  }
+		  return valid;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/gui/tree/DragTreeCellRenderer.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/gui/tree/DragTreeCellRenderer.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/gui/tree/DragTreeCellRenderer.java	(revision 13666)
@@ -0,0 +1,66 @@
+package org.greenstone.gatherer.gui.tree;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.Color;
+import java.awt.Component;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultTreeCellRenderer;
+
+public class DragTreeCellRenderer 
+	 extends DefaultTreeCellRenderer {
+	 
+	 private boolean in_focus = false;
+	 private Color selection_background;
+	 private Color selection_foreground;
+	 
+	 public DragTreeCellRenderer() {
+		  super();
+		  selection_background = getBackgroundSelectionColor();
+		  selection_foreground = getTextSelectionColor();
+	 }
+
+	 public void gainFocus() {
+		  setBackgroundSelectionColor(selection_background);
+		  setTextSelectionColor(selection_foreground);
+	 }
+
+	 public void loseFocus() {
+		  setBackgroundSelectionColor(Color.lightGray);
+		  setTextSelectionColor(Color.black);
+	 }
+}
+
Index: /tags/start/gli/src/org/greenstone/gatherer/help/ContentModel.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/help/ContentModel.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/help/ContentModel.java	(revision 13666)
@@ -0,0 +1,113 @@
+/**
+ *#########################################################################
+ *
+ * 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.help;
+
+import java.io.*;
+import java.util.HashMap;
+import javax.swing.tree.DefaultTreeModel;
+import org.greenstone.gatherer.cdm.CommandTokenizer;
+import org.greenstone.gatherer.help.HelpItem;
+import org.greenstone.gatherer.util.Utility;
+/** This is a hardcoded tree model which serves as the help pages contents page. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class ContentModel
+	 extends DefaultTreeModel {
+	 /** Constructor that builds the contents model. 
+	  * @see org.greenstone.gatherer.help.HelpItem
+	  */
+	 public ContentModel() {
+		  super(new HelpItem("Contents"));
+		  // Load the contents file and build the contents structure found within.
+		  try {
+				FileReader file_reader = new FileReader(Utility.HELP_DIR + "index.txt");
+				BufferedReader buffered_reader = new BufferedReader(file_reader);
+				String line = null;
+				HashMap known_entries = new HashMap();
+				while((line = buffered_reader.readLine()) != null) {
+					 // We'll use my ever popular command tokenizer to ensure we can parse index | title.
+					 CommandTokenizer tokenizer = new CommandTokenizer(line);
+					 // The first thing off the tokenizer is an index of the form xx.xx.xx
+					 String index_str = tokenizer.nextToken();
+					 // And the second is a title for this entry
+					 String title = tokenizer.nextToken();
+					 // Now we determine the parent of this entry. In general this involves removing the last portion of the index so 2.3 becomes 2. However there is a special case when the index has only one part, ie 2, in which case it get added to the root, then the index is replaced with 2.0.
+					 int position = -1;
+					 if((position = index_str.lastIndexOf(".")) != -1) {
+						  // Find parent index
+						  String parent_index = index_str.substring(0, position);
+						  // Retrieve parent item
+						  HelpItem parent_item = (HelpItem) known_entries.get(parent_index);
+						  // Otherwise append ".0" and search again...
+						  if(parent_item == null) {
+								parent_item = (HelpItem) known_entries.get(parent_index + ".0");
+						  }
+						  // Otherwise the parent item must be the root.
+						  if(parent_item == null) {
+								parent_item = (HelpItem) root;
+						  }
+						  // Filename has - instead of .
+						  String file_name = index_str.replace('.', '-');
+						  // Create the new item
+						  HelpItem item;
+						  File temp_file = new File(Utility.HELP_DIR + file_name + ".xml");
+						  if(temp_file.exists()) {
+								item = new HelpItem(index_str + " " + title, Utility.HELP_DIR + file_name + ".xml");
+						  }
+						  else {
+								item = new HelpItem(index_str + " " + title, Utility.HELP_DIR + file_name + ".htm");
+						  }
+						  temp_file = null;
+						  // Insert into parent
+						  insertNodeInto(item, parent_item, parent_item.getChildCount());
+						  // Record in known entries
+						  known_entries.put(index_str, item);
+						  item = null;
+						  file_name = null;
+						  parent_item = null;
+						  parent_index = null;
+					 }
+					 title = null;
+					 index_str = null;
+					 tokenizer = null;
+				}
+				known_entries.clear();
+				known_entries = null;
+				line = null;
+				buffered_reader.close();
+				buffered_reader = null;
+				file_reader.close();
+				file_reader = null;
+		  }
+		  catch (Exception error) {
+				System.err.println("Cannot build help contents. Possible error in index.txt");
+				error.printStackTrace();
+		  }
+	 }
+}
+
Index: /tags/start/gli/src/org/greenstone/gatherer/help/HelpFrame.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/help/HelpFrame.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/help/HelpFrame.java	(revision 13666)
@@ -0,0 +1,174 @@
+/**
+ *#########################################################################
+ *
+ * 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.help;
+/**
+ * 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>
+ * @author John Thompson, Greenstone Digital Libraries
+ * @version 2.1
+ */
+import calpa.html.CalHTMLPane; 
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Toolkit;
+import java.io.File;
+import java.net.URL;
+import java.util.StringTokenizer;
+import javax.swing.BorderFactory;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTree;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.TreePath;
+import org.greenstone.gatherer.help.ContentModel;
+import org.greenstone.gatherer.help.HelpItem;
+/** This class provides a nice help facility for the Gatherer tool. It
+ * is a separate frame that can be positioned as the user wishes, and provides
+ * standard help-type functionality such as contents, index and search, 
+ * glossary and of course help descriptions. <BR>
+ */
+public class HelpFrame 
+	 extends JFrame {
+	 /** The html rendering pane. */
+	 private CalHTMLPane view = null;
+	 private ContentModel model = null;
+	 
+	 private JSplitPane split_pane = null;
+	 /** A contents tree for the left of the frame. */
+	 private JTree contents = null;
+	 /** The size of a button on this pane. */
+	 static final Dimension BUTTON_SIZE = new Dimension(100,50);
+	 /** The minimum size of any component in this frame. */
+	 static final Dimension MIN_SIZE = new Dimension(100,100);
+	 /** The size of the frame itself. */
+	 static final Dimension SIZE = new Dimension(760,560);
+	 /** Constructor.
+	  * @param file_name The file name, as a <Strong>String</strong> of the help page to initially show.
+	  */
+	 public HelpFrame() { 
+		  setDefaultCloseOperation(HIDE_ON_CLOSE); 
+		  setSize(SIZE);
+		  model = new ContentModel();
+		  contents = new JTree(model);
+		  contents.addTreeSelectionListener(new ContentsListener());
+		  contents.setExpandsSelectedPaths(true);
+		  view = new CalHTMLPane();
+		  // Creation
+		  JPanel content_pane = (JPanel) this.getContentPane();
+		  split_pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
+		  JScrollPane index_scroll = new JScrollPane(contents);
+		  JScrollPane view_scroll = new JScrollPane(view);
+		  // Layout
+		  split_pane.add(index_scroll, JSplitPane.LEFT);
+		  split_pane.add(view_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);		  
+	 }
+	 /** Destructor. Removes all listeners, closes streams and explicitly sets data members to null. */
+	 public void destroy() {
+		  view = null;
+		  contents = null;
+	 }
+	 public void setView(String index) {
+		  try {
+				// Retrieve the node at index
+				HelpItem current = (HelpItem) model.getRoot();
+				StringTokenizer tokenizer = new StringTokenizer(index, ".");
+				while(tokenizer.hasMoreTokens()) {
+					 String token = tokenizer.nextToken();
+					 int position = Integer.parseInt(token);
+					 if(position > 0 && position <= current.getChildCount()) {
+						  current = (HelpItem) current.getChildAt(position - 1);
+					 }
+					 token = null;
+				}
+				tokenizer = null;
+				// Ensure path is selected
+				TreePath path = new TreePath(current.getPath());
+				contents.setSelectionPath(path);
+				contents.scrollPathToVisible(path);
+				path = null;
+				// Build url
+				URL url = current.getURL();
+				current = null;
+				// Show help dialog
+				show();
+				split_pane.setDividerLocation(0.2);
+				// Display help page
+				if(url != null) {
+					 view.showHTMLDocument(url);
+				}
+				url = null;
+		  }
+		  catch (Exception error) {
+				show();
+				split_pane.setDividerLocation(0.2);
+		  }
+	 }
+
+	 /** This listener is used to lister for selection changes in the contents tree, and to show the appropriate page as required.
+	  */
+	 private class ContentsListener 
+		  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) {
+				TreePath path = event.getPath();
+				HelpItem node = (HelpItem)path.getLastPathComponent();
+				URL url = node.getURL();
+				if(url != null) {
+					 view.showHTMLDocument(url);
+				}
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/help/HelpItem.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/help/HelpItem.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/help/HelpItem.java	(revision 13666)
@@ -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.
+ *
+ * <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.help;
+/**
+ * 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>
+ * @author John Thompson, Greenstone Digital Libraries
+ * @version 2.1
+ */
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.net.URL;
+import java.util.Vector;
+import javax.swing.tree.DefaultMutableTreeNode;
+import org.greenstone.gatherer.util.Utility;
+/** 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. */
+public class HelpItem 
+	 extends DefaultMutableTreeNode {
+	 /** The file name of the html page to load. */
+	 public String file_name = null;
+	 /** The title to be displayed for this tree node. */
+	 public String title = null;
+	 /** Default Construtor with no file and no title. */
+	 public HelpItem() {
+		  this.file_name = null;
+		  this.title = "No Content";
+	 }
+	 /** Constructor.
+	  * @param title The title to be shown for this node as a <strong>String</strong>.
+	  */
+	 public HelpItem(String title) {
+		  this.file_name = null;
+		  this.title = title;
+	 }
+	 /** Constructor.
+	  * @param title The title to be shown for this node as a <strong>String</strong>.
+	  * @param file_name The name of the html file as a <strong>String</strong>.
+	  */
+	 public HelpItem(String title, String file_name) {
+		  this.file_name = file_name;
+		  this.title = title;
+
+		  file_name = file_name.replace('/', File.separatorChar);
+		  file_name = file_name.replace('\\', File.separatorChar);
+	 }
+	 /** This method reads in the html file then returns it as one long string.
+	  * @return A <strong>String</strong> containing the entire html files contents.
+	  */
+	 public String content() {
+		  String content = "";
+		  try {
+				File file = new File(file_name);
+				FileReader in_reader = new FileReader(file);
+				BufferedReader in = new BufferedReader(in_reader, 
+																	Utility.BUFFER_SIZE);
+				String line;
+				while((line = in.readLine()) != null) {
+					 content = content + line;
+				}
+		  }
+		  catch (Exception e) {
+		  }
+		  return content;
+	 }
+	 /** Method to get the file name.
+	  * @return The file name as a <strong>String</strong>.
+	  */
+	 public String getFileName() {
+		  return file_name;
+	 }
+	 /** Method to create a url from the file name. This method is preferred over the <i>content()</i> method, as the url can then be directly parsed by the html renderer.
+	  * @return A <strong>URL</strong> that points to the files location as determined by the file name.
+	  */
+	 public URL getURL() {
+		  URL url = null; 
+		  if(file_name != null) {
+				try {
+					 File file = new File(file_name);
+					 url = file.toURL();
+				}
+				catch (Exception e) {
+				}
+		  }
+		  return url;
+	 }
+	 /** Method to acquire a string representation of this node, which in this case is its title.
+	  * @return A <strong>String</strong> which shows how this node should be displayed in the tree for example.
+	  */
+	 public String toString() {
+		  return title;
+	 }
+}
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/mem/Attribute.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/mem/Attribute.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/mem/Attribute.java	(revision 13666)
@@ -0,0 +1,91 @@
+/**
+ *#########################################################################
+ *
+ * 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.mem;
+
+public class Attribute 
+	 implements Comparable {
+	 public String language = null;
+	 public String name = null;
+	 public String value = null;
+	 public String text = null;
+	 private boolean language_specific = false;
+	 public Attribute(String name, String value) {
+		  this.name = name;
+		  this.value = value;
+	 }
+	 public Attribute(String name, String language, String value) {
+		  this.language = language;
+		  this.language_specific = true;
+		  this.name = name;
+		  this.value = value;
+	 }
+	 public int compareTo(Object other) {
+		  return toString().compareTo(other.toString());
+	 }
+	 public boolean equals(Object other) {
+		  return toString().equals(other.toString());
+	 }
+	 public String get(int column) {
+		  switch(column) {
+		  case 0:
+				return name;
+		  case 1:
+				if(language_specific) {
+					 return language;
+				}
+		  default:
+				return value;
+		  }
+	 }
+	 public String toString() {
+		  if(text == null) {
+				if(language_specific) {
+					 text = name + " [" + language + "] = " + value;
+				}
+				else {
+					 text = name + " = " + value;
+				}
+		  }
+		  return text;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/mem/AttributeTableModel.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/mem/AttributeTableModel.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/mem/AttributeTableModel.java	(revision 13666)
@@ -0,0 +1,210 @@
+package org.greenstone.gatherer.mem;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.table.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.mem.Attribute;
+import org.greenstone.gatherer.util.Utility;
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class AttributeTableModel 
+	 extends AbstractTableModel {
+	 private Attribute last_attribute = null;
+	 private int last_index = -1;
+	 private int longest[] = null;
+	 private int column_zero_width = 0;
+	 private JScrollPane scroll_pane = null;
+	 private JTable table = null;
+	 private String default_value = null;
+	 private String names[] = null;
+	 private TreeSet attributes = null;
+	 static final private int table_width = 550;
+
+	 public AttributeTableModel(TreeSet attributes, String one, String two, String default_value) {
+		  super();
+		  this.attributes = attributes;
+		  this.default_value = default_value;
+		  this.longest = new int[2];
+		  this.names = new String[2];
+		  names[0] = one;
+		  names[1] = two;
+	 }
+
+	 public AttributeTableModel(TreeSet attributes, String one, String two, String three, String default_value) {
+		  super();
+		  this.attributes = attributes;
+		  this.default_value = default_value;
+		  this.longest = new int[3];
+		  this.names = new String[3];
+		  names[0] = one;
+		  names[1] = two;
+		  names[2] = three;
+	 }
+	 public void add(Attribute attribute) {
+		  attributes.add(attribute);
+		  // Determine the row index
+		  boolean found = false;
+		  int index = 0;
+		  Iterator iterator = attributes.iterator();
+		  for(int i = 0; !found && iterator.hasNext(); i++) {
+				if(attribute == iterator.next()) {
+					 found = true;
+					 index = i;
+				}
+		  }
+		  // Fire event
+		  fireTableRowsInserted(index, index);
+	 }
+
+	 public boolean contains(String value, int column) {
+		  boolean result = false;
+		  Iterator iterator = attributes.iterator();
+		  while(iterator.hasNext() && !result) {
+				Attribute attribute = (Attribute) iterator.next();
+				if(value.equals(attribute.get(column))) {
+					 result = true;
+				}
+		  }  
+		  return result;
+	 }
+
+	 public Attribute getAttribute(int row) {
+		  if(row != last_index) {
+				last_index = row;
+				last_attribute = null;
+				// Retrieve the value from the set using its iterator
+				Iterator iterator = attributes.iterator();
+				for(int i = 0; i < row && iterator.hasNext(); i++) {
+					 iterator.next();
+				}
+				if(iterator.hasNext()) {
+					 last_attribute = (Attribute) iterator.next();
+				}
+				iterator = null;
+		  }
+		  return last_attribute;
+	 }
+
+	 public int getColumnCount() {
+		  return names.length;
+	 }
+
+	 public String getColumnName(int col) {
+		  return names[col];
+	 }
+
+	 public int getRowCount() {
+		  int count = 0;
+		  if(attributes != null) {
+				count = attributes.size();
+		  }
+		  return count;
+	 }
+
+	 public Object getValueAt(int row, int col) {
+		  String value = null;
+		  Attribute attribute = getAttribute(row);
+		  if(attribute != null) {
+				value = attribute.get(col);
+		  }
+		  if(value == null) {
+				value = default_value;
+		  }
+		  // Update table column width if necessary
+		  if(value.length() > longest[col]) {
+				Component component = table.getCellRenderer(row, col).getTableCellRendererComponent(table, value, false, false, 0, 0);
+				int width = component.getPreferredSize().width + 10;
+				TableColumn column = table.getColumnModel().getColumn(col);
+				if(width > column.getPreferredWidth()) {
+					 // Calculate default column width
+					 int default_width = 0;
+					 int total_width = scroll_pane.getSize().width;
+					 if(names.length == 2) {
+						  if(col == 0) {
+								default_width = total_width / 3;
+						  }
+						  else {
+								default_width = 2 * (total_width / 3);
+						  }
+					 }
+					 else {
+						  switch(col) {
+						  case 0:
+								default_width = (2 * total_width) / 9;
+								break;
+						  case 1:
+								default_width = total_width / 9;
+								break;
+						  default:
+								default_width = 2 * (total_width / 3);
+								break;
+						  }
+					 }
+					 if(width > default_width) {
+						  column.setPreferredWidth(width);
+					 }
+					 else {
+						  column.setPreferredWidth(default_width);
+					 }
+				}
+				longest[col] = value.length();
+		  }
+		  return Utility.stripNL(value);
+	 }
+	 public void removeRow(final int row) {
+		  ///ystem.err.println("Remove row " + row);
+		  Attribute attribute = getAttribute(row);
+		  if(attribute != null) {
+				attributes.remove(attribute);
+				// Arg... this caused me a headache for hours.
+				last_index = -1;
+				fireTableRowsDeleted(row, row);
+		  }
+	 }
+	 public void setScrollPane(JScrollPane scroll_pane) {
+		  this.scroll_pane = scroll_pane;
+	 }
+	 public void setTable(JTable table) {
+		  this.table = table;
+		  this.longest = new int[getColumnCount()];
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/mem/MEMModel.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/mem/MEMModel.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/mem/MEMModel.java	(revision 13666)
@@ -0,0 +1,100 @@
+package org.greenstone.gatherer.mem;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import javax.swing.tree.DefaultTreeModel;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.mem.MEMNode;
+import org.greenstone.gatherer.msm.MetadataSet;
+import org.greenstone.gatherer.util.SynchronizedTreeModelTools;
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class MEMModel 
+	 extends DefaultTreeModel {
+
+	 public MEMModel() {
+		  super(new MEMNode());
+	 }
+
+	 public void add(MEMNode parent, Object object, int type) {
+		  if(parent == null) {
+				parent = (MEMNode) root;
+		  }
+		  MEMNode new_node = new MEMNode(type, object, null);
+		  SynchronizedTreeModelTools.insertNodeInto(this, parent, new_node);
+	 }
+
+	 public MEMNode getProfileNode() {
+		  MEMNode node = (MEMNode) root;
+		  return (MEMNode) node.getChildAt(node.getChildCount() - 1);
+	 }
+
+	 public void remove(String name, int type) {
+		  MEMNode current = (MEMNode) root;
+		  for(int i = 0; i < current.getChildCount(); i++) {
+				MEMNode child = (MEMNode) current.getChildAt(i);
+				if(child.toString().equals(name) && type == MEMNode.SET) {
+					 // Place on AWT event thread to avoid errors.
+					 SynchronizedTreeModelTools.removeNodeFromParent(this, child);
+					 return;
+				}
+				// This may be the profiler root node, in which case we descend into its children if we're looking for collection file matches. 
+				else if(type == MEMNode.COLLECTION && child.getType() == MEMNode.PROFILER) {
+					 for(int j = 0; j < child.getChildCount(); j++) {
+						  MEMNode inner_child = (MEMNode) child.getChildAt(j);
+						  if(inner_child.toString().equals(name)) {
+								// Place on AWT event thread to avoid errors.
+								SynchronizedTreeModelTools.removeNodeFromParent(this, inner_child);
+								return;
+						  }
+					 }
+				}
+				// If this is a set and we are looking for an element, then iterate through its children. Can't really do this recursively.
+				else if(type == MEMNode.ELEMENT && child.getType() == MEMNode.SET) {
+					 for(int j = 0; j < child.getChildCount(); j++) {
+						  MEMNode inner_child = (MEMNode) child.getChildAt(j);
+						  if(inner_child.toString().equals(name)) {
+								// Place on AWT event thread to avoid errors.
+								SynchronizedTreeModelTools.removeNodeFromParent(this, inner_child);
+								return;
+						  }
+					 }
+				}
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/mem/MEMNode.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/mem/MEMNode.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/mem/MEMNode.java	(revision 13666)
@@ -0,0 +1,178 @@
+package org.greenstone.gatherer.mem;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.util.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.mem.AttributeTableModel;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.MetadataSet;
+import org.greenstone.gatherer.msm.MetadataSetManager;
+import org.w3c.dom.*;
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class MEMNode
+	 extends DefaultMutableTreeNode {
+	 private AttributeTableModel model = null;
+	 private int type = 0;
+	 static final public int COLLECTION = 0;
+	 static final public int ELEMENT    = 1;
+	 static final public int PROFILER   = 2;
+	 static final public int ROOT       = 3; 
+	 static final public int SET        = 4;
+
+	 public MEMNode() {
+		  this.type = ROOT;
+	 }
+
+	 public MEMNode(int type, Object object, MEMNode parent) {
+		  this.userObject = object;
+		  this.parent = parent;
+		  this.type = type;
+	 }
+
+	 public Enumeration children() {
+		  if(children == null) {
+				mapChildren();
+		  }		  
+		  return children.elements();
+	 }
+
+	 public boolean getAllowsChildren() {
+		  return true;
+	 }
+
+	 public TreeNode getChildAt(int index) {
+		  if(children == null) {
+				mapChildren();
+		  }
+		  return (TreeNode) children.get(index);
+	 }
+	 public int getChildCount() {
+		  if(children == null) {
+				mapChildren();
+		  }
+		  return children.size();
+	 }
+	 public ElementWrapper getElement() {
+		  ElementWrapper result = null;
+		  if(type == ELEMENT) {
+				result = (ElementWrapper) userObject;
+		  }
+		  return result;
+	 }
+	 public int getIndex(TreeNode node) {
+		  if(children == null) {
+				mapChildren();
+		  }
+		  return children.indexOf(node);
+	 }
+	 public AttributeTableModel getModel() {
+		  return model;
+	 }
+	 public TreeNode getParent() {
+		  return parent;
+	 }
+	 public MetadataSet getSet() {
+		  MetadataSet result = null;
+		  if(type == SET) {
+				result = (MetadataSet) userObject;
+		  }
+		  return result;
+	 }
+	 public int getType() {
+		  return type;
+	 }
+	 public boolean isLeaf() {
+		  if(children == null) {
+				mapChildren();
+		  }
+		  return children.size() == 0;
+	 }
+	 public void setModel(AttributeTableModel model) {
+		  this.model = model;
+	 }
+	 public String toString() {
+		  String text = "error";
+		  if(userObject != null) {
+				if(userObject instanceof ElementWrapper) {
+					 text = ((ElementWrapper)userObject).getName();
+				}
+				else {
+					 text = userObject.toString();
+				}
+		  }
+		  return text;
+	 }
+	 private void mapChildren() {
+		  ///ystem.err.println("Mapping the children of " + this);
+		  children = new Vector();
+		  // How we build children depends on the node type
+		  switch(type) {
+		  case PROFILER: // Add the collections as children
+				ArrayList a = Gatherer.c_man.msm.profiler.getCollections();
+				for(int i = 0; i < a.size(); i++) {
+					 children.add(new MEMNode(COLLECTION, a.get(i), this));
+				}
+				a = null;
+				break;
+		  case ROOT:
+				Vector v = Gatherer.c_man.msm.getSets();
+				for(int i = 0; i < v.size(); i++) {
+					 children.add(new MEMNode(SET, v.get(i), this));
+				}
+				v = null;
+				// Add the profile set.
+				children.add(new MEMNode(PROFILER, Gatherer.dictionary.get("MEM.Profiles"), this));
+				break;
+		  case SET: // Add the elements as children
+				MetadataSet set = (MetadataSet) userObject;
+				NodeList elements = set.getElements();
+				set = null;
+				for(int i = 0; i < elements.getLength(); i++) {
+					 children.add(new MEMNode(ELEMENT, new ElementWrapper((Element) elements.item(i)), this));
+				}
+				elements = null;
+				break;
+		  case COLLECTION:
+		  case ELEMENT:
+		  default:
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/mem/MetadataEditorManager.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/mem/MetadataEditorManager.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/mem/MetadataEditorManager.java	(revision 13666)
@@ -0,0 +1,1784 @@
+package org.greenstone.gatherer.mem;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.text.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.Language;
+import org.greenstone.gatherer.gui.ComboArea;
+import org.greenstone.gatherer.gui.GComboBox;
+import org.greenstone.gatherer.gui.SmarterTable;
+import org.greenstone.gatherer.gui.SmarterTree;
+import org.greenstone.gatherer.mem.Attribute;
+import org.greenstone.gatherer.mem.AttributeTableModel;
+import org.greenstone.gatherer.mem.MEMNode;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.MetadataSet;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.valuetree.GValueModel;
+import org.greenstone.gatherer.valuetree.GValueNode;
+import org.w3c.dom.*;
+/** Provides a GUI and relevant suite of tools for the editing of the metadata set associated with this collection. Again I have tried to capture a file manager type feel, with a tree showing the various set-element relations to the left of the dialog, and the right side showing details on the current tree selection. When a set is selected these details include a list of attributes, while when an element is selected this list is joined by another showing assigned values. In order for the editor to be stable and consistant with the rest of the tool, care must be taken for fire appropriate events whenever the sets are changed. There is also the addded complexity of determining what actions have to occur in order for a users edit of an assigned value to be completed, i.e. if the user chooses to remove a value then a call must be made to record_set.root.removeMetadata() to ensure all such values are actually removed, so it is not enough just to remove the value from the value model. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3b
+ */ 
+public class MetadataEditorManager
+	 extends JDialog {
+	 private AddElementActionListener add_element_action_listener = null;
+	 private AddFileActionListener add_file_action_listener = null;
+	 private AddSetActionListener add_set_action_listener = null;
+	 /** The class used to handle add or edit attribute actions has to be globally available so that we can dispose of its dialog properly. */
+	 private AddOrEditAttributeActionListener add_or_edit_attribute_action_listener = null;
+/** The class used to handle add or edit value actions has to be globally available so that we can dispose of its dialog properly. */
+	 private AddOrEditValueActionListener add_or_edit_value_action_listener = null;
+	 private boolean ignore = false;
+	 /** A card layout is used to switch between the two differing detail views. */ 
+	 private CardLayout card_layout = null;
+	 /** Um, the size of the screen I'd guess. */
+	 private Dimension screen_size = null;
+	 private ElementWrapper current_element = null;
+	 private GValueNode current_value_node = null;
+	 /** A reference to ourselves so our inner classes can dispose of us. */
+	 private MetadataEditorManager self = null;
+	 private int current_attribute = -1;
+	 private JButton add_attribute = null;
+	 private JButton add_element = null;
+	 private JButton add_file = null;
+	 private JButton add_set = null;
+	 private JButton add_value = null;
+	 private JButton close = null;
+	 private JButton edit_attribute = null;
+	 private JButton edit_value = null;
+	 private JButton remove_attribute = null;
+	 private JButton remove_element = null;
+	 private JButton remove_file = null;
+	 private JButton remove_set = null;
+	 private JButton remove_value = null;
+	 private JLabel element_name = null;
+	 private JLabel profile_name = null;
+	 private JLabel set_name = null;
+	 private JScrollPane element_attributes_scroll = null;
+	 private JScrollPane profile_attributes_scroll = null;
+	 private JScrollPane set_attributes_scroll = null;
+	 private JPanel details_pane = null;
+	 private MEMModel model = null;
+	 private MEMNode current_node = null;
+	 private MetadataSet current_set = null;
+	 private Object target = null;
+	 private SmarterTable element_attributes = null;
+	 private SmarterTable profile_attributes = null;
+	 private SmarterTable set_attributes = null;
+	 private SmarterTree element_values = null;
+	 /** A tree that represents the current metadata sets associated with this collection. */
+	 private SmarterTree mds_tree = null;
+	 private String current_collection_file = null;
+	 private String dialog_options[] = null;
+	 /** The default size of the editor dialog. */
+	 static final private Dimension ADD_ELEMENT_SIZE = new Dimension(400,125);
+	 static final private Dimension ADD_FILE_SIZE = new Dimension(400,125);
+	 static final private Dimension ADD_SET_SIZE = new Dimension(400,125);
+	 static final private Dimension ADD_OR_EDIT_ATTRIBUTE_SIZE = new Dimension(600,325);
+	 static final private Dimension ADD_OR_EDIT_VALUE_SIZE = new Dimension(600,440);
+	 static final private Dimension LABEL_SIZE = new Dimension(100,30);
+	 static final private Dimension SIZE = new Dimension(800,480);
+	 static final private String BLANK = "blank";
+	 static final private String ELEMENT = "element";
+	 static final private String PROFILE = "profile";
+	 static final private String SET = "set";
+	 /** Constructor. */
+	 public MetadataEditorManager() {
+		  super(Gatherer.g_man);
+		  this.dialog_options = new String[2];
+		  this.screen_size = Gatherer.config.screen_size;
+		  this.self = this;
+
+		  dialog_options[0] = Gatherer.dictionary.get("General.OK");
+		  dialog_options[1] = Gatherer.dictionary.get("General.Cancel");
+		  // Creation
+		  setDefaultCloseOperation(DISPOSE_ON_CLOSE);
+		  setModal(true);
+		  setSize(SIZE);
+		  setTitle(get("Title"));
+		  JPanel content_pane = (JPanel) getContentPane();
+		  content_pane.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
+		  
+		  JPanel upper_pane = new JPanel();
+		  upper_pane.setOpaque(false);
+		  
+		  model = new MEMModel();
+
+		  JPanel mds_tree_pane = new JPanel();
+		  mds_tree_pane.setOpaque(false);
+		  mds_tree_pane.setPreferredSize(new Dimension(200,500));
+		  mds_tree = new SmarterTree(model);
+		  mds_tree.setCellRenderer(new MEMTreeCellRenderer());
+		  mds_tree.setRootVisible(false);
+		  mds_tree.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  mds_tree.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+		  mds_tree.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
+		  mds_tree.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
+
+		  details_pane = new JPanel();
+		  details_pane.setOpaque(false);
+		  card_layout = new CardLayout();
+		  
+		  JPanel set_details_pane = new JPanel();
+		  set_details_pane.setOpaque(false);
+		  
+		  JPanel set_name_pane = new JPanel();
+		  set_name_pane.setOpaque(false);
+		  JLabel set_name_label = new JLabel(get("Name"));
+		  set_name_label.setOpaque(false);
+		  set_name_label.setPreferredSize(LABEL_SIZE);
+		  set_name = new JLabel();
+		  set_name.setBorder(BorderFactory.createLoweredBevelBorder());
+		  set_name.setOpaque(false);
+		  
+		  JPanel set_attributes_pane = new JPanel();
+		  set_attributes_pane.setOpaque(false);
+		  set_attributes_scroll = new JScrollPane();
+		  set_attributes_scroll.getViewport().setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  set_attributes_scroll.setOpaque(true);
+		  set_attributes = new SmarterTable();
+		  set_attributes.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
+		  set_attributes.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  set_attributes.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+		  set_attributes.setHeadingBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
+		  set_attributes.setHeadingForeground(Gatherer.config.getColor("coloring.collection_heading_foreground", false));
+		  set_attributes.setOpaque(false);
+		  set_attributes.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
+		  set_attributes.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
+		  set_attributes.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+		  
+		  JPanel element_details_pane = new JPanel();
+		  element_details_pane.setOpaque(false);
+
+		  JPanel element_name_pane = new JPanel();
+		  element_name_pane.setOpaque(false);
+		  JLabel element_name_label = new JLabel(get("Name"));
+		  element_name_label.setOpaque(false);
+		  element_name_label.setPreferredSize(LABEL_SIZE);
+		  element_name = new JLabel();
+		  element_name.setBorder(BorderFactory.createLoweredBevelBorder());
+		  element_name.setOpaque(false);
+		  
+		  JPanel element_inner_pane = new JPanel();
+		  element_inner_pane.setOpaque(false);
+		  
+		  JPanel element_attributes_pane = new JPanel();
+		  element_attributes_pane.setOpaque(false);
+		  element_attributes_scroll = new JScrollPane();
+		  element_attributes_scroll.getViewport().setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  element_attributes_scroll.setOpaque(true);
+		  element_attributes = new SmarterTable();
+		  element_attributes.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
+		  element_attributes.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  element_attributes.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+		  element_attributes.setHeadingBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
+		  element_attributes.setHeadingForeground(Gatherer.config.getColor("coloring.collection_heading_foreground", false));
+		  element_attributes.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
+		  element_attributes.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
+		  element_attributes.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+		  JPanel element_values_pane = new JPanel();
+		  element_values_pane.setOpaque(false);
+		  element_values = new SmarterTree();
+		  element_values.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  element_values.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+		  element_values.setRootVisible(false);
+		  element_values.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
+		  element_values.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
+		  
+		  JPanel profile_details_pane = new JPanel();
+		  profile_details_pane.setOpaque(false);
+		  JPanel profile_name_pane = new JPanel();
+		  profile_name_pane.setOpaque(false);
+		  JLabel profile_name_label = new JLabel(get("Name"));
+		  profile_name_label.setOpaque(false);
+		  profile_name_label.setPreferredSize(LABEL_SIZE);
+		  profile_name = new JLabel();
+		  profile_name.setBorder(BorderFactory.createLoweredBevelBorder());
+		  profile_name.setOpaque(false);
+		  
+		  JPanel profile_attributes_pane = new JPanel();
+		  profile_attributes_pane.setOpaque(false);
+		  profile_attributes_scroll = new JScrollPane();
+		  profile_attributes_scroll.getViewport().setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  profile_attributes_scroll.setOpaque(true);
+		  profile_attributes = new SmarterTable();
+		  profile_attributes.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
+		  profile_attributes.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  profile_attributes.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+		  profile_attributes.setHeadingBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
+		  profile_attributes.setHeadingForeground(Gatherer.config.getColor("coloring.collection_heading_foreground", false));
+		  profile_attributes.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
+		  profile_attributes.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
+		  profile_attributes.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+		  JPanel button_pane = new JPanel();
+		  button_pane.setOpaque(false);
+
+		  JPanel button_label_pane = new JPanel();
+		  button_label_pane.setOpaque(false);
+		  JLabel attribute_label = new JLabel(get("Attribute"));
+		  attribute_label.setOpaque(false);
+		  //attribute_label.setHorizontalAlignment(JLabel.CENTER);
+		  attribute_label.setPreferredSize(LABEL_SIZE);
+		  JLabel element_label = new JLabel(get("Element"));
+		  element_label.setOpaque(false);
+		  //element_label.setHorizontalAlignment(JLabel.CENTER);
+		  element_label.setPreferredSize(LABEL_SIZE);
+		  JLabel file_label = new JLabel(get("File"));
+		  file_label.setOpaque(false);
+		  //element_label.setHorizontalAlignment(JLabel.CENTER);
+		  file_label.setPreferredSize(LABEL_SIZE);
+		  JLabel set_label = new JLabel(get("Set"));
+		  set_label.setOpaque(false);
+		  //set_label.setHorizontalAlignment(JLabel.CENTER);
+		  set_label.setPreferredSize(LABEL_SIZE);
+		  JLabel value_label = new JLabel(get("Value"));
+		  value_label.setOpaque(false);
+		  //value_label.setHorizontalAlignment(JLabel.CENTER);
+		  value_label.setPreferredSize(LABEL_SIZE);
+
+		  JPanel inner_button_pane = new JPanel();
+		  inner_button_pane.setOpaque(false);
+		  add_attribute = new JButton(get("Add"));
+		  add_element = new JButton(get("Add"));
+		  add_file = new JButton(get("Add"));
+		  add_set = new JButton(get("Add"));
+		  add_value = new JButton(get("Add"));
+		  edit_attribute = new JButton(get("Edit"));
+		  edit_value = new JButton(get("Edit"));
+		  remove_attribute = new JButton(get("Remove"));
+		  remove_element = new JButton(get("Remove"));
+		  remove_file = new JButton(get("Remove"));
+		  remove_set = new JButton(get("Remove"));
+		  remove_value = new JButton(get("Remove"));
+		  setControls(false, false, false, false, false, false, false, false, false, false, false, false);
+
+		  close = new JButton(get("General.Close"));
+
+		  add_element_action_listener = new AddElementActionListener();
+		  add_file_action_listener = new AddFileActionListener();
+		  add_set_action_listener = new AddSetActionListener();
+		  add_or_edit_attribute_action_listener = new AddOrEditAttributeActionListener();
+		  add_or_edit_value_action_listener = new AddOrEditValueActionListener();
+
+		  // Some blank panel
+		  JPanel blank_pane = new JPanel();
+		  blank_pane.setOpaque(false);
+		  JPanel edit_file_pane = new JPanel();
+		  edit_file_pane.setOpaque(false);
+		  JPanel edit_element_pane = new JPanel();
+		  edit_element_pane.setOpaque(false);
+		  JPanel edit_set_pane = new JPanel();
+		  edit_set_pane.setOpaque(false);
+		  // Connection
+
+		  add_attribute.addActionListener(add_or_edit_attribute_action_listener);
+		  add_element.addActionListener(add_element_action_listener);
+		  add_file.addActionListener(add_file_action_listener);
+		  add_set.addActionListener(add_set_action_listener);
+		  add_value.addActionListener(add_or_edit_value_action_listener);
+		  close.addActionListener(new CloseActionListener());
+		  edit_attribute.addActionListener(add_or_edit_attribute_action_listener);
+		  edit_value.addActionListener(add_or_edit_value_action_listener);
+		  remove_attribute.addActionListener(new RemoveAttributeActionListener());
+		  remove_element.addActionListener(new RemoveElementActionListener());
+		  remove_file.addActionListener(new RemoveFileActionListener());
+		  remove_set.addActionListener(new RemoveSetActionListener());
+		  remove_value.addActionListener(new RemoveValueActionListener());
+		  element_attributes.getSelectionModel().addListSelectionListener(new AttributesListSelectionListener(element_attributes));
+		  profile_attributes.getSelectionModel().addListSelectionListener(new AttributesListSelectionListener(profile_attributes));
+		  set_attributes.getSelectionModel().addListSelectionListener(new AttributesListSelectionListener(set_attributes));
+		  element_values.addTreeSelectionListener(new ElementValuesTreeSelectionListener());
+		  mds_tree.addTreeSelectionListener(new MDSTreeSelectionListener());
+		  // Layout
+		  mds_tree_pane.setLayout(new BorderLayout());
+		  mds_tree_pane.add(new JScrollPane(mds_tree), BorderLayout.CENTER);
+		  
+		  set_name_pane.setLayout(new BorderLayout());
+		  set_name_pane.add(set_name_label, BorderLayout.WEST);
+		  set_name_pane.add(set_name, BorderLayout.CENTER);
+				
+		  set_attributes_scroll.setViewportView(set_attributes);
+
+		  set_attributes_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(get("Attributes")), BorderFactory.createEmptyBorder(2,2,2,2)));
+		  set_attributes_pane.setLayout(new BorderLayout());
+		  set_attributes_pane.add(set_attributes_scroll, BorderLayout.CENTER);
+		
+		  set_details_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(get("Set_Details")), BorderFactory.createEmptyBorder(2,2,2,2)));
+		  set_details_pane.setLayout(new BorderLayout());
+		  //set_details_pane.add(set_name_pane, BorderLayout.NORTH);
+		  set_details_pane.add(set_attributes_pane, BorderLayout.CENTER);
+		  
+		  element_name_pane.setLayout(new BorderLayout());
+		  element_name_pane.add(element_name_label, BorderLayout.WEST);
+		  element_name_pane.add(element_name, BorderLayout.CENTER);
+				
+		  element_attributes_scroll.setViewportView(element_attributes);
+
+		  element_attributes_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(get("Attributes")), BorderFactory.createEmptyBorder(2,2,2,2)));
+		  element_attributes_pane.setLayout(new BorderLayout());
+		  element_attributes_pane.add(element_attributes_scroll, BorderLayout.CENTER);
+		  
+		  element_values_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(get("Values")), BorderFactory.createEmptyBorder(2,2,2,2)));
+		  element_values_pane.setLayout(new BorderLayout());
+		  element_values_pane.add(new JScrollPane(element_values), BorderLayout.CENTER);
+		  
+		  element_inner_pane.setLayout(new GridLayout(2,1));
+		  element_inner_pane.add(element_attributes_pane);
+		  element_inner_pane.add(element_values_pane);
+		  
+		  element_details_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(get("Element_Details")), BorderFactory.createEmptyBorder(2,2,2,2)));
+		  element_details_pane.setLayout(new BorderLayout());
+		  //element_details_pane.add(element_name_pane, BorderLayout.NORTH);
+		  element_details_pane.add(element_inner_pane, BorderLayout.CENTER);
+
+		  profile_name_pane.setLayout(new BorderLayout());
+		  profile_name_pane.add(profile_name_label, BorderLayout.WEST);
+		  profile_name_pane.add(profile_name, BorderLayout.CENTER);
+				
+		  profile_attributes_scroll.setViewportView(profile_attributes);
+
+		  profile_attributes_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(get("Profiles")), BorderFactory.createEmptyBorder(2,2,2,2)));
+		  profile_attributes_pane.setLayout(new BorderLayout());
+		  profile_attributes_pane.add(profile_attributes_scroll, BorderLayout.CENTER);
+		
+		  profile_details_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(get("Profile_Details")), BorderFactory.createEmptyBorder(2,2,2,2)));
+		  profile_details_pane.setLayout(new BorderLayout());
+		  //profile_details_pane.add(profile_name_pane, BorderLayout.NORTH);
+		  profile_details_pane.add(profile_attributes_pane, BorderLayout.CENTER);
+		  
+		  details_pane.setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
+		  details_pane.setLayout(card_layout);
+		  details_pane.add(blank_pane, BLANK);
+		  details_pane.add(set_details_pane, SET);
+		  details_pane.add(element_details_pane, ELEMENT);
+		  details_pane.add(profile_details_pane, PROFILE);
+
+		  upper_pane.setLayout(new BorderLayout());
+		  upper_pane.add(mds_tree_pane, BorderLayout.WEST);
+		  upper_pane.add(details_pane, BorderLayout.CENTER);
+		  
+		  button_label_pane.setLayout(new GridLayout(5,1,0,2));
+		  button_label_pane.add(set_label);
+		  button_label_pane.add(file_label);
+		  button_label_pane.add(element_label);
+		  button_label_pane.add(attribute_label);
+		  button_label_pane.add(value_label);
+
+		  inner_button_pane.setLayout(new GridLayout(5,3,0,2));		
+		  inner_button_pane.add(add_set);
+		  inner_button_pane.add(edit_set_pane);
+		  inner_button_pane.add(remove_set);
+		  inner_button_pane.add(add_file);
+		  inner_button_pane.add(edit_file_pane);
+		  inner_button_pane.add(remove_file);
+		  inner_button_pane.add(add_element);
+		  inner_button_pane.add(edit_element_pane);
+		  inner_button_pane.add(remove_element);
+		  inner_button_pane.add(add_attribute);
+		  inner_button_pane.add(edit_attribute);
+		  inner_button_pane.add(remove_attribute);
+		  inner_button_pane.add(add_value);
+		  inner_button_pane.add(edit_value);
+		  inner_button_pane.add(remove_value);
+		  
+		  button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+		  button_pane.setLayout(new BorderLayout());
+		  button_pane.add(button_label_pane, BorderLayout.WEST);
+		  button_pane.add(inner_button_pane, BorderLayout.CENTER);
+		  button_pane.add(close, BorderLayout.EAST);
+
+		  content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		  content_pane.setLayout(new BorderLayout());
+		  content_pane.add(upper_pane, BorderLayout.CENTER);
+		  content_pane.add(button_pane, BorderLayout.SOUTH);
+
+		  // Display
+		  setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+		  show();
+	 }
+	 
+	 public void dispose() {
+		  // Destructor
+		  card_layout = null;
+		  screen_size = null;
+		  self = null;
+		  add_attribute = null;
+		  add_element = null;
+		  add_file = null;
+		  add_set = null;
+		  add_value = null;
+		  close = null;
+		  edit_attribute = null;
+		  edit_value = null;
+		  remove_attribute = null;
+		  remove_element = null;
+		  remove_file = null;
+		  remove_set = null;
+		  remove_value = null;
+		  details_pane = null;
+		  element_attributes = null;
+		  set_attributes = null;
+		  element_name = null;
+		  set_name = null;
+		  element_values = null;
+		  mds_tree = null;
+		  target = null;
+		  // Dispose of inner dialogs
+		  add_element_action_listener.dispose();
+		  add_or_edit_attribute_action_listener.dispose();
+		  add_or_edit_value_action_listener.dispose();
+		  super.dispose();
+	 }
+
+	 private String get(String key) {
+		  return get(key, (String[])null);
+	 }
+	 
+	 private String get(String key, String arg) {
+		  String[] args = new String[1];
+		  args[0] = arg;
+		  return get(key, args);
+	 }
+
+	 private String get(String key, String[] args) {
+		  if(key.indexOf(".") == -1) {
+				key = "MEM." + key;
+		  }
+		  return Gatherer.dictionary.get(key, args);
+	 }
+	 
+	 private void setControls(boolean a_s, boolean r_s, boolean a_f, boolean r_f, boolean a_e, boolean r_e, boolean a_a, boolean e_a, boolean r_a, boolean a_v, boolean e_v, boolean r_v) {
+		  add_attribute.setEnabled(a_a);
+		  add_element.setEnabled(a_e);
+		  add_file.setEnabled(true); // Always true
+		  add_set.setEnabled(true); // Always true
+		  add_value.setEnabled(a_v);
+		  edit_attribute.setEnabled(e_a);
+		  edit_value.setEnabled(e_v);
+		  remove_attribute.setEnabled(r_a);
+		  remove_element.setEnabled(r_e);
+		  remove_file.setEnabled(r_f);
+		  remove_set.setEnabled(r_s);
+		  remove_value.setEnabled(r_v);
+	 }
+
+	 private class AddOrEditAttributeActionListener
+		  extends JDialog
+		  implements ActionListener {
+		  private boolean add_type = true;
+		  private ComboArea value = null;
+		  private JButton cancel_button = null;
+		  private JButton ok_button = null;
+		  private JComboBox language_box = null;
+		  private GComboBox name = null;
+		  private HashMap name_to_values = null;
+		  private JLabel target = null;
+		  /** Constructor. */
+		  public AddOrEditAttributeActionListener() {
+				super(self);
+				setModal(true);
+				setSize(ADD_OR_EDIT_ATTRIBUTE_SIZE);
+				name_to_values = new HashMap();
+				// Creation
+				JPanel content_pane = (JPanel) getContentPane();
+				content_pane.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
+				JPanel upper_pane = new JPanel();
+				upper_pane.setOpaque(false);
+
+				JPanel target_pane = new JPanel();
+				target_pane.setOpaque(false);
+				JLabel target_label = new JLabel(get("Target"));
+				target_label.setOpaque(false);
+				target_label.setPreferredSize(LABEL_SIZE);
+				target = new JLabel();
+				target.setOpaque(false);
+
+
+				JPanel name_pane = new JPanel();
+				name_pane.setOpaque(false);
+				JLabel name_label = new JLabel(get("Name"));
+				name_label.setOpaque(false);
+				name_label.setPreferredSize(LABEL_SIZE);
+				name = new GComboBox();
+				name.setEditable(true);
+
+				JPanel language_pane = new JPanel();
+				language_pane.setOpaque(false);
+				JLabel language_label = new JLabel(get("Language"));
+				language_label.setOpaque(false);
+				language_label.setPreferredSize(LABEL_SIZE);
+				language_box = new JComboBox(Gatherer.g_man.config_pane.getLanguageCodes().toArray());
+
+				JPanel center_pane = new JPanel();
+				center_pane.setOpaque(false);
+				value = new ComboArea(get("Values"), LABEL_SIZE);
+				value.setOpaque(false);
+				JTextArea v_text_area = (JTextArea) value.getTextComponent();
+				v_text_area.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				v_text_area.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+				v_text_area.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
+				v_text_area.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
+				JPanel button_pane = new JPanel();
+				button_pane.setOpaque(false);
+				ok_button = new JButton(get("General.OK"));
+				cancel_button = new JButton(get("General.Cancel"));
+				// Connection
+				TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button);
+				cancel_button.addActionListener(this);
+				name.addActionListener(this);
+				ok_button.addActionListener(this);
+				ok_button_enabler.add((JTextComponent)name.getEditor()); // Assuming the default editor is a JTextField!
+				// Layout
+				target_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+				target_pane.setLayout(new BorderLayout());
+				target_pane.add(target_label, BorderLayout.WEST);
+				target_pane.add(target, BorderLayout.CENTER);
+				
+				language_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+				language_pane.setLayout(new BorderLayout());
+				language_pane.add(language_label, BorderLayout.WEST);
+				language_pane.add(language_box, BorderLayout.CENTER);
+
+				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);
+
+				upper_pane.setLayout(new GridLayout(3,1));
+				upper_pane.add(target_pane);
+				upper_pane.add(name_pane);
+				upper_pane.add(language_pane);
+
+				value.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+
+				button_pane.setLayout(new GridLayout(1,2,5,0));
+				button_pane.add(ok_button);
+				button_pane.add(cancel_button);
+
+				center_pane.setLayout(new BorderLayout());
+				center_pane.add(value, BorderLayout.CENTER);
+				center_pane.add(button_pane, BorderLayout.SOUTH);
+
+				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);
+
+				setLocation((Gatherer.config.screen_size.width - ADD_OR_EDIT_ATTRIBUTE_SIZE.width) / 2, (Gatherer.config.screen_size.height - ADD_OR_EDIT_ATTRIBUTE_SIZE.height) / 2);
+		  }
+		  /** Any implementation of ActionListener must include this method so that we can be informed when an action as occured on our registered component, allowing us to add a new attribute to the selected set or element.
+			* @param event An <strong>ActionEvent</strong> containing information about the event.
+			*/
+		  public void actionPerformed(ActionEvent event) {
+				Object source = event.getSource();
+				if(source == ok_button) {
+					 boolean cont = true;
+					 // Now we add the new or improved values, removing old values if this is an edit.
+					 // Depends on what we are adding the attribute to.
+					 if(current_collection_file != null) {
+						  String name_str = name.getSelectedItem().toString();
+						  String value_str = value.getText();
+						  AttributeTableModel model = (AttributeTableModel) profile_attributes.getModel();
+						  // Remove the existing one if this is an edit.
+						  if(!add_type && current_attribute != -1) {
+								String old_source = (String) profile_attributes.getValueAt(current_attribute, 0);
+								Gatherer.c_man.msm.profiler.removeAction(current_collection_file, old_source);
+								old_source = null;
+								model.removeRow(current_attribute);
+						  }
+						  // First thing we check from profiles is that there isn't already an entry for this name.
+						  if(!model.contains(name_str, 0)) {
+								// Add profile
+								Gatherer.c_man.msm.profiler.addAction(current_collection_file, name_str, value_str);
+								// Update attribute table.
+								model.add(new Attribute(name_str, value_str));
+						  }
+						  else {
+								// Show an error message and do not proceed.
+								cont = false;
+								JOptionPane.showMessageDialog(self, get("Attribute_Already_Exists"), get("General.Error"), JOptionPane.ERROR_MESSAGE);
+						  }
+						  model = null;
+						  value_str = null;
+						  name_str = null;
+					 }
+					 else if(current_element != null) {
+						  // Add the attribute, even if one of the same name already exists. Maybe one day someone would like to enforce the occurance rules but not me and not today.
+						  String name_str = name.getSelectedItem().toString();
+						  String language_code = ((Language)language_box.getSelectedItem()).getCode();
+						  String value_str = value.getText();
+						  AttributeTableModel model = (AttributeTableModel) element_attributes.getModel();
+						  // Remove the existing one if this is an edit.
+						  if(!add_type && current_attribute != -1) {
+								model.removeRow(current_attribute);
+						  }
+						  // Add attribute
+						  current_element.addAttribute(name_str, language_code, value_str);
+						  // Update the attribute table
+						  model.add(new Attribute(name_str, language_code, value_str));
+						  model = null;
+						  value_str = null;
+						  language_code = null;
+						  name_str = null;
+					 }
+					 else if(current_set != null) {
+						  String name_str = name.getSelectedItem().toString();
+						  String value_str = value.getText();						
+						  // First thing we check from profiles is that there isn't already an entry for this name.
+						  AttributeTableModel model = (AttributeTableModel) set_attributes.getModel();
+						  // Remove the existing one if this is an edit.
+						  if(!add_type && current_attribute != -1) {
+								model.removeRow(current_attribute);
+						  }
+						  // First thing we check from profiles is that there isn't already an entry for this name.
+						  if(!model.contains(name_str, 0)) {
+								// Add profile
+								current_set.addAttribute(name_str, value_str);
+								// Update attribute table.
+								model.add(new Attribute(name_str, value_str));
+						  }
+						  // Otherwise provide an error message and do not proceed.
+						  else {
+								cont = false;
+								JOptionPane.showMessageDialog(self, get("Attribute_Already_Exists"), get("General.Error"), JOptionPane.ERROR_MESSAGE);
+						  }
+						  model = null;
+						  value_str = null;
+						  name_str = null;
+					 }
+					 // Hide dialog if we are allowed to continue.
+					 if(cont) {
+						  hide();
+					 }
+				}
+				else if(source == cancel_button) {
+					 // Hide dialog
+					 hide();
+				}
+				else if(source == name) {
+					 Object object = name.getSelectedItem();
+					 if(object != null) {
+						  java.util.List values = (java.util.List) name_to_values.get(object.toString());
+						  if(values == null) { // Only for collection files, otherwise values != null && values.size() == 0
+								values = Gatherer.c_man.msm.getElements();
+						  }
+						  value.clear();
+						  for(int i = 0; i < values.size(); i++) {
+								value.add(values.get(i));
+						  }
+					 }
+				}
+				else {
+					 name_to_values.clear();
+					 name.clear();
+					 value.clear();
+					 value.setText("");
+					 // Build the correct name_to_values mapping
+					 // Attributes are slightly tricky as they can come from several sources. Has a collection file been selected...
+					 if(current_collection_file != null) {
+						  target.setText(current_collection_file);
+						  // Name is empty in this one, however values must be the current elements in the collection.						  
+						  language_box.setEnabled(false);
+					 }
+					 // or has an element been selected
+					 else if(current_element != null) {
+						  target.setText(current_element.toString());
+						  // Develop a model for name based on known attributes from all other elements.
+						  java.util.List elements = Gatherer.c_man.msm.getElements();
+						  for(int i = 0; i < elements.size(); i++) {
+								ElementWrapper element = (ElementWrapper) elements.get(i);
+								TreeSet attributes = element.getAttributes();
+								for(Iterator attribute_iterator = attributes.iterator(); attribute_iterator.hasNext(); ) {
+									 Attribute attribute = (Attribute) attribute_iterator.next();
+									 java.util.List values = (java.util.List) name_to_values.get(attribute.name);
+									 if(values == null) {
+										  values = new ArrayList();
+										  name_to_values.put(attribute.name, values);
+									 }
+									 if(!values.contains(attribute.value)) {
+										  values.add(attribute.value);
+									 }
+									 values = null;
+									 attribute = null;
+								}
+								attributes = null;
+								element = null;
+						  }
+						  elements = null;
+						  language_box.setEnabled(true);
+					 }
+					 else if(current_set != null) {
+						  target.setText(current_set.toString());
+						  // Develop a model for name based on known attributes from all other metadata sets. At the same time build a hashmap mapping attribute name to lists of values.
+						  java.util.List sets = Gatherer.c_man.msm.getSets();
+						  for(int i = 0; i < sets.size(); i++) {
+								MetadataSet set = (MetadataSet) sets.get(i);
+								NamedNodeMap attributes = set.getAttributes();
+								for(int j = 0; j < attributes.getLength(); j++) {
+									 Attr attribute = (Attr) attributes.item(j);
+									 String name_str = attribute.getName();
+									 String value_str = attribute.getValue();
+									 java.util.List values = (java.util.List) name_to_values.get(name_str);
+									 if(values == null) {
+										  values = new ArrayList();
+										  name_to_values.put(name_str, values);
+									 }
+									 if(!values.contains(value_str)) {
+										  values.add(value_str);
+									 }
+									 values = null;
+									 value_str = null;
+									 name_str = null;
+									 attribute = null;
+								}
+								attributes = null;
+								set = null;
+								language_box.setEnabled(false);
+						  }
+						  sets = null;
+						  // If this is an add remove all the attributes already present in the current set.
+						  if(source == add_attribute) {
+								name.setEnabled(true);
+								NamedNodeMap attributes = current_set.getAttributes();
+								for(int i = 0; i < attributes.getLength(); i++) {
+									 Attr attribute = (Attr) attributes.item(i);
+									 String name_str = attribute.getName();
+									 name_to_values.remove(name_str);
+									 name_str = null;
+									 attribute = null;
+								}
+								attributes = null;
+						  }
+					 }
+					 // Otherwise we actually disable the name combobox
+					 else {
+						  name.setEnabled(false);
+					 }
+					 // Now name_to_values should contain a list of unique attribute names each mapping to a list of attribute values.
+					 for(Iterator name_iterator = name_to_values.keySet().iterator(); name_iterator.hasNext(); ) {
+						  name.add(name_iterator.next());
+					 }
+					 // Now pritty up the dialog depending on the action type
+					 if(source == add_attribute) {
+						  add_type = true;
+						  setTitle(get("AddAttribute"));
+						  if(current_collection_file != null) {
+								// Name is empty in this one, however values must be the current elements in the collection.	
+								java.util.List values = Gatherer.c_man.msm.getElements();
+								for(int i = 0; i < values.size(); i++) {
+									 value.add(new NameElementWrapperEntry(values.get(i)));
+								}
+								values = null;
+						  }
+						  show();
+					 }
+					 else if(current_attribute != -1) {
+						  add_type = false;
+						  setTitle(get("EditAttribute"));
+						  String name_str = (String) profile_attributes.getValueAt(current_attribute, 0);
+						  String value_str = (String) profile_attributes.getValueAt(current_attribute, 1);
+						  // Retrieve the appropriate value model
+						  java.util.List values = (java.util.List) name_to_values.get(name_str);
+						  // Only possible for collection file selections.
+						  if(values == null) {
+								values = Gatherer.c_man.msm.getElements();
+						  }
+						  name.setSelectedItem(name_str);
+						  name_str = null;
+						  for(int i = 0; i < values.size(); i++) {
+								value.add(new NameElementWrapperEntry(values.get(i)));
+						  }
+						  values = null;
+						  value.setSelectedItem(value_str);
+						  value_str = null;
+						  show();
+					 }
+				}
+				source = null;
+		  }
+		  
+		  public void dispose() {
+				cancel_button = null;
+				name = null;
+				name_to_values = null;
+				ok_button = null;
+				target = null;
+				value = null;
+		  }
+	 }
+	 
+	 private class AddElementActionListener
+		  extends JDialog
+		  implements ActionListener {
+		  private JButton cancel_button = null;
+		  private JButton ok_button = null;
+		  private JLabel set_field = null;
+		  private JTextField name_field = null;
+		  public AddElementActionListener() {
+				super(self);
+				setModal(true);
+				setSize(ADD_ELEMENT_SIZE);
+				// Creation
+				JPanel content_pane = (JPanel) getContentPane();
+				content_pane.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
+				JPanel center_pane = new JPanel();
+				center_pane.setOpaque(false);
+				JPanel set_pane = new JPanel();
+				set_pane.setOpaque(false);
+				JLabel set_label = new JLabel(get("Set"));
+				set_label.setOpaque(false);
+				set_label.setPreferredSize(LABEL_SIZE);
+				set_field = new JLabel();
+				set_field.setOpaque(false);
+				JPanel name_pane = new JPanel();
+				name_pane.setOpaque(false);
+				JLabel name_label = new JLabel(get("Name"));
+				name_label.setOpaque(false);
+				name_label.setPreferredSize(LABEL_SIZE);
+				name_field = new JTextField();
+				name_field.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				name_field.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+				name_field.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
+				name_field.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
+				JPanel button_pane = new JPanel();
+				button_pane.setOpaque(false);
+				ok_button = new JButton(get("General.OK"));
+				cancel_button = new JButton(get("General.Cancel"));
+				TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button);
+				// Connection
+				cancel_button.addActionListener(this);
+				ok_button.addActionListener(this);
+				ok_button_enabler.add(name_field);
+				// Layout
+				set_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+				set_pane.setLayout(new BorderLayout());
+				set_pane.add(set_label, BorderLayout.WEST);
+				set_pane.add(set_field, BorderLayout.CENTER);
+
+				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_field, BorderLayout.CENTER);
+
+				center_pane.setLayout(new GridLayout(2,1,0,0));
+				center_pane.add(set_pane);
+				center_pane.add(name_pane);
+
+				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(center_pane, BorderLayout.CENTER);
+				content_pane.add(button_pane, BorderLayout.SOUTH);
+
+				setLocation((Gatherer.config.screen_size.width - ADD_ELEMENT_SIZE.width) / 2, (Gatherer.config.screen_size.height - ADD_ELEMENT_SIZE.height) / 2);
+		  }
+		  /** Any implementation of ActionListener must include this method so that we can be informed when an action as occured on our registered component, allowing us to
+			* @param event An <strong>ActionEvent</strong> containing information about the event.
+			*/
+		  public void actionPerformed(ActionEvent event) {
+				Object source = event.getSource();
+				if(source == ok_button) {
+					 // Add then dispose
+					 String name_str = name_field.getText();
+					 // If this element doesn't already exist.
+					 if(!current_set.containsElement(name_str)) {
+						  // Add it,
+						  ElementWrapper element = current_set.addElement(name_str);
+						  // Then update the tree
+						  model.add(current_node, element, MEMNode.ELEMENT);
+						  // Done
+						  element = null;
+						  hide();
+					 }
+					 // Otherwise show an error message and do not proceed.
+					 else {
+						  JOptionPane.showMessageDialog(self, get("Element_Already_Exists"), get("General.Error"), JOptionPane.ERROR_MESSAGE);
+					 }
+					 name_str = null;
+				}
+				else if(source == cancel_button) {
+					 // Dispose
+					 hide();
+				}
+				else {
+					 if(current_set != null) {
+						  // You can't manually add elements to the Greenstone metadata set.
+						  if(!current_set.getNamespace().equals("")) {
+								set_field.setText(current_set.toString());
+								name_field.setText("");
+								// Display
+								show();
+						  }
+						  // Warn the user that they can't do that dave.
+						  else {
+								JOptionPane.showMessageDialog(self, get("Cannot_Add_Elements_To_Greenstone_MDS"), get("General.Error"), JOptionPane.ERROR_MESSAGE);
+						  }
+					 }
+				}
+				source = null;
+		  }
+
+		  public void dispose() {
+				cancel_button = null;
+				ok_button = null;
+				name_field = null;
+				set_field = null;
+		  }
+	 }
+	 
+	 private class AddFileActionListener
+		  extends JDialog
+		  implements ActionListener {
+		  private JButton cancel_button = null;
+		  private JButton ok_button = null;
+		  private JTextField name_field = null;
+		  public AddFileActionListener() {
+				super(self);
+				setModal(true);
+				setSize(ADD_FILE_SIZE);
+				// Creation
+				JPanel content_pane = (JPanel) getContentPane();
+				content_pane.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
+				JPanel center_pane = new JPanel();
+				center_pane.setOpaque(false);
+				JPanel profile_pane = new JPanel();
+				profile_pane.setOpaque(false);
+				JLabel profile_label = new JLabel(get("Profile"));
+				profile_label.setOpaque(false);
+				profile_label.setPreferredSize(LABEL_SIZE);
+				JPanel name_pane = new JPanel();
+				name_pane.setOpaque(false);
+				JLabel name_label = new JLabel(get("Name"));
+				name_label.setOpaque(false);
+				name_label.setPreferredSize(LABEL_SIZE);
+				name_field = new JTextField();
+				name_field.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				name_field.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+				name_field.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
+				name_field.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
+				JPanel button_pane = new JPanel();
+				button_pane.setOpaque(false);
+				ok_button = new JButton(get("General.OK"));
+				cancel_button = new JButton(get("General.Cancel"));
+				TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button);
+				// Connection
+				cancel_button.addActionListener(this);
+				ok_button.addActionListener(this);
+				ok_button_enabler.add(name_field);
+				// Layout
+				profile_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+				profile_pane.setLayout(new BorderLayout());
+				profile_pane.add(profile_label, BorderLayout.CENTER);
+
+				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_field, BorderLayout.CENTER);
+
+				center_pane.setLayout(new GridLayout(2,1,0,0));
+				center_pane.add(profile_pane);
+				center_pane.add(name_pane);
+
+				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(center_pane, BorderLayout.CENTER);
+				content_pane.add(button_pane, BorderLayout.SOUTH);
+
+				setLocation((Gatherer.config.screen_size.width - ADD_FILE_SIZE.width) / 2, (Gatherer.config.screen_size.height - ADD_FILE_SIZE.height) / 2);
+		  }
+		  /** Any implementation of ActionListener must include this method so that we can be informed when an action as occured on our registered component, allowing us to
+			* @param event An <strong>ActionEvent</strong> containing information about the event.
+			*/
+		  public void actionPerformed(ActionEvent event) {
+				Object source = event.getSource();
+				if(source == ok_button) {
+					 String name_str = name_field.getText();
+					 // Ensure that this source doesn't already exist.
+					 if(!Gatherer.c_man.msm.profiler.containsSource(name_str)) {
+						  // Add source with empty hashmap of actions.
+						  Gatherer.c_man.msm.profiler.addSource(name_str);
+						  // Add to tree
+						  model.add(model.getProfileNode(), name_str, MEMNode.COLLECTION);
+						  hide();
+					 }
+					 // Otherwise warn the user and don't hide the prompt.
+					 else {
+						  JOptionPane.showMessageDialog(self, get("File_Already_Exists"), get("General.Error"), JOptionPane.ERROR_MESSAGE);
+					 }
+					 name_str = null;
+				}
+				else if(source == cancel_button) {
+					 hide();
+				}
+				else {
+					 name_field.setText("");
+					 show();
+				}
+				source = null;
+		  }
+
+		  public void dispose() {
+				cancel_button = null;
+				ok_button = null;
+				name_field = null;
+		  }
+	 }
+
+	 private class AddSetActionListener
+		  extends JDialog
+		  implements ActionListener {
+		  private JButton cancel_button = null;
+		  private JButton ok_button = null;
+		  private JTextField name_field = null;
+		  private JTextField namespace_field = null;
+		  public AddSetActionListener() {
+				super(self);
+				setModal(true);
+				setSize(ADD_SET_SIZE);
+				setTitle(get("AddSet"));
+				// Creation
+				JPanel content_pane = (JPanel) getContentPane();
+				content_pane.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
+				JPanel center_pane = new JPanel();
+				center_pane.setOpaque(false);
+
+				JPanel namespace_pane = new JPanel();
+				namespace_pane.setOpaque(false);
+				JLabel namespace_label = new JLabel(get("Namespace"));
+				namespace_label.setOpaque(false);
+				namespace_label.setPreferredSize(LABEL_SIZE);
+				namespace_field = new JTextField();
+				namespace_field.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				namespace_field.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+				namespace_field.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
+				namespace_field.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
+
+				JPanel name_pane = new JPanel();
+				name_pane.setOpaque(false);
+				JLabel name_label = new JLabel(get("Name"));
+				name_label.setOpaque(false);
+				name_label.setPreferredSize(LABEL_SIZE);
+				name_field = new JTextField();
+				name_field.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				name_field.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+				name_field.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
+				name_field.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
+
+				JPanel button_pane = new JPanel();
+				button_pane.setOpaque(false);
+				ok_button = new JButton(get("General.OK"));
+				ok_button.setEnabled(false);
+				cancel_button = new JButton(get("General.Cancel"));
+				TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button);
+				// Connection
+				cancel_button.addActionListener(this);
+				ok_button.addActionListener(this);
+				ok_button_enabler.add(name_field);
+				ok_button_enabler.add(namespace_field);
+				// Layout
+				namespace_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
+				namespace_pane.setLayout(new BorderLayout());
+				namespace_pane.add(namespace_label, BorderLayout.WEST);
+				namespace_pane.add(namespace_field, BorderLayout.CENTER);
+
+				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_field, BorderLayout.CENTER);
+
+				center_pane.setLayout(new GridLayout(2,1));
+				center_pane.add(namespace_pane);
+				center_pane.add(name_pane);
+
+				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(center_pane, BorderLayout.CENTER);
+				content_pane.add(button_pane, BorderLayout.SOUTH);
+
+				setLocation((Gatherer.config.screen_size.width - ADD_SET_SIZE.width) / 2, (Gatherer.config.screen_size.height - ADD_SET_SIZE.height) / 2);
+		  }
+		  /** Any implementation of ActionListener must include this method so that we can be informed when an action as occured on our registered component, allowing us to
+			* @param event An <strong>ActionEvent</strong> containing information about the event.
+			*/
+		  public void actionPerformed(ActionEvent event) {
+				Object source = event.getSource();
+				if(source == ok_button) {
+					 String namespace_str = namespace_field.getText();
+					 String name_str = name_field.getText();
+					 // Ensure the set doesn't already exist
+					 if(Gatherer.c_man.msm.getSet(name_str) == null) {
+						  MetadataSet set = Gatherer.c_man.msm.addSet(namespace_str, name_str);
+						  // Update tree.
+						  model.add(null, set, MEMNode.SET);
+						  // Done
+						  set = null;
+						  hide();
+					 }
+					 // Otherwise show a warning.
+					 else {
+						  JOptionPane.showMessageDialog(self, get("Set_Already_Exists"), get("General.Error"), JOptionPane.ERROR_MESSAGE);
+					 }
+					 name_str = null;
+					 namespace_str = null;
+				}
+				else if(source == cancel_button) {
+					 hide();
+				}
+				else {
+					 name_field.setText("");
+					 show();
+				}
+		  }
+		  
+		  public void dispose() {
+				cancel_button = null;
+				ok_button = null;
+				name_field = null;
+		  }
+	 }
+	 
+	 private class AddOrEditValueActionListener
+		  extends JDialog
+		  implements ActionListener, TreeSelectionListener {
+		  private boolean add_type = true;
+		  private boolean ignore = false;
+		  private GValueNode subject_node = null;
+		  private JButton cancel_button = null;
+		  private JButton ok_button = null;
+		  private JTextArea value = null;
+		  private JTextField alias = null;
+		  private SmarterTree subject_tree = null;
+
+		  /** Constructor. */
+		  public AddOrEditValueActionListener() {
+				super(self);
+				this.setModal(true);
+				this.setSize(ADD_OR_EDIT_VALUE_SIZE);
+				// Create
+				JPanel content_pane = (JPanel) getContentPane();
+				content_pane.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false));
+				JPanel center_pane = new JPanel();
+				center_pane.setOpaque(false);
+				JPanel inner_pane = new JPanel();
+				inner_pane.setOpaque(false);
+				JPanel subject_tree_pane = new JPanel();
+				subject_tree_pane.setOpaque(false);
+				JLabel subject_tree_label = new JLabel(get("Subject")); 
+				subject_tree_label.setOpaque(false);
+				subject_tree = new SmarterTree();
+				subject_tree.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				subject_tree.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+				subject_tree.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
+				subject_tree.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
+				JPanel value_pane = new JPanel();
+				value_pane.setOpaque(false);
+				JLabel value_label = new JLabel(get("Value"));
+				value_label.setOpaque(false);
+				value = new JTextArea();
+				value.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				value.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+				value.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
+				value.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
+				JPanel alias_pane = new JPanel();
+				alias_pane.setOpaque(false);
+				JLabel alias_label = new JLabel(get("Alias"));
+				alias_label.setOpaque(false);
+				alias_label.setPreferredSize(LABEL_SIZE);
+				alias = new JTextField();
+				alias.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+				alias.setForeground(Gatherer.config.getColor("coloring.collection_tree_foreground", false));
+				alias.setSelectionColor(Gatherer.config.getColor("coloring.collection_selection_background", false));
+				alias.setSelectedTextColor(Gatherer.config.getColor("coloring.collection_selection_foreground", false));
+				JPanel button_pane = new JPanel();
+				button_pane.setOpaque(false);
+				ok_button = new JButton(get("General.OK"));
+				ok_button.setEnabled(false);
+				cancel_button = new JButton(get("General.Cancel"));
+				// Connect
+				TextFieldEnabler ok_button_enabler = new TextFieldEnabler(ok_button);
+				cancel_button.addActionListener(this);
+				ok_button.addActionListener(this);
+				subject_tree.addTreeSelectionListener(this);
+				ok_button_enabler.add(value);
+				// Layout
+				subject_tree_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+				subject_tree_pane.setLayout(new BorderLayout());
+				subject_tree_pane.add(subject_tree_label, BorderLayout.NORTH);
+				subject_tree_pane.add(new JScrollPane(subject_tree), BorderLayout.CENTER);
+
+				value_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
+				value_pane.setLayout(new BorderLayout());
+				value_pane.add(value_label, BorderLayout.NORTH);
+				value_pane.add(new JScrollPane(value), BorderLayout.CENTER);
+				
+				inner_pane.setLayout(new GridLayout(2,1));
+				inner_pane.add(subject_tree_pane);
+				inner_pane.add(value_pane);
+
+				alias_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
+				alias_pane.setLayout(new BorderLayout());
+				alias_pane.add(alias_label, BorderLayout.WEST);
+				alias_pane.add(alias, BorderLayout.CENTER);
+
+				center_pane.setLayout(new BorderLayout());
+				center_pane.add(inner_pane, BorderLayout.CENTER);
+				center_pane.add(alias_pane, BorderLayout.SOUTH);
+
+				button_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
+				button_pane.setLayout(new GridLayout(1,2,5,5));
+				button_pane.add(ok_button);
+				button_pane.add(cancel_button);
+
+				content_pane.setLayout(new BorderLayout());
+				content_pane.add(center_pane, BorderLayout.CENTER);
+				content_pane.add(button_pane, BorderLayout.SOUTH);
+				setLocation((Gatherer.config.screen_size.width - ADD_OR_EDIT_VALUE_SIZE.width) / 2, (Gatherer.config.screen_size.height - ADD_OR_EDIT_VALUE_SIZE.height) / 2);
+		  }
+		  /** Any implementation of ActionListener must include this method so that we can be informed when an action as occured on our registered component, allowing us to add a new metadata value to the assigned values tree.
+			* @param event An <strong>ActionEvent</strong> containing information about the event.
+			*/
+		  public void actionPerformed(ActionEvent event) {
+				Object source = event.getSource();
+				if(source == ok_button) {
+					 // Now we action as necessary
+					 GValueModel model = Gatherer.c_man.msm.getValueTree(current_element);
+					 if(add_type) {
+						  // Add this value to the tree.
+						  GValueNode parent = null;
+						  model.addValue(value.getText(), subject_node, alias.getText());
+						  parent = null;
+					 }
+					 else {
+						  // Rewrite this value in the DOM model. Note that this will automatically rewrite all assignments as they are live references.
+						  current_value_node.setValue(value.getText());
+						  current_value_node.setAlias(alias.getText());
+						  // Now insert the node into the currently selected subject, but only if the parent has changed.
+						  if(subject_node != current_value_node.getParent()) {
+								GValueNode old_subject_node = (GValueNode) current_value_node.getParent();
+								// Find the new values position in subject_nodes children.
+								GValueNode sibling = null;
+								int index = 0;
+								boolean found = false;
+								while(index < subject_node.getChildCount() && !found) {
+									 sibling = (GValueNode) subject_node.getChildAt(index);
+									 int order = current_value_node.toString().compareToIgnoreCase(sibling.toString());
+									 // If the sibling is 'greater than' or comes after current value then insert.
+									 if(order < 0) {
+										  // Insert. This will coincidently remove from original parent.
+										  Node parent_node = subject_node.getElement();
+										  Node child_node = current_value_node.getElement();
+										  Node sibling_node = sibling.getElement();
+										  parent_node.insertBefore(child_node, sibling_node);
+										  found = true;
+									 }
+									 // The value already exists exactly as is. In theory this case can never happenm but just incase do nothing more.
+									 else if(order == 0) {
+										  found = true;
+									 }
+									 // The sibling is 'less than' or before the current value, keep looking.
+									 else {
+										  index++;
+									 }
+								}
+								// If we haven't done so yet, insert the current node. This will coincidently remove from original parent.
+								if(!found) {
+									 Node parent_node = subject_node.getElement();
+									 Node child_node = current_value_node.getElement();
+									 parent_node.appendChild(child_node);
+								}
+								// Inform the tree model what two nodes structures have changed (origin and destination).
+								subject_node.unmap();
+								old_subject_node.unmap();
+								model.nodeStructureChanged(old_subject_node);
+								model.nodeStructureChanged(subject_node);
+						  }
+						  // And if a data change was made tell the tree its data model is ka-bluey.
+						  else {
+								model.nodeChanged(current_value_node);
+						  }
+					 }
+					 model = null;
+					 // Hide dialog
+					 hide();
+				}
+				else if(source == cancel_button) {
+					 // Hide dialog
+					 hide();
+				}
+				else {
+					 // Reset dialog
+					 // current_value_node
+					 GValueModel model = Gatherer.c_man.msm.getValueTree(current_element);
+					 subject_tree.setModel(model);
+					 // Task specific
+					 if(source == add_value) {
+						  add_type = true;
+						  if(current_value_node != null) {
+								subject_node = current_value_node;
+						  }
+						  else {
+								subject_node = (GValueNode) model.getRoot();
+						  }
+						  value.setText("");
+						  alias.setText("");
+						  setTitle(get("AddValue"));
+					 }
+					 else {
+						  add_type = false;
+						  if(current_value_node != null) {
+								subject_node = (GValueNode) current_value_node.getParent();
+						  }
+						  else {
+								subject_node = (GValueNode) model.getRoot();
+						  }
+						  value.setText(current_value_node.toString());
+						  alias.setText(current_value_node.getAlias());
+						  setTitle(get("EditValue"));
+					 }
+					 model = null;
+					 if(subject_node != null) {
+						  TreePath path = new TreePath(subject_node.getPath());
+						  subject_tree.scrollPathToVisible(path);
+						  subject_tree.setSelectionPath(path);
+						  path = null;
+					 }
+					 // Display
+					 show();
+				}
+		  }
+
+		  public void dispose() {
+				alias = null;
+				cancel_button = null;
+				ok_button = null;
+				subject_node = null;
+				subject_tree = null;
+				value = null;
+		  }
+
+		  public void valueChanged(TreeSelectionEvent event) {
+				if(subject_tree.getSelectionCount() > 0 && !ignore) {
+					 ignore = true;
+					 TreePath selected_path = subject_tree.getSelectionPath();
+					 GValueNode requested_node = (GValueNode) selected_path.getLastPathComponent();
+					 // Ensure the requested node is not a descendant of the current_value_node
+					 if(current_value_node != null) {
+						  if(!add_type && current_value_node.isNodeDescendant(requested_node)) {
+								TreePath path = new TreePath(subject_node.getPath());
+								subject_tree.scrollPathToVisible(path);
+								subject_tree.setSelectionPath(path);
+						  }
+						  else {
+								subject_node = requested_node;
+						  }
+					 }
+					 selected_path = null;
+					 ignore = false;
+				}
+		  }
+	 }
+	 
+	private class CloseActionListener
+		extends JDialog
+		implements ActionListener {
+		/** Any implementation of ActionListener must include this method so that we can be informed when an action as occured on our registered component, allowing us to close the editor dialog.
+		 * @param event An <strong>ActionEvent</strong> containing information about the event.
+		 */
+		public void actionPerformed(ActionEvent event) {
+			self.dispose();
+		}
+	}
+
+	 private class RemoveAttributeActionListener
+		  implements ActionListener {
+		  /** Any implementation of ActionListener must include this method so that we can be informed when an action as occured on our registered component, allowing us to
+			* @param event An <strong>ActionEvent</strong> containing information about the event.
+			*/
+		  public void actionPerformed(ActionEvent event) {
+				if(current_attribute != -1) {
+					 int result = JOptionPane.showOptionDialog(self, get("MEM.Confirm_Removal", get("Attribute")), get("Confirm_Removal_Title"), JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, dialog_options, dialog_options[0]);
+					 // Remove this attribute
+					 if(result == 0) {
+						  ignore = true;
+						  // Attributes are tricky little beasties, as they can come from several different places and depend upon what other little beasties have been selected
+						  // Has a collection file been selected...
+						  if(current_collection_file != null) {
+								// Remove a profile
+								String source = (String) profile_attributes.getValueAt(current_attribute, 0);
+								Gatherer.c_man.msm.profiler.removeAction(current_collection_file, source);
+								source = null;
+								// Refresh table
+								((AttributeTableModel)profile_attributes.getModel()).removeRow(current_attribute);
+						  }
+						  // or has an element been selected
+						  else if(current_element != null) {
+								// Remove element attribute
+								String name = (String) element_attributes.getValueAt(current_attribute, 0);
+								String value = (String) element_attributes.getValueAt(current_attribute, 1);
+								current_element.removeAttribute(name, value); // Can be multiple authors for instance
+								// Refresh table
+								((AttributeTableModel)element_attributes.getModel()).removeRow(current_attribute);
+						  }
+						  else if(current_set != null) {
+								String name = (String) set_attributes.getValueAt(current_attribute, 0);
+								// Remove set attribute
+								current_set.removeAttribute(name);
+								// Refresh table
+								((AttributeTableModel)set_attributes.getModel()).removeRow(current_attribute);
+						  }
+						  // Disable buttons
+						  edit_attribute.setEnabled(false);
+						  remove_attribute.setEnabled(false);
+						  ignore = false;
+					 }
+				}
+		  }
+	 }
+
+	 private class RemoveElementActionListener
+		  implements ActionListener {
+		  /** Any implementation of ActionListener must include this method so that we can be informed when an action as occured on our registered component, allowing us to provide an editing prompt.
+			* @param event An <strong>ActionEvent</strong> containing information about the event.
+			*/
+		  public void actionPerformed(ActionEvent event) {
+				if(current_element != null) {
+					 int result = JOptionPane.showOptionDialog(self, get("MEM.Confirm_Removal", get("Element")), get("Confirm_Removal_Title"), JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, dialog_options, dialog_options[0]);
+					 // Remove this attribute
+					 if(result == 0) {
+						  ignore = true;
+						  Gatherer.c_man.msm.removeElement(current_element);
+						  // Clear selection
+						  mds_tree.clearSelection();
+						  model.remove(current_element.toString(), MEMNode.ELEMENT);
+						  // Meanwhile disable/enable controls given we had an element selected, but no longer do.
+						  remove_element.setEnabled(false);
+						  // Show a blank panel.
+						  card_layout.show(details_pane, BLANK);
+						  ignore = false;
+					 }
+				}
+				else {
+					 ///ystem.err.println("No current element selected.");
+				}
+		  }
+	 }
+
+	 private class RemoveFileActionListener
+		  implements ActionListener {
+		  /** Any implementation of ActionListener must include this method so that we can be informed when an action as occured on our registered component, allowing us to provide an editing prompt.
+			* @param event An <strong>ActionEvent</strong> containing information about the event.
+			*/
+		  public void actionPerformed(ActionEvent event) {
+				if(current_collection_file != null) {
+					 int result = JOptionPane.showOptionDialog(self, get("MEM.Confirm_Removal", get("File")), get("Confirm_Removal_Title"), JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, dialog_options, dialog_options[0]);
+					 // Remove the current collection file profile from the profiler.
+					 if(result == 0) {
+						  ignore = true;
+						  Gatherer.c_man.msm.profiler.removeProfile(current_collection_file);
+// Clear selection
+						  mds_tree.clearSelection();
+						  model.remove(current_collection_file, MEMNode.COLLECTION);
+						  // Meanwhile disable/enable controls given we had a set selected, but no longer do.
+						  remove_file.setEnabled(false);
+						  // Show a blank panel.
+						  card_layout.show(details_pane, BLANK);
+						  ignore = false;
+					 }
+				}
+		  }
+	 }
+
+	 private class RemoveSetActionListener
+		  implements ActionListener {
+		  /** Any implementation of ActionListener must include this method so that we can be informed when an action as occured on our registered component, allowing us to
+			* @param event An <strong>ActionEvent</strong> containing information about the event.
+			*/
+		  public void actionPerformed(ActionEvent event) {
+				if(current_set != null) {
+					 int result = JOptionPane.showOptionDialog(self, get("MEM.Confirm_Removal", get("Set")), get("Confirm_Removal_Title"), JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, dialog_options, dialog_options[0]);
+					 // Remove the currently selected set
+					 if(result == 0) {
+						  ignore = true;
+						  Gatherer.c_man.msm.removeSet(current_set);
+						  // Clear selection
+						  mds_tree.clearSelection();
+						  model.remove(current_set.toString(), MEMNode.SET);
+						  // Meanwhile disable/enable controls given we had a set selected, but no longer do.
+						  remove_set.setEnabled(false);
+						  // Show a blank panel.
+						  card_layout.show(details_pane, BLANK);
+						  ignore = false;
+					 }
+				}
+		  }
+	 }
+	 /** This class will remove the currently selected metadata or profile value when any registered control is actioned. Note that removing a value acts differently from the other removes in that if you remove a value which is still assigned somewhere the values are restored next time said assignment is viewed. This turned out far easier and reasonable to code than attempting to remove all remaining values when you delete its reference in the GValueModel. */
+	 private class RemoveValueActionListener
+		  implements ActionListener {
+		  /** Any implementation of ActionListener must include this method so that we can be informed when an action as occured on our registered component, allowing us to
+			* @param event An <strong>ActionEvent</strong> containing information about the event.
+			*/
+		  public void actionPerformed(ActionEvent event) {
+				if(current_value_node != null) {				 
+					 int result = JOptionPane.showOptionDialog(self, get("MEM.Confirm_Removal", get("Value")), get("Confirm_Removal_Title"), JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, dialog_options, dialog_options[0]);
+					 // Remove the current selected value
+					 if(result == 0) {
+						  ignore = true;
+						  GValueModel model = (GValueModel) element_values.getModel();
+						  model.removeValue(current_value_node);
+						  // Meanwhile disable/enable controls given we had a value selected, but no longer do.
+						  edit_value.setEnabled(false);
+						  remove_value.setEnabled(false);
+						  ignore = false;
+					 }
+				}
+		  }
+	 }
+	 
+	/** Used to enable a certain target component if and only if all the registered text fields contain non-zero length strings. */
+	private class TextFieldEnabler
+		extends KeyAdapter {
+		private Component target = null;
+		private JTextComponent[] fields = null;
+		public TextFieldEnabler(Component target) {
+			super();
+			this.target = target;
+		}
+		public void add(JTextComponent field) {
+			field.addKeyListener(this);
+			if(fields == null) {
+				fields = new JTextComponent[1];
+				fields[0] = field;
+			}
+			else {
+				JTextComponent[] temp = new JTextComponent[fields.length + 1];
+				System.arraycopy(fields, 0, temp, 0, fields.length);
+				temp[fields.length] = field;
+				fields = temp;
+			}
+		}
+		public void keyReleased(KeyEvent event) {
+			boolean enable = true;
+			for(int i = 0; i < fields.length; i++) {
+				enable = enable && fields[i].getText().length() > 0;
+			}
+			target.setEnabled(enable);
+		}
+	}
+
+	private class AttributesListSelectionListener
+		implements ListSelectionListener {
+		 private JTable table = null;
+		 public AttributesListSelectionListener(JTable table) {
+			  this.table = table;
+		 }
+		 public void valueChanged(ListSelectionEvent event) {
+			  if((current_attribute = table.getSelectedRow()) != -1) {
+					edit_attribute.setEnabled(true);
+					remove_attribute.setEnabled(true);
+			  }
+			  else {
+					current_attribute = -1;
+					edit_attribute.setEnabled(false);
+					remove_attribute.setEnabled(false);
+			  }
+		 }
+	}
+
+	private class ElementValuesTreeSelectionListener
+		implements TreeSelectionListener {
+		 public void valueChanged(TreeSelectionEvent event) {
+			  if(element_values.getSelectionCount() > 0) {
+					// Retrieve the selected value node.
+					TreePath selected_path = element_values.getSelectionPath();
+					current_value_node = (GValueNode) selected_path.getLastPathComponent();
+					edit_value.setEnabled(true);
+					remove_value.setEnabled(true);
+			  }
+			  else {
+					current_value_node = null;
+					edit_value.setEnabled(false);
+					remove_value.setEnabled(false);
+			  }
+		 }
+	}
+
+	private class MDSTreeSelectionListener
+		implements TreeSelectionListener {
+		 public void valueChanged(TreeSelectionEvent event) {
+			  if(!ignore) {
+					// Clear all variables based on previous tree selection
+					current_collection_file = null;
+					current_element = null;
+					current_set = null;
+					// Now process the node selected
+					TreePath path = event.getPath();
+					current_node = (MEMNode)path.getLastPathComponent();
+					// What we show depends on the node type...
+					AttributeTableModel atm = null;
+					TreeSet attributes = null;
+					switch(current_node.getType()) {
+					case MEMNode.COLLECTION:
+						 current_collection_file = current_node.toString();
+						 atm = current_node.getModel();
+						 if(atm == null) {
+							  ArrayList sources = Gatherer.c_man.msm.profiler.getSources(current_collection_file);
+							  attributes = new TreeSet();
+							  for(int i = 0; i < sources.size(); i++) {
+									String source = (String) sources.get(i);
+									String action = Gatherer.c_man.msm.profiler.getAction(current_collection_file, source);
+									if(action == null) {
+										 action = get("Ignore");
+									}
+									attributes.add(new Attribute(source, action));
+							  }
+							  atm = new AttributeTableModel(attributes, get("Source"), get("Target"), get("Ignore"));
+							  //current_node.setModel(atm);
+						 }
+						 profile_attributes.setModel(atm);
+						 atm.setScrollPane(profile_attributes_scroll);
+						 atm.setTable(profile_attributes);
+
+						 card_layout.show(details_pane, PROFILE);
+						 setControls(true, false, false, true, false, false, true, false, false, false, false, false);
+						 break;
+					case MEMNode.ELEMENT:
+						 current_element = current_node.getElement();
+						 atm = current_node.getModel();
+						 if(atm == null) {
+							  atm = new AttributeTableModel(current_element.getAttributes(), get("Name"), get("Language_Code"), get("Value"), "");
+							  //current_node.setModel(atm);
+						 }
+						 element_attributes.setModel(atm);
+						 atm.setScrollPane(element_attributes_scroll);
+						 atm.setTable(element_attributes);
+
+						 element_values.setModel(Gatherer.c_man.msm.getValueTree(current_element));
+						 card_layout.show(details_pane, ELEMENT);
+						 // Meanwhile disable/enable controls depending on this Element selection.
+						 setControls(true, false, false, false, false, true, true, false, false, true, false, false);
+						 break;
+					case MEMNode.SET:
+						 current_set = current_node.getSet();
+						 atm = current_node.getModel();
+						 if(atm == null) {
+							  NamedNodeMap temp = current_set.getAttributes();
+							  attributes = new TreeSet();
+							  for(int i = 0; i < temp.getLength(); i++) {
+									Attr attribute = (Attr) temp.item(i);
+									// We don't show the namespace attribute, as it is used as a unique primary key and should never be changed or removed in itself.
+									if(!attribute.getName().equals("namespace")) {
+										 attributes.add(new Attribute(attribute.getName(), attribute.getValue()));
+									}
+									attribute = null;
+							  }
+							  atm = new AttributeTableModel(attributes, get("Name"), get("Value"), "");
+							  //current_node.setModel(atm);
+							  temp = null;
+						 }
+						 set_attributes.setModel(atm);
+						 atm.setScrollPane(set_attributes_scroll);
+						 atm.setTable(set_attributes);
+						 
+						 card_layout.show(details_pane, SET);
+						 attributes = null;
+						 // Meanwhile disable/enable controls depending on this Element selection.
+						 setControls(true, true, false, false, true, false, true, false, false, false, false, false);
+						 break;
+					case MEMNode.PROFILER:
+						 // Meanwhile disable/enable controls depending on this Element selection.
+						 setControls(true, false, true, false, false, false, false, false, false, false, false, false);
+					default:
+						 // Show a blank panel.
+						 card_layout.show(details_pane, BLANK);
+					}
+					attributes = null;
+					path = null;
+					atm = null;
+			  }
+		 }
+	}
+
+	 private class MEMTreeCellRenderer
+		  extends DefaultTreeCellRenderer {
+		  public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
+				super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
+				setToolTipText(value.toString());
+				return this;
+		  }
+	 }
+
+	 /** Wrap a ElementWrapper so we get its name when we ask for toString(), not its identifier. */
+	 private class NameElementWrapperEntry 
+		  implements Comparable {
+		  private ElementWrapper element_wrapper = null;
+		  public NameElementWrapperEntry(Object object) {
+				this.element_wrapper = (ElementWrapper) object;
+		  }
+		  public int compareTo(Object object) {
+				return element_wrapper.compareTo(object);
+		  }
+		  public boolean equals(Object object) {
+				return element_wrapper.equals(object);
+		  }
+		  public String toString() {
+				return element_wrapper.getName();
+		  }
+	 }
+}
+
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/Declarations.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/Declarations.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/Declarations.java	(revision 13666)
@@ -0,0 +1,77 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+package org.greenstone.gatherer.msm;
+/**************************************************************************************
+ * Title:        Gatherer
+ * Description:  The Gatherer: a tool for gathering and enriching a digital collection.
+ * Company:      The University of Waikato
+ * Written:        /  /01
+ * Revised:      03/10/02 - Commented
+ **************************************************************************************/
+/** This utility class contains several enumerations used throughout the MSM package. 
+ * @author John Thompson
+ * @version 2.3
+ */
+final public class Declarations {
+	 /** An element of the action type enumeration. */
+	 static public final int NO_ACTION   = 0;
+	 /** An element of the action type enumeration. */
+	 static public final int ADD         = 1;
+	 /** An element of the action type enumeration. */
+	 static public final int CANCEL      = 2;
+	 /** An element of the action type enumeration. This action merges two unrelated elements, as requested by the user. */
+	 static public final int FORCE_MERGE = 3;
+	 /** An element of the action type enumeration. */
+	 static public final int MERGE       = 4;
+	 /** An element of the action type enumeration. */
+	 static public final int RENAME      = 5;
+	 /** An element of the action type enumeration. */
+	 static public final int REPLACE     = 6;
+	 /** An element of the action type enumeration. */
+	 static public final int SKIP        = 7;
+	 /** An element of the action type enumeration. */
+	 static public final int HFILE       = 8;
+	 /** An element of the action type enumeration. This special value is used internally to indicate a certain element has been removed from the metadata sets. */
+	 static public final int DELETE      = 9;
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/ElementWrapper.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/ElementWrapper.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/ElementWrapper.java	(revision 13666)
@@ -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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+package org.greenstone.gatherer.msm;
+/**************************************************************************************
+ * Title:        Gatherer
+ * Description:  The Gatherer: a tool for gathering and enriching a digital collection.
+ * Company:      The University of Waikato
+ * Written:        /  /01
+ * Revised:      03/10/02 - Commented
+ **************************************************************************************/
+import java.util.TreeSet;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.greenstone.gatherer.util.Utility;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+/** This class provides a convience wrapper around a DOM model Element to allow Components such as the MetadataTable to display this information properly. 
+ * @author John Thompson
+ * @version 2.3
+ */
+public class ElementWrapper 
+	 implements Comparable {
+	 /** The DOM element this wrapper is wrapped around. */
+	 private Element element = null;
+	 /** A string prefix identifying the metadata set namespace. */
+	 private String namespace = null;
+	 /** Constructor for elements with no namespace necessary.
+	  * @param element The DOM <strong>Element</strong> this is to be based on.
+	  */ 
+	 public ElementWrapper(Element element) {
+		  this.element = element;
+	 }
+	 /** Constructor.
+	  * @param element The DOM <strong>Element</strong> this is to be based on.
+	  * @param namespace_required <i>true</i> if this element wrapper should always attempt to show a namespace prefix (retrieving it from the DOM if necessary).
+	  * @deprecated
+	  */
+	 public ElementWrapper(Element element, boolean namespace_required) {
+		  this(element);
+	 }
+
+	 public void addAttribute(String name, String value) {
+		  MSMUtils.addElementAttribute(element, name, "en", value);
+	 }
+
+	 public void addAttribute(String name, String language, String value) {
+		  MSMUtils.addElementAttribute(element, name, language, value);
+	 }
+
+	 /** Create a copy of this element wrapper.
+	  * @return A new <strong>ElementWrapper</strong> based on the same element as this one.
+	  */
+	 public ElementWrapper copy() {
+		  Element element_copy = (Element) element.cloneNode(true);
+		  return new ElementWrapper(element_copy);
+	 }
+	 /** Compare two element wrappers for ordering.
+	  * @param object An <strong>Object</strong> which is most likely another element wrapper to be compared with.
+	  * @return An <i>int</i> indicating order, -1, 0, 1 if this element wrapper is less than, equal to or greater than the given object.
+	  */
+	 public int compareTo(Object object) {
+		  return toString().compareTo(object.toString());
+	 }
+	 /** Decrement the number of occurances of this metadata element. 
+	  * @see org.greenstone.gatherer.msm.MSMUtils
+	  */
+	 public void dec() {
+		  MSMUtils.setOccurance(element, -1);
+	 }
+	 /** Test if two ElementWrappers are equal.
+	  * @param object The <strong>Object</strong> to test against.
+	  */
+	 public boolean equals(Object object) {
+		  if(object instanceof ElementWrapper) {
+				String our_full_name = MSMUtils.getFullName(element);
+				String their_full_name = MSMUtils.getFullName(((ElementWrapper)object).getElement());
+				return our_full_name.equals(their_full_name);
+		  }
+		  return toString().equals(object.toString());
+	 }
+	 /** Retrieve the attributes associated with the element this element wrapper is built around.
+	  * @return A <strong>TreeSet</strong> of the attributes.
+	  * @see org.greenstone.gatherer.msm.MSMUtils
+	  */
+	 public TreeSet getAttributes() {
+		  return MSMUtils.getAttributes(element);
+	 }
+	 /** Retrieve the element this is wrapped around.
+	  * @return A DOM <strong>Element</strong> which represents a metadata element.
+	  */
+	 public Element getElement() {
+		  return element;
+	 }
+	 /** Retrieve the identity of this element (not necessary the same as this elements name). Identity is language and locale dependant.
+	  * @return The identity as a <strong>String</strong>.
+	  * @see org.greenstone.gatherer.msm.MSMUtils
+	  */
+	 public String getIdentity() {
+		  return MSMUtils.getIdentifier(element);
+	 }
+	 /** Retrieve the name of this element. Name is unique.
+	  * @return The name as a <strong>String</strong>.
+	  * @see org.greenstone.gatherer.msm.MSMUtils
+	  */
+	 public String getName() {
+		  return MSMUtils.getFullName(element);
+	 }
+	 /** Retrieve the namespace prefix for this element wrapper.
+	  * @return A <strong>String</strong> containing the namespace or "" if there is no namespace for this element.
+	  * @see org.greenstone.gatherer.msm.MSMUtils
+	  */
+	 public String getNamespace() {
+		  String name = getName();
+		  int pos;
+		  if((pos = name.indexOf(MSMUtils.NS_SEP)) != -1) {
+				return name.substring(0, pos);
+		  }
+		  else {
+				return "";
+		  }
+	 }
+	 /** Look for the occurances 'field' of the element and return it if found.
+	  * @return An <i>int</i> which matches the number in the occurances attribute of the element, or 0 if no such attribute.
+	  * @see org.greenstone.gatherer.msm.MSMUtils
+	  */
+	 public int getOccurances() {
+		  return MSMUtils.getOccurances(element);
+	 }
+	 /** This method is essentially the same as getDescription() in that it does indeed return this metaelements description. However this method uses the Utility function formatHTMLWidth() to ensure the String can be displayed in a tool-tip window using html markup.
+	  * @return A String containing the HTML formatted versions of definition and content (comment).
+	  * @see org.greenstone.gatherer.msm.MSMUtils
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public String getToolTip() {
+		  // Add HTML formatting
+		  return Utility.formatHTMLWidth(MSMUtils.getDescription(element), 60);
+	 }
+	 /** Increment the number of occurances of this metadata element. 
+	  * @see org.greenstone.gatherer.msm.MSMUtils
+	  */
+	 public void inc() {
+		  MSMUtils.setOccurance(element, 1);
+	 }
+	 public void removeAttribute(String name, String value) {
+		  Element attributes[] = MSMUtils.getAttributeNodesNamed(element, name);
+		  // For each of the attribute nodes which match the requested name...
+		  for(int i = 0; attributes != null && i < attributes.length; i++) {
+				// Retrieve the value for this node...
+				String current = MSMUtils.getValue(attributes[i]);
+				// And if it matches our removal value, remove the attribute node.
+				if(current.equals(value)) {
+					 element.removeChild(attributes[i]);
+					 current = null;
+					 attributes = null;
+					 return;
+				}
+				current = null;
+		  }
+		  // If we get this far then theres no match. Boo-hoo.
+		  attributes = null;
+	 }
+	 /** Set the value of the namespace required flag.
+	  * @param namespace_required The new value as a <i>boolean</i>.
+	  * @see org.greenstone.gatherer.msm.MSMUtils
+	  * @deprecated
+	  */
+	 public void setNamespaceRequired(boolean namespace_required) {
+	 }
+	 public String toString() {
+		  return MSMUtils.getFullIdentifier(element);
+	 }
+}
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/ExistingMetadataLoader.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/ExistingMetadataLoader.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/ExistingMetadataLoader.java	(revision 13666)
@@ -0,0 +1,126 @@
+package org.greenstone.gatherer.msm;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.msm.MetadataParser;
+import org.greenstone.gatherer.util.Utility;
+/** Attempts to locate and import any metadata already attatched to files about to be imported. This entire function is part of a critical file copy and so must be fast and reliable (or at least recover nicely when things go wrong). Futhermore this process must be aware of concerns such as previous greenstone collections having metadata sets that could be immediately imported, or hierarchy files needed to turn indexes into something more meaningful. We also must allow for the extensibility of this class to include custom metadata objects such as MARK records etc. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class ExistingMetadataLoader {
+	 /** A list of currently loaded metadata parsers. */
+	 private ArrayList parsers = null;
+	 /** Constructor.
+	  * @see org.greenstone.gatherer.msm.MetadataParser
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public ExistingMetadataLoader() {
+		  this.parsers = new ArrayList();
+		  ArrayList load_these = new ArrayList();
+		  // Find any metadata parsers found in parsers directory
+		  File file = new File(Utility.BASE_DIR + "classes" + File.separator + "org" + File.separator + "greenstone" + File.separator + "gatherer" + File.separator + "msm" + File.separator + "parsers");
+		  File children[] = file.listFiles();
+		  for(int i = 0; children != null && i < children.length; i++) {
+				String name = children[i].getName();
+				if(name.endsWith(".class") && name.indexOf("$") == -1) {
+					 name = name.substring(0, name.length() - 6);
+					 load_these.add("org.greenstone.gatherer.msm.parsers." + name);
+					 Gatherer.println("Loaded metadata parser: " + name);
+				}
+				name = null;
+		  }
+		  children = null;
+		  file = null;
+		  // Find any metadata parsers found in the jar file (if present)
+		  File jar_file = new File("Gatherer.jar");
+		  if(jar_file.exists()) {
+				try {
+					 JarFile jar = new JarFile(jar_file);
+					 for(Enumeration entries = jar.entries(); entries.hasMoreElements(); ) {
+						  String name = entries.nextElement().toString();
+						  if(name.startsWith("org/greenstone/gatherer/msm/parsers/") && name.endsWith(".class") && name.indexOf("$") == -1) {
+								name = name.substring(0, name.length() - 6);
+								name = name.replace('/', '.');
+								if(!load_these.contains(name)) {
+									 load_these.add(name);
+									 Gatherer.println("Loaded metadata parser: " + name);
+								}
+						  }						
+						  name = null;
+					 }
+					 jar = null;
+				}
+				catch (Exception error) {
+					 error.printStackTrace();
+				}
+		  }
+		  jar_file = null;
+		  // Load create instances of the parsers found.
+		  for(int i = 0; i < load_these.size(); i++) {
+				try {
+					 String parser_name = (String) load_these.get(i);
+					 Class custom_class = Class.forName((String)load_these.get(i));
+					 MetadataParser custom_parser = (MetadataParser)custom_class.newInstance();
+					 parsers.add(custom_parser);
+					 custom_parser = null;
+					 custom_class = null;
+					 parser_name = null;
+				}
+				catch (Exception error) {
+					 error.printStackTrace();
+				}
+		  }
+	 }
+	 /** Locates and assigns metadata for the given file by sequentially applying all active metadata parsers. */
+	 public boolean searchForMetadata(FileNode destination, FileNode source, boolean folder_level, boolean dummy_run) {
+		  boolean dialog_cancelled = false;
+		  int size = parsers.size();
+		  for(int i = 0; !dialog_cancelled && i < size; i++) {
+				MetadataParser parser = (MetadataParser) parsers.get(i);
+				dialog_cancelled = parser.process(destination, source, folder_level, dummy_run);
+				parser = null;
+		  }
+		  return dialog_cancelled;
+	 }
+}
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/ExportMDSPrompt.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/ExportMDSPrompt.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/ExportMDSPrompt.java	(revision 13666)
@@ -0,0 +1,273 @@
+package org.greenstone.gatherer.msm;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import javax.swing.*;
+import javax.swing.filechooser.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.msm.MetadataSet;
+import org.greenstone.gatherer.msm.MetadataSetManager;
+import org.greenstone.gatherer.util.Utility;
+/** A GUI component for allowing the user to export a metadata set, based on certain conditions, and to a certain file (not necessarily a .mds file). 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+final public class ExportMDSPrompt
+	 extends JDialog 
+	 implements ActionListener, KeyListener {
+	 /** Is this an export prompt or an import one? */
+	 private boolean export;
+	 /** The file we wish to export the metadata set to. */
+	 private File file = null;
+	 /** The action the user has chosen from the dialog (either -1, if cancelled, or EXPORT). */
+	 private int action = -1;
+	 /** The button used to browse the local file system. */
+	 private JButton browse_button = null;
+	 /** Used to cancel the dialog. */
+	 private JButton cancel_button = null;
+	 /** Used to initiate the export, then dispose of the dialog. */
+	 private JButton export_button = null;
+	 /** The metadata sets available for export. */
+	 private JComboBox sets = null;
+	 /** The destination file name as a string. */
+	 private JTextField file_name = null;
+	 /** Ths button that, if selected, signifies you wish to export the metadata set with all values. */
+	 private JToggleButton all_values = null;
+	 /** The button that, if selected, signifies you wish to export the metadata set without any values (ie no mdv files). */
+	 private JToggleButton no_values = null;
+	 /** The button that, if selected, signifies you wish to export the metadata set with only those values that are subject nodes in the hierarchy. */
+	 private JToggleButton structure_only = null;
+	 /** A reference to the metadata set manager. */
+	 private MetadataSetManager manager;
+	 /** The default size for this dialog window. */
+	 final static public Dimension EXPORT_SIZE = new Dimension(500,220);
+/** The default size for this dialog window. */
+	 final static public Dimension IMPORT_SIZE = new Dimension(500,120);
+	 /** The default export action (there are several depending on how much information you wish to export). */
+	 final static public int EXPORT = 0;
+	 /** Constructor.
+	  * @param manager A reference to the <strong>MetadataSetManager</strong>.
+	  * @see org.greenstone.gatherer.Configuration
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public ExportMDSPrompt(MetadataSetManager manager, boolean export) {
+		  super();
+		  this.export = export;
+		  // Creation
+		  setModal(true);
+		  if(export) {
+				setSize(EXPORT_SIZE);
+				setTitle(get("Export_Title"));
+		  }
+		  else {
+				setSize(IMPORT_SIZE);
+				setTitle(get("Import_Title"));
+		  }
+		  JPanel content_pane = (JPanel) getContentPane();
+		  JPanel control_pane = new JPanel();
+		  JLabel set_label = new JLabel(get("Export_Set"));
+		  sets = new JComboBox(manager.getSets());
+		  JLabel condition_label = new JLabel(get("Export_Conditions"));
+		  JPanel condition_pane = new JPanel();
+		  ButtonGroup condition_group = new ButtonGroup();
+		  all_values = new JToggleButton(get("Export_All_Values"));
+		  condition_group.add(all_values);
+		  no_values = new JToggleButton(get("Export_No_Values"));
+		  condition_group.add(no_values);
+		  structure_only = new JToggleButton(get("Export_Subjects_Only"));
+		  condition_group.add(structure_only);
+		  all_values.setSelected(true);
+		  JLabel file_label = new JLabel(get("Export_File"));
+		  JPanel file_pane = new JPanel();
+		  file_name = new JTextField(Utility.METADATA_DIR);
+		  browse_button = new JButton(get("General.Browse"));
+		  JPanel button_pane = new JPanel();
+		  if(export) {
+				export_button = new JButton(get("File_Export"));
+				export_button.setEnabled(false);
+		  }
+		  else {
+				export_button = new JButton(get("File_Import"));
+				export_button.setEnabled(true);
+		  }
+		  cancel_button = new JButton(get("General.Cancel"));
+		  // Listeners
+		  browse_button.addActionListener(this);
+		  cancel_button.addActionListener(this);
+		  export_button.addActionListener(this);
+		  file_name.addKeyListener(this);
+		  // Layout
+		  condition_pane.setLayout(new GridLayout(1,3));
+		  condition_pane.add(all_values);
+		  condition_pane.add(structure_only);
+		  condition_pane.add(no_values);
+
+		  file_pane.setLayout(new BorderLayout());
+		  file_pane.add(file_name, BorderLayout.CENTER);
+		  file_pane.add(browse_button, BorderLayout.EAST);
+
+		  if(export) {
+				control_pane.setLayout(new GridLayout(6, 1));
+				control_pane.add(set_label);
+				control_pane.add(sets);
+				control_pane.add(condition_label);
+				control_pane.add(condition_pane);
+				control_pane.add(file_label);
+				control_pane.add(file_pane);
+		  }
+		  else {
+				control_pane.setLayout(new GridLayout(2,1));
+				control_pane.add(condition_label);
+				control_pane.add(condition_pane);
+		  }
+		  
+		  button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+		  button_pane.setLayout(new GridLayout(1,2));
+		  button_pane.add(export_button);
+		  button_pane.add(cancel_button);
+
+		  content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		  content_pane.setLayout(new BorderLayout());
+		  content_pane.add(control_pane, BorderLayout.CENTER);
+		  content_pane.add(button_pane, BorderLayout.SOUTH);
+		  // Display
+		  Dimension screen_size = Gatherer.config.screen_size;
+		  setLocation((screen_size.width - getSize().width) / 2, (screen_size.height - getSize().height) / 2);
+	 }
+	 /** Whenever one of the buttons in the dialog is actioned this method is called to trigger the appropriate effects.
+	  * @param event An <strong>ActionEvent</strong> containing information about the action performed.
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.msm.MDSFileFilter
+	  * @see org.greenstone.gatherer.util.Utility
+	  */
+	 public void actionPerformed(ActionEvent event) {
+		  if(event.getSource() == export_button) {
+				action = EXPORT;
+				dispose();
+		  }
+		  else if(event.getSource() == cancel_button) {
+				action = -1;
+				dispose();
+		  }
+		  else {
+				JFileChooser chooser = new JFileChooser(new File(Utility.METADATA_DIR));
+				javax.swing.filechooser.FileFilter filter = new MDSFileFilter();
+				chooser.setApproveButtonText(get("General.OK"));
+				chooser.setFileFilter(filter);
+				int returnVal = chooser.showSaveDialog(Gatherer.g_man);
+				if(returnVal == JFileChooser.APPROVE_OPTION) {
+					 file = chooser.getSelectedFile();
+					 if(file.getName().indexOf(".") == -1) {
+						  file = new File(file.getName() + ".mds");
+					 }
+					 file_name.setText(file.getAbsolutePath());
+					 export_button.setEnabled(true);
+				}
+		  }
+	 }
+	 /** Show the prompt and get the user input. 
+	  * @return An <i>int</i> specifying what action the user has choosen.
+	  */
+	 public int display() {
+		  show();
+		  return action;
+	 }
+	 /** Get the current value of condition.
+	  * @return The value as an <i>int</i>.
+	  * @see org.greenstone.gatherer.msm.MetadataSet
+	  */
+	 public int getSelectedCondition() {
+		  if(all_values.isSelected()) {
+				return MetadataSet.ALL_VALUES;
+		  }
+		  else if(no_values.isSelected()) {
+				return MetadataSet.NO_VALUES;
+		  }
+		  else {
+				return MetadataSet.SUBJECTS_ONLY;
+		  }
+	 }
+	 /** Get the current value of file.
+	  * @return The value as a <strong>File</strong>.
+	  */
+	 public File getSelectedFile() {
+		  return file;
+	 }
+	 /** Get the current value of set.
+	  * @return The value as a <strong>MetadataSet</strong>.
+	  */
+	 public MetadataSet getSelectedSet() {
+		  return (MetadataSet) sets.getSelectedItem();
+	 }
+	 /** Any implementation of KeyListener must include this method so that we can be informed when a key has been pressed. In this case we ignore it.
+	  * @param event A <strong>KeyEvent</strong> containing information about the key pressed.
+	  */
+	 public void keyPressed(KeyEvent event) {
+	 }
+	 /** Any implementation of KeyListener must include this method so that we can be informed once a key has been released. This is the earliest the VK code becomes stable and usable, so we will check if the file named in file_name can be written to and if so enable the export button.
+	  * @param event A <strong>KeyEvent</strong> containing information about the key typed.
+	  */
+	 public void keyReleased(KeyEvent event) {
+		  String pos_file = file_name.getText();
+		  if(pos_file.indexOf(".") != -1) {
+				file = new File(file_name.getText());
+				if(file.canWrite() || !file.exists()) {
+					 export_button.setEnabled(true);
+				}
+				else if(export) {
+					 export_button.setEnabled(false);
+				}
+		  }
+	 }
+	 /** Any implementation of KeyListener must include this method so that we can be informed when a key has been typed. In this case we ignore it.
+	  * @param event A <strong>KeyEvent</strong> containing information about the key typed.
+	  */
+	 public void keyTyped(KeyEvent event) {
+	 }
+
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+	 private String get(String key, String[] args) {
+		  if(key.indexOf(".") == -1) {
+				key = "MSMPrompt." + key;
+		  }
+		  return Gatherer.dictionary.get(key, args);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/GDMDocument.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/GDMDocument.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/GDMDocument.java	(revision 13666)
@@ -0,0 +1,403 @@
+package org.greenstone.gatherer.msm;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.io.*;
+import java.util.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.msm.GDMManager;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.greenstone.gatherer.util.HashMap3D;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.valuetree.GValueModel;
+import org.greenstone.gatherer.valuetree.GValueNode;
+import org.w3c.dom.*;
+/** This class wraps around a DOM Document providing methods for accessing the data within. In this case the DOM represents a Greenstone Directory metadata file. It provides the necessary functionality to create a new metadata.xml file. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3b
+ */
+public class GDMDocument {
+	 /** Record if the document this object is based on is up to date. */
+	 private boolean up_to_date = true;
+	 /** The document this class sources its data from. */
+	 private Document base_document;
+	 static final private String ACCUMULATE = "accumulate";
+	 /** The pattern to match when searching for directory level assignments. */
+	 static final private String DIRECTORY_FILENAME = ".*";
+	 static final private String DESCRIPTION_ELEMENT = "Description";
+	 static final private String FILENAME_ELEMENT = "FileName";
+	 static final private String FILESET_ELEMENT = "FileSet";
+	 static final private String HVALUE_ATTRIBUTE = "hvalue";
+	 static final private String METADATA_ELEMENT = "Metadata";
+	 static final private String MODE_ATTRIBUTE = "mode";
+	 static final private String NAME_ATTRIBUTE = "name";
+	 static final private String OVERWRITE = "overwrite";
+	 /** Constructor which creates a brand new metadata.xml document. */
+	 public GDMDocument() {
+		  // Create new document. We do this by loading a copy of the template. */
+		  this.base_document = Utility.parse(Utility.GREENSTONEDIRECTORYMETADATA_TEMPLATE, true);
+	 }
+	 /** Constructor which parses an existing metadata.xml document. */
+	 public GDMDocument(File file) {
+		  try {
+				this.base_document = Utility.parse(file.getAbsolutePath(), false);
+		  }
+		  catch (Exception error) {
+				// Poorly formed, or completely invalid metadata.xml file!
+		  }
+	 }
+	 /** Constructor which wraps around an existing metadata.xml document. */
+	 public GDMDocument(Document base_document) {
+		  this.base_document = base_document;
+	 }
+	 /** Add this metadata to the named file. */
+	 public void addMetadata(String filename, Metadata metadata) {
+		  ///ystem.err.println("Add '" + metadata + "' to " + (filename != null ? filename : "directory."));
+		  try {
+				// Retrieve the document element.
+				Element directorymetadata_element = base_document.getDocumentElement();
+				// Iterate through the filesets looking for one that matches the given filename.
+				Element fileset_element = null;
+				NodeList fileset_elements = directorymetadata_element.getElementsByTagName(FILESET_ELEMENT);
+				for(int i = 0; i < fileset_elements.getLength(); i++) {
+					 fileset_element = (Element) fileset_elements.item(i);
+					 NodeList filename_elements = fileset_element.getElementsByTagName(FILENAME_ELEMENT);
+					 boolean found = false;
+					 for(int j = 0; !found && j < filename_elements.getLength(); j++) {
+						  Element filename_element = (Element) filename_elements.item(j);
+						  String filename_pattern = MSMUtils.getValue(filename_element);
+						  // Have we found a match. If so break out of for loop.
+						  if(filename != null && filename.matches(filename_pattern) && !filename_pattern.equals(DIRECTORY_FILENAME)) {
+								///ystem.err.println("Adding to file!");
+								found = true;
+						  }
+						  else if(filename == null && filename_pattern.equals(DIRECTORY_FILENAME)) {
+								///ystem.err.println("Adding to folder!");
+								///ystem.err.println("filename_pattern = '" + filename_pattern + "'");
+								found = true;
+						  }
+						  // No match. On to the next one.
+						  else {
+								fileset_element = null;
+						  }
+						  filename_pattern = null;
+						  filename_element = null;
+					 }
+				}
+				fileset_elements = null;
+				// If we still haven't found an existing fileset, then its time to create one.
+				if(fileset_element == null) {
+					 fileset_element = base_document.createElement(FILESET_ELEMENT);
+					 Element filename_element = base_document.createElement(FILENAME_ELEMENT);
+					 Element description_element = base_document.createElement(DESCRIPTION_ELEMENT);
+					 fileset_element.appendChild(filename_element);
+					 fileset_element.appendChild(description_element);
+					 Text filename_text = null;
+					 // If the filename is null then we add a directory metadata set as directorymetadata_element's first child
+					 if(filename == null) {
+						  filename_text = base_document.createTextNode(DIRECTORY_FILENAME);
+						  if(directorymetadata_element.hasChildNodes()) {
+								directorymetadata_element.insertBefore(fileset_element, directorymetadata_element.getFirstChild());
+						  }
+						  else {
+								directorymetadata_element.appendChild(fileset_element);
+						  }
+					 }
+					 // Otherwise we just append the new fileset to directorymetadata_element's children.
+					 else {
+						  filename_text = base_document.createTextNode(filename);
+						  directorymetadata_element.appendChild(fileset_element);
+					 }
+					 filename_element.appendChild(filename_text);
+					 filename_text = null;
+					 description_element = null;
+					 filename_element = null;
+				}
+				// Now, finally, we can add the metadata.
+				Element metadata_element = base_document.createElement(METADATA_ELEMENT);
+				metadata_element.setAttribute(NAME_ATTRIBUTE, metadata.getElement().getName());
+				if(metadata.accumulates()) { //mode.equals(ACCUMULATE)) {
+					 metadata_element.setAttribute(MODE_ATTRIBUTE, ACCUMULATE);
+				}
+				// As we can't possibly store all the metadata in memory, nor can we ensure that the indexes written to file remain the same until the new time we look at this file, and to avoid having to open a rewrite every collection document whenever any value tree changes, I'm adding a new attribute called hvalue which indicates the hierarchy value path as a '\' separated string.
+				GValueModel model = Gatherer.c_man.getCollection().msm.getValueTree(metadata.getElement());
+				if(model != null && model.isHierarchy()) {
+					 metadata_element.setAttribute(HVALUE_ATTRIBUTE, metadata.getValueNode().getFullPath());
+				}
+				metadata_element.appendChild(base_document.createTextNode(metadata.getAbsoluteValue()));
+				// Retrieve the first description element for this fileset (there should only be one, but I'll play it safe).
+				NodeList description_elements = fileset_element.getElementsByTagName("Description");
+				Element description_element = (Element) description_elements.item(0);
+				description_element.appendChild(metadata_element);
+				description_element = null;
+				metadata_element = null;
+				//mode = null;
+				fileset_element = null;
+				directorymetadata_element = null;
+				up_to_date = false;
+		  }
+		  catch (Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+	 }
+
+	 /** Retrieve the document this class is wrapping. */
+	 public Document getDocument() {
+		  return base_document;
+	 }
+	 /** Get all of the metadata, including directory level, associated with this file. */
+	 public ArrayList getMetadata(String filename, boolean remove, ArrayList metadatum_so_far, File file) {
+		  return getMetadata(filename, remove, metadatum_so_far, file, false);
+	 }
+	 /** Retrieve the metadata associated with the given filename. Keep track of what metadata should be overwritten and what should be accumulated. Also make note of the source file, and remove the metadata if required. Finally if purge is set retrieve every piece of metadata in this file. */
+	 public ArrayList getMetadata(String filename, boolean remove, ArrayList metadatum_so_far, File file, boolean purge) {
+		  ///ystem.err.println("Get metadata for " + filename);
+		  ArrayList metadatum = null;
+		  if(metadatum_so_far == null) {
+				metadatum = new ArrayList();
+		  }
+		  else {
+				metadatum = metadatum_so_far;
+		  }
+		  try {
+				// Retrieve the document element.
+				Element directorymetadata_element = base_document.getDocumentElement();
+				// Iterate through the filesets, checking the FileName child element against 	the target file's name using regular expression matching.
+				NodeList fileset_elements = directorymetadata_element.getElementsByTagName(FILESET_ELEMENT);
+				for(int i = 0; i < fileset_elements.getLength(); i++) {
+					 Element fileset_element = (Element) fileset_elements.item(i);
+					 NodeList filename_elements = fileset_element.getElementsByTagName(FILENAME_ELEMENT);
+					 for(int j = 0; j < filename_elements.getLength(); j++) {
+						  Element filename_element = (Element) filename_elements.item(j);
+						  String filename_text = MSMUtils.getValue(filename_element);
+						  if((filename != null && filename.matches(filename_text)) || filename_text.equals(DIRECTORY_FILENAME) || purge) {
+								// If they match add all of the metadata found in the Description child element, remembering to abide by desired mode (accumulate vs. overwrite).
+								NodeList description_elements = fileset_element.getElementsByTagName(DESCRIPTION_ELEMENT);
+								for(int k = 0; k < description_elements.getLength(); k++) {
+									 Element description_element = (Element) description_elements.item(k);
+									 NodeList metadata_elements = description_element.getElementsByTagName(METADATA_ELEMENT);
+									 for(int l = 0; l < metadata_elements.getLength(); l++) {
+										  Element metadata_element = (Element) metadata_elements.item(l);
+										  String raw_element = metadata_element.getAttribute(NAME_ATTRIBUTE);
+										  //String language = metadata_element.getAttribute("language");
+										  String mode = metadata_element.getAttribute(MODE_ATTRIBUTE);
+										  String raw_value = metadata_element.getAttribute(HVALUE_ATTRIBUTE);
+										  if(raw_value == null || raw_value.length() == 0) {
+												raw_value = MSMUtils.getValue(metadata_element);
+										  }
+										  // Using the element string and value, retrieve a matching Metadata object from the cache
+										  Metadata metadata = null;
+										  // If this element has hierarchy values then we must ensure the raw value is a full path, not an index.
+										  if(GDMManager.metadata_cache.contains(raw_element, raw_value)) {
+												///ystem.err.println("HIT! Retrieve metadata from cache: " + raw_element + " -> " + raw_value + "\n");
+												metadata = (Metadata) GDMManager.metadata_cache.get(raw_element, raw_value);
+										  }
+										  else {
+												ElementWrapper element = Gatherer.c_man.getCollection().msm.getElement(raw_element);
+												GValueNode value = Metadata.getDefaultValueNode(element, raw_value);
+												///ystem.err.println("Miss. Create new metadata: " + raw_element + " -> " + raw_value + "\n");
+												metadata = new Metadata(element, value);
+												GDMManager.metadata_cache.put(raw_element, raw_value, metadata);
+												///ystem.err.println("Added metadata to cache: " + raw_element + " -> " + raw_value + "\n");
+												value = null;
+												element = null;
+										  }
+										  // We determine whether this metadata is file or folder level
+										  if(filename != null) {
+												///ystem.err.println("Filename      = " + filename);
+												///ystem.err.println("filename_text = " + filename_text); 
+												// If can only be file level if there is no folder path details in filename and if the filename matched the filename text node (it may have matched .* instead)!
+												if(filename.indexOf(File.separator) == -1 && filename.equals(filename_text)) {
+													 metadata.setFileLevel(true);
+													 ///ystem.err.println("File level!!!");
+												}
+												else {
+													 metadata.setFileLevel(false);
+													 ///ystem.err.println("Inherited!!!");
+												}
+										  }
+										  else {
+												///ystem.err.println("Filename is null therefore this is file level metadata.");
+												metadata.setFileLevel(true);
+										  }
+										  metadata.setFile(file);
+
+										  // If mode is overwrite, then remove any previous values for this metadata element.
+										  if(mode.equals("accumulate")) {
+												metadata.setAccumulate(true);
+										  }
+										  else {
+												metadata.setAccumulate(false);
+												///ystem.err.println("Metadata overwrites: " + metadata);
+												for(int m = metadatum.size() - 1; m >= 0; m--) {
+													 Metadata old_metadata = (Metadata) metadatum.get(m);
+													 if(old_metadata.getElement().equals(metadata.getElement())) {
+														  metadatum.remove(m);
+														  ///ystem.err.println("Removing overridden metadata: " + old_metadata);
+													 }
+													 old_metadata = null;
+												}
+										  }
+										  mode = null;
+
+										  // Add the completed metadata and clean up
+										  ///ystem.err.println("Adding metadata: " + metadata);
+										  metadatum.add(metadata);
+
+										  // Having found our metadata check if the value from the xml matches the one from the gvaluenode. If not update it. This happens whenever hierarchy information is involved (indexes rapidly become obsolete).
+										  // If remove was set, remove it. We can only remove pure file level metadata, or folder level iff we were asked for folder level.
+										  if(remove && ((filename != null && filename.matches(filename_text) && !filename_text.equals(DIRECTORY_FILENAME)) || (filename == null && filename_text.equals(DIRECTORY_FILENAME)))) {
+												///ystem.err.println("Removing " + metadata + " from " + file);
+												description_element.removeChild(metadata_element);
+												// Remove the description element if empty.
+												if(!description_element.hasChildNodes()) {
+													 fileset_element.removeChild(description_element);
+												}
+										  }
+										  else {
+										      String current_value = metadata.getAbsoluteValue();
+										      if(!raw_value.equals(current_value)) {
+												    // Remove old text
+												    while(metadata_element.hasChildNodes()) {
+													     metadata_element.removeChild(metadata_element.getFirstChild());
+												    }
+												    // Add new.
+												    metadata_element.appendChild(base_document.createTextNode(current_value));
+										      }
+                                }
+
+										  metadata = null;
+										  raw_value = null;
+										  raw_element = null;
+										  metadata_element = null;
+									 }
+									 metadata_elements = null;
+									 description_element = null;
+								}
+								description_elements = null;
+						  }
+						  filename_text = null;
+						  filename_element = null;
+					 }
+					 // If the file set no longer has any description entries, remove it entirely
+					 NodeList description_elements = fileset_element.getElementsByTagName(DESCRIPTION_ELEMENT);
+					 if(description_elements.getLength() == 0) {
+						  directorymetadata_element.removeChild(fileset_element);
+					 }
+					 description_elements = null;
+					 filename_elements = null;
+					 fileset_element = null;
+				}
+				fileset_elements = null;
+				directorymetadata_element = null;
+		  }
+		  catch (Exception error) {
+				Gatherer.self.printStackTrace(error);
+		  }
+		  ///ystem.err.println("Found " + metadatum.size() + " pieces of metadata.");
+		  return metadatum;
+	 }
+
+	 /** Determine if this document has been saved recently, and thus xml file version is up to date. */
+	 public boolean isUpToDate() {
+		  return false;
+	 }
+
+	 /** Determine is this is a valid Greenstone Directory Metadata file. It may of course just be some xml file with the name metadata.xml. */
+	 public boolean isValid() {
+		  // Just determine if the doctype is GreenstoneDirectoryMetadata and root node is called DirectoryMetadata.
+		  String doctype_name = base_document.getDoctype().getName();
+		  String root_name = base_document.getDocumentElement().getTagName();
+		  return ((doctype_name.equals("GreenstoneDirectoryMetadata") && root_name.equals("GreenstoneDirectoryMetadata")) || (doctype_name.equals("DirectoryMetadata") && root_name.equals("DirectoryMetadata")));
+	 }
+	 /** Remove the given directory level metadata from this document. All directory level metadata is available under the FileSet with filename '.*' */
+	 public void removeMetadata(String filename, Metadata metadata) {
+		  try {
+				// Retrieve the document element.
+				Element directorymetadata_element = base_document.getDocumentElement();
+				// Iterate through the filesets looking for the directory level one.
+				NodeList fileset_elements = directorymetadata_element.getElementsByTagName(FILESET_ELEMENT);
+				for(int i = 0; i < fileset_elements.getLength(); i++) {
+					 Element fileset_element = (Element) fileset_elements.item(i);
+					 NodeList filename_elements = fileset_element.getElementsByTagName(FILENAME_ELEMENT);
+					 for(int j = 0; j < filename_elements.getLength(); j++) {
+						  Element filename_element = (Element) filename_elements.item(j);
+						  String filename_text = MSMUtils.getValue(filename_element);
+						  if((filename != null && filename.matches(filename_text)) || filename_text.equals(DIRECTORY_FILENAME)) {
+								// Retrieve the Metadata Element for this fileset, and iterate through them looking for the one which we are to remove.
+								NodeList description_elements = fileset_element.getElementsByTagName("Description");
+								for(int k = 0; k < description_elements.getLength(); k++) {
+									 Element description_element = (Element) description_elements.item(k);
+									 NodeList metadata_elements = description_element.getElementsByTagName("Metadata");
+									 for(int l = 0; l < metadata_elements.getLength(); l++) {		
+										  Element metadata_element = (Element) metadata_elements.item(l);
+										  String element = metadata_element.getAttribute("name");
+										  String value = MSMUtils.getValue(metadata_element);
+										  // See if this is the metadata we wish to remove
+										  if(element.equals(metadata.getElement().getName()) && value.equals(metadata.getAbsoluteValue())) {
+										  // Remove it
+												description_element.removeChild(metadata_element);
+										  }
+										  value = null;
+										  element = null;
+										  metadata_element = null;
+									 }
+									 metadata_elements = null;
+									 description_element = null;
+								}
+								description_elements = null;
+						  }
+						  filename_text = null;
+						  filename_element = null;
+					 }
+					 filename_elements = null;
+					 fileset_element = null;
+				}
+				fileset_elements = null;
+				directorymetadata_element = null;
+				up_to_date = false;
+		  }
+		  catch (Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+	 }	
+
+ 	 /** Change the up to date flag. */
+	 public void setUpToDate(boolean up_to_date) {
+		  this.up_to_date = up_to_date;
+	 }
+
+	 /** Decode a string that was previously made Perl safe. */
+	 private String decode(String safe) {
+		  return safe.replaceAll("\\\\.",".");
+	 }
+
+	 /** Encodes unsafe filename characters (such as the . before the file extension) into Perl safe ones. */
+	 private String encode(String dangerous) {
+		  return dangerous.replaceAll("\\.", "\\\\.");
+	 }
+}
+
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/GDMDocument.new
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/GDMDocument.new	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/GDMDocument.new	(revision 13666)
@@ -0,0 +1,283 @@
+package org.greenstone.gatherer.msm;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.io.*;
+import java.util.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.GDMManager;
+import org.greenstone.gatherer.msm.Metadata;
+import org.greenstone.gatherer.msm.MetadataSetManager;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.valuetree.GValueModel;
+import org.greenstone.gatherer.valuetree.GValueNode;
+import org.w3c.dom.*;
+/** This class wraps around a DOM Document providing methods for accessing the data within. In this case the DOM represents a Greenstone Directory metadata file. It provides the necessary functionality to create a new metadata.xml file. */
+public class GDMDocument {
+	 /** The document this class sources its data from. */
+	 private Document document;
+	 /** The pattern to match when searching for directory level assignments. */
+	 static final private String DIRECTORY_FILENAME = ".*";
+	 /** @deprecated */
+	 public GDMDocument(Gatherer gatherer, File file) {}
+	 /** @deprecated */
+	 public GDMDocument(Gatherer gatherer, File file, Document document) {}
+	 /** Constructor which creates a brand new metadata.xml document. */
+	 public GDMDocument() {
+		  // Create new document. We do this by loading a copy of the template. */
+		  this.document = Utility.parse(Utility.GREENSTONEDIRECTORYMETADATA_TEMPLATE, true);
+	 }
+	 /** Constructor which parses an existing metadata.xml document. */
+	 public GDMDocument(File file) {
+		  try {
+				this.document = Utility.parse(file.getAbsolutePath(), false);
+		  }
+		  catch (Exception error) {
+				// Poorly formed, or completely invalid metadata.xml file!
+		  }
+	 }
+	 /** Constructor which wraps around an existing metadata.xml document. */
+	 public GDMDocument(Document document) {
+		  this.document = document;
+	 }
+	 /** Add this piece of directory level metadata. */
+	 public void addDirectoryMetadata(Metadata metadata) {
+		  addMetadata(DIRECTORY_FILENAME, metadata);
+	 }
+	 /** Add a new piece of metadata to this document, for the given filename. */
+	 public void addMetadata(String filename, Metadata metadata) {
+		  try {
+				Element fileset_element = getFileSet(filename);
+				// Retrieve the Metadata Element for this fileset.
+				Element description_element = (Element) MSMUtils.getNodeFromNamed(fileset_element, "Description");
+				// Add the new element.
+				Element metadata_element = document.createElement("Metadata");
+				metadata_element.setAttribute("name", metadata.getElement().getName());
+				// What mode we use depends on whether this is the first metadata assignment of this type. If so we use overwrite to ensure that it overrides any directory level metadata (overwrite is the default mode). If this isn't the first metadata of this type we explicitly set accumulate.
+				if(existsMetadata(description_element, metadata.getElement().toString())) {
+					 metadata_element.setAttribute("mode", "accumulate");
+				}
+				// What actually gets written at the node depends on whether the element above is a hierarchy based one.
+				GValueModel model = MetadataSetManager.self.getValueTree(metadata.getElement());
+				Text metadata_element_value;
+				if(model != null && model.isHierarchy()) {
+					 metadata_element_value = document.createTextNode(model.getHIndex(metadata.getAbsoluteValue()));
+				}
+				else {
+					 metadata_element_value = document.createTextNode(metadata.getValue());
+				}
+				metadata_element.appendChild(metadata_element_value);
+		  }
+		  catch (Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+	 }
+
+	 /** @deprecated */
+	 public void destroy() {}
+
+	 /** Retrieve the document this class is wrapping. */
+	 public Document getDocument() {
+		  return document;
+	 }
+
+	 /** @deprecated */
+	 public File getFile() { 
+		  return null;
+	 }
+	 
+	 /** Get all of the metadata, including directory level, associated with this file. If remove is true remove any metadata we find. */
+	 public ArrayList getMetadata(String filename, boolean remove) {
+		Metadata[] metadatum = null;
+		try {
+			// Retrieve the document element.
+			Element directorymetadata_element = document.getDocumentElement();
+			// Iterate through the filesets, checking the FileName child element against 	the target file's name using regular expression matching.
+			NodeList filesets = directorymetadata_element.getElementsByTagName("FileSet");
+			for(int i = 0; i < filesets.getLength(); i++) {
+				Element fileset_element = (Element) filesets.item(i);
+				Element filename_element = (Element) MSMUtils.getNodeFromNamed(fileset_element, "FileName");
+				String current_filename = MSMUtils.getValue(filename_element);
+				if((filename != null && current_filename.matches(filename)) || current_filename.equals(DIRECTORY_FILENAME)) {
+					// If they match add all of the metadata found in the Description child 	element, remembering to abide by desired mode (accumulate vs. overwrite).
+					Element description_element = (Element)MSMUtils.getNodeFromNamed(fileset_element, "Description");
+					NodeList metadatas = description_element.getElementsByTagName("Metadata");
+					for(int j = 0; j < metadatas.getLength(); j++) {
+						Element metadata_element = (Element) metadatas.item(j);
+						String element_str = metadata_element.getAttribute("name");
+						//String language = metadata_element.getAttribute("language");
+						String mode = metadata_element.getAttribute("mode");
+						// If mode is overwrite, then remove any previous values for this metadata element.
+						if(metadatum != null) {
+							for(int k = metadatum.length - 1; k >= 0; k--) {
+								if(metadatum[k].getElement().toString().equals(element_str)) {
+									metadatum = ArrayTools.remove(metadatum, k);
+								}
+							}
+						}
+						// Add the new metadata.
+						String value_str = MSMUtils.getValue(metadata_element);
+						// Using the element string and value, retrieve a matching Metadata object from the cache
+						Metadata metadata = (Metadata) GDMManager.self.metadata_cache.get(element_str, value_str);
+						if(metadata != null) {
+							 // Retrieve the appropriate element and value Elements
+							 ElementWrapper element = MetadataSetManager.self.getElement(element_str);
+							 GValueModel model = MetadataSetManager.self.getValueTree(element);
+							 GValueNode value;
+							 if(model != null) {
+								  value = model.getValue(value_str);
+							 }
+							 else {
+								  value = new GValueNode(element_str, value_str);
+							 }
+							 metadata = new Metadata(element, value);
+							 GDMManager.self.metadata_cache.put(element_str, value_str, metadata);
+						}
+						metadatum = ArrayTools.add(metadatum, metadata);
+					}
+				}
+			}
+		}
+		catch (Exception error) {
+			Gatherer.self.printStackTrace(error);
+		}
+
+		//return metadatum;
+
+		// Change the Metadata[] into an ArrayList
+		ArrayList result = new ArrayList();
+		for(int i = 0; i < metadatum.length; i++) {
+			 result.add(metadatum[i]);
+		}
+		return result;
+	 }
+	 /** Determine is this is a valid Greenstone Directory Metadata file. It may of course just be some xml file with the name metadata.xml. */
+	 public boolean isValid() {
+		  // Just determine if the doctype is GreenstoneDirectoryMetadata and root node is called DirectoryMetadata.
+		  String doctype_name = document.getDoctype().getName();
+		  String root_name = document.getDocumentElement().getTagName();
+		  return (doctype_name.equals("GreenstoneDirectoryMetadata") && root_name.equals("DirectoryMetadata"));
+	 }
+	 /** Remove the given directory level metadata from this document. All directory level metadata is available under the FileSet with filename '.*' */
+	 public void removeDirectoryMetadata(Metadata metadata) {
+		  try {
+				Element fileset_element = getFileSet(DIRECTORY_FILENAME);
+				// Retrieve the Metadata Element for this fileset, and iterate through them looking for the one which we are to remove.
+				Element description_element = (Element) MSMUtils.getNodeFromNamed(fileset_element, "Description");
+				NodeList metadatas = description_element.getElementsByTagName("Metadata");
+				for(int j = 0; j < metadatas.getLength(); j++) {		
+					 Element metadata_element = (Element) metadatas.item(j);
+					 String element = metadata_element.getAttribute("name");
+					 String value = MSMUtils.getValue(metadata_element);
+					 // See if this is the metadata we wish to remove
+					 if(element.equals(metadata.getElement().toString()) && value.equals(metadata.getAbsoluteValue())) {
+						  // Remove it
+						  description_element.removeChild(metadata_element);
+					 }
+				}
+		  }
+		  catch (Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+	 }
+
+	 /** Remove the given metadata from the file specified within this document. */
+	 public void removeMetadata(String filename, Metadata metadata) {
+		
+	 }
+
+	 /** @deprecated */
+	 public void save() {}
+
+	 /** @deprecated */
+	 public void setUpToDate(boolean state) {}
+
+	 /** Retrieves the fileset with the desired filename pattern, or creates it if none is available. */
+	 private Element getFileSet(String pattern) {
+		  Element fileset;
+		  // Retrieve the document element.
+		  Element directorymetadata_element = document.getDocumentElement();
+		  // Iterate through the filesets looking for the directory level one.
+		  NodeList filesets = directorymetadata_element.getElementsByTagName("FileSet");
+		  for(int i = 0; i < filesets.getLength(); i++) {
+				Element fileset_element = (Element) filesets.item(i);
+				Element filename_element = (Element) MSMUtils.getNodeFromNamed(fileset_element, "FileName");
+				String filename = MSMUtils.getValue(filename_element);
+				if(name.matches(pattern)) {
+					 fileset = fileset_element;
+				}
+				filename = null;
+				filename_element = null;
+				fileset_element = null;
+		  }
+		  filesets = null;
+		  // It doesn't already exist. Add our own.
+		  if(fileset == null) {
+				Element filename = document.createElement("FileName");
+				filename.appendChild(document.createTextNode(pattern));
+				Element description = document.createElement("Description");
+				fileset = document.createElement("FileSet");
+				fileset.appendChild(filename);
+				fileset.appendChild(description);
+				if(directorymetadata_element.hasChildNodes()) {
+					 directorymetadata_element.insertBefore(fileset, directorymetadata_element.getFirstChild());
+				}
+				else {
+					 directorymetadata_element.appendChild(fileset);
+				}
+				description = null;
+				filename = null;
+		  }
+		  directorymetadata_element = null;
+		  return fileset;
+	 }
+
+	 /** Determines if there is already a metadata assignment with the given element name within the given description element. */
+	 public boolean existsMetadata(Element description, String element_name) {
+		  boolean result = false;
+		  NodeList metadatas = description.getElementsByTagName("Metadata");
+		  for(int i = 0; !result && i < metadatas.getLength(); i++) {
+				Element metadata = (Element) metadatas.item(i);
+				if(metadata.getAttribute("name").equals(element_name)) {
+					 result = true;
+				}
+		  }
+		  return result;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/GDMManager.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/GDMManager.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/GDMManager.java	(revision 13666)
@@ -0,0 +1,419 @@
+package org.greenstone.gatherer.msm;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.io.*;
+import java.util.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.GDMDocument;
+import org.greenstone.gatherer.msm.GDMParser;
+import org.greenstone.gatherer.msm.Metadata;
+import org.greenstone.gatherer.msm.MSMEvent;
+import org.greenstone.gatherer.msm.MSMListener;
+import org.greenstone.gatherer.util.HashMap3D;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.valuetree.GValueModel;
+import org.greenstone.gatherer.valuetree.GValueNode;
+import org.w3c.dom.*;
+/** This object manages the metadata attached to file records. By storing all of the metadata in one place you garner several advantages. Firstly only one copy of each metadata object is retained, all actual entries are converted to references. Next you can immediately determine what metadata is assigned to an entire directory, thus the metadata.xml files can be built more effeciently (whereas the current 'optimal' method uses recursion through the tree contents). Finally, and perhaps most importantly, it allows for dynamic 'on demand' lookup of metadata. This is especially necessary with large collections, where the raw, unconnected metadata files could range into the tens of megabytes of memory and require hundreds of megabytes to read by in using serialization. Dynamic loading allows you to connect the metadata objects on load, reducing value node paths (possibly of hundreds of characters) down to a single reference pointer! At the very worst this object uses far less memory than the current method, and given that the current method is completely incapable of handling large collections, is necessary. The trade off of course is in time needed to load metadata.xml on demand, the worst possible case being the user selecting the root node of the collection tree of a large collection immediately after opening the collection. The subsequent attempt to build the metadata table will result in the metadata being loaded for every single file. But since this process is sequential and a small cache of metadata.xml files is implemented, and given that the table will actually be build on a separate thread, the wait should not be too arduous.<BR>
+As for the size of the GDMParser cache, I was at first tempted to put around five. However after analysis of cache usage, I determined that no gain occured because of caching (in fact if everythings working as it should there should only ever be one call for a certain metadata.xml).
+*/
+public class GDMManager
+	 extends HashMap 
+	 implements MSMListener {
+	 /** A list of the known metadata instances, thus we only store one of each unique metadata, and reference the rest. */
+	 static public HashMap3D metadata_cache = null;
+	 /** The root file node. */
+	 private TreeNode root = null;
+	 /** The threaded object responsible for loading all of the existing metadata.xml files prior to any save action. This is necessary so that hierarchy indexes within the metadata.xml files stay fresh. */
+	 private GDMLoader gdm_loader = null;
+	 static final private String METADATA_XML = "metadata.xml";
+	 /** Constructor. */
+	 public GDMManager() {
+		  super();
+		  this.metadata_cache = new HashMap3D(Gatherer.c_man.getCollection().msm.getSize());
+		  // Connect
+		  Gatherer.c_man.getCollection().msm.addMSMListener(this);
+		  // Now create and start the synchronous GDM loader.
+		  gdm_loader = new GDMLoader();
+		  gdm_loader.start();
+		  ///atherer.println("New GDMManager created.");
+	 }
+
+	 /** This may seem a little odd but this method doesn't add the given metadata directly, instead calling fireMetadataChanged in MetadataSetManager so as to recursively add metadata if necessary, and to ensure that all listeners who are interested in data change (such as the Metadata Table and Save listeners) can be up to date. */
+	 public void addMetadata(FileNode node, ArrayList metadatum) {
+		  for(int i = 0; i < metadatum.size(); i++) {
+				Metadata metadata = (Metadata) metadatum.get(i);
+				Gatherer.c_man.getCollection().msm.fireMetadataChanged(node, (Metadata)null, metadata);
+		  }
+	 }
+	 /** Destructor necessary for clean exit, subsequent to saving of metadata.xml files. 
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.CollectionManager
+	  * @see org.greenstone.gatherer.msm.GDMParser
+	  * @see org.greenstone.gatherer.msm.MetadataSetManager
+	  */
+	 public void destroy() {
+		  // Destroy all the cached documents.
+		  /*
+		  Iterator iterator = keySet().iterator();
+		  while(iterator.hasNext()) {
+				File file = (File) iterator.next();
+				GDMDocument document = (GDMDocument) get(file);
+				document.destroy(file);
+		  }
+		  */
+		  // Deregister as listener
+		  Gatherer.c_man.getCollection().msm.removeMSMListener(this);
+		  // Deallocate all data members
+		  metadata_cache.clear();
+		  metadata_cache = null;
+		  // Finally clear self
+		  clear();
+		  // Done!
+	 }
+	 /** Method that is called whenever an element within a set is changed or modified. Ensure all cached GDMDocuments are marked as stale.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  */
+	 public void elementChanged(MSMEvent event) {
+		  for(Iterator values = values().iterator(); values.hasNext(); ) {
+				GDMDocument document = (GDMDocument) values.next();
+				document.setUpToDate(false);
+				document = null;
+		  }
+	 }
+	 /** Retrieve the GreenstoneMetadataDocument that is associated with a certain file. If the document is in cache returns it. If the document exists but isn't in cache loads, caches, then returns it. Otherwise it creates a brand new document, caches it, then returns it.
+	  * @see org.greenstone.gatherer.msm.GDMParser
+	  */
+	 public GDMDocument getDocument(File file) {
+		  ///ystem.err.println("Get the GDMDocument for " + file.getAbsolutePath());
+		  GDMDocument metadata_xml = null;
+		  // Determine the name of the target files metadata.xml file.
+		  File metadata_file = null;
+		  if(file.isFile()) {
+				metadata_file = new File(file.getParentFile(), METADATA_XML);
+		  }
+		  else {
+				metadata_file = new File(file, METADATA_XML);
+		  }
+		  // Then try to retrieve it from cache. First we consider the case of a cache hit.
+		  if(containsKey(metadata_file)) {
+				metadata_xml = (GDMDocument) get(metadata_file);
+		  }
+		  else {
+				// Now the two potential cache misses. The first requires us to load an existing metadata.xml
+				if(metadata_file.exists()) {
+					 metadata_xml = new GDMDocument(metadata_file);
+				}
+				// The final case is where no current metadata.xml exists. Create a new one just by creating a new GDMDocument.
+				else {
+					 metadata_xml = new GDMDocument();
+				}
+				put(metadata_file, metadata_xml);
+				//gatherer.debug(null, "[0ms]\tCached " + metadata_file);
+		  }
+		  return metadata_xml;
+	 }
+
+	 /** Recover the metadata associated with a particular file. Note that this call is synchronized, so that all of the data holders don't need to be. */
+	 public synchronized ArrayList getMetadata(File file) {
+		  return getMetadata(file, false);
+	 }
+
+	 public synchronized ArrayList getMetadata(File file, ElementWrapper element) {
+		  ArrayList metadata = getMetadata(file, false);
+		  ArrayList values = new ArrayList();
+		  for(int i = 0; i < metadata.size(); i++) {
+				Metadata data = (Metadata) metadata.get(i);
+				if(element.equals(data.getElement())) {
+					 values.add(data.getValue());
+				}
+		  }
+		  if(values.size() > 0) {
+				Collections.sort(values);
+		  }
+		  return values;
+	 }
+
+	 private ArrayList getMetadata(File file, boolean remove) {
+		  ArrayList metadata = null;
+		  String filename = null;
+		  if(file.isFile()) {
+				filename = file.getName();
+				file = file.getParentFile();
+		  }
+		  GDMDocument document = getDocument(file);
+		  if(document != null) {
+				metadata = document.getMetadata(filename, remove, metadata, file);
+				document = null;
+		  }
+		  return metadata;
+	 }
+
+	 public synchronized ArrayList getAllMetadata(File file) { // boolean remove) {
+		  ///ystem.err.println("getMetadata(" + file.getAbsolutePath() + ")");
+		  ArrayList metadata = null;
+		  // Build up a list of all the metadata xml files we have to check for metadata.
+		  ArrayList search_files = new ArrayList();
+		  String filename = null;
+		  File start_file = file;
+		  if(file.isFile()) {
+				filename = file.getName();
+				start_file = file.getParentFile();
+		  }
+		  File collection_dir = new File(Gatherer.c_man.getCollectionDirectory());
+		  ///ystem.err.println("Collection directory = " + collection_dir.getAbsolutePath());
+		  ///ystem.err.println("Start directory = " + start_file.getAbsolutePath());
+		  while(!start_file.equals(collection_dir)) {
+				///ystem.err.println("Blip!");
+				search_files.add(0, new MetadataXMLFileSearch(start_file, filename));
+				if(filename != null) {
+					 filename = start_file.getName() + "/" + filename;
+				}
+				else {
+					 filename = start_file.getName() + "/";
+				}
+				start_file = start_file.getParentFile();
+				///ystem.err.println("Start directory = " + start_file.getAbsolutePath());
+		  }
+		  // Now search each of these metadata xml for metadata, remembering to accumulate or overwrite as we go along.
+		  for(int i = 0; i < search_files.size(); i++) {
+				MetadataXMLFileSearch a_search = (MetadataXMLFileSearch) search_files.get(i);
+				///ystem.err.println("Search " + a_search.file.getAbsolutePath() + File.separator + "metadata.xml for " + (a_search.filename != null ? a_search.filename : "directory metadata"));
+				// Retrieve the document
+				GDMDocument document = getDocument(a_search.file);
+				if(document != null) {
+					 // There is one piece of slight of hand here. You can never remove metadata during a get all metadata.
+					 metadata = document.getMetadata(a_search.filename, false, metadata, a_search.file);
+					 ///ystem.err.println("Current metadata: " + toString(metadata));
+					 document = null;
+				}
+				a_search = null;
+		  }
+		  start_file = null;
+		  collection_dir = null;
+		  filename = null;
+		  search_files.clear();
+		  search_files = null;
+		  return metadata;
+	 }  
+
+	 public String toString(ArrayList list) {
+		  StringBuffer text = new StringBuffer("(");
+		  for(int i = 0; list != null && i < list.size(); i++) {
+				text.append((list.get(i)).toString());
+				if(i < list.size() - 1) {
+					 text.append(", ");
+				}
+		  }
+		  text.append(")");
+		  return text.toString();		  
+	 }
+
+	 private class MetadataXMLFileSearch {
+		  public File file;
+		  public String filename;
+		  public MetadataXMLFileSearch(File file, String filename) {
+				this.file = file;
+				this.filename = filename;
+		  }
+	 }
+
+	 /** Called whenever the metadata value changes in some way, such as the addition of a new value. This is the only event type we care about, but we care about it a lot. It tells us what metadata to add, remove, etc from the cached metadata.xml files. Note that this method is synchronized so that the data objects don't need to be.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  * @see org.greenstone.gatherer.msm.GDMDocument
+	  * @see org.greenstone.gatherer.msm.Metadata
+	  * @see org.greenstone.gatherer.util.HashMap3D
+	  */
+	 public synchronized void metadataChanged(MSMEvent event) {
+		  File file = event.getFile();
+		  if(file == null) {
+				FileNode record = event.getRecord();
+				file = record.getFile();
+		  }
+		  Metadata new_metadata = event.getNewMetadata();
+		  Metadata old_metadata = event.getOldMetadata();
+		  // These metadata objects may be new instances of metadata objects that already exist. Replace them if they are.
+		  new_metadata = checkCache(new_metadata);
+		  old_metadata = checkCache(old_metadata);
+		  // Now apply the change to the document in question.
+		  GDMDocument metadata_xml = getDocument(file);
+		  if(metadata_xml != null) {
+				if(old_metadata != null) {
+					 // File level
+					 if(file.isFile()) {
+						  metadata_xml.removeMetadata(file.getName(), old_metadata);
+					 }
+					 // Folder level
+					 else {
+						  metadata_xml.removeMetadata(null, old_metadata);
+					 }
+				}
+				if(new_metadata != null) {
+					 // File level
+					 if(file.isFile()) {
+						  metadata_xml.addMetadata(file.getName(), new_metadata);
+					 }
+					 else {
+						  metadata_xml.addMetadata(null, new_metadata);
+					 }
+				}
+		  }
+	 }
+
+	 public ArrayList removeMetadata(File file) {
+		  return getMetadata(file, true);
+	 }
+
+	 /** Causes all currently loaded GDMDocuments to write themselves out. 
+	  * @see org.greenstone.gatherer.msm.GDMDocument
+	  */
+	 public void save() {
+		  Iterator iterator = keySet().iterator();
+		  while(iterator.hasNext()) {
+				File file = (File) iterator.next();
+				GDMDocument document = (GDMDocument) get(file);
+				if(!document.isUpToDate()) {
+					 // First purge any old references.
+					 document.getMetadata(null, false, null, null, true);
+					 // Now write the xml
+					 Utility.export(document.getDocument(), file);
+					 document.setUpToDate(true);
+				}
+		  }
+	 }
+	 /** Used to cause the document associated with a particular file to write the latest copy of itself to disk. */
+	 public void save(FileNode node) {
+		  File file = node.getFile();
+		  if(file != null && file.isFile()) {
+				GDMDocument document = getDocument(file);
+				File xml_file;
+				if(file.isFile()) {
+					 xml_file = new File(file.getParentFile(), "metadata.xml");
+				}
+				else {
+					 xml_file = new File(file, "metadata.xml");
+				}
+				if(document != null && !document.isUpToDate()) {
+					 // First purge any old references.
+					 document.getMetadata(null, false, null, null, true);
+					 // Now write the xml
+					 Utility.export(document.getDocument(), xml_file);
+					 document.setUpToDate(true);
+				}
+				xml_file = null;
+				document = null;
+		  }
+		  file = null;
+	 }
+
+	 /** Method that is called whenever the metadata set collection changes in some way, such as the addition of a new set or the merging of two sets. If a set changes, mark all cached GDMDocuments as being stale.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  */
+	 public void setChanged(MSMEvent event) {
+		  for(Iterator values = values().iterator(); values.hasNext(); ) {
+				GDMDocument document = (GDMDocument) values.next();
+				document.setUpToDate(false);
+				document = null;
+		  }
+	 }
+	 /** Called whenever the value tree of an metadata element changes in some way, such as the addition of a new value. --While the comments below are now obsolete, I'll keep them just to remind me of how easy it is to back yourself into a corner with issues such as caching and persisitant references--. Such an action would require us to painstakingly reload every metadata.xml file using the value model prior to the change, then painstakingly write out each metadata.xml file again using the modified model, but I'm a glutton for punishment so thats ok. The alternative is to not do this and watch in horror as heirarchy references quickly fall into disarray, pointing to the wrong place. This task gets even more complicated by three facts:<br>1. We want to do this is a seperate thread, as we don't want the program to come to a screaming halt while we're updating metadata.xml files.<br>2. We have to prevent any metadata.xml files being removed from cache while we're doing this, as if we encounter these more recently written files their heirarchy references will already be correct and that will balls up our little process. Note that this means the saving process may have to block while pending metadata heirarchy updates are in progress.<br>3. Regarding (2) we don't have to rewrite any metadata.xml files already in cache as they will be correctly written out whenever they happen to be dumped from cache.<br>4. We need the ability to pre-empt the general update to load a user demanded metadata.xml and store it in cache, using the old value tree model as per usual, and<br>5. We have to store a cue of these events, and process them one at a time. Perhaps one day when I'm feeling masacistic I'll figure out someway to merge several updates into one, but for now we have to change the tree one node at a time in order for references to remain correct.<br>Ok, so thats five facts, but you get the gist. Not an easy task, but crucial for accurate storage and recall of metadata heirarchies.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  */
+	 public void valueChanged(MSMEvent event) {}
+
+	 public void waitUntilComplete() {
+		  gdm_loader.waitUntilComplete();
+	 }
+
+	 private Metadata checkCache(Metadata metadata) {
+		  if(metadata != null) {
+				///ystem.err.println("Search for " + metadata.toString());
+				if(metadata_cache.contains(metadata.getElement(), metadata.getValueNode())) {
+					 metadata = (Metadata) metadata_cache.get(metadata.getElement(), metadata.getValueNode());
+				}
+		  }
+		  return metadata;
+	 }
+
+	 /** A separately threaded class to load all of the current metadata.xml files. Note that files can still be loaded on demand if they're not already in the cache. Also provides the functionality to block any other thread until the loading is complete, such as is necessary when moving values about in the value tree hierarchy. */
+	 private class GDMLoader
+		  extends Thread {
+		  private boolean complete = false;
+		  public void run() {
+				// Can't open a collections metadata when the collection isn't open!
+				while(!Gatherer.c_man.ready()) {
+					 try {
+						  wait(100);
+					 }
+					 catch(Exception error) {
+					 }
+				}
+				// Now for each non-file directory in the tree, ask it to load its metadata
+				ArrayList remaining = new ArrayList();
+				remaining.add((FileNode)Gatherer.c_man.getRecordSet().getRoot());
+				int remaining_size = 0;
+				while((remaining_size = remaining.size()) > 0) {
+					 FileNode record = (FileNode) remaining.remove(remaining_size - 1);
+					 if(!record.isLeaf()) {
+						  ///atherer.println("Retrieving metadata.xml for " + record);
+						  getMetadata(record.getFile());
+						  for(int i = 0; i < record.getChildCount(); i++) {
+								remaining.add(record.getChildAt(i));
+						  }
+					 }
+					 record = null;
+				}
+				remaining = null;
+				complete = true;
+		  }
+		  public void waitUntilComplete() {
+				try {
+					 while(!complete) {
+						  sleep(100); // 1 second hopefully.
+					 }
+				}
+				catch(Exception error) {
+					 Gatherer.printStackTrace(error);
+				}
+		  }
+	 }
+}
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/GDMParser.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/GDMParser.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/GDMParser.java	(revision 13666)
@@ -0,0 +1,184 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+package org.greenstone.gatherer.msm;
+/**************************************************************************************
+ * Title:        Gatherer
+ * Description:  The Gatherer: a tool for gathering and enriching a digital collection.
+ * Company:      The University of Waikato
+ * Written:        /  /02
+ * Revised:      20/08/02 Commented and Optimized.
+ * @author John Thompson, 9826509
+ * @version 2.3
+ **************************************************************************************/
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.lang.IllegalArgumentException;
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.apache.xerces.parsers.DOMParser;
+import org.apache.xml.serialize.XMLSerializer;
+import org.apache.xml.serialize.OutputFormat;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+/** Parses metadata.xml documents of the GreenstoneDirectoryMetadata variety, caching where possible. */
+// ####################################################################################
+// Optimization                          Saving
+// ####################################################################################
+// Vector -> ArrayList                   + Memory, + Processor (pos. - Processor)
+// Hashtable -> HashMap                  + Memory, + Processor
+// Removed extra global references       + Memory (16k)
+// ####################################################################################
+public class GDMParser 
+	 extends LinkedHashMap {
+	 /** A list of file names that we know do not actually belong to valid GDM xml files, so there not much point in ever trying to read them again. */
+	 private ArrayList ignore = null;
+	 /** The actual xerces parser used to read in xml documents. */
+	 private DOMParser parser = null;
+	 /** The default maximum cache size if max size not explicitly set. */
+	 private int max_size = 25;
+	 /** Default constructor. */
+	 public GDMParser() {
+		  super();
+		  this.ignore = new ArrayList();
+		  try {
+				parser = new DOMParser();
+				// Don't let it import external dtds. If it does it'll probably spit the dummy. If people try to use a poorly formated xml file more fool them.
+				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);
+		  }
+		  catch(Exception error) {
+				///ystem.err.println("Fatal Error in GDMParser.init(): " + error);
+				error.printStackTrace();
+				System.exit(1);
+		  }
+	 }
+	 /** Constructor with maximum size set.
+	  * @param max_size The maximum size of the cache, as an <i>int</i>.
+	  */
+	 public GDMParser(int max_size) {
+		  this();
+		  this.max_size = max_size;
+	 }
+	 /** Destructor, clears cache and remove persistant global references. */
+	 public void destroy() {
+		  ignore.clear();
+		  ignore = null;
+		  parser = null;
+		  clear();
+	 }
+	 /** Fetches the document for the given xml file. This may mean (re)parsing it or simply fetching it from cache.
+	  * @param file The metadata.xml <strong>File</strong> you wish to get the document for.
+	  * @return A <strong>Document</strong> which is sourced from file.
+	  */
+	 public Document parse(File file) {
+		  ///ystem.err.println("Parse: " + file.getAbsolutePath());
+		  Document result = null;
+		  if(file.exists()) {
+				// Check if we've already parsed this file in an earlier attempt.
+				if(containsKey(file)) {
+					 ///ystem.err.println("Already cached previously.");
+					 //result = (Document) get(file);
+					 SoftReference reference = (SoftReference) get(file);
+					 if(reference != null) {
+					 	  result = (Document) reference.get();
+					 }
+					 else {
+						  ///ystem.err.println("Reference expired.");
+					 }
+				}
+				// Check the ignore list and see if we've already detected this isn't a greenstone metadata file.
+				if(result == null && !ignore.contains(file)) {
+					 ///ystem.err.println("Reparse file.");
+					 // Of course we may not have, or it may have expired so...
+					 try {
+						  // Display progress dialog.
+						  InputStream is = new FileInputStream(file);
+						  InputStreamReader isr = new InputStreamReader(is);
+						  Reader r = new BufferedReader(isr);
+						  InputSource isc = new InputSource(r);
+						  parser.parse(isc); // Slow.
+						  Document document = parser.getDocument();
+						  // First test. Check we have a GreenstoneDirectoryMetadata file, or for the older version DirectoryMetadata.
+						  if(!document.getDoctype().getName().equals("GreenstoneDirectoryMetadata") && !document.getDoctype().getName().equals("DirectoryMetadata")) {
+								///ystem.err.println("Adding to ignore list.");
+								// Add to ignore list. Not a gdm file.
+								ignore.add(file);
+						  }
+						  // Cache document.
+						  else {
+								///ystem.err.println("Adding to cache.");
+								put(file, new SoftReference(document));
+								result = document;
+						  }
+					 }
+					 catch (Exception error) {
+						  ///ystem.err.println("Error! " + error);
+						  error.printStackTrace();
+					 }
+				}
+				else {
+					 ///ystem.err.println("File on ignore list.");
+				}
+		  }
+		  else {
+				///ystem.err.println("File does not exist!");
+		  }
+		  return result;
+	 }
+	 /** Automatically called by the LinkedHashMap object whenever an object is added, to determine whether it should remove the oldest entry.
+	  * @param eldest The eldest <strong>Map.Entry</strong> which may mean in terms of age, or in terms of usage.
+	  * @return <i>true</i> if the given entry should be removed, <i>false</i> otherwise.
+	  */
+	 protected boolean removeEldestEntry(Map.Entry eldest) {
+		  return size() > max_size;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/GreenstoneArchiveParser.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/GreenstoneArchiveParser.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/GreenstoneArchiveParser.java	(revision 13666)
@@ -0,0 +1,164 @@
+package org.greenstone.gatherer.msm;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.Collection;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.MetadataSet;
+import org.greenstone.gatherer.msm.MetadataSetManager;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.greenstone.gatherer.shell.GShell;
+import org.greenstone.gatherer.shell.GShellProgressMonitor;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.valuetree.GValueModel;
+import org.greenstone.gatherer.valuetree.GValueNode;
+import org.w3c.dom.*;
+
+public class GreenstoneArchiveParser {
+
+	 private GShell shell;
+
+	 static final String ignore_list[] = {"assocfilepath","gsdl","Identifier","Source","URL"};
+
+	 public GreenstoneArchiveParser(GShellProgressMonitor progress, GShell shell) {
+		  this.shell = shell;
+		  // Determine the collection archive directory.
+		  File archive_directory = new File(Gatherer.c_man.getCollectionArchive());
+		  // For each of the hash coded directories within.
+		  File document_directories[] = archive_directory.listFiles();
+		  for(int i = 0; i < document_directories.length; i++) {
+				// Find the doc.xml file within
+				if(document_directories[i].isDirectory()) {
+					 File document_file = new File(document_directories[i], "doc.xml");
+					 // Then extract the metadata from it.
+					 if(document_file.exists()) {
+						  extractMetadata(document_file);
+						  // Display a pretty progress message.
+						  shell.fireMessage(GShell.IMPORT, shell.typeAsString(GShell.IMPORT) + "> " + Gatherer.dictionary.get("GShell.Extracted", document_directories[i].getName()), GShell.OK);
+						  progress.increment();
+					 }
+				}
+		  }
+		  // All done. Outta here like a bald man.
+	 }
+
+	 private void extractMetadata(File file) {
+		  // Retrieve the DOM of the file.
+		  Document document = Utility.parse(file, false);
+		  // If we successfully parsed the document, then it is time to search through the DOM for the Metadata tags.
+		  if(document != null) {
+				String file_path = null;
+				Element archive_element = document.getDocumentElement();
+				// Retrieve all of the Metadata sections.
+				NodeList metadata_elements = archive_element.getElementsByTagName("Metadata");
+				// Now for each Metadata entry retrieved...
+				for(int i = 0; i < metadata_elements.getLength(); i++) {
+					 Element metadata_element = (Element) metadata_elements.item(i);
+					 String name = metadata_element.getAttribute("name");
+					 // There is a special case when the metadata name is gsdlsourcefilename, as we use this to find the FileRecord we want to add metadata to.
+					 if(name.equals("gsdlsourcefilename")) {
+						  file_path = MSMUtils.getValue(metadata_element);
+					 }
+					 else {
+						  // Check if its name starts with, or is equal to, one of the values in our ignore list, and if so ignore this metadata.
+						  boolean ignore = (name.indexOf(".") != -1);
+						  for(int j = 0; !ignore && j < ignore_list.length; j++) {
+								ignore = name.startsWith(ignore_list[j]);
+						  }
+						  // Otherwise ensure the metadata is present in our collection.
+						  if(!ignore && file_path != null) {
+								// If we successfully retrieved a record we can continue.
+								if(file_path != null) {
+									 // We now retrieve the appropriate element. If no such element exists we create a new one in the greenstone mds. Remember that no element in the greenstone mds has an associated value tree, so it is perfect for metadata elements with a small number of repeated values but where the values have no relation between files (such as encoding, where many files will be iso_8859_1, but if you change one you don't intend to change them all).
+									 ElementWrapper element = Gatherer.c_man.msm.getElement(name);
+									 if(element == null) {
+										  MetadataSet greenstone_mds = Gatherer.c_man.msm.getSet("");
+										  element = greenstone_mds.addElement(name);
+									 }
+									 // If we successfully retrieved an element (and we should have) we can continue.
+									 if(element != null) {
+										  // Retrieve the metadata for the current file
+										  File target_file = new File(file_path);
+										  ArrayList metadatum = Gatherer.c_man.getCollection().gdm.getMetadata(target_file);
+										  // If no metadata exists for the current element, add it
+										  boolean found = false;
+										  for(int k = 0; !found && k < metadatum.size(); k++) {
+												Metadata sibling = (Metadata) metadatum.get(k);
+												found = element.equals(sibling.getElement());
+										  }
+										  metadatum = null;
+										  if(!found) {
+												String value = "";
+												try {
+													 value = Utility.decodeGreenstone(URLDecoder.decode(MSMUtils.getValue(metadata_element), "UTF-8"));
+												}
+												catch(UnsupportedEncodingException error) {
+													 Gatherer.printStackTrace(error);
+												}
+										      // If we successfully retrieved a value we can continue.
+												if(value != null) {
+													 // Create a new metadata object.
+													 GValueModel value_tree = Gatherer.c_man.msm.getValueTree(element);
+													 GValueNode value_node = null;
+													 if(value_tree != null) {
+														  value_node = value_tree.getValue(value);
+													 }
+													 else {
+														  value_node = new GValueNode(element.toString(), value);
+													 }
+													 Metadata metadata = new Metadata(element, value_node);
+													 Gatherer.c_man.getCollection().gdm.metadataChanged(new MSMEvent(this, System.currentTimeMillis(), target_file, null, metadata));
+													 // All done. On to next metadata.
+												}
+										  }
+										  target_file = null;
+									 }
+									 else {
+										  Gatherer.println("Cannot retrieve metadata element " + name);
+									 }
+								}
+						  }
+					 }
+				}
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/MDSFileFilter.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/MDSFileFilter.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/MDSFileFilter.java	(revision 13666)
@@ -0,0 +1,69 @@
+package org.greenstone.gatherer.msm;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.io.*;
+import javax.swing.filechooser.*;
+import org.greenstone.gatherer.Gatherer;
+/** A custom <strong>FileFilter</strong> for the file choosers. */
+final public class MDSFileFilter
+	 extends javax.swing.filechooser.FileFilter {
+	 private String description = null;
+	 /** Constructor.
+	  * @see org.greenstone.gatherer.Dictionary
+	  */
+	 public MDSFileFilter() {
+		  description = Gatherer.dictionary.get("MSMPrompt.File_Filter_Description");
+	 }
+	 /** Override this method to return <i>true</i> only if the file extension is .mds.
+	  * @param f A possible mds <strong>File</strong>.
+	  * @return <i>true</i> if we should show this file, <i>false</i> otherwise.
+	  */
+	 public boolean accept(File f) {
+		  String file_name = f.getName();
+		  file_name = file_name.toLowerCase();
+		  if(file_name.endsWith(".mds") || file_name.indexOf(".") == -1) {
+				return true;
+		  }
+		  return false;
+	 }
+	 /** Retrieve the description for this filter.
+	  * @return The description as a <strong>String</strong>.
+	  */
+	 public String getDescription() {
+		  return description;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/MSMAction.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/MSMAction.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/MSMAction.java	(revision 13666)
@@ -0,0 +1,140 @@
+/**
+ *#########################################################################
+ *
+ * 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.msm;
+/**
+ * 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:        /04/02<br>
+ * @author John Thompson, Greenstone Digital Libraries
+ * @version 2.1
+ */
+import org.greenstone.gatherer.msm.Declarations;
+import org.greenstone.gatherer.msm.MetadataSetManager;
+/** This class provides all the information required to correctly perform metadata actions, with regard to the users previously indicated preferences in terms of importing and renaming. */
+final public class MSMAction {
+	 private boolean hfile = false;
+	 /** The type of action required in subsequent actions involving the specified set and source element. */
+	 private int action = Declarations.NO_ACTION;
+	 private String set = null;
+	 private String source = null;
+	 /** The fully qualified name of the target element (which must be currently in the loaded metadata sets, otherwise the set it belongs to cannot be determined. */
+	 private String target = null;
+	 /** Constructor. Note that the standard action FORCE_MERGE is only named so for clarity and is translated into its actual action RENAME when this profile is created.
+	  * @param action An <i>int</i> representing what action needs to be taken in subsequent access of the given set and source element.
+	  * @param target A <strong>String</strong> representing the fully qualified name of the target element.
+	  * @param hfile If this action was created from the hfile parsing stage, does the element require a replacement to change its alias value into a real one. Note that this profile item may be created for fully namespaced elements as well, to ensure aliases are always remapped.
+	  */ 
+	 public MSMAction(int action, String target) {
+		  this.target = target;
+		  switch(action) {
+		  case Declarations.DELETE:
+				this.action = action;
+				break;
+		  case Declarations.FORCE_MERGE:
+				this.action = Declarations.RENAME;
+				break;
+		  case Declarations.RENAME:
+				this.action = action;
+				break;
+		  case Declarations.SKIP:
+				this.action = action;
+				this.target = null;
+				break;
+		  default:
+				this.action = Declarations.NO_ACTION;
+		  }
+	 }
+	 /** Constructor. Note that the standard action FORCE_MERGE is only named so for clarity and is translated into its actual action RENAME when this profile is created.
+	  * @param action An <i>int</i> representing what action needs to be taken in subsequent access of the given set and source element.
+	  * @param target A <strong>String</strong> representing the fully qualified name of the target element.
+	  * @param hfile If this action was created from the hfile parsing stage, does the element require a replacement to change its alias value into a real one. Note that this profile item may be created for fully namespaced elements as well, to ensure aliases are always remapped.
+	  */ 
+	 public MSMAction(int action, String target, boolean hfile) {
+		  this.hfile = hfile;
+		  this.target = target;
+		  switch(action) {
+		  case Declarations.FORCE_MERGE:
+				this.action = Declarations.RENAME;
+				break;
+		  case Declarations.RENAME:
+				this.action = action;
+				break;
+		  case Declarations.SKIP:
+				this.action = action;
+				this.target = null;
+				break;
+		  default:
+				this.action = Declarations.NO_ACTION;
+		  }
+	 }
+
+	 public MSMAction(String set, String source, int action, String target) {
+		  this(action, target);
+		  this.set = set;
+		  this.source = source;
+	 }
+
+	 /** Method for retrieving the appropriate action from this class.
+	  * @return An <i>int</i> specifying a particular action. 
+	  */
+	 public int getAction() {
+		  return action;
+	 }
+	 public String getSet() {
+		  return set;
+	 }
+	 public String getSource() {
+		  return source;
+	 }
+	 /** Method for retrieving the target element of this action.
+	  * @return A <strong>String</strong> stating the fully qualified name of the target element, within the namespace of one of the currently loaded metadata sets. 
+	  */
+	 public String getTarget() {
+		  return target;
+	 }
+	 public boolean isHFile() {
+		  return hfile;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/MSMAdapter.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/MSMAdapter.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/MSMAdapter.java	(revision 13666)
@@ -0,0 +1,76 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+package org.greenstone.gatherer.msm;
+/**************************************************************************************
+ * Title:        Gatherer
+ * Description:  The Gatherer: a tool for gathering and enriching a digital collection.
+ * Copyright:    Copyright (c) 2001
+ * Company:      The University of Waikato
+ * Written:      22/07/02
+ * Revised:
+ * @author John Thompson, 9826509
+ * @version 2.3
+ **************************************************************************************/
+import org.greenstone.gatherer.msm.MSMEvent;
+import org.greenstone.gatherer.msm.MSMListener;
+/** The default adapter for a MSMListener doesn't actually do anything, thus users can override whatever methods they want. */
+public class MSMAdapter 
+	 implements MSMListener {
+	 /** Method that is called whenever an element within a set is changed or modified.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  */
+	 public void elementChanged(MSMEvent event){}
+	 /** Called whenever the metadata value changes in some way, such as the addition of a new value.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  */
+	 public void metadataChanged(MSMEvent event){}
+	 /** Method that is called whenever the metadata set collection changes in some way, such as the addition of a new set or the merging of two sets.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  */
+	 public void setChanged(MSMEvent event){}
+	 /** Called whenever the value tree of an metadata element changes in some way, such as the addition of a new value.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  */
+	 public void valueChanged(MSMEvent event){}
+} 
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/MSMEvent.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/MSMEvent.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/MSMEvent.java	(revision 13666)
@@ -0,0 +1,194 @@
+/**
+ *#########################################################################
+ *
+ * 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.msm;
+/**
+ * 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>
+ * @author John Thompson, Greenstone Digital Libraries
+ * @version 2.1
+ */
+import java.awt.AWTEvent;
+import java.io.*;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.Metadata;
+import org.greenstone.gatherer.msm.MSMAction;
+import org.greenstone.gatherer.valuetree.GValueModel;
+/** An event object which contains useful information about the event that generated it, which in this case is probably an element update (this means a MSMAction object should be provided). */
+public class MSMEvent
+	 extends AWTEvent {
+	 /** The element associated with this event. */
+	 private ElementWrapper element = null;
+	 /** The file associated with this event. */
+	 private File file = null;
+	 /** The record associated with this event. */
+	 private FileNode record = null;
+	 /** The value tree model after adding a new value. */
+	 private GValueModel new_model = null;
+	 /** The value tree model prior to adding a new value. */
+	 private GValueModel old_model = null;
+	 /** A unique id given to any file or metadata task so it can be undone in its entirity. */
+	 private long id;
+	 /** The new metadata associated with this event. */
+	 private Metadata new_metadata = null;
+	 /** The old metadata associated with this event. */
+	 private Metadata old_metadata = null;
+	 /** The profile associated with this event. */
+	 private MSMAction profile = null;
+	 /** The value associated with this event. */
+	 private String value = null;
+	 /** The message counter. */
+	 static private int count = 0;
+	 /** Constructor.
+	  * @param source The <strong>Object</strong> that caused this event.
+	  * @param id An <i>long</i> identifier.
+	  * @param element The <strong>ElementWrapper</strong> affected.
+	  */
+	 public MSMEvent(Object source, long id, ElementWrapper element, GValueModel old_model, GValueModel new_model) {
+		  super(source, 0);
+		  this.element = element;
+		  this.id = id;
+		  this.new_model = new_model;
+		  this.old_model = old_model;
+		  this.profile = null;
+		  this.record = null;
+	 }
+	 /** Constructor for a metadata change event involving a file. */
+	 public MSMEvent(Object source, long id, File file, Metadata old_metadata, Metadata new_metadata) {
+		  super(source, 0);
+		  this.element = null;
+		  this.file = file;
+		  this.id = id;
+		  this.new_metadata = new_metadata;
+		  this.old_metadata = old_metadata;
+		  this.profile = null;
+	 }
+	 /** Constructor for a metadata change event involving a filenode. */
+	 public MSMEvent(Object source, long id, FileNode record, Metadata old_metadata, Metadata new_metadata) {
+		  super(source, 0);
+		  this.element = null;
+		  this.id = id;
+		  this.new_metadata = new_metadata;
+		  this.old_metadata = old_metadata;
+		  this.record = record;
+		  this.profile = null;
+	 }
+	 /** Constructor.
+	  * @param source The <strong>Object</strong> that caused this event.
+	  * @param id An <i>long</i> identifier.
+	  * @param profile The <strong>MSMAction</strong> profile if one is applicable.
+	  */
+	 public MSMEvent(Object source, long id, MSMAction profile) {
+		  super(source, 00);
+		  this.element = null;
+		  this.id = id;
+		  this.record = null;
+		  this.profile = profile;
+	 }
+	 /** Constructor for a metadata element changed event. 
+	  * @param source The <strong>Object</strong> that caused this event.
+	  * @param element A reference to the effected metadata <strong>ElementWrapper</strong>, or <i>null</i> if element no longer exists.
+	  * @param value The old name of the element (if its name has changed). If <i>null</i> old name defaults to element.toString().
+	  */
+	 public MSMEvent(Object source, ElementWrapper element, String value) {
+		  super(source, count++);
+		  this.element = element;
+		  this.value = value;
+	 }
+	 /** Method to retrieve of the element associated with this event.
+	  * @return A <strong>ElementWrapper</strong>, or <i>null</i> if there is none.
+	  */
+	 public ElementWrapper getElement() {
+		  return element;
+	 }
+
+	 public File getFile() {
+		  return file;
+	 }
+	 /** Method to retrieve the new metadata associated with this event.
+	  * @return A <strong>Metadata</strong>, or <i>null</i> if there is none.
+	  */
+	 public Metadata getNewMetadata() {
+		  return new_metadata;
+	 } 
+	 public GValueModel getNewModel() {
+		  return new_model;
+	 }
+	 /** Method to retrieve the old metadata associated with this event.
+	  * @return A <strong>Metadata</strong>, or <i>null</i> if there is none.
+	  */
+	 public Metadata getOldMetadata() {
+		  return old_metadata;
+	 } 
+	 public GValueModel getOldModel() {
+		  return old_model;
+	 }
+	 /** Method to retrieve of the profile associated with this event.
+	  * @return A <strong>MSMAction</strong> which details the action profile, or <i>null</i> if no profile exists.
+	  */
+	 public MSMAction getProfile() {
+		  return profile;
+	 }
+	 /** Retrieve the record associated with this event. */
+	 public FileNode getRecord() {
+		  return record;
+	 }
+	 /** Retrieve the associated with this event.
+	  * @return A <strong>String</strong>.
+	  */
+	 public String getValue() {
+		  String result = null;
+		  if(value != null) {
+				result = value;
+		  }
+		  else if(element != null) {
+				result = element.toString();
+		  }
+		  return result;
+	 }
+	 public long ID() {
+		  return id;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/MSMListener.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/MSMListener.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/MSMListener.java	(revision 13666)
@@ -0,0 +1,71 @@
+/**
+ *#########################################################################
+ *
+ * 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.msm;
+/**
+ * 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>
+ * @author John Thompson, Greenstone Digital Libraries
+ * @version 2.1
+ */
+import org.greenstone.gatherer.msm.MSMEvent;
+/** This class provides an interface for classes who wish to listener for events within the <strong>MetadataSetManager</strong>. There are events which are fired whenever a set or an element within a set changes. The events are either very broad, of the <i>metadataSetChanged()</i> variaty down to the more explicit <i>elementChanged(Profile change)</i> which actually details what change occured so the GUI etc can update just that element. */
+public interface MSMListener {
+	 /** Method that is called whenever an element within a set is changed or modified.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  */
+	 public void elementChanged(MSMEvent event);
+	 /** Called whenever the metadata value changes in some way, such as the addition of a new value.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  */
+	 public void metadataChanged(MSMEvent event);
+	 /** Method that is called whenever the metadata set collection changes in some way, such as the addition of a new set or the merging of two sets.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  */
+	 public void setChanged(MSMEvent event);
+	 /** Called whenever the value tree of an metadata element changes in some way, such as the addition of a new value.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  */
+	 public void valueChanged(MSMEvent event);
+} 
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/MSMListenerAdapter.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/MSMListenerAdapter.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/MSMListenerAdapter.java	(revision 13666)
@@ -0,0 +1,77 @@
+/**
+ *#########################################################################
+ *
+ * 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.msm;
+/**
+ * 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>
+ * @author John Thompson, Greenstone Digital Libraries
+ * @version 2.1
+ */
+import org.greenstone.gatherer.msm.MSMEvent;
+import org.greenstone.gatherer.msm.MSMListener;
+/** This class provides an interface for classes who wish to listener for events within the <strong>MetadataSetManager</strong>. There are events which are fired whenever a set or an element within a set changes. The events are either very broad, of the <i>metadataSetChanged()</i> variaty down to the more explicit <i>elementChanged(Profile change)</i> which actually details what change occured so the GUI etc can update just that element. */
+public class MSMListenerAdapter 
+	 implements MSMListener {
+	 /** Method that is called whenever an element within a set is changed or modified.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  */
+	 public void elementChanged(MSMEvent event) {
+	 }
+	 /** Called whenever the metadata value changes in some way, such as the addition of a new value.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  */
+	 public void metadataChanged(MSMEvent event) {
+	 }
+	 /** Method that is called whenever the metadata set collection changes in some way, such as the addition of a new set or the merging of two sets.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  */
+	 public void setChanged(MSMEvent event) {
+	 }
+	 /** Called whenever the value tree of an metadata element changes in some way, such as the addition of a new value.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  */
+	 public void valueChanged(MSMEvent event) {
+	 }
+} 
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/MSMProfiler.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/MSMProfiler.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/MSMProfiler.java	(revision 13666)
@@ -0,0 +1,313 @@
+package org.greenstone.gatherer.msm;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.msm.Declarations;
+import org.greenstone.gatherer.msm.MSMAdapter;
+import org.greenstone.gatherer.util.HashMap3D;
+import org.greenstone.gatherer.util.Utility;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+/** This class is essentially records what actions a user took when merging two metadata sets, so we can avoid having to get the user to repeat the proceedure. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.2
+ */ 
+public class MSMProfiler 
+	 extends MSMAdapter {
+	 /** The file the profile should be loaded from and saved to. */
+	 private File profile_file = null;
+	 /** A mapping of known profile actions. */
+	 private HashMap3D profiles = null;
+	 static final private String IGNORE = "\nIGNORE\n";
+	 /** The constructor loads the previous profile for this collection if there is one. 
+	  * @see org.greenstone.gatherer.collection.CollectionManager
+	  * @see org.greenstone.gatherer.msm.MetadataSetManager 
+	  */
+	 public MSMProfiler() {
+		  this.profile_file = new File(Gatherer.c_man.getCollectionMetadata(), "profile.xml");
+		  this.profiles = new HashMap3D();
+		  // Load an existing profile if there is one.
+		  if(profile_file.exists()) {
+				Document document = Utility.parse(profile_file, false);
+				if(document != null) {
+					 load(document);
+					 document = null;
+				}
+		  }
+	 }
+	 /** Adds a new action mapping to the profile. Such a mapping records that for a certain collection (file) and metadata element a specific action must occur. The action is either a renaming to a new metadata element name, also provided, or an instruction to ignore this particular metadata element, is the target is null.
+	  * @param collection_file The aboslute path name to the collection where the metadata was sourced, as a <strong>String</strong>.
+	  * @param source A <strong>String</strong> containing the fully qualified name of the source metadata element.
+	  * @param target Another <strong>String</strong> which is either the fully qualified name of the target element, or <i>null</i> if this is actually an ignore action addition.
+	  */
+	 public void addAction(String collection_file, String source, String target) {
+		  if(target == null) {
+				target = IGNORE;
+		  }
+		  profiles.put(collection_file, source, target);
+	 }
+
+	 public void addSource(String collection_file) {
+		  profiles.put(collection_file, new HashMap());
+	 }
+
+	 /** Determine if an action exists for the given collection and source.
+	  * @param collection_file The aboslute path name to the collection where the metadata was sourced, as a <strong>String</strong>.
+	  * @param source A <strong>String</strong> containing the fully qualified name of the source metadata element.
+	  * @return <i>true</i> if such an action exists, <i>false</i> otherwise.
+	  */
+	 public boolean containsAction(String collection_file, String source) {
+		  return profiles.contains(collection_file, source);
+	 }
+
+	 public boolean containsSource(String collection_file) {
+		  return profiles.containsKey(collection_file);
+	 }
+
+	 /** Destructor to ensure that no memory leaks. */
+	 public void destroy() {
+		  //save();
+		  profiles.clear();
+		  profile_file = null;
+		  profiles = null;
+	 }
+	 /** Method that is called whenever an element within a set is changed or modified, in which case we must modify the action profiles to suit. If an element was removed, remove all action profiles with this element as the target. If an elements name changes, update all matching targets to reflect new name.
+	  * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
+	  */
+	 public void elementChanged(MSMEvent event) {
+		  Gatherer.println("Element changed: " + event);
+		  String new_name = null;
+		  String old_name = event.getValue();
+		  ElementWrapper element = event.getElement();
+		  boolean delete = false;
+		  boolean rename = false;
+		  // First we check if the element has been removed.
+		  if(element == null) {
+				delete = true;
+		  }
+		  // Next we determine if its name has changed 
+		  else if(!(new_name = element.toString()).equals(old_name)) {
+				rename = true;
+		  }
+		  // Perform any action we need to.
+		  if(delete || rename) {
+				Iterator iterator_value_one = profiles.values().iterator();
+				while(iterator_value_one.hasNext()) {
+					 HashMap map = (HashMap) iterator_value_one.next();
+					 Iterator iterator_key_two = map.keySet().iterator();
+					 while(iterator_key_two.hasNext()) {
+						  String key_two = (String) iterator_key_two.next();
+						  String value = (String) map.get(key_two);
+						  if(value.equals(old_name)) {
+								if(delete) {
+									 map.remove(key_two);
+								}
+								else {
+									 map.put(key_two, new_name);
+								}
+						  }
+						  key_two = null;
+						  value = null;
+					 }
+					 map = null;
+					 iterator_key_two = null;
+				}
+				iterator_value_one = null;
+		  }
+		  // Otherwise nothing for us to do (must be an add, or possibly a move if I can ever get round to the editor).
+		  element = null;
+		  old_name = null;
+		  new_name = null;
+	 }
+	 /** Search the profilerer for any previous actions regarding the indicated collection and metadata element.
+	  * @param collection_file The absolute path name to the collection where the metadata was sourced, as a <strong>String</strong>.
+	  * @param source A <strong>String</strong> containing the fully qualified name of the source metadata element.
+	  * @return The fully qualified name of the target metadata element, as a <strong>String</strong>, or <i>null</i> if we are to ignore this metadata. Note that the target elements name may be exactly the source elements one.
+	  * @see org.greenstone.gatherer.msm.Declarations
+	  */
+	 public String getAction(String collection_file, String source) {
+		  ///atherer.println("Get action.");
+		  String result = (String) profiles.get(collection_file, source);
+		  if(result.equals(IGNORE)) {
+				result = null;
+		  }
+		  return result;
+	 }
+
+	 public HashMap getActions(String collection_file) {
+		  return (HashMap) profiles.get(collection_file);
+	 }
+	 
+	 public ArrayList getCollections() {
+		  return new ArrayList(profiles.keySet());
+	 }
+
+	 public ArrayList getSources(String collection_file) {
+		  ArrayList result = new ArrayList();
+		  HashMap map = (HashMap) profiles.get(collection_file);
+		  if(map != null) {
+				result.addAll(map.keySet());
+		  }
+		  return result;
+	 }
+
+	 public void removeProfile(String collection_file) {
+		  profiles.remove(collection_file);
+	 }
+
+	 public void removeAction(String collection_file, String source) {
+		  HashMap map = (HashMap) profiles.get(collection_file);
+		  if(map != null) {
+				map.remove(source);
+		  } 
+	 }
+
+	 /** Save the profile document. */
+	 public void save() {
+		  // While we're at it save the profiles.
+		  try {
+				// Create backup.
+				if(profile_file.exists()) {
+					 File backup = new File(profile_file.getAbsolutePath() + "~");
+					 backup.deleteOnExit();
+					 if(!profile_file.renameTo(backup)) {
+						  Gatherer.println("Error in MSMProfiler.save(): FileRenameException");
+					 }
+					 backup = null;
+				}
+				// Build the profile document.
+				StringBuffer buffer = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+				buffer.append("<!DOCTYPE Profiles [\n");
+			   buffer.append("<!ELEMENT Profiles (Action*)>\n");
+			   buffer.append("<!ELEMENT Action (#PCDATA)>\n");
+			   buffer.append("<!ATTLIST Action\n");
+				buffer.append("		    collection CDATA #REQUIRED\n");
+				buffer.append("		    source     CDATA #REQUIRED\n");
+				buffer.append("		    target     CDATA \"\">\n");
+            buffer.append("]>\n");
+            buffer.append("<Profiles>\n");
+				Iterator iterator_key_one = profiles.keySet().iterator();
+				while(iterator_key_one.hasNext()) {
+					 String key_one = (String) iterator_key_one.next();
+					 HashMap map = (HashMap) profiles.get(key_one);
+					 Iterator iterator_key_two = map.keySet().iterator();
+					 while(iterator_key_two.hasNext()) {
+						  String key_two = (String) iterator_key_two.next();
+						  String value = (String) map.get(key_two);
+						  buffer.append("  <Action collection=\"");
+						  buffer.append(key_one);
+						  buffer.append("\" source=\"");
+						  buffer.append(key_two);
+						  buffer.append("\" target=\"");
+						  buffer.append(value);
+						  buffer.append("\"> </Action>\n");
+						  key_two = null;
+						  value = null;
+					 }
+					 key_one = null;
+					 map = null;
+					 iterator_key_two = null;
+				}
+				iterator_key_one = null;
+            buffer.append("</Profiles>");
+				String buffer_str = buffer.toString();
+				buffer = null;
+				// Now write it to file.
+				FileOutputStream fos = new FileOutputStream(profile_file);
+				OutputStreamWriter osw = new OutputStreamWriter(fos);
+				int position = 0;
+				int BLOCK_SIZE = 1024;
+				// Write x block sized chunks to file.
+				while(position + BLOCK_SIZE < buffer_str.length()) {
+					 osw.write(buffer_str, position, BLOCK_SIZE);
+					 position = position + BLOCK_SIZE;
+				}
+				// Write the remainder of the buffer.
+				if(position < buffer_str.length()) {
+					 osw.write(buffer_str, position, buffer_str.length() - position);
+				}
+				osw.close();
+				fos.close();
+				fos = null;
+				osw = null;
+				buffer_str = null;
+		  }
+		  catch (Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+	 }
+	 /** Reload the mapping information stored in this document.
+	  * @param document The <strong>Document</strong> to parse.
+	  */
+	 private void load(Document document) {
+		  Element root = document.getDocumentElement();
+		  NodeList actions = root.getElementsByTagName("Action");
+		  for(int i = 0; i < actions.getLength(); i++) {
+				Element action = (Element) actions.item(i);
+				String collection = action.getAttribute("collection");
+				String source = action.getAttribute("source");
+				String target = action.getAttribute("target");
+				if(collection.length() > 0 && source.length() > 0) {
+					 if(target.length() == 0) {
+						  target = null;
+					 }
+					 profiles.put(collection, source, target);
+				}
+				action = null;
+				collection = null;
+				source = null;
+				target = null;
+		  }
+		  root = null;
+		  actions = null;
+	 }
+}
+
+
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/MSMPrompt.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/MSMPrompt.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/MSMPrompt.java	(revision 13666)
@@ -0,0 +1,1053 @@
+package org.greenstone.gatherer.msm;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.msm.Declarations;
+import org.greenstone.gatherer.msm.MetadataSet;
+import org.greenstone.gatherer.msm.MetadataSetManager;
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.MED;
+import org.w3c.dom.*;
+/** A class dedicated to producing the visual components used by the MSM package.
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 1.2
+ */
+public class MSMPrompt 
+	 implements ActionListener {
+
+	 private boolean dialog_cancelled = false;
+	 private Dimension screen_size = null;
+	 private int action = Declarations.NO_ACTION;
+	 private JButton add = null;
+	 private JButton cancel = null;
+	 private JButton merge = null;
+	 private JButton rename = null;
+	 private JButton replace = null;
+	 private JButton skip = null;
+	 private JDialog off_screen = null;
+	 private JDialog on_screen = null;
+	 private JDialog dialog = null;
+	 private JLabel current_details_label = null;
+	 private JLabel new_details_label = null;
+	 private JLabel progress_label = null;
+	 private JProgressBar progress = null;
+	 private JTextArea current_details = null;
+	 private JTextArea new_details = null;
+	 private MetadataSetManager manager = null;
+	 private Object result = null;
+
+	 final static private Dimension MDE_SIZE = new Dimension(500,200);
+	 final static private Dimension MDS_SIZE = new Dimension(800,400);
+	 final static private Dimension PROGRESS_SIZE = new Dimension(500,80);
+	 final static private Dimension RENAME_LABEL_SIZE = new Dimension(100,25);
+	 final static private Dimension RENAME_SIZE = new Dimension(300,120);
+	 final static private Dimension SELECT_ELEMENT_SIZE = new Dimension(500,280);
+	 final static private Dimension SELECT_LABEL_SIZE = new Dimension(175, 25);
+	 final static private Dimension SELECT_SET_SIZE = new Dimension(600,210);
+	 final static private Dimension SELECT_SIZE = new Dimension(200,200);
+	 final static private int SELECT_LINE_COUNT = 8;
+	 
+	 public MSMPrompt(MetadataSetManager manager) {
+		  this.manager = manager;
+		  // Create components
+
+		  add = new JButton(get("Add"));
+		  add.addActionListener(this);
+		  add.setEnabled(false);
+		  add.setMnemonic(KeyEvent.VK_A);
+		  
+
+		  cancel = new JButton(get("Cancel"));
+		  cancel.addActionListener(this);
+		  cancel.setEnabled(true);
+		  cancel.setMnemonic(KeyEvent.VK_C);
+
+		  current_details = new JTextArea(get("No_Details"));
+
+		  current_details_label = new JLabel(get("Current_Details"));
+
+		  merge = new JButton(get("Merge"));
+		  merge.addActionListener(this);
+		  merge.setEnabled(true);
+		  merge.setMnemonic(KeyEvent.VK_M);
+
+		  new_details = new JTextArea(get("No_Details"));
+
+		  new_details_label = new JLabel(get("New_Details"));
+
+		  progress = new JProgressBar();
+		  progress.setStringPainted(true);
+
+		  progress_label = new JLabel(get("Progress"));
+
+		  rename = new JButton(get("Rename"));
+		  rename.addActionListener(this);
+		  rename.setEnabled(false);
+		  rename.setMnemonic(KeyEvent.VK_N);
+
+		  replace = new JButton(get("Replace"));
+		  replace.addActionListener(this);
+		  replace.setEnabled(false);
+		  replace.setMnemonic(KeyEvent.VK_R);
+
+		  skip = new JButton(get("Skip"));
+		  skip.addActionListener(this);
+		  skip.setEnabled(true);
+		  skip.setMnemonic(KeyEvent.VK_S);
+
+		  screen_size = Gatherer.config.screen_size;
+	 }
+
+/** When called this method produces a nice error message on the screen, advising the user that the add action has failed.
+	  * @param mde_new The <strong>Element</strong> that we were attempting to add.
+	  * @param reason The phrase key for the reason the add failed, as a <strong>String</strong>.
+	  */
+	 public void addFailed(Element mde_new, String reason) {
+		  String args[] = new String[2];
+		  args[0] = mde_new.getAttribute("name");
+		  args[1] = get(reason, null);
+		  JOptionPane.showMessageDialog(off_screen, get("Add_Failed", args), get("Add_Failed_Title", null), JOptionPane.ERROR_MESSAGE);
+	 }
+
+	 /** 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 source = event.getSource();
+		  action = Declarations.NO_ACTION;
+		  if(source == add) {
+				action = Declarations.ADD;
+		  }
+		  else if(source == cancel) {
+				action = Declarations.CANCEL;
+		  }
+		  else if(source == merge) {
+				action = Declarations.MERGE;
+		  }
+		  else if(source == rename) {
+				action = Declarations.RENAME;
+		  }
+		  else if(source == replace) {
+				action = Declarations.REPLACE;
+		  }
+		  else if(source == skip) {
+				action = Declarations.SKIP;
+		  }
+		  on_screen.hide();
+	 }
+	 /** Method called when the merging process is complete and the progress bar is no longer needed.
+	  */
+	 public void endMerge() {
+		  off_screen.dispose();
+		  off_screen = null;
+	 }
+	 /** Method to indicate that yet another element has been succesfully merged, so that progress bar should reflect this.
+	  */
+	 public void incrementMerge() {
+		  progress.setValue(progress.getValue() + 1);
+		  String percent = ((100 * progress.getValue()) / progress.getMaximum()) + "%";
+		  progress.setString(percent);
+	 }
+	 /** Method to display the metadata element merging prompt, wherein the user determines how the attributes within an element should be merged.
+	  * @param mde_cur The current <strong>Element</strong> we are merging against.
+	  * @param att_cur The attribute <strong>Element</strong> of the current element in question.
+	  * @param mde_new The <strong>Element</strong> which we have choosen to merge in, and whose attributes are being examined.
+	  * @param att_new And the new elements attribute <strong>Element</strong>.
+	  * @return An <i>int</i> specifying what further action should be undertaken, if any.
+	  */
+	 public int mDEPrompt(Element mde_cur, Element att_cur, Element mde_new, Element att_new) {
+		  action = Declarations.NO_ACTION;
+		  // Construction and configuration
+		  JDialog dialog = new JDialog();
+		  dialog.setModal(true);
+		  dialog.setSize(MDE_SIZE);
+		  dialog.setTitle(get("Merge_MDE"));
+		  JPanel content_pane = (JPanel)dialog.getContentPane();
+
+		  JLabel cur_name_label = new JLabel(get("Element_Name"));
+
+		  JLabel cur_name = new JLabel(MSMUtils.getFullName(mde_cur));
+		  cur_name.setBackground(Color.white);
+		  cur_name.setOpaque(true);
+
+		  JLabel cur_att_label = new JLabel(get("Attribute"));
+
+		  JLabel cur_att = new JLabel(att_cur.getAttribute("name") +" = " + MSMUtils.getValue(att_cur));
+		  cur_att.setBackground(Color.white);
+		  cur_att.setOpaque(true);
+
+		  JLabel new_name_label = new JLabel(cur_name_label.getText());
+
+		  JLabel new_name = new JLabel(MSMUtils.getFullName(mde_new));
+		  new_name.setBackground(Color.white);
+		  new_name.setOpaque(true);
+
+		  JLabel new_att_label = new JLabel(cur_att_label.getText());
+
+		  JLabel new_att = new JLabel(att_new.getAttribute("name") +" = " + MSMUtils.getValue(att_new));
+		  new_att.setBackground(Color.white);
+		  new_att.setOpaque(true);
+
+		  replace.setEnabled(true);
+		  skip.setEnabled(true);
+
+		  // Layout
+		  JPanel current_pane = new JPanel();
+		  current_pane.setBorder(BorderFactory.createTitledBorder(get("Current_Element")));
+		  current_pane.setLayout(new GridLayout(2,2));
+		  current_pane.add(cur_name_label);
+		  current_pane.add(cur_name);
+		  current_pane.add(cur_att_label);
+		  current_pane.add(cur_att);
+
+		  JPanel new_pane = new JPanel();
+		  new_pane.setBorder(BorderFactory.createTitledBorder(get("New_Element")));
+		  new_pane.setLayout(new GridLayout(2,2));
+		  new_pane.add(new_name_label);
+		  new_pane.add(new_name);
+		  new_pane.add(new_att_label);
+		  new_pane.add(new_att);
+
+		  JPanel central_pane = new JPanel();
+		  central_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		  central_pane.setLayout(new GridLayout(2,1));
+		  central_pane.add(current_pane);
+		  central_pane.add(new_pane);
+
+		  JPanel button_pane = new JPanel();
+		  button_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
+		  button_pane.setLayout(new GridLayout(1,3));
+		  button_pane.add(replace);
+		  button_pane.add(skip);
+		  button_pane.add(cancel);
+
+		  content_pane.setLayout(new BorderLayout());
+		  content_pane.add(central_pane, BorderLayout.CENTER);
+		  content_pane.add(button_pane, BorderLayout.SOUTH);
+
+		  // Display
+		  dialog.setLocation((screen_size.width - MDE_SIZE.width) / 2, (screen_size.height - MDE_SIZE.height) / 2);
+		  on_screen = dialog;
+		  off_screen.hide();
+		  on_screen.show();
+		  off_screen.show();
+		  on_screen.dispose();
+
+		  content_pane = null;
+		  cur_name_label = null;
+		  cur_name = null;
+		  cur_att_label = null;
+		  cur_att = null;
+		  new_name_label = null;
+		  new_name = null;
+		  new_att_label = null;
+		  new_att = null;
+		  current_pane = null;
+		  new_pane = null;
+		  central_pane = null;
+		  button_pane = null;
+		  screen_size = null;
+		  on_screen = null;
+		  dialog = null;
+
+		  return action;
+	 }
+	 /** This method displays the metadata data set merging prompt, wherein the user determines how the elements within a set should be merged.
+	  * @param mds_cur The current <strong>MetadataSet</strong> containing our document.
+	  * @param mde_cur The current <strong>Element</strong> we are merging against.
+	  * @param mds_new The <strong>MetadataSet</strong> we are merging in.
+	  * @param mde_new The <strong>Element</strong> which we have choosen to merge in.
+	  * @return An <i>int</i> specifying what further action should be undertaken, if any.
+	  */
+	 public int mDSPrompt(MetadataSet mds_cur, Element mde_cur, MetadataSet mds_new, Element mde_new) {
+		  action = Declarations.NO_ACTION;
+		  // Construction and configuration
+		  JDialog dialog = new JDialog();
+		  dialog.setModal(true);
+		  dialog.setSize(MDS_SIZE);
+		  dialog.setTitle(get("Merge_MDS"));
+		  JPanel content_pane = (JPanel)dialog.getContentPane();
+		  if(mde_cur != null) {
+				add.setEnabled(false);
+				cancel.setEnabled(true);
+				merge.setEnabled(true);
+				rename.setEnabled(true);
+				replace.setEnabled(true);
+				skip.setEnabled(true);
+				// Current details.
+				String str_cur[] = MSMUtils.getStructuralDetails(mde_cur);
+				String opt_cur[] = MSMUtils.getOptionListDetails(mde_cur);
+				String ass_cur[] = MSMUtils.getAssignedValuesDetails(mds_cur, mde_cur);
+				String details_cur = get("Structural");
+				if(opt_cur != null) {
+					 details_cur = details_cur + "\n" + get("OptionList", opt_cur);
+				}
+				if(ass_cur != null) {
+					 details_cur = details_cur + "\n" + get("AssignedValues", ass_cur);
+				}
+				current_details.setText(details_cur);
+				str_cur = null;
+				opt_cur = null;
+				ass_cur = null;
+				details_cur = null;
+		  }
+		  else {
+				add.setEnabled(true);
+				cancel.setEnabled(true);
+				merge.setEnabled(true);
+				rename.setEnabled(false);
+				replace.setEnabled(false);
+				skip.setEnabled(true);
+				current_details.setText(get("No_Element"));
+		  }
+		  // New details.
+		  String str_new[] = MSMUtils.getStructuralDetails(mde_new);
+		  String opt_new[] = MSMUtils.getOptionListDetails(mde_new);
+		  String ass_new[] = MSMUtils.getAssignedValuesDetails(mds_new, mde_new);
+		  String details_new = get("Structural", str_new);
+		  if(opt_new != null) {
+				details_new = details_new + "\n" + get("OptionList", opt_new);
+		  }
+		  if(ass_new != null) {
+				details_new = details_new + "\n" + get("AssignedValues", ass_new);
+		  }
+		  new_details.setText(details_new);
+		  // Layout
+		  JPanel current_details_pane = new JPanel();
+		  current_details_pane.setLayout(new BorderLayout());
+		  current_details_pane.add(current_details_label, BorderLayout.NORTH);
+		  current_details_pane.add(new JScrollPane(current_details), BorderLayout.CENTER);
+
+		  JPanel new_details_pane = new JPanel();
+		  new_details_pane.setLayout(new BorderLayout());
+		  new_details_pane.add(new_details_label, BorderLayout.NORTH);
+		  new_details_pane.add(new JScrollPane(new_details), BorderLayout.CENTER);
+
+		  JPanel details_pane = new JPanel();
+		  details_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		  details_pane.setLayout(new GridLayout(1,2));
+		  details_pane.add(current_details_pane);
+		  details_pane.add(new_details_pane);
+
+		  JPanel button_pane = new JPanel();
+		  button_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
+		  button_pane.setLayout(new GridLayout(1,6));
+		  button_pane.add(add);
+		  button_pane.add(merge);
+		  button_pane.add(rename);
+		  button_pane.add(replace);
+		  button_pane.add(skip);
+		  button_pane.add(cancel);
+		  
+		  JPanel control_pane = new JPanel();
+		  control_pane.setLayout(new BorderLayout());
+		  control_pane.add(details_pane, BorderLayout.CENTER);
+		  control_pane.add(button_pane, BorderLayout.SOUTH);
+
+		  JPanel progress_pane = new JPanel();
+		  progress_pane.setBorder(BorderFactory.createEmptyBorder(5,5,0,5));
+		  progress_pane.setLayout(new BorderLayout());
+		  progress_pane.add(progress_label, BorderLayout.NORTH);
+		  progress_pane.add(progress, BorderLayout.CENTER);
+
+		  content_pane.setLayout(new BorderLayout());
+		  content_pane.add(progress_pane, BorderLayout.NORTH);
+		  content_pane.add(control_pane, BorderLayout.CENTER);
+
+		  // Display
+		  dialog.setLocation((screen_size.width - MDS_SIZE.width) / 2, (screen_size.height - MDS_SIZE.height) / 2);
+		  on_screen = dialog;
+		  off_screen.hide();
+		  on_screen.show(); // Blocks until hidden.
+		  off_screen.show();
+		  on_screen.dispose();
+		  on_screen = null;
+
+		  content_pane = null;
+		  str_new = null;
+		  opt_new = null;
+		  ass_new = null;
+		  details_new = null;
+		  current_details_pane = null;
+		  new_details_pane = null;
+		  details_pane = null;
+		  button_pane = null;
+		  control_pane = null;
+		  progress_pane = null;
+		  dialog = null;
+
+		  if(mde_cur == null && action == Declarations.MERGE) {
+				action = Declarations.FORCE_MERGE;
+		  }
+		  return action;
+	 }
+	 /** This method creates an initial JDialog which simply shows the MSMs progress towards merging the metadata sets.
+	  * @param element_count An <i>int</i> specifying the total number of elements to be merged.
+	  */
+ 	 public void startMerge(int element_count) {
+		  action = Declarations.NO_ACTION;
+		  JDialog dialog = new JDialog();
+		  dialog.setModal(false);
+		  dialog.setSize(PROGRESS_SIZE);
+		  dialog.setTitle(get("Merge_Progress"));
+		  JPanel content_pane = (JPanel)dialog.getContentPane();
+		  progress.setMaximum(element_count);
+		  progress.setMinimum(0);
+		  progress.setString("0%");
+		  progress.setValue(0);
+		  // Layout.
+		  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, BorderLayout.CENTER);
+		  // Display.
+		  dialog.setLocation((screen_size.width - PROGRESS_SIZE.width) / 2, (screen_size.height - PROGRESS_SIZE.height) / 2);
+		  off_screen = dialog;
+		  dialog.show();
+		  content_pane = null;
+		  dialog = null;
+	 }
+	 /** This method creates a prompt for renaming an Element.
+	  * @param mde_new The <strong>Element</strong> we wish to rename.
+	  * @return The new name as a <strong>String</strong>, <i>null</i> if cancelled.
+	  */
+	 public String rename(Element mde_new) {
+		  action = Declarations.NO_ACTION;
+		  // Create
+		  JDialog dialog = new JDialog();
+		  dialog.setModal(true);
+		  dialog.setSize(RENAME_SIZE);
+		  dialog.setTitle(get("Rename"));
+
+		  JLabel old_name_label = new JLabel(get("Old_Name"));
+		  old_name_label.setPreferredSize(RENAME_LABEL_SIZE);
+
+		  JLabel old_name = new JLabel(mde_new.getAttribute("name"));
+		  old_name.setBackground(Color.white);
+		  old_name.setOpaque(true);
+
+		  JLabel new_name_label = new JLabel(get("New_Name"));
+		  new_name_label.setPreferredSize(RENAME_LABEL_SIZE);
+		  
+		  JTextField new_name = new JTextField("");
+		  new_name.grabFocus();
+
+		  JButton ok = new JButton(get("General.OK"));
+		  ok.addActionListener(this);
+		  ok.setMnemonic(KeyEvent.VK_O);
+
+		  JPanel content_pane = (JPanel) dialog.getContentPane();
+
+		  // Layout 
+		  JPanel old_name_pane = new JPanel();
+		  old_name_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		  old_name_pane.setLayout(new BorderLayout());
+		  old_name_pane.add(old_name_label, BorderLayout.WEST);
+		  old_name_pane.add(old_name, BorderLayout.CENTER);
+
+		  JPanel new_name_pane = new JPanel();
+		  new_name_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
+		  new_name_pane.setLayout(new BorderLayout());
+		  new_name_pane.add(new_name_label, BorderLayout.WEST);
+		  new_name_pane.add(new_name, BorderLayout.CENTER);		  
+
+		  JPanel control_pane = new JPanel();
+		  control_pane.setLayout(new GridLayout(2,1));
+		  control_pane.add(old_name_pane);
+		  control_pane.add(new_name_pane);
+
+		  JPanel button_pane = new JPanel();
+		  button_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
+		  button_pane.setLayout(new GridLayout(1,2));
+		  button_pane.add(ok);
+		  button_pane.add(cancel);
+
+		  content_pane.setLayout(new BorderLayout());
+		  content_pane.add(control_pane, BorderLayout.CENTER);
+		  content_pane.add(button_pane, BorderLayout.SOUTH);
+		  // Display
+		  dialog.setLocation((screen_size.width - RENAME_SIZE.width) / 2, (screen_size.height - RENAME_SIZE.height) / 2);
+		  on_screen = dialog;
+		  off_screen.hide();
+		  on_screen.show();
+		  off_screen.show();
+		  on_screen.dispose();
+		  on_screen = null;		  
+
+		  button_pane = null;	
+		  control_pane = null;	
+		  new_name_pane = null;	
+		  old_name_pane = null;	
+		  content_pane = null;
+		  ok.removeActionListener(this);
+		  ok = null;	
+		  new_name = null;	
+		  new_name_label = null;	
+		  old_name = null;	
+		  old_name_label = null;	
+		  dialog = null;	
+
+		  if(action == Declarations.CANCEL) {
+				return null;
+		  }
+		  action = Declarations.NO_ACTION;
+		  dialog = null;
+		  return new_name.getText();
+	 }
+
+	 /** When called this method produces a nice error message on the screen, advising the user that the remove action has failed.
+	  * @param mde_cur The <strong>Element</strong> that we are attempting to remove.
+	  * @param reason The phrase key for the reason the rename failed, also as a <strong>String</strong>.
+	  */
+	 public void removeFailed(Element mde_cur, String reason) {
+		  String args[] = new String[2];
+		  args[0] = mde_cur.getAttribute("name");
+		  args[1] = get(reason, null);
+		  JOptionPane.showMessageDialog(off_screen, get("Remove_Failed", args), get("Remove_Failed_Title", null), JOptionPane.ERROR_MESSAGE);
+	 }
+
+	 /** When called this method produces a nice error message on the screen, advising the user that the rename action has failed.
+	  * @param mde_new The <strong>Element</strong> that we are attempting to add.
+	  * @param new_name The name that we attempted to add it under, as a <strong>String</strong>.
+	  * @param reason The phrase key for the reason the rename failed, also as a <strong>String</strong>.
+	  */
+	 public void renameFailed(Element mde_new, String new_name, String reason) {
+		  String args[] = new String[3];
+		  args[0] = mde_new.getAttribute("name");
+		  args[1] = new_name;
+		  args[2] = get(reason, null);
+		  JOptionPane.showMessageDialog(off_screen, get("Rename_Failed", args), get("Rename_Failed_Title", null), JOptionPane.ERROR_MESSAGE);
+	 }
+
+	 /** Method to display a prompt asking the user to select a specific element to merge with.
+	  * @param mds_cur The current <strong>MetadataSet</strong>.
+	  * @return The selected <strong>Element</strong> or <i>null</i> if the user cancels the action.
+	  */
+	 public Element selectElement(MetadataSet mds_cur) {
+		  action = Declarations.NO_ACTION;
+		  // Create
+		  JDialog dialog = new JDialog();
+		  dialog.setModal(true);
+		  dialog.setSize(SELECT_SIZE);
+		  dialog.setTitle(get("Select"));
+		  
+		  JButton ok = new JButton(get("General.OK"));
+		  ok.addActionListener(this);
+		  ok.setMnemonic(KeyEvent.VK_O);
+		  ok.setEnabled(false);
+
+		  Node elements_raw[] = ArrayTools.nodeListToNodeArray(mds_cur.getElements());
+		  ElementWrapper elements[] = new ElementWrapper[elements_raw.length];
+		  for(int i = 0; i < elements_raw.length; i++) {
+				elements[i] = new ElementWrapper((Element)elements_raw[i]);
+		  }
+		  JList list = new JList(elements);
+		  ElementListListener element_list_listener = new ElementListListener(list, ok);
+		  list.addListSelectionListener(element_list_listener);
+		  JPanel content_pane = (JPanel) dialog.getContentPane();
+		  // Layout
+		  JPanel list_pane = new JPanel();
+		  list_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		  list_pane.setLayout(new BorderLayout());
+		  list_pane.add(new JScrollPane(list), BorderLayout.CENTER);
+		  
+		  JPanel button_pane = new JPanel();
+		  button_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
+		  button_pane.setLayout(new GridLayout(1,2));
+		  button_pane.add(ok);
+		  button_pane.add(cancel);
+
+		  content_pane.setLayout(new BorderLayout());
+		  content_pane.add(list_pane, BorderLayout.CENTER);
+		  content_pane.add(button_pane, BorderLayout.SOUTH);
+		  // Display
+		  dialog.setLocation((screen_size.width - SELECT_SIZE.width) / 2, (screen_size.height - SELECT_SIZE.height) / 2);
+		  on_screen = dialog;
+		  off_screen.hide();
+		  on_screen.show();
+		  off_screen.show();
+		  on_screen.dispose();
+		  on_screen = null;	
+		  // Deallocate stuff since JDK1.4 won't.
+		  ok.removeActionListener(this);
+		  ok = null;
+		  elements_raw = null;
+		  elements = null;
+		  list.removeListSelectionListener(element_list_listener);
+		  list = null;
+		  element_list_listener = null;
+		  content_pane = null;
+		  list_pane = null;
+		  button_pane = null;
+		  dialog = null;
+		  // Return selected element.
+		  if(action == Declarations.CANCEL) {
+				return null;
+		  }
+		  return ((ElementWrapper)list.getSelectedValue()).getElement();
+	 }
+
+	 /** Prompts the user to choose how to import a metadata element. Gives the option of renaming the element to a certain value of a certain set, or adding to a selected set.
+	  * @param name The name of the original metadata as a String.
+	  * @param set The set previously choosen as the default set for this metadata (which it doesn't match somehow).
+	  * @return An ElementWrapper around the element that it has been matched to.
+	  * @see org.greenstone.gatherer.msm.MSMPrompt.MSMDialog
+	  * @see org.greenstone.gatherer.util.MED
+	  */
+	 public ElementWrapper selectElement(String name) {
+		  dialog_cancelled = false;
+		  result = null;
+		  String args[] = new String[1];
+		  args[0] = name;
+		  // Create
+		  MSMDialog dialog = new MSMDialog();
+		  dialog.setModal(true);
+		  dialog.setSize(SELECT_ELEMENT_SIZE);
+		  dialog.setTitle(get("Select_Element_Title"));
+		  JPanel content_pane = (JPanel) dialog.getContentPane();
+		  JPanel control_pane = new JPanel();
+		  JTextArea instructions = new JTextArea(get("Select_Element_Instructions", args));
+		  instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  instructions.setEditable(false);
+		  instructions.setLineWrap(true);
+		  instructions.setRows(SELECT_LINE_COUNT);
+		  instructions.setWrapStyleWord(true);
+		  JPanel original_pane = new JPanel();
+		  JLabel original_label = new JLabel(get("Select_Element_Original"));
+		  original_label.setPreferredSize(SELECT_LABEL_SIZE);
+		  JTextField original = new JTextField(name);
+		  original.setEditable(false);
+		  JPanel element_pane = new JPanel();
+		  JLabel element_label = new JLabel(get("Select_Element_Element"));
+		  element_label.setPreferredSize(SELECT_LABEL_SIZE);
+		  JComboBox element = new JComboBox();
+		  element.setBackground(Color.white);
+		  JButton add_button = new JButton(get("Select_Element_Add"));
+		  add_button.setEnabled(false);
+		  add_button.setMnemonic(KeyEvent.VK_A);
+		  JButton cancel_button = new JButton(get("General.Cancel"));
+		  cancel_button.setMnemonic(KeyEvent.VK_C);
+		  JButton merge_button = new JButton(get("Select_Element_Merge"));
+		  merge_button.setEnabled(false);
+		  merge_button.setMnemonic(KeyEvent.VK_M);
+		  JButton ignore_button = new JButton(get("Select_Element_Ignore"));
+		  ignore_button.setMnemonic(KeyEvent.VK_I);
+		  JPanel set_pane = new JPanel();
+		  JLabel set_label = new JLabel(get("Select_Element_Set"));
+		  set_label.setPreferredSize(SELECT_LABEL_SIZE);
+		  JComboBox set = new JComboBox(manager.getSets(false)); // Don't include the greenstone metadata set.
+		  set.setBackground(Color.white);
+		  JPanel button_pane = new JPanel();
+		  // Connect
+		  AddListener add_listener = new AddListener(dialog, name, set);
+		  CancelListener cancel_listener = new CancelListener(dialog);
+		  IgnoreListener ignore_listener = new IgnoreListener(dialog);
+		  MergeListener merge_listener = new MergeListener(dialog, element);
+		  SetListener set_listener = new SetListener(set, element, name, add_button, merge_button);
+
+		  add_button.addActionListener(add_listener);
+		  cancel_button.addActionListener(cancel_listener);
+		  merge_button.addActionListener(merge_listener);
+		  ignore_button.addActionListener(ignore_listener);
+		  set.addActionListener(set_listener);
+
+		  // Init controls
+		  if(set.getItemCount() > 0) {
+				// We now try to determine the existing metadata element that is the closest match to the one we are trying to merge.
+				MetadataSet closest_set = null;
+				ElementWrapper closest_element = null;
+				int med = -1;
+				for(int i = 0; i < set.getItemCount(); i++) {
+					 MetadataSet mds = (MetadataSet) set.getItemAt(i);
+					 for(int j = 0; j < mds.size(); j++) {
+						  ElementWrapper mde = new ElementWrapper(mds.getElement(j));
+						  int new_med = MED.LD(name, mde.toString());
+						  if(med == -1 || new_med < med) {
+								med = new_med;
+								closest_element = mde;
+								closest_set = mds;
+						  }
+						  mde = null;
+					 }
+					 mds = null;
+				}
+				if(closest_set != null && closest_element != null) {
+					 set.setSelectedItem(closest_set);
+					 element.setSelectedItem(closest_element);
+					 set_listener.actionPerformed();
+				}
+				else {
+					 set_listener.actionPerformed();
+				}
+				closest_set = null;
+				closest_element = null;
+		  }
+		  merge_button.setEnabled(element.getItemCount() > 0);
+		  // Layout
+		  original_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+		  original_pane.setLayout(new BorderLayout());
+		  original_pane.add(original_label, BorderLayout.WEST);
+		  original_pane.add(original, BorderLayout.CENTER);
+		  set_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+		  set_pane.setLayout(new BorderLayout());
+		  set_pane.add(set_label, BorderLayout.WEST);
+		  set_pane.add(set, BorderLayout.CENTER);
+		  element_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+		  element_pane.setLayout(new BorderLayout());
+		  element_pane.add(element_label, BorderLayout.WEST);
+		  element_pane.add(element, BorderLayout.CENTER);
+		  control_pane.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
+		  control_pane.setLayout(new GridLayout(3,1));
+		  control_pane.add(original_pane);
+		  control_pane.add(set_pane);
+		  control_pane.add(element_pane);
+		  button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
+		  button_pane.setLayout(new GridLayout(1,4));
+		  button_pane.add(add_button);
+		  button_pane.add(merge_button);
+		  button_pane.add(ignore_button);
+		  button_pane.add(cancel_button);
+		  content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		  content_pane.setLayout(new BorderLayout());
+		  content_pane.add(new JScrollPane(instructions), BorderLayout.NORTH);
+		  content_pane.add(control_pane, BorderLayout.CENTER);
+		  content_pane.add(button_pane, BorderLayout.SOUTH);
+		  // Display
+		  dialog.setLocation((screen_size.width - SELECT_ELEMENT_SIZE.width) / 2, (screen_size.height - SELECT_ELEMENT_SIZE.height) / 2);
+		  dialog.show();
+		  // Deallocate everything because JDK1.4 won't.
+		  // Why, oh why did I do this?
+		  add_button.removeActionListener(add_listener);
+		  merge_button.removeActionListener(merge_listener);
+		  ignore_button.removeActionListener(ignore_listener);
+		  add_button = null;
+		  merge_button = null;
+		  ignore_button = null;
+		  add_listener = null;
+		  merge_listener = null;
+		  ignore_listener = null;
+		  // References
+		  args = null;
+		  content_pane = null;
+		  control_pane = null;
+		  instructions = null;
+		  original_pane = null;
+		  original_pane = null;
+		  original = null;
+		  element_pane = null;
+		  element_label = null;
+		  element = null;
+		  set_pane = null;
+		  set_label = null;
+		  set.removeActionListener(set_listener);
+		  set_listener = null;
+		  set = null;
+		  button_pane = null;
+		  dialog.dispose();
+		  dialog.destroy();
+		  dialog = null;
+		  // Dondage.
+		  return (ElementWrapper)result;
+	 }
+
+	 public boolean wasDialogCancelled() {
+		  return dialog_cancelled;
+	 }
+
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+
+	 private String get(String key, String args[]) {
+		  if(key.indexOf(".") == -1) {
+				key = "MSMPrompt." + key;
+		  }
+		  return Gatherer.dictionary.get(key, args);
+	 }
+	 	 
+	 /** Prompts the user to select a metadata set from the given list. Uses the name parameter to attempt to automatically select the correct collection (ie the only collection that has an element with the same name).
+	  * @param name The name of the metadata element whose set name is unknown.
+	  * @return The metadata set the user has selected or null if no set selected.
+	  */
+	 final public MetadataSet selectSet(String name) {
+		  String args[] = new String[1];
+		  args[0] = name;
+		  // Creation
+		  MSMDialog dialog = new MSMDialog();
+		  dialog.setModal(true);
+		  dialog.setSize(SELECT_SET_SIZE);
+		  dialog.setTitle(get("Select_Set_Title"));
+		  JPanel content_pane = (JPanel) dialog.getContentPane();
+		  JPanel control_pane = new JPanel();
+		  JTextArea instructions = new JTextArea(get("Select_Set_Instructions", args));
+		  instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+		  instructions.setEditable(false);
+		  instructions.setLineWrap(true);
+		  instructions.setRows(SELECT_LINE_COUNT);
+		  instructions.setWrapStyleWord(true);
+		  JComboBox set = new JComboBox();
+		  set.setBackground(Color.white);
+		  set.addItem(get("Select_Set_None"));
+		  Vector sets = manager.getSets();
+		  for(int i = sets.size() - 1; i >= 0; i--) {
+				set.addItem(sets.get(i));
+		  }
+		  JButton ok = new JButton(get("General.OK"));
+		  ActionListener ok_listener = new IgnoreListener(dialog);
+		  ok.addActionListener(ok_listener); // Doesn't really ignore. Just disposes()
+		  // Select most likely set.
+		  if(name.indexOf(".") != -1) {
+				String set_name = name.substring(0, name.indexOf("."));
+				MetadataSet metadata_set = manager.getSet(set_name);
+				if(metadata_set != null) {
+					 set.setSelectedItem(metadata_set);
+				}
+				metadata_set = null;
+				set_name = null;
+		  }
+		  else {
+				Vector matches = manager.setsThatContain(name);
+				if(matches.size() == 1) {
+					 set.setSelectedItem(matches.get(0));
+				}
+				matches = null;
+		  }
+		  // Layout
+		  control_pane.setLayout(new GridLayout(2,1));
+		  control_pane.add(set);
+		  control_pane.add(ok);
+		  content_pane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
+		  content_pane.setLayout(new BorderLayout());
+		  content_pane.add(new JScrollPane(instructions), BorderLayout.CENTER);
+		  content_pane.add(control_pane, BorderLayout.SOUTH);
+		  // Display
+		  dialog.setLocation((screen_size.width - SELECT_SET_SIZE.width) / 2, (screen_size.height - SELECT_SET_SIZE.height) / 2);
+		  dialog.show();
+		  Object value = set.getSelectedItem();
+		  if(value instanceof MetadataSet) {
+				return (MetadataSet) value;
+		  }
+		  value = null;
+		  ok.removeActionListener(ok_listener);
+		  ok_listener = null;
+		  ok = null;
+		  content_pane = null;
+		  control_pane = null;
+		  instructions = null;
+		  set = null;
+		  dialog.destroy();
+		  dialog = null;
+		  return null;
+	 }
+
+	 private class AddListener 
+		  implements ActionListener {
+		  private JComboBox set = null;
+		  private JDialog dialog = null;
+		  private String name = null;
+		  public AddListener(JDialog dialog, String name, JComboBox set) {
+				this.dialog = dialog;
+				this.name = name;
+				this.set = set;
+		  }
+		  public void actionPerformed(ActionEvent event) {
+				// Get the currently selected metadata set.
+				MetadataSet mds = (MetadataSet) set.getSelectedItem();
+				String n = name;
+				// If we've been forced to go this far then any given namespace is complete bollocks.
+				while(n.indexOf(".") != -1 && !n.equals(".")) {
+					 n = n.substring(n.indexOf(".") + 1);
+				}
+				// However, before we attempt to add a new element to the set, we should check that none already exists.
+				Element element = mds.getElement(name);
+				if(element == null) {
+					 result = mds.addElement(n);
+				}
+				else {
+					 result = (ElementWrapper) element;
+				}
+				mds = null;
+				n = null;
+				element = null;
+				dialog.dispose();
+		  }
+	 }
+	 /** This listener listens for selections within the select element to merge prompt, and once one has been made enables the ok button.*/
+	 private class ElementListListener 
+		  implements ListSelectionListener {
+		  /** The button we either enable or disable depending on user selection. */
+		  private JButton ok = null;
+		  /** The list from whom we are listening for selection events. */
+		  private JList list = null;
+		  /** Constructor.
+			* @param list The <strong>JList</Strong> from whom we are listening for selection events.
+			* @param ok The <Strong>JButton</strong> we either enable or disable depending on user selection.
+			*/
+		  public ElementListListener(JList list, JButton ok) {
+				this.list = list;
+				this.ok = ok;
+		  }
+		  /** Any implementation of <i>ListSelectionListener</i> must include this method so we can be informed when a list selection event has occured.
+			* @param event A <strong>ListSelectionEvent</strong> generated by the event.
+			*/
+		  public void valueChanged(ListSelectionEvent event) {
+				if(list.getSelectedValue() != null) {
+					 ok.setEnabled(true);
+				}
+				else {
+					 ok.setEnabled(false);
+				}
+		  }
+	 }
+
+	 private class CancelListener
+		  implements ActionListener {
+		  private JDialog dialog = null;
+		  public CancelListener(JDialog dialog) {
+				this.dialog = dialog;
+		  }
+		  public void actionPerformed(ActionEvent event) {
+				dialog_cancelled = true;
+				dialog.dispose();
+		  }		  
+	 }
+
+	 private class IgnoreListener 
+		  implements ActionListener {
+		  private JDialog dialog = null;
+		  public IgnoreListener(JDialog dialog) {
+				this.dialog = dialog;
+		  }
+		  public void actionPerformed(ActionEvent event) {
+				dialog.dispose();
+		  }
+	 }
+
+	 private class MergeListener 
+		  implements ActionListener {
+		  private JComboBox element = null;
+		  private JDialog dialog = null;
+		  public MergeListener(JDialog dialog, JComboBox element) {
+				this.dialog = dialog;
+				this.element = element;
+		  }
+		  public void actionPerformed(ActionEvent event) {
+				// Return the currently selected element
+				result = (ElementWrapper)element.getSelectedItem();
+				dialog.dispose();
+		  }
+	 }
+
+	 private class MSMDialog
+		  extends JDialog {
+		  public void destroy() {
+				rootPane = null;
+		  }
+	 }
+
+	 private class SetListener 
+		  implements ActionListener {
+		  private JButton add_button = null;
+		  private JButton merge_button = null;
+		  private JComboBox element = null;
+		  private JComboBox set = null;
+		  private String name = null;
+		  public SetListener(JComboBox set, JComboBox element, String name, JButton add_button, JButton merge_button) {
+				this.add_button = add_button;
+				this.element = element;
+				this.merge_button = merge_button;
+				this.name = name.toLowerCase();
+				this.set = set;
+		  }
+		  public void actionPerformed() {
+				element.removeAllItems();
+				MetadataSet mds = (MetadataSet) set.getSelectedItem();
+				System.err.println("Set selected: " + mds);
+				if(mds != null) {
+					 NodeList elements = mds.getElements();
+					 Vector temp = new Vector();
+					 for(int i = elements.getLength() - 1; i >= 0; i--) {
+						  temp.add(new ElementWrapper((Element)elements.item(i)));
+					 }
+					 
+					 // The add button is only enabled if an element with the same name doesn't already exist in the destination set.
+					 boolean add_button_enabled = true;
+					 ///ystem.err.println("Checking for " + name);
+					 for(int j = 0; j < temp.size(); j++) {
+						  ElementWrapper an_element = (ElementWrapper)temp.get(j);
+						  // Can only add if no file with the same name exists.
+						  String check = an_element.toString().toLowerCase();
+						  int position = -1;
+						  if((position = check.indexOf(".")) != -1) {
+								check = check.substring(position + 1);
+						  }
+						  ///ystem.err.println("does it match " + check + "? " + name.equals(check));
+						  add_button_enabled = add_button_enabled && !name.equals(check);
+						  check = null;
+						  element.addItem(an_element);
+						  an_element = null;
+					 }
+					 add_button.setEnabled(add_button_enabled);
+
+					 // The merge button is only enabled if there is more than one element in the destination set.
+					 if(temp.size() > 0) {
+						  merge_button.setEnabled(true);
+					 }
+					 else {
+						  merge_button.setEnabled(false);
+					 }
+					 temp = null;
+					 elements = null;
+				}
+				else {
+					 add_button.setEnabled(false);
+					 merge_button.setEnabled(false);
+				}
+				mds = null;
+		  }
+		  public void actionPerformed(ActionEvent item) {
+				actionPerformed();
+		  }  
+	 }
+}
+
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/MSMUtils.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/MSMUtils.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/MSMUtils.java	(revision 13666)
@@ -0,0 +1,851 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* GPL_HEADER */
+package org.greenstone.gatherer.msm;
+/**************************************************************************************
+ * 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 
+ * @author John Thompson, Greenstone Digital Libraries
+ * @version 2.3
+ **************************************************************************************/
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.TreeSet;
+import java.util.Vector;
+import org.greenstone.gatherer.cdm.CommandTokenizer;
+import org.greenstone.gatherer.mem.Attribute;
+import org.greenstone.gatherer.msm.MetadataSet;
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.valuetree.GValueModel;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+/** This class contains a plethora of methods associated with handling the content of <strong>MetadataSet</strong>s and the <strong>Element</strong>s within. For example this is where you will find methods for comparing various parts of two <strong>MetadataSet</strong>s for equality. It also has methods for extracting common and useful data from <strong>Element</strong>s such as the AssignedValue nodes.
+ * @author John Thompson, Greenstone Digital Libraries
+ * @version 2.3
+ */
+public class MSMUtils {
+	 /** An element of the enumeration of type filter. */
+	 static public final int NONE = 0;
+	 /** An element of the enumeration of type filter. */
+	 static public final int VALUES = 1;
+	 /** An element of the enumeration of type filter. */
+	 static public final int ALIASES = 2;
+	 /** An element of the enumeration of type filter. */
+	 static public final int BOTH = 3;
+	 /** The character used to separate name space from metadata element. */
+	 static public final char NS_SEP= '.';
+	 /** Method to add one node as a child of another, after migrating into the target document.
+	  * @param parent The <strong>Node</strong> we are inserting into.
+	  * @param child The original <strong>Node</strong> we are inserting. Must first be cloned into the parents document.
+	  */
+	 static final public void add(Node parent, Node child) {
+		  Document document = parent.getOwnerDocument();
+		  Node new_child = document.importNode(child, true);
+		  parent.appendChild(new_child);
+	 } 
+
+	 static final public void addElementAttribute(Node node, String name, String language, String value) {
+		  Document document = node.getOwnerDocument();
+		  Element attribute_node = document.createElementNS("", "Attribute");
+		  attribute_node.setAttribute("name", name);
+		  attribute_node.setAttribute("language", language);
+		  node.appendChild(attribute_node);
+		  Node attribute_text = document.createTextNode(value);
+		  attribute_node.appendChild(attribute_text);
+	 }
+
+	 /** A method for comparing two AssignedValues trees. This compares not only the Subject hierarchies but also the values themselves.
+	  * @param avt A <strong>Node</strong> which is the root of an AssignedValues tree.
+	  * @param bvt The <strong>Node</strong> which is the root of the tree we wish to compare it to.
+	  * @return <i>true</i> if the two trees are equal, <i>false</i> otherwise.
+	  */
+	 static final public boolean assignedValuesEqual(Node avt, Node bvt) {
+		  if(avt == null && bvt == null) {
+				return true; // Both are null so both are equal.
+		  }
+		  else if(avt == null || bvt == null) {
+				// One is null and the other isn't.
+				return false;
+		  }
+		  else {
+				Hashtable a_map = new Hashtable();
+				getValueMappings(avt, null, a_map);
+				Hashtable b_map = new Hashtable();
+				getValueMappings(bvt, null, b_map);
+				if(a_map.size() == b_map.size()) {
+					 /** @TODO - Figure out what to do now. */
+					 return true;
+				}
+		  }
+		  return false;
+	 }
+	 /** A method for comparing two attribute nodes of type Node not Attr as you might think. Attr objects are used to describe the attributes of tags themselves, while in a metadata set we intend attribute nodes to describe qualities of metadata elements. It's just confusing because the two systems (DOM model and Dublin Core) are quite similar.
+	  * @param an A <strong>Node</strong> representing some attribute of an element.
+	  * @param bn The <strong>Node</strong> we wish to compare it to.
+	  * @return <i>true</i> if and only if the attributes are equal.
+	  */
+	 static final public boolean attributesEqual(Node an, Node bn) {
+		  // Check we are comparing apples and apples...
+		  if(an.getNodeName().equals("Attribute") && bn.getNodeName().equals("Attribute")) {
+				Element ae = (Element) an;
+				Element be = (Element) bn;
+				// Ensure we are comparing the same type of attribute.
+				if(ae.getAttribute("name").equals(be.getAttribute("name"))) {
+					 // And finally retrieve and compare the values.
+					 if(getValue(ae).equals(getValue(be))) {
+						  // We have a match.
+						  return true;
+					 }
+				}
+		  }
+		  // And if anything goes wrong we can't be dealing with equal attributes.
+		  return false;
+	 }
+	 /** Method to determine if a certain path of elements can be found in another tree. This method tests by comparing node names, and finally the #text node past the leaf end of the path.
+	  * @param tree The root <strong>Node</strong> of the tree to be searched.
+	  * @param path The <strong>Node[]</strong> path to be found.
+	  * @return <i>true</i> if the path was found (including matching #text elements at the leaf), or <i>false</i> otherwise.
+	  */
+	 static final public boolean containsPath(Node tree, Node path[]) {
+		  // If there is no tree then there are no values.
+		  if(tree == null) {
+				return false;
+		  }
+		  // Ensure we are comparing equivent things.
+		  if(tree.getNodeName().equals("AssignedValues") && path[0].getNodeName().equals("AssignedValues")) {
+				int index = 1;
+				while(index < path.length && tree != null) {
+					 Node next = null;
+					 for(Node n = tree.getFirstChild(); n != null && next == null; n = n.getNextSibling()) {
+						  if(n.getNodeName().equals(path[index].getNodeName())) {
+								next = n;
+								index++;
+						  }
+						  tree = next;
+					 }
+				}
+				// Tree may now be pointing at the same node as 
+				// path[path.length - 1] so we should test their child text nodes.
+				if(tree != null) {
+					 Node tree_text = tree.getFirstChild();
+					 Node path_text = path[path.length - 1].getFirstChild();
+					 if(tree_text.getNodeValue().equals(path_text.getNodeValue())) {
+						  // Path found!
+						  return true;
+					 }
+				}
+		  }
+		  return false;		 
+	 }
+	 /** Method to compare two metadata elements (of type Element, which is bound to get more than a bit confusing) for equality. This test may only check the structural (ie pretty much unchanging) consistancy, or may include the AssignedValue tree as well (which will be different for each collection I'd imagine).
+	  * @param a_set The <strong>MetadataSet</strong> a comes from.
+	  * @param a An <strong>Element</strong>.
+	  * @param b_set The <strong>MetadataSet</strong> b comes from.
+	  * @param b The <strong>Element</strong> to compare it to.
+	  * @param values <i>true</i> if the AssignedValues tree should also be compared, <i>false</i> otherwise.
+	  * @return <i>true</i> if the elements are equal, <i>false</i> otherwise.
+	  */
+	 static final public boolean elementsEqual(MetadataSet a_set, Element ae, MetadataSet b_set, Element be, boolean values) {
+		  // Compare Element Attr(ibutes) within the DOM, not to be confused with comparing element attributes in a Dublin Core sense...
+		  NamedNodeMap aas = ae.getAttributes();
+		  NamedNodeMap bas = be.getAttributes();
+		  // For each attribute in a...
+		  for(int i = 0; i < aas.getLength(); i++) {
+				Attr aa = (Attr)aas.item(i);
+				// Try to retrieve an attribute of the same name from b.
+				Attr ba = (Attr)bas.getNamedItem(aa.getNodeName());
+				// Now if there was no such attribute, or if the values for the
+ 				// two attributes are different the structures different.
+				if(ba == null || (!aa.getValue().equals(ba.getValue()))) {
+					 //ystem.err.println("Attributes are not equal");
+					 return false;
+				}
+		  }
+		  // Quickest test of children is to see we have the same number in
+		  // each. Remember to modify for missing AssignedValues which have
+		  // nothing to do with structure.
+		  int anc = getAttributeCount(ae);
+		  int bnc = getAttributeCount(be);
+		  if(anc != bnc) {
+				return false;
+		  }
+		  // Now we compare the child nodes of the two Elements taking into 
+		  // account three special cases...
+		  // 1. We don't test the AssignedValues element here.
+		  // 2. Remember OptionList node.
+		  // 3. The Attributes of each metadata element.
+		  // For each child node of a.
+		  for(Node an = ae.getFirstChild(); an !=null; an =an.getNextSibling()) {
+				if(an.getNodeName().equals("OptionList")) {
+					 //ystem.err.println("Matching OptionLists.");
+					 Node bn = getNodeFromNamed(be, "OptionList");
+					 if(bn == null || !optionListsEqual(an, bn)) {
+						  //ystem.err.println("OptionLists are not equal");
+						  return false;
+					 }
+				}
+				// Matching attributes.
+				else if(an.getNodeName().equals("Attribute")) {
+					 //ystem.err.println("Matching Attributes.");
+					 boolean matched = false;
+					 for(Node bn = be.getFirstChild(); bn != null && !matched;
+						  bn = bn.getNextSibling()) {
+						  if(bn.getNodeName().equals("Attribute")) {
+								matched = attributesEqual(an, bn);
+						  }
+					 }
+					 if(!matched) {
+						  //ystem.err.println("Cannot match attribute.");
+						  return false;
+					 }
+				}
+		  }
+		  // Finally, if we've been asked to compares value trees (for some unknown reason) go ahead and compare them too.
+		  if(values) {
+				GValueModel avt = a_set.getValueTree(new ElementWrapper(ae));
+				GValueModel bvt = b_set.getValueTree(new ElementWrapper(be));
+				return assignedValuesEqual(avt.getDocument().getDocumentElement(), bvt.getDocument().getDocumentElement());
+		  }
+		  // If we've got this far the elements match!
+		  return true;
+	 }	
+	 /** This method extracts the assigned value trees details, if any, from a certain element and stores them in an array ready to be passed as arguments to the Dictionary.
+	  * @param element The <strong>Element</strong> whose values we wish to view.
+	  * @return A <strong>String[]</strong> containing the details of the assigned values tree.
+	  * @see org.greenstone.gatherer.Dictionary
+	  */
+	 static final public String[] getAssignedValuesDetails(MetadataSet mds, Element element) {
+		  String details[] = null;
+		  //Node avt = getNodeFromNamed(element, "AssignedValues");
+		  GValueModel avt = mds.getValueTree(new ElementWrapper(element));
+		  if(avt != null) {
+				Hashtable mapping = new Hashtable();
+				getValueMappings(avt.getDocument().getDocumentElement(), null, mapping);
+				ArrayList values = new ArrayList(mapping.keySet());
+				Collections.sort(values);
+				details = new String[1];
+				for(int i = 0; i < values.size(); i++) {
+					 if(details[0] == null) {
+						  details[0] = "   " + values.get(i);
+					 }
+					 else {
+						  details[0] = details[0] + "\n   " + values.get(i);
+					 }
+				}
+				mapping = null;
+				values = null;
+		  }
+		  avt = null;
+		  return details;
+	 }
+
+	 static final public TreeSet getAttributes(Element element) {
+		  TreeSet attributes = new TreeSet();
+		  for(Node n = element.getFirstChild(); n != null; n = n.getNextSibling()) {
+				if(n.getNodeName().equals("Attribute")) {
+					 Element e = (Element)n;
+					 attributes.add(new Attribute(e.getAttribute("name"), e.getAttribute("language"), getValue(e)));
+				}
+		  }
+		  return attributes;
+	 }
+
+	 /** Method to count the number of Attribute nodes under a certain Element. This ignores other nodes such as #text, OptionList and AssignedValues nodes.
+	  * @param element The <strong>Element</strong> whose attributes you want to count.
+	  * @return An <i>int</i> which is the number of attribute nodes.
+	  */
+	 static final public int getAttributeCount(Node element) {
+		  int count = 0;
+		  for(Node n = element.getFirstChild(); n != null; 
+				n = n.getNextSibling()) {
+				if(n.getNodeName().equals("Attribute")) {
+					 count++;
+				}
+		  }
+		  return count;
+	 }
+
+	 /*************************************************************************/
+	 
+	 /** This method is a slight variation on getNodeNamed in that it is especially written to retrieve the attribute Nodes of a certain name present under the given element. Note that this method is language specific.
+	  * @param element The target element <strong>Node</strong>.
+	  * @param name The name of the attribute you wish to return.
+	  * @return An <strong>Element[]</strong> containing the attributes you requested, or <i>null</i> if no such attributes exists.
+	  */
+	 static final public Element getAttributeNodeNamed(Node element, String name) { 
+		  Element attribute = null;
+		  String language_code = Locale.getDefault().getLanguage();
+		  for(Node n = element.getFirstChild(); n != null; n = n.getNextSibling()) {
+				if(n.getNodeName().equals("Attribute")) {
+					 Element e = (Element)n;
+					 if(e.getAttribute("name").equals(name)) {
+						  if(e.getAttribute("language").equalsIgnoreCase(language_code)) {
+								return e;
+						  }
+						  else if(e.getAttribute("language").equalsIgnoreCase("en")) {
+								attribute = e;
+						  }
+						  else if(attribute == null) {
+								attribute = e;
+						  }
+					 }
+					 e = null;
+				}
+		  }
+		  return attribute;
+	 }
+
+	 /** This method is a slight variation on getNodeNamed in that it is especially written to retrieve the attribute Nodes of a certain name present under the given element.
+	  * @param element The target element <strong>Node</strong>.
+	  * @param name The name of the attribute you wish to return.
+	  * @return An <strong>Element[]</strong> containing the attributes you requested, or <i>null</i> if no such attributes exists.
+	  */
+	 static final public Element[] getAttributeNodesNamed(Node element, String name) { 
+		  Element attributes[] = null;
+		  for(Node n = element.getFirstChild(); n != null; n = n.getNextSibling()) {
+				if(n.getNodeName().equals("Attribute")) {
+					 Element e = (Element)n;
+					 if(e.getAttribute("name").equals(name)) {
+						  if(attributes == null) {
+								attributes = new Element[1];
+								attributes[0] = e;
+						  }
+						  else {
+								Element temp[] = attributes;
+								attributes = new Element[temp.length + 1];
+								System.arraycopy(temp, 0, attributes, 0, temp.length);
+								attributes[temp.length] = e;
+								temp = null;
+						  }
+					 }
+					 e = null;
+				}
+		  }
+		  return attributes;
+	 }
+
+	 /** Method to construct an elements description by retrieving the correct attribute.
+	  * @param element The <strong>Element</strong> whose name we wish to retrieve.
+	  * @return A <strong>String</strong> which is the elements description, or an empty string if no description exists.
+	  */
+	 static final public String getDescription(Node element) {
+		  String definition = "";
+		  Element definition_node = getAttributeNodeNamed(element, "definition");
+		  if(definition_node != null) {
+				definition = getValue(definition_node);
+		  }
+		  String comment = "";
+		  Element comment_node = getAttributeNodeNamed(element, "comment");
+		  if(comment_node != null) {
+				comment = getValue(comment_node);
+		  }
+		  String description = definition + comment;
+		  return Utility.stripNL(description.trim());
+	 }
+
+	 /** Extracts the file name pattern from within a fileset of a Greenstone Directory Metadata model.
+	  * @param fileset The fileset Node in question.
+	  * @return The pattern as a String.
+	  */
+	 static final public String getFileNamePattern(Node fileset) {
+		  // Locate the child node called filename
+		  for(Node child = fileset.getFirstChild(); child != null; child = child.getNextSibling()) {
+				if(child.getNodeName().equalsIgnoreCase("FileName")) {
+					 // Find the file string.
+					 return MSMUtils.getValue(child);
+				}
+		  }		  
+		  return null;
+	 }
+
+	 /*************************************************************************/
+	 /** Method to create the fully namespace quantified identifier for this element.
+	  * @param element The <strong>Node</strong> in question.
+	  * @return A fully qualified identifier as a <strong>String</strong>
+	  */
+	 static final public String getFullIdentifier(Node element) {
+		  if(element == null) {
+				return "Error";
+		  }
+		  // Get namespace for given element.
+		  Element root = (Element)element.getParentNode();
+		  if(root != null) {
+				String identifier = root.getAttribute("namespace");
+				// Get name and return it.
+				if(identifier.equals("")) {
+					 identifier = Utility.EXTRACTED_METADATA_NAMESPACE;
+				}
+				return identifier + NS_SEP + getIdentifier(element);
+		  }
+		  return getIdentifier(element); // No namespace anymore
+	 } // static public String getFullIdentier(Node element)
+
+	 /*************************************************************************/
+	 /** Method to construct an elements fully qualified name. Note that this is different from a nodes identifier. Think of name as a short, unique reference to an metadata element, whereas identifier can be much longer, language specific and non-unique.
+	  * @param element An <strong>Element</strong> whose name we are interested in.
+	  * @return A <strong>String</strong> representing this given elements fully namespace qualified name.
+	  */
+	 static final public String getFullName(Element element) {
+		  if(element == null) {
+				return null;
+		  }
+		  // Get namespace for given element.
+		  Element root = (Element)element.getParentNode();
+		  String identifier = root.getAttribute("namespace") + NS_SEP + element.getAttribute("name");
+		  // Get name and return it.
+		  if(identifier.startsWith(".")) {
+				identifier = identifier.substring(1);
+		  }
+		  return identifier;
+	 } // static public String getFullName(Element element)
+
+	 /** Method to construct an elements identifier by retrieving the correct attribute. Language specific, based on default Locale.
+	  * @param element The <strong>Element</strong> whose name we wish to retrieve.
+	  * @return A <strong>String</strong> which is the elements identifier, or an empty string if no identifier exists.
+	  */
+	 static final public String getIdentifier(Node element) {
+		  String identifier = null;
+		  // Determine locale code.
+		  String language_code = Locale.getDefault().getLanguage();
+		  // Get the 'identifier' Element with the correct locale
+		  for(Node node = element.getFirstChild(); node != null;
+				node = node.getNextSibling()) {
+				if(node.getNodeName().equals("Attribute")) {
+					 Element target = (Element)node;
+					 if(target.getAttribute("name").equals("identifier")) {
+						  Node text = target.getFirstChild();
+						  if(target.getAttribute("language").equalsIgnoreCase(language_code)) {
+								return text.getNodeValue();
+						  }
+						  else if(target.getAttribute("language").equalsIgnoreCase("en")) {
+								identifier = text.getNodeValue();
+						  }
+						  else if(identifier == null) {
+								identifier = text.getNodeValue();
+						  }
+						  text = null;
+					 }
+					 target = null;
+				}
+		  }
+		  language_code = null;
+		  // We may have harvested some identifier from the file.
+		  if(identifier != null) {
+				return identifier;
+		  }
+		  // Failing the above we return the nodes name instead.
+		  return ((Element)element).getAttribute("name");
+	 }
+
+	 /** Retrieve the metadata description element from this fileset node.
+	  * @param fileset The fileset in question.
+	  * @return The description node or null if no such node.
+	  */
+	 static final public Node getMetadataDescription(Node fileset) {
+		  // Locate the child node called filename
+		  for(Node child = fileset.getLastChild(); child != null; child = child.getPreviousSibling()) {
+				if(child.getNodeName().equalsIgnoreCase("Description")) {
+					 return child;
+				}
+		  }		  
+		  return null;
+	 }
+
+	 /** 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.
+	  */ 
+	 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;
+	 }
+	 /** Look for the occurances 'field' of the element and return it if found.
+	  * @return An <i>int</i> which matches the number in the occurances attribute of the element, or 0 if no such attribute.
+	  */
+	 static final public int getOccurances(Element element) {
+		  int count = 0;
+		  String number = null;
+		  if((number = element.getAttribute("occurances")) != null) {
+				try {
+					 count = Integer.parseInt(number);
+				}
+				catch(Exception error) {
+					 count = 0;
+				}
+		  }
+		  return count;
+	 }	 
+	 /** This method extracts the option list details, if any, from a certain element and stores them in an array ready to be passed as arguments to the <strong>Dictionary</strong>.
+	  * @param element The <strong>Element</strong> whose option list we wish to view.
+	  * @return A <strong>String[]</strong> containing the details of the option list.
+	  * TODO implement.
+	  * @see org.greenstone.gatherer.Dictionary
+	  */
+	 static final public String[] getOptionListDetails(Element element) {
+		  return null;
+	 }
+
+	 /** This method traces the path between the 'root' node given and the target node. This path is returned starting at the root.
+	  * @param root The root <strong>Node</strong> to start this path at.
+	  * @param target The final <strong>Node</strong> to end up at.
+	  * @return A <strong>Node[]</strong> that contains the sequence of nodes from root to target.
+	  */
+	 static final public Node[] getPath(Node root, Node target) {
+		  if(root == target) {
+				return ArrayTools.add(null, root);
+		  }
+		  else {
+				return ArrayTools.add(getPath(root, target.getParentNode()), target);
+		  }
+	 }
+
+	 /** This method extracts the structural details from a certain element and stores them in an array, all ready for passing to the <strong>Dictionary</strong>.
+	  * @param element The <Strong>Element</strong> whose details we wish to gather.
+	  * @return A <strong>String[]</strong> containing the structural details.
+	  */
+	 static final public String[] getStructuralDetails(Element element) {
+		  String details[] = new String[4];
+		  Element root = (Element)element.getParentNode();
+		  details[0] = root.getAttribute("name");
+		  details[1] = root.getAttribute("namespace");
+		  details[2] = getFullName(element);
+		  details[3] = null;
+		  // Get attributes
+		  Vector attributes = new Vector();
+		  for(Node n=element.getFirstChild(); n!=null; n=n.getNextSibling()) {
+				if(n.getNodeName().equals("Attribute")) {
+					 Element temp = (Element)n;
+					 attributes.add(temp.getAttribute("name") + "=" + getValue(n));
+				}
+		  }
+		  // Sort attributes
+		  Collections.sort(attributes);
+		  // Add attributes to details.
+		  for(int i = 0; i < attributes.size(); i++) {
+				if(details[3] == null) {
+					 details[3] = "   " + attributes.get(i);
+				}
+				else {
+					 details[3] = details[3] + "\n   " + attributes.get(i);
+				}
+		  }
+		  return details;
+	 }
+
+	 /** Method to retrieve the value of a given node (not the assigned values tree!).
+	  * @param element The <strong>Element</strong> whose value we wish to find.
+	  * @return The value found as a <strong>String</strong>, or <i>null</i> if this element has no value.
+	  */
+	 static final public String getValue(Node element) {
+		  // If we've been given a subject node first retrieve its value node.
+		  if(element.getNodeName().equals("Subject")) {
+				element = getNodeFromNamed(element, "Value");
+		  }
+		  if(element != null && element.hasChildNodes()) {
+				Node text = element.getFirstChild();
+				return text.getNodeValue();
+		  }
+		  return "";
+	 }
+
+	 /** Method to traverse the given value tree, and build up a hashtable of mappings between the value path key names and the Subject nodes of the tree.
+	  * @param current The root <strong>Node</strong> of a subtree of the AssignedValues tree.
+	  * @param prefix The value path key <strong>String</string>, which shows the path from the root of the AssignedValue tree to <i>current</i>s parent using '\' as a separator.
+	  * @param values A <strong>Hashtable</strong> containing the mapping discovered so far in our tree traversal.
+	  */ 
+	 static final public void getValueMappings(Node current, String prefix, Hashtable values) {
+		  if(current != null) {
+				String name = current.getNodeName();
+				String new_prefix = prefix;
+				// If we've found the outer layer of a new value, add it to our
+				// mapping.
+				if(name.equals("Subject")) {
+					 Node value_node = getNodeFromNamed(current, "Value");
+					 String value = getValue(value_node);
+					 if(new_prefix != null) {
+						  new_prefix = new_prefix + "\\" + value;
+					 }
+					 else {
+						  new_prefix = value;
+					 }
+					 values.put(new_prefix, current);
+				}
+				if(name.equals("Subject") || name.equals("AssignedValues")) {
+					 for(Node child = current.getFirstChild(); child != null;
+						  child = child.getNextSibling()) {
+						  getValueMappings(child, new_prefix, values);
+					 }
+				}
+		  }
+	 }
+	 /** Parses the value tree template file.
+	  * @return The Document parsed.
+	  */
+	 static final public Document getValueTreeTemplate() {
+		  return Utility.parse(Utility.METADATA_VALUE_TEMPLATE, true);
+	 }
+	 /** Method to compare two OptionsLists for equality.
+	  * @param al A <strong>Node</strong> which represents an OptionList.
+	  * @param bl The <strong>Node</strong> we wish to test against.
+	  * @return A <i>boolean</i> which is <i>true</i> if the two option lists are equal, <i>false</i> otherwise.
+	  * TODO Implementation
+	  */
+	 static final public boolean optionListsEqual(Node al, Node bl) {
+		  // Compare the 'restricted' attribute of the two lists.
+		  Element ae = (Element) al;
+		  Element be = (Element) bl;
+		  if(!ae.getAttribute("restricted").equals
+			  (be.getAttribute("restricted"))) {
+				return false;
+		  }
+		  // Compare the Values under each list.
+		  for(Node an = al.getFirstChild(); an != null; 
+				an = an.getNextSibling()){
+				if(an.getNodeName().equals("Value")) {
+					 boolean matched = false;
+					 for(Node bn = bl.getFirstChild(); bn != null && !matched;
+						  bn = bn.getNextSibling()) {
+						  if(bn.getNodeName().equals("Value")) {
+								matched = valuesEqual(an, bn);
+						  }
+					 }
+					 if(!matched) {
+						  return false;
+					 }
+				}
+		  }
+		  return true;
+	 }
+
+	 static final public void setIdentifier(Node element, String value) {
+		  // Get the 'identifier' Element
+		  for(Node node = element.getFirstChild(); node != null;
+				node = node.getNextSibling()) {
+				if(node.getNodeName().equals("Attribute")) {
+					 Element target = (Element)node;
+					 if(target.getAttribute("name").equals("identifier")) {
+						  Node text = target.getFirstChild();
+						  text.setNodeValue(value);
+					 }
+				}
+		  }
+	 }
+	 /** Set the value of the element attribute occurances.
+	  * @param element The <strong>Element</strong> to change.
+	  * @param value The value to change by as an <i>int</i>.
+	  */
+	 static final public void setOccurance(Element element, int value) {
+		  Integer new_value = new Integer(getOccurances(element) + value);
+		  element.setAttribute("occurances", new_value.toString());
+	 }
+	 /** This method also traverses the tree, but this one is used to gather all the values and aliases at once, and to 'prune' the tree if necessary.
+	  * @param current The current root <strong>Node</strong> of this AssignedValues tree subtree.
+	  * @param return_filter This <i>int</i> specifies what nodes from the tree should be returned, where;<br>VALUES  = return values only<br>ALIASES = return aliases only<br>BOTH    = return both values and aliases<br>NONE    = return nothing.
+	  * @param remove_leaves A leaf node is a subject that contains no child subjects. If this <i>boolean</i> is set to <i>true</i> then the leaf nodes will be removed from the tree. 
+	  * @return A <strong>Node[]</strong> containing whatever values or aliases have been found during the trees traversal.
+	  */
+	 static final public Node[] traverseTree(Node current, int return_filter, boolean remove_leaves) {
+		  Node leaves[] = null;
+		  String name = current.getNodeName();
+		  if(name.equals("Value") && (return_filter == VALUES || return_filter == BOTH)) {
+				leaves = ArrayTools.add(leaves, current);
+		  }
+		  else if(name.equals("Alias") && (return_filter == ALIASES || return_filter == BOTH)) {
+				leaves = ArrayTools.add(leaves, current);
+		  }
+		  else if(name.equals("Subject")) {
+				boolean has_subject_child = false;
+				Node children[] = ArrayTools.nodeListToNodeArray(current.getChildNodes());
+				for(int i = 0; i < children.length; i++) {
+					 if(children[i].getNodeName().equals("Subject")) {
+						  has_subject_child = true;
+					 }
+					 leaves = ArrayTools.add(leaves, traverseTree(children[i], return_filter, remove_leaves));
+				}
+				if(!has_subject_child && remove_leaves) {
+					 Node parent = current.getParentNode();
+					 parent.removeChild(current);
+				}
+		  }
+		  else if(name.equals("AssignedValues")) {
+				Node children[] = ArrayTools.nodeListToNodeArray(current.getChildNodes());
+				for(int i = 0; i < children.length; i++) {
+					 leaves = ArrayTools.add(leaves, traverseTree(children[i], return_filter, remove_leaves));
+				}
+		  }															  
+		  return leaves;
+	 }
+
+	 /** This method is used to systematically merge two AssignedValues tree. Both trees have their current values mapped, then the new tree is searched for key paths that don't exist in the current tree. If such a key is found, the Subject <strong>Node</strong> it maps to is retrieved and then imported and added to whatever was the closest available node (in terms of tree path) in the current tree.
+	  * @param a_set The MetadataSet from which the Element a came from.
+	  * @param a The Element at the root of the current AssignedValues tree.
+	  * @param b_set The MetadataSet from which the Element b came from.
+	  * @param b The root Element of the tree that is being merged.
+	  * @return A <i>boolean</i> which is <i>true</i> if the trees merged without error, <i>false</i> otherwise.
+	  */
+	 static final public boolean updateValueTree(MetadataSet a_set, Element a, MetadataSet b_set, Element b) {
+		  GValueModel avt = a_set.getValueTree(new ElementWrapper(a));
+		  GValueModel bvt = b_set.getValueTree(new ElementWrapper(b));
+		  // If neither element even has a value tree, we're all done.
+		  if(avt == null && bvt == null) {
+				avt = null;
+				bvt = null;
+				return true;
+		  }
+		  // If the new element has no value tree then nothing needs to be done.
+		  else if(avt != null && bvt == null) {
+				avt = null;
+				bvt = null;
+				return true;
+		  }
+		  // If only the new element has a value tree, then add all of its values
+		  // immediately.
+		  else if(avt == null && bvt != null) {
+				a_set.addValueTree(new ElementWrapper(a), bvt);
+				avt = null;
+				bvt = null;
+				return true;
+		  }
+		  // We have both trees for both elements, time to merge.
+		  else {
+				Document document = avt.getDocument();
+				Hashtable a_map = new Hashtable();
+				getValueMappings(document.getDocumentElement(), null, a_map);
+				Hashtable b_map = new Hashtable();
+				getValueMappings(bvt.getDocument().getDocumentElement(), null, b_map);
+				// For each new entry in b_map
+				for(Enumeration b_keys = b_map.keys(); b_keys.hasMoreElements(); ) {
+					 String b_key = (String)b_keys.nextElement();
+					 // Test if there is already an entry in a_map.
+					 if(!a_map.containsKey(b_key)) {
+						  // If not, search through a_map for the longest match.
+						  Node target = document.getDocumentElement();
+						  String last_match = null;
+						  for(Enumeration a_keys = a_map.keys(); 
+								a_keys.hasMoreElements(); ) {
+								String a_key = (String)a_keys.nextElement();
+								if(b_key.startsWith(a_key)) {
+									 if(last_match == null || a_key.length() > last_match.length()) {
+										  last_match = a_key;
+										  target = (Node)a_map.get(a_key);
+									 }
+								}
+								a_key = null;
+						  }
+						  // Now import the node at b_key and add it to target.
+						  Node subtree = (Node)b_map.get(b_key);
+						  subtree = document.importNode(subtree, true);
+						  // Find the node to insert before...
+						  String name = getValue(subtree);
+						  Node move = null;
+						  for(Node n = target.getFirstChild(); n != null && move == null; n = n.getNextSibling()) {
+								if(n.getNodeName().equals("Subject")) {
+									 if(name.compareTo(getValue(n)) <= 0) {
+										  move = n;
+									 }
+								}
+						  }
+						  if(move == null) {
+								target.appendChild(subtree);
+						  }
+						  else {
+								target.insertBefore(subtree, move);
+						  }
+						  target = null;
+						  last_match = null;
+						  subtree = null;
+						  name = null;
+						  move = null;
+					 }
+					 b_key = null;
+				}
+				document = null;
+				a_map = null;
+				b_map = null;
+				avt = null;
+				bvt = null;
+				return true;
+		  }
+	 }
+
+	 /** Method to determine if two Value nodes are equal.
+	  * @param av A <strong>Node</strong> representing a value.
+	  * @param bv The <strong>Node</strong> we want to compare it to.
+	  * @return A <i>boolean</i> which is <i>true</i> if the two value nodes are equal, <i>false</i> otherwise.
+	  */
+	 static final public boolean valuesEqual(Node av, Node bv) {
+		  // Check we are comparing apples and apples...
+		  if(av.getNodeName().equals("Value") && 
+			  bv.getNodeName().equals("Value")) {
+				// Retrieve and then compare their text values.
+				Node at = av.getFirstChild();
+				Node bt = bv.getFirstChild();
+				if(at.getNodeValue().equals(bt.getNodeValue())) {
+					 return true;
+				}
+		  }
+		  return false;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/Metadata.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/Metadata.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/Metadata.java	(revision 13666)
@@ -0,0 +1,224 @@
+package org.greenstone.gatherer.msm;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.io.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.collection.Collection;
+import org.greenstone.gatherer.collection.CollectionManager;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.MetadataSetManager;
+import org.greenstone.gatherer.valuetree.GValueModel;
+import org.greenstone.gatherer.valuetree.GValueNode;
+import org.w3c.dom.Element;
+/** Stores a mapping between a particular metadata element, and a certain value node. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class Metadata 
+	 implements Comparable {
+	 /** Is this an accumulating piece of metadata? */
+	 transient private boolean accumulate = false;
+	 /** Indicates what level of metadata this is, relative to the file it was retrieved for. */
+	 transient private boolean file_level = true;
+	 /** The file for which this metadata was retrieved. This allows us to determine the source of folder level metadata. */
+	 transient private File file;
+	 /** The value node this metadata maps to. */
+	 private GValueNode value = null;
+	 /** Used to count the number of references to this piece of metadata within the metadata table. */
+	 private int count = 1;
+	 /** The metadata element this metadata maps to. */
+	 private ElementWrapper element = null;
+	 /** Constructs a new Metadata object with no current value.
+	  * @param element The <strong>ElementWrapper</strong> associated with this metadata.
+	  */
+	 public Metadata(ElementWrapper element) {
+		  super();
+		  this.element = element;
+		  this.value = null;
+	 }
+	 /** Default constructor simply creates a new Metadata object based on the given parameters.
+	  * @param element The <strong>ElementWrapper</strong> associated with this metadata. 
+	  * @param value The assigned value for the given element, as a <strong>GValueNode</strong>.
+	  */
+	 public Metadata(ElementWrapper element, GValueNode value) {
+		  super();
+		  this.element = element;
+		  this.value = value;
+	 }
+	 /** Constructs a new Metadata object, given the value. The metadata element is extracted from the value tree information.
+	  * @param value The assigned value for the given element, as a <strong>GValueNode</strong>.
+	  * @see org.greenstone.gatherer.Gatherer
+	  * @see org.greenstone.gatherer.collection.CollectionManager
+	  * @see org.greenstone.gatherer.msm.MetadataSetManager
+	  */
+	 public Metadata(GValueNode value) {
+		  super();
+		  this.element = Gatherer.c_man.getCollection().msm.getElement(value.getMetadataElementName());
+		  this.value = value;
+	 }
+	 /** Determine if this metadata overwrites or accumulates. */
+	 public boolean accumulates() {
+		  return accumulate;
+	 }
+	 /** Compares two Metadata objects for ordering purposes.
+	  * @param object The other metadata as an <strong>Object</strong>.
+	  * @return An <i>int</i> value as specified in java.lang.String#compareTo
+	  * @see java.lang.String#compareTo
+	  */
+	 public int compareTo(Object object) {
+		  return toString().compareTo(object.toString());
+	 }
+	 /** Decrease the reference count by 1. */
+	 public void dec() {
+		  count--;
+	 }
+	 /** Tests to metadata objects for equality.
+	  * @param object The other metadata as an <strong>Object</strong>.
+	  * @return <i>true</i> if the metadata are equal, <i>false</i> otherwise.
+	  */
+	 public boolean equals(Object object) {
+		  if(compareTo(object) == 0) {
+				return true;
+		  }
+		  return false;
+	 }
+	 /** Determine the absolute path value of this metadata, taking into account whether this value is hierarchical. */
+	 public String getAbsoluteValue() {
+		  String abs_value = getValue();
+		  // What actually gets written as the value depends on whether this is a hierarchy based element.
+		  GValueModel model = Gatherer.c_man.getCollection().msm.getValueTree(element);
+		  if(model != null && model.isHierarchy()) {
+				if(value != null) {
+					 GValueNode node = (GValueNode)value.getParent();
+					 while(node != null) {
+						  GValueNode next = (GValueNode)node.getParent();
+						  if(next != null) {
+								abs_value = node.toString() + "\\" + abs_value;
+						  }
+						  node = next;
+					 }
+				}
+				abs_value = model.getHIndex(abs_value);
+		  }
+		  // Return the result
+		  return abs_value;
+	 }
+	 /** Retrieve the reference count.
+	  * @return The count as an <i>int</i>.
+	  */
+	 public int getCount() {
+		  return count;
+	 }
+	 /** Retrieve the element associated with this metadata.
+	  * @return An <strong>ElementWrapper</strong>.
+	  */
+	 public ElementWrapper getElement() {
+		  return element;
+	 }
+
+	 /** Retrieve the source file if any. */
+	 public File getFile() {
+		  return file;
+	 }
+
+	 /** Get the textual value of this metadata.
+	  * @return A <strong>String</strong> representing the value of this Metadata. Note that if the value node is null, then the String returned is "".
+	  */
+	 public String getValue() {
+		  String result = "";
+		  if(value != null) {
+				result = value.toString();
+		  }
+		  return result;
+	 }
+	 /** Retrieve the value node associated with this metadata.
+	  * @return A <strong>GValueNode</strong>.
+	  */
+	 public GValueNode getValueNode() {
+		  return value;
+	 }
+	 /** Increase the reference count by 1. */
+	 public void inc() {
+		  count++;
+	 }
+	 
+	 /** Determine if this metadata is file level or folder level. */
+	 public boolean isFileLevel() {
+		  return file_level;
+	 }
+
+	 /** Inform this metadata whether it will accumulate with any other metadata of the same type. */
+	 public void setAccumulate(boolean accumulate) {
+		  this.accumulate = accumulate;
+	 }
+	 /** Sets the reference count. 
+	  * @param value The new value of count as an <i>int</i>.
+	  */
+	 public void setCount(int value) {
+		  count = value;
+	 }
+	 /** Set the level of this metadata (whether it is associated with this file explicitly or found in some folder above this file). */
+	 public void setFileLevel(boolean file_level) {
+		  this.file_level = file_level;
+	 }
+
+	 /** Set the current source file for this metadata to the given collection. This value should not be counted are remaining valid at any time other than immediately after a getMetadata call as it is relative the the file that metadata call was for. */
+	 public void setFile(File file) {
+		  this.file = file;
+	 }
+
+	 /** Translates this object into a string representation.
+	  * @return A <strong>String</strong>.
+	  */
+	 public String toString() {
+		  return element.toString() + "=" + getValue();
+	 }
+	 /** Retrieve the value node associated with a certain value string. */
+	 static final public GValueNode getDefaultValueNode(ElementWrapper element, String value) {
+		  // Retrieve the GValueNode
+		  GValueModel model = Gatherer.c_man.getCollection().msm.getValueTree(element);
+		  GValueNode value_node;
+		  if(model != null) {
+				value_node = model.getValue(value);
+		  }
+		  else {
+				value_node = new GValueNode(element.getName(), value);
+		  }
+		  model = null;
+		  return value_node;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/MetadataComboBoxModel.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/MetadataComboBoxModel.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/MetadataComboBoxModel.java	(revision 13666)
@@ -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.msm;
+
+import java.util.Collections;
+import java.util.Vector;
+import javax.swing.DefaultComboBoxModel;
+import org.greenstone.gatherer.msm.MetadataSetManager;
+import org.greenstone.gatherer.msm.MSMEvent;
+import org.greenstone.gatherer.msm.MSMListener;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+/** A combobox model that contains information from an array of NodeLists. */
+public class MetadataComboBoxModel
+	 extends DefaultComboBoxModel 
+	 implements MSMListener {
+	 private MetadataSetManager msm = null;
+	 /** Constructor.
+	  * @param nodelists The <strong>NodeList[]</strong> this model is proxied to.
+	  */
+	 public MetadataComboBoxModel(MetadataSetManager msm) {
+		  super();
+		  this.msm = msm;
+		  init();
+	 }
+	 /** Called whenever a metadata element is changed.
+	  * @param event A <strong>MSMEvent</strong> containing pertinent information about the event.
+	  */
+	 public void elementChanged(MSMEvent event) {
+		  init();
+	 }
+	 /** Called whenever a metadata value is changed.
+	  * @param event A <strong>MSMEvent</strong> containing pertinent information about the event.
+	  */
+	 public void metadataChanged(MSMEvent event) {
+		  // Don't care.
+	 }
+	 /** Called whenever a metadata set is changed.
+	  * @param event A <strong>MSMEvent</strong> containing pertinent information about the event.
+	  */
+	 public void setChanged(MSMEvent event) {
+		  init();
+	 }
+	 /** Called whenever the value tree of a certain element is significantly changed.
+	  * @param event A <strong>MSMEvent</strong> containing information about the event.
+	  */
+	 public void valueChanged(MSMEvent event) {
+		  // Don't care.
+	 }
+	 private void init() {
+		  removeAllElements();
+		  Vector elements = msm.getElements();
+		  Collections.sort(elements);
+		  for(int k = 0; k < elements.size(); k++) {
+				addElement(elements.get(k));
+		  }
+	 }
+}
+
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/MetadataParser.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/MetadataParser.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/MetadataParser.java	(revision 13666)
@@ -0,0 +1,47 @@
+package org.greenstone.gatherer.msm;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.file.FileNode;
+/** Provides an interface for all parsers which should be called during the 'search for existing metadata' phase of a file copy. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public interface MetadataParser {
+	 /** Locate and import any metadata parsed by this metadata parser given the file involved and its previous incarnation. The last parameter indicates that the parser is forced to assign otherwise folder level metadata to the desired -files-. If the filenode was a directory folder_level is automatically true.*/
+	 public boolean process(FileNode destination, FileNode origin, boolean folder_level, boolean dummy_run);
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/MetadataSet.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/MetadataSet.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/MetadataSet.java	(revision 13666)
@@ -0,0 +1,545 @@
+package org.greenstone.gatherer.msm;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import org.apache.xerces.dom.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.valuetree.GValueModel;
+import org.greenstone.gatherer.valuetree.GValueNode;
+import org.greenstone.gatherer.util.Utility;
+import org.w3c.dom.*;
+/** An semi-data class to hold details about a loaded metadata set, it also provides some methods to manipulating the data within. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3b
+ */
+public class MetadataSet {
+	 /** The <Strong>Document</strong> of the DOM model. */
+	 private Document document = null;
+	 /** The document <strong>Element</strong> of the DOM model. */
+	 private Element  root     = null;
+	 /** The <strong>File</strong> this metadata set was loaded from. */
+	 private File     file     = null;
+	 /** A mapping from metadata elements to the root element of the value trees for that element. */
+	 private Hashtable value_trees = null;
+	 /** The list of metadata elements which are, of course, children of the root node. */
+	 private NodeList elements = null;
+	 /** The description of this metadata set. Cached as it takes more computation time. */
+	 private String description = null;
+	 /** The name of this metadata set. Cached as it takes more computation time. */
+	 private String name = null;
+	 /** An element of the tree pruning filter enumeration, that indicates all nodes in the tree should be retained. */
+	 static final int ALL_VALUES    = 1;
+	 /** An element of the tree pruning filter enumeration, that indicates only metadata Subject nodes or higher should remain after pruning. */
+	 static final int SUBJECTS_ONLY = 2;
+	 /** An element of the tree pruning filter enumeration, that indicates no value nodes i.e. the entire AssignedValues subtree, should remain after pruning. */
+	 static final int NO_VALUES     = 3;
+
+	 public MetadataSet(String metadata_template) {
+		  URL url = ClassLoader.getSystemResource(metadata_template);
+		  init(new File(URLDecoder.decode(url.getFile())));
+	 }
+
+	 /** Constructor.
+	  * @param file The file the metadata set should be loaded from. 
+	  */
+	 public MetadataSet(File file) {
+		  init(file);
+	 }
+
+	 /** Metadata Set already parsed constructor.
+	  * @param file The file the metadata was loaded from.
+	  * @param document The DOM model <strong>Document</strong> containing the metadata set.
+	  */
+	 public MetadataSet(File file, Document document) {
+		  this.document = document;
+		  this.elements = document.getElementsByTagName("Element");
+		  this.file     = file;
+		  this.root     = document.getDocumentElement();
+		  this.value_trees = new Hashtable();
+		  // Now for each element read in its value tree if present.
+		  for(int i = elements.getLength() - 1; i >= 0; i--) {
+				ElementWrapper value_element = new ElementWrapper((Element)elements.item(i));
+				File value_file = new File(file.getParentFile(), value_element.toString() + ".mdv");
+				///ystem.err.println("Searching for " + value_file.getAbsolutePath());
+				if(value_file.exists()) {
+					 Document value_document = Utility.parse(value_file, false);
+					 if(value_document != null) {
+						  value_trees.put(value_element, new GValueModel(value_element, value_document));
+					 }
+					 else {
+						  Gatherer.println("Error! Missing mdv file: " + value_file.getAbsolutePath());
+					 }
+				}
+		  }
+	 }
+	 /** Copy constructor. 
+	  * @param original The original metadata set to copy from.
+	  */
+	 public MetadataSet(MetadataSet original) {
+		  this.value_trees = new Hashtable();
+		  // We have to create a new document.
+		  document = new DocumentImpl(original.getDocument().getDoctype());
+		  root = (Element) document.importNode(original.getDocument().getDocumentElement(), true);
+		  document.appendChild(root);
+		  elements = root.getElementsByTagName("Element");
+		  file = original.getFile();
+		  // Now for each element read in its value tree if present.
+		  for(int i = elements.getLength() - 1; i >= 0; i--) {
+				ElementWrapper value_element_wrapper = new ElementWrapper((Element)elements.item(i));
+				GValueModel value_tree = original.getValueTree(value_element_wrapper);
+				Document value_document = value_tree.getDocument();
+				Document value_document_copy = new DocumentImpl(value_document.getDoctype());
+				Element value_element = value_document.getDocumentElement();
+				Element value_element_copy = (Element) value_document_copy.importNode(value_element, true);
+				value_document_copy.appendChild(value_element_copy);
+				GValueModel value_tree_copy = new GValueModel(value_element_wrapper, value_document_copy);
+				value_trees.put(value_element_wrapper, value_tree_copy);
+		  }
+	 }
+	 /** Conditional copy constructor. 
+	  * @param original The original metadata set to copy from.
+	  * @param condition An <i>int</i> which matches one of the tree pruning filter types.
+	  */
+	 public MetadataSet(MetadataSet original, int condition) {
+		  this(original); 
+		  // Now based on condition, we may have to remove some nodes from
+		  // this model.
+		  switch(condition) {
+		  case ALL_VALUES:
+				// Do nothing.
+				break;
+		  case SUBJECTS_ONLY:
+				// For each element retrieve its AssignedValues element.
+				for(Enumeration keys = value_trees.keys(); keys.hasMoreElements(); ) {
+					 ElementWrapper value_element = (ElementWrapper)keys.nextElement();
+					 GValueModel value_tree = (GValueModel)value_trees.get(value_element);
+					 Document value_tree_document = value_tree.getDocument();
+					 Element value_tree_root_element = value_tree_document.getDocumentElement();
+					 // Traverse tree and remove leaf nodes. 
+					 MSMUtils.traverseTree(value_tree_root_element, MSMUtils.NONE, true);
+				}
+				break;
+		  case NO_VALUES:
+				// Remove assigned values trees.
+				value_trees.clear();
+				break;
+		  }
+	 }
+
+	 /** Add a mds level attribute.
+	  * @param name The name of the attribute to add as a <Strong>String</strong>.
+	  * @param value The value as a <strong>String</strong>.
+	  */
+	 public void addAttribute(String name, String value) {
+		  root.setAttribute(name, value);
+	 }
+
+	 /** Add a new default metadata element with the given name to this metadata set.
+	  * @param name The name of this element as a <strong>String</strong>.
+	  * @return An <strong>ElementWrapper</strong> around the newly created element or null if the element was not created.
+	  */
+	 public ElementWrapper addElement(String name) {
+		  Text text = document.createTextNode(name);
+		  Element identifier = document.createElementNS("","Attribute");
+		  identifier.setAttribute("name","identifier");
+		  identifier.appendChild(text);
+		  Element element = document.createElementNS("","Element");
+		  element.setAttribute("name",name);
+		  element.appendChild(identifier);
+		  root.appendChild(element);
+		  ElementWrapper wrapper = new ElementWrapper(element);
+		  ///ystem.err.println("Added a new element " + wrapper);
+		  return wrapper;
+	 }
+
+	 /** Method to add a new metadata element to this metadata set, if and only if the element is not already present. 
+	  * @param others_element An <strong>Element</strong> we wish to add to this metadata set, that currently belongs to some other set.
+	  * @return <i>null</i> if the add is successful, otherwise a <strong>String</strong> containing an error message (phrase key).
+	  */
+	 public String addElement(Element others_element) {
+		  if(!containsElement(others_element.getAttribute("name"))) {
+				// First get ownership of the new element, then add it.
+				Node our_element = document.importNode(others_element, true);
+				root.appendChild(our_element);
+				return null;
+		  }
+		  else {
+				return "Element name already exists!";
+		  }
+	 }
+
+	 /** Method to add a new metadata element with the specified new name to this metadata set, if and only if the name is not already in use. 
+	  * @param others_element An <strong>Element</strong> we wish to add to this metadata set, that currently belongs to some other set.
+	  * @param new_name The new name to be given this element, as a <strong>String</strong>.
+	  * @return <i>null</i> if the add is successful, otherwise a <strong>String</strong> containing an error message (phrase key).
+	  */
+	 public String addElement(Element others_element, String new_name) {
+		  if(!containsElement(new_name)) {
+				// First get ownership of the new element, then add it.
+				Element our_element = 
+					 (Element) document.importNode(others_element, true);
+				// Change name
+				our_element.setAttribute("name", new_name);
+				// Add it
+				root.appendChild(our_element);
+				return null;
+		  }
+		  else {
+				return "MSMPrompt.Name_Exists";
+		  }
+	 }
+	 /** Add a value tree to a given metadata element.
+	  * @param element The <strong>ElementWrapper</strong> containing the element you wish to add a value tree for.
+	  * @param value_tree The root <strong>Element</strong> of the value tree.
+	  */
+	 public void addValueTree(ElementWrapper element, GValueModel model) {
+		  ///ystem.err.println("Adding value tree for " + element.toString());
+		  value_trees.put(element, model);
+	 }
+	 /** A method to determine if this metadata set contains an element with a certain name.
+	  * @param name A <strong>String</strong> which is the name of the element whose presence we are checking.
+	  * @return A <i>boolean</i> which is <i>true</i> if the named element exists, <i>false</i> otherwise.
+	  */
+	 public boolean containsElement(String name) {
+		  for(int i = 0; i < elements.getLength(); i++) {
+				Element sibling = (Element) elements.item(i);
+				String sibling_name = sibling.getAttribute("name");
+				if(sibling_name.equals(name)) {
+					 return true;
+				}
+		  }
+		  return false;
+	 }
+
+	 public NamedNodeMap getAttributes() {
+		  return root.getAttributes();
+	 }
+
+	 /** Method to retrieve the contact address of the metadata set creator.
+	  * @return A <strong>String</strong> containing the address. 
+	  */
+	 public String getContact() {
+		  return root.getAttribute("contact");
+	 }
+	 /** Method to retrieve the name of the creator of this metadata set. 
+	  * @return A <strong>String</strong> containing the name.
+	  */
+	 public String getCreator() {
+		  return root.getAttribute("creator");
+	 }
+	 /** Method to retrieve the description of this metadata set. Note that this is language specific, so we determine the desired language from the Dictionary. If no such entry exists, first try returning the english version and failing that the first description found.
+	  * @return The description as a <strong>String</strong>.
+	  */
+	 public String getDescription() {
+		  if(description == null) {
+				// Determine the code.
+				String language_code = Gatherer.dictionary.getLanguage();
+				// Recover all Description elements
+				NodeList descriptions = document.getElementsByTagName("Description");
+				// Iterate through the available descriptions looking for the appropriate one. Also make note of the first description, then overwrite it with any english one.
+				boolean found = false;
+				for(int i = 0; !found && i < descriptions.getLength(); i++) {
+					 Element pos_description = (Element) descriptions.item(i);
+					 String pos_description_code = pos_description.getAttribute("language");
+					 if(pos_description_code.equalsIgnoreCase(language_code)) {
+						  description = MSMUtils.getValue(pos_description);
+						  found = true;
+					 }
+					 else if(pos_description_code.equalsIgnoreCase("en")) {
+						  description = MSMUtils.getValue(pos_description);
+					 }
+					 else if(description == null) {
+						  description = MSMUtils.getValue(pos_description);
+					 }
+					 pos_description_code = null;
+					 pos_description = null;
+				}
+				descriptions = null;
+				language_code = null;
+				// Failing all that set an error message
+				if(description == null) {
+					 description = Gatherer.dictionary.get("MSM.No_Description");
+				}
+		  }
+		  return description;
+	 }
+	 /** Method to retrieve the <strong>Document</strong> associated with this metadata set.
+	  * @return The <strong>Document</strong> representing this metadata set.
+	  */
+	 public Document getDocument() {
+		  return document;
+	 }
+	 /** Method to retrieve the metadata element indicated by an index.
+	  * @param index An <i>int</i> specifying the required element.
+	  * @return The <strong>Element</strong> at the index.
+	  */
+	 public Element getElement(int index) {
+		  return (Element)elements.item(index);
+	 }
+	 /** This method is used to acquire a reference to the element which matches the given metadata. Note that this is not the same as <i>metadata.getElement()</i> as the reference returned by it may now be obsolete.
+	  * @param metadata A <strong>Metadata</strong> object representing an element and value assignment.
+	  * @return A 'live' reference to an <strong>Element</strong> which is the same as that referenced by the given metadata, or <i>null</i> if there is no such element.
+	  */
+	 public Element getElement(Metadata metadata) {
+		  return metadata.getElement().getElement();
+	 }
+	 /** This method is used to acquire a reference to the element which has the name specified. Note that this is not the same as <i>metadata.getElement()</i> as the reference returned by it may now be obsolete.
+	  * @param name A <strong>String</strong> stating the desired objects name.
+	  * @return A 'live' reference to an <strong>Element</strong> which is the same as that referenced by the given metadata, or <i>null</i> if there is no such element.
+	  */
+	 public Element getElement(String name) {
+		  // Strip any namespace.
+		  while(name.indexOf(".") != -1 && !name.equals(".")) {
+				name = name.substring(name.indexOf(".") + 1);
+		  }
+		  ///ystem.err.println("Get element named " + name);
+		  for(int i = 0; i < elements.getLength(); i++) {
+				Element element = (Element) elements.item(i);
+				///ystem.err.println("Compare to: " + element.getAttribute("name"));
+				if(element.getAttribute("name").equals(name)) {
+					 return element;
+				}
+		  }
+		  return null;
+	 }
+	 /** Method to acquire a list of all the elements in this metadata set. 
+	  * @return A <strong>NodeList</strong> containing all of this sets elements.
+	  */
+	 public NodeList getElements() {
+		  return elements;
+	 }
+	 /** Method to retrieve the original file this metadata set was created from.
+	  * @return A <strong>File</strong>.
+	  */
+	 public File getFile() {
+		  return file;
+	 }
+	 /** Get the last changed attribute.
+	  * @return Last changed as a <strong>String</strong>.
+	  */
+	 public String getLastChanged() {
+		  return root.getAttribute("lastchanged");
+	 }
+	 /** Method to get this metadata sets name. Note that this is language specific, so we determine the desired language from the Dictionary. If no such entry exists, first try returning the english version and failing that the first name found.
+	  * @return A <strong>String</strong> which contains its name.
+	  */
+	 public String getName() {
+		  if(name == null) {
+				// Determine the code.
+				String language_code = Gatherer.dictionary.getLanguage();
+				// Recover all Name elements
+				NodeList names = document.getElementsByTagName("Name");
+				// Iterate through the available names looking for the appropriate one. Also make note of the first name, then overwrite it with any english one.
+				boolean found = false;
+				for(int i = 0; !found && i < names.getLength(); i++) {
+					 Element pos_name = (Element) names.item(i);
+					 String pos_name_code = pos_name.getAttribute("language");
+					 if(pos_name_code.equalsIgnoreCase(language_code)) {
+						  name = MSMUtils.getValue(pos_name);
+						  found = true;
+					 }
+					 else if(pos_name_code.equalsIgnoreCase("en")) {
+						  name = MSMUtils.getValue(pos_name);
+					 }
+					 else if(name == null) {
+						  name = MSMUtils.getValue(pos_name);
+					 }
+					 pos_name_code = null;
+					 pos_name = null;
+				}
+				names = null;
+				language_code = null;
+				// Failing all that set an error message
+				if(name == null) {
+					 name = Gatherer.dictionary.get("MSM.No_Name");
+				}
+		  }
+		  return name;
+	 }
+	 /** Method to retrieve this metadata sets namespace.
+	  * @return The namespace as a <strong>String</strong>.
+	  */
+	 public String getNamespace() {
+		  return root.getAttribute("namespace");
+	 }
+	 /** Method to retrieve the root element, i.e. the Document Element, of the DOM model behind this metadata set.
+	  * @return An <strong>Element</strong> which is at the root of the modal.
+	  */ 
+	 public Element getRoot() {
+		  return root;
+	 }
+	 /** Retrieve the value tree from this set that matches the given element.
+	  * @param element The target <strong>ElementWrapper</strong>.
+	  * @return A <strong>GValueModel</strong> value tree, or <i>null</i> if no such element or value tree.
+	  */
+	 public GValueModel getValueTree(ElementWrapper element) {
+		  GValueModel value_tree = null;
+		  ///ystem.err.println("Retrieving value tree for element: " + element.toString());
+		  // Stinking hashtable get doesn't use the overridden equals. So I'll do a loop, which should be pretty small ie O(n) for n metadata elements.
+		  for(Enumeration keys = value_trees.keys(); keys.hasMoreElements(); ) {
+				ElementWrapper sibling = (ElementWrapper) keys.nextElement();
+				if(sibling.equals(element)) {
+					 value_tree = (GValueModel) value_trees.get(sibling);
+				}
+		  }
+		  // If we've found no value tree, create a new one.
+		  if(value_tree == null) {
+				value_tree = new GValueModel(element);
+				value_trees.put(element, value_tree);
+		  }
+		  return value_tree;
+	 }
+	 /** Remove a mds level attribute.
+	  * @param name The name of the attribute to remove.
+	  */
+	 public void removeAttribute(String name) {
+		  root.removeAttribute(name);
+	 }
+	 /** Method to remove the given element from this metadata set.
+	  * @param element The <strong>Element</strong> to be removed.
+	  */
+	 public void removeElement(Element element) {
+		  root.removeChild(element);
+	 }
+	 /** Used to remove the value tree for a specific element.
+	  * @param element The <strong>ElementWrapper</strong> whose tree you wish to remove.
+	  * @return The <strong>Element</strong> at the root of the value tree we just removed.
+	  */
+	 public Element removeValueTree(ElementWrapper element) {
+		  for(Enumeration keys = value_trees.keys(); keys.hasMoreElements(); ) {
+				ElementWrapper sibling = (ElementWrapper) keys.nextElement();
+				if(sibling.equals(element)) {
+					 Element tree_root = (Element) value_trees.get(sibling);
+					 value_trees.remove(sibling);
+					 return tree_root;
+				}
+		  }
+		  return null;
+	 }
+	 /** Set one of the mds level attributes.
+	  * @param name The attribute to change.
+	  * @param value its new value.
+	  */
+	 public void setAttribute(String name, String value) {
+		  root.setAttribute(name, value);
+	 }
+	 /** Once the metadata set has been saved to a different location, this is used to update the file parameter.
+	  * @param file The new location of this metadata set <strong>File</strong>.
+	  */
+	 public void setFile(File file) {
+		  this.file = file;
+	 }
+
+	 public void setName(String name) {
+		  // Retrieve the name element. We look for the first english one.
+		  Element name_element = null;
+		  Element metadataset_element = document.getDocumentElement();
+		  NodeList name_elements = metadataset_element.getElementsByTagName(Utility.NAME_ELEMENT);
+		  for(int i = 0; i < name_elements.getLength(); i++) {
+				Element possible_name_element = (Element) name_elements.item(i);
+				if(possible_name_element.getAttribute(Utility.LANGUAGE_ATTRIBUTE).equals(Utility.ENGLISH_VALUE)) {
+					 // Found it.
+					 name_element = possible_name_element;
+				}
+		  }
+		  // If there is none add one. Note that we can only add english metadata sets. Although others can edit them to add further names as necessary.
+		  if(name_element == null) {
+				name_element = document.createElement(Utility.NAME_ELEMENT);
+				name_element.setAttribute(Utility.LANGUAGE_ATTRIBUTE, Utility.ENGLISH_VALUE);
+				metadataset_element.insertBefore(name_element, metadataset_element.getFirstChild());
+		  }
+		  // Replace the text node
+		  while(name_element.hasChildNodes()) {
+				name_element.removeChild(name_element.getFirstChild());
+		  }
+		  name_element.appendChild(document.createTextNode(name));
+	 }
+
+	 /** Method to determine the number of elements in this set.
+	  * @return An <i>int</i> specifying the element count.
+	  */
+	 public int size() {
+		  return elements.getLength();
+	 }
+	 /** Method to translate this class into a meaningful string, which in this case is the metadata sets name.
+	  * @return The metadata sets name as a <strong>String</strong>.
+	  */
+	 public String toString() {
+		  String name = getName();
+		  // If there is no given name, then use the namespace as there is garaunteed to be one of them.
+		  if(name == null || name.length() == 0) {
+				name = root.getAttribute("namespace");
+		  }
+		  // Append namespace
+		  String namespace = root.getAttribute("namespace");
+		  if(namespace == null || namespace.equals("")) {
+				namespace = Utility.EXTRACTED_METADATA_NAMESPACE;
+		  }
+		  name = name + " (" + namespace + ")";
+		  return name;
+	 }
+
+	 private void init(File file) {
+		  this.file = file;
+		  this.value_trees = new Hashtable();
+		  this.document = Utility.parse(file, false);
+		  if(document != null) {
+				this.elements = document.getElementsByTagName("Element");
+				this.root = document.getDocumentElement();
+				// Now for each element read in its value tree if present.
+				for(int i = elements.getLength() - 1; i >= 0; i--) {
+					 ElementWrapper value_element = new ElementWrapper((Element)elements.item(i));
+					 File value_file = new File(file.getParentFile(), value_element.toString() + ".mdv");
+					 ///ystem.err.println("Searching for " + value_file.getAbsolutePath());
+					 if(value_file.exists()) {
+						  Document value_document = Utility.parse(value_file, false);
+						  if(value_document != null) {
+								value_trees.put(value_element, new GValueModel(value_element, value_document));
+						  }
+						  else {
+								Gatherer.println("Error! Missing mdv file: " + value_file.getAbsolutePath());
+						  }
+					 }
+				}
+		  }
+		  else {
+				Gatherer.println("Error! Missing mds file: " + file.getAbsolutePath());
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/MetadataSetManager.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/MetadataSetManager.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/MetadataSetManager.java	(revision 13666)
@@ -0,0 +1,1209 @@
+package org.greenstone.gatherer.msm;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.filechooser.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.CommandTokenizer;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.gui.MetaEditPrompt;
+import org.greenstone.gatherer.mem.MetadataEditorManager;
+import org.greenstone.gatherer.msm.Declarations;
+import org.greenstone.gatherer.msm.MDSFileFilter;
+import org.greenstone.gatherer.msm.MetadataSet;
+import org.greenstone.gatherer.msm.MSMAction;
+import org.greenstone.gatherer.msm.MSMEvent;
+import org.greenstone.gatherer.msm.MSMPrompt;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.greenstone.gatherer.valuetree.GValueModel;
+import org.greenstone.gatherer.valuetree.GValueNode;
+import org.greenstone.gatherer.util.MetadataXML;
+import org.greenstone.gatherer.util.Utility;
+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 John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3b
+ */
+public class MetadataSetManager {
+
+	 /** The name of the hidden, or system, metadata set. */
+	 static final public String HIDDEN = "hidden";
+
+	 /** A mapping from metadata namespace to metadata set. */
+	 static private Hashtable mds_hashtable = new Hashtable();
+
+	 /** The class responsible for creating and maintaining all the visual components of the metadata management package. */
+	 public MSMPrompt prompt = null;
+	 /** The profiler is responsible for remembering what actions a user has requested when importing metadata, so as to prevent the user needlessly re-entering this information for each import. */
+	 public MSMProfiler profiler = null;
+
+	/** Records all of the changes made to metadata as part of the current metadata change. Entries map from a particular FileNode to an ArrayList of the modified metadata for that node. Not to be confused with the undo managers idea of undo which records a list of all metadata changes requested. */
+	 private HashMap undo_buffer = new HashMap(); 
+	 /** The loader responsible for sequentially loading and attempting to use all registered metadata parsers to extract existing metadata from new files. */
+	 private ExistingMetadataLoader loader = null;
+	 /** Specialized parser for parsing GreenstoneDirectoryMetadata files, which not only caches entries, but also breaks up massive metadata.xml files into reasonable sizes. */
+	 private GDMParser gdm_parser = null;
+	 /** A list of classes who are interested in changes to the loaded metadata sets. */
+	 private Vector listeners = null;
+
+	 /** Constructor. */
+	 public MetadataSetManager() {
+		  this.gdm_parser = new GDMParser();
+		  this.listeners = new Vector();
+		  this.loader = new ExistingMetadataLoader();
+		  loadProfiler();
+		  this.prompt = new MSMPrompt(this);
+	 }
+
+	 /** Attach a piece of metadata to a record or records, ensuring the value tree is built properly, and correct messaging fired.
+	  * @param records A FileNode[] of records, or directories, to add the specified metadata to.
+	  * @param element The metadata element, contained within an ElementWrapper to base metadata on.
+	  * @param value The value to assign to the metadata as a String.
+	  */
+	 public void addMetadata(long id, FileNode records[], ElementWrapper element, String value_str) {
+		  addMetadata(id, records, element, value_str, MetaEditPrompt.CONFIRM);
+	 }
+	 public void addMetadata(long id, FileNode records[], ElementWrapper element, String value_str, int action) {
+		  // Retrieve the appropriate value node from the value tree for this element, creating it if necessary.
+		  GValueModel model = getValueTree(element);
+		  GValueNode value = null;
+		  if(model != null) {
+				value = model.addValue(value_str); // Only adds if not already present, otherwise just returns existing node.
+		  }
+		  else {
+				value = new GValueNode(element.toString(), value_str);
+		  }
+		  // Create new metadata.
+		  Metadata metadata = new Metadata(value);
+		  // Reset the undo buffer.
+		  undo_buffer.clear();
+		  // Assign to records. Note that we must watch for responses from the user prompts, and cease loop if break signalled.
+		  // Now add the metadata to each selected file node.
+		  for(int i = 0; action != MetaEditPrompt.CANCEL && i < records.length; i++) {
+				action = addMetadata(id, records[i], metadata, action, (records.length > 1));
+		  }
+		  // If we were cancelled we should undo any changes so far
+		  if(action == MetaEditPrompt.CANCEL) {
+				for(Iterator keys = undo_buffer.keySet().iterator(); keys.hasNext(); ) {
+					 FileNode record = (FileNode) keys.next();
+					 undoAdd(id, record);
+				}
+		  }
+	 }
+
+	 /** Adds a metadata set listener to this set, if it isn't alreay listening.
+	  * @param listener The new MSMListener.
+	  */
+	 public void addMSMListener(MSMListener listener) {
+		  if(!listeners.contains(listener)) {
+				listeners.add(listener);
+		  }
+	 }
+
+	 public MetadataSet addSet(String namespace, String name) {
+		  MetadataSet mds = new MetadataSet(Utility.METADATA_SET_TEMPLATE);
+		  mds.setAttribute("creator","The Gatherer");
+		  // Calculate lastchanged to right now on this machine by this user
+		  String user_name = System.getProperty("user.name");
+		  String machine_name = Utility.getMachineName();
+		  mds.setAttribute("lastchanged", Utility.getDateString() + " - " + user_name + " on " + machine_name);
+		  // And the remaining attributes.
+		  //mds.setAttribute("name", name);
+		  mds.setAttribute("namespace", namespace);
+		  mds_hashtable.put(namespace, mds);
+		  // Add the name element.
+		  mds.setName(name);
+		  fireSetChanged(mds);
+		  return mds;
+	 }
+
+	 /** Add a value tree to a given metadata element.
+	  * @param element The ElementWrapper containing the element you wish to add a value tree for.
+	  * @param value_tree The root Element of the value tree.
+	  */
+	 public void addValueTree(GValueModel model) {
+		  ElementWrapper element = model.getElement();
+		  String namespace = element.getNamespace();
+		  MetadataSet mds = (MetadataSet) mds_hashtable.get(namespace);
+		  if(mds != null) {
+				mds.addValueTree(element, model);
+		  }
+	 }
+	 /** Destructor. 
+	  * @see org.greenstone.gatherer.msm.MSMProfiler
+	  */
+	 public void destroy() {
+		  mds_hashtable.clear();
+		  profiler.destroy();
+		  profiler = null;
+	 }
+	 /** Method called to open a metadata set editing window.
+	  * @return A boolean indicating if the edit was successful.
+	  */
+	 public boolean editMDS() {
+		  /* TODO - implement. Something here like: new MSMEditor() */
+		  MetadataEditorManager mem = new MetadataEditorManager();
+		  mem.dispose();
+		  mem = null;
+		  return true;
+	 }
+
+	 /** This method is called to export a metadata set. First a prompt is displayed to gather necessary details such as which metadata set to export, where to export it to and what conditions should be applied when exporting. Once this information is gathered the static method <i>exportMDS()</i> is called with the appropriate output stream.
+	  * @return A boolean which is <i>true</i> if the metadata set has been exported successfully, <i>false</i> otherwise.
+	  */
+	 public boolean exportMDS() {
+		  ExportMDSPrompt emdsp = new ExportMDSPrompt(this, true);
+		  int result = emdsp.display();
+		  MetadataSet set = emdsp.getSelectedSet();
+		  if(result == ExportMDSPrompt.EXPORT && set != null) {
+				File file = emdsp.getSelectedFile();
+				MetadataSet set_copy = new MetadataSet(set, emdsp.getSelectedCondition());
+				try {
+					 file.getParentFile().mkdirs();
+					 Utility.export(set_copy.getDocument(), file);
+					 // Now for each element attempt to save its value tree.
+					 NodeList elements = set_copy.getElements();
+					 for(int i = elements.getLength() - 1; i >= 0; i--) {
+						  ElementWrapper value_element = new ElementWrapper((Element)elements.item(i));
+						  GValueModel value_tree = set_copy.getValueTree(value_element);
+						  if(value_tree != null) {
+								File value_file = new File(file.getParentFile(), value_element.toString() + ".mdv");
+								///ystem.err.println("Saving value file: " + value_file.toString());
+								Utility.export(value_tree.getDocument(), value_file);
+						  }
+					 }
+					 return true;
+				}
+				catch (Exception error) {
+					 error.printStackTrace();
+				}
+		  }
+		  emdsp.dispose();
+		  emdsp = null;
+		  return false;
+	 }
+
+	 /** Fire an element changed message off to all registered listeners.
+	  * @param event An MSMEvent detailing the change.
+	  */
+	 public void fireElementChanged(MSMEvent event) {
+		  // Then send it to all the listeners.
+		  for(int i = 0; i < listeners.size(); i++) {
+				((MSMListener)listeners.get(i)).elementChanged(event);
+		  }
+	 }
+
+	 /** Fire a metadata value changed message, whose id is to be generated now, off to all registered listeners. */
+	 public void fireMetadataChanged(FileNode node, Metadata old_data, Metadata new_data) {
+		  fireMetadataChanged(System.currentTimeMillis(), node, old_data, new_data);
+	 }
+
+	 /** Fire a metadata value changed message off to all registered listeners. */
+	 public void fireMetadataChanged(long id, FileNode node, Metadata old_data, Metadata new_data) {
+		  if(old_data != null) {
+				old_data.getElement().dec();
+		  }
+		  if(new_data != null) {
+				new_data.getElement().inc();
+		  }
+		  ///ystem.err.println("Metadata changed: " + record + " > '" + old_data + "' -> '" + new_data + "'");
+		  // Create a new MSMEvent based on the record.
+		  MSMEvent event = new MSMEvent(this, id, node, old_data, new_data);
+		  // Then send it to all the listeners.
+		  for(int i = 0; i < listeners.size(); i++) {
+				((MSMListener)listeners.get(i)).metadataChanged(event);
+		  }
+	 }
+
+	 /** Fire a metadata set changed message off to all registered listeners.
+	  * @param set The MetadataSet thats changed.
+	  */
+	 public void fireSetChanged(MetadataSet set) {
+		  // Create a new MSMEvent, with a MSMAction containing only the new set.
+		  MSMEvent event = new MSMEvent(this, 0L, new MSMAction(set.toString(), null, -1, null));
+		  // Then send it to all the listeners.
+		  for(int i = 0; i < listeners.size(); i++) {
+				((MSMListener)listeners.get(i)).setChanged(event);
+		  }
+	 }
+	 /** Called whenever the value tree associated with an element changes significantly.
+	  * @param element The metadata element whose value tree has changed, as an ElementWrapper.
+	  */
+	 public void fireValueChanged(ElementWrapper element, GValueModel old_model, GValueModel new_model) {
+		  // Create a new MSMEvent based on the element wrapper.
+		  MSMEvent event = new MSMEvent(this, 0L, element, old_model, new_model);
+		  // Then send it to all the listeners.
+		  for(int i = 0; i < listeners.size(); i++) {
+				((MSMListener)listeners.get(i)).valueChanged(event);
+		  }		  
+	 }
+	 /** Builds a list of elements that have been assigned as metadata in this collection. We go through all of the elements, looking for elements whose occurances are greater than 0. A convenience call to the version with one parameter. 
+	  * @return A Vector of assigned elements.
+	  */
+	 public Vector getAssignedElements() {
+		  return getAssignedElements(false);
+	 }
+	 /** Builds a list of elements that have been assigned as metadata in this collection. We go through all of the elements, looking for elements whose occurances are greater than 0.
+	  * @param hierarchy_only <i>true</i> to only return those elements that are both assigned and have hierarchical value trees, <i>false</i> for just assignments. 
+	  * @return A Vector of assigned elements.
+	  */
+	 public Vector getAssignedElements(boolean hierarchy_only) {
+		  Vector elements = new Vector();
+		  for(Enumeration keys = mds_hashtable.keys(); keys.hasMoreElements(); ) {
+				MetadataSet mds = (MetadataSet)mds_hashtable.get(keys.nextElement());
+				if(!mds.getNamespace().equals(HIDDEN)) {
+					 NodeList set_elements = mds.getElements();
+					 for(int i = 0; i < set_elements.getLength(); i++) {
+						  ElementWrapper element = new ElementWrapper((Element)set_elements.item(i));
+						  elements.add(element);
+					 }
+				}
+		  }
+		  Collections.sort(elements);
+		  for(int i = elements.size(); i != 0; i--) {
+				ElementWrapper element = (ElementWrapper) elements.get(i - 1);
+				if(element.getOccurances() == 0 && element.getNamespace().length() > 0 && !element.toString().equals("Source")) {
+					 elements.remove(element);
+				}
+				else if(hierarchy_only) {
+					 GValueModel model = getValueTree(element);
+					 if(!model.isHierarchy()) {
+						  elements.remove(element);
+					 }
+				}
+		  }
+		  return elements;
+	 }
+	 /** Used to get all the (non-hidden) elements in this manager.
+	  * @return A Vector of ElementWrappers.
+	  */
+	 public Vector getElements() {
+		  return getElements(false);
+	 }
+	 /** Used to get all the elements in this manager.
+	  * @param all <i>true</i> if all elements, including hidden, should be returned.
+	  * @return A Vector of ElementWrappers.
+	  */
+	 public Vector getElements(boolean all) {
+		  Vector all_elements = new Vector();
+		  for(Enumeration keys = mds_hashtable.keys(); keys.hasMoreElements(); ) {
+				MetadataSet mds = (MetadataSet)mds_hashtable.get(keys.nextElement());
+				if(all || !mds.getNamespace().equals(HIDDEN)) {
+					 NodeList set_elements = mds.getElements();
+					 ///ystem.err.println("The set " + mds + " has " + set_elements.getLength() + " elements.");
+					 for(int i = 0; i < set_elements.getLength(); i++) {
+						  ElementWrapper element = new ElementWrapper((Element)set_elements.item(i));
+						  if(!element.toString().equals("Source")) {
+								all_elements.add(element);
+						  }
+					 }
+				}
+		  }
+		  Collections.sort(all_elements);
+		  return all_elements;
+	 }
+	 /** Returns all the elements within this set as a combobox model. 
+	  * @return A MetadataComboBoxModel containing all the metadata elements from all the sets, with namespacing.
+	  */
+	 public MetadataComboBoxModel getElementModel() {
+		  return new MetadataComboBoxModel(this);
+	 }
+	 /** Retrieve a metadata element by its index.
+	  * @param index The specified index as an int.
+	  * @return An ElementWrapper containing the specied element, or <i>null</i> is no such element exists.
+	  */
+	 public ElementWrapper getElement(int index) {
+		  Vector elements = getElements(false);
+		  ElementWrapper result = null;
+		  if(0 <= index && index < elements.size()) {
+				result = (ElementWrapper) elements.get(index);
+		  }
+		  return result;
+	 }
+	 /** Retrieve a metadata element by looking at the current metadata element. Note that this 'index' element may now be disconnected from the DOM model, so we have to reload the target element by the string method.
+	  * @param element The possibly out-of-data MetadataElement.
+	  * @return An ElementWrapper containing the specied element, or <i>null</i> is no such element exists.
+	  */
+	 public ElementWrapper getElement(ElementWrapper element) {
+		  return getElement(element.toString());
+	 }
+	 /** Retrieve a metadata element by its fully qualified name.
+	  * @param name The elements name as a String.
+	  * @return An ElementWrapper containing the specied element, or <i>null</i> is no such element exists.
+	  */
+	 public ElementWrapper getElement(String name) {
+		  ///ystem.err.println("Retrieve element " + name);
+		  if(name == null) {
+				///ystem.err.println("No name!");
+				return null;
+		  }
+		  ElementWrapper result = null;
+		  MetadataSet set = null;
+		  String element = null;
+		  // First we seperate off what set it is in, where we have '<set><namespace_separator><element>'.
+		  if(name.indexOf(MSMUtils.NS_SEP) != -1) {
+				String namespace = name.substring(0, name.indexOf(MSMUtils.NS_SEP));
+				// Retrieve the correct set if possible.
+				set = (MetadataSet)mds_hashtable.get(namespace);
+				namespace = null;
+				// Now retrieve the element name.
+				element = name.substring(name.indexOf(MSMUtils.NS_SEP) + 1);
+		  }
+		  else {
+				// No namespace so assume ns = "".
+				set = (MetadataSet)mds_hashtable.get("");
+				element = name;
+		  }
+		  if(set != null) {
+				///ystem.err.print("Trying to match element " + element +"?");
+				Element temp = set.getElement(element);
+				if(temp != null) {
+					 ///ystem.err.println("Found!");
+					 result = new ElementWrapper(temp);
+				}
+				else {
+					 ///ystem.err.println("Not found.");
+				}
+				element = null;
+				temp = null;
+		  }
+		  else {
+				///ystem.err.println("No such set");
+		  }
+		  set = null;
+		  if(result == null) {
+				///ystem.err.println("Shouldn't return null unless this is greenstone archive parsing.");
+		  }
+		  return result;
+	 }
+	 /** Retrieve a certain named element from a certain named set.
+	  * @param set The metadata set whose element you want.
+	  * @param name The name of the element.
+	  * @return An ElementWrapper around the requested element, or null if no such set or element.
+	  */
+	 public ElementWrapper getElement(String set, String name) {
+		  if(mds_hashtable.containsKey(set)) {
+				MetadataSet temp = (MetadataSet)mds_hashtable.get(set);
+				return new ElementWrapper(temp.getElement(name));
+		  }
+		  return null;
+	 }
+	 /** Get all of the metadata elements as an array of nodelists.
+	  * @return A NodeList[] of metadata elements.
+	  */
+	 public NodeList[] getNodeLists() {
+		  NodeList elements[] = null;
+		  int index = 0;
+		  elements = new NodeList[getSets().size()]; // Remember not to count hidden metadata
+		  for(Enumeration keys = mds_hashtable.keys(); keys.hasMoreElements(); ) {
+				MetadataSet mds = (MetadataSet)mds_hashtable.get(keys.nextElement());
+				if(!mds.getNamespace().equals(HIDDEN)) {
+					 elements[index] = mds.getElements();
+					 index++;
+				}
+		  }
+		  return elements;
+	 }
+
+	 /** Retrieve the named metadata set.
+	  * @param name The sets name as a String.
+	  * @return The MetadataSet as named, or null if no such set.
+	  */
+	 public MetadataSet getSet(String name) {
+		  if(mds_hashtable.containsKey(name)) {
+				return (MetadataSet) mds_hashtable.get(name);
+		  }
+		  else {
+				///ystem.err.println("Couldn't find metadata set.");
+				if(name.equals(HIDDEN)) {
+					 return createHidden();
+				}
+		  }
+		  return null;
+	 }
+
+	 /** Method to retrieve all of the metadata sets loaded in this collection. 
+	  * @return A Vector of metadata sets.
+	  */
+	 public Vector getSets() {
+		  return getSets(true);
+	 }
+	 public Vector getSets(boolean include_greenstone) {
+		  Vector result = new Vector();
+		  for(Enumeration keys = mds_hashtable.keys(); keys.hasMoreElements(); ) {
+				MetadataSet set = (MetadataSet)mds_hashtable.get(keys.nextElement());
+				if(!set.getNamespace().equals(HIDDEN) && (include_greenstone || !set.getNamespace().equals(""))) {
+					 result.add(set);
+				}
+		  }
+		  return result;
+	 }
+	 /** Find the total number of elements loaded.
+	  * @return The element count as an int.
+	  */
+	 public int getSize() {
+		  int count = 0;
+		  if(mds_hashtable.size() > 0) {
+				for(Enumeration keys = mds_hashtable.keys(); keys.hasMoreElements();) {
+					 MetadataSet mds = (MetadataSet)mds_hashtable.get(keys.nextElement());
+					 if(mds.getNamespace().equals(HIDDEN)) {
+						  count = count + mds.size();
+					 }
+				}
+		  }
+		  return count;
+	 }
+	 /** Get the value tree that matches the given element.
+	  * @param element The ElementWrapper representing the element.
+	  * @return The GValueModel representing the value tree or null.
+	  */
+	 public GValueModel getValueTree(ElementWrapper element) {
+		  GValueModel value_tree = null;
+		  if(element != null) {
+				String namespace = element.getNamespace();
+				if(namespace.length() > 0) {
+					 MetadataSet mds = (MetadataSet) mds_hashtable.get(namespace);
+					 if(mds != null) {
+						  value_tree = mds.getValueTree(element);
+					 }
+				}
+		  }
+		  return value_tree;
+	 }
+	 /** This method is called to import a metadata set. First a prompt is displayed to gather necessary details such as which metadata set to import. Once this information is gathered the method <i>importMDS(File)</i> is called with the appropriate filename.
+	  * @return A boolean which is <i>true</i> if the metadata set has been imported successfully, <i>false</i> otherwise.
+	  */
+	 public boolean importMDS() {
+		  JFileChooser chooser = new JFileChooser(new File(Utility.METADATA_DIR));
+		  javax.swing.filechooser.FileFilter filter = new MDSFileFilter();
+		  chooser.setFileFilter(filter);
+		  int returnVal = chooser.showDialog(Gatherer.g_man, Gatherer.dictionary.get("MSMPrompt.File_Import"));
+		  if(returnVal == JFileChooser.APPROVE_OPTION) {
+				return importMDS(chooser.getSelectedFile(), true);
+		  }
+		  return false;
+	 }
+
+	 public boolean importMDS(File mds_file, boolean user_driven) {
+		  // 1. Parse the new file.
+		  MetadataSet mds_new = new MetadataSet(mds_file);
+		  // Display a prompt asking how much of the value structure the user wishes to import.
+		  if(user_driven) {
+				ExportMDSPrompt imdsp = new ExportMDSPrompt(this, false);
+				int result = imdsp.display();
+				if(result == ExportMDSPrompt.EXPORT) { // Here export means the user didn't cancel.
+					 switch(imdsp.getSelectedCondition()) {
+					 case MetadataSet.NO_VALUES:
+						  mds_new = new MetadataSet(mds_new, MetadataSet.NO_VALUES);
+						  break;
+					 case MetadataSet.SUBJECTS_ONLY:
+						  mds_new = new MetadataSet(mds_new, MetadataSet.SUBJECTS_ONLY);
+						  break;
+					 default: // ALL_VALUES
+						  // Don't do anything.
+					 }
+				}
+				else {
+					 mds_new = null;
+				}
+				imdsp.dispose();
+				imdsp = null;
+		  }
+		  // Carry on importing the new collection
+		  if(mds_new != null && mds_new.getDocument() != null) {
+				String family = mds_new.getNamespace();
+				// 2. See if we have another metadata set of the same family
+				// already. If so retrieve it and merge.
+				boolean matched = false;
+				for(Enumeration keys = mds_hashtable.keys(); 
+					 keys.hasMoreElements();) {
+					 String key = (String)keys.nextElement();
+					 if(key.equals(family)) {
+						  matched = true;
+						  MetadataSet mds_cur = (MetadataSet)mds_hashtable.get(key);
+						  //ystem.err.println("Merging " + mds_new + " into " + mds_cur);
+						  mergeMDS(mds_cur, mds_new);
+					 }
+				}
+				if(!matched) {
+					 ///ystem.err.println("Mapping " + family + " to " + mds_new);
+					 mds_hashtable.put(family, mds_new);
+				}
+				// Fire setChanged() message.
+				fireSetChanged(mds_new);
+				return true;
+		  }
+		  // else we cancelled for some reason.
+		  return false;
+	 }
+
+	 /** This method reloads all of the metadata sets that have been marked as included in this collection by entries in the collection configuration file. 
+	  */
+	 public void load() {
+		  File source = new File(Gatherer.c_man.getCollectionMetadata());
+		  File files[] = source.listFiles();
+		  for(int i = 0; files != null && i < files.length; i++) {
+				if(files[i].getName().endsWith(".mds")) {
+					 importMDS(files[i], false);
+				}
+		  }
+		  // If no current 'hidden' metadata set exists, create one.
+		  if(getSet(HIDDEN) == null) {
+				createHidden();
+		  }
+	 }
+	 /** This method takes two metadata sets, the current one and a new one, and merges them. This merge takes place at an element level falling to lower levels as necessary (using <i>mergeMDE()</i> to merge elements and <i>mergeMDV()</i> to merge value trees.
+	  * @param mds_current The currently loaded MetadataSet.
+	  * @param mds_new A new MetadataSet you wish to merge in.
+	  * @return A boolean with value <i>true</i> indicating if the merge was successful, otherwise <i>false</i> if errors were detected.
+	  */
+	 public boolean mergeMDS(MetadataSet mds_cur, MetadataSet mds_new) {
+		  // For a super quick check for equivelent trees, we compare the last changed values.
+		  if(mds_cur.getLastChanged().equals(mds_new.getLastChanged())) {
+				// Exactly the same. Nothing to change.
+				return true;
+		  }
+		  // Show initial progress prompt.
+		  prompt.startMerge(mds_new.size());
+		  boolean cancel = false;
+		  // For each element in the new set
+		  for(int i = 0; !cancel && i < mds_new.size(); i++) {
+				boolean cont = false;
+				Element mde_new = mds_new.getElement(i);
+				// See if the element already exists in the current set
+				Element mde_cur = mds_cur.getElement(mde_new.getAttribute("name"));
+				int option = Declarations.NO_ACTION;
+				while(!cont && !cancel) {
+					 // We may be dealing with a brand new element, or possibly a 
+					 // renamed one.
+					 if(mde_cur == null) {
+						  // Provide merge, rename and skip options.
+						  option = prompt.mDSPrompt(mds_cur, null, mds_new, mde_new);
+					 }
+					 else {
+						  // If the two elements have equal structure we only have 
+						  // to worry about merging the values.
+						  if(MSMUtils.elementsEqual(mds_cur, mde_cur, mds_new, mde_new, false)) {
+								cancel = !mergeMDV(mds_cur, mde_cur, mds_new, mde_new);
+								cont = true;
+						  }
+						  else {
+								// Provide add, merge and skip options.
+								option = prompt.mDSPrompt(mds_cur, mde_cur, mds_new, mde_new);
+						  }
+					 }
+					 String reason = null;
+					 switch(option) {
+					 case Declarations.ADD:
+						  // Only available to brand new elements, this options 
+						  // simply adds the element to the set.
+						  reason = mds_cur.addElement(mde_new);
+						  if(reason == null) {
+								cont = true;
+						  }
+						  else {
+								prompt.addFailed(mde_new, reason);
+								cont = false;
+						  }
+						  break;
+					 case Declarations.CANCEL:
+						  cancel = true;
+						  cont = true;
+						  break;
+					 case Declarations.FORCE_MERGE:
+						  // If the mde_cur is null, that means the users has asked
+						  // to merge but hasn't choosen any element to merge with.
+						  // Make the user select an element.
+						  mde_cur = prompt.selectElement(mds_cur);
+					 case Declarations.MERGE:
+						  // This case in turn calls the mergeMDE method to perform
+						  // the actual merging of the Elements.
+						  if(mde_cur != null) {
+								cancel = !mergeMDE(mds_cur, mde_cur, mds_new, mde_new);
+						  }
+						  cont = true;
+						  break;
+					 case Declarations.RENAME:
+						  ///ystem.err.println("Rename element");
+						  // This case adds the Element, but requires the user to 
+						  // enter a unique name.
+						  String new_name = prompt.rename(mde_new);
+						  if(new_name != null && new_name.length() > 0) {
+								reason = mds_cur.addElement(mde_new, new_name);
+								if(reason == null) {
+									 mde_cur = mds_cur.getElement(new_name);
+									 cont = true;
+								}
+								else {
+									 prompt.renameFailed(mde_new, new_name, reason);
+									 cont = false;
+								}
+						  }
+						  else {
+								if(new_name != null) {
+									 prompt.renameFailed(mde_new, new_name, 
+																"MSMPrompt.Invalid_Name");
+								}
+								cont = false;
+						  }
+						  break;
+					 case Declarations.REPLACE:
+						  // Removes the existing Element then adds the new.
+						  mds_cur.removeElement(mde_cur);
+						  reason = mds_cur.addElement(mde_new);
+						  if(reason == null) {
+								cont = true;
+						  }
+						  else {
+								prompt.removeFailed(mde_cur, reason);
+								cont = false;
+						  }
+						  break;
+					 case Declarations.SKIP:
+						  // Does not change the set.
+						  cont = true;
+						  break;
+					 }
+					 // Add this action to profile for later reference.
+					 if(profiler == null) {
+						  ///ystem.err.println("No Profiler");
+					 }
+					 //profiler.addAction(mds_new.getFile().getAbsolutePath(), MSMUtils.getFullName(mde_new), option, MSMUtils.getFullName(mde_cur));
+				}
+				prompt.incrementMerge();
+		  }
+		  prompt.endMerge();
+		  return true;
+	 }
+
+	 /** This method allows for two metadata elements to be merged. Essentially merging existing elements give the users such options as keeping or replacing attribute elements as they are merged.
+	  * @param mde_cur The Element that already exists in the current metadata sets.
+	  * @param mde_new A new Element which has the same name as the current one but different data.
+	  * @return A boolean that if <i>true</i> indicats the action was completed. If <i>false</i> then an error or user action has prevented the merge.
+	  * TODO Implement
+	  */
+	 public boolean mergeMDE(MetadataSet mds_cur, Element mde_cur, MetadataSet mds_new, Element mde_new) {
+		  while(true) {
+				for(Node mdn_new = mde_new.getFirstChild(); mdn_new != null; mdn_new = mdn_new.getNextSibling()) {
+					 // Only merge the nodes whose name is 'Attribute'
+					 if(mdn_new.getNodeName().equals("Attribute")) {
+						  Element att_new = (Element) mdn_new;
+						  // Unfortunately some attributes, such as author, can have several occurances, so match each in turn.
+						  Element temp[] = MSMUtils.getAttributeNodesNamed(mde_cur, att_new.getAttribute("name"));
+						  for(int i = 0; temp != null && i < temp.length; i++) {
+								Element att_cur = temp[i];
+								boolean cont = false;
+								int action = Declarations.NO_ACTION;					 
+								while(!cont) {
+									 if(att_cur != null) {
+										  if(!MSMUtils.attributesEqual(att_cur, att_new)) {
+												action = prompt.mDEPrompt(mde_cur, att_cur, mde_new, att_new);
+										  }
+										  else {
+												action = Declarations.SKIP;
+										  }
+									 }
+									 else {
+										  action = Declarations.ADD;
+									 }
+									 switch (action) {
+									 case Declarations.REPLACE:
+										  // Out with the old.
+										  mde_cur.removeChild(att_cur);
+									 case Declarations.ADD:
+										  // Simply add the new attribute. No clash is possible as we have already tested for it.
+										  MSMUtils.add(mde_cur, att_new);
+										  cont = true;
+										  break;
+									 case Declarations.SKIP:
+										  // Do nothing. Move on to next attribute.
+										  cont = true;
+										  break;
+									 case Declarations.CANCEL:
+										  return false;
+									 default:
+										  cont = false;
+									 }
+								}
+								att_cur = null;
+						  }
+						  temp = null;
+						  att_new = null;
+					 }
+				}
+				return mergeMDV(mds_cur, mde_cur, mds_new, mde_new);
+		  }
+	 }
+	 /** Merge two metadata value trees.
+	  * @param mds_cur The current MetadataSet. 
+	  * @param mde_cur The current Element which acts as a value tree root.
+	  * @param mds_new The MetadataSet we are merging in.
+	  * @param mde_new The Element which acts as a value tree that we are merging in.
+	  */
+	 public boolean mergeMDV(MetadataSet mds_cur, Element mde_cur, 
+									 MetadataSet mds_new, Element mde_new) {
+		  // Remember we may be asked to merge with a current mdv of null.
+		  return MSMUtils.updateValueTree(mds_cur, mde_cur, mds_new, mde_new);
+	 }
+
+	 public void removeElement(ElementWrapper element) {
+		  // Retrieve the metadata set this element belongs to.
+		  String namespace = element.getNamespace();
+		  MetadataSet set = (MetadataSet) mds_hashtable.get(namespace);
+		  if(set != null) {
+				// Bugger. Get the old name -before- we remove the element from the set.
+				String old_name = element.toString();
+				// Remove the element.
+				set.removeElement(element.getElement());
+				// Fire event.
+				fireElementChanged(new MSMEvent(this, null, old_name));
+		  }
+		  else {
+				///ystem.err.println("no such set " + namespace);
+		  }
+		  // No such set. No such element.
+	 }
+	 
+	 /** Remove a piece of metadata from a record or records[] and fire all the relevant events.
+	  * @param records A FileNode[] of records to be changed.
+	  * @param metadata The Metadata to remove.
+	  */
+	 public void removeMetadata(long id, Metadata metadata, FileNode records[]) {
+		  // Reset undo buffer
+		  undo_buffer.clear();
+		  // Simplier than the others. Simply remove the metadata.
+		  int action = MetaEditPrompt.CONFIRM;
+		  // Now remove metadata from the selected file nodes.
+		  for(int i = 0; action != MetaEditPrompt.CANCEL && i < records.length; i++) {
+				action = removeMetadata(id, records[i], metadata, action, (records.length > 1));
+		  }
+		  // If we were cancelled we should undo any changes so far
+		  if(action == MetaEditPrompt.CANCEL) {
+				for(Iterator keys = undo_buffer.keySet().iterator(); keys.hasNext(); ) {
+					 FileNode record = (FileNode) keys.next();
+					 undoRemove(id, record);
+				}
+		  }
+	 }
+	 /** Remove the specified listener from ourselves.
+	  * @param listener The MSMListener in question.
+	  */
+	 public void removeMSMListener(MSMListener listener) {
+		  listeners.remove(listener);
+	 }
+
+	 public void removeSet(MetadataSet set) {
+		  mds_hashtable.remove(set.getNamespace());
+		  fireSetChanged(set);
+	 }
+
+	 /** Rename the identifier of a given element to the name given.
+	  * @param element The metadata element effected, as an ElementWrapper.
+	  * @param new_name The String to use as the new name.
+	  */
+	 public void renameElement(ElementWrapper element, String new_name) {
+		  Element e = element.getElement();
+		  String old_name = element.toString();
+		  MSMUtils.setIdentifier(e, new_name);
+		  fireElementChanged(new MSMEvent(this, element, old_name));
+		  old_name = null;
+		  e = null;
+	 }
+	 /** A method to save the state of this metadata set manager. First we ensure that the names of all included metadata sets have been added to the collection configuration file, then all of the metadata sets contained are exported with full content to the collect/<col_name>/metadata/ directory. 
+	  */
+	 public void save() {
+		  // Create the correct file to save these sets to...
+		  File file = new File(Gatherer.self.getCollectionMetadata());
+		  // And make back ups of all existing metadata set files.
+		  File temp[] = file.listFiles();
+		  for(int i = temp.length - 1; i >= 0; i--) {
+				if(temp[i].getName().endsWith(".mds") || temp[i].getName().endsWith(".mdv")) {
+					 File backup = new File(temp[i].getAbsolutePath() + "~");
+					 backup.deleteOnExit();
+					 if(!temp[i].renameTo(backup)) {
+						  Gatherer.println("Error in MetadataSetManager.save(): FileRenameException");
+					 }
+				}
+		  }
+		  // Now save the latest versions of the metadata sets.
+		  for(Enumeration keys = mds_hashtable.keys(); keys.hasMoreElements(); ) {
+				String namespace = (String) keys.nextElement();
+				MetadataSet set = (MetadataSet) mds_hashtable.get(namespace);
+				try {
+					 File mds_file = null;
+					 if(!namespace.equals("")) {
+						  mds_file = new File(file, set.getNamespace() + ".mds");
+					 }
+					 else {
+						  mds_file = new File(file, "greenstone.mds");
+					 }
+					 Utility.export(set.getDocument(), mds_file);
+					 set.setFile(mds_file);
+					 // Now for each element attempt to save its value tree.
+					 NodeList elements = set.getElements();
+					 for(int i = elements.getLength() - 1;	!namespace.equals("") && i >= 0; i--) {
+						  ElementWrapper value_element = new ElementWrapper((Element)elements.item(i));
+						  GValueModel value_tree = set.getValueTree(value_element);
+						  if(value_tree != null) {
+								File value_file = new File(file, value_element.toString() + ".mdv");
+								///ystem.err.println("Saving value file: " + value_file.toString());
+								Utility.export(value_tree.getDocument(), value_file);
+								// If this is a hierarchy element, write hierarchy file.
+								if(value_element.getNamespace().equals(MetadataSetManager.HIDDEN) || value_tree.isHierarchy()) {
+									 MetadataXML.write(value_tree, this, Gatherer.c_man.getCollectionEtc());
+								}
+						  }
+						  else {
+								///ystem.err.println("No value tree for " + value_element.toString());
+						  }
+					 }
+					 // Note that filenames might have changed so we better warn everyone.
+					 fireSetChanged(set);
+				}
+				catch (Exception error) {
+					 error.printStackTrace();
+				}
+		  }
+		  profiler.save();
+	 }
+	 /** Given a FileNode of the original file and the new FileNode, search for any metadata, either from a greenstone directory archive xml file, or from one of the registered 'plugin' parsers.
+	  * @param source The source FileNode.
+	  * @param destination The new FileNode.
+	  */
+	 public final boolean searchForMetadata(FileNode destination, FileNode source, boolean folder_level) {
+		  return searchForMetadata(destination, source, folder_level, false);
+	 }
+	 public final boolean searchForMetadata(FileNode destination, FileNode source, boolean folder_level, boolean dummy_run) {
+		  Gatherer.println("MetadataSetManager.searchForMetadata()");
+		  return loader.searchForMetadata(destination, source, folder_level, dummy_run);
+	 }
+	 /** Build a vector of all the metadata sets that contain an element with the given name.
+	  * @param name The name of an element as a String.
+	  * @return A Vector of metadata sets.
+	  * @see MSMPrompt (org.greenstone.gatherer.msm.MSMPrompt#selectSet)
+	  */
+	 public Vector setsThatContain(String name) {
+		  Vector result = new Vector();
+		  for(Enumeration keys = mds_hashtable.keys(); keys.hasMoreElements(); ) {
+				MetadataSet set = (MetadataSet) mds_hashtable.get(keys.nextElement());
+				if(set.getElement(name) != null) {
+					 result.add(set);
+				}
+		  }
+		  return result;
+	 }
+
+	 public final int size() {
+		  return getSets().size();
+	 }
+
+	 /** Update a piece of metadata connected to a record or records, ensuring the value tree is built properly, and correct messaging fired.
+	  * @param records A FileNode[] of records, or directories, to add the specified metadata to.
+	  * @param element The metadata element, contained within an ElementWrapper to base metadata on.
+	  * @param value The value to assign to the metadata as a String.
+	  * @return The Metadata we just assigned.
+	  */
+	 public Metadata updateMetadata(long id, Metadata old_metadata, FileNode records[], String value_str, int action) {
+		  // Retrieve the new value node from the same value tree as the old metadata.
+		  ElementWrapper element = old_metadata.getElement();
+		  GValueModel model = getValueTree(element);
+		  GValueNode value = null;
+		  if(model != null) {
+				value = model.addValue(value_str);
+		  }
+		  else {
+				value = new GValueNode(element.toString(), value_str);
+		  }
+		  // Create new metadata.
+		  Metadata new_metadata = new Metadata(value);
+		  // Reset the undo buffer
+		  undo_buffer.clear();
+		  // And update the old with it.
+		  if(action == -1) {
+				action = MetaEditPrompt.CONFIRM;
+		  }
+		  // And then update each selection file node.
+		  for(int i = 0; action != MetaEditPrompt.CANCEL && i < records.length; i++) {
+				action = updateMetadata(id, records[i], old_metadata, new_metadata, action, (records.length > 1));
+		  }
+		  // If we were cancelled we should undo any changes so far
+		  if(action == MetaEditPrompt.CANCEL) {
+				for(Iterator keys = undo_buffer.keySet().iterator(); keys.hasNext(); ) {
+					 FileNode record = (FileNode) keys.next();
+					 undoUpdate(id, record);
+				}
+		  }
+		  // All done. Any events would have been fired within the record recursion.
+		  return new_metadata;
+	 }
+
+	 /** Add a reference to a piece of metadata to the given FileNode. The whole method gets a wee bit messy as we have to allow for several different commands from users such as accumulate / overwrite, skip just this file or cancel the whole batch. Cancelling is especially problematic as we need to rollback any changes (within reason).
+	  * It is also worth mentioning that despite its name, no actual metadata is added directly by this method. Instead a call to fireMetadataChanged() is issued, which is in turn processed by the GDMManager (which, given this method may have been called from GDMManager as well, means the cycle is complete. Um, that doesn't mean theres an infinite loop... I hope).
+	  * @param id a long unique identifier shared by all actions caused by the same gesture.
+	  * @param record the FileNode we are adding the metadata to.
+	  * @param data the new Metadata.
+	  * @param action the default action as an int. May require user interaction.
+	  * @param fire_event <i>true</i> if this action should fire a metadata changed event, <i>false</i> if we are calling this as an affect of a previous event. (Don't want an infinitely recursive loop, do we).
+	  * @param multiple_selection <i>true</i> if more than one file or folder was selected.
+	  * @return an int specifying the current action. Thus changes in lower parts of the tree continue to effect other disjoint subtrees.
+	  */
+	 private int addMetadata(long id, FileNode record, Metadata data, int action, boolean multiple_selection) {
+		  // Super special exception for accumulate all action. We are going to add this metadata anyway, regardless of whats already there, so just add it.
+		  if(action == MetaEditPrompt.ACCUMULATE_ALL || action == MetaEditPrompt.OVERWRITE_ALL) {
+				fireMetadataChanged(id, record, null, data);
+		  }
+		  else {
+				// Recover the metadata from this file.
+				ArrayList metadata = Gatherer.c_man.getCollection().gdm.getMetadata(record.getFile());
+				// Most important test, we don't have to add the metadata if its already there!
+				if(!metadata.contains(data)) {
+					 // Record undo information for this file node.
+					 ArrayList undo = new ArrayList();
+					 // Prepare for MEP
+					 int user_action = MetaEditPrompt.ACCUMULATE;
+					 String values = "";
+					 // See if there is any existing metadata with the same name. If so make a string from all the values (bob, jim etc).
+					 int metadata_size = metadata.size();
+					 for(int i = 0; i < metadata_size; i++) {
+						  Metadata current_data = (Metadata)metadata.get(i);
+						  if(current_data.getElement().equals(data.getElement())) {
+								if(values.length() > 0) {
+									 values = values + ", ";
+								}
+								values = values + current_data.getValue();
+						  }
+					 }
+					 // If we are confirming prompt for user_action.
+					 if(values.length() > 0 && action == MetaEditPrompt.CONFIRM) {
+						  MetaEditPrompt mep = new MetaEditPrompt(MetaEditPrompt.ADD_PROMPT, multiple_selection);
+						  user_action = mep.display(record.toString(), data.getElement().toString(), values, data.getValue());
+					 }
+					 if(user_action == MetaEditPrompt.ACCUMULATE_ALL || user_action == MetaEditPrompt.CANCEL || user_action == MetaEditPrompt.OVERWRITE_ALL) {
+						  action = user_action;
+					 }
+					 // If we are overwriting we first remove all metadata with the same element, unless the metadata is non-file level is which case we leave it, and hope the accumulate vs overwrite will be followed during the determining of metadata assigned.
+					 if(action == MetaEditPrompt.OVERWRITE_ALL || user_action == MetaEditPrompt.OVERWRITE) {
+						  for(int i = metadata_size; i != 0; i--) {
+								Metadata old_data = (Metadata)metadata.get(i - 1);
+								if(old_data.getElement().equals(data.getElement()) && old_data.isFileLevel()) {
+									 // We have a match. Remove this metadata.
+									 fireMetadataChanged(id, record, old_data, null);
+									 // Add it to our undo buffer.
+									 undo.add(old_data);
+								}
+						  }
+					 }
+					 // Ensure the metadata will accumulate or overwrite as the user wishes.
+					 if(user_action == MetaEditPrompt.ACCUMULATE || user_action == MetaEditPrompt.ACCUMULATE_ALL) {
+						  data.setAccumulate(true);
+					 }
+					 else if(user_action == MetaEditPrompt.OVERWRITE || user_action == MetaEditPrompt.OVERWRITE_ALL) {
+						  data.setAccumulate(false);
+					 }
+					 // Unless cancelled, add the metadata after checking we don't already have it in the metadata (obviously not if we're overwriting but we'd better check anyway). Also if we've skipped the file we should do so, but move on to the next child...
+					 if((user_action == MetaEditPrompt.ACCUMULATE || user_action == MetaEditPrompt.ACCUMULATE_ALL || user_action == MetaEditPrompt.OVERWRITE || user_action == MetaEditPrompt.OVERWRITE_ALL) && !metadata.contains(data)) {
+						  ///ystem.err.println("Adding metadata " + data);
+						  fireMetadataChanged(id, record, null, data);
+						  // The last element in undo is the new element.
+						  undo.add(data);
+					 }
+					 // Store the undo list in our undo buffer.
+					 undo_buffer.put(record, undo);
+				}
+		  }
+		  // If we've been cancelled, roll back the addition.
+		  if(action == MetaEditPrompt.CANCEL) {
+				undoAdd(id, record);
+		  }
+		  return action;
+	 }
+	 /** addMetadata(long, FileNode, Metadata, int, boolean) */
+
+	 /** Create the hidden mds, used for custom classifiers. */
+	 private MetadataSet createHidden() {
+		  MetadataSet hidden_mds = new MetadataSet(Utility.METADATA_SET_TEMPLATE);
+		  hidden_mds.setAttribute("creator","The Gatherer");
+		  hidden_mds.setAttribute("contact","gatherer@greenstone");
+		  hidden_mds.setAttribute("description","A hidden metadata set used to create custom classifiers.");
+		  hidden_mds.setAttribute("family","Gatherer Hidden Metadata");
+		  hidden_mds.setAttribute("lastchanged","");
+		  hidden_mds.setAttribute("name","Gatherer Hidden Metadata");
+		  hidden_mds.setAttribute("namespace",HIDDEN);
+		  mds_hashtable.put(HIDDEN, hidden_mds);
+		  fireSetChanged(hidden_mds);
+		  return hidden_mds;
+	 }
+
+	 /** Creates a new profiler, which in turn will attempt to load previous profile information. */
+	 private void loadProfiler() {
+		  profiler = new MSMProfiler();
+		  addMSMListener(profiler);
+	 }
+
+	 /** In order to remove metadata from the tree you first call this method providing it with the metadata you want removed. This will remove any occurance of said metadata from the given FileNode (using fireMetadataChanged()).
+	  * @param id a unique long identifier common to all actions caused by a single gesture.
+	  * @param record the FileNode who we are removing metadata from.
+	  * @param data the <strong>Metadata</strong> you wish removed from the tree.
+	  * @param action an <i>int</i> specifying the wanted prompting action.
+	  * @param fire_event <i>true</i> if this action should fire metadata changed events.
+	  * @param multiple_selection the number of records in the selection, as an <i>int</i>. Used to determine prompt controls.
+	  * @return an <i>int</i> specifying the current action. Thus changes in lower parts of the tree continue to effect other disjoint subtrees.
+	  */
+	 private int removeMetadata(long id, FileNode record, Metadata data, int action, boolean multiple_selection) {
+		  ArrayList metadata = Gatherer.c_man.getCollection().gdm.getMetadata(record.getFile());
+		  int user_action = MetaEditPrompt.REMOVE;
+		  // See if we even have this metadata.
+		  if(metadata.contains(data)) {
+				ArrayList undo = new ArrayList();
+				// We do have it. If action == CONFIRM, show user prompt.
+				if(action == MetaEditPrompt.CONFIRM) {
+					 MetaEditPrompt mep = new MetaEditPrompt(MetaEditPrompt.REMOVE_PROMPT, multiple_selection);
+					 user_action = mep.display(record.toString(), data.getElement().toString(), data.getValue());
+				}
+				// Set action to match the user_action under certain circumstances.
+				if(user_action == MetaEditPrompt.CANCEL || user_action == MetaEditPrompt.REMOVE_ALL) {
+					 action = user_action;
+				}
+				if(action == MetaEditPrompt.REMOVE_ALL || user_action == MetaEditPrompt.REMOVE) {
+					 fireMetadataChanged(id, record, data, null);
+					 undo.add(data);
+				}
+				// Store undo information
+				undo_buffer.put(record, data);
+		  }
+		  // If we've been cancelled higher up, undo action.
+		  if(action == MetaEditPrompt.CANCEL) {
+				undoRemove(id, record);
+		  }
+		  return action;
+	 }
+
+	 /** Rollback any changes made as part of a single metadata add process (only valid during the action itself, ie if a user presses cancel).
+	  * @param id the unique identify of all actions created as part of a single gesture, as a <i>long</i>.
+	  * @param record the FileNode whose metadata was changed.
+	  */
+	 private void undoAdd(long id, FileNode record) {
+		  // Retrieve the undo data from the buffer
+		  ArrayList undo = (ArrayList) undo_buffer.get(record);
+		  // If there is no undo then we can't do anything, but there should be
+		  if(undo != null && undo.size() > 0) {
+				// The last piece of data in an add actions undo buffer is the metadata that was added
+				Metadata data = (Metadata) undo.remove(undo.size() - 1);
+				// Remove the data
+				fireMetadataChanged(id, record, data, null);
+				// If we removed other metadata when adding this metadata restore it too
+				for(int i = 0; i < undo.size(); i++) {
+					 Metadata old_data = (Metadata) undo.get(i);
+					 fireMetadataChanged(id, record, null, old_data);
+				}
+		  }
+	 }
+	 /** Rollback any changes made as part of a single metadata remove process (only valid during the action itself, ie if a user presses cancel).
+	  * @param id the unique identify of all actions created as part of a single gesture, as a long.
+	  * @param record the FileNode metadata was removed from.
+	  */
+	 private void undoRemove(long id, FileNode record) {
+		  // Retrieve undo information
+		  ArrayList undo = (ArrayList) undo_buffer.get(record);
+		  // Ensure that we have something to undo
+		  if(undo != null && undo.size() == 1) {
+				// The undo buffer should contain exactly one entry, the metadata removed
+				Metadata data = (Metadata) undo.get(0);
+				fireMetadataChanged(id, record, null, data);
+		  }
+	 }
+	 /** Roll back any changes made as part of a single metadata update process (only valid during the action itself, ie if a user presses cancel).
+	  * @param id the unique identify of all actions created as part of a single gesture, as a long.
+	  * @param record the FileNode whose metadata was changed.
+	  */
+	 private void undoUpdate(long id, FileNode record) {
+		  // Retrieve undo information
+		  ArrayList undo = (ArrayList) undo_buffer.get(record);
+		  if(undo != null && undo.size() == 2) {
+				Metadata old_data = (Metadata) undo.get(0);
+				Metadata new_data = (Metadata) undo.get(1);
+				fireMetadataChanged(id, record, new_data, null);
+				fireMetadataChanged(id, record, null, old_data);
+		  }
+	 }
+
+	 /** Used to update the values of one of the metadata elements within this node. Has the same trickiness as Add but only half the number of options.
+	  * @param id the unique identify of all actions created as part of a single gesture, as a <i>long</i>.
+	  * @param record the FileNode whose metadata we are changing.
+	  * @param old_data The old existing <strong>Metadata</strong>.
+	  * @param new_data The new updated <strong>Metadata</strong>.
+	  * @param action An <i>int</i> indicating what we are going to do about it.
+	  * @param multiple_selection The number of records in the selection, as an <i>int</i>. Used to determine prompt controls.
+	  * @return An <i>int</i> specifying the current action. Thus changes in lower parts of the tree continue to effect other disjoint subtrees.
+	  */
+	 private int updateMetadata(long id, FileNode record, Metadata old_data, Metadata new_data, int action, boolean multiple_selection) {
+		  ArrayList metadata = Gatherer.c_man.getCollection().gdm.getMetadata(record.getFile());
+		  int user_action = MetaEditPrompt.UPDATE;
+		  // Standard case of updating an existing metadata value.
+		  if(metadata.contains(old_data)) {
+				ArrayList undo = new ArrayList();
+				// If we are to prompt the user, do so.
+				if(action == MetaEditPrompt.CONFIRM) {
+					 MetaEditPrompt mep = new MetaEditPrompt(MetaEditPrompt.UPDATE_PROMPT, multiple_selection);
+					 user_action = mep.display(record.toString(), old_data.getElement().toString(), old_data.getValue(), new_data.getValue());
+				}
+				// Some user actions should have a continuous effect.
+				if(user_action == MetaEditPrompt.UPDATE_ALL || user_action == MetaEditPrompt.CANCEL) {
+					 action = user_action;
+				}
+				// And if the update chose update, do so.
+				if(action == MetaEditPrompt.UPDATE_ALL || user_action == MetaEditPrompt.UPDATE || action == MetaEditPrompt.UPDATE_ONCE) {
+					 ///ystem.err.println("Updating:\n"+old_data+"\nto\n"+new_data);
+					 fireMetadataChanged(id, record, old_data, new_data);
+					 undo.add(old_data);
+					 undo.add(new_data);
+				}
+				// Store the undo information
+				undo_buffer.put(record, undo);
+		  }
+		  // If we've been cancelled undo.
+		  if(action == MetaEditPrompt.CANCEL) {
+				undoUpdate(id, record);
+		  }
+		  return action;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/msm/parsers/GreenstoneMetadataParser.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/msm/parsers/GreenstoneMetadataParser.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/msm/parsers/GreenstoneMetadataParser.java	(revision 13666)
@@ -0,0 +1,896 @@
+package org.greenstone.gatherer.msm.parsers;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.io.*;
+import java.lang.ref.*;
+import java.net.*;
+import java.util.*;
+import java.util.regex.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.cdm.CommandTokenizer;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.Metadata;
+import org.greenstone.gatherer.msm.MetadataParser;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.greenstone.gatherer.util.DecodeHTMLReader;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.valuetree.GValueModel;
+import org.greenstone.gatherer.valuetree.GValueNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+/** Provides a metadata parser implementation that knows how to locate, prepare for, then import metadata from a previous Greenstone collection. Is aware of such factors as the presence of Metadata Set files and hierarchy files. Updates the profiler where possible to allow for faster subsequent imports from a certain collection. Caches all the information about encountered collections in CollectCFG objects which are softly cached (ie are cached, but are reclaimed before an OutOfMemory exception would be thrown). 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class GreenstoneMetadataParser
+	 extends LinkedHashMap
+	 implements MetadataParser {
+
+	 static final private int MAX_CFG_CACHE_SIZE = 10;
+	 static final private int MAX_GDM_CACHE_SIZE = 10;
+	 /** The default name and location for a collection configuration file (presuming that a collection file prefix will be added). */
+	 static final private String CONFIG_FILENAME = "etc" + File.separator + "collect.cfg";
+	 /** The pattern to match when searching for directory level assignments. */
+	 static final private String DIRECTORY_FILENAME = ".*";
+	 static final private String DIRECTORY_FILENAME_SUFFIX = "/.*";
+	 static final private String DESCRIPTION_ELEMENT = "Description";
+	 static final private String FILENAME_ELEMENT = "FileName";
+	 static final private String FILESET_ELEMENT = "FileSet";
+	 /** The name of a gdm file. */
+	 static final private String GIMPORT = "gimport";
+	 static final private String IMPORT = "import";
+	 static final private String METADATA_ELEMENT = "Metadata";
+	 static final private String METADATA_XML_FILENAME = "metadata.xml";
+	 static final private String MODE_ATTRIBUTE = "mode";
+	 static final private String NAME_ATTRIBUTE = "name";
+
+	 /** A list of the collect.cfg paths that we should ignore. */
+	 private ArrayList ignore_list = new ArrayList();
+	 /** Has this process been cancelled. */
+	 private boolean dialog_cancelled = false;
+	 /** A cache of previously parsed collection configuration files. */
+	 private CollectCFGCache cfg_cache = new CollectCFGCache();
+	 /** A mapping from BasicMetadata to their fully enabled Metadata incarnation. */
+	 private HashMap transform = new HashMap();
+
+	 /** Default constructor needed for dynamic class loading. */
+	 public GreenstoneMetadataParser() {
+	 }
+	 /** Locate and import any metadata parsed by this metadata parser given the file involved and its previous incarnation. */
+	 public boolean process(FileNode destination, FileNode origin, boolean folder_level, boolean dummy_run) {
+		  Gatherer.println("GreenstoneMetadataParser: Process " + origin + ": ");
+		  int counter = 0;
+		  dialog_cancelled = false;
+
+		  // 1. Determine what collection the file is in, and load/parse the appropriate collect.cfg. Cache collect.cfg object.
+		  ///ystem.err.print("1 ");
+		  // Start at the origin node file. If its a file get its parent directory.
+		  File collection_dir = origin.getFile();
+		  if(collection_dir.isFile()) {
+				collection_dir = collection_dir.getParentFile();
+		  }
+		  // We're currently in the importing directory so we'll go one more step up.
+		  collection_dir = collection_dir.getParentFile();
+		  // We are looking for a directory which contains a etc/collect.cfg file and either an import or a gimport directory.
+		  boolean found = false;
+		  while(!found && collection_dir != null) {
+				File possible_cfg_file = new File(collection_dir, CONFIG_FILENAME);
+				File possible_gimport_directory = new File(collection_dir, GIMPORT);
+				File possible_import_directory = new File(collection_dir, IMPORT);
+				if(possible_cfg_file.exists() && (possible_gimport_directory.exists() || possible_import_directory.exists())) {
+					 found = true;
+					 ///ystem.err.println("Found greenstone collection at " + collection_dir.getAbsolutePath());
+				}
+				else {
+					 collection_dir = collection_dir.getParentFile();
+				}
+		  }
+
+		  // Now retrieve the configuration file if there is one.
+		  CollectCFG collect_cfg = null;
+		  if(collection_dir != null) {
+				File collect_cfg_file = new File(collection_dir, CONFIG_FILENAME);
+				if(collect_cfg_file.exists()) {
+					 collect_cfg = cfg_cache.get(collect_cfg_file);
+				}
+		  }
+
+		  // Continue only if we are sure this is a greenstone collection
+		  if(collection_dir != null && collect_cfg != null) {
+				// 2. Attempt to merge in any mdses and make note of those that are successfully imported (by removing reference from collect.cfg).
+				///ystem.err.print("2 ");
+				ArrayList mdses = collect_cfg.getMetadataSets();
+				for(int i = 0; i < mdses.size(); i++) {
+					 File mds_file = (File) mdses.get(i);
+					 Gatherer.c_man.getCollection().msm.importMDS(mds_file, false);
+				}
+				mdses.clear();
+				mdses = null;
+
+				// 3. Locate all of the metadata.xml files that may have an affect on the origin file. Make sure the metadata.xml closest to the origin files directory is last (to ensure property inheritance regarding accumulate/overwrite).
+				///ystem.err.print("3 ");
+				ArrayList search_files = new ArrayList();
+				File file = origin.getFile();
+				String filename = null;
+				if(file.isFile()) {
+					 filename = file.getName();
+					 file = file.getParentFile();
+				}
+				while(!file.equals(collection_dir)) {
+					 File test_file = new File(file, Utility.METADATA_XML);
+					 if(test_file.exists()) {
+						  search_files.add(0, new MetadataXMLFileSearch(test_file, filename));
+					 }
+					 if(filename != null) {
+						  filename = file.getName() + "/" + filename;
+					 }
+					 else {
+						  filename = file.getName() + "/";
+					 }
+					 file = file.getParentFile();
+				}
+				filename = null;
+				file = null;
+				// Start with an initially empty ArrayList of metadata
+				ArrayList metadatum = new ArrayList();
+				// Now search each of these metadata xml for metadata, remembering to accumulate or overwrite as we go along.
+				for(int i = 0; i < search_files.size(); i++) {
+					 MetadataXMLFileSearch a_search = (MetadataXMLFileSearch) search_files.get(i);
+					 ///ystem.err.println("Search " + a_search.file.getAbsolutePath() + " for " + (a_search.filename != null ? a_search.filename : "directory metadata"));
+					 // Retrieve the document
+					 BasicGDMDocument document = getDocument(a_search.file);
+					 if(document != null) {
+						  // If this is a dummy run, our original source file is actually the metadata.xml file and we retrieve all metadata for this collection, as if accumulated!
+						  if(dummy_run) {
+								metadatum = document.getAllMetadata();
+						  }
+						  else {
+								metadatum = document.getMetadata(a_search.filename, metadatum, true);
+						  }
+						  document = null;
+					 }
+					 a_search = null;
+				}
+				search_files = null;
+				// Finally assign the metadata
+				///ystem.err.println("Found " + metadatum.size() + " pieces of metadata for " + destination);
+				if(metadatum.size() > 0) {
+					 addMetadata(destination, metadatum, collection_dir, collect_cfg, dummy_run);
+				}
+		  }
+		  else {
+				///ystem.err.println("Not a greenstone collection (no collect.cfg found).");
+		  }
+		  return dialog_cancelled;
+	 }
+
+	 protected boolean removeEldestEntry(java.util.Map.Entry entry) {
+		  return (size() > MAX_GDM_CACHE_SIZE);
+	 }
+
+	 private void addMetadata(FileNode destination, ArrayList metadatum, File collection_dir, CollectCFG collect_cfg, boolean dummy_run) {
+		  ///ystem.err.print("6 ");
+		  // Used in a complicated test later on.
+		  ArrayList inherited_metadata = null;
+		  if(destination != null) {
+				inherited_metadata = Gatherer.c_man.getCollection().gdm.getMetadata(destination.getFile());
+		  }
+		  else {
+				inherited_metadata = new ArrayList();
+		  }
+		  for(int i = 0; !dialog_cancelled && i < metadatum.size(); i++) {
+				BasicMetadata basic_metadata = (BasicMetadata) metadatum.get(i);
+				BasicMetadata metadata = (BasicMetadata) metadatum.get(i);
+				metadata.collection = collection_dir;
+				Metadata final_metadata = null;
+				// If this BasicMetadata already exists in the transform cache then we can save ourselves a lot of work.
+				SoftReference reference = (SoftReference) transform.get(basic_metadata);
+				if(reference != null) {
+					 final_metadata = (Metadata) reference.get();
+				}
+				if(final_metadata == null) {
+					 ///ystem.err.println("No existing Metadata object for BasicMetadata: " + basic_metadata);
+					 // 6a. Check if an hfile is associated with this metadata, and if so load it, cache it in the collection.cfg object, then resolve metadata value index.
+					 HFile h_file = collect_cfg.getHFile(metadata.element);
+					 if(h_file != null && !dummy_run) {
+						  ///ystem.err.print(metadata.value + " maps to ");
+						  metadata.value = h_file.getValue(metadata.value);
+						  ///ystem.err.println(metadata.value);
+					 }
+					 h_file = null;
+					 // 6b. Check if there is a profile regarding the current metadata.
+					 ///ystem.err.println("Retrieve existing action: " + collection_dir.getAbsolutePath() + ", " + metadata.element);
+					 if(Gatherer.c_man.getCollection().msm.profiler.containsAction(collection_dir.getAbsolutePath(), metadata.element)) {
+						  String new_element_name = Gatherer.c_man.getCollection().msm.profiler.getAction(collection_dir.getAbsolutePath(), metadata.element);
+						  ///ystem.err.println("Profile result = " + new_element_name);
+						  if(new_element_name == null) {
+								metadata = null;
+						  }
+						  else {
+								metadata.element = new_element_name;
+						  }
+						  new_element_name = null;
+					 }
+					 ///atherer.println("Assigning metadata.");
+					 if(metadata != null) {
+						  // 6c. Try to add metadata. If there is no matching metadata element:
+						  ElementWrapper element = Gatherer.c_man.getCollection().msm.getElement(metadata.element);
+						  // Arg. The element returned may come from the Greenstone dls, which of course should never be involved during importing. To solve check the namespace isn't "" and if it is nullify the element. Nullify. NULLIFY, Bwuhahahaha...
+						  if(element != null && element.getNamespace().equals("")) {
+								element = null;
+						  }
+						  // 6ci. If no match exists, prompt the user to add/merge with specific metadata element. The user can also choose to ignore this metadata.
+						  if(element == null) {
+								element = selectElement(metadata.element);
+								if(!dialog_cancelled) {
+									 // 6ciii. If either of the above work, remember to add to profile.
+									 if(element == null) {
+										  ///ystem.err.println("Adding profile action: " + collection_dir.getAbsolutePath() + ", " + metadata.element + ", null");
+										  Gatherer.c_man.getCollection().msm.profiler.addAction(collection_dir.getAbsolutePath(), metadata.element, null);
+									 }
+									 else {
+										  ///ystem.err.println("Adding profile action: " + collection_dir.getAbsolutePath() + ", " + metadata.element + ", " + element.getName());
+										  Gatherer.c_man.getCollection().msm.profiler.addAction(collection_dir.getAbsolutePath(), metadata.element, element.getName());
+									 }
+								}
+						  }
+						  // - Add metadata
+						  if(!dummy_run && element != null && !dialog_cancelled) {
+								///ystem.err.println("Retrieve the value tree for " + element.toString());
+								GValueModel model = Gatherer.c_man.getCollection().msm.getValueTree(element);
+								if(model != null) {
+									 GValueNode node = model.addValue(metadata.value);
+									 final_metadata = new Metadata(element, node);
+									 ///ystem.err.println("Adding final metadata: " + metadata.toString());
+									 node = null;
+								}
+								model = null;
+						  }
+						  element = null;
+					 }
+					 // If we have successfully created a Metadata from the BasicMetadata, store it
+					 if(final_metadata != null && !dialog_cancelled) {
+						  transform.put(basic_metadata, new SoftReference(final_metadata));
+						  ///ystem.err.println("Add a Metadata object for BasicMetadata: " + basic_metadata);
+					 }
+				}
+				else {
+					 ///ystem.err.println("Found a Metadata object for BasicMetadata: " + basic_metadata);
+				}
+				if(!dummy_run && final_metadata != null && !dialog_cancelled) {
+					 final_metadata.setAccumulate(metadata.accumulates);
+					 // There is one final test, caused by the advent of directory vs file level metadata, but its a mouthfull to explain. And it goes a little something like this: 
+					 // When you drag in a single file you want to record all of the metadata, both file and directory level, associated with it. If a user later sets directory level metadat this is overridden by directory level metadat present at file level in this file then that is just too bad. For example a user gathers a file, ec121e.htm, into a their folder 'docs/'. ec121e.htm has amoungst its metadata 'Date=01-01-01' which it inherited from its folder (ec121e/). Later the user sets 'Date=15-06-03' for the folder 'docs/'. The Date metadata now at the file level of ec121e.htm will now overwrite any such setting, which wouldn't have happened if magically the folder level metadata had stayed folder level. Of course thats some impossible magic due to the fact that source folder structure is unlikely to match destination level when moving individual files, and even asking for the metadata the the new file will inherit won't help (except by chance). 
+					 // Now consider a user dragging in a folder containing several files or folders. Essentially the same tatic taken above is used for the top level folder being moved, in that any and all metadata, inherited or no, is added to this new folder in the collection. However when adding subsequent files and folders it becomes possible to notice if inherited metadata is already set (just ask the collections GDMManager what metadata is available for a certain file -before- the file is actually added to the collection. This being the case only those unique metadata should subsequently be added to the file. Note that these unique metadata may still include directory level metadata that would have been better off added to a folder, but since none is available we make do.
+					 if(!inherited_metadata.contains(final_metadata) || final_metadata.accumulates()) {
+						  // Now we can finally add the metadata.
+						  Gatherer.c_man.getCollection().msm.fireMetadataChanged(0, destination, null, final_metadata);
+					 }
+					 else {
+						  ///ystem.err.println("Metadata already exists: " + final_metadata);
+					 }
+				}
+				// Otherwise there is no way to add this metadata. No value model no metadata value.
+				final_metadata = null;
+				metadata = null;
+		  }
+	 }
+
+	 /** Determine the different suffix between two string.
+	  * @param base_str The base <strong>String</strong>, expected to be the short of the two strings provided.
+	  * @param target_str The target <strong>String</strong>, whose differing suffix is returned.
+	  * @return A <strong>String</strong> containing the suffix from target which is different from base.
+	  */
+	 private String diff(String base_str, String target_str) {
+		  StringTokenizer base_tokenizer = new StringTokenizer(base_str, File.separator);
+		  StringTokenizer target_tokenizer = new StringTokenizer(target_str, File.separator);
+		  String base = null;
+		  String target = null;
+		  while(base_tokenizer.hasMoreTokens() && (base = base_tokenizer.nextToken()).equals((target = target_tokenizer.nextToken()))) {
+		  }
+		  StringBuffer result = new StringBuffer(target);
+		  while(target_tokenizer.hasMoreTokens()) {
+				result.append(File.separator);
+				result.append(target_tokenizer.nextToken());
+		  }
+		  return result.toString();
+	 }
+
+	 /** Retrieve the BasicGDMDocument found at the given file, or null if there is no such file or if it isn't a valid BasicGDMDocument. */
+	 private BasicGDMDocument getDocument(File file) {
+		  ///ystem.err.println("Get Document at: " + file.getAbsolutePath());
+		  BasicGDMDocument document = null;
+		  if(!ignore_list.contains(file) && file.exists()) {
+				// Check cache
+				SoftReference reference = (SoftReference) get(file);
+				if(reference != null) {
+					 ///ystem.err.println("Hit!!");
+					 document = (BasicGDMDocument) reference.get();
+					 reference = null;
+				}
+				// If that didn't work try to parse in the document
+				if(document == null) {
+					 ///ystem.err.println("Miss or stale reference.");
+					 document = new BasicGDMDocument(file);
+					 if(document.isValid()) {
+						  put(file, new SoftReference(document));
+					 }
+					 else {
+						  ///ystem.err.println(file.getAbsolutePath() + " is not a valid GDM XML file.");
+						  ignore_list.add(file);
+						  document = null;
+					 }
+				}
+		  }
+		  else {
+				///ystem.err.println("Ignoring file or file doesn't exists.");
+		  }
+		  return document;
+	 }
+
+
+	 /** Display a prompt allowing a user to select a metadata element to attempt to force add/merge or ignore a metadata element to. For instance an old version of a metadata.xml from the DLS collection might have an assigned metadata value "Publisher=EC Courier", however Publisher won't automatically match to any metadata set. This prompt will be displayed, and some effort will be made to systematically locate the appropriate set. In this case this should be the DLS metadata set as dls.Publisher should be the closest match. Regardless the element selected is returned.
+	  * @param element_name The name of the element we are trying to add, as a <strong>String</strong>.
+	  * @return The <strong>ElementWrapper</strong> choosen by the user, or <i>null</i> to skip this metadata element.
+	  */
+	 private ElementWrapper selectElement(String element_name) {
+		  ElementWrapper result = Gatherer.c_man.getCollection().msm.prompt.selectElement(element_name);
+		  dialog_cancelled = Gatherer.c_man.getCollection().msm.prompt.wasDialogCancelled();
+		  return result;
+	 }
+
+	 /** A 'basic' version of the more complete GDMDocument used elsewhere, this object provides the same functionality except that it doesn't use Metadata objects. These objects require live references to elements within the MetadataSetManager and GValueModels, but these may not yet exist (and indeed may never exist) for metadata parsed from metadata.xml's outside of our current collection. Thus this class returns a String (or an ArrayList of Strings) when asked for the metadata associated with a certain file. Also notice that this class provides no constructor method for creating a blank document, nor does it ever need a reference to the Gatherer.*/
+	 private class BasicGDMDocument 
+		  extends HashMap {
+		  /** The document this class sources its data from. */
+		  private Document base_document;
+		  /** This constructor takes the original document and parsed out and stores metadata with its association to filenames. */
+		  public BasicGDMDocument(File file) {
+				///ystem.err.println("New BasicGDMDocument: " + file.getAbsolutePath());
+				base_document = Utility.parse(file.getAbsolutePath(), false);
+		  }
+		  /** Retrieve all of the metadata in this file. */
+		  public ArrayList getAllMetadata() {
+				ArrayList metadatum = new ArrayList();
+				// Don't search the cache as this would never have been added.
+				try {
+					 // Retrieve the document element.
+					 Element directorymetadata_element = base_document.getDocumentElement();
+					 // Iterate through the filesets, checking the FileName child element against 	the target file's name using regular expression matching.
+					 NodeList fileset_elements = directorymetadata_element.getElementsByTagName(FILESET_ELEMENT);
+					 for(int i = 0; i < fileset_elements.getLength(); i++) {
+						  Element fileset_element = (Element) fileset_elements.item(i);
+						  NodeList filename_elements = fileset_element.getElementsByTagName(FILENAME_ELEMENT);
+						  for(int j = 0; j < filename_elements.getLength(); j++) {
+								Element filename_element = (Element) filename_elements.item(j);
+								// If they match add all of the metadata found in the Description child element, overwriting any metadata with the same element
+								NodeList description_elements = fileset_element.getElementsByTagName(DESCRIPTION_ELEMENT);
+								for(int k = 0; k < description_elements.getLength(); k++) {
+									 Element description_element = (Element) description_elements.item(k);
+									 NodeList metadata_elements = description_element.getElementsByTagName(METADATA_ELEMENT);
+									 for(int l = 0; l < metadata_elements.getLength(); l++) {
+										  Element metadata_element = (Element) metadata_elements.item(l);
+										  String element = metadata_element.getAttribute(NAME_ATTRIBUTE);
+										  BasicMetadata metadata = new BasicMetadata(element, Utility.METADATA_XML, true);
+										  // Remove any previous values for this metadata element.
+										  for(int m = metadatum.size() - 1; m >= 0; m--) {
+												BasicMetadata old_metadata = (BasicMetadata) metadatum.get(m);
+												if(old_metadata.element.equals(element)) {
+													 metadatum.remove(m);
+												}
+												old_metadata = null;
+										  }
+										  // Add the completed metadata and clean up
+										  metadatum.add(metadata);
+										  metadata = null;
+										  element = null;
+										  metadata_element = null;
+									 }
+									 metadata_elements = null;
+									 description_element = null;
+								}
+								description_elements = null;
+								filename_element = null;
+						  }
+						  filename_elements = null;
+						  fileset_element = null;
+					 }
+					 fileset_elements = null;
+					 directorymetadata_element = null;
+				}
+				catch (Exception error) {
+					 Gatherer.self.printStackTrace(error);
+				}
+				return metadatum;
+		  }
+		  
+		  /** Retrieve any metadata associated with a certain file. If filename is null we are attempting to find directory level metadata. */
+		  public ArrayList getMetadata(String filename, ArrayList metadatum_so_far, boolean folder_level) {
+				///ystem.err.println("Retrieving metadata for: " + filename);
+				ArrayList metadatum = null;
+				// We start by attempting to retrieve this metadata from the cache.
+				if(filename != null) {
+					 metadatum = (ArrayList) get(filename);
+				}
+				else {
+					 metadatum = (ArrayList) get(DIRECTORY_FILENAME);
+				}
+				// If that failed we consult the document for metadata.
+				if(metadatum == null) {
+					 metadatum = new ArrayList();
+					 if(metadatum_so_far == null) {
+						  metadatum = new ArrayList();
+					 }
+					 else {
+						  metadatum = metadatum_so_far;
+					 }
+					 try {
+						  // Retrieve the document element.
+						  Element directorymetadata_element = base_document.getDocumentElement();
+						  // Iterate through the filesets, checking the FileName child element against 	the target file's name using regular expression matching.
+						  NodeList fileset_elements = directorymetadata_element.getElementsByTagName(FILESET_ELEMENT);
+						  for(int i = 0; i < fileset_elements.getLength(); i++) {
+								Element fileset_element = (Element) fileset_elements.item(i);
+								NodeList filename_elements = fileset_element.getElementsByTagName(FILENAME_ELEMENT);
+								for(int j = 0; j < filename_elements.getLength(); j++) {
+									 Element filename_element = (Element) filename_elements.item(j);
+									 String filename_text = MSMUtils.getValue(filename_element);
+									 // Crappy. There are apparently two ways of assigning, say, directory level metadata to anything in the ac01ne directory from a parent directories metadata.xml.
+									 // The developers guide way: ac01ne/.*
+									 // The dls way: ac01ne
+									 // So the three tests are
+									 ///ystem.err.println("Check for:");
+									 ///ystem.err.println("filename != null && '" + filename + "'.matches('" + filename_text + "') = " + (filename != null ? filename.matches(filename_text) : false));
+									 ///ystem.err.println("filename != null && '" + filename + "'.matches('" + filename_text + DIRECTORY_FILENAME_SUFFIX + "') = " + (filename != null ? filename.matches(filename_text + DIRECTORY_FILENAME_SUFFIX) : false));
+									 ///ystem.err.println("filename == null && '" + filename_text + "'.equals('.*') = " + (filename == null ? filename_text.equals(DIRECTORY_FILENAME) : false));
+									 if((filename != null && (filename.matches(filename_text) || filename.matches(filename_text + DIRECTORY_FILENAME_SUFFIX))) 
+										 || (filename == null && filename_text.equals(DIRECTORY_FILENAME))) {
+										  ///ystem.err.println("Match!!!");
+										  // If they match add all of the metadata found in the Description child element, remembering to abide by desired mode (accumulate vs. overwrite).
+										  NodeList description_elements = fileset_element.getElementsByTagName(DESCRIPTION_ELEMENT);
+										  for(int k = 0; k < description_elements.getLength(); k++) {
+												Element description_element = (Element) description_elements.item(k);
+												NodeList metadata_elements = description_element.getElementsByTagName(METADATA_ELEMENT);
+												for(int l = 0; l < metadata_elements.getLength(); l++) {
+													 Element metadata_element = (Element) metadata_elements.item(l);
+													 String element = metadata_element.getAttribute(NAME_ATTRIBUTE);
+													 ///ystem.err.println("Found element: " + element);
+													 //String language = metadata_element.getAttribute("language");
+													 String mode = metadata_element.getAttribute(MODE_ATTRIBUTE);
+													 // Add the new metadata to our list of metadata for this target file.
+													 String value = Utility.stripNL(MSMUtils.getValue(metadata_element));
+													 ///ystem.err.println("Found value: " + element);
+													 BasicMetadata metadata = new BasicMetadata(element, value, mode.equals("accumulate"));
+													 // If mode is overwrite, then remove any previous values for this metadata element.
+													 if(!metadata.accumulates) {
+														  for(int m = metadatum.size() - 1; m >= 0; m--) {
+																BasicMetadata old_metadata = (BasicMetadata) metadatum.get(m);
+																if(old_metadata.element.equals(element)) {
+																	 metadatum.remove(m);
+																}
+																old_metadata = null;
+														  }
+													 }
+													 mode = null;
+													 
+													 // Add the completed metadata and clean up
+													 metadatum.add(metadata);
+													 metadata = null;
+													 value = null;
+													 element = null;
+													 metadata_element = null;
+												}
+												metadata_elements = null;
+												description_element = null;
+										  }
+										  description_elements = null;
+									 }
+									 else {
+										  ///ystem.err.println("No Match!");
+									 }
+									 filename_text = null;
+									 filename_element = null;
+								}
+								filename_elements = null;
+								fileset_element = null;
+						  }
+						  fileset_elements = null;
+						  directorymetadata_element = null;
+					 }
+					 catch (Exception error) {
+						  Gatherer.self.printStackTrace(error);
+					 }
+					 // Cache the result, given that these external metadata.xmls are taken to be static at the time of reading (if you happen to be sourcing information from a opened collection that someone is working on, too bad.
+					 if(filename != null) { 
+						  put(filename, metadatum);
+					 }
+					 else {
+						  put(DIRECTORY_FILENAME, metadatum);
+					 }
+				}
+				return metadatum;
+		  }
+		  
+		  /** Determine is this is a valid Greenstone Directory Metadata file. It may of course just be some xml file with the name metadata.xml. */
+		  public boolean isValid() {
+				// Just determine if the doctype is GreenstoneDirectoryMetadata and root node is called DirectoryMetadata.
+				String doctype_name = base_document.getDoctype().getName();
+				String root_name = base_document.getDocumentElement().getTagName();
+				return ((doctype_name.equals("DirectoryMetadata") || doctype_name.equals("GreenstoneDirectoryMetadata")) && (root_name.equals("DirectoryMetadata") || root_name.equals("GreenstoneDirectoryMetadata")));
+		  }
+
+		  /** Decode a string that was previously made Perl safe.
+			* @param safe The encoded <strong>String</strong> where dangerous characters have been escaped.
+			* @return A <strong>String</strong> with all the escaping removed.
+			*/
+		  private String decode(String safe) {
+				String dangerous = safe.replaceAll("\\\\.",".");
+				return dangerous;
+		  }
+	 }
+	 /** A simplistic version of metadata, with no live references. */
+	 private class BasicMetadata 
+		  implements Comparable {
+		  public boolean accumulates;
+		  /** The collection this metadata was extracted from. Important when attempting to map BasicMetadata to its Metadata incarnation. */
+		  public File collection;
+		  /** The metadata element. */
+		  public String element = null;
+		  /** The value. */
+		  public String value = null;
+		  /** Constructor takes initial values for element and value. 
+			* @param element The metadata element as a <strong>String</strong>.
+			* @param value The value as a <strong>String</strong>.
+			*/
+		  public BasicMetadata(String element, String value, boolean accumulates) {
+				this.accumulates = accumulates;
+				this.element = element;
+				this.value = value;
+		  }
+
+		  public int compareTo(Object other) {
+				return toString().compareTo(other.toString());
+		  }
+		  /** Compare two BasicMetadata objects for equality.
+			* @param object The other <strong>Object</strong>.
+			* @return <i>true</i> if this BasicMetadata matches the given object, <i>false</i> otherwise.
+			*/
+		  public boolean equals(Object object) {
+				BasicMetadata other = (BasicMetadata) object;
+				if(collection != null) {
+					 return (collection.equals(other.collection) && element.equals(other.element) && value.equals(other.value));
+				}
+				return (element.equals(other.element) && value.equals(other.value)); 
+		  }
+		  public String toString() {
+				return element + " = " + value;
+		  }
+	 }
+
+	 /** This class provides a cache for the instances of parsed collect.cfg files and their associated data. Assures that the most recently cached CollectCFG will remain available. Older objects are maintained as soft references and are freed at the JVM implementations descretion, but are gareunteed to be garbage collected before an OutOfMemory exception is thrown. */
+	 private class CollectCFGCache
+		  extends LinkedHashMap {
+		  /** Retrieve the CollectCFG object that matches the given collection file path.
+			* @param collection_file The <strong>File</strong> that references the collection's directory.
+			* @return The <strong>CollectCFG</strong> that belongs to this collection, or <i>null</i> if no such file exists (so we probably aren't in a collection!).
+			*/
+		  public CollectCFG get(File collect_cfg_file) {
+				///ystem.err.println("Retrieve the collection configuration file at: " + collect_cfg_file);
+				CollectCFG collect_cfg = null;
+				// Attempt to load from cache.
+				SoftReference reference = (SoftReference) super.get(collect_cfg_file);
+				// If is doesn't exist, either because its never been loaded, or thats its cache reference has gone stale, attempt to load it again.
+				if(reference == null || (collect_cfg = (CollectCFG)reference.get()) == null) {
+					 try {
+						  collect_cfg = new CollectCFG(collect_cfg_file);
+						  put(collect_cfg_file, new SoftReference(collect_cfg));
+					 }
+					 catch(Exception error) {
+						  Gatherer.printStackTrace(error);
+						  collect_cfg = null;
+					 }
+				}
+				return collect_cfg;
+		  }
+
+		  protected boolean removeEldestEntry(java.util.Map.Entry entry) {
+				return (size() > MAX_CFG_CACHE_SIZE);
+		  }
+	 }
+
+	 /** The CollectCFG object encapsulates important metadata information extracted from a collect.cfg file, such as required metadata sets, and hfile associations. As the former are merged, their references are removed from this object, whereas the for the later references are replaced a representation of the hfile itself. */
+	 private class CollectCFG {
+		  /** A list of the metadata sets associated with the collect.cfg file. */
+		  private ArrayList metadatasets = null;
+		  /** A hash mapping from metadata element name to hierarchy file, or possibly hierarchy object. */
+		  private HashMap hfiles = null;
+		  /** The token at the start of a classify command line within the collect.cfg. */
+		  static final private String CLASSIFY_COMMAND = "classify";
+		  /** The token at the start of a metadataset command line within the collect.cfg. */
+		  static final private String METADATASET_COMMAND = "metadataset";
+		  /** Constructor which takes a file assumed to be the location of a collect.cfg file belonging to a Greenstone Collection.
+			* @param file A <strong>File</strong> referencing a collect.cfg file.
+			*/
+		  public CollectCFG(File file) 
+				throws Exception {
+				///atherer.println("Loading a new collection configuration file: " + file.getAbsolutePath());
+				File etc_directory = file.getParentFile();
+				hfiles = new HashMap();
+				metadatasets = new ArrayList();
+				FileReader reader = new FileReader(file);
+				BufferedReader in = new BufferedReader(reader);
+				String command = null;
+				while((command = in.readLine()) != null) {
+					 CommandTokenizer tokenizer = new CommandTokenizer(command);
+					 if(tokenizer.hasMoreTokens()) {
+						  String token = tokenizer.nextToken().toLowerCase();
+						  if(token.equals(METADATASET_COMMAND)) {
+								String family_name = tokenizer.nextToken(); 
+								String file_str = tokenizer.nextToken();
+								if(file_str.startsWith("\"") && file_str.endsWith("\"") && !file_str.equals("\"\"")) {
+									 file_str = file_str.substring(1, file_str.length() - 1);
+								}
+								// If the file str is -only- the filename then we add <col_dir>/metadata/
+								File mds_file = null;
+								if(file_str.indexOf(File.separator) == -1) {
+									 mds_file = new File(file.getParentFile().getParentFile(), File.separator + "metadata" + File.separator + file_str);
+								}
+								else {
+									 mds_file = new File(file_str);
+								}
+								///ystem.err.println("Attempting to file mds file at " + file.getAbsolutePath());
+								if(mds_file.exists()) {
+									 metadatasets.add(mds_file);
+								}
+								mds_file = null;
+								file_str = null;
+								family_name = null;
+						  }
+						  // Also look for any classify commands that include an hfile and element
+						  else if(token.equals(CLASSIFY_COMMAND)) {
+								String hfile_name = null;
+								String element_name = null;
+								// Drop the classifier name
+								tokenizer.nextToken();
+								while(tokenizer.hasMoreTokens()) {
+									 token = tokenizer.nextToken().toLowerCase();
+									 if(token.equals("-hfile")) {
+										  hfile_name = tokenizer.nextToken();
+									 }
+									 else if(token.equals("-metadata")) {
+										  element_name = tokenizer.nextToken();
+									 }
+								}
+								if(hfile_name != null && element_name != null) {
+									 // If hfile_name has no path, append the etc directories one. Either way create a file reference
+									 File hfile = null;
+									 hfile_name = hfile_name.replace('\\', File.separatorChar);
+									 hfile_name = hfile_name.replace('/', File.separatorChar);
+									 if(hfile_name.indexOf(File.separator) == -1) {
+										  hfile = new File(etc_directory, hfile_name);
+									 }
+									 else {
+										  hfile = new File(hfile_name);
+									 }
+									 // Add to hfiles
+									 ///atherer.println("Adding hfile reference: " + element_name + " -> " + hfile);
+									 hfiles.put(element_name, hfile);
+									 hfile = null;
+								}
+								element_name = null;
+								hfile_name = null;
+						  }
+						  tokenizer = null;
+					 }
+				}
+				command = null;
+				in.close();
+				reader.close();
+				in = null;
+				reader = null;
+				// Now we search the etc directory for *.txt files which we attempt to parse as hfiles
+				File children[] = etc_directory.listFiles(); // We are sure there is at least one, collect.cfg
+				for(int i = 0; i < children.length; i++) {
+					 // If this is a text file, extract the element name and process
+					 String name = children[i].getName();
+					 if(children[i].isFile() && name.endsWith(".txt")) {
+						  String element_name = name.substring(0, name.lastIndexOf("."));
+						  if(!hfiles.containsKey(element_name)) {
+								///atherer.println("Adding hfile reference: " + element_name + " -> " + children[i]);
+								hfiles.put(element_name, children[i]);
+						  }
+						  element_name = null;
+					 }
+					 name = null;
+				}
+				children = null;
+				etc_directory = null;
+				file = null;
+		  }
+		  /** Attempts to retrieve the HFile object associated with a certain metadata element. This may have already been cached, or may need to be loaded. Then again it may not even be necessary.
+			* @param element The fully qualified name of a metadata element, as a <strong>String</strong>.
+			* @return The <strong>HFile</strong> associated with the given element, or <i>null</i> if its unnecessary.
+			* @see org.greenstone.gatherer.cdm.CommandTokenizer
+			*/
+		  public HFile getHFile(String element) {
+				HFile result = null;
+				Object target = hfiles.get(element);
+				// If target is non-null
+				if(target != null) {
+					 // If we haven't already load and parse the file.
+					 if(target instanceof File) {
+						  ///ystem.err.println("\nHFILE-MISS!! Loading " + target.toString());
+						  result = new HFile();
+						  try {
+								FileReader in_filereader = new FileReader((File)target);
+								//DecodeHTMLReader in_decodehtmlreader = new DecodeHTMLReader(in_filereader);
+								BufferedReader in = new BufferedReader(in_filereader);
+								String line = null;
+								while((line = in.readLine()) != null) {								
+									 CommandTokenizer tokenizer = new CommandTokenizer(line);
+									 String alias = Utility.decodeGreenstone(tokenizer.nextToken());
+									 String index = tokenizer.nextToken();
+									 String value = Utility.decodeGreenstone(tokenizer.nextToken());
+									 ///ystem.err.println("Read " + index + ", " + alias + ", " + value);
+									 if(alias.startsWith("\"") && alias.endsWith("\"") && !alias.equals("\"\"")) {
+										  alias = alias.substring(1, alias.length() - 1);
+									 }
+									 if(value.startsWith("\"") && value.endsWith("\"") && !value.equals("\"\"")) {
+										  value = value.substring(1, value.length() - 1);
+									 }
+									 result.add(index, alias, value);
+									 value = null;
+									 alias = null;
+									 index = null;
+									 tokenizer = null;
+								}
+								line = null;
+								in.close();
+								in = null;
+								//in_decodehtmlreader = null;
+								in_filereader = null;
+								hfiles.put(element, result);
+						  }
+						  catch (Exception error) {
+								error.printStackTrace();
+								hfiles.remove(element);
+						  }
+					 }
+					 else {
+						  ///ystem.err.print("HFILE-HIT!!! ");
+						  result = (HFile) target;
+					 }
+				}
+				// Else no hfile is needed for this element
+				target = null;
+				return result;
+		  }
+		  /** Retrieve the list of metadata sets associated with this collection.
+			* @return An <strong>ArrayList</strong> of metadata set Files.
+			*/
+		  public ArrayList getMetadataSets() {
+				return metadatasets;
+		  }
+	 }
+
+	 /** The HFile object provides a container for the mappings from indexes, of the form 1.1.1, to alias-value pairs. It also provides method to retrieving the alias and value for a certain element, remembering that values must be expressed in terms of their absolute subject heirarchy path. */
+	 private class HFile 
+		  extends HashMap {
+		  /** Construct a new HFile object with no initial values. */
+		  public HFile() {
+				super();
+		  }
+		  /** Add a new (index,(alias, value)) mapping.
+			* @param index The index of this mapping as a <strong>String</strong>.
+			* @param alias The alias of this mapping as a <strong>String</strong>.
+			* @param value And finally the value of this mapping as a, you guessed it, <strong>String</strong>.
+			*/
+		  public void add(String index, String alias, String value) {
+				Entry entry = new Entry(index, alias, value);
+				///ystem.err.println("Adding entry: " + index + " \"" + alias + "\" \"" + value + "\"");
+				put(index, entry);
+				put(alias, entry);
+		  }
+		  public String getAlias(String index) {
+				String alias = "";
+				Entry entry = (Entry) get(index);
+				if(entry != null) {
+					 alias = entry.alias;
+				}
+				entry = null;
+				return alias;
+		  }
+		  /** Retrieve the value associated with a certain index. This is harder than it first sounds as you must take into account the parent indexes of this one.
+			* @param index The index whose value you wish to calculate, as a <strong>String</strong>.
+			* @return The fully quantified path to the value that matches index, also as a <strong>String</strong>. Delimitiation between subject layers is denoted by the character '/'
+			*/
+		  public String getValue(String index) {
+				///ystem.err.println("Retrieve value for the alias/index: '" + index + "'");
+				StringBuffer value = new StringBuffer("");
+				// If index isn't the index, it must be the alias. Replace it with the index dammit.
+				Entry entry = null;
+				if(!Utility.isIndex(index)) {
+					 ///ystem.err.println("\tThis is an alias.");
+					 // Store this for later, as its exactly the same entry we'd get had we found the last component of a proper index.
+					 entry = (Entry) get(index);
+					 index = entry.index;
+					 ///ystem.err.println("\tIndex is actually: " + index);
+				}
+				// Now build the hierarchy if necessary.
+				int dot_index = -1;
+				if((dot_index = index.indexOf(".")) != -1) {
+					 ///ystem.err.println("\tHierarchy information required -->");
+					 value.append(getValue(index.substring(0, dot_index)));
+					 value.append("\\");
+					 ///ystem.err.println("\t<-- Hierarchy information complete");
+				}
+				if(entry == null) {
+					 entry = (Entry) get(index);
+				}
+				if(entry != null) {
+					 value.append(entry.value);
+				}
+				entry = null;
+				///ystem.err.println("\tFinal value is: '" + value.toString() + "'\n");
+				return value.toString();
+		  }
+
+		  private class Entry {
+				public String alias = null;
+				public String index = null;
+				public String value = null;
+				public Entry(String index, String alias, String value) {
+					 this.alias = alias;
+					 this.index = index;
+					 this.value = value;
+				}
+		  }
+	 }
+
+	 private class MetadataXMLFileSearch {
+		  public File file;
+		  public String filename;
+		  public MetadataXMLFileSearch(File file, String filename) {
+				this.file = file;
+				this.filename = filename;
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/sarm/SearchAndReplace.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/sarm/SearchAndReplace.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/sarm/SearchAndReplace.java	(revision 13666)
@@ -0,0 +1,849 @@
+package org.greenstone.gatherer.sarm;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+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.Gatherer;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.gui.CollectionPane;
+import org.greenstone.gatherer.gui.MetaEditPane;
+import org.greenstone.gatherer.gui.MetaEditPrompt;
+import org.greenstone.gatherer.gui.table.GTableModel;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.Metadata;
+import org.greenstone.gatherer.util.EnumeratedVector;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.XORToggleButtonGroup;
+import org.greenstone.gatherer.valuetree.GValueModel;
+import org.greenstone.gatherer.valuetree.GValueNode;
+/** Provides a convenient class which searches through all of the various data attached to a collection, globally searching and replacing values as necessary, and firing the relevant events to have the gui update properly. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.3
+ */
+public class SearchAndReplace
+	 extends JDialog {
+	 /** <i>true</i> if this dialog should allow for the replace and replace all buttons to be validated, <i>false</i> otherwise. */
+	 private boolean enable_replace = false;
+	 /** <i>true</i> if the last call to find() found something, <i>false</i> otherwise. */
+	 private boolean found = false;
+	 /** The size of the current screen real-estate. */
+	 private Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
+	 /** The metadata element that we are currently inspecting. If we are anywhere but within the find() function, then this is the last element found that matched the search string. */
+	 private ElementWrapper current_element = null;
+	 /** A vector containing the result of a depth first enumeration of the records in the collection record set tree. */
+	 private EnumeratedVector records = null;
+	 /** The file record that we are currently inspecting. If we are anywhere but within the find() function, and the target type is a FileNode, then this is the last record that matched our search string. Otherwise this is the record that the last metadata value that matched resides in. */
+	 private FileNode current_record = null;
+	 /** The button used to close the dialog. Has the same action as the destroy button. */
+	 private JButton close_button = null;
+	 /** The button used to begin a find() function call. Something must be typed in the search field before this button becomes active. */
+	 private JButton find_button = null;
+	 /** The button used to repeat the find() call in order to find the next matching object. Note this only becomes active after a successful find button press. */
+	 private JButton find_next_button = null;
+	 /** Redoes the action the was last undoes. Doesn't become active until there are job that are undone to be redone. :P */
+	 private JButton redo_button = null;
+	 /** Replaces the currently selected object with the given replacement text. The selection was determined by find() either as part of a previous action, or immediately before the replace() is called. This button only become active if there is something typed in the search and replace fields and if enable_replace is set. */
+	 private JButton replace_button = null;
+	 /** Replace all occurances of the search string with the replace string. This returns to the start of the collection and replaced every single matching reference. It only becomes enabled if something is typed in the search and replace fields and enable_replace is set. */
+	 private JButton replace_all_button = null;
+	 /** When pressed this button returns the 'searching pointer' back to the start of the collection. This is used when there are no further matches for your query, or at anytime you wish to start a new query. This button only becomes active after a success find(). */
+	 private JButton reset_button = null;
+	 /** This button undoes any changes made by the previous action, such as restoring all objects affected by a replace all. It only makes sense for this button to be active after a successful action. */
+	 private JButton undo_button = null;
+	 /** When checked this control indicates the search comparisons should be made taking into account case. Otherwise the case becomes irrelevant to matching. */
+	 private JCheckBox case_sensitive = null;
+	 /** When checked the SARM treats both search and replace string as regular expression when matching and replacing. */
+	 private JCheckBox regular_expression = null;
+	 /** When checked the SARM will search the metadata element identifiers for values that match your search string. Note that at least one of the search domains is selected at all times. */
+	 private JCheckBox search_elements = null;
+	 /** When checked the SARM will search the file records in the collection for values that match your search string. Note that at least one of the search domains is selected at all times. */
+	 private JCheckBox search_records = null;
+	 /** When checked the SARM will search the metadata values associated with each file record in the collection for values that match your search string. Note that at least one of the search domains is selected at all times. */ 
+	 private JCheckBox search_values = null;
+	 /** The status label shows the result of the last action. */
+	 private JLabel status = null;
+	 /** This field is used to enter a string which is in turn used to replace any text value that matches the search string. If enable_replace is not set, this field remains grayed out. If enabled, and you type within this field the replace buttons will become active. */
+	 private JTextField replace = null;
+	 /** The value entered in the search field is used to determine what object should be selected and brought to your attention. Note that this field can contain plain text or a regular expression, and that any typing in this field automatically resets the find() functions state to the start of the collection. */
+	 private JTextField search = null;
+	 /** Whenever a string is tested against the compiled regular Pattern, a Matcher is created. Not only does this matcher allow us to determine if the test string matches the pattern, but is can be subsequently used during a replace action to evaluate special 'capture group flags' within a regular expression based replace string.<BR><BR>For instance:Seach - '(.*)fug(.*)' will match 'Refugee'<BR>and<BR>Replace - '\1\1\1. \2' will replace the match with 'ReReRe. ee'. */
+	 private Matcher matcher = null;
+	 /** This is the current metadata value that we are inspecting. If non-null anywhere other then in the find() method, then this is the last metadata value that matched on search string. However it makes no sense by itself, and current_record is needed to actually reference this piece of metadata. */
+	 private Metadata current_value = null;
+	 /** This is used to determine the target class of any object whose text component we are trying to replace. It is actually set to the last object that matched the search string. */
+	 private Object target = null;
+	 /** This object is created by compiling a regular expression string retrieved from the search field, and in only non-null when regualr_expressions is checked. By compiling it once at the very beginning of the find() method, we lower processing time. Note that pattern is set to null whenever the find() state is reset. */ 
+	 private Pattern pattern = null;
+	 /** A reference to ourselves so that our inner classes can dispose of us for the insurance money. */
+	 private SearchAndReplace self = null;
+	 /** A stack of actions that have been undone, wait to be done again. */
+	 private Stack redo = new Stack();
+	 /** A stack of actions that have been done, waiting to undo. */
+	 private Stack undo = new Stack();
+	 /** A vector of the metadata elements attached to this collection, in the form of ElementWrappers for ease of data access. */ 
+	 private Vector elements = null;
+	 /** The default size for a label, used to produce purty column alignment. */
+	 static final private Dimension LABEL_SIZE = new Dimension(120, 30);
+	 /** The default size for the dialog. */
+	 static final private Dimension SIZE = new Dimension(640,210);
+	 /** Constructor.
+	  * @param enable_replace <i>true</i> if this dialog can be used for replace actions, <i>false</i> otherwise.
+	  */
+	 public SearchAndReplace(boolean enable_replace) {
+		  super();
+		  ///ystem.err.println("Creating a new search and replace dialog.");
+		  this.enable_replace = enable_replace;
+		  this.self = this;
+		  // Creation
+		  setModal(false);
+		  setSize(SIZE);
+		  setTitle(get("Title"));
+		  JPanel content_pane = (JPanel) getContentPane();
+
+		  JPanel central_pane = new JPanel();
+
+		  JPanel search_pane = new JPanel();
+		  JLabel search_label = new JLabel(get("Search"));
+		  search_label.setPreferredSize(LABEL_SIZE);
+		  search = new JTextField("");
+
+		  JPanel replace_pane = new JPanel();
+		  JLabel replace_label = new JLabel(get("Replace"));
+		  replace_label.setPreferredSize(LABEL_SIZE);
+		  replace = new JTextField("");
+		  replace.setEnabled(enable_replace);	  
+		  if(!enable_replace) {
+				replace.setBackground(Color.lightGray);
+		  }
+
+		  JPanel options_pane = new JPanel();
+		  JLabel options_label = new JLabel(get("Options"));
+		  options_label.setPreferredSize(LABEL_SIZE);
+		  JPanel inner_options_pane = new JPanel();
+		  case_sensitive = new JCheckBox(get("Case_Sensitive"));
+		  regular_expression = new JCheckBox(get("Regular_Expression"));
+		  
+		  JPanel options2_pane = new JPanel();
+		  JLabel options2_label = new JLabel(get("Search_In"));
+		  options2_label.setPreferredSize(LABEL_SIZE);
+		  JPanel inner_options2_pane = new JPanel();
+		  XORToggleButtonGroup check_box_group = new XORToggleButtonGroup();
+		  search_elements = new JCheckBox(get("Search_Elements"));
+		  search_elements.setSelected(true);
+		  check_box_group.add(search_elements);
+		  search_records = new JCheckBox(get("Search_Records"));
+		  search_records.setSelected(true);
+		  check_box_group.add(search_records);
+		  search_values = new JCheckBox(get("Search_Values"));
+		  search_values.setSelected(true);
+		  check_box_group.add(search_values);
+
+		  JPanel results_pane = new JPanel();
+		  status = new JLabel(get("Status"));
+
+		  JPanel buttons_pane = new JPanel();
+		  find_button = new JButton(get("Find_Button"));
+		  find_button.setMnemonic(KeyEvent.VK_F);
+		  find_next_button = new JButton(get("Find_Next_Button"));
+		  find_next_button.setEnabled(false);
+		  find_next_button.setMnemonic(KeyEvent.VK_N);
+		  replace_button = new JButton(get("Replace_Button"));
+		  replace_button.setEnabled(false);
+		  replace_button.setMnemonic(KeyEvent.VK_R);
+		  replace_all_button = new JButton(get("Replace_All_Button"));
+		  replace_all_button.setEnabled(false);
+		  replace_all_button.setMnemonic(KeyEvent.VK_N);
+		  reset_button = new JButton(get("Reset"));
+		  reset_button.setEnabled(false);
+		  reset_button.setMnemonic(KeyEvent.VK_ESCAPE);
+		  undo_button = new JButton(get("Undo"));
+		  undo_button.setEnabled(false);
+		  undo_button.setMnemonic(KeyEvent.VK_U);
+		  redo_button = new JButton(get("Redo"));
+		  redo_button.setEnabled(false);
+		  redo_button.setMnemonic(KeyEvent.VK_D);
+		  close_button = new JButton(get("General.Close"));
+		  close_button.setMnemonic(KeyEvent.VK_C);
+		  // Connection
+		  close_button.addActionListener(new CloseActionListener());
+		  find_button.addActionListener(new FindActionListener());
+		  find_next_button.addActionListener(new FindNextActionListener());
+		  redo_button.addActionListener(new RedoActionListener());
+		  replace.addActionListener(new FindActionListener());
+		  replace_button.addActionListener(new ReplaceActionListener());
+		  replace_all_button.addActionListener(new ReplaceAllActionListener());
+		  reset_button.addActionListener(new ResetActionListener());
+		  undo_button.addActionListener(new UndoActionListener());
+		  replace.addKeyListener(new ReplaceKeyListener());
+		  search.addKeyListener(new SearchKeyListener());
+		  // Layout
+		  search_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+
+		  search_pane.setLayout(new BorderLayout());
+		  search_pane.add(search_label, BorderLayout.WEST);
+		  search_pane.add(search, BorderLayout.CENTER);
+
+		  replace_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+		  
+		  replace_pane.setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
+		  replace_pane.setLayout(new BorderLayout());
+		  replace_pane.add(replace_label, BorderLayout.WEST);
+		  replace_pane.add(replace, BorderLayout.CENTER);
+
+		  inner_options_pane.setLayout(new GridLayout(1,2));
+		  inner_options_pane.add(case_sensitive);
+		  inner_options_pane.add(regular_expression);
+
+		  options_pane.setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
+		  options_pane.setLayout(new BorderLayout());
+		  options_pane.add(options_label, BorderLayout.WEST);
+		  options_pane.add(inner_options_pane, BorderLayout.CENTER);
+
+		  inner_options2_pane.setLayout(new GridLayout(1,3));
+		  inner_options2_pane.add(search_elements);
+		  inner_options2_pane.add(search_records);
+		  inner_options2_pane.add(search_values);
+
+		  options2_pane.setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
+		  options2_pane.setLayout(new BorderLayout());
+		  options2_pane.add(options2_label, BorderLayout.WEST);
+		  options2_pane.add(inner_options2_pane, BorderLayout.CENTER);
+
+		  results_pane.setBorder(BorderFactory.createRaisedBevelBorder());
+		  results_pane.setLayout(new BorderLayout());
+		  results_pane.add(status, BorderLayout.CENTER);
+
+		  central_pane.setLayout(new GridLayout(5,1));
+		  central_pane.add(search_pane);
+		  central_pane.add(replace_pane);
+		  central_pane.add(options_pane);
+		  central_pane.add(options2_pane);
+		  central_pane.add(results_pane);
+		  
+		  buttons_pane.setBorder(BorderFactory.createEmptyBorder(2,0,0,0));
+		  buttons_pane.setLayout(new GridLayout(2,4));
+		  buttons_pane.add(find_button);
+		  buttons_pane.add(find_next_button);
+		  buttons_pane.add(replace_button);
+		  buttons_pane.add(replace_all_button);
+		  buttons_pane.add(reset_button);
+		  buttons_pane.add(undo_button);
+		  buttons_pane.add(redo_button);
+		  buttons_pane.add(close_button);
+
+		  content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		  content_pane.setLayout(new BorderLayout());
+		  content_pane.add(central_pane, BorderLayout.CENTER);
+		  content_pane.add(buttons_pane, BorderLayout.SOUTH);
+		  // Reset data.
+		  reset();
+		  // Restore visual position.
+		  setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
+		  show();
+	 }
+	 /** Updates the status bar to reflect the result of the latest action. Includes the ability to reset the status label whenever the find() state resets.
+	  * @param key A <strong>String</strong> of text to use as the explaination of the actions result.
+	  * @param optional_count An <i>int</i> which if any value, other than -1, shows the number of objects the action was performed on. 
+	  */
+	 private void changeStatus(String key, int optional_count) {
+		  String args[] = null;
+		  if(optional_count >= 0) {
+				args = new String[2];
+				args[1] = "" + optional_count + "";
+		  }
+		  else {
+				args = new String[1];
+		  }
+		  if(key != null) {
+				args[0] = search.getText();
+				status.setText(get("Status") + ": " + get(key, args));
+		  }
+		  else {
+				status.setText(get("Status"));
+		  }
+	 }
+	 /** The guts of this module, the find method, in conjunction with the matches method, searches through the several targetted domains looking for values which match the search string, returning true while leaving itself in a state that points to the matching object if one is found. What exact part of each object is matched against is decided by the objects type, and in one case this is made even more complex as one type of object exists inside the other so we need to carefully iterate through the inner before increamenting the outer. 
+	  * @param <i>true</i> if a match was found thus the current_<object> parameters are pointing to it, otherwise <i>false</i>.
+	  */
+	 private boolean find() {
+		  boolean local_found = false;
+		  String find_str = search.getText();
+		  if(find_str.length() > 0) {
+				// If a pattern currently hasn't been compiled, compile one.
+				if(pattern == null) {
+					 // If no actual regular expression script is present add .* to either end of the search string so we actually search for content of the target string not exact equality.
+					 if(!regular_expression.isSelected()) {
+						  find_str = "(.*)("+find_str+")(.*)";  
+					 }
+					 // Compile pattern
+					 try {
+						  if(case_sensitive.isSelected()) {
+								pattern = Pattern.compile(find_str);
+						  }
+						  else {
+								pattern = Pattern.compile(find_str.toLowerCase());
+						  }
+					 }
+					 catch(Exception error) {
+					 }
+				}
+				// Search through the metadata elements if required for a matching entry.
+				if(search_elements.isSelected()) {
+					 for(int i = (current_element != null ? elements.indexOf(current_element) + 1 : 0); !local_found && i < elements.size(); i++) {
+						  current_element = (ElementWrapper) elements.get(i);
+						  if(match(current_element.getIdentity())) {
+								local_found = true;
+								target = current_element;
+								fireSelect(current_element);
+						  }
+					 }
+				}
+				// Search through file names.
+				if(!local_found && (search_records.isSelected() || search_values.isSelected()) && (records.hasMoreElements() || current_record != null)) {
+					 if(current_record == null) {
+						  current_record = (FileNode)records.nextElement();
+					 }
+					 while(!local_found && (current_record != null || records.hasMoreElements())) {
+						  // Try to match current record (if we haven't already).
+						  if(match(current_record.toString()) && search_records.isSelected() && current_record != target) {
+								local_found = true;
+								target = current_record;
+								fireSelect(current_record);
+						  }
+						  else {
+								// Search through metadata values is required.
+								if(search_values.isSelected()) {
+									 ArrayList metadatum = Gatherer.c_man.getCollection().gdm.getMetadata(current_record.getFile());
+									 for(int i = (current_value != null ? metadatum.indexOf(current_value) + 1 : 0); !local_found && i < metadatum.size(); i++) {
+										  current_value = (Metadata)metadatum.get(i);
+										  if(match(current_value.getValue())) {
+												local_found = true;
+												target = current_value;
+												fireSelect(current_record, current_value);
+										  }
+									 }
+									 if(!local_found) {
+										  current_value = null;
+									 }
+								}
+						  }
+						  if(!local_found) {
+								current_record = (FileNode)records.nextElement();
+						  }
+					 }
+				}
+		  }
+		  return local_found;
+	 }
+	 /** When a metadata element that matches our search string is found, this method is called to provide a visual cue as to what element matched in which collection. This is done by changing the tab view of the main gui and selecting the correct line from the list of sets/elements on one screen of the CDM. This method subsequently calls unhideBound() passing in the bounds of the selected component (cell or row). 
+	  * @param element The <strong>ElementWrapper</strong> that matches our search string.
+	  */
+	 private void fireSelect(ElementWrapper element) {
+		  // Ensure the CDM view is visible.
+		  Gatherer.g_man.setSelectedView(Gatherer.g_man.config_pane);
+		  // Select the correct metadata element
+		  Rectangle bounds = Gatherer.g_man.config_pane.setSelectedElement(element);
+		  unhideSelection(bounds);
+	 }
+	 /** When a file record that matches our search string is found, this method is called to provide a visual cue as to what file matched. This is done by changing the tab view of the main gui and expanding and selecting the correct line from the tree of file records. This method subsequently calls unhideBound() passing in the bounds of the selected component (cell or row). 
+	  * @param record The <strong>FileNode</strong> that matches our search string.
+	  */
+	 private void fireSelect(FileNode record) {
+		  // Ensure that either the CollectionPane or the MetaEditPane is visible. If not make the CollectionPane visible.
+		  Gatherer.g_man.setSelectedView(Gatherer.g_man.collection_pane);
+		  // Select the appropriate record.
+		  TreePath path = new TreePath(record.getPath());
+		  Rectangle bounds = Gatherer.g_man.collection_pane.expandPath(path);
+		  unhideSelection(bounds);
+	 }
+	 /** When a metadata value that matches our search string is found, this method is called to provide a visual cue as to what value from which file matched. This is done by changing the tab view of the main gui and expanding and selecting the correct line from the tree of file records, and then highlighting the appropriate line of the metadata table. This method subsequently calls unhideBound() passing in the bounds of the selected component (cell or row). 
+	  * @param record The <strong>FileNode</strong> that matches our search string.
+	  */
+	 private void fireSelect(FileNode record, Metadata metadata) {
+		  // Ensure that either the MetaEditPane is visible.
+		  Gatherer.g_man.setSelectedView(Gatherer.g_man.metaedit_pane);
+		  // Select the appropriate record in the metaedit pane tree, which will cause the Metadata table to update with the appropriate bunch of metadata... 
+		  TreePath path = new TreePath(record.getPath());
+		  Gatherer.g_man.metaedit_pane.expandPath(path);
+		  // Now select the correct metadata.
+		  Rectangle bounds = Gatherer.g_man.metaedit_pane.setSelectedMetadata(metadata);
+		  unhideSelection(bounds);
+	 }
+	 /** Retrieve a pharse string from the Dictionary matching the given key.
+	  * @param key The <strong>String</strong> which maps to a certain phrase.
+	  * @return The required, locale specific, phrase as a <strong>String</strong>.
+	  * @see org.greenstone.gatherer.Dictionary
+	  */
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+	 /** Retrieve a pharse string from the Dictionary matching the given key and based apon the given arguments.
+	  * @param key The <strong>String</strong> which maps to a certain phrase.
+	  * @param args The argument Strings to the Dictionary, as a <strong>String[]</strong>.
+	  * @return The required, locale specific, phrase as a <strong>String</strong>.
+	  * @see org.greenstone.gatherer.Dictionary
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf(".") == -1) {
+				key = "SearchAndReplace." + key;
+		  }
+		  return Gatherer.dictionary.get(key, args);
+	 }
+	 /** Used to determine is one string matches another tkaing into account the options of case sensitivity and regular expressions.
+	  * @param find_str The search <strong>String</strong> we are trying to find. This may be a regular expression.
+	  * @param target_str The <strong>String</strong> we are matching it against, as provided by some object.
+	  * @return <i>true</i> if the Strings match given the option settings, <i>false</i> otherwise.
+	  */
+	 private boolean match(String target_str) {
+		  ///ystem.err.println("Matching " + target_str + " against " + pattern.pattern());
+		  boolean result = false;
+		  if(!case_sensitive.isSelected()) {
+				target_str = target_str.toLowerCase();
+		  }
+		  try {
+				matcher = pattern.matcher(target_str);
+				result = matcher.matches();
+		  }
+		  catch(Exception error) {
+		  }
+		  return result;
+	 }
+	 /** Called once by the replace button, or repeatedly by replace all, in order to replace the text of the target object, as referenced by the current_<object>s, with the replace text string. This takes into account if regular expressions are expected, and modifies the replacement string with appropriate 'capture groups'. 
+	  * @return <i>true</i> if the replace action was successful, <i>false</i> otherwise.
+	  */
+	 private boolean replace() {
+		  boolean result = false;
+		  String replace_str = replace.getText();
+		  // If regular expressions are allowed, we have to search for regular expression commands and deal with them.
+		  if(matcher != null) {
+				StringBuffer temp = new StringBuffer("");
+				int index_ptr = 0;
+				while(index_ptr < replace_str.length()) {
+					 char c = replace_str.charAt(index_ptr);
+					 // First we check for escaped regualr expression commands which start '\\'
+					 if(c == '\\') {
+						  index_ptr++;
+						  char s = replace_str.charAt(index_ptr);
+						  if(s == '\\') {
+								index_ptr++;
+								char i = replace_str.charAt(index_ptr);
+								// I currently only support one regular expression command, 'capture groups'.
+								if(Character.isDigit(i)) {
+									 try {
+										  int group_num = Character.getNumericValue(i);
+										  if(group_num <= matcher.groupCount()) {
+												temp.append(matcher.group(group_num));
+										  }
+									 }
+									 catch (Exception error) {
+									 }
+								}
+						  }
+						  // The \ had nothing to do with groups, so I guess its a path marker.
+						  else {
+								temp.append(c);
+								temp.append(s);
+						  }
+					 }
+					 else {
+						  temp.append(c);
+					 }
+					 index_ptr++;
+				}
+				replace_str = temp.toString();
+		  }
+		  if(found && replace_str.length() > 0) {
+				if(target instanceof ElementWrapper) {
+					 undo.push(new UndoItem(current_element, current_element.getIdentity(), replace_str));
+					 updateElement(current_element, replace_str);
+					 result = true;
+				}
+				if(target instanceof FileNode) {
+					 undo.push(new UndoItem(current_record, current_record.toString(), replace_str));
+					 updateRecord(current_record, replace_str);
+					 result = true;
+				}
+				if(target instanceof Metadata) {
+					 // If we are replacing metadata value there is a bit more messaging we need to do to any replacement string to ensure that any hierarchy context is transferred to the new value, so...
+					 String absolute_value = current_value.getAbsoluteValue();
+					 if(absolute_value.indexOf("\\") != -1) {
+						  String absolute_path = absolute_value.substring(0, absolute_value.lastIndexOf("\\") + 1);
+						  replace_str = absolute_path + replace_str;
+						  ///ystem.err.println("I replaced a hierarchy value like so:\n"+absolute_value+"\nto\n"+replace_str);
+					 }
+					 undo.push(new UndoItem(current_value, current_record, current_value.getValue(), replace_str));
+					 updateMetadata(current_value, current_record, replace_str);
+					 result = true;
+				}
+		  }
+		  ///ystem.err.println("Undo queue length = " + undo.size());
+		  return result;
+	 }
+	 /** Used to restore the search space within the collection to its initial state for find(). 
+	  */
+	 private void reset() {
+		  current_element = null;
+		  current_record = null;
+		  current_value = null;
+		  elements = Gatherer.c_man.getCollection().msm.getElements();
+		  found = false;
+		  matcher = null;
+		  pattern = null;
+		  records = Utility.depthFirstEnumeration((TreeNode)Gatherer.c_man.getRecordSet().getRoot(), new EnumeratedVector());
+		  target = null;
+	 }
+	 /** Attempts to move the dialog so that it doesn't obscure the coordinates detailed. Can't always do so. 
+	  * @param bounds A <strong>Rectangle</strong> around the selected component, with co-ordinates corrected to be absolute to the screen rather than relative to whatever parent component the selection was in. 
+	  */
+	 private void unhideSelection(Rectangle bounds) {
+		  /** @TODO - Elsewhere generate absolute references. Here make use of them. */
+		  ///ystem.err.println("Unhide selection with bounds " + bounds);
+	 }
+	 /** Whenever replace(), the undo action listener or the redo action listener wants to actually change the value of an element it uses this method. Hows that for code reuse.
+	  * @param element The <strong>ElementWrapper</strong> containing the metadata element we want to change.
+	  * @param value The new text value for the elements identifier as a <strong>String</strong>.
+	  */
+	 private void updateElement(ElementWrapper element, String value) {
+		  Gatherer.c_man.getCollection().msm.renameElement(element, value);
+	 }
+	 /** Whenever replace(), the undo action listener or the redo action listener wants to actually change the value of a metadata value it uses this method. Hows that for code reuse.
+	  * @param metadata The <strong>Metadata</strong> we want to change.
+	  * @param record The <strong>FileNode</strong> the target metadata will be found in.
+	  * @param value The new text value for the metadata as a <strong>String</strong>.
+	  */
+	 private void updateMetadata(Metadata metadata, FileNode record, String value) {
+		  FileNode array[] = new FileNode[1];
+		  array[0] = record;
+		  Gatherer.c_man.getCollection().msm.updateMetadata(0L, metadata, array, value, MetaEditPrompt.UPDATE_ONCE);
+	 }
+	 /** Whenever replace(), the undo action listener or the redo action listener wants to actually change the value of a file record it uses this method. Hows that for code reuse.
+	  * @param record The <strong>FileNode</strong> we want to change.
+	  * @param value The new text value for the files name as a <strong>String</strong>.
+	  */
+	 private void updateRecord(FileNode record, String value) {
+		  TreeModel model = Gatherer.c_man.getRecordSet();
+		  /* @todo
+			  model.rename(record, value);
+		  */
+	 }
+	 /** Several actions methods call this to check if the current state of the dialog allows for the replace butons to become active.
+	  */
+	 private void validateReplaceButtons() {
+		  boolean value = (replace.getText().length() > 0) && enable_replace;
+		  ///ystem.err.println("Validating replace buttons to " + value);
+		  replace_button.setEnabled(value);
+		  replace_all_button.setEnabled(value);
+	 }
+
+	 private class CloseActionListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				self.dispose();
+		  }
+	 }
+
+	 private class FindActionListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				reset();
+				if(find()) {
+					 find_button.setEnabled(false);
+					 find_next_button.setEnabled(true);
+					 if(enable_replace) {
+						  replace_button.setEnabled(true);
+						  replace_all_button.setEnabled(true);
+					 }
+					 reset_button.setEnabled(true);
+					 changeStatus("Found", -1);
+					 found = true;
+				}
+				else {
+					 changeStatus("Not_Found", -1);
+					 found = false;
+				}
+		  }
+	 }
+
+	 private class FindNextActionListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				if(find()) {
+					 changeStatus("Found", -1);
+					 found = true;
+				}
+				else {
+					 find_next_button.setEnabled(false);
+					 changeStatus("Not_Found", -1);
+				}
+		  }
+	 }
+
+	 private class RedoActionListener
+		  implements ActionListener {
+		  private boolean start = false;
+		  public void actionPerformed(ActionEvent event) {
+				if(!redo.empty()) {
+					 start = true;
+					 UndoItem redo_item = (UndoItem) redo.pop();
+					 while(redo_item != null && !redo_item.isDummy()) {
+						  // Determine the type of action we have to undo, then undo it.
+						  ElementWrapper element = redo_item.getElement();
+						  if(element != null) {
+								updateElement(element, redo_item.getAfter());
+								addToUndo(redo_item);
+						  }
+						  FileNode record = redo_item.getRecord();
+						  Metadata metadata = redo_item.getMetadata();
+						  if(metadata != null && record != null) {
+								updateMetadata(metadata, record, redo_item.getAfter());
+								addToUndo(redo_item);
+						  }
+						  else if(record != null) {
+								updateRecord(record, redo_item.getAfter());
+								addToUndo(redo_item);
+						  }
+						  if(!redo.empty()) {
+								redo_item = (UndoItem) redo.pop();
+						  }
+						  else {
+								redo_item = null;
+						  }
+					 }
+					 if(redo.empty()) {
+						  redo_button.setEnabled(false);
+					 }
+				}
+		  }
+		  private void addToUndo(UndoItem redo_item) {
+				if(start) {
+					 undo.push(new UndoItem());
+					 start = false;
+				}
+				undo.push(redo_item);
+				undo_button.setEnabled(true);
+		  }
+	 }
+
+	 private class ReplaceActionListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				if(!found) {
+					 found = find();
+				}
+				if(found) {
+					 undo.push(new UndoItem());
+					 replace();
+					 replace_button.setEnabled(false);
+					 reset_button.setEnabled(true);
+					 undo_button.setEnabled(true);
+					 changeStatus("Replaced", -1);
+				}
+				else {
+					 find_next_button.setEnabled(false);
+					 replace_button.setEnabled(false);
+					 replace_all_button.setEnabled(false);
+					 changeStatus("Not_Found", -1);
+				}
+		  }
+	 }
+
+	 private class ReplaceAllActionListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				reset();
+				int count = 0;
+				boolean start = true;
+				while((found = find()) == true) {
+					 if(start) {
+						  undo.push(new UndoItem());
+						  start = false;
+					 }
+					 count++;
+					 replace();
+				}
+				find_button.setEnabled(false);
+				find_next_button.setEnabled(false);
+				replace_button.setEnabled(false);
+				replace_all_button.setEnabled(false);
+				reset_button.setEnabled(true);
+				if(!undo.empty()) {
+					 undo_button.setEnabled(true);
+				}
+				changeStatus("Replaced_All", count);
+		  }
+	 }
+
+	 private class ResetActionListener
+		  implements ActionListener {
+		  public void actionPerformed(ActionEvent event) {
+				reset();
+				find_button.setEnabled(true);
+				find_next_button.setEnabled(false);
+				replace_button.setEnabled(false);
+				replace_all_button.setEnabled(false);
+				reset_button.setEnabled(false);
+				changeStatus(null, -1);
+		  }
+	 }
+
+	 private class UndoActionListener
+		  implements ActionListener {
+		  private boolean start = false;
+		  public void actionPerformed(ActionEvent event) {
+				if(!undo.empty()) {
+					 start = true;
+					 UndoItem undo_item = (UndoItem) undo.pop();
+					 while(undo_item != null && !undo_item.isDummy()) {
+						  // Determine the type of action we have to undo, then undo it.
+						  ElementWrapper element = undo_item.getElement();
+						  if(element != null) {
+								updateElement(element, undo_item.getBefore());
+								addToRedo(undo_item);
+						  }
+						  else {
+								FileNode record = undo_item.getRecord();
+								Metadata metadata = undo_item.getMetadata();
+								if(metadata != null && record != null) {
+									 // The old metadata doesn't actually exist anymore. We have to generate a new metadata object based on the old metadata objects element and the 'after' string.
+									 GValueModel model = Gatherer.c_man.getCollection().msm.getValueTree(metadata.getElement());
+									 GValueNode value = model.getValue(undo_item.getAfter());
+									 Metadata new_metadata = new Metadata(metadata.getElement(), value);
+									 updateMetadata(new_metadata, record, undo_item.getBefore());
+									 addToRedo(undo_item);
+								}
+								else if(record != null) {
+									 updateRecord(record, undo_item.getBefore());
+									 addToRedo(undo_item);
+								}
+								else {
+									 ///ystem.err.println("Unknown undo item.");
+								}
+						  }
+						  if(!undo.empty()) {
+								undo_item = (UndoItem) undo.pop();
+						  }
+						  else {
+								undo_item = null;
+						  }
+					 }
+					 if(undo.empty()) {
+						  undo_button.setEnabled(false);
+					 }
+				}
+		  }
+		  private void addToRedo(UndoItem undo_item) {
+				if(start) {
+					 redo.push(new UndoItem());
+					 start = false;
+				}
+				redo.push(undo_item);
+				redo_button.setEnabled(true);
+		  }
+	 }
+
+	 private class ReplaceKeyListener
+		  extends KeyAdapter {
+		  public void keyTyped(KeyEvent event) {
+				validateReplaceButtons();
+		  }
+	 }
+
+	 private class SearchKeyListener
+		  extends KeyAdapter {
+		  public void keyTyped(KeyEvent event) {
+				if(current_element != null || current_record != null || current_value != null) {
+					 reset();
+					 find_button.setEnabled(true);
+					 find_next_button.setEnabled(false);
+					 replace_button.setEnabled(false);
+					 replace_all_button.setEnabled(false);
+					 reset_button.setEnabled(false);
+					 changeStatus(null, -1);
+				}
+		  }
+	 }
+	 
+	 private class UndoItem {
+		  private ElementWrapper element = null;
+		  private FileNode record = null;
+		  private Metadata metadata = null;
+		  private String after = null;
+		  private String before = null;
+		  /** Constructor for a dummy item, which separates different batches of changes. */
+		  public UndoItem() {
+		  }
+		  public UndoItem(ElementWrapper element, String before, String after) {
+				this.after = after;
+				this.before = before;
+				this.element = element;
+		  }
+		  public UndoItem(FileNode record, String before, String after) {
+				this.after = after;
+				this.before = before;
+				this.record = record;
+		  }
+		  public UndoItem(Metadata metadata, FileNode record, String before, String after) {
+				this.after = after;
+				this.before = before;
+				this.metadata = metadata;
+				this.record = record;
+		  }
+		  public String getAfter() {
+				return after;
+		  }
+		  public String getBefore() {
+				return before;
+		  }
+		  public ElementWrapper getElement() {
+				return element;
+		  }
+		  public Metadata getMetadata() {
+				return metadata;
+		  }
+		  public FileNode getRecord() {
+				return record;
+		  }
+		  public boolean isDummy() {
+				return (element == null && record == null && metadata == null);
+		  }
+	 }
+}
+
Index: /tags/start/gli/src/org/greenstone/gatherer/shell/GBasicProgressMonitor.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/shell/GBasicProgressMonitor.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/shell/GBasicProgressMonitor.java	(revision 13666)
@@ -0,0 +1,125 @@
+/**
+ *#########################################################################
+ *
+ * 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 javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JProgressBar;
+import org.greenstone.gatherer.shell.GShellProgressMonitor;
+import org.greenstone.gatherer.util.Utility;
+/** This is the most basic implementation of <i>GShellProgressMonitor</i> in that it doesn't even attempt to parse the process messages. Instead it has one graphic which is displayed once the start() method is called, and another which appears after the stop().
+ */
+public class GBasicProgressMonitor 
+	 extends JProgressBar 
+	 implements GShellProgressMonitor {
+	 /** Whether the process has been asked to stop. */
+	 private boolean stop = false;
+	 /** Constructor **/
+	 public GBasicProgressMonitor() {
+		  super();
+		  //this.setIcon(ready);
+	 }
+	 /** Don't do anything if we are given a progress bar, we have our own.
+	  * @param progress_bar A JProgressBar
+	  */
+	 public void addProgressBar(JProgressBar 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() {
+		  // Always return true as we don't know any better.
+		  return 0;
+	 }
+	 /** As we are probably accessing this via an interface we need to gain
+	  * access to the component itself.
+	  */
+	 public Component getProgress() {
+		  return this;
+	 }
+	 /** 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() {
+		  return stop;
+	 }
+	 /** Inform the progress bar that it should programatically increment progress by one step. */
+	 public void increment() {
+		  // We can't do anything about this.
+	 }
+	 /** The parse method is how more complex progress bars figure out how far they have progressed. However we don't.
+	  * @param line A String representing the latest line of output from
+	  * the external process we are monitoring.
+	  */
+	 public void parse(String line) {
+	 }
+	 /** 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) {
+		  stop = state;
+	 }
+	 /** This method tells this class that the job it is showing the progress
+	  * for has begun.
+	  */
+	 public void start() {
+		  //this.setIcon(busy);
+		  setIndeterminate(true);
+	 }
+	 /** This method tells this class that the job it is showing the progress
+	  * for has come to an end.
+	  */
+	 public void stop() {
+		  //this.setIcon(ready);
+		  setIndeterminate(false);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/shell/GBuildProgressMonitor.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/shell/GBuildProgressMonitor.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/shell/GBuildProgressMonitor.java	(revision 13666)
@@ -0,0 +1,330 @@
+package org.greenstone.gatherer.shell;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.Component;
+import javax.swing.JProgressBar;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.shell.GImportProgressMonitor;
+import org.greenstone.gatherer.shell.GShellProgressMonitor;
+/** 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.1
+ */
+public class GBuildProgressMonitor
+	 implements GShellProgressMonitor {
+	 /** Indicates if the GUI has asked the process this object monitors to stop. */
+	 private boolean stop = false;
+
+	 private GImportProgressMonitor import_progress = null;
+
+	 private int num_docs = -1;
+
+	 private int num_indexes = -1;
+
+	 private int state = 0;
+
+	 /** The progress bar this monitor updates. */
+	 private JProgressBar progress_bar;
+
+	 static final private int MIN = 0;
+	 static final private int MAX = 1000000;
+
+	 static final int BASE        =  0;
+	 static final int CTCT        =  1; // Creating the compressed text
+	 static final int CTCT_CTS    =  2; // Creating the compressed text - collecting text statistics
+	 static final int CTCT_CTS_PS =  3; // Creating the compressed text - collecting text statistics - parsed successfully
+	 static final int CTCT_CTCD   =  4; // Creating the compressed text - creating the compression dictionary
+	 static final int CTCT_CTT    =  5; // Creating the compressed text - compressing the text
+	 static final int CTCT_CTT_PS =  6; // Creating the compressed text - compressing the text - parsed successfully
+	 static final int BI          =  7; // Building index
+	 static final int BI_CID      =  8; // Building index - creating index dictionary
+	 static final int BI_CID_PS   =  9; // Building index - creating index dictionary - parsed successfully
+	 static final int BI_ITT      = 10; // Building index - inverting the text
+	 static final int BI_ITT_PS   = 11; // Building index - inverting the text - parsed successfully
+	 static final int BI_CTWF     = 12; // Building index - create the weights file
+	 static final int BI_CODSD    = 13; // Building index - creating 'on-disk' stemmed dictionary
+	 static final int BI_CSI      = 14; // Building index - creating stem indexes
+	 static final int CTID        = 15; // Creating the info database
+	 static final int CTID_PS     = 16; // Creating the info database - parsed successfully
+	 static final int CAF         = 17; // Creating auxiliary files
+
+	 static final String BI_STR   = "*** building index";
+	 static final String CTS_STR  = "collecting text statistics";
+	 static final String CTT_STR  = "compressing the text";
+	 static final String CTWF_STR = "create the weights file";
+	 static final String CAF_STR = "creating auxiliary files";
+	 static final String CID_STR  = "creating index dictionary";
+	 static final String CSI_STR  = "creating stem indexes";
+	 static final String CTCT_STR = "*** creating the compressed text";
+	 static final String CTCD_STR = "creating the compression dictionary";
+	 static final String CTID_STR = "*** creating the info database and processing associated files";
+	 static final String CODSD_STR = "creating 'on-disk' stemmed dictionary";
+	 static final String ITT_STR  = "inverting the text";
+	 static final String PS_STR   = "hash";
+
+	 public GBuildProgressMonitor(GImportProgressMonitor import_progress) {
+		  this.import_progress = import_progress;
+		  progress_bar = new JProgressBar();
+		  progress_bar.setMaximum(MAX);
+		  progress_bar.setMinimum(MIN);
+		  progress_bar.setValue(MIN);
+	 }
+
+	 /** Method to register a new progress bar with this monitor.
+	  * @param progress_bar The new <strong>JProgressBar</strong>.
+	  */	 
+	 public void addProgressBar(JProgressBar progress_bar) {
+		  this.progress_bar = progress_bar;
+		  progress_bar.setMaximum(MAX);
+		  progress_bar.setMinimum(MIN);
+		  progress_bar.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>JProgressBar</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;
+	 }
+	 /** 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() {
+		  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 line A <strong>String</strong> of text captured from either standard out or standard error.
+	  */
+	 public void parse(String raw_line) {
+		  String line = raw_line.toLowerCase();
+		  // We first check if we can parse, which depends on num_docs > 0 and num_indexes > 0.
+		  if(num_docs > 0 && num_indexes > 0) {
+				switch(state) {
+				case BASE:
+					 // We are watching for the beginning of a phase
+					 if(line.indexOf(CTCT_STR) != -1) {
+						  // No progress really.
+						  state = CTCT;
+						  ///ystem.err.println("CTCT [" + state + "] - " + ((progress_bar.getValue() * 100) / MAX) + "%");
+					 }
+					 else if(line.indexOf(BI_STR) != -1) {
+						  // Skip the progress up to this point.
+						  progress_bar.setValue(progress_bar.getValue() + (MAX / (3 + num_indexes)));
+						  state = BI;
+						  ///ystem.err.println("BI [" + state + "] - " + ((progress_bar.getValue() * 100) / MAX) + "%");
+					 }
+					 else if(line.indexOf(CTID_STR) != -1) {
+						  // Skip the progress up to this point
+						  progress_bar.setValue(progress_bar.getValue() + (((1 + num_indexes ) * MAX) / (3 + num_indexes)));
+						  state = CTID;
+						  ///ystem.err.println("CTID [" + state + "] - " + ((progress_bar.getValue() * 100) / MAX) + "%");
+					 }
+					 else if(line.indexOf(CAF_STR) != -1) {
+						  // Skip the progres up to this point
+						  progress_bar.setValue(progress_bar.getValue() + (((2 + num_indexes ) * MAX) / (3 + num_indexes)));
+						  state = CAF;
+						  ///ystem.err.println("CAF [" + state + "] - " + ((progress_bar.getValue() * 100) / MAX) + "%");
+					 }
+					 break;
+				case CTCT:
+					 if(line.indexOf(CTS_STR) != -1) {
+						  // No progress really.
+						  state = CTCT_CTS;
+						  ///ystem.err.println("CTS [" + state + "] - " + ((progress_bar.getValue() * 100) / MAX) + "%");
+					 }
+					 break;
+				case CTCT_CTS:
+					 if(line.indexOf(PS_STR) != -1) {
+						  // We have finally found something we can increment because of.
+						  progress_bar.setValue(progress_bar.getValue() + (MAX / ((3 + num_indexes) * 3 * num_docs)));
+						  ///ystem.err.println("Increase " + (MAX / ((3 + num_indexes) * 3 * num_docs)));
+					 }
+					 else if(line.indexOf(CTCD_STR) != -1) {
+						  state = CTCT_CTCD;
+						  ///ystem.err.println("CTCD [" + state + "] - " + ((progress_bar.getValue() * 100) / MAX) + "%");
+					 }
+					 break;
+				case CTCT_CTCD:
+					 if(line.indexOf(CTT_STR) != -1) {
+						  // Finished creating the compression dictionary.
+						  progress_bar.setValue(progress_bar.getValue() + (MAX / ((3 + num_indexes) * 3)));
+						  ///ystem.err.println("Increase " + (MAX / ((3 + num_indexes) * 3)));
+						  state = CTCT_CTT;
+						  ///ystem.err.println("CTT [" + state + "] - " + ((progress_bar.getValue() * 100) / MAX) + "%");
+					 }
+					 break;
+				case CTCT_CTT:
+					 if(line.indexOf(PS_STR) != -1) {
+						  // We have finally found something we can increment because of.
+						  progress_bar.setValue(progress_bar.getValue() + (MAX / ((3 + num_indexes) * 3 * num_docs)));
+						  ///ystem.err.println("Increase " + (MAX / ((3 + num_indexes) * 3 * num_docs)));
+					 }
+					 else if(line.indexOf(BI_STR) != -1) {
+						  state = BI;
+						  ///ystem.err.println("BI [" + state + "] - " + ((progress_bar.getValue() * 100) / MAX) + "%");
+					 }
+					 break;
+				case BI:
+					 if(line.indexOf(CID_STR) != -1) {
+						  state = BI_CID;
+						  ///ystem.err.println("CID [" + state + "] - " + ((progress_bar.getValue() * 100) / MAX) + "%");
+					 }
+					 break;
+				case BI_CID:
+					 if(line.indexOf(PS_STR) != -1) {
+						  // We have finally found something we can increment because of.
+						  progress_bar.setValue(progress_bar.getValue() + (MAX / ((3 + num_indexes) * 5 * num_docs)));
+						  ///ystem.err.println("Increase " + (MAX / ((3 + num_indexes) * 5 * num_docs)));
+					 }
+					 else if(line.indexOf(ITT_STR) != -1) {
+						  state = BI_ITT;
+						  ///ystem.err.println("ITT [" + state + "] - " + ((progress_bar.getValue() * 100) / MAX) + "%");
+					 }
+					 break;
+				case BI_ITT:
+					 if(line.indexOf(PS_STR) != -1) {
+						  // We have finally found something we can increment because of.
+						  progress_bar.setValue(progress_bar.getValue() + (MAX / ((3 + num_indexes) * 5 * num_docs)));
+						  ///ystem.err.println("Increase " + (MAX / ((3 + num_indexes) * 5 * num_docs)));
+					 }
+					 else if(line.indexOf(CTWF_STR) != -1) {
+						  state = BI_CTWF;
+						  ///ystem.err.println("CTWF [" + state + "] - " + ((progress_bar.getValue() * 100) / MAX) + "%");
+					 }
+					 break;
+				case BI_CTWF:
+					 if(line.indexOf(CODSD_STR) != -1) {
+						  progress_bar.setValue(progress_bar.getValue() + (MAX / ((3 + num_indexes) * 5)));
+						  ///ystem.err.println("Increase " + (MAX / ((3 + num_indexes) * 5)));
+						  state = BI_CODSD;
+						  ///ystem.err.println("CODSD [" + state + "] - " + ((progress_bar.getValue() * 100) / MAX) + "%");
+					 }
+					 break;
+				case BI_CODSD:
+					 if(line.indexOf(CSI_STR) != -1) {
+						  progress_bar.setValue(progress_bar.getValue() + (MAX / ((3 + num_indexes) * 5)));
+						  ///ystem.err.println("Increase " + (MAX / ((3 + num_indexes) * 5)));
+						  state = BI_CSI;
+						  ///ystem.err.println("CSI [" + state + "] - " + ((progress_bar.getValue() * 100) / MAX) + "%");
+					 }
+					 break;
+				case BI_CSI:
+					 if(line.indexOf(BI_STR) != -1) {
+						  progress_bar.setValue(progress_bar.getValue() + (MAX / ((3 + num_indexes) * 5)));
+						  ///ystem.err.println("Increase " + (MAX / ((3 + num_indexes) * 5)));
+						  state = BI;
+						  ///ystem.err.println("BI [" + state + "] - " + ((progress_bar.getValue() * 100) / MAX) + "%");
+					 }
+					 else if(line.indexOf(CTID_STR) != -1) {
+						  progress_bar.setValue(progress_bar.getValue() + (MAX / ((3 + num_indexes) * 5)));
+						  ///ystem.err.println("Increase " + (MAX / ((3 + num_indexes) * 5)));
+						  state = CTID;
+						  ///ystem.err.println("CTID [" + state + "] - " + ((progress_bar.getValue() * 100) / MAX) + "%");
+					 }
+					 break;
+				case CTID:
+					 if(line.indexOf(PS_STR) != -1) {
+						  // We have finally found something we can increment because of.
+						  progress_bar.setValue(progress_bar.getValue() + (MAX / ((3 + num_indexes) * num_docs)));
+						  ///ystem.err.println("Increase " + (MAX / ((3 + num_indexes) * num_docs)));
+					 }
+					 else if(line.indexOf(CAF_STR) != -1) {
+						  state = CAF;
+						  ///ystem.err.println("CAF [" + state + "] - " + ((progress_bar.getValue() * 100) / MAX) + "%");
+					 }
+					 break;
+				case CAF:
+					 progress_bar.setValue(MAX);
+					 state = BASE;
+					 ///ystem.err.println("Done! 100%");
+					 break;
+				}
+		  }
+		  else {
+				///ystem.err.println("Number of documents = " + num_docs);
+				///ystem.err.println("Number of indexes = " + num_indexes);
+				progress_bar.setIndeterminate(true);
+		  }
+	 }
+
+	 public void reset() {
+		  state = BASE;
+		  progress_bar.setValue(MIN);
+		  num_docs = -1;
+		  num_indexes = -1;
+		  stop = false;
+		  progress_bar.setIndeterminate(false);
+	 }
+
+	 /** 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) {
+		  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() {
+		  progress_bar.setValue(MIN);
+		  num_indexes = Gatherer.g_man.config_pane.getIndexes().size();
+		  num_docs = import_progress.getNumberOfDocuments();
+	 }
+	 /** This method indicates the process is complete. 
+	  * TODO Everthing.
+	  */
+	 public void stop() {
+		  progress_bar.setIndeterminate(false);
+		  progress_bar.setValue(MAX); // Not max, or else it won't blank properly for the next build.
+	 }
+}
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/shell/GImportProgressMonitor.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/shell/GImportProgressMonitor.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/shell/GImportProgressMonitor.java	(revision 13666)
@@ -0,0 +1,173 @@
+package org.greenstone.gatherer.shell;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.Component;
+import java.util.StringTokenizer;
+import javax.swing.JProgressBar;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.shell.GShellProgressMonitor;
+/** 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 GUI has asked the process this object monitors to stop. */
+	 private boolean stop = false;
+	 /** The number of directories that are expected to be scanned by this import process. May not be correct for various reasons, such as a custom RecPlug setup, but its seems the most reliable for general cases. */
+	 private int num_dirs = 0;
+	 /** 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 = 0;
+	 /** The progress bar this monitor updates. */
+	 private JProgressBar progress_bar;
+	 /** The maximum value for this progress bar. */
+	 static final private int MAX = 1000000;
+	 /** The minimum value for this progress bar. */
+	 static final private int MIN = 0;
+	 /** A String fragment which is used to determine if the current output process line is referring to the number of documents actually processed by the import script. */
+	 static final private String NUM_DOCS_PROCESSED = "processed and included in the collection";
+	 /** The Sentinel value is the String fragment an output process line must start with to be considered a milestone. In this case we are counting directories, so the fragment refers to a directory scan. */
+	 static final private String SENTINEL = "recplug: getting directory ";
+	 public GImportProgressMonitor() {
+		  progress_bar = new JProgressBar();
+		  progress_bar.setMaximum(MAX);
+		  progress_bar.setMinimum(MIN);
+		  progress_bar.setValue(MIN);
+	 }
+	 /** Method to register a new progress bar with this monitor.
+	  * @param progress_bar The new <strong>JProgressBar</strong>.
+	  */	 
+	 public void addProgressBar(JProgressBar progress_bar) {
+		  this.progress_bar = progress_bar;
+		  progress_bar.setMaximum(MAX);
+		  progress_bar.setMinimum(MIN);
+		  progress_bar.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(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>JProgressBar</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;
+	 }
+	 /** 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() {
+		  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 (100 / 5) / num_docs. */
+	 public void increment() {
+		  if(num_docs > 0) {
+				progress_bar.setValue(progress_bar.getValue() + ((MAX / 5) / num_docs));
+		  }
+		  else {
+				progress_bar.setIndeterminate(true);
+		  }
+	 }
+	 /** This method is used to 'feed in' a line of text captured from the process.
+	  * @param line A <strong>String</strong> of text captured from either standard out or standard error.
+	  * TODO Everthing.
+	  */
+	 public void parse(String line_raw) {
+		  String line = line_raw.toLowerCase();
+		  if(line.indexOf(SENTINEL) != -1) {
+				///ystem.err.println("Sentinal value detected: ");
+				if(num_dirs > 0) {
+					 ///ystem.err.println(count + " of " + num_dirs);
+					 ///ystem.err.println("Value before: " + progress_bar.getValue());
+					 progress_bar.setValue(progress_bar.getValue() + ((4 * (MAX / 5)) / num_dirs));
+					 ///ystem.err.println("Value after:  " + progress_bar.getValue());
+				}
+				else {
+					 progress_bar.setIndeterminate(true);
+				}
+		  }
+		  else if(line.indexOf(NUM_DOCS_PROCESSED) != -1) {
+				// Increment the import because we have finished a directory
+				
+				num_docs = -1;
+				StringTokenizer tokenizer = new StringTokenizer(line);
+				while(num_docs == -1 && tokenizer.hasMoreTokens()) {
+					 String pos_num_docs_str = tokenizer.nextToken();
+					 try {
+						  num_docs = Integer.parseInt(pos_num_docs_str);
+					 }
+					 catch (Exception error) {
+					 }
+				}
+				///ystem.err.println("Parsed num_docs to be " + num_docs);
+		  }
+	 }
+	 /** 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) {
+		  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() {
+		  num_dirs = Gatherer.c_man.getCollection().getFolderCount();
+		  progress_bar.setValue(MIN);
+		  System.err.println("Number of directories is " + num_dirs);
+	 }
+	 /** This method indicates the process is complete. 
+	  * TODO Everthing.
+	  */
+	 public void stop() {
+		  progress_bar.setIndeterminate(false);
+		  progress_bar.setValue(MAX);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/shell/GShell.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/shell/GShell.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/shell/GShell.java	(revision 13666)
@@ -0,0 +1,336 @@
+package org.greenstone.gatherer.shell;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.io.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.Message;
+import org.greenstone.gatherer.msm.GreenstoneArchiveParser;
+import org.greenstone.gatherer.shell.GShellListener;
+import org.greenstone.gatherer.shell.GShellProgressMonitor;
+/** 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;
+	 /** 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;
+	 /** Element in process type enumeration. */
+	 static final public int BUILD = 0;
+	 /** Element in process type enumeration. */
+	 static final public int IMPORT = 1;
+	 /** Element in process type enumeration. */
+	 static final public int NEW = 2;
+	 /** Element in process type enumeration. */
+	 static final public int OTHER = 3;
+	 /** Element in status type enumeration. */
+	 static final public int ERROR = 0;
+	 /** Element in status type enumeration. */
+	 static final public int OK = 1;
+	 /** Element in process type name enumeration. */
+	 static public String GSHELL_BUILD = "gshell_build";
+	 /** Element in process type name enumeration. */
+	 static public String GSHELL_IMPORT = "gshell_import";
+	 /** Element in process type name enumeration. */
+	 static public String GSHELL_NEW = "gshell_new";
+	 /** 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.
+	  */
+	 public void removeGShellListener(GShellListener listener) {
+		  listeners.remove(GShellListener.class, listener);
+	 }
+	 /** Any threaded class must include this method to allow the thread body to be run.
+	  */
+    public void run() {
+		  // Setup
+		  if(progress != null) {
+				progress.start();
+		  }
+		  // Determine if the user has asked for an outfile.
+		  String out_name = null;
+		  FileOutputStream fos = null;
+		  BufferedOutputStream bos = null;
+		  if(type == IMPORT || type == BUILD) {
+				if(type == IMPORT) {
+					 out_name = (String) Gatherer.c_man.getCollection().build_options.getImportValue("out");
+				}
+				else {
+					 out_name = (String) Gatherer.c_man.getCollection().build_options.getBuildValue("out");
+				}
+				if(out_name != null && out_name.length() > 0) {
+					 File out = new File(out_name);
+					 try {
+						  if(out.exists()) {
+								boolean append = true;
+								fos = new FileOutputStream(out, append);
+								bos = new BufferedOutputStream(fos);
+						  }
+					 } 
+					 catch (Exception error) {
+						  error.printStackTrace();
+					 }
+				}
+		  }
+		  // Issue a processBegun event
+		  fireProcessBegun(type, status);
+		  try {
+				String command = "";
+				for(int i = 0; i < args.length; i++) {
+					 command = command + args[i] + " ";
+				}
+				///ystem.err.println("Command: " + command);
+				fireMessage(type, get("Command") + ": " + command, status);
+				message(Message.EVENT, get("Command") + ": " + command);
+				
+				Runtime rt = Runtime.getRuntime();
+				Process prcs = rt.exec(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) && !hasSignalledStop()) {
+					 if(eline != null) {
+						  if(progress != null) {
+								progress.parse(eline);
+						  }
+						  if(bos != null) {
+								bos.write(eline.getBytes(), 0, eline.length());
+						  }
+						  ///ystem.err.println("stderr: " + eline);
+						  fireMessage(type, typeAsString(type) + "> " + eline, 
+										  status);
+						  message(Message.INFO, eline);
+					 }
+					 if(stdinline != null) {
+						  if(bos != null) {
+								//bos.write(stdinline.getBytes(), 0, stdinline.length());
+						  }
+						  ///ystem.err.println("stdin: " + stdinline);
+						  fireMessage(type, typeAsString(type) + "> " + stdinline,
+										  status);
+						  message(Message.INFO, stdinline);
+					 }
+				}
+
+				if(!hasSignalledStop()) {
+					 // Now display final message based on exit value
+					 prcs.waitFor();
+					 
+					 if(prcs.exitValue() == 0) {
+						  status = OK;
+						  fireMessage(type, typeAsString(type) + "> " + get("Success"), status);
+						  message(Message.MAIN, get("Success"));
+					 } else {
+						  status = ERROR;
+						  fireMessage(type, typeAsString(type) + "> " + get("Failure"), status);
+						  message(Message.ERROR, get("Failure"));
+					 }
+				}
+				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.
+					 prcs.getOutputStream().close();
+					 prcs.destroy();
+					 status = ERROR;
+				}
+		  }
+		  // Exception
+		  catch (Exception error) {
+				message(Message.ERROR, get("Failure"));
+				message(Message.ERROR, error.toString());
+				Gatherer.printStackTrace(error);
+				status = ERROR;
+		  }
+		  // If no error occured, and this was an import process we now extract any new metadata from the archive directory.
+		  if(status == OK && type == IMPORT) {
+				fireMessage(type, typeAsString(type) + "> " + get("Parsing_Metadata_Start"), status);
+				new GreenstoneArchiveParser(progress, this);
+				fireMessage(type, typeAsString(type) + "> " + get("Parsing_Metadata_Complete"), status);
+		  }
+		  // Tidy up.
+		  if(progress != null) {
+				progress.stop();
+		  }
+		  if(bos != null) {
+				try {
+					 bos.close();
+				}
+				catch (Exception e) {
+				}
+		  }
+		  // We're done.
+		  fireProcessComplete(type, status);
+    }
+	 /** 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) {
+		  GShellEvent event = new GShellEvent(this, 0, type, message, status);
+		  Object[] concerned = listeners.getListenerList();
+		  for(int i = 0; i < concerned.length ; i++) {
+				if(concerned[i] == GShellListener.class) {
+					 ((GShellListener)concerned[i+1]).message(event);
+				}
+		  }
+	 }
+	 /** 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) {
+		  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) {
+		  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);
+				}
+		  }
+	 }
+	 /** Retrieve a phrase from the dictionary based on the given key.
+	  * @param key A <strong>String</strong> used to match against a phrase from the <strong>Dictionary</strong>.
+	  * @return The phrase as a <strong>String</strong>.
+	  */
+	 private String get(String key) {
+		  if(key.indexOf('.') == -1) {
+				key = "GShell." + key;
+		  }
+		  return Gatherer.dictionary.get(key);
+	 }
+	 /** 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.
+	  */
+	 private boolean hasSignalledStop() {
+		  boolean has_signalled_stop = false;
+		  if(progress != null) {
+				return progress.hasSignalledStop();
+		  }
+		  return has_signalled_stop;
+	 }
+	 /** Creates and dispatches a message given the initial details.
+	  * @param level An <strong>int</strong> indicating the message level for this message.
+	  * @param message A <strong>String</strong> which contains the payload of this message.
+	  */
+	 private void message(int level, String message) {
+		  Message msg = new Message(msg_type, level, message);
+		  if(Gatherer.g_man != null) {
+				Gatherer.log.add(msg);
+		  }
+	 }
+	 /** 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 = get("Build");
+				break;
+		  case IMPORT:
+				name = get("Import");
+				break;
+		  case NEW:
+				name = get("New");
+				break;
+		  default:
+				name = get("Other");
+		  }
+		  return name;
+	 }
+}
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/shell/GShellEvent.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/shell/GShellEvent.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/shell/GShellEvent.java	(revision 13666)
@@ -0,0 +1,99 @@
+/**
+ *#########################################################################
+ *
+ * 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 {
+	 /** 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;
+	 }
+
+	 public String toString() {
+		  return "org.greenstone.gatherer.shell.GShellEvent[" + message + "," + status + "," + type + "]";
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/shell/GShellListener.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/shell/GShellListener.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/shell/GShellListener.java	(revision 13666)
@@ -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.
+ *
+ * <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/start/gli/src/org/greenstone/gatherer/shell/GShellProgressMonitor.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/shell/GShellProgressMonitor.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/shell/GShellProgressMonitor.java	(revision 13666)
@@ -0,0 +1,93 @@
+/**
+ *#########################################################################
+ *
+ * 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 javax.swing.JProgressBar;
+/** 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>JProgressBar</strong>.
+	  */
+	 public void addProgressBar(JProgressBar 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();
+	 /** Method to retrieve whatever control is being used as the progress indicator. Usually a <strong>JProgressBar</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();
+	 /** 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 line A <strong>String</strong> of text captured from either standard out or standard error.
+	  */
+	 public void parse(String line);
+	 /** 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/start/gli/src/org/greenstone/gatherer/temp.txt
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/temp.txt	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/temp.txt	(revision 13666)
@@ -0,0 +1,51 @@
+	 -- Collection Preferences --
+
+	 /** <i>true</i> if Greenstone type metadata should be automatically extracted, <i>false</i> otherwise. */
+	 public boolean auto = true;
+	 /** Specifies whether Gatherer should overwrite existing files (<i>true</i> to overwrite, <i>false</i> otherwise). */
+	 public boolean clobber = false;
+	 /** <i>true</i> to indicate that during mirroring no file from higher in the file hierarchy should be downloaded (i.e. download this url or files in the directories below this url), <i>false</i> if mirroring should be complete. */
+	 public boolean no_parents = true;
+	 /** <i>true</i> to remove failed mirroring jobs from the queue, <i>false</i> to leave them where they are (but mark them as failed). */
+	 public boolean remove_failed = false;
+	 /** <i>true</i> to allow the mirroring to bridge hosts, <i>false</i> to make it stay on the initial host. */
+	 public boolean other_hosts = false;
+	 /** <i>true</i> to ensure that all files needs to correctly render a page are downloaded, and/or added when adding files, <i>false</i> if only selected files are added. */
+	 public boolean page_requisites = true;
+	 /** The depth a site should be mirrored to (how many links should be followed). */
+	 public int depth = 0;
+
+	 -- General Preferences --
+
+	 /** Specifies what levels should visible messages be from. */
+	 public boolean level[] = new boolean[4];
+	 /** Specifies what sources should visible messages be from. */
+	 public boolean source[] = new boolean[6];
+	 /** Does Gatherer need to access the net via a proxy? */
+	 public boolean use_proxy = false;
+	 /** The size of the main Gatherer window. */
+	 public Dimension size = null;
+	 /** The default font used when building controls with text in them. */
+	 public FontUIResource font = null;
+	 /** The font used for the tool tip gets it own little setting, as we need to use some set character width font if we wish the tips to appear justified properly. */
+	 public FontUIResource tooltip_font = null;
+	 /** The current Locale of Gatherer. Initialized to default if no other provided. */
+	 public Locale locale = null;
+	 /** The current Gatherer homepage. */
+	 public GURL home = new GURL("http://www.greenstone.org/");
+	 /** The file name of the currently open, or open at end of last session, collection. */
+	 public String open_collection = null;
+	 /** The host address of a proxy server, if necessary. */
+	 public String proxy_host = null;
+	 /** The port number of a proxy server, if necessary. */
+	 public String proxy_port = null;
+
+	 -- Transient Preferences (not written to xml) --
+
+	 /** Should debug features be turned on (<i>true</i> to enable debug, <i>false</i> otherwise). */
+	 public boolean debug = true;
+	 /** The password for the proxy server indicated above. */
+	 transient public String proxy_pass = null;
+	 /** The username for the proxy server indicated above. */
+	 transient public String proxy_user = null;
+
Index: /tags/start/gli/src/org/greenstone/gatherer/undo/UndoManager.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/undo/UndoManager.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/undo/UndoManager.java	(revision 13666)
@@ -0,0 +1,548 @@
+package org.greenstone.gatherer.undo;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.datatransfer.Transferable;
+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.Gatherer;
+import org.greenstone.gatherer.file.FileJob;
+import org.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.file.FileQueue;
+import org.greenstone.gatherer.file.FileSystemModel;
+import org.greenstone.gatherer.msm.GDMDocument;
+import org.greenstone.gatherer.msm.Metadata;
+import org.greenstone.gatherer.msm.MSMEvent;
+import org.greenstone.gatherer.msm.MSMListenerAdapter;
+import org.greenstone.gatherer.util.ArrayTools;
+import org.greenstone.gatherer.util.DragComponent;
+import org.greenstone.gatherer.util.DragGroup;
+import org.greenstone.gatherer.util.Utility;
+/** Manages the rather complex task of undoing and redoing actions. It does this by storing two queues, undo and redo, containing undo jobs which encapsulate all the information needed to undo or redo an action. It is also important to note that the manage creates a temporary directory, and then places any deleted files in this directory, and saves their associated metadata with them, for the life of the session. This is to facilitate the restoring of deleted files. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato 
+ * @version 2.3c
+ */
+public class UndoManager
+	 extends JButton
+	 implements ActionListener, DragComponent, DropTargetListener {
+	 private ArrayList redo_sources;
+	 private ArrayList undo_sources;
+	 private boolean ignore = false;
+	 private boolean ignore_next = 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 FileQueue file_queue;
+	 private FileSystemModel model;
+	 private GDMDocument obsolete_metadata;
+	 /** 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();
+	 private UndoStack redo;
+	 private UndoStack undo;
+	 static final public int FILE_COPY = 1;
+	 static final public int FILE_DELETE = 2;
+	 static final public int FILE_MOVE = 3;
+
+	 public UndoManager() {
+		  super(Utility.getImage("bin.gif"));
+		  this.file_queue = Gatherer.f_man.getQueue();
+		  this.drop_target = new DropTarget(this, drag_action, this, true);
+
+		  setBackground(Gatherer.config.getColor("coloring.button_background", true));
+		  setForeground(Gatherer.config.getColor("coloring.button_foreground", true));
+		  setOpaque(true);
+
+		  // Creation
+		  File recycle_directory = new File(Utility.RECYCLE);
+		  if(!recycle_directory.exists()) {
+				recycle_directory.mkdirs();
+				recycle_directory.deleteOnExit();
+		  }
+		  this.model = new FileSystemModel(new FileNode(recycle_directory, "Undo"));
+		  obsolete_metadata = new GDMDocument(); // This GDM is never saved.
+		  redo = new UndoStack(false);
+		  redo_sources = new ArrayList();
+		  undo = new UndoStack(true);
+		  undo_sources = new ArrayList();
+		  if(Gatherer.debug != null) {
+				showTree();
+		  }
+	 }
+
+	 public void actionPerformed(ActionEvent event) {
+		  // Is this an undo event source...
+		  if(undo_sources.contains(event.getSource())) {
+				UndoJob undo_job = undo.pop();
+				undo_job.action(true, file_queue);
+				// Now retrieve all other undo jobs with the same job-number and action them
+				while((undo_job = undo.getJob(undo_job.ID())) != null) {
+					 undo_job.action(true, file_queue);
+				}
+		  }
+		  // Or a redo one.
+		  else if(redo_sources.contains(event.getSource())) {
+				UndoJob redo_job = redo.pop();
+				redo_job.action(false, file_queue);
+				// Now retrieve all other redo jobs with the same job-number and action them
+				while((redo_job = redo.getJob(redo_job.ID())) != null) {
+					 redo_job.action(false, file_queue);
+				}
+		  }
+	 }
+
+	 public void addMetadata(File file, ArrayList metadatum) {
+		  for(int i = 0; metadatum != null && i < metadatum.size(); i++) {
+				Metadata metadata = (Metadata) metadatum.get(i);
+				///ystem.err.println("UndoMetadata: " + file.getAbsolutePath() + " => " + metadata);
+				obsolete_metadata.addMetadata(file.getAbsolutePath(), metadata);
+		  }
+	 }
+
+	 public void addUndo(long id, int type, DragComponent source_model, FileNode source_parent, DragComponent target_model, FileNode record, boolean undo_event) {
+		  if(target_model == null) {
+				target_model = this;
+		  }
+		  UndoJobAdder job_adder = new UndoJobAdder(id, type, source_model, source_parent, target_model, record, undo_event);
+		  SwingUtilities.invokeLater(job_adder);
+	 }
+
+	 public void clear() {
+		  undo.clear();
+		  redo.clear();
+	 }
+
+	 /** 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(){
+	 }
+
+	 public void destroy() {
+		  // Remove all references of this as a listener
+		  for(int i = 0; i < redo_sources.size(); i++) {
+				AbstractButton source = (AbstractButton) redo_sources.get(i);
+				source.removeActionListener(this);
+		  }
+		  for(int j = 0; j < undo_sources.size(); j++) {
+				AbstractButton source = (AbstractButton) undo_sources.get(j);
+				source.removeActionListener(this);
+		  }
+		  redo_sources = null;
+		  undo_sources = null;
+		  redo = null;
+		  undo = null;
+		  obsolete_metadata = null;
+		  file_queue = null;
+	 }
+
+ 	 /** 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) {
+		  //ystem.err.println("Drag entered");
+		  group.grabFocus(this);
+		  setBackground(Gatherer.config.getColor("coloring.button_selected_background", true));
+		  setForeground(Gatherer.config.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) {
+		  //ystem.err.println("Drag exitted");
+		  setBackground(Gatherer.config.getColor("coloring.button_background", true));
+		  setForeground(Gatherer.config.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(Gatherer.config.getColor("coloring.button_background", true));
+		  setForeground(Gatherer.config.getColor("coloring.button_foreground", true));
+		  Transferable transferable = event.getTransferable();
+		  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();
+				}
+				///ystem.err.println("Dropped files vector contains " + new_files.size() + " files.");
+				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) {
+	 }
+
+	 public void fileCopied(long id, DragComponent target_model, FileNode target_parent, FileNode record, boolean undo_event) {
+		  ///ystem.err.println("fileCopied(" + id + ", " + target_model + ", " + target_parent + ", " + record + ", " + undo_event + ")");
+		  UndoJob job = new UndoJob(id, null, null, target_model, record, FILE_COPY);
+		  if(undo_event) {
+				///ystem.err.println("Add undo job");
+				undo.push(job);
+		  }
+		  else {
+				///ystem.err.println("Add redo job");
+				redo.push(job);
+		  }
+	 }
+
+	 public void fileDeleted(long id, DragComponent source_model, FileNode source_parent, FileNode target_parent, FileNode record, boolean undo_event) {
+		  UndoJob job = new UndoJob(id, source_model, source_parent, this, record, FILE_DELETE);
+		  if(undo_event) {
+				///ystem.err.println("Add undo job");
+				undo.push(job);
+		  }
+		  else {
+				///ystem.err.println("Add redo job");
+				redo.push(job);
+		  }
+	 } 
+
+	 public void fileMoved(long id, DragComponent source_model, FileNode source_parent, DragComponent target_model, FileNode target_parent, FileNode record, boolean undo_event) {
+		  ///ystem.err.println("fileMoved(" + id + ", " + source_model + ", " + source_parent + ", " + target_model + ", " + target_parent + ", " + record + ", " + undo_event + ")");
+		  UndoJob job = new UndoJob(id, source_model, source_parent, target_model, record, FILE_MOVE);
+		  if(undo_event) {
+				///ystem.err.println("Add undo job");
+				undo.push(job);
+		  }
+		  else {
+				///ystem.err.println("Add redo job");
+				redo.push(job);
+		  }
+	 }
+
+	 /** Used to notify this component that it has gained focus by some method other that mouse focus. */
+	 public void gainFocus(){
+	 }
+
+	 public ArrayList getMetadata(File file) {
+		  ///ystem.err.println("UndoMetadata: " + file.getAbsolutePath());
+		  return obsolete_metadata.getMetadata(file.getAbsolutePath(), true, new ArrayList(), file);
+	 }
+
+	 /** 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 registerRedoSource(AbstractButton source) {
+		  if(!redo_sources.contains(source)) {
+				redo_sources.add(source);
+				source.addActionListener(this);
+		  }
+	 }
+
+	 public void registerUndoSource(AbstractButton source) {
+		  if(!undo_sources.contains(source)) {
+				undo_sources.add(source);
+				source.addActionListener(this);
+		  }
+	 }
+
+	 public void setGroup(DragGroup group) {
+		  this.group = group;
+	 }
+
+	 public void undoAll() {
+		  FileQueue immediate_queue = new FileQueue(true);
+		  UndoJob undo_job = null;
+		  while((undo_job = undo.pop()) != null) {
+				undo_job.action(true, immediate_queue);
+				// Now retrieve all other undo jobs with the same job-number and action them
+				while((undo_job = undo.getJob(undo_job.ID())) != null) {
+					 undo_job.action(true, immediate_queue);
+				}
+		  }
+		  immediate_queue.run();
+		  // Returns only when all undo actions complete.
+	 }
+
+	 static final public File generateUniqueFile(FileNode record) {
+		  String filename_raw = ArrayTools.objectArrayToString(record.getPath());
+		  int hash_code = filename_raw.hashCode();
+		  File file = new File(Utility.RECYCLE, String.valueOf(hash_code));
+		  int offset = 65;
+		  while(file.exists() && offset != 90) {
+				file = new File(Utility.RECYCLE, String.valueOf(hash_code) + (char)offset);
+				offset++;
+		  }
+		  return file;
+	 }
+
+	 private void showTree() {
+		  JDialog dialog = new JDialog(Gatherer.g_man, "Recycle Bin Model");
+		  dialog.setSize(new Dimension(400,300));
+		  JPanel content_pane = (JPanel) dialog.getContentPane();
+		  JTree tree = new JTree(model);
+		  content_pane.setLayout(new BorderLayout());
+		  content_pane.add(new JScrollPane(tree), BorderLayout.CENTER);
+		  dialog.show();
+	 }
+
+	 private class UndoJob {
+		  private FileNode record = null;
+		  private FileNode source_parent = null;
+		  private DragComponent source_model = null;
+		  private DragComponent target_model = null;
+		  private long id = 0;
+		  private int type = -1;
+		  private TreePath record_path = null;
+		  private TreePath source_parent_path = null;
+		  /** Undo file action Constructor.
+			* @param id A unique <i>long</i> id number for all actions associated with a certain gesture.
+			* @param source_model The source <strong>DragComponent</strong> where the new record originally came from. If this is <i>null</i> then it is assumed you are interested in using the 'recycle' bin model.
+			* @param source_parent The previous parent <strong>FileNode</strong> of the new record.
+			* @param target_model The target <strong>DragComponent</strong> where the new record is now.
+			* @param record The new <strong>FileNode</strong> itself.
+			* @param type An <i>int</i> indicating the action that has occured, not what undo action is needed.
+			*/
+		  public UndoJob(long id, DragComponent source_model, FileNode source_parent, DragComponent target_model, FileNode record, int type) {
+				this.id = id;
+				this.record = record;
+				if(record != null) {
+					 this.record_path = new TreePath(record.getPath());
+				}
+				this.source_model = source_model;
+				this.source_parent = source_parent;
+				if(source_parent != null) {
+					 this.source_parent_path = new TreePath(source_parent.getPath());
+				}
+				this.target_model = target_model;
+				this.type = type;
+		  }
+		  
+		  public void action(boolean is_undo, FileQueue file_queue) {
+				// Retrieve the lastest version of each file record
+				FileNode latest_record = null;
+				FileNode latest_source_parent = null;
+				if(target_model != null && record_path != null) {
+					 ///ystem.err.println("Retrieving latest version of record from " + target_model + ".");
+					 latest_record = ((FileSystemModel)target_model.getTreeModel()).getNode(record_path);
+				}
+				if(source_model != null && source_parent_path != null) {
+					 ///ystem.err.println("Retrieving latest version of source parent.");
+					 latest_source_parent = ((FileSystemModel)source_model.getTreeModel()).getNode(source_parent_path);
+				}
+				// Of course if there are no newer versions, stick to the ones we've already got.
+				if(latest_record == null) {
+					 ///ystem.err.println("Using original record.");
+					 latest_record = record;
+				}
+				if(latest_source_parent == null) {
+					 ///ystem.err.println("Using original source parent.");
+					 latest_source_parent = source_parent;
+				}
+				// Heres the fraction, too much friction. 
+				switch(type) {
+				case FILE_COPY:					 
+					 // To undo a file copy we issue a delete file action on the destination file record.
+					 file_queue.addJob(id, target_model, latest_record, source_model, latest_source_parent, FileJob.DELETE, !is_undo, true, false);
+					 break;
+				case FILE_DELETE:
+					 // To undo a file delete we issue a copy file action from our recycle bin.
+					 file_queue.addJob(id, target_model, latest_record, source_model, latest_source_parent, FileJob.MOVE, !is_undo, true, false);
+					 break;
+				case FILE_MOVE:			 
+					 // This may be a legitimate move, or may be a side effect of an undelete. If the formed source model and parent will be non-null.
+					 if(source_model != null && source_parent != null) {
+						  // To undo a file move we issue a move file action to return it to where it was.
+						  file_queue.addJob(id, target_model, latest_record, source_model, latest_source_parent, FileJob.MOVE, !is_undo, true, false);
+					 }
+					 // Otherwise we perform another delete.
+					 else {
+						  file_queue.addJob(id, target_model, latest_record, source_model, latest_source_parent, FileJob.DELETE, !is_undo, true, false);
+					 }
+					 break;
+				default:
+					 System.err.println("Unknown code.");
+				}
+		  }
+
+		  public FileNode getRecord() {
+				return record;
+		  }
+
+		  public long ID() {
+				return id;
+		  }
+	 }
+
+	 private class UndoJobAdder 
+		  implements Runnable {
+		  private boolean undo_event;
+		  private FileNode record;
+		  private FileNode source_parent;
+		  private DragComponent source_model;
+		  private DragComponent target_model;
+		  private int type;
+		  private long id;
+		  public UndoJobAdder(long id, int type, DragComponent source_model, FileNode source_parent, DragComponent target_model, FileNode record, boolean undo_event) {
+				this.id = id;
+				this.record = record;
+				this.source_model = source_model;
+				this.source_parent = source_parent;
+				this.target_model = target_model;
+				this.type = type;
+				this.undo_event = undo_event;
+		  }
+		  public void run() {
+				UndoJob job = new UndoJob(id, source_model, source_parent, target_model, record, type);
+				if(undo_event) {
+					 undo.push(job);
+				}
+				else {
+					 redo.push(job);
+				}
+		  }
+	 }
+
+	 private class UndoStack 
+		  extends LinkedList {
+		  private boolean enabled = false;
+		  private boolean undo;
+		  private int pos = 0;
+		  public UndoStack(boolean undo) {
+				this.undo = undo;
+		  }
+		  public void clear() {
+				super.clear();
+				pos = 0;
+				if(enabled) {
+					 setEnabled(false);
+				}				
+		  }
+		  public UndoJob getJob(long id) {
+				UndoJob job = null;
+				while(job == null && pos < size()) {
+					 UndoJob temp = (UndoJob) get(pos);
+					 if(temp.ID() == id) {
+						  job = temp;
+						  remove(temp);
+					 }
+					 else {
+						  pos++;
+					 }
+				}
+				if(size() == 0) {
+					 setEnabled(false);
+					 pos = 0;
+				}
+				return job;
+		  }
+		  public void push(UndoJob job) {
+				addFirst(job);
+				pos = 0;
+				if(!enabled) {
+					 setEnabled(true);
+				}
+		  }
+		  public UndoJob pop() {
+				UndoJob job = null;
+				if(size() > 0) {
+					 job = (UndoJob) removeFirst();
+					 if(size() == 0 && enabled) {
+						  setEnabled(false);
+						  pos = 0;
+					 }
+				}
+				return job;
+		  }
+		  public void reset() {
+				pos = 0;
+		  }
+		  private void setEnabled(boolean state) {
+				ArrayList sources;
+				if(undo) {
+					 sources = undo_sources;
+				}
+				else {
+					 sources = redo_sources;
+				}
+				for(int i = 0; i < sources.size(); i++) {
+					 AbstractButton source = (AbstractButton) sources.get(i);
+					 source.setEnabled(state);
+				}
+				enabled = state;
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/util/ArrayTools.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/ArrayTools.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/ArrayTools.java	(revision 13666)
@@ -0,0 +1,454 @@
+/* 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.greenstone.gatherer.file.FileNode;
+import org.greenstone.gatherer.msm.Metadata;
+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 FileNode onto the end of a FileNode array.
+	  * @param a The initial <strong>FileNode[]</strong>.
+	  * @param b The new <strong>FileNode</strong>.
+	  * @return An <strong>FileNode[]</strong> containing a followed by b.
+	  */
+	 static public FileNode[] add(FileNode a[], FileNode b) {
+		  FileNode[] c = null;
+		  if(a != null && b != null) {
+				c = new FileNode[a.length + 1];
+				System.arraycopy(a, 0, c, 0, a.length);
+				c[c.length - 1] = b;
+		  }
+		  else if(a == null && b != null) {
+				c = new FileNode[1];
+				c[0] = b;
+		  }
+		  else if(a != null && b == null) {
+				c = a;
+		  }
+		  return c;
+	 }
+	 /** This method efficently appends one FileNode array onto the end of another FileNode array.
+	  * @param a The initial <strong>FileNode[]</strong>.
+	  * @param b The <strong>FileNode[]</strong> to append.
+	  * @return An <strong>FileNode[]</strong> containing a followed by b.
+	  */
+	 static final public FileNode[] add(FileNode a[], FileNode b[]) {
+		  FileNode[] c = null;
+		  if(a != null && b != null) {
+				c = new FileNode[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;
+	 }
+	 /** Determine if a certain FileNode is present in an array of FileNodes.
+	  * @param array The <strong>FileNode[]</strong>.
+	  * @param a The <strong>FileNode</strong> we are searching for.
+	  * @return <i>true</i> if the FileNode is in the array, <i>false</i> otherwise.
+	  */
+	 static final public boolean contains(FileNode array[], FileNode a) {
+		  for(int i = 0; i < array.length; i++) {
+				if(array[i].equals(a)) {
+					 return true;
+				}
+		  }
+		  return false;
+	 }
+	 /** Remove the first element from an array, and return the remaining 'tail'.
+	  * @param a A <strong>FileNode[]</strong>.
+	  * @return The same <strong>FileNode[]</strong> sans its head element.
+	  */
+	 static final public FileNode[] tail(FileNode a[]) {
+		  if(a.length == 1) {
+				return null;
+		  }
+		  FileNode b[] = new FileNode[a.length - 1];
+		  System.arraycopy(a, 1, b, 0, b.length);
+		  return b;
+	 }
+	 
+	 /** Append a Metadata object onto an array of Metadata objects. */
+	 static public Metadata[] add(Metadata[] a, Metadata b) {
+		  Metadata[] c = null;
+		  if(a != null && b != null) {
+				c = new Metadata[a.length + 1];
+				System.arraycopy(a, 0, c, 0, a.length);
+				c[c.length - 1] = b;
+		  }
+		  else if(a == null && b != null) {
+				c = new Metadata[1];
+				c[0] = b;
+		  }
+		  else if(a != null && b == null) {
+				c = a;
+		  }
+		  return c;
+	 }
+	 /** Append a Metadata object array onto an array of Metadata objects. */
+	 static public Metadata[] add(Metadata[] a, Metadata[] b) {
+		  Metadata[] c = null;
+		  if(a != null && b != null) {
+				c = new Metadata[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;
+	 }
+	 /** Remove the Metadata object at the given index form the specified Metadata object array. */
+	 static public Metadata[] remove(Metadata[] a, int index) {
+		  Metadata[] c = null;
+		  if(a != null) {
+				c = new Metadata[a.length - 1];
+				System.arraycopy(a, 0, c, 0, index);
+				System.arraycopy(a, index + 1, c, index, c.length - index);
+		  }
+		  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;
+	 }
+
+	 /** Method to convert a list of nodes from the DOM model into a node array. This is quite useful as using a <strong>NodeList</strong> is problematic if you wish to traverse the tree while editing. Because they are 'live' representations of the model you are editing, it is easy to drop out of for loops early or run off the ends of arrays.
+	  * @param node_list A <strong>NodeList</strong> representing the <strong>Node</strong>s we want to iterate through.
+	  * @return A brand new <strong>Node[]</strong> with the first <strong>Node</strong> in the <strong>NodeList</strong> at the head.
+	  * @see org.w3c.dom.Node
+	  * @see org.w3c.dom.NodeList
+	  */
+	 static public Node[] nodeListToNodeArray(NodeList node_list) {
+		  Node nodes[] = null;
+		  for(int i = 0; i < node_list.getLength(); i++) {
+				nodes = add(nodes, node_list.item(i));
+		  }
+		  return nodes;
+	 }
+	 /** 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. */
+	 static public void sort(File[] files) {
+		  sort(files, false);
+	 }
+
+	 /** Sorts an array of files. Can also to instructed to list directories first. Case insensitive.
+	  * @param files The File[] to be sorted.
+	  * @param directories_first true if you want to directories to be listed first.
+	  */
+	 static public void sort(File[] files, boolean directories_first) {
+		  if(files != null && files.length > 1) {
+				FileComparator comparator = new FileComparator(directories_first);
+				Arrays.sort(files, comparator);
+		  }		  
+	 }
+
+	 /** Comparator used to order files. */
+	 static private class FileComparator
+	 implements Comparator {
+		  private boolean directories_first = false;
+
+		  public FileComparator(boolean directories_first) {
+				this.directories_first = directories_first;
+		  }
+		  /** 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) {
+				int result = 0;
+				File f1 = (File) o1;
+				String n1 = f1.getName().toLowerCase();
+				File f2 = (File) o2;
+				String n2 = f2.getName().toLowerCase();
+				// Special checks for system roots as these include removable media drives and thus we should never attempt to call isDirectory until the user explicitly attempts to map drive.
+				boolean f1_system_root = FileSystemView.getFileSystemView().isFileSystemRoot(f1);
+				boolean f2_system_root = FileSystemView.getFileSystemView().isFileSystemRoot(f2);
+				if((f1_system_root && f2_system_root) || (!f2_system_root && f1_system_root && f2.isDirectory()) || (!f1_system_root && f1.isDirectory() && f2_system_root) || (f1.isDirectory() && f2.isDirectory()) || (f1.isFile() && f2.isFile())) {
+					 result = n1.compareTo(n2);
+				}
+				else if(f1_system_root || f1.isDirectory()) {
+					 result = -1;
+				}
+				else {
+					 result = 1;
+				}
+				return result;
+		  }
+		  /** Compare two files for equality, in terms of their file paths.
+			* @param object The <strong>Object</strong> representing the file we are about to compare ourselves to.
+			* @return <i>true</i> if we equal the given file, <i>false</i> otherwise.
+			*/
+		  public boolean equals(Object obj) {
+				return (compare(this, obj) == 0);
+		  }
+	 }
+}
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/util/DecodeHTMLReader.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/DecodeHTMLReader.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/DecodeHTMLReader.java	(revision 13666)
@@ -0,0 +1,124 @@
+package org.greenstone.gatherer.util;
+
+import java.io.*;
+import org.greenstone.gatherer.Gatherer;
+
+public class DecodeHTMLReader
+	 extends PushbackReader {
+
+	 public DecodeHTMLReader(Reader source) {
+		  super(source, 4);
+	 }
+
+	 /** Read a single character. */
+	 public int read() {
+		  return decode();
+	 }
+ 
+	 /** Read characters into a portion of an array. */
+	 public int read(char[] cbuf, int off, int len) {
+		  int count = 0;
+		  for(int i = off; i < len && ready(); i++) {
+				cbuf[i] = (char)decode();
+				count++;
+		  }
+		  return count;
+	 }
+
+	 public boolean ready() {
+		  try {
+				return super.ready();
+		  }
+		  catch (Exception error) {
+		  }
+		  return false;
+	 }
+
+	 /** Retrieve the next character off the stream. Unfortunately I have to do this a character at a time (which is slow). I also have to keep in mind that if a suspect encoded character turns out not to be I have to replace the extra characters. */
+	 private int decode() {
+		  int character;
+		  try {
+				character = super.read();
+		  }
+		  catch (Exception error) {
+				character = ' ';
+		  }
+		  try {
+				if(character == '&') {
+					 int amp = super.read();
+					 switch(amp) {
+					 case 'a':
+					 case 'A':
+						  int ampap = super.read();
+						  int ampapo = super.read();
+						  int ampapos = super.read();
+						  int ampapossemi = super.read();
+						  if((ampap == 'p' || ampap == 'P') && (ampapo == 'o' || ampapo == 'O') && (ampapos == 's' || ampapos == 'S') && ampapossemi == ';') {
+								// Read an &apos; so return an apostrophy
+								return '\'';
+						  }
+						  // Not a apos. Return the characters removed in the correct order.
+						  super.unread(ampapossemi);
+						  super.unread(ampapos);
+						  super.unread(ampapo);
+						  super.unread(ampap);
+						  break;
+					 case 'g':
+					 case 'G':
+						  int ampgt = super.read();
+						  int ampgtsemi = super.read();
+						  if((ampgt == 't' || ampgt == 'T') && ampgtsemi == ';') {
+								return '>';
+						  }
+						  super.unread(ampgtsemi);
+						  super.unread(ampgt);
+						  break;
+					 case 'l':
+					 case 'L':
+						  int amplt = super.read();
+						  int ampltsemi = super.read();
+						  if((amplt == 't' || amplt == 'T') && ampltsemi == ';') {
+								return '<';
+						  }
+						  super.unread(ampltsemi);
+						  super.unread(amplt);
+						  break;
+					 case 'q':
+					 case 'Q':
+						  int ampqu = super.read();
+						  int ampquo = super.read();
+						  int ampquot = super.read();
+						  int ampquotsemi = super.read();
+						  if((ampqu == 'u' || ampqu == 'U') && (ampquo == 'o' || ampquo == 'O') && (ampquot == 't' || ampquot == 'T') && ampquotsemi == ';') {
+								return '\"';
+						  }
+						  super.unread(ampquotsemi);
+						  super.unread(ampquot);
+						  super.unread(ampquo);
+						  super.unread(ampqu);
+						  break;
+					 case '#':
+						  int amphash = super.read();
+						  int amphash3 = super.read();
+						  int amphash39 = super.read();
+						  int amphash39semi = super.read();
+						  if(amphash == '#' && amphash3 == '3' && amphash39 == '9' && amphash39semi == ';') {
+								return '\'';
+						  }
+						  super.unread(amphash39semi);
+						  super.unread(amphash39);
+						  super.unread(amphash3);
+						  super.unread(amphash);
+						  break;
+					 }
+					 // Not a suspect. Return the character removed.
+					 super.unread(amp);
+				}
+		  }
+		  catch (Exception error) {
+				Gatherer.printStackTrace(error);
+		  }
+		  // Nothing special. Simply return the character extracted.
+		  return character;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/util/DictionaryTreeNode.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/DictionaryTreeNode.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/DictionaryTreeNode.java	(revision 13666)
@@ -0,0 +1,14 @@
+package org.greenstone.gatherer.util;
+
+import javax.swing.tree.TreeNode;
+
+public interface DictionaryTreeNode {
+	 /** Returns the child at the specified index in this node's child array. */
+	 public TreeNode getChildAt(int index);
+	 /** Returns the number of children of this node. */   
+	 public int getChildCount();
+	 /** This method should always return the same key, regardless of the value of toString(). */
+	 public String getKey();
+	 /** Set the text shown by toString() to the given value. */
+	 public void setText(String value);
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/util/DragComponent.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/DragComponent.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/DragComponent.java	(revision 13666)
@@ -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;
+import org.greenstone.gatherer.util.DragGroup;
+/** 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/start/gli/src/org/greenstone/gatherer/util/DragGroup.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/DragGroup.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/DragGroup.java	(revision 13666)
@@ -0,0 +1,155 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *               24/03/03 - Moved again, and rewritten for new Tree.
+ * @author John Thompson
+ * @version 2.3
+ */
+import java.awt.Point;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+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;
+import org.greenstone.gatherer.util.DragComponent;
+
+/** 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. 
+	  * @see org.greenstone.gatherer.tree.DragComponent#gainFocus
+	  * @see org.greenstone.gatherer.tree.DragComponent#loseFocus
+	  */
+	 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;
+		  System.err.println("The drag source is now " + drag_source);
+	 }
+}
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/util/DragTreeSelectionModel.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/DragTreeSelectionModel.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/DragTreeSelectionModel.java	(revision 13666)
@@ -0,0 +1,292 @@
+package org.greenstone.gatherer.util;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+import java.awt.Point;
+import java.awt.event.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Dictionary;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.tree.DragTree;
+
+public class DragTreeSelectionModel
+	 extends DefaultTreeSelectionModel
+	 implements MouseListener {
+
+	 boolean immediate = false;
+
+	 private int type               = -1;
+
+	 private String suffix = null;
+
+	 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;
+
+	 public DragTreeSelectionModel(DragTree tree) {
+		  super();
+		  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);
+				suffix = null;		
+		  }
+	 }
+	 
+	 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);
+				suffix = null;
+		  }		  
+	 }
+	 
+	 public String getDetails() {
+		  if(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 = Gatherer.dictionary.get("FileActions.Selected", args);
+					 }
+					 else if(file_count > 1) {
+						  args = new String[1];
+						  args[0] = String.valueOf(file_count);
+						  suffix = Gatherer.dictionary.get("FileActions.Files_And_Directory_Selected", args);
+					 }
+					 else if(folder_count > 1) {
+						  args = new String[1];
+						  args[0] = String.valueOf(folder_count);
+						  suffix = Gatherer.dictionary.get("FileActions.File_And_Directories_Selected", args);
+					 }
+					 else {
+						  suffix = Gatherer.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 = Gatherer.dictionary.get("FileActions.Files_Selected", args);
+					 }
+					 else if(file_count == 1) {
+						  suffix = Gatherer.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 = Gatherer.dictionary.get("FileActions.Directories_Selected", args);
+					 }
+					 else {
+						  suffix = Gatherer.dictionary.get("FileActions.Directory_Selected");
+					 }
+				}
+				else {
+					 Gatherer.dictionary.get("FileActions.No_Selection"); 
+				}
+				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) {
+		  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;
+				suffix = null;
+				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;
+				suffix = null;
+				break;
+		  }
+	 }
+
+	 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);
+				suffix = null;
+		  }
+	 }
+	 
+	 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);
+				suffix = null;
+		  }
+	 }
+
+	 /** Ensure that the given path is appropriate to add to the current selection, preventing mixed selections of files and folder. We also must check that no path is a ancestor/descendant of another. There is also a slight optimization in that if the current selection contains only files (which if the rules are followed, and the first 'test' node is a file, then it must) there is no point in checking the remaining files in the selection. Its a different story for folders however as we have to ensure no folder is in the lineage of another, even if they are all folders! */
+	 private boolean isAppropriate(TreePath path) {
+		  boolean appropriate = true;
+		  TreeNode new_node = (TreeNode) path.getLastPathComponent();
+		  if(selection != null && selection.length > 0) {
+				TreeNode test_node = (TreeNode) selection[0].getLastPathComponent();
+				appropriate = appropriate && (new_node.isLeaf() == test_node.isLeaf());
+				if(!test_node.isLeaf()) {
+					 appropriate = appropriate && !path.isDescendant(selection[0]) && !selection[0].isDescendant(path);
+					 for(int i = 1; appropriate && selection != null && i < selection.length; i++) {
+						  TreeNode current_node = (TreeNode) selection[i].getLastPathComponent();
+						  appropriate = appropriate && (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. 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(paths != null) {
+				if(paths.length >= 2) {
+					 // Prevent folders being added to a previous selection of files and vice-versa
+					 // First check that the new selection are all of the same type
+					 for(int i = 0; appropriate && paths != null && i < paths.length - 1; i++) {
+						  TreeNode one_node = (TreeNode) paths[i].getLastPathComponent();
+						  TreeNode other_node = (TreeNode) paths[i+1].getLastPathComponent();
+						  appropriate = appropriate && (one_node.isLeaf() == other_node.isLeaf());
+						  appropriate = appropriate && !paths[i].isDescendant(paths[i+1]) && !paths[i+1].isDescendant(paths[i]);
+					 }
+				}
+				// Now we check the current selection against the first node in our new selection
+				if(appropriate && check_current) {
+					 appropriate = isAppropriate(paths[0]);
+				}
+		  }
+		  return appropriate;
+	 }
+}
+
Index: /tags/start/gli/src/org/greenstone/gatherer/util/EmailAddress.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/EmailAddress.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/EmailAddress.java	(revision 13666)
@@ -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.
+ *
+ * <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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* 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:      03/05/02
+ * Revised:      04/10/02 - Commented
+ **************************************************************************************/
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.GridLayout;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.util.StringTokenizer;
+import javax.swing.BorderFactory;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import org.greenstone.gatherer.Gatherer;
+/** This class wraps an email address, separating address and host, and providing a pretty printer. 
+ * @author John Thompson
+ * @version 2.3
+ */
+public class EmailAddress {
+	 /** The controls for editing this email. */
+	 private Control controls = null;
+	 /** A reference to the Gatherer. */
+	 private Gatherer gatherer = null;
+	 /** The type of this email, in collection configuration terms. */
+	 private int type = -1;
+	 /** The host part of the email (after @). */
+	 public String host = null;
+	 /** The user part of the email (before @). */
+	 public String user = null;
+	 /** The name given to or associated with this particular email (maybe the persons name, or it this email belongs to a certain variable i.e Collection Author). */
+	 public String name = null;
+	 /** Enumeration of important email address types - in this case the creator of a collection. */
+	 static final public int CREATOR = 0;
+	 /** Enumeration of important email address types - in this case the maintainer of a collection. */
+	 static final public int MAINTAINER = 1;
+	 /** Enumeration of important email address types - in this case any other email address other than the two noted above. */
+	 static final public int OTHER = 2;
+	 /** Constructor.
+	  * @param gatherer A reference to the <strong>Gatherer</strong> for messaging purposes.
+	  */
+	 public EmailAddress(Gatherer gatherer) {
+		  this.gatherer = gatherer;
+	 }
+	 /** Constructor.
+	  * @param gatherer A reference to the <strong>Gatherer</strong> for messaging purposes.
+	  * @param raw A <strong>String</strong> containing both the name and email separated by whitespace.
+	  */
+	 public EmailAddress(Gatherer gatherer, String raw) {
+		  this(gatherer);
+		  StringTokenizer tokenizer = new StringTokenizer(raw);
+		  if(tokenizer.countTokens() >= 2) {
+				this.name = tokenizer.nextToken();
+				if(name.equals("creator")) {
+					 type = CREATOR;
+				}
+				else if(name.equals("maintainer")) {
+					 type = MAINTAINER;
+				}
+				else {
+					 type = OTHER;
+				}
+				String email = tokenizer.nextToken();
+				if(email.indexOf("@") != -1) {
+					 this.user = email.substring(0, email.indexOf("@"));
+					 this.host = email.substring(email.indexOf("@") + 1);
+				}
+		  }
+		  else {
+				this.name = "Invalid Email";
+				this.user = "";
+				this.host = "";
+		  }
+	 }
+	 /** Retrieve the controls associated with editing this email address.
+	  * @return A <strong>JPanel</strong> containing those controls.
+	  */
+	 public JPanel getControls() {
+		  if(controls == null) {
+				controls = new Control(name);
+		  }
+		  return controls;
+	 }
+	 /** Retrieve the controls associated with editing this email address, but ensure they have a certain title label.
+	  * @param label The <strong>String</strong> to use as the label.
+	  * @return A <strong>JPanel</strong> containing those controls.
+	  */
+	 public JPanel getControls(String label) {
+		  if(controls == null) {
+				controls = new Control(label);
+		  }
+		  return controls;
+	 }
+	 /** Method to produce this email as a string.
+	  * @return A <strong>String</string> representing this email.
+	  */
+	 public String toString() {
+		  return name + " " + user + "@" + host;
+	 }
+	 /** Determines if this is a valid email. 
+	  * @return <i>true</i> if it is current valid, <i>false</i> otherwise. 
+	  */
+	 public boolean isValid() {
+		  return (user != null && user.length() > 0) && (host != null && host.length() > 0);
+	 }
+	 /** 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 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.
+	  */
+	 private 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. Note that argument numbers greater than or equal to 32 are automatically mapped to the formatting String named Farg<I>n</I>.
+	  * @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 automatically populated with formatting Strings of with argument String provided in the get call.
+	  * @see org.greenstone.gatherer.Dictionary
+	  * @see org.greenstone.gatherer.Gatherer
+	  */
+	 private String get(String key, String args[]) {
+		  if(key.indexOf('.') == -1) {
+				key = "CDM.General.Email." + key;
+		  }
+		  return gatherer.dictionary.get(key, args);
+	 }
+	 /** The controls used for editing an email address. Basically two text fields with an '@' label in the middle. You also have a title label for this control, which is known for the major email address types, or can be supplied for any other purpose. */
+	 private class Control 
+		  extends JPanel {
+		  /** The at symbol label. */
+		  private JLabel at = null;
+		  /** The title label. */
+		  private JLabel label = null;
+		  /** The first text field for the user part of an address. */
+		  private JTextField field1 = null;
+		  /** The second text field for the host part of an address. */
+		  private JTextField field2 = null;
+		  /** The panel on to which the text fields and the at label are placed. */
+		  private JPanel middle = null;
+		  /** Constructor.
+			* @param name The <strong>String</strong> to use for the title label.
+			* @see org.greenstone.gatherer.util.EmailAddress.Control.HostListener
+			* @see org.greenstone.gatherer.util.EmailAddress.Control.UserListener
+			*/
+		  public Control(String name) {
+				super();
+				switch(type) {
+				case CREATOR:
+					 label = new JLabel(get("Creator"));
+					 break;
+				case MAINTAINER:
+					 label = new JLabel(get("Maintainer"));
+					 break;					 
+				default:
+					 label = new JLabel(name);
+				}
+				middle = new JPanel();
+				field1 = new JTextField(user);
+				at = new JLabel("@");
+				field2 = new JTextField(host);
+				// Add listeners
+				field1.addKeyListener(new UserListener());
+				field2.addKeyListener(new HostListener());
+				// Layout
+				label.setBorder(BorderFactory.createEmptyBorder(2,5,2,10));
+
+				at.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
+
+				middle.setLayout(new BorderLayout());
+				middle.add(field1, BorderLayout.CENTER);
+				middle.add(at, BorderLayout.EAST);
+
+				setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+				setLayout(new GridLayout(1,3));
+				add(label);
+				add(middle);
+				add(field2);
+		  }
+		  /** Listens for changes of the host part of the email address and updates the email object accordingly. */	 
+		  private class HostListener
+				extends KeyAdapter {
+				/** Whenever a key is released (ie after a key typed event has been fired) when typing in the host field, this method updates the host field of the email object.
+				 * @param event A <strong>KeyEvent</strong> containing extra information about the key release performed.
+				 */
+				public void keyReleased(KeyEvent event) {
+					 host = field2.getText();
+				}
+		  }
+		  /** Listens for changes of the user part of the email address and updates the email object accordingly. */
+		  private class UserListener
+				extends KeyAdapter {
+				/** Whenever a key is released (ie after a key typed event has been fired) when typing in the user field, this method updates the user field of the email object.
+				 * @param event A <strong>KeyEvent</strong> containing extra information about the key release performed.
+				 */
+				public void keyReleased(KeyEvent event) {
+					 user = field1.getText();
+				}
+		  }
+		  
+	 }
+}
+
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/util/EnumeratedVector.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/EnumeratedVector.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/EnumeratedVector.java	(revision 13666)
@@ -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.
+ *
+ * <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
+ * Description:  The Gatherer: a tool for gathering and enriching a digital collection.
+ * Company:      The University of Waikato
+ * Written:      15/07/02
+ * Revised:      04/10/02 - Commented
+ **************************************************************************************/
+import java.util.Enumeration;
+import java.util.Vector;
+/** A Vector which also supports the enumeration interface.
+ * @author John Thompson
+ * @version 2.3
+ */
+public class EnumeratedVector
+	 extends Vector 
+	 implements Enumeration {
+	 /** The current index into our enumerated vector. */
+	 private int index = 0;
+	 /** Can we call nextElement() without running out of entries in the vector.
+	  * @return <i>true</i> if there are elements remaining, <i>false</i> otherwise.
+	  */
+	 public boolean hasMoreElements() {
+		  return (index < size());
+	 }
+	 /** Retrieve the next element indicated by the current index.
+	  * @return The next element as an <strong>Object</strong>.
+	  */
+	 public Object nextElement() {
+		  Object object = null;
+		  if(index < size()) {
+				object = get(index);
+				index++;
+		  }
+		  return object;
+	 }  
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/util/ExclusiveListSelectionListener.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/ExclusiveListSelectionListener.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/ExclusiveListSelectionListener.java	(revision 13666)
@@ -0,0 +1,96 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* 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:      16/05/02
+ * Revised:      04/10/02 - Commented
+ **************************************************************************************/
+import javax.swing.JList;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+/** This listener is used to ensure that in a group of JList or similar components, only one list actually has elements selected. 
+ * @author John Thompson
+ * @version 2.3
+ */
+public class ExclusiveListSelectionListener 
+	 implements ListSelectionListener {
+	 /** A flag set to show that we are already dealing with a list selection change, and to ignore further ones until the flag becomes unset again. */
+	 private boolean ignore = false;
+	 /** An array of JList components, containing each JList thats registered with this listener. */
+	 private JList lists[] = null;
+	 /** Method to register a new JList with this listener.
+	  * @param list The new <strong>JList</strong> to register.
+	  */
+	 public void add(JList list) {
+		  list.addListSelectionListener(this);
+		  if(lists == null) {
+				lists = new JList[1];
+				lists[0] = list;
+		  }
+		  else {
+				JList temp[] = new JList[lists.length + 1];
+				System.arraycopy(lists, 0, temp, 0, lists.length);
+				temp[lists.length] = list;
+				lists = temp;
+		  }
+	 }
+	 /** Any implementation of ListSelectionListener must include this method so we can be informed when the selection changes. In this case we want to clear the selections of all other registered JLists other than the caller.
+	  * @param event A <strong>ListSelectionEvent</strong> containing informaiton about the event.
+	  */
+	 public void valueChanged(ListSelectionEvent event) {
+		  if(!ignore) {
+				ignore = true;
+				JList source = (JList)event.getSource();
+				for(int i = 0; i < lists.length; i++) {
+					 if(lists[i] != source) {
+						  lists[i].clearSelection();
+					 }
+				}
+				ignore = false;
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/util/GURL.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/GURL.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/GURL.java	(revision 13666)
@@ -0,0 +1,193 @@
+/**
+ *#########################################################################
+ *
+ * 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.io.File;
+import java.io.Serializable;
+
+import java.lang.Cloneable;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import java.util.Vector;
+
+import javax.swing.JProgressBar;
+
+/**
+ * Extends the standard URL class to include several new data elements and
+ * the ability to take a string and parse a valid url.
+ */
+public class GURL
+	 implements Cloneable, Serializable {
+
+	 private Integer type;
+
+	 private URL url;
+
+	 private String file;
+	 private String host;
+	 private String path;
+	 private String protocol;
+	 private String title = "empty";
+
+	 /** This Vector maintains a record of the url links from within
+	  * this resource, and their type (EXTERNAL vs INTERNAL). Internal
+	  * links can be 'hidden' from the user if desired, or a user can
+	  * opt to have all internal links automatically moved into a
+	  * collection if the page that depends upon them is moved. <BR>
+	  * Each entry in the vector is of the form.
+	  * links[i] = String url
+	  * links[i+1] = int type
+	  */
+	 private Vector links;
+
+	 /* Static Integer identifiers for ease of use. */
+	 static public Integer INTERNAL = new Integer(0);
+	 static public Integer EXTERNAL = new Integer(1);
+
+	 public GURL(String url_str) {
+		  this(url_str, GURL.EXTERNAL);
+	 }
+
+	 public GURL(URL url) {
+		  this(url, GURL.EXTERNAL);
+	 }
+
+	 public GURL(URL url, Integer type) {
+		  this.type = type;
+		  this.url = url;
+	 }
+
+	 public GURL(String url_str, Integer type) {
+		  this.type = type;
+
+		  try {
+				if(!url_str.startsWith("file:") && url_str.indexOf("://") == -1) {
+					 url_str = "http://" + url_str;
+				}
+				url = new URL(url_str);
+		  }
+		  catch (MalformedURLException e) {
+				// Fix it
+		  }
+	 }
+
+	 public void addLink(String url) {
+		  addLink(url, GURL.EXTERNAL);
+	 }
+
+	 public void addLink(String url, Integer type) {
+		  if(links == null) {
+				links = new Vector();
+		  }
+		  links.add(url);
+		  links.add(type);
+	 }
+
+	 /** Used by tree renderer to display name. So we'll only return the
+	  * filename.
+	  */
+	 public String getFile() {
+		  return parseFile(url.getFile());
+	 }
+
+	 public String getHost() {
+		  return url.getHost();
+	 }
+
+	 public String getLocalFile() {
+		  String local_file = getPath() + File.separator + getFile();
+		  // Strip msdos roots if they're still there.
+			while(local_file.indexOf(":") != -1) {
+				local_file = local_file.substring(0, local_file.indexOf(":")) + local_file.substring(local_file.indexOf(":") + 1);
+			}
+		  return local_file;
+	 }
+
+	 public String getPath() {
+		  return getHost() + parsePath(url.getFile());
+	 }
+
+	 public String getProtocol() {
+		  String protocol = url.getProtocol();
+		  if(protocol.equals("file")) {
+				return protocol + ":";
+		  }
+		  return protocol + "://";
+	 }
+
+	 public URL getURL() {
+		  return url;
+	 }
+
+	 public String toString() {
+		  return url.toString();
+	 }
+
+	 public boolean valid() {
+		  return (url != null);
+	 }
+
+	 private String parseFile(String raw) {
+		  if(raw != null && !raw.equals("")) {
+				// Remove everything upto and including the last '/'
+				if(raw.indexOf("/") != -1) {
+					 return raw.substring(raw.lastIndexOf("/") + 1);
+				}
+		  }
+		  return raw;
+	 }
+
+	 private String parsePath(String raw) {
+		  if(raw != null && !raw.equals("")) {
+				// Remove everything after the last "/"
+				if(raw.indexOf("/") != -1) {
+					 return raw.substring(0, raw.lastIndexOf("/"));
+				}
+		  }
+		  return raw;
+	 }
+
+}
+
Index: /tags/start/gli/src/org/greenstone/gatherer/util/Generator.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/Generator.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/Generator.java	(revision 13666)
@@ -0,0 +1,450 @@
+/**
+ *#########################################################################
+ *
+ * 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.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.lang.Exception;
+import java.lang.String;
+import java.lang.StringBuffer;
+import java.util.HashMap;
+/** Automatically generates html help documents given an input text file using markup and a template defining what the markup means. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 1.0
+ */
+public class Generator {
+
+	private FileOutputStream file_output_stream = null;
+
+	private TemplateManager template_manager = null;
+
+	public Generator(File test_file, File template_file) {
+		template_manager = new TemplateManager(template_file);
+		File files[] = null;
+		// If test_file is a file, goody.
+		if(test_file.isFile()) {
+			files = new File[1];
+			files[0] = test_file;
+		}
+		// Otherwise we use all of test_files children.
+		else {
+			files = test_file.listFiles();
+		}
+		// Its unfortunate we test this twice for the basic case, but we need to ensure that source managers are only contructed for non-directory files.
+		for(int i = 0; i < files.length; i++) {
+			if(files[i].isFile()) {
+				SourceManager source_manager = new SourceManager(files[i]);
+				source_manager = null;
+			}
+		}
+		// All done.
+	}
+
+	public void exit() {
+		if(file_output_stream != null) {
+			try {
+				file_output_stream.close();
+				file_output_stream = null;
+			}
+			catch(Exception error) {
+				error.printStackTrace();
+			}
+		}
+		System.exit(0);
+	}
+
+	public void out(String msg) {
+		System.err.println(msg);
+		try {
+			if(file_output_stream == null) {
+				file_output_stream = new FileOutputStream("output.txt");
+			}
+			file_output_stream.write((msg + "\n").getBytes());
+		}
+		catch(Exception error) {
+			error.printStackTrace();
+			System.err.println("An error has occured. View output.txt for more information.");
+			exit();
+		}
+	}
+
+	static public void main(String args[]) {
+		System.err.println("Rapid repeated HTML generation tool.");
+		System.err.println("  written by John Thompson, 2002\n");
+		boolean usage = false;
+		// Attempt to generate html from text
+		if(args.length == 2) {
+			File text_file = new File(args[0]);
+			File template_file = new File(args[1]);
+			if(!text_file.exists() || !template_file.exists() || !template_file.isFile()) {
+				usage = true;
+			}
+			else {
+				Generator generator = new Generator(text_file, template_file);
+				generator.exit();
+			}
+		}
+		else {
+			usage = true;
+		}
+		// Print usage message
+		if(usage) {
+			System.err.println("Usage: GenHelp <text_file> <template_file>");
+			System.err.println("text_file     - A file containing text marked up using special tags.");
+			System.err.println("template_file - An HTML file using tags to specify where to insert text.");
+		}
+	}
+
+	/** An HTML block object is essentially a String buffer containing several places where it demands further text be appended. To this end you can ask if an HTML block is ready, and if not provide it with a further text fragment and try again. */
+	private class HTMLBlock {
+		/** Prevent the original HTML block being changed. */
+		private boolean original;
+
+		private int insertion_position = -1;
+		/** The name of this HTML block as taken from the template file. */
+		private String name = null;
+		private String paragraph_tag = null;
+		/** The HTML block itself. */
+		private StringBuffer data = null;
+		/** Constructor takes the HTML blocks name as extracted from the template file.
+		* @param name The name of this HTML block as a <strong>String</strong>.
+		*/
+		public HTMLBlock(String name) {
+			this.data = new StringBuffer("");
+			this.name = name;
+			this.original = true;
+		}
+		/** Copy constructor takes the HTML block and its name as extracted from the template file.
+		* @param name The name of this HTML block as a <strong>String</strong>.
+		* @param raw The raw HTML code as a <strong>String</strong>.
+		*/
+		public HTMLBlock(String name, String raw) {
+			this.data = new StringBuffer(raw);
+			this.name = name;
+			this.original = false;
+		}
+		/** Append this text to the end of the current block.
+		* @param text The <strong>String</strong> to add.
+		*/
+		public void addLine(String text) {
+			if(original) {
+				data.append(text);
+				data.append("\n");
+			}
+		}
+		/** Retrieve the name of this HTML block.
+		* @return A <strong>String</strong> representing the name.
+		*/
+		public String getName() {
+			return name;
+		}
+		/** Insert a text fragment into this HTML block.
+		* @param fragment The <strong>String</strong> to insert.
+		* @return <i>true</i> if an insertion occured, <i>false</i> otherwise.
+		*/
+		public boolean insert(String fragment) {
+			if(!original) {
+				// Find the start of an insertion tag.
+				int start = data.indexOf("<$");
+				if(start != -1) {
+					// Find the end of an insertion tag.
+					int end = data.indexOf(">", start) + 1;
+					// Determine the tag, and search for any paragraphing information.
+					String tag = data.substring(start, end);
+					if(tag.length() > 7) {
+						paragraph_tag = "<p " + tag.substring(7) + "\n";
+						fragment = paragraph_tag + fragment + "\n</p>\n";
+					}
+					// Substitue the fragment for the tag.
+					data.replace(start, end, fragment);
+					// Now set insertion position
+					insertion_position = start + fragment.length();
+					return true;
+				}
+				// Its possible that we've already got enough text to output this block. Essentially this new fragment is meant to be another paragraph. Such fragments are always added immediately after the last fragment inserted.
+				else if(insertion_position != -1) {
+					if(paragraph_tag != null) {
+						fragment = paragraph_tag + fragment + "\n</p>\n";
+					}
+				  data.insert(insertion_position, fragment);
+					insertion_position = insertion_position + fragment.length();
+				}
+			}
+			return false;
+		}
+		/** Is this block ready to written out.
+		* @return <i>true</i> if we can write this block out, <i>false</i> if text insertion points still exist.
+		*/
+		public boolean ready() {
+			return data.indexOf("<$") == -1;
+		}
+		/** Produce a copy of this block with all text insertions intact.
+		* @return A new <strong>HTMLBlock</strong>.
+		*/
+		public HTMLBlock spawn() {
+			return new HTMLBlock(name, data.toString());
+		}
+		/** Return the HTML block within this object.
+		* @return A <strong>String</strong> containing the HTML code.
+		*/
+		public String toString() {
+			return data.toString();
+		}
+	}
+	/** Reads in the given text file, outputing HTML by utilizing HTML blocks stored in the TemplateManager. The manager understands one extra tag <$FILE name=<filename>> which is used to indicate the presence of several output files within one input file. If this tag is not found the default name for the output file is "<text_file_name>.htm". */
+	private class SourceManager {
+		private File text_file = null;
+
+		private FileOutputStream output_file = null;
+
+		public SourceManager(File text_file) {
+			out("Building Source Manager:");
+			this.text_file = text_file;
+			try {
+				out("  reading from: " + text_file.getName());
+				// Create input stream from the text file which we read a line at a time.
+				FileReader file_reader = new FileReader(text_file);
+				BufferedReader buffered_reader = new BufferedReader(file_reader);
+				HTMLBlock block = null;
+				String line = null;
+				StringBuffer paragraph = null;
+				while((line = buffered_reader.readLine()) != null) {
+					boolean done = false;
+					// What we do here depends on what state we are in and what tag or text we are reading.
+					// The first case to consider is a file open command tag. This tells us the next block of html should be written to a certain file.
+					if(line.startsWith("<$FILE")) {
+						// Close any existing output file.
+						if(output_file != null) {
+  						// Write any existing block
+  						if(block != null) {
+  							if(paragraph != null) {
+  								block.insert(paragraph.toString());
+  								paragraph = null;
+  							}
+  							out("  write: " + block.getName());
+	  						output_file.write((block.toString()).getBytes());
+	  						block = null;
+	  					}
+							output_file.close();
+							output_file = null;
+						}
+						// Determine the new file name.
+						String name = line.substring(12, line.lastIndexOf(">"));
+						// Create new file.
+						output_file = new FileOutputStream(name);
+						// Dealt with
+						out("  writing to: " + name);
+						name = null;
+						done = true;
+					}
+					else if(line.startsWith("<$")) {
+						// If we have a block open its time to write it out.
+						if(block != null) {
+							if(paragraph != null) {
+								block.insert(paragraph.toString());
+								paragraph = null;
+							}
+							// Check we have somewhere to write to.
+							if(output_file == null) {
+								output_file = new FileOutputStream(text_file.getName() + ".htm");
+							}
+							out("  write: " + block.getName());
+							output_file.write((block.toString()).getBytes());
+							block = null;
+						}
+						// Now determine the new blocks name.
+						String name = line.substring(2, line.lastIndexOf(">"));
+						// Retrieve that block
+						block = template_manager.getHTMLBlock(name);
+						if(block == null) {
+							// Somethings gone wrong, most likely an unidentified block name.
+							out("  no such block: " + name);
+						}
+						name = null;
+						done = true;
+					}
+					// Its just text. However we want text in paragraph blocks. A paragraph is delimited by a "\n\n" or the start of a tag.
+					if(!done) {
+						// If the line read is "" it means we've encountered a "\n\n".
+						if(line.equals("")) {
+							// Add paragraph to open block.
+							if(block != null && paragraph != null) {
+								block.insert(paragraph.toString());
+								paragraph = null;
+							}
+						}
+						// Any other case just add to paragraph. Ensure that there is at least one space between the two fragments
+						else {
+							if(paragraph == null) {
+								paragraph = new StringBuffer(line);
+							}
+							else {
+								if(paragraph.charAt(paragraph.length() - 1) != ' ' && line.charAt(0) != ' ') {
+									paragraph.append(" ");
+								}
+								paragraph.append(line);
+							}
+						}
+					}
+				}
+				// Write out any outstanding blocks.
+				if(block != null) {
+					if(paragraph != null) {
+						block.insert(paragraph.toString());
+						paragraph = null;
+					}
+					// Check we have somewhere to write to.
+					if(output_file == null) {
+						output_file = new FileOutputStream(text_file.getName() + ".htm");
+					}
+					out("  write: " + block.getName());
+					output_file.write((block.toString()).getBytes());
+				}
+				block = null;
+				paragraph = null;
+				line = null;
+				output_file.close();
+				output_file = null;
+			}
+			catch (Exception error) {
+				error.printStackTrace();
+  			System.err.println("An error has occured. View output.txt for more information.");
+				exit();
+			}
+		}
+	}
+	/** Reads in a template file, extracting HTMLBlocks and storing them. It then allows the program to retrieve a block by its name and process it accordingly. */
+	private class TemplateManager
+		extends HashMap {
+		/** Constructor.
+		* @param template_file The <strong>File</strong> template information will be extracted from.
+		*/
+		public TemplateManager(File template_file) {
+			out("Building Template Manager:");
+			try {
+				FileReader file_reader = new FileReader(template_file);
+				BufferedReader buffered_reader = new BufferedReader(file_reader);
+				HTMLBlock block = null;
+				String line = null;
+				while((line = buffered_reader.readLine()) != null) {
+					boolean done = false;
+					// Detect a template command.
+					if(line.startsWith("<$")) {
+						// See if this is an open block tag, text insertion tag, or a block closing tag and react appropriately.
+						if(line.startsWith("<$TEXT")) {
+							// Text tag. deal with it below.
+						}
+						else if(line.startsWith("<$/")) {
+							// Block closing tag. If we have an open block close it.
+							if(block != null) {
+								out("  parsed: " + block.getName());
+								// Add to our hashmapping of known blocks.
+								put(block.getName(), block);
+								block = null;
+								done = true;
+							}
+							// Otherwise deal with it below.
+						}
+						// The last option is an open block tag.
+						else {
+							// If have a block open, close it.
+							if(block != null) {
+								out("  parsed: " + block.getName());
+								put(block.getName(), block);
+								block = null;
+							}
+							// Now create a new block with the appropriate name.
+							String name = line.substring(2, line.indexOf(">"));
+							block = new HTMLBlock(name);
+							done = true;
+						}
+					}
+					// Otherwise its just HTML.
+					if(!done) {
+						// If we are building a block append this line.
+						if(block != null) {
+							block.addLine(line);
+						}
+						// Otherwise we just ignore it.
+						else {
+							if(line.length() > 0) {
+								out("  can't parse: " + line);
+							}
+							// Otherwise we're just chewing up blank space.
+						}
+					}
+				}
+				// If we have a block open close it.
+				if(block != null) {
+					out("  parsed: " + block.getName());
+					put(block.getName(), block);
+				}
+				line = null;
+				block = null;
+				buffered_reader.close();
+				buffered_reader = null;
+				file_reader.close();
+				file_reader = null;
+			}
+			catch (Exception error) {
+				error.printStackTrace();
+  			System.err.println("An error has occured. View output.txt for more information.");
+				exit();
+			}
+		}
+		/** Retrieve the block indicated by the given name.
+		* @param name The name of the block as a <strong>String</strong>.
+		* @return The <strong>HTMLBlock</strong> asked for or <i>null</i> if no such block.
+		*/
+		public HTMLBlock getHTMLBlock(String name) {
+			HTMLBlock block = (HTMLBlock) get(name);
+			// Don't return the original, but a copy.
+			if(block != null) {
+				block = block.spawn();
+			}
+			return block;
+		}
+	}
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/util/HTMLStringTokenizer.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/HTMLStringTokenizer.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/HTMLStringTokenizer.java	(revision 13666)
@@ -0,0 +1,164 @@
+/**
+ *#########################################################################
+ *
+ * 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:        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>
+ * @author John Thompson, Greenstone Digital Libraries
+ * @version 2.1
+ */
+import java.util.Stack;
+import org.greenstone.gatherer.util.Utility;
+/** 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;
+	 }
+	 /** Repeats the result of the last <i>nextToken()</i>.
+	  * @return A <strong>String</strong> representing the token.
+	  */
+	 public String sameToken() {
+		  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++;
+		  }
+	 }
+
+	 static public void main(String args[]) {
+		  String init = "<HTML>Where material to be imported is found. Defaults to <i>GSDLHOME/collection/col_name/gimport</i></HTML>";
+		  ///ystem.err.println("Before: " + init);
+		  String result = Utility.formatHTMLWidth(init, 40);
+		  ///ystem.err.println("After: " + result);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/util/HashMap3D.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/HashMap3D.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/HashMap3D.java	(revision 13666)
@@ -0,0 +1,178 @@
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* 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:      20/08/02
+ * Revised:      
+ * @author John Thompson, 9826509
+ * @version 2.3
+ **************************************************************************************/
+import java.util.HashMap;
+import java.util.Iterator;
+import org.greenstone.gatherer.msm.Metadata;
+/** Provides a HashMap implementation that indexes by two keys. Perfect for the storage of metadata references based on their metadata element and assigned value. */
+public class HashMap3D
+	 extends HashMap {
+
+	 private int capacity = 4;
+
+	 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, as we should already have a good idea based on the number of Metadata Elements.
+	  * @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() {
+		  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;
+	 }
+	 /** -SPECIAL - Attempts to retrieve a previous instance of metadata with the same parameters as the given one. If such a metadata is found, it is returned, otherwise the given metadata is added then returned as being the first unique instance.
+	  * @param metadata The <strong>Metadata</strong> for whom we are trying to find the first unique instance.
+	  * @return The first unique instance of the target <strong>Metadata</strong> which may in fact be the same metadata given as a paramater.
+	  */
+	 public Metadata locate(Metadata metadata) {
+		  Metadata result = null;
+		  if(metadata != null) {
+				// Locate the appropriate value->metadata hashmap.
+				String element_name = metadata.getElement().toString();
+				HashMap inner_mapping = (HashMap) get(element_name);
+				if(inner_mapping == null) {
+					 inner_mapping = new HashMap(4); // Small initial capacity.
+					 put(element_name, inner_mapping);
+				}
+				element_name = null;
+				// Locate the appropriate metadata
+				String value_name = metadata.getValueNode().getFullPath();
+				result = (Metadata) inner_mapping.get(value_name);
+				if(result == null) {
+					 result = metadata;
+					 inner_mapping.put(value_name, metadata);
+				}
+				value_name = null;
+				inner_mapping = null;
+		  }
+		  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);
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/util/MED.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/MED.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/MED.java	(revision 13666)
@@ -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.
+ *
+ * <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.
+ *########################################################################
+ */
+
+ 
+
+
+
+
+/* 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:      28/08/02
+ * Revised:      
+ * @author John Thompson, 9826509
+ * @author Michael Gilleland, Merriam Park Software
+ * @version 2.3
+ **************************************************************************************/
+/** Determines the MED between two metadata element names.<BR>
+ * Adapted from code by Michael Gilleland, Merriam Park Software, as detailed in a short essay called "Levenshtein Distance, in Three Flavors" available at http://www.merriampark.com/ld.htm.
+ */
+public class MED {
+	 //****************************
+	 // Get minimum of three values
+	 //****************************
+	 static private int Minimum (int a, int b, int c) {
+		  int mi = a;
+		  if (b < mi) {
+				mi = b;
+		  }
+		  if (c < mi) {
+				mi = c;
+		  }
+		  return mi;
+	 }
+	 //*****************************
+	 // Compute Levenshtein distance
+	 //*****************************
+	 static public int LD (String s, String t) {
+		  int d[][]; // matrix
+		  int n; // length of s
+		  int m; // length of t
+		  int i; // iterates through s
+		  int j; // iterates through t
+		  char s_i; // ith character of s
+		  char t_j; // jth character of t
+		  int cost; // cost
+		  // Step 1
+		  // Set n to be the length of s.
+		  // Set m to be the length of t.
+		  // If n = 0, return m and exit.
+		  // If m = 0, return n and exit.
+		  // Construct a matrix containing 0..m rows and 0..n columns.
+		  n = s.length ();
+		  m = t.length ();
+		  if (n == 0) {
+				return m;
+		  }
+		  if (m == 0) {
+				return n;
+		  }
+		  d = new int[n+1][m+1];
+		  // Step 2
+		  // Initialize the first row to 0..n.
+		  // Initialize the first column to 0..m.
+		  for (i = 0; i <= n; i++) {
+				d[i][0] = i;
+		  }
+		  for (j = 0; j <= m; j++) {
+				d[0][j] = j;
+		  }
+		  // Step 3
+		  // Examine each character of s (i from 1 to n).
+		  for (i = 1; i <= n; i++) {
+				s_i = s.charAt (i - 1);
+				// Step 4
+				// Examine each character of t (j from 1 to m).
+				for (j = 1; j <= m; j++) {
+					 t_j = t.charAt (j - 1);
+					 // Step 5
+					 // If s[i] equals t[j], the cost is 0.
+					 // If s[i] doesn't equal t[j], the cost is 1.
+					 if (s_i == t_j) {
+						  cost = 0;
+					 }
+					 else {
+						  cost = 1;
+					 }
+					 // Step 6
+					 // Set cell d[i,j] of the matrix equal to the minimum of:
+					 // a. The cell immediately above plus 1: d[i-1,j] + 1.
+					 // b. The cell immediately to the left plus 1: d[i,j-1] + 1.
+					 // c. The cell diagonally above and to the left plus the cost: d[i-1,j-1] + cost.
+					 d[i][j] = Minimum (d[i-1][j]+1, d[i][j-1]+1, d[i-1][j-1] + cost);
+				}
+		  }
+		  // Step 7
+		  // After the iteration steps (3, 4, 5, 6) are complete, the distance is found in cell d[n,m].
+		  int result = d[n][m];
+		  d = null;
+		  return result;
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/util/MetadataXML.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/MetadataXML.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/MetadataXML.java	(revision 13666)
@@ -0,0 +1,185 @@
+package org.greenstone.gatherer.util;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.Point;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.Vector;
+import javax.swing.tree.TreePath;
+import net.n3.nanoxml.IXMLElement;
+import net.n3.nanoxml.IXMLParser;
+import net.n3.nanoxml.IXMLReader;
+import net.n3.nanoxml.StdXMLReader;
+import net.n3.nanoxml.XMLParserFactory;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.SaveProgressDialog;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.Metadata;
+import org.greenstone.gatherer.msm.MetadataSetManager;
+import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.valuetree.GValueModel;
+import org.greenstone.gatherer.valuetree.GValueNode;
+import org.greenstone.gatherer.valuetree.GValueTree;
+import org.w3c.dom.Element;
+
+public class MetadataXML {
+	 //private boolean can_wait = true;
+	 private Gatherer gatherer = null;
+	 private Hashtable known_indexes = null;
+	 //private int spare_processes = 25;
+	 //private MetadataXML mummy = null;
+	 private SaveProgressDialog spd = null;
+	 //private Vector complete = null;
+	 //private Vector processes = null;
+
+	 static public String METADATA_FILE = "metadata.xml";
+
+	 static public IXMLElement read(String filename) {
+		  IXMLElement xml = null;
+		  IXMLParser parser = null;
+		  IXMLReader reader = null;
+		  try {
+				parser = XMLParserFactory.createDefaultXMLParser();
+				File in_file = new File(filename);
+				FileReader in_reader = new FileReader(in_file);
+				BufferedReader in = new BufferedReader(in_reader, Utility.BUFFER_SIZE);
+				String content = "";
+				String next_line = null;
+				while((next_line = in.readLine()) != null) {
+					 // Throw away the document type, as I don't want to deal
+					 // with dtd's. If someone has tampered with these files to
+					 // the point that this parser can't read them then too bad.
+					 if(!next_line.startsWith("<!DOCTYPE")) {
+						  content = content + next_line;
+					 }
+				}
+				in.close();
+				reader = StdXMLReader.stringReader(content);
+				parser.setReader(reader);
+			   xml = (IXMLElement) parser.parse();
+		  }
+		  catch (Exception e) {
+		  }
+		  return xml;
+	 }
+
+	 public static void write(Gatherer gatherer, String etc_dir) {
+		  if(gatherer != null && gatherer.c_man != null && gatherer.c_man.getCollection() != null && gatherer.c_man.getCollection().msm != null) {
+				Vector elements = gatherer.c_man.getCollection().msm.getElements(true);
+				for(int i = 0; i < elements.size(); i++) {
+					 ElementWrapper element = (ElementWrapper)elements.get(i);
+					 ///ystem.err.print("Checking " + element + " for HFile: ");
+					 GValueModel model = gatherer.c_man.getCollection().msm.getValueTree(element);
+					 if(model != null && (element.getNamespace().equals(MetadataSetManager.HIDDEN) || model.isHierarchy())) {
+						  ///ystem.err.println("Found. Writing file.");
+						  write(model, gatherer.c_man.getCollection().msm, etc_dir);
+					 }
+					 else {
+						  ///ystem.err.println("No file found.");
+					 }
+				}
+		  }
+	 }
+
+	 private String getHIndex(Gatherer gatherer, GValueModel model, String value) {
+		  String index = null;
+		  index = (String) known_indexes.get(value);
+		  if(index == null) {
+				index = model.getHIndex(value);
+				///ystem.err.println("Adding to known indexes: " + value + " -> " + index);
+				known_indexes.put(value, index);
+		  }
+		  return index;
+	 }
+
+	 static private String safe(String unsafe) {
+		  String safe_str = "";
+		  for(int i = 0; i < unsafe.length(); i++) {
+				char c = unsafe.charAt(i);
+				if(c != ' ') {
+					 safe_str = safe_str + c;
+				}
+		  }
+		  return safe_str;
+	 }
+
+	 static private void write(Writer w, String text)
+		  throws Exception {
+		  text = text + "\r\n";
+		  char buffer[] = text.toCharArray();
+		  w.write(buffer, 0, buffer.length);
+	 }
+
+	 static public void write(GValueModel model, MetadataSetManager msm, String etc_dir) {
+		  try {
+				File out_file = new File(etc_dir + model.toString() + ".txt");
+				FileOutputStream fos = new FileOutputStream(out_file);
+				OutputStreamWriter osw = new OutputStreamWriter(fos);
+				BufferedWriter bw = new BufferedWriter(osw, Utility.BUFFER_SIZE);
+				Vector all_values = model.traverseTree();
+				for(int i = 0; i < all_values.size(); i++) {
+					 GValueNode node = (GValueNode)all_values.get(i);
+					 TreePath path = new TreePath(node.getPath());
+					 String value = GValueTree.formatPath(null, path, true);
+					 String index = model.getHIndex(value);
+					 String alias = node.getAlias(index);
+					 if(value.indexOf("\\") != -1) {
+						  value = value.substring(value.lastIndexOf("\\") + 1);
+					 }
+					 write(bw, index + "\t\"" + alias + "\"\t\"" + Utility.stripNL(value) + "\"");
+				}
+				// Very important we do this, or else buffer may not have 
+				// flushed.
+				bw.flush();
+				bw.close();
+		  }
+		  catch(Exception error) {
+				error.printStackTrace();
+		  }
+	 }
+
+	 static final private long showTime(String message, long time) {
+		  if(time == -1) {
+				///ystem.err.println(message + System.currentTimeMillis());
+		  }
+		  else {
+				///ystem.err.println(message + (System.currentTimeMillis() - time));
+		  }
+		  return System.currentTimeMillis();
+	 }
+}
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/util/MutableComboBoxEntry.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/MutableComboBoxEntry.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/MutableComboBoxEntry.java	(revision 13666)
@@ -0,0 +1,5 @@
+package org.greenstone.gatherer.util;
+
+public interface MutableComboBoxEntry {
+	 public void setText(String text);
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/util/SwingWorker.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/SwingWorker.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/SwingWorker.java	(revision 13666)
@@ -0,0 +1,132 @@
+package org.greenstone.gatherer.util;
+
+import javax.swing.SwingUtilities;
+
+/**
+ * This is the 3rd version of SwingWorker (also known as
+ * SwingWorker 3), an abstract class that you subclass to
+ * perform GUI-related work in a dedicated thread.  For
+ * instructions on using this class, see:
+ * 
+ * http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
+ *
+ * Note that the API changed slightly in the 3rd version:
+ * You must now invoke start() on the SwingWorker after
+ * creating it.
+ */
+public abstract class SwingWorker {
+    private Object value;  // see getValue(), setValue()
+    private Thread thread;
+
+    /** 
+     * Class to maintain reference to current worker thread
+     * under separate synchronization control.
+     */
+    private static class ThreadVar {
+        private Thread thread;
+        ThreadVar(Thread t) { thread = t; }
+        synchronized Thread get() { return thread; }
+        synchronized void clear() { thread = null; }
+    }
+
+    private ThreadVar threadVar;
+
+    /** 
+     * Get the value produced by the worker thread, or null if it 
+     * hasn't been constructed yet.
+     */
+    protected synchronized Object getValue() { 
+        return value; 
+    }
+
+    /** 
+     * Set the value produced by worker thread 
+     */
+    private synchronized void setValue(Object x) { 
+        value = x; 
+    }
+
+    /** 
+     * Compute the value to be returned by the <code>get</code> method. 
+     */
+    public abstract Object construct();
+
+    /**
+     * Called on the event dispatching thread (not on the worker thread)
+     * after the <code>construct</code> method has returned.
+     */
+    public void finished() {
+    }
+
+    /**
+     * A new method that interrupts the worker thread.  Call this method
+     * to force the worker to stop what it's doing.
+     */
+    public void interrupt() {
+        Thread t = threadVar.get();
+        if (t != null) {
+            t.interrupt();
+        }
+        threadVar.clear();
+    }
+
+    /**
+     * Return the value created by the <code>construct</code> method.  
+     * Returns null if either the constructing thread or the current
+     * thread was interrupted before a value was produced.
+     * 
+     * @return the value created by the <code>construct</code> method
+     */
+    public Object get() {
+        while (true) {  
+            Thread t = threadVar.get();
+            if (t == null) {
+                return getValue();
+            }
+            try {
+                t.join();
+            }
+            catch (InterruptedException e) {
+                Thread.currentThread().interrupt(); // propagate
+                return null;
+            }
+        }
+    }
+
+
+    /**
+     * Start a thread that will call the <code>construct</code> method
+     * and then exit.
+     */
+    public SwingWorker() {
+        final Runnable doFinished = new Runnable() {
+           public void run() { finished(); }
+        };
+
+        Runnable doConstruct = new Runnable() { 
+            public void run() {
+                try {
+                    setValue(construct());
+                }
+                finally {
+                    threadVar.clear();
+                }
+
+                SwingUtilities.invokeLater(doFinished);
+            }
+        };
+
+        Thread t = new Thread(doConstruct);
+        threadVar = new ThreadVar(t);
+    }
+
+    /**
+     * Start the worker thread.
+     */
+    public void start() {
+        Thread t = threadVar.get();
+        if (t != null) {
+            t.start();
+        }
+    }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/util/SynchronizedTreeModelTools.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/SynchronizedTreeModelTools.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/SynchronizedTreeModelTools.java	(revision 13666)
@@ -0,0 +1,137 @@
+package org.greenstone.gatherer.util;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.lang.Runnable;
+import java.lang.Thread;
+import javax.swing.SwingUtilities;
+import javax.swing.tree.*;
+/** 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(final DefaultTreeModel model, final MutableTreeNode parent, final MutableTreeNode target_node) {
+		  final Runnable doInsertNodeInto = new Runnable() {
+					 public void run() {
+						  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);
+					 }
+				};
+		  try {
+				//SwingUtilities.invokeLater(doInsertNodeInto);
+				SwingUtilities.invokeAndWait(doInsertNodeInto);
+		  }
+		  catch (Exception e) {
+				e.printStackTrace();
+		  }
+		  // If (and only 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(doInsertNodeInto);
+				}
+		  }
+		  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 e) {
+				e.printStackTrace();
+				///ystem.err.println(e);
+		  }
+		  // 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);
+				}
+		  }
+	 }
+	 /** Adds a replaceNode 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 change.
+	  * @param old_node The <strong>GTreeNode</strong> to replace.
+	  * @param new_node The <strong>GTreeNode</strong> to replace it with.
+	  */
+	 static final public void replaceNode(final DefaultTreeModel model, final MutableTreeNode old_node, final MutableTreeNode new_node) {
+		  final Runnable doReplaceNode = new Runnable() {
+					 public void run() {
+						  MutableTreeNode parent = (MutableTreeNode) old_node.getParent();
+						  if(parent != null) {
+								int index = parent.getIndex(old_node);
+								model.removeNodeFromParent(old_node);
+								model.insertNodeInto(new_node, parent, index);
+						  }
+						  parent = null;
+					 }
+				};
+		  try {
+				//SwingUtilities.invokeLater(doReplaceNode);
+				SwingUtilities.invokeAndWait(doReplaceNode);
+		  }
+		  catch (Exception e) {
+				e.printStackTrace();
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/util/TreeSynchronizer.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/TreeSynchronizer.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/TreeSynchronizer.java	(revision 13666)
@@ -0,0 +1,137 @@
+package org.greenstone.gatherer.util;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.util.Vector;
+import javax.swing.JTree;
+import javax.swing.event.TreeExpansionEvent;
+import javax.swing.event.TreeExpansionListener;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.TreePath;
+import org.greenstone.gatherer.gui.tree.DragTree;
+/** My latest diabolical class synchronizes the expansion state of two or more JTrees. Muh-hahahaha. Note that these tree should be based on the same model. 
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.1
+ */
+final public class TreeSynchronizer 
+	 extends Vector 
+	 implements TreeExpansionListener, TreeSelectionListener {
+	 /** <i>true</i> if we should temporarily ignore further events, most likely because we know our actions are causing them. */ 
+	 private boolean ignore;
+	 /** A list of tree selection listeners. */
+	 private Vector selection_listeners = new Vector();
+	 /** Add a new tree to the synchronization list of trees to be synchronized.
+	  * @param tree The lastest victim, a <strong>JTree</strong>.
+	  */
+	 public void add(JTree tree) {
+		  super.add(tree);
+		  tree.addTreeExpansionListener(this);
+		  //tree.addTreeSelectionListener(this);
+	 }
+
+	 /** We allow the Gatherer to add tree listeners to this class, as it persists between collection changes transparently. Thus there is no need to reattach listeners everytime the collection changes. */
+	 public void addTreeSelectionListener(TreeSelectionListener listener) {
+		  if(!selection_listeners.contains(listener)) {
+				selection_listeners.add(listener);
+		  }
+	 }
+
+	 /** Called whenever an item in the tree has been collapsed.
+	  * @param event A <strong>TreeExpansionEvent</strong> containing information about the event.
+	  */
+	 public void treeCollapsed(TreeExpansionEvent event) {
+		  if(!ignore) {
+				ignore = true;
+				// Collapse that path in all registered trees.
+				JTree tree = (JTree)event.getSource();
+				TreePath path = event.getPath();
+				for(int i = size(); i != 0; i--) {
+					 JTree sibling = (JTree) get(i - 1);
+					 if(!sibling.equals(tree)) {
+						  sibling.collapsePath(path);
+					 }
+				}
+				ignore = false;
+		  }
+	 }
+	 /** Called whenever an item in the tree has been expanded.
+	  * @param event A <strong>TreeExpansionEvent</strong> containing information about the event.
+	  */
+	 public void treeExpanded(TreeExpansionEvent event) {
+		  if(!ignore) {
+				ignore = true;
+				// Expand that path in all registered trees.
+				JTree tree = (JTree)event.getSource();
+				TreePath path = event.getPath();
+				for(int i = size(); i != 0; i--) {
+					 JTree sibling = (JTree) get(i - 1);
+					 if(!sibling.equals(tree)) {
+						  sibling.expandPath(path);
+					 }
+				}
+				ignore = false;
+		  }
+	 }
+	 /** Called whenever the one of the trees selection changes.
+	  * @param event A <strong>TreeSelectionEvent</strong> containing information about the event.
+	  */
+	 public void valueChanged(TreeSelectionEvent event) {
+		  if(!ignore) {
+				ignore = true;
+				// Recover the tree that is the source.
+				JTree tree = (JTree) event.getSource();
+				// Brute Force approach.
+				// Extract the currently selected paths.
+				TreePath paths[] = tree.getSelectionPaths();
+				// Then for every registered tree, that isn't this one, ensure those paths are selected.
+				for(int i = size(); paths != null && i != 0; i--) {
+					 JTree sibling = (JTree) get(i - 1);
+					 if(!sibling.equals(tree)) {
+						  // One last thing to do. If this is actually a DragTree we are dealing with we have to tell it to set the selection values immediately, not wait for the clear until it is sure it is no the pre-cursor to a drag.
+						  if(sibling instanceof DragTree) {
+								DragTree gtree = (DragTree)sibling;
+								gtree.setImmediate(true);
+								gtree.setSelectionPaths(paths);
+								// I'm going to ensure that the last selected path is visible.
+								gtree.scrollPathToVisible(paths[paths.length - 1]);
+								gtree.setImmediate(false);
+						  }
+						  else {
+								sibling.setSelectionPaths(paths);
+								sibling.scrollPathToVisible(paths[paths.length - 1]);
+						  }
+					 }
+				}
+				// Pass on message to all listeners.
+				for(int i = 0; i < selection_listeners.size(); i++) {
+					 ((TreeSelectionListener) selection_listeners.get(i)).valueChanged(event);
+				}
+				ignore = false;
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/util/Utility.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/Utility.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/Utility.java	(revision 13666)
@@ -0,0 +1,886 @@
+package org.greenstone.gatherer.util;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.tree.*;
+import org.apache.xerces.parsers.*;
+import org.apache.xml.serialize.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.util.HTMLStringTokenizer;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+/** 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 {
+	 /** The default size of a gatherer progress bar, in either the download view or the build view. */
+	 static final public Dimension PROGRESS_BAR_SIZE = new Dimension(580,65);
+	 /** The number of kilobytes to use as a io buffer. */
+	 static final public int FACTOR = 1;
+	 /** The size of the io buffer, calculated as FACTOR * 1024. */
+	 static final public int BUFFER_SIZE = FACTOR * 1024;
+	 /** Definition of an important directory name, in this case the archive directory for the collection. */
+	 static final public String ARCHIVE_DIR = "archives" + File.separator;
+	 /** Definition of an important directory name, in this case the base dir, or the working directory of the Gatherer. */
+	 static final public String BASE_DIR  = System.getProperty("user.dir") + File.separator;
+	 /** Definition of an important directory name, in this case the building directory for the collection. */
+	 static final public String BUILD_DIR = "building" + File.separator;
+	 /** Definition of an important directory name, in this case the public web cache for the Gatherer. */
+	 static final public String CACHE_DIR = BASE_DIR + "cache" + File.separator;
+	 static final public String CFG_COLLECTIONMETA_COLLECTIONNAME = "collectionmeta collectionname";
+	 static final public String CFG_COLLECTIONMETA_COLLECTIONEXTRA = "collectionmeta collectionextra";
+	 static final public String CFG_CLASSIFY = "classify";
+	 static final public String CFG_CLASSIFY_HFILE = "-hfile";
+	 static final public String CFG_CLASSIFY_METADATA = "-metadata";
+	 static final public String CFG_CREATOR = "creator";
+	 static final public String CFG_MAINTAINER = "maintainer";
+	 /** Definition of an important directory name, in this case the parent directory of all the collections in the gsdl. */
+	 static final public String COL_DIR = "collect" + File.separator;
+	 static final public String COLLECTION_DLS = "Development Library Subset";
+	 /** Definition of an important directory name, in this case the file the collection configuration is expect to be in. */
+	 static final public String CONFIG_DIR = "etc" + File.separator + "collect.cfg";
+	 /** The default file name for the urls missing any file. */
+	 static final public String DEFAULT_FILE = "index.html";
+	 static final public String DEFAULT_NAMESPACE = "gsp";
+	 /** The default protocol header for those urls missing any protocol. */
+	 static final public String DEFAULT_PROTOCOL = "http://";
+	 /** The default dictionary to load. */
+	 static final public String DICTIONARY = "dictionary";
+	 static final public String DLS_MDS = "dls.mds";
+	 static final public String ENGLISH_VALUE = "en";
+	 /** Definition of an important directory name, in this case the etc (or extra information) directory for the collection. */
+	 static final public String ETC_DIR = "etc" + File.separator;
+	 static final public String EXTRACTED_METADATA_NAMESPACE = "ex";
+	 /** The location of the default greenstone metadata file. */
+	 static final public String GREENSTONEDIRECTORYMETADATA_TEMPLATE = "xml/metadata.xml";
+	 /** Definition of an important directory name, in this case the private web cache directory for the collection. */
+	 static final public String GCACHE_DIR = "gcache" + File.separator;
+/** Definition of an important directory name, in this case the location of help documentation. */
+	 static final public String HELP_DIR = BASE_DIR + "help" + File.separator;
+	 /** Definition of an important directory name, in this case the import directory for the collection. */
+	 static final public String IMPORT_DIR = "gimport" + File.separator;
+	 /** Definition of an important directory name, in this case the index directory for the collection. */
+	 static final public String INDEX_DIR = "index" + File.separator;
+	 static final public String LANGUAGE_ATTRIBUTE = "language";
+	 /** Definition of an important directory name, in this case the location of the expected collection metadata sets.. */
+	 static final public String META_DIR = "metadata" + File.separator; // Col. Copy
+	 /** Definition of an important directory name, in this case the location of the default metadata sets. */
+	 static final public String METADATA_DIR = BASE_DIR + "metadata" + File.separator;
+	 static final public String METADATA_EXTRACTED = "extracted.mds";
+	 /** The location the gatherer expects to find metadata set information. */
+	 static final public String METADATA_SET_TEMPLATE = "xml" + File.separator + "template.mds";
+	 static final public String METADATA_VALUE_TEMPLATE = "xml" + File.separator + "template.mdv";
+	 static final public String METADATA_XML = "metadata.xml";
+	 static final public String NAME_ELEMENT = "Name";
+	 /** Definition of an important directory name, in this case the import directory for the collection. */
+	 static final public String OLD_IMPORT_DIR = "import" + File.separator;
+	 /** 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";
+	 /** The name of the Gatherer. */
+	 static final public String PROGRAM_NAME = "The Librarian Interface";
+	 /** The current version of the Gatherer. */
+	 static final public String PROGRAM_VERSION = "ver 2.0";
+	 /** Definition of an important directory name, in this case the location of the recycled files location. */
+	 static final public String RECYCLE = BASE_DIR + "recycle" + File.separator;
+	 /** Definition of an important directory name, in this case the location of image and other resources. */
+	 static final public String RES_DIR = BASE_DIR + "resource" + File.separator;
+	 /** Definition of an important directory name, in this case the location of opening (or welcome) screen html. */
+	 static final public String WELCOME_DIR = BASE_DIR + "welcome" + File.separator;
+	 // These are out of alphabetic order to avoid forward reference error.
+	 /** The default icon to produce a 'help-icon' sized blank space before a menu entry. */
+	 static final public ImageIcon BLANK_ICON = new ImageIcon(ClassLoader.getSystemResource("images/blank.gif"));
+	 /** The default error icon image. */
+	 static final public ImageIcon ERROR_ICON = new ImageIcon(ClassLoader.getSystemResource("images/error.gif"));
+	 static final public ImageIcon HELP_ICON = new ImageIcon(ClassLoader.getSystemResource("images/help.gif"));
+	 /** The image for a toggle button whose state is 'on'. */
+	 static final public ImageIcon ON_ICON = new ImageIcon(ClassLoader.getSystemResource("images/check.gif"));
+	 /** The image for a toggle button whose state is 'off'. */
+	 static final public ImageIcon OFF_ICON = new ImageIcon(ClassLoader.getSystemResource("images/cross.gif"));
+	 /** Method to turn a file from with the system file tree into a tree path for insertion into a tree.
+	  * @param file The <strong>File</strong> whose tree path you are attempting to discover.
+	  * @param in_col A <i>boolean</i> indicating whether we are looking for a file within a collection of not. If <i>true</i> then the tree paths head in the collection name, and no element in the path refers to the import directory. Otherwise the paths head will be one of the system roots and all traversed file locations will exist in the path.
+	  * @return A <strong>TreePath</strong> which traverses the file system tree to the specified file.
+	  */ 
+	 public static TreePath createTreePath(File file, boolean in_col) {
+		  TreePath path = null;
+		  // Get the absolute path of the file.
+		  String abs_path = file.getAbsolutePath();
+		  while(file != null) {
+				// If we are looking for a node within our collection, we expect
+				// its path from root to be <col_name>/... without any higher
+				// details and without gimport. So if we encounter a gimport we
+				// skip to its parent, add that, then return.
+				if(in_col && file.getName().equals("gimport")) {
+					 file = file.getParentFile();
+					 if(path == null) {
+						  path = new TreePath(file.getName());
+					 }
+					 else {
+						  path = path.pathByAddingChild(file.getName());
+					 }
+					 file = null;
+				}
+				else {
+					 if(path == null) {
+						  path = new TreePath(file.getName());
+					 }
+					 else {
+						  path = path.pathByAddingChild(file.getName());
+					 }
+					 file = file.getParentFile();
+				}
+		  }
+		  // Unfortunately we've created the path in reverse order so we have to
+		  // reverse it.
+		  Object temp[] = new Object[path.getPathCount()];
+		  for(int i = 0; i < temp.length; i++) {
+				temp[(temp.length - 1) - i] = path.getPathComponent(i);
+		  }
+		  return new TreePath(temp);
+	 }
+	 /** Decodes a string of text so its safe to use in a Greenstone configuration file. Esentially replaces "\n" with a newline.
+	  * @param raw The <strong>String</strong> before decoding, read from the configuration file..
+	  * @return A <strong>String</strong> ready to be placed in a component.
+	  */
+	 static public String decodeGreenstone(String raw) {
+		  raw = raw.replaceAll("&apos;", "\'");
+		  raw = raw.replaceAll("&gt;", ">");
+		  raw = raw.replaceAll("&lt;", "<");
+		  raw = raw.replaceAll("&quot;", "\"");
+		  raw = raw.replaceAll("&#39;", "\'");
+		  raw = raw.replaceAll("\\\\n", "\n");
+		  return raw;
+	 }
+	 /** Takes a rfc2616 'safe' String and translates it back into its 'unsafe' form. Basically the native c wget decode_string() function, but without pointer stuff. If searches through the String looking for the pattern %xy where x and y are hexidecimal digits and where xy maps to a character.<BR> If x or y are not hexidecimal or % is followed by a \0 then the pattern is left as is.
+	  * @param encoded The url-safe <strong>String</strong> to be decoded.
+	  * @return The decoded <strong>String</strong>.
+	  */
+	 public static String decodeString(String encoded) {
+		  String decoded = "";
+		  for(int i = 0; i < encoded.length(); i++) {
+				if(encoded.charAt(i) == '%') {
+					 if(hexidecimal(encoded.charAt(i+1)) != -1
+						 && hexidecimal(encoded.charAt(i+2)) != -1) {
+						  char unsafe_chr = (char)
+								((hexidecimal(encoded.charAt(i+1)) * 16) +
+								 hexidecimal(encoded.charAt(i+2)));
+						  decoded = decoded + unsafe_chr;
+						  i = i + 2;
+					 }
+				}
+				else {
+					 decoded = decoded + encoded.charAt(i);
+				}
+		  }
+		  return decoded;
+	 }
+	 /** It turns out that in Java you have to make sure a directory is empty before you delete it (much like unix I suppose), and so just like unix I'll have to set up a recursive delete function.
+	  * @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) {
+		  boolean result = true;
+		  // If files a directory, delete files children.
+		  if(file.isDirectory()) {
+				File files[] = file.listFiles();
+				for(int i = 0; files != null && result && i < files.length; i++) {
+					 result = delete(files[i]);
+				}
+		  }
+		  if(result) {
+				// Delete file.
+				return file.delete();
+		  }
+		  return result;
+	 }
+	 /** Generate a depth first enumeration of a tree. */
+	 static public EnumeratedVector depthFirstEnumeration(TreeNode node, EnumeratedVector result) {
+		  result.add(node);
+		  for(int i = 0; i < node.getChildCount(); i++) {
+				depthFirstEnumeration(node.getChildAt(i), result);
+		  }
+		  return result;
+	 }
+	 /** Encodes a string of text so its safe to use in a Greenstone configuration file. Esentially replaces newlines with their escaped form.
+	  * @param raw The <strong>String</strong> before encoding.
+	  * @return A <strong>String</strong> which is safe to write to the configuration file.
+	  */
+	 static public String encodeGreenstone(String raw) {
+		  raw = raw.replaceAll("<", "&lt;");
+		  raw = raw.replaceAll(">", "&gt;");
+		  return raw.replaceAll("\n", "\\\\n");
+	 }
+
+	 /** Using this method we can request that a certain document be written, as valid XML, to a certain output stream. This makes use of the Xerces Serialization suite, which should in no way be confused with the usual method of Serialization used by Java. */ 
+	 static public boolean export(Document document, String filename) {
+		  return export(document, new File(filename));
+	 }
+
+	 static public boolean export(Document document, File file) {
+		  try {
+				OutputStream os = new FileOutputStream(file);
+				// Create an output format for our document.
+				OutputFormat f = new OutputFormat(document);
+				f.setIndenting(true);
+				f.setLineWidth(256);
+				f.setPreserveSpace(false);
+				// Create the necessary writer stream for serialization.
+				OutputStreamWriter osw = new OutputStreamWriter(os);
+				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();
+				return true;
+		  }
+		  // A file not found exception is most likely thrown because the directory the metadata.xml file is attempting to be written to no longer has any files in it. I'll add a test in GDMDocument to test for this, but if it still happens ignore it (a non-existant directory can't really have metadata added to it any way. 
+		  catch (FileNotFoundException fnf_exception) {
+				if(!file.getName().endsWith(METADATA_XML)) {
+					 fnf_exception.printStackTrace();
+					 return false;
+				}
+				return true;
+		  }
+		  catch (IOException ioe) {
+				ioe.printStackTrace();
+				return false;
+		  }
+	 }
+
+	 /** Given a starting directory, searches for the collect.cfg file and returns it if found.
+	  * @return The collect.cfg File or null if not found.
+	  */
+	 static final public File findConfigFile(File start) {
+		  if(start == null) {
+				return null;
+		  }
+		  // See if the collect.cfg files here.
+		  File collect_cfg = new File(start, "collect.cfg");
+		  if(collect_cfg.exists()) {
+				return collect_cfg;
+		  }
+		  // Search for the existance of collect.cfg in a etc directory.
+		  File etc_dir = new File(start, "etc" + File.separator + "collect.cfg");
+		  if(etc_dir.exists()) {
+				return etc_dir;
+		  }
+		  // Otherwise search this directories parent if its not null.
+		  return findConfigFile(start.getParentFile());
+	 }
+
+	 /** 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 {
+				number = (float) length;
+				suffix = 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) {
+		  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) {
+								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) {
+								line = space(line, width, current_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;
+	 }
+	 /** 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.
+	  */
+	 static public String formatPath(String key, String raw, int width) {
+		  JLabel label = new JLabel(Gatherer.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(Gatherer.dictionary.get(key, raw));
+		  }
+		  if(raw.indexOf(File.separator) == -1 && raw.startsWith("...")) {
+				raw = raw.substring(3);
+		  } 
+		  return raw;
+	 }
+
+	 /** Method which constructs the archive 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 archive directory, also as a <strong>String</strong>.
+	  */
+	 static public String getArchiveDir(String gsdl_path, String col_name) {
+		  return gsdl_path + File.separator + COL_DIR + col_name + File.separator + ARCHIVE_DIR;
+	 }
+	 /** Method which constructs the build 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 build directory, also as a <strong>String</strong>.
+	  */
+	 static public String getBuildDir(String col_dir) {
+		  if(col_dir == null) {
+				return BASE_DIR + BUILD_DIR;
+		  }
+		  return col_dir + BUILD_DIR;
+	 }
+	 /** Builds the private cache dir by appending col_dir and 'cache'.
+	  * @param col_dir A String representing the directory path of the current collection.
+	  * @return A String representing the path to the private file cache within the current collection.
+	  */
+	 public static String getCacheDir(String col_dir) {
+		  return col_dir + GCACHE_DIR;
+	 }
+	 /** Method which constructs the collection directory for Greenstone.
+	  * @param gsdl_path The location of the gsdl installation directory as a <strong>String</strong>.
+	  * @return The location of the collection directory, also as a <strong>String</strong>.
+	  */
+	 public static String getCollectionDir(String gsdl_path) {
+		  return gsdl_path + COL_DIR;
+	 }
+	 /** Method which constructs the configuration file 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 configuration file, also as a <strong>String</strong>.
+	  */
+	 static public String getConfigDir(String col_dir) {
+		  return col_dir + CONFIG_DIR;
+	 }
+
+	 static public String getDateString() {
+		  Calendar current = Calendar.getInstance();
+		  String day_name = null;
+		  switch(current.get(Calendar.DAY_OF_WEEK)) {
+		  case Calendar.MONDAY: day_name = "Mon"; break;
+		  case Calendar.TUESDAY: day_name = "Tue"; break;
+		  case Calendar.WEDNESDAY: day_name = "Wed"; break;
+		  case Calendar.THURSDAY: day_name = "Thu"; break;
+		  case Calendar.FRIDAY: day_name = "Fri"; break;
+		  case Calendar.SATURDAY: day_name = "Sat"; break;
+		  case Calendar.SUNDAY: day_name = "Sun"; break;
+		  default: day_name = "";
+		  }
+		  String month_name = null;
+		  switch(current.get(Calendar.MONTH)) {
+		  case Calendar.JANUARY: month_name = "Jan"; break;
+		  case Calendar.FEBRUARY: month_name = "Feb"; break;
+		  case Calendar.MARCH: month_name = "Mar"; break;
+		  case Calendar.APRIL: month_name = "Apr"; break;
+		  case Calendar.MAY: month_name = "May"; break;
+		  case Calendar.JUNE: month_name = "Jun"; break;
+		  case Calendar.JULY: month_name = "Jul"; break;
+		  case Calendar.AUGUST: month_name = "Aug"; break;
+		  case Calendar.SEPTEMBER: month_name = "Sep"; break;
+		  case Calendar.OCTOBER: month_name = "Oct"; break;
+		  case Calendar.NOVEMBER: month_name = "Nov"; break;
+		  case Calendar.DECEMBER: month_name = "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 day_name + " " + 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);
+	 }
+
+	 /** Retrieves and formats the depth field of the config file to four characters.
+	  * @param length The length of the desired string as an <i>int</i>.
+	  * @return A <strong>String</strong> representation of the mirroring depth padded to length characters.
+	  */
+	 public static String getDepthString(int length) {
+		  return pad("" + Gatherer.self.config.getInt("mirroring.depth", false), length);
+	 }
+	 /** Method which constructs the etc 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 etc directory, also as a <strong>String</strong>.
+	  */
+	 public static String getEtcDir(String col_dir) {
+		  return col_dir + ETC_DIR;
+	 }
+	 /** 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) {
+		  ImageIcon image = null;
+		  try {
+				image = new ImageIcon(ClassLoader.getSystemResource("images/" + Gatherer.dictionary.get("Version") + File.separator + filename));
+		  }
+		  catch(Exception error_one) {
+				try {
+					 image = new ImageIcon(ClassLoader.getSystemResource("images/" + filename));
+				}
+				catch (Exception error_two) {
+					 if(Gatherer.dictionary != null) {
+						  File locale_image_file = new File(RES_DIR + Gatherer.dictionary.get("Version") + File.separator + filename);
+						  if(locale_image_file.exists()) {
+								image = new ImageIcon(locale_image_file.toString());
+						  }
+					 }
+					 if(image == null) {
+						  File image_file = new File(RES_DIR + filename);
+						  if(image_file.exists()) {
+								image = new ImageIcon(image_file.toString());
+						  }
+					 }
+				}
+		  }
+		  if(image == null) {
+				image = ERROR_ICON;
+		  }
+		  return image;
+	 }
+
+	 /** Method which constructs the import 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 import directory, also as a <strong>String</strong>.
+	  */
+	 public static String getImportDir(String col_dir) {
+		  return col_dir + IMPORT_DIR;
+	 }
+	 /** Method which constructs the index 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 index directory, also as a <strong>String</strong>.
+	  */
+	 static public String getIndexDir(String col_dir) {
+		  return col_dir + INDEX_DIR;
+	 }
+	 /** 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";
+	 }
+	 /** Method which constructs the metadata 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 metadata directory, also as a <strong>String</strong>.
+	  */
+	 static public String getMetadataDir(String col_dir) {
+		  return col_dir + META_DIR;
+	 }
+
+
+	 static public File getRecycleDirectory() {
+		  return new File(RECYCLE);
+	 }
+
+	 /** Determine whether a character is a hexidecimal one.
+	  * @param chr The <i>char</i> in question.
+	  * @return An <i>int</i> representing the value of the hexidecimal character or -1 if not a hexidecimal.
+	  */
+	 public static int hexidecimal(char chr) {
+		  switch(chr) {
+		  case '0':
+				return 0;
+		  case '1':
+				return 1;
+		  case '2':
+				return 2;
+		  case '3':
+				return 3;
+		  case '4':
+				return 4;
+		  case '5':
+				return 5;
+		  case '6':
+				return 6;
+		  case '7':
+				return 7;
+		  case '8':
+				return 8;
+		  case '9':
+				return 9;
+		  case 'A':
+				return 10;
+		  case 'B':
+				return 11;
+		  case 'C':
+				return 12;
+		  case 'D':
+				return 13;
+		  case 'E':
+				return 14;
+		  case 'F':
+				return 15;
+		  default:
+				return -1;
+		  }
+	 }
+
+	 /** A string is a valid hierarchy index if it matches '[0-9](\.[0-9])*' */
+	 static public boolean isIndex(String raw) {
+		  boolean result = true;
+		  for(int i = 0; result && i < raw.length(); i++) {
+				char c = raw.charAt(i);
+				if(Character.isDigit(c) || (c == '.' && (i != 0 || i != raw.length() - 1))) {
+					 // Valid index
+				}
+				else {
+					 result = false;
+				}
+		  }
+		  return result;
+	 }
+
+	 /** 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;
+	 }
+	 /** 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.
+	  */
+	 public static String pad(String str, int length) {
+		  return pad(str, length, ' ', true);
+	 }
+	 public static 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();
+	 }
+
+	 /** Parse in a xml document from a given filename. Note that this filename may need to be resolved by the class loader, especially for template files within a jar. */
+	 static public Document parse(String filename, boolean use_classloader) {
+		  File file = null;
+		  if(use_classloader) {
+				try {
+					 URL url = ClassLoader.getSystemResource(filename);
+					 file = new File(URLDecoder.decode(url.getFile()));
+					 url = null;
+				}
+				catch (Exception error) {
+					 // Most likely file name.
+					 file = new File("classes" + File.separator + filename);
+					 //Gatherer.printStackTrace(error);
+				}
+		  }
+		  if(file == null) {
+				file = new File(filename);
+		  }
+		  return parse(file, true);
+	 }
+	 /** Parse in a xml document from a given file. */
+	 static public Document parse(File file) {
+		  return parse(file, true);
+	 }
+	 /** Parse in a xml document from a given file. */
+	 static public Document parse(File file, boolean noisey) {
+		  Document document = null;
+		  try {
+				FileInputStream fis   = new FileInputStream(file); 
+				InputStreamReader isr = new InputStreamReader(fis);
+				Reader r              = new BufferedReader(isr);
+				InputSource isc       = new InputSource(r);
+				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();
+				isr.close();
+				fis.close();
+				parser = null;
+				isc = null;
+				r = null;
+				isr = null;
+				fis = null;
+				file = null;
+		  } 
+		  catch (Exception error) {
+				if(noisey) {
+					 Gatherer.printStackTrace(error);
+				}
+		  }
+		  return document;
+	 }
+
+	 /** Method to spread out a line of text so that is is justified to the given width, by attempting to widen white-spacing in a balanced way.
+	  * @param original The <strong>String</strong> to justify.
+	  * @param width The desired width as an <i>int</i>.
+	  * @param current_width An <i>int</i> representing the current width of the string, which takes into account special characters.
+	  * @return The newly justified <strong>String</strong>.
+	  */
+	 static public String space(String original, int width, int current_width) {
+		  // Strip trailing whitespace.
+		  while(original.charAt(original.length() - 1) == ' ') {
+				original = original.substring(0, original.length() - 2);
+		  }
+		  int diff = width - current_width;
+		  // Now add diff spaces, one at each existing space.
+		  int pos = 0;
+		  while(diff > 0) {
+				if(pos == original.length()) {
+					 pos = 0;
+				}
+				if(original.charAt(pos) == ' ') {
+					 // Insert a space.
+					 String prefix = original.substring(0, pos);
+					 String suffix = original.substring(pos);
+					 original = prefix + " " + suffix;
+					 pos = pos + 2;
+					 diff--;
+				}
+				pos++;
+		  }
+		  return original;
+	 }
+	 /** Method to strip new lines and extra spaces from a string. Used to restore text that has been mangled into width formatted blocks by the DOM parser.
+	  * @param raw The <strong>Strong</strong> containing the mangled text.
+	  * @return A <strong>String</strong> with new lines and extra spaces removed.
+	  */
+	 static public String stripNL(String raw_str) {
+		  byte raw[] = raw_str.getBytes();
+		  byte formatted[] = new byte[raw.length];
+		  byte previous = '\0';
+		  int j = 0;
+		  for(int i = 0; i < raw.length; i++) {
+				if(raw[i] == '\n') {
+					 // Skip new lines.
+				}
+				else if(raw[i] == '\t') {
+					 // Skip tabs.
+				}
+				else if(raw[i] == ' ' && raw[i] == previous) {
+					 // Skip erroneous whitespace.
+				}
+				else {
+					 formatted[j] = raw[i];
+					 j++;
+				}
+				previous = raw[i];
+		  }
+		  byte finish[] = new byte[j];
+		  System.arraycopy(formatted, 0, finish, 0, j);
+		  return new String(finish);
+	 }
+	 /** Trims the string text to the length specified removing end characters and adding if necessary.
+	  * @param text A <strong>String</strong> which you wish to ensure is shorter than length.
+	  * @param length An <i>int</i> specifying the strings maximum length after which its trimmed.
+	  * @return The trimmed <strong>String</strong>.
+	  */
+	 public static String trim(String text, int length) {
+		  if(text.length() > length) {
+				text = text.substring(0, length);
+				text = text + "...";
+		  }
+		  return text;
+	 }
+	 /** This method checks to see what registered file system root directorys are mounted, and returns only accessible ones. The exception is removable media drives (in particular floppy-disk drives) which will throw all sorts of error if we test them here. Instead they are assumed to be always accessible, but a test is conducted at the time you attempt to map them to test for actual accessibility (then at least the errors are thrown after the user tries to initiate the mapping of the drive which has no disk in it).
+	  * @param roots A <strong>File[]</strong> containing all of the file system roots registered on this system.
+	  * @return A filtered <strong>File[]</strong> containing only those drives that are accessible and/or are floppy-disk media drives.
+	  */
+	 public static File[] validateDrives(File roots[]) {
+		  Vector valid = new Vector();
+		  for(int i = 0; i < roots.length; i++) {
+				String name = roots[i].getAbsolutePath();
+				name = name.toLowerCase();
+				if(!name.startsWith("a:") && !name.startsWith("b:")) {
+					 valid.add(roots[i]);
+				}
+		  }
+		  roots = new File[valid.size()];
+		  for(int i = 0; i < roots.length; i++) {
+				roots[i] = (File)valid.get(i);
+		  }
+		  return roots;		
+	 }
+}
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/util/WinRegistry.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/WinRegistry.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/WinRegistry.java	(revision 13666)
@@ -0,0 +1,248 @@
+/**
+ *#########################################################################
+ *
+ * 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:        The Gatherer
+ * Description:  The Gatherer: a tool for gathering and enriching digital collections.
+ * Copyright:    Copyright (c) 2001
+ * Company:      The University of Waikato
+ * Written:      18/11/01
+ * Revised:      24/07/02
+ * @author John Thompson, Greenstone Digital Libraries
+ * @version 2.1
+ */
+import java.lang.reflect.Method;
+/** This class provides access to the Windows registry via the preferences modules of JDK1.4. But wouldn't you know it, it doesn't always read the windows key files correctly as they appear to have changed how they store keys between win98, win2000 and winNT. To combat this, this class will eventually be swallowed by the LauchProgramManager, and used only to attempt to determine the default launching commands. */
+public class WinRegistry {
+    /** Windows security mask */
+    private final static int KEY_QUERY_VALUE = 1;
+    /** A constant used to interpret the return of a native function as successful. */
+    private final static int NATIVE_HANDLE = 0;
+	 /** A constant used to interpret the return of a native function as an error. */
+    private final static int ERROR_CODE = 1;
+    /** Windows error codes. */
+    private final static int ERROR_SUCCESS = 0;
+    /** HKEY_LOCAL_MACHINE address. */
+    private final static int HKEY_LOCAL_MACHINE = 0x80000002;
+	 /** Called to build a command string that will launch the given file in its associated program according to the windows registry.
+	  * @param filename The name of a file, including the required extension, as a <strong>String</strong>.
+	  * @return Another <strong>String</strong> containing a command line which, when run in a command shell, will launch an external application to view this file.
+	  */
+    public static String openCommand(String filename) {
+		  if(filename.indexOf(".") != -1) {
+				String extension = filename.substring(filename.indexOf("."));
+				try {
+					 // First find the name of the file type that is associated with this extension.
+					 String file_type = getValue("Software\\CLASSES\\" + extension);
+					 // Then if we got a type, get the open command from its shell reference.
+					 ///ystem.err.println("Searching for file-type = " + file_type);
+					 if(file_type != null) {
+						  String raw = getValue("Software\\CLASSES\\" + file_type + "\\shell\\open\\command");
+						  //Replace "%1" with "filename"
+						  if(raw.indexOf("%1") != -1) {
+								String prefix = raw.substring(0, raw.indexOf("%1"));
+								if(!prefix.endsWith("\"")) {
+									 prefix = prefix + "\"";
+								}
+								String suffix = raw.substring(raw.indexOf("%1") + 2);
+								if(!suffix.endsWith("\"")) {
+									 suffix = suffix + "\"";
+								}
+								return prefix + filename + suffix;
+						  }
+						  // Arg. There is a windows flag called /dde, which if it exists in a command tells it to use the filename (hence the meaningful name dde eh?)
+						  else if(raw.indexOf("/dde") != -1) {
+								String prefix = raw.substring(0, raw.indexOf("/dde"));
+								if(!prefix.endsWith("\"")) {
+									 prefix = prefix + "\"";
+								}
+								String suffix = raw.substring(raw.indexOf("/dde") + 4);
+								if(!suffix.endsWith("\"")) {
+									 suffix = suffix + "\"";
+								}
+								return prefix + filename + suffix;
+						  }
+						  // No file parameter. Append the file to the command and hope for the best.
+						  return raw + " \"" + filename + "\"";
+					 }
+				}
+				catch (Exception error) {
+					 ///ystem.err.println("No such value.");
+					 //error.printStackTrace();
+				}
+		  }
+		  return null;
+	 }
+	 /** Attempts to retrieve the value at the location given from the registry using Reflection.
+	  * @param path The path to the desired key as a <strong>String</strong>.
+	  * @return The value found at the indicated key as a <strong>String</strong>.
+	  */ 
+	 private static String getValue(String path)
+		  throws ClassNotFoundException, Exception, NoSuchMethodException {
+		  ///ystem.err.println("Get value " + path);
+		  byte[] WINDOWS_ROOT_PATH = stringToByteArray(path);
+		  Class theClass = Class.forName("java.util.prefs.WindowsPreferences");
+		  int[] result = openKey(HKEY_LOCAL_MACHINE, WINDOWS_ROOT_PATH, KEY_QUERY_VALUE);
+		  if (result[ERROR_CODE] != ERROR_SUCCESS) {
+				throw new Exception("Path not found!");
+		  }
+		  int native_handle = result[NATIVE_HANDLE];
+		  Method m = theClass.getDeclaredMethod("WindowsRegQueryValueEx", new Class[]{int.class, byte[].class});
+		  m.setAccessible(true);
+		  byte[] windows_name = toWindowsName("");
+		  Object value = m.invoke(null, new Object[]{new Integer(native_handle), windows_name});
+		  WindowsRegCloseKey(native_handle);
+		  if (value == null) {
+				throw new Exception("Path found. Key not found.");
+		  }
+		  byte[] origBuffer = (byte[]) value;
+		  byte[] destBuffer = new byte[origBuffer.length - 1];
+		  System.arraycopy(origBuffer, 0, destBuffer, 0, origBuffer.length - 1);
+		  return new String(destBuffer);
+	 }
+	 /** Closes the reference (and hence the instantiated objects) to a certain entry within the registry. Do this or suffer massive memory leaks.
+	  * @param nativeHandle A reference to the piece of memory containing an inspected windows key-value pair.
+	  * @return The status code returned from closing the key, as an <i>int</i>.
+	  */
+	 public static int WindowsRegCloseKey(int nativeHandle)
+		  throws Exception {
+		  Class theClass = Class.forName("java.util.prefs.WindowsPreferences");
+		  Method m = theClass.getDeclaredMethod("WindowsRegCloseKey", new Class[]{int.class});
+		  m.setAccessible(true);
+		  Object ret = m.invoke(null, new Object[]{new Integer(nativeHandle)});
+		  return ((Integer) ret).intValue();
+	 }
+	 /** Attempts to open a certain key-value pair from the windows registry, from within a certain region (or HKEY). 
+	  * @param hkey An <i>int</i> which is the offset for a certain group within the registry.
+	  * @param windowsAbsolutePath A <i>byte[]</i> containing the path to the desired key, relative to the given HKEY.
+	  * @param securityMask A mask needed to read values from the registry, as an <i>int</i>.
+	  * @return An <i>int[]</i> pair, the first of which is the reference to the indicated key if no error occured, and the second of which reports the end error state of the registry open attempt.
+	  */
+	 public static int[] openKey(int hkey, byte[] windowsAbsolutePath, int securityMask)
+		  throws Exception {
+		  Class theClass = Class.forName("java.util.prefs.WindowsPreferences");
+		  Method m = theClass.getDeclaredMethod("WindowsRegOpenKey", new Class[]{int.class, byte[].class, int.class});
+		  m.setAccessible(true);
+		  Object ret = m.invoke(null, new Object[]{new Integer(hkey), windowsAbsolutePath, new Integer(securityMask)});
+		  return (int[]) ret;
+	 }
+	 /** Converts a string to a byte array. Duh!
+	  * @param str The <strong>String</strong> to be converted.
+	  * @return A <i>byte[]</i> containing orderer characters from the String.
+	  */
+	 private static byte[] stringToByteArray(String str) {
+		  byte[] result = new byte[str.length() + 1];
+		  for (int i = 0; i < str.length(); i++) {
+				result[i] = (byte) str.charAt(i);
+		  }
+		  result[str.length()] = 0;
+		  return result;
+	 }
+	 
+	 private static String toJavaValueString(byte[] windowsNameArray) {
+		  // Use modified native2ascii algorithm
+		  String windowsName = byteArrayToString(windowsNameArray);
+		  StringBuffer javaName = new StringBuffer();
+		  char ch;
+		  for (int i = 0; i < windowsName.length(); i++) {
+				if ((ch = windowsName.charAt(i)) == '/') {
+					 char next = ' ';
+					 
+					 if (windowsName.length() > i + 1 &&
+						  (next = windowsName.charAt(i + 1)) == 'u') {
+						  if (windowsName.length() < i + 6) {
+								break;
+						  } else {
+								ch = (char) Integer.parseInt
+									 (windowsName.substring(i + 2, i + 6), 16);
+								i += 5;
+						  }
+					 } else
+						  if ((windowsName.length() > i + 1) &&
+								((windowsName.charAt(i + 1)) >= 'A') && (next <= 'Z')) {
+								ch = next;
+								i++;
+						  } else if ((windowsName.length() > i + 1) &&
+										 (next == '/')) {
+								ch = '\\';
+								i++;
+						  }
+				} else if (ch == '\\') {
+					 ch = '/';
+				}
+				javaName.append(ch);
+		  }
+		  return javaName.toString();
+	 }
+	 /** */
+	 private static String byteArrayToString(byte[] array) {
+		  StringBuffer result = new StringBuffer();
+		  for (int i = 0; i < array.length - 1; i++) {
+				result.append((char) array[i]);
+		  }
+		  return result.toString();
+	 }
+	 /** Magics the name of a certain path component from a Java String to the unique string windows requires.
+	  * @param javaName The name of a path component as a <strong>String</strong>.
+	  * @return A <i>byte[]</i> containing the translated string.
+	  */
+	 private static byte[] toWindowsName(String javaName) {
+		  StringBuffer windowsName = new StringBuffer();
+		  for (int i = 0; i < javaName.length(); i++) {
+				char ch = javaName.charAt(i);
+				if ((ch < 0x0020) || (ch > 0x007f)) {
+					 throw new RuntimeException("Unable to convert to Windows name");
+				}
+				if (ch == '\\') {
+					 windowsName.append("//");
+				} else if (ch == '/') {
+					 windowsName.append('\\');
+				} else if ((ch >= 'A') && (ch <= 'Z')) {
+					 windowsName.append("/" + ch);
+				} else {
+					 windowsName.append(ch);
+				}
+		  }
+		  return stringToByteArray(windowsName.toString());
+	 } 
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/util/XORToggleButtonGroup.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/util/XORToggleButtonGroup.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/util/XORToggleButtonGroup.java	(revision 13666)
@@ -0,0 +1,50 @@
+package org.greenstone.gatherer.util;
+import java.awt.event.*;
+import javax.swing.*;
+/** Just like any other button group, this object encapsulates several checkbox listeners, but instead of recording which are selected, or indeed what buttons it has assigned to it, this group has but one purpose: to ensure that at least one check button is always selected. */
+public class XORToggleButtonGroup
+	 implements ActionListener {
+	 /** true if we are to ignore any further change events we recieve. */
+	 private boolean ignore = false;
+	 /** The current number of checkboxes that are selected. Never < 1. */
+	 private int selected_count = 0;
+
+	 private JToggleButton last_button;
+
+	 /** Any implementation of ActionListener includes this method so that we can be informed when an action has occured on any registered checkboxes, allowing us to roll back the action if this is the only selected checkbox remaining.
+	  * @param event An <strong>ActionEvent</strong> containing information about the event.
+	  */
+	 public void actionPerformed(ActionEvent event) {
+		  if(!ignore) {
+				ignore = true;
+				JToggleButton toggle_button = (JToggleButton) event.getSource();
+				if(toggle_button.isSelected()) { 
+					 selected_count++;
+				}
+				else {
+					 if(selected_count > 1) {
+						  selected_count--;
+					 }
+					 else {
+						  toggle_button.setSelected(true);
+					 }
+				}
+				ignore = false;
+		  }
+	 }
+	 public void add(JToggleButton toggle_button) {
+		  last_button = toggle_button;
+		  // If the checkbox is selected, increase our count.
+		  if(toggle_button.isSelected()) {
+				selected_count++;
+		  }
+		  toggle_button.addActionListener(this);
+	 }
+
+	 /** Ensures that at least one option is selected. */
+	 public void establish() {
+		  if(selected_count == 0 && last_button != null) {
+				last_button.setSelected(true);
+		  }
+	 }
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/valuetree/GNode.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/valuetree/GNode.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/valuetree/GNode.java	(revision 13666)
@@ -0,0 +1,61 @@
+/**
+ *#########################################################################
+ *
+ * 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.valuetree;
+
+import java.util.Vector;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+
+public class GNode
+	extends DefaultMutableTreeNode {
+
+	private String name     = null;
+
+	public GNode(String name) {
+		this.name = name;
+	}
+
+	public String toString() {
+		return name;
+	}
+}
Index: /tags/start/gli/src/org/greenstone/gatherer/valuetree/GValueModel.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/valuetree/GValueModel.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/valuetree/GValueModel.java	(revision 13666)
@@ -0,0 +1,321 @@
+package org.greenstone.gatherer.valuetree;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.util.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.MetadataSetManager;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.greenstone.gatherer.util.SynchronizedTreeModelTools;
+import org.greenstone.gatherer.util.Utility;
+import org.w3c.dom.*;
+/*
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.1
+ */
+public class GValueModel 
+	 extends DefaultTreeModel {
+
+	 private ElementWrapper element;
+
+	 public GValueModel() {
+		  super(new DefaultMutableTreeNode("Temp"));
+	 }
+
+	 public GValueModel(String root) {
+		  super(new DefaultMutableTreeNode(root));
+	 }
+
+	 public GValueModel(ElementWrapper e) {
+	     super(new DefaultMutableTreeNode("Temp"));
+	     this.element = e;
+		  // Load the template value tree document.
+		  Document document = MSMUtils.getValueTreeTemplate();
+		  Element new_root = document.getDocumentElement();
+		  new_root.setAttribute("element", e.getName());
+		  root = new GValueNode(new_root);
+	 }
+
+	 public GValueModel(ElementWrapper e, Document document) {
+		  super(new DefaultMutableTreeNode("Temp"));
+		  this.element = e;
+		  Element new_root = document.getDocumentElement();
+		  new_root.setAttribute("element", e.getName());
+		  root = new GValueNode(new_root);
+	 }
+
+	 /** Value may include path ie news/newssw */
+	 public GValueNode addValue(String value) {
+		  ///ystem.err.println("Adding value to valuetree: " + value);
+		  StringTokenizer tokenizer = new StringTokenizer(value, "\\");
+		  GValueNode subject = (GValueNode) root;
+		  while(tokenizer.hasMoreTokens() && subject != null) {
+				String token = tokenizer.nextToken();
+				subject = addValue(token, subject, null);
+				///ystem.err.println("Found or created a node " + token);
+		  }
+		  return subject;
+	 }
+
+	 public GValueNode addValue(String value, GValueNode subject, String alias) {
+		  // To add a value we must first ensure it isn't already present in -this- nodes children. The bummer is that the nice getElements functions search the whole tree so...
+		  GValueNode value_node = subject.getValue(Utility.stripNL(value));
+		  if(value_node == null) {
+				// Now add the new value.
+				Document document = subject.getElement().getOwnerDocument();
+				// Now we create a new subject and add it subject
+				Element new_subject = document.createElementNS("","Subject");
+				Element new_value = document.createElementNS("","Value");
+				new_subject.appendChild(new_value);
+				Text new_text = document.createTextNode(value);
+				new_value.appendChild(new_text);
+				if(alias != null && alias.length() > 0) {
+					 Element new_alias = document.createElementNS("","Alias");
+					 new_subject.appendChild(new_alias);
+					 Text new_alias_text = document.createTextNode(alias);
+					 new_alias.appendChild(new_alias_text);					
+				} 
+				value_node = new GValueNode(new_subject);
+				// Figure out where this node will be inserted in subjects 
+				// children.
+				int position = -1;
+				for(int i = 0; position == -1 && i < subject.getChildCount(); i++) {
+					 Object sibling = subject.getChildAt(i);
+					 int rel_pos = value.compareTo(sibling.toString());
+					 ///ystem.err.println("'"+value+"'.compareTo('"+sibling+"') = " + rel_pos);
+					 if(rel_pos <= 0) {
+						  position = i;
+					 }
+				}
+				if(position == -1) {
+					 position = subject.getChildCount();
+				}
+				// Insert it. If position is still -1, append it to the end of subjects children.
+				///ystem.err.println("Inserting '" + value + "' at position " + position);
+				insertNodeInto(value_node, subject, position);
+				// Inform listeners that we've changed.
+				Gatherer.c_man.getCollection().msm.fireValueChanged(element, null, this);
+		  }
+		  return value_node;
+	 }
+
+	 public Document getDocument() {
+		  return ((GValueNode)root).getElement().getOwnerDocument();
+	 }
+
+	 public ElementWrapper getElement() {
+		  return element;
+	 }
+
+	 /** Retrieve the hindex for a certain value within the value tree.
+	  * @param value The value whose index you wish to determine as a <strong>String</strong>.
+	  * @return A <strong>String</strong> containing an index such as "1", "2.1" or "18.2.5".
+	  */ 
+	 public String getHIndex(String value) {
+		  ///ystem.err.println("getHIndex(" + value + ")");
+		  return getHIndex((GValueNode) root, value, null);
+	 }
+
+	 /** Retrieve a value node given its hierarchical reference or value.
+	  * @param index The hierarchy index or value as a <strong>String</strong>.
+	  */
+	 public GValueNode getValue(String index_str) {
+		  ///ystem.err.println("Retrieve the value for: " + index_str);
+		  GValueNode result = null;
+		  if(isHierarchy() && Utility.isIndex(index_str)) {
+				// StringTokenize the index
+				StringTokenizer tokenizer = new StringTokenizer(index_str, ".");
+				result = (GValueNode) root;
+				// Using the index numbers retrieve the appropriate node.
+				try {
+					 while(result != null && tokenizer.hasMoreTokens()) {
+						  int index = Integer.parseInt(tokenizer.nextToken()) - 1;
+						  // Retrieve the index'th child of the current result node
+						  if(0 <= index && index < result.getChildCount()) {
+								result = (GValueNode) result.getChildAt(index);
+						  }
+						  // Otherwise we're broken.
+						  else {
+								///ystem.err.println("There is no " + index + "th childnode of " + result);
+								result = null;
+						  }
+					 }
+				}
+				// Most likely caused by parseInt throwing a wobbly.
+				catch (Exception error) {
+					 result = null;
+				}
+				if(result != null) {
+					 // Ensure result is enabled
+					 result.setEnabled(true);
+				}
+		  }
+		  if(result == null) {
+				///ystem.err.println("No existing value. Adding " + index_str);
+				result = addValue(index_str);
+		  }
+		  return result;
+	 }
+
+	 public boolean isHierarchy() {
+		  boolean result = false;
+		  for(int i = 0; i < root.getChildCount() && !result; i++) {
+				GValueNode node = (GValueNode) root.getChildAt(i);
+				if(node != null && node.getChildCount() > 0) {
+					 result = true;
+				}
+		  }
+		  return result;
+	 }
+
+	 public void removeValue(GValueNode child) {
+		  child.setEnabled(false); // Doesn't appear anymore.
+		  SynchronizedTreeModelTools.removeNodeFromParent(this, child);
+		  Gatherer.c_man.getCollection().msm.fireValueChanged(new ElementWrapper(child.getElement()), null, this);
+	 }
+
+	 public void removeValue(String value) {
+		  // Retrieve the node to be removed.
+		  GValueNode node = getValue(value);
+		  // Now remove it
+		  removeNodeFromParent(node);
+	 }
+
+	 /** Called to remove a certain value of metadata within a specific
+	  * subject within a sbject hierarchy. 
+	  * Note that this method currently doesn't do anything.
+	  * @param value A String representing the value to be removed.
+	  * @param subject An Element representing the subject you wish to remove 
+	  * this value from.
+	  */ 
+	 public void removeValue(String value, GValueNode subject) {
+	 }
+
+	 public int size() {
+		  return size(root);
+	 }
+
+	 private int size(TreeNode current) {
+		  int size = 1;
+		  for(int i = 0; i < current.getChildCount(); i++) {
+				size = size + size(current.getChildAt(i));
+		  }
+		  return size;
+	 }
+
+	 public String toString() {
+		  return element.toString();
+	 }
+
+	 public Vector traverseTree() {
+		  Vector contents = new Vector();
+		  contents.addAll(traverseTree((GValueNode) root));
+		  contents.remove((GValueNode) root);
+		  return contents;
+	 }
+
+	 public void updateValue(String new_value, String old_value) {
+		  ///ystem.err.println("Updating '" + old_value + "' to '" + new_value + "'"); 
+		  StringTokenizer tokenizer = new StringTokenizer(new_value, "\\");
+		  GValueNode subject = (GValueNode) root;
+		  while(tokenizer.hasMoreTokens()) {
+				String token = tokenizer.nextToken();
+				subject = updateValue(token, old_value, subject);
+		  }
+	 }
+
+	 /** Called to update a certain value of metadata within a specific
+	  * subject within a sbject hierarchy. 
+	  * Note that this simply in turn calls removeValue() to deal with the
+	  * old value, then addValue() to account for the new. 
+	  * @param new_value A String representing the updated value.
+	  * @param old_value A String representing the old value.
+	  * @param subject An Element representing the subject you wish to update 
+	  * this value in.
+	  */ 
+	 public GValueNode updateValue(String new_value, String old_value, GValueNode subject) {
+		  return addValue(new_value, subject, null);
+	 }
+
+	 private GValueModel copy() {
+		  Element document_element = ((GValueNode) root).getElement();
+		  Document document_copy = MSMUtils.getValueTreeTemplate();
+		  Element document_copy_element = document_copy.getDocumentElement();
+		  document_copy_element.setAttribute("element", element.getName());
+		  for(Node node = document_element.getFirstChild(); node != null; node = node.getNextSibling()) {
+				if(node.getNodeName().equals("Subject")) {
+					 Node node_copy = document_copy.importNode(node, true);
+					 document_copy_element.appendChild(node_copy);
+				}
+		  }
+		  return new GValueModel(element, document_copy); 				
+	 }
+
+	 private String getHIndex(GValueNode node, String value, String index) {
+		  for(int i = node.size(); i != 0; i--) {
+				GValueNode next = (GValueNode)node.get(i - 1);
+				String next_str = next.toString();
+				if(value.startsWith(next_str)) {
+					 if(index == null) {
+						  index = String.valueOf(i);
+					 }
+					 else {
+						  index = index + "." + i;
+					 }
+					 value = value.substring(next.toString().length());
+					 if(value.startsWith("\\")) {
+						  value = value.substring(1);
+						  index = getHIndex(next, value, index);
+					 }
+					 return index;
+				}
+		  }
+		  return index;
+	 }
+
+	 private Vector traverseTree(GValueNode node) {
+		  Vector contents = new Vector();
+		  contents.add(node);
+		  for(int i = 0; i < node.getChildCount(); i++) {
+				contents.addAll(traverseTree((GValueNode)node.getChildAt(i)));
+		  }
+		  return contents;
+	 }
+}
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/valuetree/GValueNode.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/valuetree/GValueNode.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/valuetree/GValueNode.java	(revision 13666)
@@ -0,0 +1,442 @@
+/**
+ *#########################################################################
+ *
+ * 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.valuetree;
+/**
+ * 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>
+ * First Coded:  20/06/02
+ * Revised:<br>
+ * @author John Thompson, Greenstone Digital Libraries
+ * @version 2.1
+ */
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Vector;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
+import javax.swing.tree.MutableTreeNode;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.MSMUtils;
+import org.greenstone.gatherer.util.Utility;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+/** This class is instantiated using a metadata element. From this parent element, which refers to a specific Element in the mds DOM model, the AssignedValues child is used as the root of a tree data-structure encompassing all of the nodes within the AssignedValues tree. This class also provide methods for adding, updating and removing nodes within this tree, as well as implementing all of the methods necessary for this node to be used as the basis of a tree model.
+ */
+public class GValueNode 
+	 extends DefaultMutableTreeNode {
+	 private String element_name = null;
+	 private String default_value = null;
+	 public GValueNode(Element element) {
+		  this.children = null;
+		  this.userObject = element;
+		  this.default_value = null;
+	 }
+
+	 public GValueNode(String element_name, String default_value) {
+		  this.element_name = element_name;
+		  this.default_value = default_value;
+	 }
+	 /** Compares two GValueNodes for ordering by using the String.compareTo method.
+	  * @param sibling The <strong>Object</strong> representing the GValueNode we are comparing ourselves to.
+	  * @return An <i>int</i> indicating the ordering. The value is less than zero if we are before the parameter object, zero if we are equal and greater than zero if we preceed sibling.
+	  */
+	 public int compareTo(Object sibling) {
+		  return toString().compareTo(sibling.toString());
+	 }
+	 /** Determine if this tree node contains a child with a matching value.
+	  * @param value The value we are attempting to match, as a <strong>String</strong>.
+	  * @return <i>true</i> if there is a matching child node, <i>false</i> otherwise.
+	  */
+	 public boolean containsValue(String value) {
+		  if(default_value != null) {
+				return false;
+		  }
+		  return getValue(value) != null;
+	 }
+	 /** Returns an enumeration of the child nodes.
+	  * @return An <strong>Enumeration</strong> containing the child nodes.
+	  */
+	 public Enumeration children() {
+		  if(default_value != null) {
+				return null;
+		  }
+		  if(children == null) {
+				map();
+		  }
+		  return children.elements();
+	 }
+	 public boolean equals(Object other) {
+		  return compareTo(other) == 0;
+	 }
+
+	 public GValueNode get(int index) {
+		  GValueNode result = null;
+		  if(children != null) {
+				result = (GValueNode) children.get(index);
+		  }
+		  return result;
+	 }
+
+	 public String getAlias() {
+		  // Attempt to retrieve a child node named Alias
+		  Element element = (Element) userObject;
+		  for(Node pos_node = element.getFirstChild(); pos_node != null; pos_node = pos_node.getNextSibling()) {
+				// And if we find such a node 
+				if(pos_node.getNodeName().equals("Alias")) {
+					 // Retrieve its text node
+					 for(Node pos_text = pos_node.getFirstChild(); pos_text != null; pos_text = pos_text.getNextSibling()) {
+						  // When we find the node return its value
+						  if(pos_text.getNodeName().equals("#text")) {
+								return pos_text.getNodeValue();
+						  }
+					 }
+				}
+		  }		  
+		  return "";
+	 }
+
+	 public String getAlias(String index) {
+		  return index;
+	 }
+
+	 /** Returns <I>true</I> if the reciever allows children. */
+	 public boolean getAllowsChildren() {
+		  return true;
+	 }
+
+	 /** Returns the child <I>TreeNode</I> at index <I>childIndex</I>.*/
+	 public TreeNode getChildAt(int index) {
+		  GValueNode result = null;
+		  if(default_value != null) {
+				return this;
+		  }
+		  else {
+				if(children == null) {
+					 map();
+				}
+				for(int i = 0; index >= 0 && i < children.size(); i++) {
+					 GValueNode child = (GValueNode) children.get(i);
+					 if(child.getEnabled()) {
+						  result = child;
+						  index--;
+					 }
+				}
+		  }
+		  return result;
+	 }
+	 /** Returns the number of children <I>TreeNode</I>s the reciever contains. */
+	 public int getChildCount() {
+		  int size = 0;
+		  if(default_value != null) {
+				size = 0;
+		  }
+		  else {
+				if(children == null) {
+					 map();
+				}
+				for(int i = 0; i < children.size(); i++) {
+					 GValueNode child = (GValueNode) children.get(i);
+					 if(child.getEnabled()) {
+						  size++;
+					 }
+				}
+		  }
+		  return size;
+	 }
+	 public Element getElement() {
+		  return (Element) userObject;
+	 }
+	 public boolean getEnabled() {
+		  return !(((Element)userObject).getAttribute("enabled").equals("false"));
+	 }
+
+	 /** Return the path to this node within the value tree model.
+	  * @return A <strong>String</strong> representing the path, ie "Titles\Modern\The Green Mile"
+	  */
+	 public String getFullPath() {
+		  if(default_value != null) {
+				return default_value;
+		  }
+		  StringBuffer path = new StringBuffer(toString());
+		  GValueNode node = (GValueNode) getParent();
+		  while(node != null && !node.getElement().getNodeName().equalsIgnoreCase("AssignedValues")) {
+				path.insert(0, "\\");
+				path.insert(0, node.toString());
+				node = (GValueNode) node.getParent();
+		  }
+		  return path.toString();
+	 }
+
+	 /** Returns the index of <I>node</I> in the recievers children. If the
+	  * reciever does not contain <I>node</I>, <I>-1</I> will be returned. */
+	 public int getIndex(TreeNode node) {
+		  if(default_value != null) {
+				return 0;
+		  }
+		  if(children == null) {
+				map();
+		  }
+		  return children.indexOf(node);
+	 }
+
+	 public String getMetadataElementName() {
+		  if(default_value != null) {
+				return element_name;
+		  }
+		  GValueNode node = this;
+		  while(node != null && !node.getElement().getNodeName().equalsIgnoreCase("AssignedValues")) {
+				node = (GValueNode)node.getParent();
+		  }
+		  if(node != null) {
+				return node.getElement().getAttribute("element");
+		  }
+		  return null;
+	 }
+
+	 public GValueNode getValue(String value) {
+		  if(default_value != null) {
+				return this;
+		  }
+		  if(children == null) {
+				map();
+		  }
+		  GValueNode result = null;
+		  for(int i = 0; result == null && i < children.size(); i++) {
+				Object child = children.get(i);
+				if(child.toString().equals(value)) {
+					 result = (GValueNode) child;
+				}
+		  }
+		  return result;
+	 }
+
+	 /** Adds <I>child</I> to the receiever at <I>index</I>. <I>child</I> will
+	  * be messaged with setParent().
+	  */
+	 public void insert(MutableTreeNode child, int index) {
+		  if(default_value != null) {
+				return;
+		  }
+		  if(index >= children.size()) {
+				// Append to children.
+				children.add(child);
+				// And to document
+				getElement().appendChild(((GValueNode)child).getElement());
+		  }
+		  else {
+				GValueNode sibling = (GValueNode) children.get(index);
+				// Insert in children
+				children.add(index, child);
+				// And in document
+				getElement().insertBefore(((GValueNode)child).getElement(), sibling.getElement());
+		  }
+		  child.setParent(this);
+	 }
+	 /** Returns <I>true</I> if the reciever is a leaf. */
+	 public boolean isLeaf() {
+		  if(default_value != null || getChildCount() > 0) {
+				return false;
+		  }
+		  return true;
+	 }
+
+	 /** Ensure that the children nodes of this tree are instantiated, and record the initial mappings for legacy sake. 
+	  * @param mapping A <strong>HashMap</strong> into which to write the initial mappings.
+	  * @param prefix The prefix to use for indexes, as a <strong>String</strong>.
+	  */
+	 public void map(HashMap mapping, String prefix) {
+		  if(default_value != null) {
+				return;
+		  }
+		  children = new Vector();
+		  if(prefix.length() > 0) {
+				prefix = prefix + ".";
+		  }
+		  int i = 1;
+		  for(Node node = getElement().getFirstChild(); node != null; node = node.getNextSibling()) {
+				if(node.getNodeName().equals("Subject")) {
+					 GValueNode child = new GValueNode((Element)node);
+					 child.setParent(this);
+					 children.add(child);
+					 String index = prefix + i;
+					 mapping.put(index, child);
+					 child.map(mapping, index);
+					 i++;
+				}
+		  }
+	 }
+
+	 /** Removes the child at <I>index</I> from the reciever. */
+	 public void remove(int index) {
+		  // Can't ever remove Elements from here. Have to use editor. */
+	 }
+
+	 /** Removes <I>node</I> from the reciever. <I>setParent</I> will be 
+	  * messaged on node. 
+	  */
+	 public void remove(MutableTreeNode node) {
+		  // Can't ever remove Elements from here. Have to use editor. */
+	 }
+
+	 /** Removes the reciever from its parent. */
+	 public void removeFromParent() {
+		  // Can't ever remove Elements from here. Have to use editor. */
+	 }
+
+	 public void setAlias(String alias) {
+		  setNodeValue("Alias", alias);
+	 }
+
+	 public void setEnabled(boolean state) {
+		  Element element = (Element) userObject;
+		  if(state) {
+				element.setAttribute("enabled", "true");
+		  }
+		  else {
+				element.setAttribute("enabled", "false");
+		  }
+	 }
+
+	 /** Resets the user object of the reciever to <I>object</I>. */
+	 public void setUserObject(Object object) {
+		  // Can't ever change Elements from here. Have to use editor. */		  
+	 }
+
+	 public void setValue(String value) {
+		  setNodeValue("Value", value);
+	 }
+
+	 public int size() {
+		  int size = 0;
+		  if(children != null) {
+				size = children.size();
+		  }
+		  return size;
+	 }
+
+	 /** Returns a <I>String</I> representation of the reciever. If this
+	  * happens to be the AssignedValues 'root' then we do something slightly
+	  * different, otherwise we return the value of the <I>#Text</I> child of 
+	  * the <I>Value</I> of this <I>Subject</I> node!
+	  */
+	 public String toString() {
+		  if(default_value != null) {
+				return default_value;
+		  }
+		  Element element = getElement();
+		  String name = element.getNodeName();
+		  String result = null;
+		  if(name.equals("Subject")) {
+				result = MSMUtils.getValue(element);
+		  }
+		  else if(name.equals("AssignedValues")) {
+				result = getMetadataElementName();
+		  }
+		  return Utility.stripNL(result);
+	 }
+
+	 public void unmap() {
+		  children = null;
+	 }
+
+	 private void map() {
+		  children = new Vector();
+		  for(Node node = getElement().getFirstChild(); node != null; node = node.getNextSibling()) {
+				if(node.getNodeName().equals("Subject")) {
+					 GValueNode child = new GValueNode((Element)node);
+					 child.setParent(this);
+					 children.add(child);
+				}
+		  }
+	 }
+
+	 private void setNodeValue(String name, String value) {
+		  boolean found = false;
+		  // Attempt to retrieve a child node named name
+		  Element element = (Element) userObject;
+		  for(Node pos_node = element.getFirstChild(); pos_node != null; pos_node = pos_node.getNextSibling()) {
+				// And if we find such a node 
+				if(pos_node.getNodeName().equals(name)) {
+					 // And the new value is non-null, retrieve its text node and change it.
+					 if(value != null) {
+						  for(Node pos_text = pos_node.getFirstChild(); pos_text != null; pos_text = pos_text.getNextSibling()) {
+								// When we find the node...
+								if(pos_text.getNodeName().equals("#text")) {
+									 pos_text.setNodeValue(value);
+								}
+						  }
+					 }
+					 // Otherwise remove the node altogether
+					 else {
+						  element.removeChild(pos_node);
+					 }
+					 found = true;
+				}
+		  }
+		  // Otherwise if no such node exists add it.
+		  if(!found && value != null) {
+				Document document = element.getOwnerDocument();
+				Node new_node = document.createElementNS("", name);
+				element.appendChild(new_node);
+				Node new_text = document.createTextNode(value);
+				new_node.appendChild(new_text);
+				new_text = null;
+				new_node = null;
+		  }
+		  // Done.
+		  element = null;
+		  return;
+	 }
+}
+
+
+
+
Index: /tags/start/gli/src/org/greenstone/gatherer/valuetree/GValueTree.java
===================================================================
--- /tags/start/gli/src/org/greenstone/gatherer/valuetree/GValueTree.java	(revision 13666)
+++ /tags/start/gli/src/org/greenstone/gatherer/valuetree/GValueTree.java	(revision 13666)
@@ -0,0 +1,895 @@
+package org.greenstone.gatherer.valuetree;
+/**
+ *#########################################################################
+ *
+ * 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.
+ *########################################################################
+ */
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.text.*;
+import javax.swing.tree.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.gui.EditorDialog;
+import org.greenstone.gatherer.gui.MetaEditPane;
+import org.greenstone.gatherer.gui.SmarterTextArea;
+import org.greenstone.gatherer.gui.combobox.GComboBox;
+import org.greenstone.gatherer.gui.combobox.GComboBoxModel;
+import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.msm.Metadata;
+import org.greenstone.gatherer.msm.MetadataComboBoxModel;
+import org.greenstone.gatherer.msm.MSMAction;
+import org.greenstone.gatherer.msm.MSMEvent;
+import org.greenstone.gatherer.msm.MSMListener;
+import org.greenstone.gatherer.util.Utility;
+/**
+ * @author John Thompson, Greenstone Digital Library, University of Waikato
+ * @version 2.2
+ */
+public class GValueTree
+	 extends JPanel
+	 implements ActionListener, FocusListener, MSMListener, ItemListener, KeyListener, TreeSelectionListener {
+	 /** Is the metadata currently shown in the edit controls common to all records selected. */
+	 private boolean common = false;
+	 /** Certain actions are disabled if the metadata selected isn't at file level. */
+	 private boolean file_level = false;
+	 private boolean ignore = false;
+	 private boolean ignore_item_change = false;
+	 private CardLayout card_layout;
+	 private DefaultListModel list_model;
+	 /** The metadata element that is currently selected. */
+	 private ElementWrapper selected_metadata_element = null;
+	 private GComboBox elements;
+	 private MetadataComboBoxModel em;
+	 private GValueModel vm;
+	 private Hashtable previous_values = new Hashtable();
+	 private JButton add;
+	 /** This button creates an editor dialog to allow for an expanded area to type in text. */
+	 private JButton expand = null;
+	 private JButton remove;
+	 private JButton restore;
+	 private JButton search;
+	 private JButton update;
+	 private JLabel element_label;
+	 private JLabel value_label;
+	 private JList list;
+	 private JPanel auto_pane;
+	 private JPanel button_pane;
+	 private JPanel center_pane;
+	 private JPanel list_pane;
+	 private JPanel north_pane;
+	 private JPanel south_pane;
+	 private JPanel tree_pane;
+	 private JPanel value_pane;
+	 private JTextArea auto_message;
+	 private JTextField value;
+	 private JTree tree;
+	 private MetaEditPane metaedit;
+	 private String args[] = new String[1];
+	 private TreePath previous;
+	 private ValueListener value_listener;
+	 /** Stock standard size for labels. */
+	 static final private Dimension LABEL_SIZE = new Dimension(132, 26);
+
+	 static final private String LIST = "List";
+	 static final private String NONE = "None";
+	 static final private String TREE = "Tree";
+
+
+	 public GValueTree(MetaEditPane metaedit, int width, int height, JButton add, JButton update, JButton remove) {
+		  this(metaedit, new Dimension(width, height), add, update, remove);
+	 }
+
+	 public GValueTree(MetaEditPane metaedit, Dimension size, JButton add, JButton update, JButton remove) {
+		 super();
+
+		 this.add = add;
+		 this.metaedit = metaedit;
+		 this.remove = remove;
+		 this.update = update;
+
+		 ///ystem.err.println("Created new ValueListener!");
+		 value_listener = new ValueListener();
+
+		 int height = size.height;
+		 int width = size.width;
+
+		 setFont(Gatherer.config.getFont("general.font", false));
+		 //setSize(size);
+		 setPreferredSize(size);
+
+		 north_pane = new JPanel();
+
+		 element_label = new JLabel(get("Element"));
+		 element_label.setPreferredSize(LABEL_SIZE);
+
+		 elements = new GComboBox();
+		 elements.addItemListener(this);
+		 elements.setEditable(false);
+		 elements.setMaximumRowCount(5);
+		 elements.setPreferredSize(new Dimension(413, 24));
+
+		 center_pane = new JPanel();
+
+		 card_layout = new CardLayout();
+
+		 auto_pane = new JPanel();
+
+		 args[0] = "Title";
+		 auto_message = new SmarterTextArea(get("AutoMessage", args), false);
+		 auto_message.setLineWrap(true);
+		 auto_message.setOpaque(false);
+		 auto_message.setWrapStyleWord(true);
+
+		 tree_pane = new JPanel();
+
+		 JLabel tree_label = new JLabel(get("Tree"));
+
+		 tree = new JTree(new GValueModel());
+		 tree.addTreeSelectionListener(this);
+		 tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+		 tree.setRootVisible(true);
+		 tree.putClientProperty("JTree.lineStyle", "Angled");
+		 //setTreeEnabled(false);
+
+		 list_pane = new JPanel();
+
+		 JLabel list_label = new JLabel(get("List"));
+
+		 list_model = new DefaultListModel();
+		 list = new JList(list_model);
+		 list.addListSelectionListener(new ListSelectionListenerImpl());
+
+		 south_pane = new JPanel();
+
+		 value_pane = new JPanel();
+
+		 value_label = new JLabel(get("Value"));
+		 value_label.setPreferredSize(LABEL_SIZE);
+
+		 value = new JTextField();
+		 value.addActionListener(this);
+		 value.addFocusListener(this);
+		 //value.addKeyListener(this);
+		 value.getDocument().addDocumentListener(new DocumentListenerImpl());
+		 value.setPreferredSize(new Dimension(413, 24));
+
+		 button_pane = new JPanel();
+
+		 expand = new JButton(get("General.Expand"));
+		 expand.addActionListener(this);
+		 expand.setMnemonic(KeyEvent.VK_E);
+
+		 restore = new JButton(get("Restore"));
+		 restore.addActionListener(this);
+		 restore.setEnabled(false);
+		 restore.setMnemonic(KeyEvent.VK_T);
+
+		 search = new JButton(get("Search"));
+		 search.addActionListener(this);
+		 search.setMnemonic(KeyEvent.VK_S);
+
+		 // Layout
+		 element_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+
+		 north_pane.setLayout(new BorderLayout());
+		 north_pane.add(element_label, BorderLayout.CENTER);
+		 north_pane.add(elements, BorderLayout.EAST);
+
+		 tree_pane.setLayout(new BorderLayout());
+		 tree_pane.add(tree_label, BorderLayout.NORTH);
+		 tree_pane.add(new JScrollPane(tree), BorderLayout.CENTER);
+
+		 list_pane.setLayout(new BorderLayout());
+		 list_pane.add(list_label, BorderLayout.NORTH);
+		 list_pane.add(new JScrollPane(list), BorderLayout.CENTER);
+
+		 auto_pane.setBorder(BorderFactory.createEmptyBorder(25,10,25,10));
+		 auto_pane.setLayout(new BorderLayout());
+		 auto_pane.add(auto_message, BorderLayout.CENTER);
+
+		 center_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
+		 center_pane.setLayout(card_layout);
+		 center_pane.add(tree_pane, TREE);
+		 center_pane.add(list_pane, LIST);
+		 center_pane.add(auto_pane, NONE);
+
+		 value_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
+
+		 value_pane.setBorder(BorderFactory.createEmptyBorder(0,0,2,0));
+		 value_pane.setLayout(new BorderLayout());
+		 value_pane.add(value_label, BorderLayout.CENTER);
+		 value_pane.add(value, BorderLayout.EAST);
+
+		 button_pane.setLayout(new GridLayout(2,3,2,0));
+		 button_pane.add(search);
+		 button_pane.add(restore);
+		 button_pane.add(expand);
+		 button_pane.add(add);
+		 button_pane.add(update);
+		 button_pane.add(remove);
+
+		 south_pane.setLayout(new BorderLayout());
+		 south_pane.add(value_pane, BorderLayout.CENTER);
+		 south_pane.add(button_pane, BorderLayout.SOUTH);
+
+		 this.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+		 this.setLayout(new BorderLayout());
+		 this.add(north_pane, BorderLayout.NORTH);
+		 this.add(center_pane, BorderLayout.CENTER);
+		 this.add(south_pane, BorderLayout.SOUTH);
+	 }
+
+	public void actionPerformed(ActionEvent event) {
+		 ignore = true;
+		 if(event.getSource() == value) {
+			  StringTokenizer tokenizer = new StringTokenizer(value.getText(), "\\");
+			  TreePath closest = getClosestPath(tokenizer);
+			  if(closest != null) {
+					TreePath path = tree.getSelectionPath();
+					GValueNode node = (GValueNode)path.getLastPathComponent();
+					///ystem.err.println("1. Set value: " + node.toString());
+					value.setText(Utility.stripNL(node.toString()));//formatPath(path, false)));
+					// Now systematically add to selected record.
+					add.doClick();
+			  }
+			  else {
+					int response = JOptionPane.showConfirmDialog(this, "Do you wish to create a new entry?", "Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
+					if(response == JOptionPane.YES_OPTION) {
+						 TreePath new_path = addNode(value.getText());
+						 tree.setSelectionPath(new_path);
+						 tree.scrollPathToVisible(new_path);
+						 GValueNode node = (GValueNode)new_path.getLastPathComponent();
+						 ///ystem.err.println("2. Set value: " + node.toString());
+						 value.setText(Utility.stripNL(node.toString()));		
+						 // Now systematically add to selected record.
+						 add.doClick();
+					}
+			  }
+		 }
+		 else if(event.getSource() == search) {
+			  searchValues();
+			  restore.setEnabled(true);
+			  card_layout.show(center_pane, LIST);
+		 }
+		 else if(event.getSource() == restore) {
+			  restore.setEnabled(false);
+			  card_layout.show(center_pane, TREE);
+		 }
+		 else if(event.getSource() == expand) {
+			  EditorDialog ed = new EditorDialog();
+			  String temp = ed.display(value.getText());
+			  if(temp != null) {
+					///ystem.err.println("3. Set value: " + temp);
+					value.setText(temp);
+			  }
+			  //validateControls();
+		 }
+		 ignore = false;
+	}
+	 /** Called whenever an element within the metadata set module changes in some way.
+	  * @param event A <strong>MSMEvent</strong> which contains information about the change.
+	  */
+	 public void elementChanged(MSMEvent event) {
+		  /* @TODO - Not sure. Figure out. */
+	 }
+	 public void focusGained(FocusEvent event) {
+
+	 }
+
+	 public void focusLost(FocusEvent event) {
+
+	 }
+
+	 public boolean getCommon() {
+		  return common;
+	 }
+
+	 public ElementWrapper getSelectedMetadataElement() {
+		  return selected_metadata_element;
+	 }
+
+	 public String getSelectedValue() {
+		  String value_text = value.getText();
+		  previous_values.put(selected_metadata_element, value_text);
+		  return value_text;
+	 }
+
+	 public GValueModel getValueModel() {
+		  return (GValueModel) tree.getModel();
+	 }
+
+	 /** This method is required for any ItemListener so that it can be informed when the state of an item set changes (such as when a new selection is made in a combobox). Note that this update is subtly different from the validateControls() method as it also gathers new models for each combobox as required. The reason this isn't done as part of validateControls() is that this would continously reset whatever the user is attempting to type (ie value would be found to be enabled and a new model would be loaded erasing whatever the user just typed in value to fire the validateControls() in the first place!)
+	  * @param event An ItemEvent encapsulating all the information about this event.
+	  */
+    public void itemStateChanged(ItemEvent event) {
+		  ///ystem.err.println("Item State Changed");
+		  if(!ignore_item_change) {
+				ignore_item_change = true;
+				selected_metadata_element = (ElementWrapper)em.getSelectedItem();
+				if(selected_metadata_element != null) {
+					 elements.setToolTipText(selected_metadata_element.getToolTip());
+					 vm = null;
+					 vm = Gatherer.c_man.getCollection().msm.getValueTree(selected_metadata_element);
+					 if(vm != null) {
+						  ///ystem.err.println("Assigning value model.");
+						  vm.addTreeModelListener(value_listener);
+						  tree.addTreeSelectionListener(this);
+						  setTreeEnabled(true);
+					 }
+					 else {
+						  ///ystem.err.println("Creating new model.");
+						  vm = new GValueModel(get("Not_Applicable"));
+						  setTreeEnabled(false);
+					 }
+					 tree.setModel(vm);
+				}
+				else {
+					 setTreeEnabled(false);
+				}
+				value.setText("");
+				metaedit.validateControls();
+		  }
+		  previous = null;
+		  ignore_item_change = false;
+		  validateControls();
+    }
+
+	 public void keyPressed(KeyEvent event) {
+	 }
+
+    public void keyReleased(KeyEvent event) {
+		  ignore = true;
+		  ///ystem.err.println("Key released.");
+		  StringTokenizer tokenizer = new StringTokenizer(value.getText(), "\\");
+		  TreePath closest = getClosestPath(tokenizer);
+		  if(closest == previous) {
+				validateControls();
+				ignore = false;
+				return;
+		  }
+		  else {
+				// Clear previous
+				if(previous != null) {
+					 // We have a brand new match close up the old one.
+					 if(closest != null) {
+						  if(getParent(previous) != null &&
+							  !getParent(previous).toString().equals
+							  ("[AssignedValues]")) {
+								tree.collapsePath(getParent(previous));
+						  }
+						  previous = null;
+					 }
+					 // We haven't got a match, but we did have a matching path to
+					 // this point. Move the selection to previous paths parent.
+					 else {
+						  tree.setSelectionPath(getParent(previous));
+					 }
+				}
+				
+				if(closest != null) {
+					 tree.setSelectionPath(closest);
+					 tree.scrollPathToVisible(closest);
+					 previous = closest;
+				}
+		  }
+		  ignore = false;
+		  validateControls();
+    }
+    
+    public void keyTyped(KeyEvent event) {
+    }
+
+	 /** Called whenever a metadata value is changed.
+	  * @param event A <strong>MSMEvent</strong> which encapsulates relevant data about the change.
+	  */
+	 public void metadataChanged(MSMEvent event) {
+		  // Don't care.
+	 }
+	 
+    public void newMetadataSetManager() {
+		  if(Gatherer.c_man != null && Gatherer.c_man.getCollection() != null && Gatherer.c_man.getCollection().msm != null) {
+				Gatherer.c_man.getCollection().msm.addMSMListener(this);
+		  }
+		  setChanged(null);
+    }
+
+	 public void refreshValueTree() {
+		  if(em != null && em.getSize() > 0) {
+				setSelectedMetadataElement((ElementWrapper)em.getSelectedItem());
+		  }
+	 }
+    
+    public void registerModel(GValueModel model) {
+		  vm = model;
+		  vm.addTreeModelListener(value_listener);
+		  tree.setModel(model);
+		  tree.addTreeSelectionListener(this);
+    }
+	 /** Called whenever a set within the metadata set module changes in some way.
+	  * @param event A <strong>MSMEvent</strong> which contains information about the change.
+	  */
+	 public void setChanged(MSMEvent event) {
+		  // Update the element model.
+		  MetadataComboBoxModel model = Gatherer.c_man.getCollection().msm.getElementModel();
+		  if(model.getSize() > 0) {
+				setElementModel(model);
+				model.setSelectedItem(model.getElementAt(0));
+				vm = Gatherer.c_man.getCollection().msm.getValueTree((ElementWrapper)model.getSelectedItem());
+				setTreeEnabled(true);
+				if(vm == null) {
+					 vm = new GValueModel(get("Not_Applicable"));
+					 setTreeEnabled(false);
+				}
+		  }
+		  else {
+				vm = new GValueModel();
+				setTreeEnabled(true);
+		  }
+		  vm.addTreeModelListener(value_listener);
+		  tree.setModel(vm);
+		  tree.addTreeSelectionListener(this);
+	 } 
+
+	 public void setCommon(boolean common) {
+		  this.common = common;
+	 }
+
+    public void setElementModel(MetadataComboBoxModel model) {
+		  ///ystem.err.println("Reset ElementModel.");
+		  setTreeEnabled(true);
+		  Gatherer.c_man.getCollection().msm.addMSMListener(this);
+		  if(model == null) {
+				Gatherer.println("model = null");
+				System.exit(0);
+		  }
+		  ignore_item_change = true;
+		  em = model;
+		  elements.setModel(em);
+		  if(em.getSize() > 0) {
+				///ystem.err.println("em.size() > 0");
+				elements.setEnabled(true);
+				elements.setSelectedIndex(0);
+				selected_metadata_element = (ElementWrapper)em.getSelectedItem();
+				elements.setToolTipText(selected_metadata_element.getToolTip());
+				// First we create and install a blank model, or else no updates ever work.
+				vm = new GValueModel(get("Not_Applicable"));
+				tree.setModel(vm);
+				// Now we create a new model if applicable, disabling otherwise.
+				if(selected_metadata_element.getNamespace().length() > 0) {
+					 vm = Gatherer.c_man.getCollection().msm.getValueTree(selected_metadata_element);
+					 vm.addTreeModelListener(value_listener);
+					 ///ystem.err.println("Found existing model containing " + vm.size() + " entries");
+					 setTreeEnabled(true);
+					 tree.setModel(vm); // This doesn't seem to work
+				}
+				else {
+					 ///ystem.err.println("Creating new model.");
+					 setTreeEnabled(false);
+				}
+				///ystem.err.println("The value tree should have been updated by now.");
+				///ystem.err.println("6. Set value: " + getLastValue());
+				value.setText(Utility.stripNL(getLastValue()));
+		  }
+		  else {
+				///ystem.err.println("No elements loaded.");
+				elements.setEnabled(false);
+				elements.setToolTipText(get("No_Description"));
+				//setTreeEnabled(false);
+				value.setText("");
+		  }
+		  previous = null;
+		  ignore_item_change = false;
+		  validateControls();
+    }
+
+	 public void setFileLevel(boolean file_level) {
+		  this.file_level = file_level;
+	 }
+
+	 public void setRootVisible(boolean val) {
+		  tree.setRootVisible(val);
+	 }
+
+    public void setSelectedMetadataElement(ElementWrapper element) {
+		  if(!ignore_item_change) {
+				ignore_item_change = true;
+				if(element != null) {
+					 selected_metadata_element = element;
+					 elements.setSelectedItem(element);
+					 elements.setToolTipText(element.getToolTip());
+					 vm = Gatherer.c_man.getCollection().msm.getValueTree(element);
+					 if(vm != null) {
+						  vm.addTreeModelListener(value_listener);
+						  setTreeEnabled(true);
+					 }
+					 else {
+						  vm = new GValueModel(get("Not_Applicable"));
+						  setTreeEnabled(false);
+					 }
+					 tree.setModel(vm);
+					 ///ystem.err.println("7. Set value: " + getLastValue());
+					 value.setText(Utility.stripNL(getLastValue()));
+				}
+				else {
+					 elements.setToolTipText(get("No_Description"));
+					 setTreeEnabled(false);
+					 value.setText("");
+				}
+				metaedit.validateControls();
+		  }
+		  previous = null;
+		  ignore_item_change = false;
+		  validateControls();
+    }
+
+	 public void setSelectedValue(String val) {
+		  ignore = true;
+		  value.setText(Utility.stripNL(val));
+		  StringTokenizer tokenizer = new StringTokenizer(val, "\\");
+		  TreePath closest = getClosestPath(tokenizer);
+		  if(previous != null) {
+				tree.collapsePath(getParent(previous));
+				previous = null;
+		  }
+		  if(closest != null) {
+				tree.setSelectionPath(closest);
+				tree.scrollPathToVisible(closest);
+		  }
+		  ignore = false;
+		  validateControls();
+	 }
+
+	 /** This method enables or diables the various controls based upon the
+	  * state of the system. This method should be called after every change
+	  * which could affect the GUI.
+	  */
+	 public void validateControls() {
+		  //gatherer.debug("Validating controls...");
+		  ///ystem.err.println("Validating controls...");
+		  // Validate add
+		  if(metaedit.getSelectedNode() != null && value.getText().length() > 0) {
+		      add.setEnabled(true);
+		      //gatherer.debug("Accepted.");
+		      ///ystem.err.println("Yes");
+		  }
+		  else {
+		      add.setEnabled(false);
+		      //gatherer.debug("Denied.");
+		      ///ystem.err.println("No.");
+		  }
+
+		  // Validate update
+		  Metadata selected_metadata = metaedit.getSelectedMetadata();
+		  if(metaedit.getSelectedNode() != null &&  selected_metadata != null && selected_metadata.getValueNode() != null && selected_metadata.getValueNode().getFullPath().length() > 0 && value.getText().length() > 0 && common) {
+				update.setEnabled(true);
+		  }
+		  else {
+				update.setEnabled(false);
+		  }
+
+		  // Validate remove
+		  if(metaedit.getSelectedNode() != null && metaedit.getSelectedMetadata() != null && file_level) {
+				remove.setEnabled(true);
+		  }
+		  else {
+				remove.setEnabled(false);
+		  }
+	 }
+
+	 /** Called when the value tree of a certain element has changed significantly. If we are displaying the tree for the element noted in the event, then reload the value model.
+	  * @param event A <strong>MSMEvent</strong> containing information about the event.
+	  */
+	 public void valueChanged(MSMEvent event) {
+		  ElementWrapper element = event.getElement();
+		  if(selected_metadata_element.equals(element)) {
+				vm = new GValueModel(get("Not_Applicable"));
+				tree.setModel(vm);
+				GValueModel temp = Gatherer.c_man.getCollection().msm.getValueTree(element);
+				if(temp != null) {
+					 vm = temp;
+					 tree.setModel(vm);
+					 vm.addTreeModelListener(value_listener);
+					 setTreeEnabled(true);
+				}
+				else {
+					 setTreeEnabled(false);
+				}
+		  }
+	 }
+
+    public void valueChanged(TreeSelectionEvent event) {
+		  if(tree.getSelectionCount() != 0 && !ignore) {
+				TreePath path = tree.getSelectionPath();
+				GValueNode node = (GValueNode) path.getLastPathComponent();
+				value.setText(node.getFullPath());//formatPath(tree.getSelectionPath(), false)));
+		  }
+		  validateControls();
+    }
+    
+    private TreePath addNode(String reference) {
+		  StringTokenizer tokenizer = new StringTokenizer(reference, "\\");
+		  GValueModel model = (GValueModel)tree.getModel();
+		  GValueNode current = (GValueNode)model.getRoot();
+		  while(tokenizer.hasMoreElements()) {
+				String token = tokenizer.nextToken();
+				GValueNode node = (GValueNode)getClosestNode(token, current);
+				if(node == null) {
+					 Gatherer.println("Before: '" + current.toString() + "'");
+					 for(int i = 0; i < current.getChildCount(); i++) {
+						  Gatherer.println(current.getChildAt(i).toString());
+					 }
+					 node = model.addValue(token, current, null);
+					 Gatherer.println("After: '" + current.toString() + "'");
+					 for(int i = 0; i < current.getChildCount(); i++) {
+						  Gatherer.println(current.getChildAt(i).toString());
+					 }
+				}
+				current = node;
+		  }
+		  tree.updateUI();
+		  if(current != null) {
+				return new TreePath(current.getPath());
+		  }
+		  else {
+				return new TreePath(((GValueNode)model.getRoot()).getPath());
+		  }
+    }
+	 /** Returns the given tree path as path formatted string (ie subject\subject\subject).
+	  * @param tree The <strong>JTree</strong> the TreePath came from. Used to determine if the root node should be encoded as well.
+	  * @param path A <strong>TreePath</strong> that you wish to encode to String.
+	  * @param full <i>true</i> if this is the full path (ie a leaf node), <i>false</i> otherwise.
+	  * @return A <strong>String</strong> encoding the information from the TreePath.
+	  * @see javax.swing.JTree
+	  * @see javax.swing.tree.TreePath
+	  */
+	static public String formatPath(JTree tree, TreePath path, boolean full) {
+		String text = "";
+		int i = 0;
+		if(tree == null || (!tree.isRootVisible() && !full)) {
+			 i = 1;
+		}
+		for( ; i < path.getPathCount(); i++) {
+			GValueNode node = (GValueNode)path.getPathComponent(i);
+		  text = text + node.toString();
+			if(node.getChildCount() > 0) {
+				text = text + "\\";
+			}
+		}
+		if(full && text.endsWith("\\")) {
+			 return text.substring(0, text.length() - 1);
+		}
+		return text;
+	}
+
+	 private String get(String key) {
+		  return get(key, null);
+	 }
+
+	 private String get(String key, String args[]) {
+		  if(key.indexOf('.') == -1) {
+				key = "MetaEdit." + key;
+		  }
+		  return Gatherer.dictionary.get(key,args);
+	 }
+
+	private GValueNode getClosestNode(String target, GValueNode current) {
+		// We have struck it lucky.
+		if(startsWith(current.toString(), target)) {
+			return current;
+		}
+		GValueNode closest = null;
+		for(int i = 0; i < current.getChildCount() && closest == null; i++) {
+			closest = getClosestNode(target, (GValueNode)current.getChildAt(i));
+		}
+		return closest;
+	}
+
+	 private TreePath getClosestPath(StringTokenizer tokenizer) {
+		  if(tokenizer.countTokens() > 0) {
+				TreeNode tree_node = (TreeNode)tree.getModel().getRoot();
+				if(tree_node instanceof GValueNode) {
+					 GValueNode current = (GValueNode)tree_node;
+					 TreePath closest = null;
+					 while(tokenizer.hasMoreElements() && current != null) {
+						  current = getClosestNode(tokenizer.nextToken(), current);
+					 }
+					 if(current != null) {
+						  return new TreePath(current.getPath());
+					 }
+					 return null;
+				}
+		  }
+		  return null;
+	 }
+
+	 private String getLastValue() {
+		  if(previous_values.containsKey(selected_metadata_element)) {
+				return (String)previous_values.get(selected_metadata_element);
+		  }
+		  return "";
+	 }
+
+	private TreePath getParent(TreePath path) {
+		if(path.getPathCount() > 1) {
+			TreeNode nodes[] = new TreeNode[path.getPathCount() - 1];
+			for(int i = 0; i < path.getPathCount() - 1; i++) {
+				nodes[i] = (TreeNode)path.getPathComponent(i);
+			}
+			return new TreePath(nodes);
+		}
+		return null;
+	}
+
+	private void searchValues() {
+		 // Clear any old search results.
+		 list_model.clear();
+		 String target = value.getText();
+		 GValueNode current = (GValueNode)tree.getModel().getRoot();
+		 Vector search_space = new Vector();
+		 search_space.add(current);
+		 for(int i = 0; i < search_space.size(); i++) {
+			  GValueNode node = (GValueNode)search_space.get(i);
+			  // Add this nodes children.
+			  for(int j = 0; j < node.getChildCount(); j++) {
+					search_space.add(node.getChildAt(j));
+			  }
+			  // And if this node matches add it to list, except for the very
+			  // first node as that is AssignedValues the root node!
+			  if(node.toString().indexOf(target) != -1 &&
+				  node != current) {
+					list_model.add(list_model.size(), node);
+			  }
+		 }
+	}
+
+	private void setTreeEnabled(boolean value) {
+		 tree.setRootVisible(!value);
+		 tree.setEnabled(value);
+		 if(value) {
+			  card_layout.show(center_pane, TREE);
+		 }
+		 else {
+			  args[0] = selected_metadata_element.toString();
+			  auto_message.setText(get("AutoMessage", args));
+			  card_layout.show(center_pane, NONE);
+		 }
+	}
+
+	private boolean startsWith(String longer, String shorter) {
+		if(longer.length() > shorter.length()) {
+		  longer = longer.substring(0, shorter.length());
+		}
+		return longer.equalsIgnoreCase(shorter);
+	}
+
+    private void printTreePaths() {
+	///ystem.out.println("Tree Paths according to getPath() method.");
+	Vector nodes = new Vector();
+	nodes.add(tree.getModel().getRoot());
+		  while(nodes.size() > 0) {
+		      GValueNode node = (GValueNode)nodes.get(0);
+		      nodes.remove(node);
+		      for(int i = 0; i < node.getChildCount(); i++) {
+			  nodes.add(node.getChildAt(i));
+		      }
+				///ystem.out.println("TreePath = " + node.getPath());
+		  }
+    }
+
+	 private class DocumentListenerImpl
+		  implements DocumentListener {
+		  /** Gives notification that an attribute or set of attributes changed. */
+		  public void changedUpdate(DocumentEvent e) {
+				validateControls();
+		  }
+          
+		  /** Gives notification that there was an insert into the document. */
+		  public void insertUpdate(DocumentEvent e) {
+				validateControls();
+		  }
+          
+		  /** Gives notification that a portion of the document has been removed. */
+		  public void removeUpdate(DocumentEvent e) {
+				validateControls();
+		  }
+	 }
+
+	 private class ListSelectionListenerImpl
+		  implements ListSelectionListener {
+		  public void valueChanged(ListSelectionEvent event) {
+				GValueNode node = (GValueNode)list.getSelectedValue();
+				value.setText(Utility.stripNL(node.toString()));//formatPath(node.getPath(), false)));
+				value.setCaretPosition(0);
+		  }
+	 }
+
+    private class ValueListener
+		  implements TreeModelListener {
+		  /* Called when nodes have been modified, but the model hasn't changed.
+			* @param event Everything you ever wanted to know about model changes
+			* in one tidy TreeModelEvent package.
+			*/
+		  public void treeNodesChanged(TreeModelEvent event) {
+				update();
+		  }
+		  
+		  /* Called when nodes have been added to the model.
+			* @param event Everything you ever wanted to know about model changes
+			* in one tidy TreeModelEvent package.
+			*/
+		  public void treeNodesInserted(TreeModelEvent event) {
+				update();
+		  }
+		  
+		  /* Called when nodes have been removed from the model.
+			* @param event Everything you ever wanted to know about model changes
+			* in one tidy TreeModelEvent package.
+			*/
+		  public void treeNodesRemoved(TreeModelEvent event) {
+				update();
+		  }
+		  
+		  /** Called when nodes have been rearranged within the model.
+			* @param event Everything you ever wanted to know about model changes
+			* in one tidy TreeModelEvent package.
+			*/
+		  public void treeStructureChanged(TreeModelEvent event) {
+				update();
+		  }
+		  
+		  private void update() {
+				// Don't bother updating if the metaedit tab isn't selected.
+				if(Gatherer.g_man.getSelectedView() == Gatherer.g_man.metaedit_pane) {
+					 vm = null;
+					 vm = Gatherer.c_man.getCollection().msm.getValueTree((ElementWrapper)em.getSelectedItem());
+					 if(vm != null) {
+						  vm.addTreeModelListener(value_listener);
+					 }
+					 else {
+						  vm = new GValueModel(get("Not_Applicable"));
+					 }
+					 tree.setModel(vm);
+					 tree.repaint();
+				}
+		  }
+    }
+}
+
+
+
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/Build.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/Build.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/Build.java	(revision 13666)
@@ -0,0 +1,75 @@
+package org.greenstone.gsdl3.gs3build;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class Build
+{
+  BuildManager manager;
+
+  public Build(List inputRoots, String site, String collection, String outputDir)
+  { this.manager = new BuildManager(inputRoots, site, collection, outputDir);
+  }
+
+  public void run()
+  { this.manager.run();
+  }
+
+  public static void main(String args[])
+  { int a = 0;
+    List inputDirs = new ArrayList();
+    String collection = null;
+    String site = null;
+    String outputDir  = null;
+
+    while (a < args.length)
+    { System.out.println(args[a]);
+      if (args[a].equals("-inputdir")) {
+	if (a < args.length - 1 &&
+	    args[a+1].charAt(0) != '-')
+	{
+	  inputDirs.add(args[a+1]);
+	  a ++;	
+	}
+      }
+      else if (args[a].equals("-collect")) {
+	if (a < args.length - 1 &&
+	    args[a+1].charAt(0) != '-')
+	{
+	  collection = args[a+1];
+	  a ++;
+	}
+      }
+      else if (args[a].equals("-site")) {
+	if (a < args.length - 1 &&
+	    args[a+1].charAt(0) != '-')
+	{
+	  site = args[a+1];
+	  a ++;
+	}
+      }	  
+      else if (args[a].equals("-outputDir")) {
+	if (a < args.length - 1 &&
+	    args[a+1].charAt(0) != '-')
+	{ outputDir = args[a+1];
+	  a ++;
+	}
+      }
+      a ++;
+    }
+
+    if (site == null) {
+	System.err.println("you must specify the site name");
+	System.exit(0);
+    }
+    if (collection == null && inputDirs.size() == 0) {
+	System.err.println("At least one input directory must be given, or a collection name");
+	System.exit(0);
+    }
+    
+    Build build = new Build(inputDirs, site, collection, outputDir);
+    build.run();
+
+    return;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/BuildManager.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/BuildManager.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/BuildManager.java	(revision 13666)
@@ -0,0 +1,154 @@
+package org.greenstone.gsdl3.gs3build;
+
+import org.greenstone.gsdl3.gs3build.doctypes.*;
+import org.greenstone.gsdl3.gs3build.indexers.*;
+import org.greenstone.gsdl3.gs3build.notifier.NotifierManager;
+import org.greenstone.gsdl3.gs3build.extractor.*;
+import org.greenstone.gsdl3.gs3build.classifier.*;
+import org.greenstone.gsdl3.gs3build.collection.*;
+
+import java.io.File;
+import java.util.List;
+
+public class BuildManager 
+{
+    CollectionManager collectionManager;
+    RecogniserManager recogniserManager;
+    IndexerManager    indexerManager;
+    ClassifierManager classifierManager;
+    ExtractorManager  extractorManager;
+    NotifierManager   notifierManager;
+    DocumentList      docList;
+    List              inputRoots;
+    String            outputDir;
+    String            archiveDir;
+    
+    public BuildManager(List inputRoots, String site, String collection, String outputDir) 
+    {
+	// set up the collection manager
+	this.collectionManager = new CollectionManager(site, collection);
+	this.collectionManager.setBuildManager(this);
+	
+	// set up the list of input directories
+	if (inputRoots.size() == 0) {
+	    inputRoots.add(this.collectionManager.getImportDirectory());
+	    System.out.println("Adding collection import directory to input list " + this.collectionManager.getImportDirectory());
+	}
+	this.inputRoots = inputRoots;
+	
+	// set up the output directories (building and archive)
+	this.outputDir  = outputDir != null ? outputDir : this.collectionManager.getBuildDirectory();
+	File outputDirFile = new File(this.outputDir);
+	if (!outputDirFile.isDirectory()) {
+	    System.err.println("Unable to open directory " + this.outputDir + " for writing");
+	    System.exit(1);
+	}
+	System.out.println("Output directory set to " + this.outputDir);
+	
+	// set up the archive directory - this will definitely exist
+	this.archiveDir = this.collectionManager.getArchiveDirectory();
+
+	// the list that documents get added to when they are recognised
+	this.docList = new DocumentList(new DocumentIDFactory(this.collectionManager), 
+					this.collectionManager.getDatabase());
+	
+	// set up the various managers
+	this.recogniserManager = new RecogniserManager(this.docList);
+	this.extractorManager  = new ExtractorManager(this.docList);
+	this.classifierManager = new ClassifierManager(this.docList, collectionManager.getDatabase());
+	this.indexerManager = new IndexerManager(this.docList);
+	this.notifierManager = new NotifierManager();
+	
+	// configure the collection - this will add classifiers, indexers, recognisers to the various managers.
+	this.collectionManager.configureCollection();
+	
+	// add in expanders by hand cos they are not in the config file yet
+	// TODO
+	// add in extractors by hand cos they are not in the config file yet
+	this.extractorManager.addExtractor(new IndexExtractor());
+	this.extractorManager.addExtractor(new MetaXMLExtractor());
+	
+	// add in enrichers by hand cos they are not in the config file yet
+	// TODO
+		
+	// prepare a file crawler on the etc directory, and a crawl observer to respond to
+	// the appropriate files.
+	FileCrawler fileCrawler = new FileCrawler(new File(this.collectionManager.getEtcDirectory()), 
+						  new CollectionCrawlObserver(this));
+
+	fileCrawler.crawl();    
+    }
+  
+    public String getLastBuildSequence()
+    { 
+	return this.collectionManager.getCollectionMetadata("gsdl3", "buildsequence");
+    }
+
+    public ClassifierManager getClassifierManager()
+    { 
+	return this.classifierManager;
+    }
+
+    public IndexerManager getIndexerManager()
+    { 
+	return this.indexerManager;
+    }
+
+    // TODO: validation phase
+    public RecogniserManager getRecogniserManager()
+    {
+	return this.recogniserManager;
+    }
+    
+    public void addIndexer(IndexerInterface iface)
+    { 
+	iface.configure(IndexerManager.outputDir, this.outputDir);
+	this.indexerManager.addIndexer(iface);
+    }
+
+    public void run()
+    { 
+	// Initialise collection manager - note start of build
+	this.collectionManager.startBuild();
+	
+	// TODO: add expansion (e.g. Zip files)
+    
+	// Crawl the file tree - will recognise documents
+	for (int i = 0; i < this.inputRoots.size(); i ++) {
+	    FileCrawler fileCrawler = new FileCrawler(new File((String) this.inputRoots.get(i)), recogniserManager);
+
+	    fileCrawler.crawl();
+	}
+
+	// Extract phase, etc.
+	this.extractorManager.extractDocuments();
+	this.classifierManager.classifyDocuments();
+	this.indexerManager.indexDocuments();
+
+	// Timestamp management - update all timestamps on modified dates...
+	// 
+	// This should only occur at the end of building in case the build is cancelled...
+	docList.updateTimestamps(this.collectionManager.getBuildTimestamp());
+	
+	// TODO: validation phase
+	this.notifierManager.detectEvents(this.collectionManager);
+	
+	if (this.archiveDir != null) {
+	    this.docList.writeDocuments(new File(this.archiveDir));
+	    //this.docList.writeSQLDocuments(this.collectionManager.getDatabase());
+	}
+	
+	this.collectionManager.setCollectionMetadata("gsdl3", "documentCount", Integer.toString(this.docList.getCount()));
+    
+	// TODO: write out collection configuration file (service lists, etc.)
+    
+	this.collectionManager.endBuild();
+    }
+  
+    public void addInputDirectory(String inputDir)
+    {
+	this.inputRoots.add(inputDir);
+    }
+}
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/CollectionManager.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/CollectionManager.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/CollectionManager.java	(revision 13666)
@@ -0,0 +1,594 @@
+package org.greenstone.gsdl3.gs3build;
+
+import java.util.Date;
+import java.util.Calendar;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.GregorianCalendar;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.FileOutputStream;
+import java.io.BufferedWriter;
+import java.io.OutputStreamWriter;
+
+import java.net.URL;
+import java.net.URLEncoder;
+
+import java.sql.*;
+
+import javax.xml.parsers.*;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import org.greenstone.gsdl3.gs3build.database.*;
+import org.greenstone.gsdl3.gs3build.collection.*;
+import org.greenstone.gsdl3.gs3build.classifier.*;
+import org.greenstone.gsdl3.gs3build.indexers.*;
+import org.greenstone.gsdl3.gs3build.doctypes.RecogniserInterface;
+
+import org.greenstone.gsdl3.gs3build.util.DOMUtils;
+import org.greenstone.gsdl3.gs3build.util.URLTools;
+
+import org.greenstone.gsdl3.util.GSFile;
+import org.greenstone.gsdl3.util.GSXML;
+import org.greenstone.gsdl3.util.XMLConverter;
+
+/**
+ *  Store and hold collection-level configuration information for a collection.
+ *  This should be used by BuildManager to work out which classes, etc. to load
+ *  at build time, and as a repository for the collection-level metadata, and
+ *  a means of loading and saving the same to a file or database, as is seen
+ *  fit in the final development of gs3.
+ */
+
+public class CollectionManager
+{
+  GregorianCalendar  lastBuildDate;  // pretty obvious
+  String             adminEmail;     // the email address of the administrator of the
+		                     // collection
+  int                buildDocNo;     // used to generate document identifiers
+  CollectionMetadata metadata;       // collection-level metadata
+  GS3SQLConnection   database;       // the database to store everything in
+  String             collectionHome;
+  String             siteHome;
+  String             collectionName;
+  String             qualifiedCollectionName; // used as the database name 
+  String             notifyHost;
+
+  BuildManager       buildManager;
+   
+  class CollectionClassifier
+  { URL    file;
+    String type;
+    List fields;
+    String sort;
+    String className;
+
+    public CollectionClassifier(URL parentURL, String type, String className, Node node)
+    { this.type = type;
+      this.className = className;
+      this.fields = new ArrayList();
+
+      NodeList children = node.getChildNodes();
+      for (int c = 0; c < children.getLength(); c ++) {
+	Node child = children.item(c);
+
+	if (child.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
+	  String name = child.getNodeName();
+	  
+	  if (name.equals("file")) {
+	    NamedNodeMap atts = children.item(c).getAttributes();
+	    Node attribute = atts.getNamedItem("URL");
+	    String urlString = attribute.getNodeValue();
+	    if (urlString == null)
+	      continue;
+
+	    System.out.println("Path is" + parentURL.getPath());
+	    System.out.println("Host is" + parentURL.getHost());
+	    System.out.println(urlString);
+
+	    try {
+	      URL url = new URL(parentURL, urlString);
+	      this.file = url;
+	      System.out.println(url);
+	    }
+	    catch (java.net.MalformedURLException malEx) {
+	      System.out.println(malEx);
+	    }
+	  }
+	  else if (name.equals("field")) {
+	    String fieldName = DOMUtils.getNodeChildText(children.item(c));
+	    this.fields.add(fieldName.toString());
+	  }
+	  else if (name.equals("sort")) {
+	    String sortName = DOMUtils.getNodeChildText(children.item(c));
+	    this.sort = sortName;
+	  }
+	}
+      }
+    }
+
+    public ClassifierInterface getClassifier()
+    { ClassifierInterface classifier = null;
+
+      if (this.type == null) {
+	return null;
+      }
+      System.out.println("Creating a classifier of type " + this.type.toLowerCase());
+      
+      if (this.type.toLowerCase().equals("hierarchy")) {
+	System.out.println("  hierarchy file is " + this.file);
+	classifier = new HierarchyClassifier(this.className, this.file, this.fields, this.sort);
+      }
+      else if (this.type.toLowerCase().equals("azlist")) {
+	classifier = new AZListClassifier(this.className, this.fields);
+      }
+
+      return classifier;
+    }
+  }
+   
+  /**
+   *  Create the collection manager for a given collection
+   *
+   * @param site the name of the site
+   *  @param collection <code>String</code> the name of the collection
+   */
+  public CollectionManager(String site, String collection) {
+    
+    String gsdl3Root = System.getProperty("GSDL3HOME");
+    if (gsdl3Root == null) {
+      System.out.println("Error: Unable to locate GSDL3HOME");
+      System.exit(1);
+      //return;
+    }
+    
+    this.siteHome = GSFile.siteHome(gsdl3Root, site);
+    File site_dir = new File(this.siteHome);
+    System.out.println(site_dir);
+    if (!site_dir.exists()) {
+      System.out.println("Error: Non-existant site ("+site+") specified");
+      System.exit(1);
+    }
+    site_dir = null;
+    this.collectionHome = GSFile.collectionBaseDir(this.siteHome, collection);
+    
+    File collect_dir = new File(this.collectionHome);
+    if (!collect_dir.exists()) {
+      System.out.println("Error: Non-existant collection ("+collection+") specified in site "+site);
+      System.exit(1);
+    }
+    collect_dir = null;
+
+    this.collectionName = collection;
+    this.qualifiedCollectionName = site+"_"+collection;
+
+    this.database = GS3SQLConnectionFactory.getGS3SQLConnection(this.qualifiedCollectionName);
+    /*    if (this.database != null) {
+      this.database.clearCollection(collection);
+      this.database = null;
+    }
+    */
+    if (this.database == null) {
+	this.database = GS3SQLConnectionFactory.getGS3SQLConnection("test");
+	if (this.database == null) {
+	    System.err.println("Can't connect to the mysql database. Please make sure your mysql is running, and that the correct passwords (if any) are specified in "+gsdl3Root+"/WEB-INF/classes/global.properties");
+	    System.exit(1);
+	}
+	boolean success = this.database.initCollection(this.qualifiedCollectionName);
+	if (!success) {
+	    System.err.println("couldn't init collection " + this.qualifiedCollectionName);
+	    System.exit(1);
+	}
+    }
+
+    this.metadata = new CollectionMetadata();
+
+    File buildDirectory = new File(getBuildDirectory());
+    if (!buildDirectory.exists()) {
+      buildDirectory.mkdir();
+    }
+    if (!buildDirectory.isDirectory()) {
+	System.err.println("Unable to open directory " + buildDirectory + " for writing");
+	System.exit(1);
+    }
+
+    File archiveDirectory = new File(getArchiveDirectory());
+    if (!archiveDirectory.exists()) {
+      archiveDirectory.mkdir();
+    }
+    if (!archiveDirectory.isDirectory()) {
+	System.err.println("Unable to open directory " + archiveDirectory + " for writing");
+	System.exit(1);
+    }
+
+    this.buildDocNo = 1;
+
+    try {
+      GS3SQLSelect select = new GS3SQLSelect("build");
+      select.addField("*");
+      Statement statement = this.database.createStatement();
+      ResultSet results = statement.executeQuery(select.toString());
+      if (results.first()) {
+	System.out.println("Reading all keys");
+	do {
+	  String key = results.getString("buildKey");
+	  String value = results.getString("buildValue");
+
+	  if (key.equals("NextSeqNo")) {
+	    this.buildDocNo = Integer.parseInt(value);
+	  }
+	  else if (key.equals("lastBuildDate")) {
+	    int year, month, day;
+	    year = Integer.parseInt(value.substring(0, 4));
+	    month = Integer.parseInt(value.substring(4, 6)) - 1; // -1 because Gregorian Calendar perversely treats January as 0, etc.
+	    day = Integer.parseInt(value.substring(6, 8));
+	    
+	    this.lastBuildDate = new GregorianCalendar(year, month, day);
+	  }
+	} while (results.next());
+      }
+      statement.close();
+    }
+    catch (SQLException ex)
+      { System.out.println(ex);
+      }
+  }
+
+  public void setBuildManager(BuildManager build_man) 
+  { this.buildManager = build_man;
+  }
+
+  private void configureBrowsers(Node node, File etcFile)
+  { CollectionClassifier classifier = null;
+    URL etcURL = null;
+
+    etcURL = URLTools.getFileURL(etcFile);
+
+    NodeList children = node.getChildNodes();
+    for (int c = 0; c < children.getLength(); c ++)
+    { // assume that non-element children are irrelevant
+      if (children.item(c).getNodeType() != org.w3c.dom.Node.ELEMENT_NODE)
+      { continue;
+      }
+
+      String name = children.item(c).getNodeName();
+      System.out.println(name);
+
+      if (name.equals(GSXML.CLASSIFIER_ELEM))
+      { NamedNodeMap atts = children.item(c).getAttributes();
+
+        // get the type attribute
+	Node attribute = atts.getNamedItem(GSXML.TYPE_ATT);
+	if (attribute == null) {
+	  continue;
+	}
+	String type = attribute.getNodeValue();
+
+        // get the type attribute
+	attribute = atts.getNamedItem(GSXML.NAME_ATT);
+	if (attribute == null) {
+	  continue;
+	}
+	String className = attribute.getNodeValue();
+
+	classifier = new CollectionClassifier(etcURL, type, className, children.item(c));
+	
+	System.out.println("Found classifier " + type);
+	
+	// attach the classifier
+	ClassifierInterface classify = classifier.getClassifier();
+	this.buildManager.getClassifierManager().addClassifier(classify);
+      }  
+    }
+  }
+
+  public void configureCollection()
+  { File collectionConfig = new File(GSFile.collectionConfigFile(this.collectionHome));
+
+    // get the File and read it in
+    try
+    {
+      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+      DocumentBuilder builder = factory.newDocumentBuilder();
+      Document document = builder.parse(collectionConfig);
+
+      // TODO: report an error
+      if (document == null)
+      {	
+      }
+
+      // now parse the manager file...
+      Element rootElement = document.getDocumentElement();
+
+      if (rootElement.getTagName() != GSXML.COLLECTION_CONFIG_ELEM)
+      {	// TODO: throw exception
+      }
+
+      System.out.println("Configuring collection");
+
+      NodeList children = rootElement.getChildNodes();
+      for (int c = 0; c < children.getLength(); c ++)
+      {	// assume that non-element children are irrelevant
+	if (children.item(c).getNodeType() != org.w3c.dom.Node.ELEMENT_NODE)
+	{ continue;
+	}
+
+	String name = children.item(c).getNodeName();
+
+	// the name is a plugin element
+
+	if (name.equals(GSXML.RECOGNISE_ELEM)) {
+	    System.out.println("recognise elem");
+	    
+	    NodeList doc_types = ((Element)children.item(c)).getElementsByTagName(GSXML.DOC_TYPE_ELEM);
+	    for(int i=0; i<doc_types.getLength(); i++) {
+		Element doc_type = (Element)doc_types.item(i);
+		String type = doc_type.getAttribute(GSXML.NAME_ATT);
+		System.err.println("adding recogniser, type "+type);
+		RecogniserInterface ri = this.buildManager.getRecogniserManager().addRecogniser(type);
+		if (ri != null) {
+		    ri.configure(doc_type);
+		}
+	    }
+	} else if (name.equals(GSXML.SEARCH_ELEM)) {
+	  // pick up attributes from the <search> tag now...
+	  NamedNodeMap searchAttributes = children.item(c).getAttributes();
+	  Node searchAttribute = searchAttributes.getNamedItem(GSXML.TYPE_ATT);
+	  String searchType = null;
+	  if (searchAttribute != null) {
+	      searchType = searchAttribute.getNodeValue();
+	  } else {
+	      System.out.println("no "+GSXML.TYPE_ATT+" attribute found for the "+GSXML.SEARCH_ELEM+" element, assuming mg");
+	      searchType = MGIndexer.MG_INDEX_TYPE;
+	  }
+	  
+	  searchAttribute = searchAttributes.getNamedItem(GSXML.NAME_ATT);
+	  String searchName = null;
+	  if (searchAttribute != null) {
+	      searchName = searchAttribute.getNodeValue();
+	  }
+	  if (searchName == null) {
+	      searchName = "idx"; // need to modify this if we have two search elements with no names
+	  }
+	  // create the pertinent indexer...
+	  IndexerInterface indexer = IndexerFactory.makeIndexer(searchType, searchName);
+
+	  if (indexer == null) {
+	    continue;
+	  }
+
+	  // configure the indexer
+	  indexer.configure(children.item(c));
+
+	  // install it into the build manager
+	  this.buildManager.addIndexer(indexer);
+	}
+	else if (name.equals(GSXML.BROWSE_ELEM))
+	{ this.configureBrowsers(children.item(c), collectionConfig);
+	}
+	else if (name.equals(GSXML.NOTIFY_ELEM))
+	{
+	    this.notifyHost = ((Element) children.item(c)).getAttribute(GSXML.NOTIFY_HOST_ATT);
+	}
+	// TODO: other elements - make a factory-method approach here...
+	else
+	{
+	}
+      }
+    }
+    catch (FactoryConfigurationError e) {
+      System.out.println(e);
+    }
+    catch (ParserConfigurationException ex) {
+      System.out.println(ex);
+    }
+    catch (SAXException ex) {
+      System.out.println(ex);
+    }
+    catch (IOException ex)
+    {
+      System.out.println(ex);
+    }
+
+    System.out.println("<<<Obtaining database>>>>");
+  }
+
+  public String getEtcDirectory()
+  { return GSFile.collectionEtcDir(this.collectionHome);
+  }
+
+  public String getImportDirectory()
+  { return GSFile.collectionImportDir(this.collectionHome);
+  }
+
+  public String getBuildDirectory()
+  { return GSFile.collectionBuildDir(this.collectionHome);
+  }
+
+  public String getArchiveDirectory()
+  { return GSFile.collectionArchiveDir(this.collectionHome);
+  }
+
+  public GS3SQLConnection getDatabase()
+  {
+    return this.database;
+  }
+
+  public long getBuildTimestamp()
+  { return this.lastBuildDate.getTime().getTime();
+  }
+
+  public Date getBuildDate()
+  { return this.lastBuildDate.getTime();
+  }
+
+  public void startBuild()
+  { GregorianCalendar today = new GregorianCalendar();
+  
+    if (this.lastBuildDate != null)
+    { // if the build date is different to the last build date, then reset the build
+      // document number
+      if (today.get(Calendar.YEAR) != this.lastBuildDate.get(Calendar.YEAR) ||
+	  today.get(Calendar.MONTH) != this.lastBuildDate.get(Calendar.MONTH) ||
+	  today.get(Calendar.DAY_OF_MONTH) != this.lastBuildDate.get(Calendar.DAY_OF_MONTH))
+      { this.buildDocNo = 1;
+      }
+      else 
+      { System.out.println("Continuing build sequence from " + this.buildDocNo);
+      }
+    }
+    this.lastBuildDate = today;
+  }
+
+  public void endBuild()
+  {
+    // here we write out the build config file
+    // create the xml for the buildConfig
+    XMLConverter converter = new XMLConverter();
+    Document doc = converter.newDOM();
+    Element build_config = doc.createElement(GSXML.COLLECTION_BUILD_ELEM);
+    Element meta_list = doc.createElement(GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER);
+    build_config.appendChild(meta_list);
+    Element service_list = doc.createElement(GSXML.SERVICE_CLASS_ELEM+GSXML.LIST_MODIFIER);
+    build_config.appendChild(service_list);
+    
+    // ask the indexers and classifiers to add stuff into the service rack list
+    this.buildManager.getIndexerManager().addServiceDescriptions(service_list);
+    this.buildManager.getClassifierManager().addServiceDescriptions(service_list);
+    // get the String
+    String build_config_string = converter.getString(build_config);
+    // write it to the file
+    try {
+      File build_config_file = new File(GSFile.collectionBuildConfigFileBuilding(this.collectionHome));
+      BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(build_config_file), "UTF-8"));
+      writer.write(build_config_string, 0, build_config_string.length());
+      writer.close();
+    } catch (Exception e) {
+      System.err.println("CollectionManager.endBuild() Error while trying to output the buildConfig.xml file.");
+      System.err.println(e.getMessage());
+    }
+    
+    // Update build date information
+    try {
+      GS3SQLDelete remove = new GS3SQLDelete("build");
+      //    GS3SQLWhere where = new GS3SQLWhere(new GS3SQLWhereItem("buildKey", "=", "NextSeqNo"));
+      //    rem
+      Statement statement = this.database.createStatement();
+      statement.execute(remove.toString());
+      
+      GS3SQLInsert insert = new GS3SQLInsert("build");
+      insert.addValue("buildKey", "NextSeqNo");
+      insert.addValue("buildValue", Integer.toString(this.buildDocNo));
+      statement.execute(insert.toString());
+    
+      insert = new GS3SQLInsert("build");
+      insert.addValue("buildKey", "lastBuildDate");
+      insert.addValue("buildValue", getDateString(this.lastBuildDate));
+      statement.execute(insert.toString());
+      statement.close();
+    } catch (SQLException e) {
+	System.err.println("CollectionManager.endBuild(): Can't update build information: "+e);
+    }
+    
+    // Do tail of build output
+    Date startDate = this.lastBuildDate.getTime();
+    Date date = new Date();
+
+    long startTime = startDate.getTime();
+    long endTime   = date.getTime();
+
+    long difference = ((endTime - startTime) + 500) / 1000;
+
+    System.out.println("Build completed");
+    System.out.println("---------------");
+    System.out.println("Total Documents: " + this.getCollectionMetadata("gsdl3", "documentCount"));
+    System.out.println("Total Time :     " + (difference / 60) + " min. " + (difference % 60) + " secs.");
+  }
+
+  private static String getDateString(GregorianCalendar date)
+  { StringBuffer dateString = new StringBuffer();
+  
+    int value;
+    dateString.append(date.get(Calendar.YEAR));
+
+    // the use of month is a little odd, hence the following
+    // code.  Calendar.MONTH yields 0 = January, 1 = February,
+    // etc. hence there is a '+1' added to the month to make 
+    // it into January = 1, etc., and the padding is altered
+    // correspondingly.
+    value = date.get(Calendar.MONTH);
+    if (value < 9)
+    { dateString.append("0");
+    }
+    dateString.append(value + 1);
+    value = date.get(Calendar.DAY_OF_MONTH);
+    if (value < 10)
+      dateString.append("0");
+    dateString.append(value);
+
+    return dateString.toString();
+  }
+
+
+  public String getNextDocumentID()
+  { StringBuffer ID = new StringBuffer(getDateString(this.lastBuildDate));
+
+    int value = this.buildDocNo;
+    this.buildDocNo ++;
+    
+    ID.append(":");
+    ID.append(Integer.toString(value));
+    return ID.toString();
+  }
+  
+  public int getDocumentNumber()
+  { this.buildDocNo ++;
+    return this.buildDocNo - 1;
+  }
+
+  /**
+   *  Get the collection metadata item in the given namespace
+   *
+   *  @param <code>String</code> the namespace
+   *  @param <code>String</code> the label of the metadata
+   */
+  public String getCollectionMetadata(String namespace, String label)
+  { return this.metadata.getCollectionMetadata(namespace, label).get(0).toString();
+  }
+
+  /**
+   *  Set the collection metadata item in the given namespace
+   *
+   *  @param <code>String</code> the namespace
+   *  @param <code>String</code> the label
+   *  @param <code>String</code> the value
+   */
+  public void setCollectionMetadata(String namespace, String label, String value)
+  { this.metadata.setCollectionMetadata(namespace, label, value);
+  }
+  
+  public String getCollectionName() {
+      return collectionName;
+  }
+
+/**
+ * @return
+ */
+public String getNotifyHost() {
+    return notifyHost;
+}
+}
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/Create.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/Create.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/Create.java	(revision 13666)
@@ -0,0 +1,116 @@
+package org.greenstone.gsdl3.gs3build;
+
+import java.io.File;
+import org.greenstone.gsdl3.util.GSFile;
+
+public class Create
+{
+    String gsdl3_home = null;
+    String gsdl3_srchome = null;
+    String site = null;
+    String site_home = null;
+    String collection = null;
+
+    public Create(String gsdl3_home, String gsdl3_srchome, String site, 
+		  String collection)
+    { 
+	this.gsdl3_home = gsdl3_home;
+	this.gsdl3_srchome = gsdl3_srchome;
+	this.site = site;
+	this.site_home = GSFile.siteHome(gsdl3_home, site);
+	this.collection = collection;
+
+	// check the site's collect directory
+	File site_collect = new File(GSFile.collectDir(this.site_home));
+	if (!site_collect.isDirectory()) {
+	    System.err.println("Site's collect directory "+site_collect.getPath()+" doesn't exist. Please create it and try again");
+	    System.exit(1);
+	}
+
+       	
+    }
+    
+    public void makeCollection() {
+	
+	String coll_home = GSFile.collectionBaseDir(this.site_home, this.collection);
+	File coll_dir_file = new File(coll_home);
+	if (coll_dir_file.exists()) {
+	    System.err.println("Collection directory ("+coll_dir_file.getPath()+") already exists, not creating it.");
+	    System.exit(1);
+	}
+	createDirectory(coll_dir_file);
+	createDirectory(new File(GSFile.collectionImportDir(coll_home)));
+	createDirectory(new File(GSFile.collectionEtcDir(coll_home)));
+
+	File config_template = new File(gsdl3_srchome + File.separator+ "resources"+File.separator + "xml"+File.separator+"collectionConfig.xml");
+	if (!config_template.isFile()) {
+	    System.err.println("Couldn't find the config file template "+config_template.getPath());
+	    System.exit(1);
+	}
+
+	File coll_config = new File(GSFile.collectionConfigFile(coll_home));
+	GSFile.copyFile(config_template, coll_config);
+
+	System.err.println("New collection created in "+coll_home);
+	System.err.println("Put source documents into import, set the collection's configuration in etc/collectionConfig.xml, then run \"gs3-build.(sh|bat) "+ this.site+" "+this.collection+"\" to build the collection");
+    }
+
+    protected void createDirectory(File dir) {
+	dir.mkdir();
+	if (!dir.isDirectory()) {
+	    System.err.println("Couldn't create directory "+dir.getPath());
+	    System.exit(1);
+	}
+    }
+
+    public static void main(String args[])
+    { 
+	String gsdl3_home = System.getProperty("GSDL3HOME");
+	String gsdl3_srchome = System.getProperty("GSDL3SRCHOME");
+	if (gsdl3_home == null) {
+	    System.out.println("Error: Unable to locate GSDL3HOME");
+	    System.exit(1);
+	}
+	if (gsdl3_srchome == null) {
+	    System.out.println("Error: Unable to locate GSDL3SRCHOME");
+	    System.exit(1);
+	}
+
+	int a = 0;
+	String collection = null;
+	String site = null;
+	
+	while (a < args.length) {
+	    if (args[a].equals("-collect")) {
+		if (a < args.length - 1 &&
+		    args[a+1].charAt(0) != '-') {
+		    
+			collection = args[a+1];
+			a ++;
+		}
+	    } else if (args[a].equals("-site")) {
+		if (a < args.length - 1 &&
+		    args[a+1].charAt(0) != '-') {
+		    
+		    site = args[a+1];
+		    a ++;
+		}
+	    }
+	    a ++;
+	}
+	
+	if (site == null) {
+	    
+	    System.err.println("you must specify the site name");
+	    System.exit(0);
+	}
+	if (collection == null) {
+	    System.err.println("you must specify a collection");
+	    System.exit(0);
+	}
+    
+	Create c = new Create(gsdl3_home, gsdl3_srchome, site, collection);
+	c.makeCollection();
+	return;
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/FileCrawlObserver.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/FileCrawlObserver.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/FileCrawlObserver.java	(revision 13666)
@@ -0,0 +1,8 @@
+package org.greenstone.gsdl3.gs3build;
+
+import java.io.File;
+
+public interface FileCrawlObserver
+{
+	public void processFile(File file);
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/FileCrawler.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/FileCrawler.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/FileCrawler.java	(revision 13666)
@@ -0,0 +1,39 @@
+package org.greenstone.gsdl3.gs3build;
+
+import java.io.File;
+
+public class FileCrawler
+{
+  File root;
+  FileCrawlObserver observer;
+
+  public FileCrawler(File file, FileCrawlObserver observer)
+  { this.root = file;
+    this.observer = observer;
+  }
+
+  public void crawl()
+  { this.crawlDirectory(this.root);
+  }
+
+  public boolean crawlDirectory(File file)
+  {
+    File [] children = file.listFiles();
+
+    if (children == null) {
+      return true;
+    }
+
+    for (int c = 0; c < children.length; c ++) {
+      if (children[c].isDirectory()) {
+	crawlDirectory(children[c]);
+      }
+      else
+      {
+	// TODO: process file
+	this.observer.processFile(children[c]);
+      }
+    }
+    return true;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/GSDataDump.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/GSDataDump.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/GSDataDump.java	(revision 13666)
@@ -0,0 +1,20 @@
+package org.greenstone.gsdl3.gs3build;
+
+import java.io.File;
+
+import org.greenstone.gsdl3.gs3build.doctypes.*;
+
+import org.greenstone.gsdl3.gs3build.database.GS3SQLConnection;
+import org.greenstone.gsdl3.gs3build.database.GS3SQLConnectionFactory;
+
+public class GSDataDump
+{ 
+  public static void main(String args[])
+  {
+    String database = args[0];
+
+    GS3SQLConnection connection = GS3SQLConnectionFactory.getGS3SQLConnection(database);
+    DocumentList docList = DocumentList.readSQLDocuments(connection);
+    docList.writeDocuments(new File(database));
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/AZListClassifier.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/AZListClassifier.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/AZListClassifier.java	(revision 13666)
@@ -0,0 +1,356 @@
+package org.greenstone.gsdl3.gs3build.classifier;
+
+import java.io.*;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.xml.sax.XMLReader;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.Attributes;
+import org.xml.sax.helpers.XMLReaderFactory;
+import org.xml.sax.helpers.DefaultHandler;
+
+import org.w3c.dom.Element;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+import org.greenstone.gsdl3.gs3build.util.XMLTools;
+import org.greenstone.gsdl3.gs3build.database.*;
+import org.greenstone.gsdl3.gs3build.util.MultiMap;
+import org.greenstone.gsdl3.util.GSXML;
+
+public class AZListClassifier extends AbstractClassifier
+{
+  GS3SQLConnection database;
+  MultiMap         alphaMap;
+  List             fields;
+  String           name;
+
+  class AZDocumentItem
+  { public DocumentID documentId;
+    public String     title;
+
+    public AZDocumentItem(DocumentID documentId, String title)
+    { this.documentId = documentId;
+      this.title = title;
+    }
+
+    public String getTitle()
+    { return this.title;
+    }
+
+    public DocumentID getID()
+    { return this.documentId;
+    }
+
+    public String toString()
+    { return this.title;
+    }
+  }
+
+  private void sortList(String key)
+  { List list = this.alphaMap.getAll(key);
+    if (list.size() > 1) {
+      int first, last;
+
+      first = 0;
+      last = list.size() - 1;
+      while (first != last)
+      { int at = (first + last) / 2;
+
+        if (list.get(at).toString().compareTo(list.get(list.size() - 1).toString()) > 0) {
+	  last = at;
+        }
+	else {
+	  first = at + 1;
+	}
+      }
+
+      Object newObject = list.get(list.size()-1);
+      last = list.size() - 1;
+      while (last > first) {
+	list.set(last, list.get(last-1));
+	last --;
+      }
+      list.set(first, newObject);
+    }
+  }
+
+  public AZListClassifier(String name, List fields)
+  { this.fields   = fields;
+    this.alphaMap = new MultiMap();
+    this.name     = name;
+    //  System.out.println("AZList :"+fields.size());
+  }
+
+  public AZListClassifier()
+  { this.fields = new ArrayList();
+  }
+
+  public void configure(List parameters)
+  {
+    Iterator iterator = parameters.iterator();
+    while (iterator.hasNext()) {
+      String param = iterator.next().toString();
+      if (param.equals("-metadata")) {
+	if (iterator.hasNext()) {
+	  String field = iterator.next().toString();
+	  if (field != null && field.length() > 0) {
+	    this.fields.add(field);
+	  }
+	}
+      }
+    }
+  }
+
+  public void setDatabase(GS3SQLConnection connection)
+  { this.database = connection;
+  }
+
+  public boolean classifyDocument(DocumentID documentID, DocumentInterface document)
+  { // get the metadata item from the document
+    Iterator thisField = this.fields.iterator();
+
+    // for every field listed as being a scannable field...
+    while (thisField.hasNext())
+    { String fieldName = thisField.next().toString();
+			
+      // ...get the values for that field...
+      List values = document.getDocumentMetadataItem(fieldName);
+
+      if (values == null)
+      {	continue;
+      }
+
+      // ...and send them to the classifier
+      Iterator thisValue = values.iterator();
+      while (thisValue.hasNext()) 
+      { String value = thisValue.next().toString();
+
+	String classText = null;
+
+	int c = 0;
+	while (c < value.length() && classText == null)
+	{ if (Character.isDigit(value.charAt(c))) 
+	  { classText = "0-9";
+	  }
+	  else if (Character.isLetter(value.charAt(c))) 
+	  { classText = value.substring(c, c+1).toLowerCase();
+	  }
+  	  c ++;
+	}
+
+	if (classText != null) {
+	    //	  System.out.println(classText + " " + documentID);
+	  this.alphaMap.put(classText, new AZDocumentItem(documentID, value));
+	  this.sortList(classText);
+	}
+      }
+    }
+
+    return true;    
+  }
+
+  public void startClassifierPass(int pass)
+  {
+  }
+
+  public int getClassifierPasses()
+  { return 1;
+  }
+
+  public void endClassifierPass(int pass)
+  {
+  }
+
+  public void completeClassification()
+  { this.writeSQL(this.database);
+  }
+
+  public int writeSQLClassifyNode(GS3SQLConnection connection, String parentId, int orderRef,
+				  String label, String name, String description, int noOfLeafDocs)
+  { GS3SQLAction action;
+    GS3SQLSelect select;
+    GS3SQLInsert insert;
+  
+    int classifyRef;
+
+    // check for existing node
+    select = new GS3SQLSelect("classifiers");
+    select.addField("ClassifyRef");
+    GS3SQLWhereItem whereItem = new GS3SQLWhereItem("ClassifyID", "=", label);
+    GS3SQLWhere where = new GS3SQLWhere(whereItem);
+    select.setWhere(where);
+
+
+    try {
+      Statement statement = connection.createStatement();
+      ResultSet results = statement.executeQuery(select.toString());
+      if (results.first()) {
+	GS3SQLUpdate update = new GS3SQLUpdate("classifiers");
+	update.setWhere(where);
+	action = update;
+ 
+	classifyRef = results.getInt("ClassifyRef");
+      }
+      else {
+	insert = new GS3SQLInsert("classifiers");
+
+	insert.addValue("ParentID", parentId);
+
+	action = insert;
+	classifyRef = -1;
+      }
+      action.addValue("ClassifyID", label);
+      action.addValue("Name", name);
+      action.addValue("Description", description);
+      action.addValue("ClassifyOrder", Integer.toString(orderRef), GS3SQLField.INTEGER_TYPE);
+      action.addValue("NumLeafDocs", Integer.toString(noOfLeafDocs), GS3SQLField.INTEGER_TYPE);
+
+      // do the update/insert
+      statement.execute(action.toString());
+
+
+      // get the ClassifyRef if we don't already have it (have done a
+      // insert action above)...
+      if (classifyRef == -1) {
+	results = statement.executeQuery(select.toString());
+	if (!results.first()) {
+	  return -1;
+	}
+	
+	classifyRef = results.getInt("ClassifyRef");
+      }
+      
+      statement.close();
+    }  catch (SQLException sqlEx) {
+	System.err.println("AZListClassifier.writeSQLClassifyNode(): "+sqlEx);
+	return -1;
+    }
+  
+
+    return classifyRef;
+  }
+
+  public boolean writeSQL(GS3SQLConnection connection)
+  { GS3SQLAction action;
+    GS3SQLSelect select;
+    GS3SQLInsert insert;
+ 
+    Iterator keys;
+ 
+    String prefix = this.name;
+    if (prefix==null || prefix.equals("")) {
+	prefix = "CLAZ"+this.fields.get(0).toString();
+	// TODO: write this name back to collectionConfig.xml
+	this.name = prefix;
+    }
+
+    int leafCount = 0;
+    keys = this.alphaMap.keySet().iterator();
+    while (keys.hasNext()) {
+      Object key = keys.next();
+
+      List childDocs = (List) this.alphaMap.getAll(key);
+      if (childDocs != null) {
+	leafCount += childDocs.size();
+      }
+    }
+
+    int parentClassify = this.writeSQLClassifyNode(connection, "", 0, prefix, "", "Classifier", leafCount);
+
+    if (parentClassify < 0) 
+    { return false;
+    }
+
+    try {
+	Statement statement = connection.createStatement();
+    
+    List children;
+    
+    // TODO: cope with change rather than create from scratch...
+    int nodeOrder = 1;
+    keys = this.alphaMap.keySet().iterator();
+    while (keys.hasNext()) {
+      Object key = keys.next();
+
+      List childDocs = (List) this.alphaMap.getAll(key);
+
+      if (childDocs != null) {
+	String className = prefix + "." + key.toString();
+
+	int classifyRef = this.writeSQLClassifyNode(connection, prefix, nodeOrder, className, key.toString(), key.toString(), childDocs.size());
+
+	// note the child documents...
+        Iterator iterator = childDocs.iterator();
+	int childOrder = 1;
+	//St
+	while (iterator.hasNext()) {
+	  AZDocumentItem documentItem = (AZDocumentItem) iterator.next();
+	  DocumentID docId = documentItem.getID();
+
+	  insert = new GS3SQLInsert("classdocuments");
+	  insert.addValue("ClassifyRef", Integer.toString(classifyRef), GS3SQLField.INTEGER_TYPE);
+	  insert.addValue("DocID", docId.toString());
+	  insert.addValue("DocOrder", Integer.toString(childOrder), GS3SQLField.INTEGER_TYPE);	  
+
+	  statement.execute(insert.toString());
+
+	  childOrder ++;
+	}
+
+	nodeOrder ++;
+      }
+    }
+
+   
+    /*
+    else {
+      // TODO: clear 'dead' child classifications
+
+      // delete child documents
+      GS3SQLDelete delete = new GS3SQLDelete("classdocuments");
+      delete.setWhere(where);
+
+      statement.execute(delete.toString());
+    }
+
+    // post the child nodes...
+    Iterator iterator = this.childNodes.iterator();
+    while (iterator.hasNext()) {
+      AbstractHierarchyNode childNode = (AbstractHierarchyNode) iterator.next();
+
+      if (!childNode.writeSQL(connection)) {
+	return false;
+      }
+    }
+    */
+    statement.close();
+    } catch (SQLException e) {
+	System.err.println("AZListClassifier.writeSQL(): "+e);
+	return false;
+    }
+
+    return true;
+  }
+    public boolean addClassifierDescription(Element classifier_list) {
+	// TODO check that there are some docs in the classification
+	Element classifier = classifier_list.getOwnerDocument().createElement(GSXML.CLASSIFIER_ELEM);
+	classifier.setAttribute(GSXML.NAME_ATT, this.name);
+	classifier_list.appendChild(classifier);
+	return true;
+    }
+
+}
+
+
+
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/AbstractClassifier.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/AbstractClassifier.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/AbstractClassifier.java	(revision 13666)
@@ -0,0 +1,61 @@
+package org.greenstone.gsdl3.gs3build.classifier;
+
+import java.io.*;
+
+import java.net.URL;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+import org.greenstone.gsdl3.gs3build.util.DOMUtils;
+
+public abstract class AbstractClassifier implements ClassifierInterface
+{ public AbstractClassifier()
+  {
+  }
+
+  public void configure(URL parentURL, org.w3c.dom.Node node)
+  { NodeList children = node.getChildNodes();
+    for (int c = 0; c < children.getLength(); c ++) {
+      Node child = children.item(c);
+      
+      if (child.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
+	String name = child.getNodeName();
+	
+	if (name.equals("file")) {
+	  NamedNodeMap atts = children.item(c).getAttributes();
+	  Node attribute = atts.getNamedItem("URL");
+	  String urlString = attribute.getNodeValue();
+	  if (urlString == null)
+	    continue;
+	  
+	  try {
+	    URL url = new URL(parentURL, urlString);
+	    //	    this.file = url;
+	    System.out.println(url);
+	  }
+	  catch (java.net.MalformedURLException malEx) {
+	    System.out.println(malEx);
+	  }
+	}
+	else if (name.equals("field")) {
+	  String fieldName = DOMUtils.getNodeChildText(children.item(c));
+	  System.out.println("Adding field " + fieldName);
+	  //	  this.fields.add(fieldName.toString());
+	}
+	else if (name.equals("sort")) {
+	  String sortName = DOMUtils.getNodeChildText(children.item(c));
+	  //	  this.sort = sortName;
+	}
+      }
+    }
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/AbstractHierarchyNode.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/AbstractHierarchyNode.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/AbstractHierarchyNode.java	(revision 13666)
@@ -0,0 +1,428 @@
+package org.greenstone.gsdl3.gs3build.classifier;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+
+import org.greenstone.gsdl3.gs3build.database.*;
+
+public abstract class AbstractHierarchyNode
+{
+  String prefix;        // a basic prefix used in this hierarchy
+  String descriptor;    // the textual descriptor used on screen or long-hand
+  String name;          // the index number, letter assignment or other item
+                        //   used to identify the position of the item in the
+                        //   hierarchy
+  String id;            // an identifier used by the GLI for maintenance
+                        //   purposes; this plays no active role in the
+                        //   rebuilding process (at the moment)
+  List childNodes;      // the child classification nodes of this node
+  List childDocs;       // the child documents of this node
+  List matches;         // the other metadata values that may be matched
+                        //   against the classifier
+  AbstractHierarchyNode parent; // the parent of the node
+
+  class AbstractHierarchyDocument
+  { DocumentID documentId;
+    String     sortKey;
+
+    public AbstractHierarchyDocument(DocumentID documentId, String sortKey)
+    { this.documentId = documentId;
+      this.sortKey    = sortKey;
+    }
+
+    public DocumentID getID()
+    { return this.documentId;
+    }
+
+    public String toString()
+    { return this.sortKey;
+    }
+  } 
+
+  /**
+   *  Simple node
+   */
+  public AbstractHierarchyNode()
+  { this.descriptor = "";
+    this.name       = "";
+    this.id         = "";
+    this.prefix     = "";
+    this.childNodes = new ArrayList();
+    this.childDocs  = new ArrayList();
+    this.parent     = null;
+    this.matches    = new ArrayList();
+  }
+    
+  public AbstractHierarchyNode(String prefix, String name, String id, String descriptor)
+  { this.descriptor = descriptor;
+    this.name       = name;
+    this.id         = id;
+    this.prefix     = prefix;
+    this.childNodes = new ArrayList();
+    this.childDocs  = new ArrayList();
+    this.parent     = null;
+    this.matches    = new ArrayList();
+    this.matches.add(this.id);
+    this.matches.add(this.name);
+  }
+    
+  public void addChild(AbstractHierarchyNode child)
+  { this.childNodes.add(child);
+    child.setParent(this);
+
+    /**
+    if (this.id == null) {
+      System.out.println(child.id.toString() + " added to root");
+    }
+    else {
+      System.out.println(child.id.toString() + " added to " + this.id);
+    }
+    */
+  }
+
+  public boolean add(AbstractHierarchyNode child)
+  { if (this.id != null && this.id.length() > 0 &&
+        !child.id.startsWith(this.id + "."))
+    { return false;
+    }
+
+    Iterator subNodes = this.childNodes.iterator();
+    while (subNodes.hasNext()) {
+      AbstractHierarchyNode subNode = (AbstractHierarchyNode) subNodes.next();
+      
+      if (subNode.add(child)) {
+	return true;
+      }
+    }
+    
+    this.addChild(child);
+    return true;
+  }
+
+  public void addDocument(DocumentID document, String sortKey)
+  { if (sortKey == null && false) {
+    System.err.println("attempt to classify by an unset key");
+      return;
+    }
+    this.childDocs.add(new AbstractHierarchyDocument(document, sortKey));
+
+    System.out.println("Adding " + document.toString() + " to " + this.name + " " + this.childDocs.size());
+    if (sortKey != null) {
+      int first = 0;
+      int last  = this.childDocs.size() - 1;
+
+      while (first != last) {
+	int at = (first + last) / 2;
+	
+	System.out.println(this.name + " " + at + " " + this.childDocs.size() + " " + this.childDocs.get(at) + " " + sortKey);
+	if (this.childDocs.get(at) == null ||
+	    this.childDocs.get(at).toString() == null) {
+	  last = at;
+	  System.out.println("COntinuing");
+	  continue;
+	}
+
+	if (this.childDocs.get(at).toString().compareTo(sortKey) > 0) {
+	  last = at;
+	}
+	else {
+	  first = at + 1;
+	}
+      }
+
+      Object newItem = this.childDocs.get(this.childDocs.size() - 1);
+      last = this.childDocs.size() - 1;
+      while (last > first) {
+	this.childDocs.set(last, this.childDocs.get(last-1));
+	last --;
+      }
+      this.childDocs.set(first, newItem);
+    }
+
+    //  System.out.println("Added " + document.toString() + " to " + this.name + " " + this.childDocs.size());
+    //    for (int a = 0; a < this.childDocs.size(); a ++) {
+    //System.out.println(this.childDocs.get(a));
+    //}
+  }
+
+  public void setParent(AbstractHierarchyNode parent)
+  { this.parent = parent;
+  }
+    
+  public AbstractHierarchyNode getParent()
+  { return this.parent;
+  }
+
+  public String getParentId()
+  { 
+    if (this.id == null) {
+      return "";
+    }
+
+    int dotAt = this.id.lastIndexOf('.');
+    if (dotAt < 0) {
+      return "";
+    }
+    return this.id.substring(0, dotAt);
+  }  
+
+  public void setDescriptor(String descriptor)
+  { this.descriptor = descriptor;
+  }
+
+  public void setID(String id)
+  { this.id = id;
+    this.matches.add(id);
+  }
+
+  public String getID()
+  { return this.id;
+  }
+
+  public int noOfChildDocs()
+  { return this.childDocs.size();
+  }
+
+  public int noOfLeafDocs()
+  { int total = this.childDocs.size();
+
+    Iterator iterator = this.childNodes.iterator();
+    while (iterator.hasNext()) {
+      AbstractHierarchyNode childNode = (AbstractHierarchyNode) iterator.next();
+
+      total += childNode.noOfLeafDocs();
+    }
+
+    return total;
+  }
+
+  /**
+   *  Set the name for this hierarchy node - i.e. its brief description
+   *
+   *  @param <code>String</code> the new node name.
+   */
+  public void setName(String name)
+  { this.name = name;
+    this.matches.add(name);
+  }
+
+  /**
+   *  Get the name for this hierarchy node - i.e. its brief description
+   *
+   *  @return <code>String</code> the node's name.
+   */
+  public String getName()
+  { return this.name;
+  }
+
+  /**
+   *  Add another string which can be used to describe this hierarchy node - i.e. one which if
+   *  found in a document would indicate that that document belongs to this hierarchy node.
+   *
+   *  @param <code>String</code> the string to match.
+   */
+  public void addMatch(String match)
+  { this.matches.add(match);
+  }
+
+  /**
+   *  Check if a given string matches any of the values given for this hierarchy node...
+   *
+   *  @param <code>String</code> the descriptive string to be compared against the hierarchy
+   *  @return <code>boolean</code> <code>true</code> whether the string matches this hierarchy
+   */
+  public boolean isMatch (String toMatch)
+  { Iterator thisMatch = this.matches.iterator();
+			
+    while (thisMatch.hasNext())
+    { String thisMatchText = thisMatch.next().toString();
+      
+      if (thisMatchText.equals(toMatch))
+      { return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   *  Take a document, and find the classifications that it matches against in
+   *  the current hierarchy.  
+   *
+   *  @param <code>DocumentID</code> the id of the document being classified
+   *  @param <code>List</code> the values against which the classifier should
+   *         test for the document being a match - i.e. the pertinent document
+   *         property values.
+   *  @param <code>ClassifierObserverInterface</code>
+   *         object modifies the document with information about the
+   *         classifications that it fell within.
+   */
+  abstract public void getClassifications(DocumentID documentID, List values, String sortKey,
+					  ClassifierObserverInterface observer);
+
+  public boolean writeSQL(GS3SQLConnection connection)
+  {
+    int classifyRef;
+    GS3SQLAction action = null;
+    GS3SQLSelect select;
+    GS3SQLInsert insert;
+
+    Statement statement;
+    // can we connect to the database?
+    try {
+	statement = connection.createStatement();
+    } catch (SQLException e) {
+	System.err.println("AbstractHierarchyNode.writeSQL(): "+e);
+	return false;
+    }
+    
+    // Get own full id
+    String fullId = this.id.length() > 0 ? this.prefix+"."+this.id : this.prefix;
+
+    // check for an existing instance of this classifier
+    select = new GS3SQLSelect("classifiers");
+    select.addField("ClassifyRef");
+    GS3SQLWhereItem whereItem = new GS3SQLWhereItem("ClassifyID", "=", fullId);
+    GS3SQLWhere where = new GS3SQLWhere(whereItem);
+    select.setWhere(where);
+
+
+    // update or insert the classifier as required
+    try {
+      ResultSet results = statement.executeQuery(select.toString());
+      if (results.first()) {
+	GS3SQLUpdate update = new GS3SQLUpdate("classifiers");
+	update.setWhere(where);
+	action = update;
+ 
+	classifyRef = results.getInt("ClassifyRef");
+      }
+      else {
+	insert = new GS3SQLInsert("classifiers");
+
+	if (this.id == null || this.id.length() == 0) {
+	  insert.addValue("ParentID", "");
+	}
+	else {
+	  String parentId = this.getParentId();
+
+	  if (parentId.length() > 0) {
+	    insert.addValue("ParentID", this.prefix+"."+this.getParentId());
+	  }
+	  else {
+	    insert.addValue("ParentID", this.prefix);
+	  }
+	}
+
+	action = insert;
+	classifyRef = -1;
+      }
+      action.addValue("ClassifyID", fullId);
+      action.addValue("Name", this.name);
+      action.addValue("Description", this.descriptor);
+
+      String tailId = "0";
+      if (this.id.length() > 0) {
+	int lastDot = this.id.lastIndexOf('.');
+	if (lastDot >= 0) {
+	  tailId = this.id.substring(lastDot+1);
+	}
+	else {
+	  tailId = this.id;
+	}
+      }
+      action.addValue("ClassifyOrder", tailId, GS3SQLField.INTEGER_TYPE);
+      action.addValue("NumLeafDocs", Integer.toString(this.noOfLeafDocs()), GS3SQLField.INTEGER_TYPE);
+
+      statement.execute(action.toString());
+    }
+    catch (SQLException sqlEx) {
+      if (action == null) {
+	System.err.println("AbstractHierarchyNode.writeSQL(): "+sqlEx);
+      }
+      else {
+	System.err.println("AbstractHierarchyNode.writeSQL(): "+sqlEx + " " + action.toString());
+      }
+      return false;
+    }
+
+    // get the ClassifyRef if we don't already have it (have done a
+    // insert action above)...
+    if (classifyRef == -1) {
+      try {
+        ResultSet results = statement.executeQuery(select.toString());
+	if (!results.first()) {
+	    statement.close();
+	    return false;
+	}
+	
+	classifyRef = results.getInt("ClassifyRef");
+	
+      }
+      catch (SQLException sqlEx) {
+	System.err.println("AbstractHierarchyNode.writeSQL(): "+sqlEx);
+	return false;
+      }
+    }
+    else {
+      // TODO: clear 'dead' child classifications
+
+      // delete child documents
+      GS3SQLDelete delete = new GS3SQLDelete("classdocuments");
+      delete.setWhere(where);
+      try {
+	  statement.execute(delete.toString());
+      } catch (SQLException e) {
+	  System.err.println("AbstractHierarchyNode.writeSQL(): "+e);
+	  return false;
+      }
+    }
+    
+    // post the child nodes...
+    Iterator iterator = this.childNodes.iterator();
+    while (iterator.hasNext()) {
+      AbstractHierarchyNode childNode = (AbstractHierarchyNode) iterator.next();
+
+      if (!childNode.writeSQL(connection)) {
+	  System.out.println("Failed to write " );
+	  return false;
+      }
+    }
+
+    // note the child documents...
+    iterator = this.childDocs.iterator();
+    int order = 1;
+    while (iterator.hasNext()) {
+      AbstractHierarchyDocument hierarchyDoc = (AbstractHierarchyDocument) iterator.next();
+      DocumentID docId = hierarchyDoc.getID();
+
+      insert = new GS3SQLInsert("classdocuments");
+      insert.addValue("ClassifyRef", Integer.toString(classifyRef), GS3SQLField.INTEGER_TYPE);
+      insert.addValue("DocID", docId.toString());
+      insert.addValue("DocOrder", Integer.toString(order), GS3SQLField.INTEGER_TYPE);
+      try {
+	  statement.execute(insert.toString());
+      } catch (SQLException e) {
+	  System.err.println("AbstractHierarchyNode.writeSQL(): "+e);
+	  return false;
+      }
+      order ++;
+    }
+    // close the statment
+    try {
+	statement.close();
+    } catch (SQLException e) {
+	System.err.println("AbstractHierarchyNode.writeSQL(): "+e);
+    }
+
+    return true;
+  }
+}
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/ClassifierInterface.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/ClassifierInterface.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/ClassifierInterface.java	(revision 13666)
@@ -0,0 +1,44 @@
+package org.greenstone.gsdl3.gs3build.classifier;
+
+import java.util.List;
+
+import org.w3c.dom.Element;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+
+public interface ClassifierInterface
+{
+  /**
+   *  Initialise the classifier as required.  The parameters given are specific
+   *  to the classifier type, so this interface does not guarantee any interpretations
+   *  of any given parameter.
+   *  
+   *  @param <code>List</code> the parameters with which to configure the classifier.
+   */
+  public void configure(List parameters);
+  public void configure(java.net.URL baseURL, org.w3c.dom.Node node);
+
+  public void setDatabase(org.greenstone.gsdl3.gs3build.database.GS3SQLConnection connection);
+
+  /**
+   *  Classify an individual document - the document should be informed of any
+   *  classification nodes which it is assigned to, so that it can obtain knowledge
+   *  of any "parents".  These are assigned into the "classified" metadata item in
+   *  the "gsdl3" namespace...
+   */
+  public boolean classifyDocument(DocumentID documentID, DocumentInterface document);
+  
+  public void startClassifierPass(int pass);
+  
+  public int getClassifierPasses();
+  
+  public void endClassifierPass(int pass);
+  
+  /**
+   *  Called at the end of the classification sequence - the classifier should
+   *  save its state at this point...
+   */
+  public void completeClassification();
+
+    public boolean addClassifierDescription(Element classifier_list);
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/ClassifierManager.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/ClassifierManager.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/ClassifierManager.java	(revision 13666)
@@ -0,0 +1,155 @@
+package org.greenstone.gsdl3.gs3build.classifier;
+
+import java.util.List;
+import java.util.Iterator;
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentList;
+import org.greenstone.gsdl3.gs3build.database.GS3SQLConnection;
+import org.greenstone.gsdl3.util.GSXML;
+
+
+public class ClassifierManager
+{
+  DocumentList           documents;
+  ClassifierInterface [] list;
+  int                    size;
+  int                    used;
+  GS3SQLConnection       database;
+
+  /**
+   *  Instantiate a classifier manager that will classify the
+   *  documents in a given <code>DocumentList</code> object.
+   *  The list of documents should not change during the
+   *  <code>classifyDocuments</code> function, and the documents
+   *  themselves may be altered at that time.
+   *
+   *  @param <code>DocumentList</code> a provider of documents for
+   *         classification.
+   */
+  public ClassifierManager(DocumentList documentList, GS3SQLConnection database)
+  { this.list = new ClassifierInterface[10];
+    this.size = 10;
+    this.used = 0;
+    this.documents = documentList;
+    this.database  = database;
+  }
+
+  /**
+   *  Add a classifier to the end of the list of classifiers...
+   *
+   *  @param <code>ClassifierInterface</code> the classifier.
+   */
+  public void addClassifier(ClassifierInterface classifier)
+  { this.ensureSize(this.used + 1);
+    this.list[this.used] = classifier;
+    this.used ++;
+
+    classifier.setDatabase(this.database);
+  }
+
+  /**
+   *  Classify an individual document - the document itself may be written
+   *  to in consequence, in which case the document <strong>must</strong>
+   *  be rewritten to disk.  This function does <strong>not</strong> do the
+   *  writing itself.
+   *
+   *  @param <code>DocumentID</code> the document's identifier.
+   *  @param <code>DocumentInterface</code> the document itself.
+   */
+  public void classifyDocument(DocumentID docId, DocumentInterface document)
+  { for (int i = 0; i < this.used; i ++)
+    {	this.list[i].classifyDocument(docId, document);
+    }
+  }
+
+  /**
+   *  Classify all the documents that the document list is able to provide...
+   */
+  public void classifyDocuments()
+  { for (int i = 0; i < this.used; i ++)
+    { for (int p = 0; p < this.list[i].getClassifierPasses(); p ++)
+      {	this.list[i].startClassifierPass(p);
+
+	Iterator iterator = this.documents.iterator();
+
+	while (iterator.hasNext()) {
+	  DocumentInterface document = (DocumentInterface) iterator.next();
+
+	  if (document.isIndexed()) {
+	    if (!this.list[i].classifyDocument(document.getID(), document)) {
+	      System.out.println("Ending document");
+	    }
+	    
+	    if (document.isChanged()) {
+	      //	      System.out.println("Writing document " + document.getID());
+	      this.documents.storeChangedDocument(document);
+	    }
+	  }
+	}
+	this.list[i].endClassifierPass(p);
+      }
+      this.list[i].completeClassification();
+    }
+  }
+
+  public void ensureSize(int size)
+  { while (size >= this.size)
+    { ClassifierInterface newList [] = new ClassifierInterface[this.size*2];
+      this.size *= 2;
+      System.arraycopy(this.list, 0, newList, 0, this.size);
+      this.list = newList;
+    }
+  }
+
+  public static ClassifierInterface loadClassifier(String classifierName)
+  { System.out.println("Loading classifier " + classifierName);
+    try {
+      ClassifierInterface classifier = 
+	(ClassifierInterface) Class.forName("org.greenstone.gsdl3.gs3build.classifier."+classifierName+"Classifier").newInstance();
+      return classifier;
+    }
+    catch (ClassNotFoundException ex) {
+      System.err.println("Attempt to load classifier " + classifierName + " which does not exist");
+    }
+    catch (InstantiationException instEx) {
+      System.err.println("Unable to create classifier " + classifierName);
+    }
+    catch (IllegalAccessException accessEx) {
+      System.err.println("Unable to instantiate classifier " + classifierName + " due to permissions problems " + accessEx.toString());
+    }
+    return null;
+  }
+    
+  public static ClassifierInterface loadClassifier(String classifierName, List params)
+  { ClassifierInterface classifier = loadClassifier(classifierName);
+    if (classifier != null) {
+      classifier.configure(params);
+    }
+    return classifier;
+  }
+
+  public boolean addServiceDescriptions(Element service_class_list) {
+    if (this.used==0) {
+      // no classiifers
+      return true;
+    }
+    Document owner_doc = service_class_list.getOwnerDocument();
+    Element browse_service = owner_doc.createElement(GSXML.SERVICE_CLASS_ELEM);
+    browse_service.setAttribute(GSXML.NAME_ATT, "GS3Browse");
+    service_class_list.appendChild(browse_service);
+    
+    Element classifier_list = owner_doc.createElement(GSXML.CLASSIFIER_ELEM+GSXML.LIST_MODIFIER);
+    browse_service.appendChild(classifier_list);
+    boolean success = true;
+    for (int i = 0; i < this.used; i ++) {
+	if (!this.list[i].addClassifierDescription(classifier_list)) {
+	    success = false;
+	}
+    }
+    return success;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/ClassifierObserverInterface.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/ClassifierObserverInterface.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/ClassifierObserverInterface.java	(revision 13666)
@@ -0,0 +1,7 @@
+package org.greenstone.gsdl3.gs3build.classifier;
+
+public interface ClassifierObserverInterface
+{
+  public void recordClassification(String label);
+  public java.util.List getClassifications();
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/GS2HierarchyClassifier.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/GS2HierarchyClassifier.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/GS2HierarchyClassifier.java	(revision 13666)
@@ -0,0 +1,309 @@
+package org.greenstone.gsdl3.gs3build.classifier;
+
+import java.io.*;
+
+import java.net.URL;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.xml.sax.XMLReader;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.Attributes;
+import org.xml.sax.helpers.XMLReaderFactory;
+import org.xml.sax.helpers.DefaultHandler;
+import org.w3c.dom.Element;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentLoader;
+import org.greenstone.gsdl3.gs3build.util.XMLTools;
+import org.greenstone.gsdl3.gs3build.util.GS2TextFileHandler;
+import org.greenstone.gsdl3.gs3build.database.GS3SQLConnection;
+import org.greenstone.gsdl3.util.GSXML;
+
+public class GS2HierarchyClassifier implements ClassifierInterface
+{ 
+  class GS2HierarchyClassifierObserver implements ClassifierObserverInterface
+  { List              classifications;
+    DocumentInterface document;
+
+    public GS2HierarchyClassifierObserver(DocumentInterface document)
+    { this.document = document;
+    }
+
+    public void recordClassification(String label)
+    { this.document.addDocumentMetadata("gsdl3", "classified", label);
+      this.document.setChanged(true);
+      //      System.out.println("Assigned document " + this.document.getID().toString() + " to " + label);
+    }
+
+    public List getClassifications()
+    { return this.classifications;
+    }
+  }
+
+  class GS2HierarchyNode extends AbstractHierarchyNode
+  { /**
+     *  Simple node
+     */
+    public GS2HierarchyNode()
+    { super();
+    }
+    
+    public GS2HierarchyNode(String prefix, String name, String id, String descriptor)
+    { super(prefix, name, id, descriptor);
+    }
+    
+    /**
+     *  Take a document, and find the classifications that it matches against in
+     *  the current hierarchy.  
+     *
+     *  @param <code>DocumentID</code> the id of the document being classified
+     *  @param <code>List</code> the values against which the classifier should
+     *         test for the document being a match - i.e. the pertinent document
+     *         property values.
+     *  @param <code>ClassifierObserverInterface</code>
+     *         object modifies the document with information about the
+     *         classifications that it fell within.
+     */
+    public void getClassifications(DocumentID documentID, List values, String sortKey,
+				   ClassifierObserverInterface observer)
+    { // Go through the list of values, and if this node matches, record
+      // the fact in the classifier observer...
+      Iterator valueList = values.iterator();
+
+      while (valueList.hasNext())
+      {	if (this.isMatch(valueList.next().toString()))
+	{ observer.recordClassification(this.id);
+	  this.addDocument(documentID, sortKey);
+	}
+      }
+     
+      // recurse into the child nodes for them to do the same...
+      Iterator childList = this.childNodes.iterator();
+
+      while (childList.hasNext())
+      { ((GS2HierarchyNode) childList.next()).getClassifications(documentID, values, sortKey, observer);
+      }
+    }
+  }
+
+  /**
+   *  An inner class to handle Classifier files
+   */
+  class GS2HierarchyHandler extends GS2TextFileHandler
+  { GS2HierarchyNode rootNode = null;
+
+    GS2HierarchyHandler(String hierarchyName, String content)
+    { super(content);
+ 
+      String prefix = "CL"+hierarchyName;
+      this.rootNode = new GS2HierarchyNode(prefix, hierarchyName, "", hierarchyName);
+
+      while (this.hasMoreLines()) {
+	String description;
+	String name, id;
+
+	this.getLine();
+	
+	name = this.getEntry(true);
+	if (name == null || name.length() == 0) {
+	  continue;
+	}
+
+	id = this.getEntry(true);
+	if (id == null || id.length() == 0) {
+	  continue;
+	}
+
+	description = this.getEntry(true);
+	if (description == null || description.length() == 0) {
+	  continue;
+	}
+	
+	// Initialise the tree
+	GS2HierarchyNode node = new GS2HierarchyNode(prefix, name, id, description);
+
+	this.rootNode.add(node);
+      }
+    }
+
+    public GS2HierarchyNode getHierarchy()
+    { return this.rootNode;
+    }
+  }
+
+  private          GS2HierarchyNode hierarchy;
+  List             fields;
+  String           sortBy;
+  GS3SQLConnection database;
+
+  public GS2HierarchyClassifier()
+  { // a 'do nothing' constructor which takes more information from configure...
+    this.fields = new ArrayList();
+    this.database = null;
+  }
+
+  public GS2HierarchyClassifier(File file)
+  {	
+    String documentText = 
+      DocumentLoader.getAsString(file);
+	
+    if (documentText == null) {
+      System.err.println("GS2HierarchyClassifier: Unable to load any content for " + file);
+      return;
+    }
+
+    GS2HierarchyHandler handler = new GS2HierarchyHandler("CL", documentText);
+
+    this.hierarchy = handler.getHierarchy();
+    this.fields = new ArrayList();
+    //    System.out.println("loaded hierarchy for "+ file.toString());
+    this.database = null;
+  }
+
+  public void setDatabase(GS3SQLConnection database)
+  { this.database = database;
+  }
+
+  public void configure(URL url, org.w3c.dom.Node node)
+  {
+  }
+
+  public void configure(List parameters)
+  {
+    File file = null;
+    
+    Iterator iterator = parameters.iterator();
+    while (iterator.hasNext()) {
+      String param = iterator.next().toString();
+
+      if (param.equals("-metadata")) {
+	if (iterator.hasNext()) {
+	  String field = iterator.next().toString();
+	  if (field != null && field.length() > 0) {
+	    this.fields.add(field);
+	  }
+	}
+      }
+      else if (param.equals("-hfile")) {
+	// this parameter had better have been expanded previously to a full path,
+	// as we're not going to do that here!!!
+	if (iterator.hasNext()) {
+	  file = new File(iterator.next().toString());
+	}
+      }
+      else if (param.equals("-sort")) {
+	if (iterator.hasNext()) {
+	  String sort = iterator.next().toString();
+	  if (sort != null && sort.length() > 0) {
+	    this.sortBy = sort;
+	  }
+	}
+      }
+    }
+
+    if (file == null) {
+      return;
+    }
+
+    String documentText = 
+      DocumentLoader.getAsString(file);
+	
+    if (documentText == null) {
+      System.err.println("GS2HierarchyClassifier: Unable to load any content for " + file);
+      return;
+    }
+
+    GS2HierarchyHandler handler = new GS2HierarchyHandler(this.fields.get(0).toString(), documentText);
+
+    this.hierarchy = handler.getHierarchy();    
+  }
+
+  /**
+   *  Classify a particular document - the document id will be used to record its
+   *  membership of any classifier nodes, and the document interface will also be
+   *  used to assign back knowledge of any classifiers to which the document is
+   *  assigned.
+   *
+   *  @param <code>DocumentID</code> the document identifier
+   *  @param <code>DocumentInterface</code> the document interface
+   */
+  public boolean classifyDocument(DocumentID documentID, DocumentInterface document)
+  { if (this.hierarchy == null) {
+      return true;
+    }
+    
+    // the observer records the assignment of documents to classifications
+    GS2HierarchyClassifierObserver classifyObserver = new GS2HierarchyClassifierObserver(document);
+		
+    // get the metadata item from the document
+    Iterator thisField = this.fields.iterator();
+
+    // for every field listed as being a scannable field...
+    while (thisField.hasNext())
+    { String fieldName = thisField.next().toString();
+
+      // ...get the values for that field...
+      List values = document.getDocumentMetadataItem(fieldName);
+
+      if (values == null)
+      {	continue;
+      }
+
+      //      System.out.println("Matching " + values.get(0).toString());
+
+      if (documentID == null) {
+	System.out.println("Bad documentID");
+	continue;
+      }
+
+      // get the sort key for the metadata item if possible
+      String sortKey = null;
+
+      if (this.sortBy != null) {
+	List sortKeys = document.getDocumentMetadataItem(this.sortBy);
+	if (sortKeys != null && sortKeys.size() > 0) {
+	  sortKey = sortKeys.get(0).toString();
+	}
+      }
+
+      // ...and send them to the classifier
+      this.hierarchy.getClassifications(documentID, values, sortKey, classifyObserver);
+    }
+    return true;
+  }
+
+  public int getClassifierPasses()
+  { return 1;
+  }
+
+  public void startClassifierPass(int pass)
+  {
+  }
+  
+  public void endClassifierPass(int pass)
+  {
+  }
+  
+  public void completeClassification()
+  { // TODO: store the classifications to file...
+
+    // The hierarchy member may be null if the classifier did not initialise correctly...
+    if (this.hierarchy != null) {
+      this.hierarchy.writeSQL(this.database);
+    }
+  }
+    public boolean addClassifierDescription(Element classifier_list) {
+	// TODO check that there are some docs in the classification
+	Element classifier = classifier_list.getOwnerDocument().createElement(GSXML.CLASSIFIER_ELEM);
+	//classifier.setAttribute(GSXML.NAME_ATT, this.name);
+	classifier.setAttribute(GSXML.NAME_ATT, "name"); // what is teh name???
+	classifier_list.appendChild(classifier);
+	return true;
+    }
+
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/HierarchyClassifier.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/HierarchyClassifier.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/classifier/HierarchyClassifier.java	(revision 13666)
@@ -0,0 +1,344 @@
+package org.greenstone.gsdl3.gs3build.classifier;
+
+import java.io.*;
+
+import java.net.URL;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.apache.xerces.parsers.SAXParser;
+import org.xml.sax.XMLReader;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.Attributes;
+import org.xml.sax.helpers.XMLReaderFactory;
+import org.xml.sax.helpers.DefaultHandler;
+import org.w3c.dom.Element;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+import org.greenstone.gsdl3.gs3build.util.XMLTools;
+import org.greenstone.gsdl3.gs3build.database.GS3SQLConnection;
+import org.greenstone.gsdl3.util.GSXML;
+
+
+public class HierarchyClassifier extends AbstractClassifier
+{ 
+  class HierarchyClassifierObserver implements ClassifierObserverInterface
+  { List              classifications;
+    DocumentInterface document;
+
+    public HierarchyClassifierObserver(DocumentInterface document)
+    { this.document = document;
+    }
+
+    public void recordClassification(String label)
+    { this.document.addDocumentMetadata("gsdl3", "classified", label);
+    }
+
+    public List getClassifications()
+    { return this.classifications;
+    }
+  }
+
+  class HierarchyNode extends AbstractHierarchyNode
+  { /**
+     *  Simple node
+     */
+    public HierarchyNode()
+    { super();
+    }
+
+    public HierarchyNode(String prefix, String name, String id, String descriptor)
+    { super(prefix, name, id, descriptor);
+    }
+    
+    public void getClassifications(DocumentID documentID, List values, String sortKey,
+				   ClassifierObserverInterface observer)
+    { Iterator valueList = values.iterator();
+
+      while (valueList.hasNext())
+      {	if (this.isMatch(valueList.next().toString()))
+	{ observer.recordClassification(this.name);
+	  this.addDocument(documentID, sortKey);
+	}
+      }
+     
+      // recurse into the child nodes for them to do the same...
+      Iterator childList = this.childNodes.iterator();
+
+      while (childList.hasNext())
+      { ((HierarchyNode) childList.next()).getClassifications(documentID, values, sortKey, observer);
+      }
+    }
+  }
+
+  /**
+   *  An inner class to handle Classifier files
+   */
+  class HierarchyHandler extends DefaultHandler
+  { StringBuffer description;
+    StringBuffer name;
+    StringBuffer path;
+    StringBuffer match;
+    String       prefix;
+    boolean inElement;
+    AbstractHierarchyNode rootNode = null;
+    AbstractHierarchyNode currentNode = null;
+
+    HierarchyHandler(String classifierName)
+    { super();
+ 
+      this.name        = null;
+      this.description = null;
+      this.path        = null;
+      this.match       = null;
+      this.prefix      = classifierName;
+    }
+
+    public void startElement(String URI, String localName, String qName, Attributes attributes)
+    { if (localName.equals("Hierarchy"))
+      {	// create a new node in the hierarchy
+	HierarchyNode node = new HierarchyNode(prefix, "", "", "Classifier");
+
+	this.rootNode = node;
+	this.currentNode = node;
+      }
+      else if (localName.equals("Classification"))
+      {	// create a new node in the hierarchy
+	HierarchyNode node = new HierarchyNode(this.prefix, "", "", "");
+
+	// Initialise the tree
+	if (this.currentNode == null)
+	{ this.rootNode = node;
+	}
+        // Add the node
+	else
+	{ this.currentNode.addChild(node);
+	}
+	this.currentNode = node;
+      }
+      else if (localName.equals("Name"))
+      {	this.name = new StringBuffer();
+      }
+      else if (localName.equals("Path"))
+      {	this.path   = new StringBuffer();
+      }
+      else if (localName.equals("Description"))
+      {	this.description = new StringBuffer();
+      }
+      else if (localName.equals("Matches"))
+      {	this.match = new StringBuffer();
+      }
+      else if (localName.equals("Children"))
+      {	
+      }
+    }
+
+    public void endElement(String URI, String localName, String qName)
+    { if (localName.equals("Classification"))
+      {	if (this.currentNode.getParent() == null) {
+	  // TODO: Error state
+          // this.rootNodes.add(this.currentNode);
+        }
+	this.currentNode = this.currentNode.getParent();
+      }
+      else if (localName.equals("Name"))
+      { this.currentNode.setName(XMLTools.cleanString(this.name.toString()));
+      System.out.println("Name is " + this.name);
+        this.name = null;
+      }
+      else if (localName.equals("Path"))
+      {	this.currentNode.setID(XMLTools.cleanString(this.path.toString()));
+        this.path = null;
+      }
+      else if (localName.equals("Description"))
+      { this.currentNode.setDescriptor(XMLTools.cleanString(this.description.toString()));
+        this.description = null;
+      }
+      else if (localName.equals("Matches"))
+      { this.currentNode.addMatch(XMLTools.cleanString(this.match.toString()));
+        this.match = null;
+      }
+      else if (localName.equals("Children"))
+      {	
+      }
+    }
+
+    public void characters(char c[], int start, int length)
+    { String string = new String(c, start, length);
+      if (this.path != null)
+      { this.path.append(string);
+      }
+      else if (this.name != null)
+      { this.name.append(string);
+      }
+      else if (this.description != null)
+      { this.description.append(string);
+      }
+      else if (this.match != null)
+      { this.match.append(string);
+      }
+    }
+
+    public AbstractHierarchyNode getHierarchy()
+    { return this.rootNode;
+    }
+  }
+  
+  private GS3SQLConnection database;
+  private AbstractHierarchyNode    hierarchy;
+  private List             fields;
+  private String           sortBy;
+  private String           name;
+
+  public HierarchyClassifier(String name, URL basefile, List fields, String sortBy)
+  {	
+    try 
+    { SAXParser parser = new SAXParser();
+      HierarchyHandler handler = new HierarchyHandler(name);
+      /*
+      XMLReader reader = XMLReaderFactory.createXMLReader();
+      reader.setContentHandler(handler);
+      reader.setErrorHandler(handler);*/
+      parser.setContentHandler(handler);
+
+      // A Classifier consists of one file only - get it.
+      /*
+      FileReader fileReader = new FileReader(basefile);
+      reader.parse(new InputSource(fileReader));
+      */
+      parser.parse(basefile.toString());
+
+      this.hierarchy = handler.getHierarchy();
+      this.fields = fields;
+      this.sortBy = sortBy;
+      this.name = name;
+      System.out.println("Counting " + this.fields.size() + " fields");
+    }
+    catch (SAXException saxException)
+    { // TODO: log error
+	System.out.println("unable to process hierarchy " + saxException.toString());
+    }
+    catch (java.io.FileNotFoundException fileException)
+    {
+	System.out.println("unable to process hierarchy " + fileException.toString());
+    }
+    catch (java.io.IOException ioException)
+    {
+	System.out.println("unable to process hierarchy " + ioException.toString());
+    }
+  }
+
+  public void configure(List parameters)
+  {
+    Iterator iterator = parameters.iterator();
+    while (iterator.hasNext()) {
+      String param = iterator.next().toString();
+      if (param.equals("-metadata")) {
+	if (iterator.hasNext()) {
+	  String field = iterator.next().toString();
+	  if (field != null && field.length() > 0) {
+	    this.fields.add(field);
+	  }
+	}
+      }
+    }
+  }
+
+  /**
+   *  Indicate the database to be used for saving the hierarchy to.
+   *
+   *  @param <code>GS3SQLConnection</code> the database
+   */
+  public void setDatabase(GS3SQLConnection database)
+  { this.database = database;
+  }
+
+  /**
+   *  Classify a particular document - the document id will be used to record its
+   *  membership of any classifier nodes, and the document interface will also be
+   *  used to assign back knowledge of any classifiers to which the document is
+   *  assigned.
+   *
+   *  @param <code>DocumentID</code> the document identifier
+   *  @param <code>DocumentInterface</code> the document interface
+   *
+   *  @return <code>boolean</code> a return value - currently always 
+   *          <code>true</code> for success
+   */
+  public boolean classifyDocument(DocumentID documentID, DocumentInterface document)
+  { // the observer records the assignment of documents to classifications
+    HierarchyClassifierObserver classifyObserver = new HierarchyClassifierObserver(document);
+
+    // if we have no fields, there is nothing to do...
+    if (this.fields == null)
+    { return true;
+    }
+
+    // get the metadata item from the document
+    Iterator thisField = this.fields.iterator();
+
+    // for every field listed as being a scannable field...
+    while (thisField.hasNext())
+    { String fieldName = thisField.next().toString();
+			
+      // ...get the values for that field...
+      List values = document.getDocumentMetadataItem(fieldName);
+
+      if (values == null)
+      {	continue;
+      }
+
+      if (documentID == null) {
+	System.out.println("Bad documentID");
+	continue;
+      }
+
+      // get the sort key for the metadata item if possible
+      String sortKey = null;
+
+      if (this.sortBy != null) {
+	List sortKeys = document.getDocumentMetadataItem(this.sortBy);
+	if (sortKeys != null && sortKeys.size() > 0) {
+	  sortKey = sortKeys.get(0).toString();
+	}
+      }
+
+      // ...and send them to the classifier
+      this.hierarchy.getClassifications(documentID, values, sortKey, classifyObserver);
+    }
+    return true;
+  }
+
+  /**
+   *  @see ClassifierInterface:getClassifierPasses
+   */
+  public int getClassifierPasses()
+  { return 1;
+  }
+
+  public void startClassifierPass(int pass)
+  {
+  }
+  
+  public void endClassifierPass(int pass)
+  {
+  }
+  
+  public void completeClassification()
+  { // TODO: store the classifications to file...
+    if (this.hierarchy != null) {
+      this.hierarchy.writeSQL(this.database);
+    }
+  }
+
+    public boolean addClassifierDescription(Element classifier_list) {
+	// TODO check that there are some docs in the classification
+	Element classifier = classifier_list.getOwnerDocument().createElement(GSXML.CLASSIFIER_ELEM);
+	classifier.setAttribute(GSXML.NAME_ATT, this.name);
+	classifier_list.appendChild(classifier);
+	return true;
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/collection/BuildIDFactory.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/collection/BuildIDFactory.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/collection/BuildIDFactory.java	(revision 13666)
@@ -0,0 +1,31 @@
+package org.greenstone.gsdl3.gs3build.collection;
+
+import java.util.GregorianCalendar;
+
+import org.greenstone.gsdl3.gs3build.BuildManager;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+
+public class BuildIDFactory implements IDFactoryInterface
+{
+	int sequenceNumber;
+
+	public BuildIDFactory(BuildManager manager)
+	{
+		GregorianCalendar today = new GregorianCalendar();
+
+		String oldBuild = manager.getLastBuildSequence();
+		if (oldBuild != null)
+		{ this.sequenceNumber = Integer.parseInt(oldBuild);
+		}
+		else
+		{	this.sequenceNumber = 0;
+		}
+	}
+
+	public DocumentID getDocumentID(DocumentInterface document)
+	{	String value = new String(Integer.toString(this.sequenceNumber));
+		this.sequenceNumber ++;
+		return new DocumentID(value);
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/collection/CollectionCrawlObserver.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/collection/CollectionCrawlObserver.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/collection/CollectionCrawlObserver.java	(revision 13666)
@@ -0,0 +1,28 @@
+package org.greenstone.gsdl3.gs3build.collection;
+
+import java.io.File;
+
+import org.greenstone.gsdl3.gs3build.classifier.*;
+import org.greenstone.gsdl3.gs3build.BuildManager;
+
+import org.greenstone.gsdl3.gs3build.FileCrawlObserver;
+
+public class CollectionCrawlObserver implements FileCrawlObserver
+{
+  BuildManager manager;
+
+  public CollectionCrawlObserver(BuildManager manager)
+  { this.manager = manager;
+  }
+
+  public void processFile(File file)
+  { if (file.getName().equals("collect.cfg")) {
+      GS2CollectionCfg config = GS2CollectionCfg.getGS2CollectionCfg(this.manager, file);
+    }
+    else if (file.toString().endsWith(".txt")) {
+      // Commented out: this is now done on the line above...
+      // GS2HierarchyClassifier classifier = new GS2HierarchyClassifier(file);
+      // manager.getClassifierManager().addClassifier(classifier);
+    }
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/collection/CollectionMetadata.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/collection/CollectionMetadata.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/collection/CollectionMetadata.java	(revision 13666)
@@ -0,0 +1,66 @@
+package org.greenstone.gsdl3.gs3build.collection;
+
+import java.io.PrintWriter;
+
+import java.util.List;
+
+import org.greenstone.gsdl3.gs3build.metadata.METSDescriptive;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+
+/**
+ *  A class to consolidate the metadata assigned to the documents of a collection
+ *  as per the extension to Greenstone 2 done by George Buchanan.
+ */
+
+public class CollectionMetadata
+{ METSDescriptive metadata;
+	
+  public CollectionMetadata()
+  { this.metadata = new METSDescriptive("CM0", "collection");
+  }
+
+  /**
+   *  Accrue the metadata assigned to a particular document
+   *
+   *  @param <code>DocumentID</code> the document identifier
+   *  @param <code>String</code> the namespace of the metadata
+   *  @param <code>String</code> the field of metadata
+   *  @param <code>String</code> the actual value assigned
+   */
+  public void addDocumentMetadata(DocumentID documentID, String namespace, String field, String value)
+  { // we don't presently use the document ID in this member function
+    this.metadata.addMetadata(namespace, field, value);
+  }
+
+  /**
+   *  Set the metadata stored on a given metadata item - any other values are
+   *  destroyed.
+   *
+   *  @param <code>String</code> the namespace
+   *  @param <code>String</code> the label of the metadata
+   *  @param <code>String</code> the actual value assigned
+   */
+  public void setCollectionMetadata(String namespace, String label, String value)
+  { this.metadata.setMetadata(namespace, label, value);
+  }
+
+  /**
+   *  Get the metadata stored on a given metadata item
+   *
+   *  @param <code>String</code> the namespace
+   *  @param <code>String</code> the label of the metadata
+   */
+  public List getCollectionMetadata(String namespace, String label)
+  { return this.metadata.getMetadata(namespace, label);
+  }
+
+  /**
+   *  Write the collection metadata
+   *
+   *  TODO: dummy function - complete
+   */
+  public boolean write(PrintWriter writer)
+  { return false;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/collection/GS2CollectionCfg.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/collection/GS2CollectionCfg.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/collection/GS2CollectionCfg.java	(revision 13666)
@@ -0,0 +1,159 @@
+package org.greenstone.gsdl3.gs3build.collection;
+
+import java.io.File;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentLoader;
+import org.greenstone.gsdl3.gs3build.util.XMLTools;
+import org.greenstone.gsdl3.gs3build.util.GS2TextFileHandler;
+
+import org.greenstone.gsdl3.gs3build.classifier.ClassifierInterface;
+import org.greenstone.gsdl3.gs3build.classifier.ClassifierManager;
+
+import org.greenstone.gsdl3.gs3build.indexers.*;
+
+import org.greenstone.gsdl3.gs3build.BuildManager;
+
+public class GS2CollectionCfg
+{
+  BuildManager buildManager;
+  IndexerInterface indexer;
+
+  class GS2CollectCfgHandler extends GS2TextFileHandler
+  { 
+    
+    GS2CollectCfgHandler(String content, File collectFile, GS2CollectionCfg configurator)
+    { super(content);
+ 
+      while (this.hasMoreLines()) {
+	String lineType;
+
+	this.getLine();
+	
+	lineType = this.getEntry(true);
+	if (lineType == null || lineType.length() == 0) {
+	  continue;
+	}
+
+	if (lineType.equals("classify"))
+	{
+	  String classType = this.getEntry(true);
+	  if (classType == null || classType.length() == 0) {
+	    continue;
+	  }
+	  classType = "GS2" + classType;
+	  
+	  List paramList = new ArrayList();
+	  
+	  // read in the parameters - to allow for better abstraction of other parts,
+	  // the handling of this is a bit 'odd', specifically modifying any file
+	  // references here before passing them on...
+	  String parameter = null;
+	  String lastParam = null;
+	  while (this.hasMore())
+	  { String param = this.getEntry(true);
+	    
+	    if (param != null && param.length() > 0) 
+	    { // expand any hfile references...
+	      if (lastParam != null && lastParam.equals("-hfile")) {
+		param = collectFile.getParent() + File.separator + param;
+	      }
+	      
+	      paramList.add(param);
+	    }
+
+	    lastParam = param;
+	  }
+
+	  ClassifierInterface classifier = ClassifierManager.loadClassifier(classType, paramList);
+	  if (classifier != null) {
+	    configurator.addClassifier(classifier);
+	  }
+	  else {
+	    System.err.println("Classifier not loaded");
+	  }
+	}
+	else if (lineType.equals("buildtype")) {
+	  if (this.hasMore()) {
+	    String type = this.getEntry(true);
+	    if (type != null) {
+	      configurator.setBuildType(type);	      
+	    }
+	  }
+	}
+	else if (lineType.equals("indexes")) {
+	  while (this.hasMore()) {
+	    String index = this.getEntry(true);
+	    if (index != null) {
+	      System.out.println("Adding index " + index);
+	      configurator.addIndex(index);
+	    }
+	  }
+	}
+      }
+    }
+  }
+
+  public GS2CollectionCfg(BuildManager manager, File file)
+  {
+    String documentText = 
+      DocumentLoader.getAsString(file);
+
+    if (documentText == null) {
+      return;
+    }
+
+    this.buildManager = manager;
+
+    GS2CollectCfgHandler handler = new GS2CollectCfgHandler(documentText, file, this);
+  }
+  
+  void addClassifier(ClassifierInterface classifier)
+  {
+    ClassifierManager manager = this.buildManager.getClassifierManager();
+
+    if (manager != null) {
+      manager.addClassifier(classifier);
+    }
+    else {
+      System.out.println("Unable to install due to missing manager");
+    }
+  }
+
+  void addIndex(String index)
+  {
+    if (this.indexer == null) {
+      this.setBuildType("mg");
+    }
+    this.indexer.configure(IndexerInterface.GS2_INDEX_LABEL, index);
+  }
+
+  void setBuildType(String type)
+  { if (type.equals("mgpp")) {
+      this.indexer = new MGPPIndexer("mgpp");
+    }
+    else {
+      this.indexer = new MGIndexer("mg");
+    }
+    this.buildManager.addIndexer(this.indexer);
+  }
+
+  public static GS2CollectionCfg getGS2CollectionCfg(BuildManager manager, File cfgFile)
+  { GS2CollectionCfg configurator = new GS2CollectionCfg(manager, cfgFile);
+    return configurator;
+  }
+
+  public static GS2CollectionCfg getGS2CollectionCfg(BuildManager manager, String etcDir)
+  {
+    File file = new File(etcDir, "collect.cfg");
+    
+    if (!file.exists()) {
+      return null;
+    }
+
+    return getGS2CollectionCfg(manager, file);
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/collection/IDFactoryInterface.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/collection/IDFactoryInterface.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/collection/IDFactoryInterface.java	(revision 13666)
@@ -0,0 +1,9 @@
+package org.greenstone.gsdl3.gs3build.collection;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+
+public interface IDFactoryInterface
+{
+	public DocumentID getDocumentID(DocumentInterface document);
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/DatabaseAdaptorInterface.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/DatabaseAdaptorInterface.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/DatabaseAdaptorInterface.java	(revision 13666)
@@ -0,0 +1,17 @@
+package org.greenstone.gsdl3.gs3build.database;
+
+/**
+ *  Facilitates communication between Greenstone and a database system,
+ *  be it gdbm, an SQL database or other product - what lies underneath
+ *  is down to you...
+ *
+ *  As this is a "write only" interface, the document is only stored as
+ *  required.
+ */
+
+import java.sql.*;
+
+public interface DatabaseAdaptorInterface
+{
+    //  public Connection getConnection();
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLAction.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLAction.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLAction.java	(revision 13666)
@@ -0,0 +1,54 @@
+package org.greenstone.gsdl3.gs3build.database;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+public class GS3SQLAction
+{ String      table;
+  List        values;
+
+  public GS3SQLAction(String table)
+  {
+    this.table  = table;
+    this.values = new ArrayList();
+  }
+
+  public void addValue(String field, String value, String type)
+  { this.values.add(new GS3SQLValue(field, value, type));
+  }
+  
+  public void addValue(String field, String value)
+  { this.values.add(new GS3SQLValue(field, value));
+  }
+
+  public void addDate(String field, java.sql.Timestamp date)
+  { this.values.add(new GS3SQLValue(field, getDateString(date)));
+  }
+
+  public static String getDateString(java.sql.Timestamp date)
+  { StringBuffer reply = new StringBuffer();
+    Calendar calendar = new GregorianCalendar();
+    calendar.setTime(date);
+
+    reply.append(Integer.toString(calendar.get(Calendar.YEAR)));
+    reply.append("-");
+    reply.append(Integer.toString(calendar.get(Calendar.MONTH)+1));
+    reply.append("-");
+    reply.append(Integer.toString(calendar.get(Calendar.DAY_OF_MONTH)));
+    reply.append(" ");
+    reply.append(Integer.toString(calendar.get(Calendar.HOUR_OF_DAY)));
+    reply.append(":");
+    reply.append(Integer.toString(calendar.get(Calendar.MINUTE)));
+    reply.append(":");
+    reply.append(Integer.toString(calendar.get(Calendar.SECOND)));
+
+    return reply.toString();
+  }
+  
+  public void addField(String field)
+  { this.values.add(new GS3SQLValue(field, null));
+  }
+}
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLConnection.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLConnection.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLConnection.java	(revision 13666)
@@ -0,0 +1,245 @@
+package org.greenstone.gsdl3.gs3build.database;
+
+import java.util.List;
+import java.util.ArrayList;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.ResultSet;
+
+
+public class GS3SQLConnection extends SQLConnection
+{
+
+    public GS3SQLConnection(java.sql.Connection connection, String database)
+    { 
+	super(connection, database);
+    }
+    
+
+  public void clearCollection(String collectionName)
+  {
+      dropDatabase(collectionName);
+  }
+    
+    public GS3SQLConnection cloneConnection() {
+	GS3SQLConnection conn = GS3SQLConnectionFactory.getGS3SQLConnection(this.database);
+	return conn;
+    }
+  /**
+   *  Initialise a collection for use.
+   *
+   *  @return <code>boolean</code> <code>true</code> if the collection successfully initialised.
+   */
+  public boolean initCollection(String collectionName)
+  {	
+    /*
+    // Check if the collection already exists
+    // if so, abort
+
+    // do a sample query to check if the collection exists
+    GS3SQLSelect select = new GS3SQLSelect("document");
+    select.addField("*");
+    if (this.execute(select.toString())) {
+      return true;
+    }
+
+    // if there is an error, assume that the database doesn't exist...
+    // and reconnect to a "test" database for now...
+    this.connection = GS3SQLConnectionFactory.getConnection("test");
+    */
+
+      // create the new db
+      if (!createDatabase(collectionName)) {
+          System.err.println("Couldn't create database " + collectionName);
+	  return false;
+      }
+      // now connect to it
+      if (!connectToDatabase(collectionName)) {
+          System.err.println("couldn't connect to the database " + collectionName);
+	  return false;
+      }
+    
+      
+    try {
+      Statement statement = this.connection.createStatement();
+
+      // create build history table
+      GS3SQLCreateTable buildTable = new GS3SQLCreateTable("build");
+      buildTable.addAutoPrimaryKey("buildRef");
+      buildTable.addProperty("buildKey", 64);
+      buildTable.addProperty("buildValue");
+      statement.execute(buildTable.toString());
+
+      // create document table
+      GS3SQLCreateTable docTable = new GS3SQLCreateTable("document");
+      docTable.addProperty("DocID", 64);   // The document identifer, unique in collection
+      docTable.setPrimaryKey("DocID");     // ...which is also the primary key
+      docTable.addProperty("DocType", 64); // The document type - used to regenerate the
+                                           // correct Document object type.
+      docTable.addProperty("AccessionDate", GS3SQLField.DATETIME_TYPE);
+      docTable.addProperty("IndexedDate", GS3SQLField.DATETIME_TYPE);
+      docTable.addProperty("ModifiedDate", GS3SQLField.DATETIME_TYPE);
+      statement.execute(docTable.toString());
+      
+      // create structure table
+      GS3SQLCreateTable structureMap = new GS3SQLCreateTable("structure");
+      structureMap.addAutoPrimaryKey("StructureRef");
+      structureMap.addProperty("DocID", 64);          // a 'foreign key' in effect - but not treated
+                                                      // as such for efficiency reasons
+      structureMap.addProperty("StructureID", 64);    // this identifier
+      structureMap.addProperty("StructureType", 64);  // the type of the structure
+      structureMap.addProperty("Label", 128);         // the label of the structure
+      statement.execute(structureMap.toString());
+    
+      // create section table
+      GS3SQLCreateTable sectionMap = new GS3SQLCreateTable("divisions");
+      sectionMap.addAutoPrimaryKey("DivisionRef");
+      sectionMap.addProperty("StructureRef", GS3SQLField.INTEGER_TYPE);
+      sectionMap.addProperty("DocID", 64);        // a 'foreign key' in effect - but not treated
+                                                  // as such for efficiency reasons
+      sectionMap.addProperty("ParentType", 64);   // the type of the parent - document or section
+      sectionMap.addProperty("ParentRef", 64);    // the parent sql reference identifier
+      sectionMap.addProperty("SectionID", 64);    // this identifier
+      sectionMap.addProperty("DivisionType", 64); // the type of the section
+      sectionMap.addProperty("LabelOrder", 64);   // the order of the section
+      sectionMap.addProperty("ShortLabel", 128);  // the short label of the section
+      sectionMap.addProperty("UserLabel", 255);   // the long label of the section
+      statement.execute(sectionMap.toString());
+
+      // a division->metadata reference mapping
+      GS3SQLCreateTable metaRefs = new GS3SQLCreateTable("divisionmetarefs");
+      metaRefs.addProperty("DocID", 64);
+      metaRefs.addProperty("DivisionRef", GS3SQLField.INTEGER_TYPE);
+      metaRefs.addProperty("DivisionType", 16);   // whether a namespace or meta ref
+      metaRefs.addProperty("MetaID", 64); // the metadata reference itself, as a string
+      statement.execute(metaRefs.toString());
+
+      // a division->file reference mapping
+      GS3SQLCreateTable fileRefs = new GS3SQLCreateTable("divisionfilerefs");
+      fileRefs.addProperty("DocID", 64);
+      fileRefs.addProperty("DivisionRef", GS3SQLField.INTEGER_TYPE);
+      fileRefs.addProperty("DivisionType", 16); // whether section, group or file
+      fileRefs.addProperty("FileID", 32);
+      statement.execute(fileRefs.toString());
+      
+      //   create metadata table section table
+      GS3SQLCreateTable metadataSection = new GS3SQLCreateTable("metadata");
+      metadataSection.addAutoPrimaryKey("MetadataRef");
+      metadataSection.addProperty("DocID", 64);   // this table isn't actually used for much
+      metadataSection.addProperty("MetaID", 64);  // in and of itself...
+      metadataSection.addProperty("GroupID", 64); // the 'name' property
+      statement.execute(metadataSection.toString());
+      
+      //   create namespace table
+      GS3SQLCreateTable namespaces = new GS3SQLCreateTable("namespaces");
+      namespaces.addAutoPrimaryKey("NamespaceRef");
+      namespaces.addProperty("MetadataRef", GS3SQLField.INTEGER_TYPE);
+      namespaces.addProperty("DocID", 64);   // these three fields are the primary key
+      namespaces.addProperty("MetaID", 64);
+      namespaces.addProperty("NamespaceID", 64);
+      namespaces.addProperty("NamespaceType", 64);
+      namespaces.addProperty("FileType", 64);
+      namespaces.addProperty("FileLoc");
+      namespaces.addProperty("Creator", 128);
+      statement.execute(namespaces.toString());
+
+      // create metadata grouping table
+      GS3SQLCreateTable metagroups = new GS3SQLCreateTable("mdgroups");
+      metagroups.addProperty("NamespaceRef", GS3SQLField.INTEGER_TYPE);
+      metagroups.addAutoPrimaryKey("MdGroupRef");
+      metagroups.addProperty("MdGroupID", 32);
+      statement.execute(metagroups.toString());
+
+      // create metadata qualifiers table
+      GS3SQLCreateTable metaqualifiers = new GS3SQLCreateTable("mdqualifiers");
+      metaqualifiers.addProperty("MdGroupRef", GS3SQLField.INTEGER_TYPE);
+      metaqualifiers.addProperty("QualifierName", 64);
+      metaqualifiers.addProperty("QualifierValue", 64);
+      statement.execute(metaqualifiers.toString());
+      
+      // create metadata values table
+      GS3SQLCreateTable metadata = new GS3SQLCreateTable("mdvalues");
+      metadata.addProperty("NamespaceRef", GS3SQLField.INTEGER_TYPE); // the parent namespace {one candidate primary key}
+      metadata.addProperty("GroupRef", GS3SQLField.INTEGER_TYPE);     // the parent group     {a sub-key or independent primary key}
+      metadata.addProperty("Label", 256);                             // the key of the metadata item
+      metadata.addProperty("Value");                                  // the value of the metadata item
+      statement.execute(metadata.toString());
+    
+      //   create file section table
+      GS3SQLCreateTable filesec = new GS3SQLCreateTable("filesection");
+      filesec.addAutoPrimaryKey("FileSectionRef");
+      filesec.addProperty("DocID", 64);
+      filesec.addProperty("FileSecID", 64);
+      statement.execute(filesec.toString());
+    
+      //   create file groups table
+      GS3SQLCreateTable filegroups = new GS3SQLCreateTable("filegroups");
+      // TODO: some unique identifier
+      filegroups.addAutoPrimaryKey("FileGroupRef");
+      filegroups.addProperty("DocID", 64);
+      filegroups.addProperty("FileGroupID", 64);
+      filegroups.addProperty("ParentRef", GS3SQLField.INTEGER_TYPE);
+      filegroups.addProperty("ParentType", 16);
+      statement.execute(filegroups.toString());
+    
+      //   create file table
+      GS3SQLCreateTable files = new GS3SQLCreateTable("files");
+      // TODO: the unique identifier from file groups table
+      files.addProperty("FileGroupRef", GS3SQLField.INTEGER_TYPE);
+      files.addProperty("FileLocType", 64);
+      files.addProperty("FileLocation");
+      files.addProperty("MIMEType", 64);
+      files.addProperty("FileID", 32);
+      statement.execute(files.toString());
+      
+      //   create admin table...etc.
+
+      // 
+      // END OF METS TABLES
+      //
+
+      //
+      // BEGINNING OF GSDL TABLES
+      //
+      GS3SQLCreateTable classifiers = new GS3SQLCreateTable("classifiers");
+      classifiers.addAutoPrimaryKey("ClassifyRef");
+      classifiers.addProperty("ClassifyID");
+      classifiers.addProperty("ParentID");
+      classifiers.addProperty("ClassifyOrder");
+      classifiers.addProperty("Name");
+      classifiers.addProperty("Description");
+      classifiers.addProperty("NumLeafDocs", GS3SQLField.INTEGER_TYPE);
+      statement.execute(classifiers.toString());
+
+      GS3SQLCreateTable classDocs = new GS3SQLCreateTable("classdocuments");
+      classDocs.addProperty("ClassifyRef", GS3SQLField.INTEGER_TYPE);
+      classDocs.addProperty("DocID");
+      classDocs.addProperty("DocOrder", GS3SQLField.INTEGER_TYPE);
+      statement.execute(classDocs.toString());
+
+      GS3SQLCreateTable classData = new GS3SQLCreateTable("classdata");
+      classData.addProperty("ClassifyRef", GS3SQLField.INTEGER_TYPE);
+      classData.addProperty("Label");
+      classData.addProperty("Value");
+      statement.execute(classData.toString());
+
+      statement.close();
+      //
+      // END OF GSDL TABLES
+      //
+
+    }
+    catch (SQLException ex)
+    {
+      System.out.println(ex.toString());
+      return false;
+    }
+    return true;
+  }
+
+}
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLConnectionFactory.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLConnectionFactory.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLConnectionFactory.java	(revision 13666)
@@ -0,0 +1,76 @@
+package org.greenstone.gsdl3.gs3build.database;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.io.InputStream;
+import java.util.Properties;
+import org.greenstone.gsdl3.util.GlobalProperties;
+
+public class GS3SQLConnectionFactory
+{
+
+    public static Connection getConnection(String database)
+    {
+	try {	    
+	    String server = GlobalProperties.getProperty("mysql.server", "localhost");
+	    String port = GlobalProperties.getProperty("mysql.tcp.port", "3306");
+	    String password = GlobalProperties.getProperty("mysql.gsdl3admin.password");
+	    
+	    Class.forName("com.mysql.jdbc.Driver").newInstance();
+	    String connection_address = "jdbc:mysql://"+server+":"+port+"/"+database+"?user=gsdl3admin";
+	    if (password != null && !password.equals("")) {
+		connection_address += "&password="+password;
+	    }
+	    Connection connection = DriverManager.getConnection(connection_address);
+	    return connection;
+	}
+	catch (Exception ex) {
+	    System.out.println("GS3SQLConnectionFactory.getConnection() Error:");
+	    System.out.println(ex.getMessage());
+	}
+	return null;
+    }
+    
+    public static SQLConnection getSQLConnection(String database)
+    {
+	Connection c = getConnection(database);
+	if (c== null) {
+	    return null;
+	}
+	return new SQLConnection(c, database);
+    }
+
+    
+    public static GS3SQLConnection getGS3SQLConnection(String database)
+    {
+	Connection c = getConnection(database);
+	if (c== null) {
+	    return null;
+	}
+	return new GS3SQLConnection(c, database);
+    }
+
+    /* returns a Connection to the server, */
+    public static Connection getConnection() 
+    {
+	return getConnection("test");
+    }
+
+    /* returns a Connection to the server, */
+    public static SQLConnection getSQLConnection() 
+    {
+	return getSQLConnection("test");
+    }
+
+    public static GS3SQLConnection getGS3SQLConnection()
+    { 
+	return getGS3SQLConnection("test");
+    }
+
+    public static void main(String args[])
+    { 
+	GS3SQLConnection connection = getGS3SQLConnection();
+	connection.initCollection("maya");
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLCreateTable.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLCreateTable.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLCreateTable.java	(revision 13666)
@@ -0,0 +1,96 @@
+package org.greenstone.gsdl3.gs3build.database;
+  
+import java.util.List;
+import java.util.ArrayList;
+
+
+public class GS3SQLCreateTable
+{ 
+    String tableName;
+    List   properties;
+    List   primaryKey;
+    List   indexed;
+
+    public GS3SQLCreateTable(String tableName)
+    { 
+	this.tableName = tableName;
+	this.properties = new ArrayList();
+	this.primaryKey = new ArrayList();
+	this.indexed    = new ArrayList();
+    }
+    
+    public void addAutoPrimaryKey(String fieldName)
+    {
+	GS3SQLField field = new GS3SQLField(fieldName, GS3SQLField.AUTOINTEGER_TYPE);
+	this.properties.add(field);
+	this.setPrimaryKey(fieldName);
+    }
+
+    public void addProperty(String fieldname)
+    { 
+	GS3SQLField field = new GS3SQLField(fieldname);
+	this.properties.add(field);
+    }
+    
+    public void addProperty(String fieldname, String type)
+    { 
+	GS3SQLField field = new GS3SQLField(fieldname, type);
+	this.properties.add(field);
+    }
+
+    public void addProperty(String fieldname, int length)
+    { 
+	GS3SQLField field = new GS3SQLField(fieldname, length);
+	this.properties.add(field);
+    }
+
+    public void setPrimaryKey(String fieldname)
+    { 
+	this.primaryKey.clear();
+	this.primaryKey.add(fieldname);
+    }
+
+    public void extendPrimaryKey(String fieldname)
+    { 
+	this.primaryKey.add(fieldname);
+    }
+    
+    public void addIndex(String fieldname)
+    { 
+	this.indexed.add(fieldname);
+    }
+
+    public String toString()
+    {	
+	StringBuffer reply = new StringBuffer();
+	
+	reply.append("CREATE TABLE ");
+	reply.append(this.tableName);
+	reply.append(" (");
+	for (int f = 0; f < this.properties.size(); f ++) {
+	    GS3SQLField field = (GS3SQLField) this.properties.get(f);
+	    if (f != 0) {
+		reply.append(",");
+	    }
+	    reply.append(field.toString());
+	}
+
+	for (int p = 0; p < this.primaryKey.size(); p ++) {
+	    if (p == 0){
+		reply.append(", PRIMARY KEY(");
+	    }
+	    else {
+		reply.append(",");
+	    }
+	    reply.append(this.primaryKey.get(p).toString());
+	    
+	    if (p == this.primaryKey.size() - 1) {
+		reply.append(")");
+	    }
+	}
+	// TODO: add primary key, index etc. notations
+	reply.append(");");
+	
+	return reply.toString();
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLDelete.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLDelete.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLDelete.java	(revision 13666)
@@ -0,0 +1,35 @@
+package org.greenstone.gsdl3.gs3build.database;
+
+public class GS3SQLDelete
+{ 
+  GS3SQLWhere where;
+  String      table;
+
+  public GS3SQLDelete(String table)
+  { this.table = table;
+    this.where = null;
+  }
+
+  public void setWhere(GS3SQLWhere where)
+  { this.where = where;
+  }
+
+  public String toString()
+  {
+    StringBuffer reply = new StringBuffer();
+    reply.append("DELETE FROM ");
+    reply.append(this.table);
+
+    if (this.where != null)
+    { reply.append(" WHERE ");
+      reply.append(where.toString());
+    }
+
+    return reply.toString();
+  }
+}
+
+
+
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLField.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLField.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLField.java	(revision 13666)
@@ -0,0 +1,74 @@
+package org.greenstone.gsdl3.gs3build.database;
+
+public class GS3SQLField
+{ String name;
+  int    length;
+  String type;
+
+    public final static String VARCHAR_TYPE = "VARCHAR";
+    public final static String INTEGER_TYPE = "INTEGER";
+    public final static String AUTOINTEGER_TYPE = "AUTOINTEGER";
+    public final static String DATE_TYPE = "DATE";
+    public final static String DATETIME_TYPE = "DATETIME";
+
+    public GS3SQLField(String name)
+    { this.name = name;
+      this.length = 1024;
+      this.type   = VARCHAR_TYPE;
+    }
+
+    public GS3SQLField(String name, int length)
+    { this.name = name;
+      this.length = length;
+      this.type   = VARCHAR_TYPE;
+    }
+
+    public GS3SQLField(String name, String type)
+    { this.name = name;
+      this.type   = type;
+      this.length = 1024;
+    }
+
+    public GS3SQLField(String name, String type, int length)
+    { this.name = name;
+      this.length = length;
+      this.type   = type;
+    }
+
+    public String getName()
+    { return this.name;
+    }
+
+    public int getLength()
+    { return this.length;
+    }
+
+    public String toString()
+    { StringBuffer reply = new StringBuffer();
+
+      reply.append(this.name);
+      reply.append(" ");
+      if (this.type.equals(VARCHAR_TYPE))
+      {
+	if (length > 255) {
+	  reply.append("TINYTEXT");
+	}
+	else {
+	  reply.append("VARCHAR(");
+	  reply.append(Integer.toString(this.length));
+	  reply.append(")");
+	}
+      }
+      else if (this.type.equals(AUTOINTEGER_TYPE))
+      { reply.append("INTEGER AUTO_INCREMENT");
+      }
+      else
+      {
+	reply.append(this.type);
+      }
+      return reply.toString();
+    }
+
+}
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLInsert.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLInsert.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLInsert.java	(revision 13666)
@@ -0,0 +1,54 @@
+package org.greenstone.gsdl3.gs3build.database;
+
+public class GS3SQLInsert extends GS3SQLAction
+  { public GS3SQLInsert(String table)
+    { super(table);
+    }
+
+    public String toString()
+    {
+      StringBuffer reply = new StringBuffer();
+      reply.append("INSERT INTO ");
+      reply.append(this.table);
+      reply.append(" ");
+      if (this.values.size() >= 1)
+	reply.append("(");
+      for (int i = 0; i < this.values.size(); i ++)
+      { GS3SQLValue value = (GS3SQLValue) this.values.get(i);
+        if (i > 0)
+	  reply.append(", ");
+        reply.append(value.field);
+      }
+      if (this.values.size() >= 1)
+	reply.append(")");
+      reply.append(" VALUES ");
+      if (this.values.size() >= 1)
+	reply.append("(");
+      for (int i = 0; i < this.values.size(); i ++)
+      { GS3SQLValue value = (GS3SQLValue) this.values.get(i);
+        if (i > 0)
+	  reply.append(", ");
+	if (value.getType() == null ||
+	    value.getType().equals(GS3SQLField.DATETIME_TYPE) ||
+	    value.getType().equals(GS3SQLField.VARCHAR_TYPE))
+	{
+	    reply.append("\"");
+	}
+        reply.append(value.value);
+	if (value.getType() == null ||
+	    value.getType().equals(GS3SQLField.DATETIME_TYPE) ||
+	    value.getType().equals(GS3SQLField.VARCHAR_TYPE))
+	{
+	    reply.append("\"");
+	}
+      }
+      if (this.values.size() >= 1)
+	reply.append(")");
+      reply.append(";");
+      return reply.toString();
+    }
+  }
+
+
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLSelect.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLSelect.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLSelect.java	(revision 13666)
@@ -0,0 +1,48 @@
+package org.greenstone.gsdl3.gs3build.database;
+
+public class GS3SQLSelect extends GS3SQLAction
+{ GS3SQLWhere where;
+  boolean     distinct;
+
+  public GS3SQLSelect(String table)
+  { super(table);
+    this.where  = null;
+    this.distinct = false;
+  }
+    
+  public void setWhere(GS3SQLWhere where)
+  { this.where = where;
+  }
+
+  public void setDistinct(boolean distinct)
+  { this.distinct = distinct;
+  }
+
+  public String toString()
+  { StringBuffer reply = new StringBuffer();
+  
+    reply.append("SELECT ");
+
+    if (this.distinct)
+    { reply.append("DISTINCT ");
+    }
+ 
+    for (int i = 0; i < this.values.size(); i ++)
+    { GS3SQLValue value = (GS3SQLValue) this.values.get(i);
+      if (i > 0)
+	reply.append(", ");
+      reply.append(value.field);
+    }
+
+    reply.append(" FROM ");
+    reply.append(this.table);
+
+    if (this.where != null)
+    { reply.append(" WHERE ");
+      reply.append(where.toString());
+    }
+    return reply.toString();
+  }
+}
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLUpdate.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLUpdate.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLUpdate.java	(revision 13666)
@@ -0,0 +1,50 @@
+package org.greenstone.gsdl3.gs3build.database;
+
+public   class GS3SQLUpdate extends GS3SQLAction
+  { GS3SQLWhere where;
+
+    public GS3SQLUpdate(String table)
+    { super(table);
+      this.where  = null;
+    }
+
+    public void setWhere(GS3SQLWhere where)
+    { this.where = where;
+    }
+
+    public String toString()
+    {
+      StringBuffer reply = new StringBuffer();
+      reply.append("UPDATE ");
+      reply.append(this.table);
+      reply.append(" SET ");
+      for (int i = 0; i < this.values.size(); i ++)
+      { GS3SQLValue value = (GS3SQLValue) this.values.get(i);
+        if (i > 0)
+	  reply.append(", ");
+        reply.append(value.field);
+	reply.append("=");
+	if (value.getType() == null ||
+	    value.getType().equals(GS3SQLField.VARCHAR_TYPE))
+	{
+	    reply.append("\"");
+	}
+	reply.append(value.value);
+	if (value.getType() == null ||
+	    value.getType().equals(GS3SQLField.VARCHAR_TYPE))
+	{
+	    reply.append("\"");
+	}
+      }
+      if (this.where != null)
+      { reply.append(" WHERE ");
+	reply.append(where.toString());
+      }
+      reply.append(";");
+      return reply.toString();
+    }
+  }
+
+
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLValue.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLValue.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLValue.java	(revision 13666)
@@ -0,0 +1,28 @@
+package org.greenstone.gsdl3.gs3build.database;
+
+public class GS3SQLValue
+{ String field;
+  String value;
+  String type;
+
+  public GS3SQLValue(String field, String value)
+  {
+    this.field = field;
+    this.value = value;
+    this.type  = null;
+  }
+
+  public GS3SQLValue(String field, String value, String type)
+  {
+    this.field = field;
+    this.value = value;
+    this.type  = type;
+  }
+
+  public String getType()
+  {
+    return this.type;
+  }
+}
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLWhere.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLWhere.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLWhere.java	(revision 13666)
@@ -0,0 +1,55 @@
+package org.greenstone.gsdl3.gs3build.database;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class GS3SQLWhere implements GS3SQLWhereElement
+{ String condition;
+  List   elements;
+
+  public static final String AND_CONDITION = "AND";
+  public static final String OR_CONDITION = "OR";
+
+  public GS3SQLWhere(GS3SQLWhereElement element)
+  { this.condition = AND_CONDITION;
+    this.elements  = new ArrayList();
+    this.elements.add(element);
+  }
+
+  public GS3SQLWhere()
+  { this.condition = AND_CONDITION;
+    this.elements  = new ArrayList();   
+  }
+
+  public GS3SQLWhere(GS3SQLWhereElement element, String condition, GS3SQLWhereElement other)
+  { this.elements = new ArrayList();
+    this.elements.add(element);
+    this.elements.add(other);
+    this.condition = condition;
+  }
+
+  public void add(GS3SQLWhereElement element)
+  { this.elements.add(element);
+  }
+
+  public String toString()
+  { StringBuffer reply = new StringBuffer();
+
+    for (int i = 0; i < this.elements.size(); i ++)
+    {
+      if (i != 0) {
+	reply.append(" ");
+	reply.append(this.condition);
+	reply.append(" ");
+      }
+      reply.append(this.elements.get(i).toString());
+    }
+    return reply.toString();
+  }
+
+  public void setCondition(String condition)
+  { this.condition = condition;
+  }
+}
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLWhereElement.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLWhereElement.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLWhereElement.java	(revision 13666)
@@ -0,0 +1,10 @@
+package org.greenstone.gsdl3.gs3build.database;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public interface GS3SQLWhereElement
+{ // empty interface for type safety
+}
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLWhereItem.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLWhereItem.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/GS3SQLWhereItem.java	(revision 13666)
@@ -0,0 +1,47 @@
+package org.greenstone.gsdl3.gs3build.database;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class GS3SQLWhereItem implements GS3SQLWhereElement
+{ String field;
+  String comparison;
+  String value;
+  String type;
+
+  public GS3SQLWhereItem(String field, String comparison, String value, String type)
+  { this.field      = field;
+    this.comparison = comparison;
+    this.value      = value;
+    this.type       = type;
+  }
+
+  public GS3SQLWhereItem(String field, String comparison, String value)
+  { this.field      = field;
+    this.comparison = comparison;
+    this.value      = value;
+    this.type       = GS3SQLField.VARCHAR_TYPE;
+  }
+
+  public String toString()
+  { StringBuffer reply = new StringBuffer();
+
+    reply.append(this.field);
+    if (!this.comparison.equals("=")) {
+      reply.append(" ");
+    }
+    reply.append(this.comparison);
+    if (!this.comparison.equals("=")) {
+      reply.append(" ");
+    }
+    if (type.equals(GS3SQLField.VARCHAR_TYPE)) {
+	reply.append("\"" + this.value + "\"");
+    }
+    else {
+	reply.append(this.value);
+    }
+    return reply.toString();
+  }
+}
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/MySQLAdaptor.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/MySQLAdaptor.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/MySQLAdaptor.java	(revision 13666)
@@ -0,0 +1,7 @@
+package org.greenstone.gsdl3.gs3build.database;
+
+import java.sql.*;
+
+public class MySQLAdaptor implements DatabaseAdaptorInterface
+{
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/SQLConnection.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/SQLConnection.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/database/SQLConnection.java	(revision 13666)
@@ -0,0 +1,80 @@
+package org.greenstone.gsdl3.gs3build.database;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.ResultSet;
+
+public class SQLConnection
+{
+    protected Connection connection;
+    protected String database;
+    
+    public SQLConnection(java.sql.Connection connection, String database)
+    { 
+	this.connection = connection;
+	this.database = database;
+    }
+    
+    protected void finalize() {
+	if (this.connection!=null) {
+	    try {
+		this.connection.close();		
+	    } catch (Exception e) {}
+	}	
+	this.connection = null;   
+    }
+    
+    public void close() {
+	finalize();
+    }
+    
+    public Statement createStatement() throws SQLException
+    { 
+	return this.connection.createStatement();
+    }
+    
+    public boolean connectToDatabase(String database) {
+	if (this.connection != null) {
+	    try {
+		this.connection.close();
+	    } catch (Exception e) {}
+	}
+	this.connection = GS3SQLConnectionFactory.getConnection(database);
+	if (this.connection == null) {
+	    return false;
+	}
+	this.database = database;
+	return true;
+    }
+    
+    public boolean dropDatabase(String database) {
+	try {
+	    Statement statement = this.connection.createStatement();
+	    statement.execute("DROP DATABASE "+database+";");
+	    statement.close();
+	}
+	catch (SQLException ex){
+	    System.err.println(ex);
+	    return false;
+	}
+	return true;
+	
+    }
+
+    public boolean createDatabase(String database) {
+	try {
+	    String command = "CREATE DATABASE " + database;
+	    Statement statement = this.connection.createStatement();
+	    statement.execute(command);
+	    statement.close();
+	} catch (Exception e) {
+	    System.err.println(e);
+	    return false;
+	}
+	 
+	return true;
+    }
+
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/AbstractDocument.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/AbstractDocument.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/AbstractDocument.java	(revision 13666)
@@ -0,0 +1,488 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Date;
+
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.ResultSet;
+import java.sql.Timestamp;
+
+import java.net.URL;
+
+import org.greenstone.gsdl3.gs3build.metadata.NamespaceFactory;
+import org.greenstone.gsdl3.gs3build.metadata.StructureIdentifierFactory;
+import org.greenstone.gsdl3.gs3build.metadata.GSDL3Namespace;
+import org.greenstone.gsdl3.gs3build.metadata.METSDescriptiveSet;
+import org.greenstone.gsdl3.gs3build.metadata.METSFile;
+import org.greenstone.gsdl3.gs3build.metadata.METSFileSet;
+import org.greenstone.gsdl3.gs3build.metadata.METSHeader;
+import org.greenstone.gsdl3.gs3build.metadata.METSStructure;
+import org.greenstone.gsdl3.gs3build.metadata.METSStructureSet;
+import org.greenstone.gsdl3.gs3build.metadata.METSDivision;
+import org.greenstone.gsdl3.gs3build.metadata.METSNamespace;
+import org.greenstone.gsdl3.gs3build.metadata.MetadataLabel;
+
+import org.greenstone.gsdl3.gs3build.util.MultiMap;
+import org.greenstone.gsdl3.gs3build.database.GS3SQLConnection;
+
+/**
+ *  Provide a base-line functionality for the <code>DocumentInterface</code>
+ *  class.
+ */
+
+public abstract class AbstractDocument implements DocumentInterface
+{
+  METSFileSet        fileSet;
+  METSDescriptiveSet metadata;
+  METSStructureSet   structureSet;
+  METSHeader         header;
+  DocumentID         id;
+  boolean            isModified;
+  StructureIdentifierFactory structureIdFactory;
+  java.sql.Timestamp firstDate;
+  java.sql.Timestamp indexDate;
+  java.sql.Timestamp modifiedDate;
+
+  /**
+   *  <p>Create a very vanilla document with a given document identifier.</p>
+   *  <p>Most commonly used in dealing with loading files using DocumentFactory
+   *  or similar.</p>
+   *
+   *  @param <code>DocumentID</code> the document identifier
+   */
+  public AbstractDocument(DocumentID id)
+  { this.fileSet      = new METSFileSet();
+    this.metadata     = new METSDescriptiveSet();
+    this.header       = new METSHeader();
+    this.structureSet = new METSStructureSet();
+    this.id           = id;
+    this.structureIdFactory = new StructureIdentifierFactory();
+
+    java.util.Date thisDate = new java.util.Date();
+    this.firstDate = new java.sql.Timestamp(thisDate.getTime());
+    this.indexDate = new java.sql.Timestamp(thisDate.getTime());
+    this.modifiedDate = null; // as a signature that the modified date needs finding...
+  }
+  
+  /**
+   *  Create a basic document from a given <code>URL</code.  This is usually the form
+   *  called through the recognisers.
+   *
+   *  @param <code>URL</code> the URL of the first file in the document package
+   */
+  public AbstractDocument(URL url)
+  { this.fileSet      = new METSFileSet();
+    METSFile metsFile = this.fileSet.addFile(url);
+    this.metadata     = new METSDescriptiveSet();
+    this.header       = new METSHeader();
+    this.structureSet = new METSStructureSet();
+    this.id           = null;
+
+    java.util.Date thisDate = new java.util.Date();
+    this.firstDate = new java.sql.Timestamp(thisDate.getTime());
+    this.indexDate = new java.sql.Timestamp(thisDate.getTime());
+
+    METSStructure structure = new METSStructure("All", "All", "Whole Document");
+    METSDivision documentBody = new METSDivision("All", "All", "All", "Whole Document", "Document");
+    structure.addDivision(documentBody);
+    this.structureSet.addStructure(structure);
+    documentBody.addFileReference(metsFile.getID());
+    documentBody.addMetadataReference("DM1");
+  }
+
+  /**
+   *  Set the identified for the document.  Every document should have
+   *  a document number set on its accession, either through metadata
+   *  placed upon it internally or externally, or by assignment through
+   *  a <code>DocumentIDFactory</code>.  Each identifier should be
+   *  unique.
+   *
+   *  @param <code>DocumentID</code> the document identifier - in XML
+   *         terms, the gsdl3:id element.
+   */
+  public void setID(DocumentID id)
+  { this.id = id;
+    this.isModified = true;
+  }
+
+  /**
+   *  Get the document identifier - this should be unique to the document,
+   *  but care must be taken in the configuration of the collection to
+   *  ensure that this is the case.
+   *
+   *  @return <code>DocumentID</code> the identifer
+   */
+  public DocumentID getID()
+  { return this.id;
+  }
+
+  /**
+   *  Indicate whether this document is indexed.
+   *
+   *  @see: DocumentInterface.isIndexed
+   */
+  public boolean isIndexed()
+  { return true;
+  }
+
+  /**
+   *  Get the date that this file was modified
+   */
+  public long getFilesDatestamp()
+  { return this.fileSet.getModifiedDatestamp(); 
+  }
+
+  /**
+   *  Get the date that this file was modified
+   */
+  public long getModifiedDatestamp()
+  { if (this.modifiedDate == null) {
+      this.setModifiedDatestamp();
+    }
+    return this.modifiedDate.getTime();
+  }
+
+  /**
+   *  Update/set the date of the most recent file modification
+   */
+  public void setModifiedDatestamp()
+  { this.modifiedDate = new java.sql.Timestamp(this.fileSet.getModifiedDatestamp()); 
+  }
+
+  /**
+   *  Get the date that this document was first indexed
+   */
+  public long getAccessionDate()
+  { return this.firstDate.getTime();
+  }
+
+  /**
+   *  Get the date that this document was last indexed
+   */
+  public long getLastIndexedDate()
+  { return this.indexDate.getTime();
+  }
+
+  /**
+   *  Set the last indexed date for this document;
+   */
+  public void setLastIndexedDate(long timestamp)
+  { this.indexDate = new java.sql.Timestamp(timestamp);
+  }
+
+  /**
+   *  Check if this document is in the database already.
+   *
+   *  In this simple implementation, the first file in the document's "default"
+   *  filegroup is taken to be the canonical file for this document - any document
+   *  of the same type with the same canonical file is taken to be a match.
+   *
+   *  @return <code>boolean</code> - if a matching document is found in the
+   *                                 database.
+   */
+  public String getDuplicateID(GS3SQLConnection connection)
+  { //String query = "SELECT * FROM document INNER JOIN filegroups ON document.docId=filegroups.docId WHERE DocType=\"" + HTML_DOCUMENT_TYPE + "\"";
+
+    // Query for documents using the same file...
+    String query = "SELECT DocID FROM files INNER JOIN filegroups ON files.FileGroupRef=filegroups.FileGroupRef WHERE (filegroups.FileGroupId=\"default\" AND files.FileLocation=\"" + this.fileSet.getFile(0).getLocation().toString() + "\")";
+    try {
+	Statement statement = connection.createStatement();
+	ResultSet results = statement.executeQuery(query);
+
+	List docs = new ArrayList();
+
+	if (results.first()) {
+	    do {
+		String value = results.getString("DocID");		
+		docs.add(value);
+	    } while (results.next());
+	    
+	    Iterator docIterator = docs.iterator();
+	    while (docIterator.hasNext()) {
+		String docId = docIterator.next().toString();
+		String innerQuery = "SELECT * FROM document WHERE DocID=\"" + docId + "\"";
+		results = statement.executeQuery(innerQuery);
+		if (results.first()) {
+		    String docType = results.getString("DocType");
+		    if (docType.equals(this.getDocumentType())) {
+			return docId;
+		    }
+		}
+	    }
+	}
+	statement.close();
+    }
+    catch (java.sql.SQLException sqlEx) {
+      System.err.println("AbstractDocument.getDuplicateID(): "+sqlEx);
+    }
+
+    return "";
+  }
+
+  /**
+   *  Obtain the METS header of this document
+   *
+   *  @return <code>METSHeader</code> the header
+   */
+  public METSHeader getHeader()
+  { return this.header;
+  }	
+
+  /**
+   *  Set the METS header for this document.
+   *
+   *  @param <code>METSHeader</code> the header
+   */
+  public void setHeader(METSHeader header)
+  { this.header = header;
+  }
+
+  /**
+   *  A simple implementation of the isDocumentType function that does <b>not</b> consider
+   *  inheritance - it <code>must</code> be extended as required.
+   */
+  public boolean isDocumentType(String type)
+  { return type.equals(this.getDocumentType());
+  }
+
+  public abstract String getDocumentType();
+  
+  public abstract String getDocumentText();
+
+  public abstract String getSectionText(String sectionId);
+
+  public String getMETSType()
+  { return "document";
+  }
+
+  /**
+   *   @see DocumentInterface:addDocumentMetadata
+   */
+  public void addDocumentMetadata(MetadataLabel label, String value)
+  { // no need to set isModified, as the following call will do it anyway!
+    this.addDocumentMetadata(label.getNamespace(), label.getLabel(), value);
+  }
+
+  /**
+   *   @see DocumentInterface:addDocumentMetadata
+   */
+  public void setDocumentMetadata(MetadataLabel label, String value)
+  { // no need to set isModified, as the following call will do it anyway!
+    this.setDocumentMetadata(label.getNamespace(), label.getLabel(), value);
+  }
+
+  /**
+   *   @see DocumentInterface:addDocumentMetadata
+   */
+  public void addDocumentMetadata(String namespace, String label, String value)
+  { this.metadata.addMetadata("default", namespace, label, value);
+    this.isModified = true;
+  }
+
+  /**
+   *   @see DocumentInterface:addDocumentMetadata
+   */
+  public void setDocumentMetadata(String namespace, String label, String value)
+  { this.metadata.setMetadata("default", namespace, label, value);
+    this.isModified = true;
+  }
+
+  /**
+   *  @see DocumentInterface:removeDocumentMetadata
+   */
+  public void removeDocumentMetadata(String namespace, String label)
+  { this.metadata.removeMetadata("default", namespace, label);
+    this.isModified = true;
+  }
+
+  /**
+   *
+   */
+  public void removeAllMetadata(String namespace, String label)
+  { this.metadata.removeAllMetadata(namespace, label);
+    this.isModified = true;
+  }
+
+  /**
+   *  Post metadata to a file in this document - the appropriate changes
+   *  should be made...
+   */
+  public void postFileMetadata(URL fileLocation, String namespace, String label, String value)
+  {
+    // First get the list of file groups, etc. that this file is associated with...
+    List fileGroups = this.fileSet.findGroups(fileLocation);
+
+    // Next, get the METS divisions associated with each file group...
+    List divisions = this.structureSet.findDivisionsForFiles(fileGroups);
+    
+    // Finally, post the metadata to the metadata group associated with each structure
+    Iterator divisionIter = divisions.iterator();
+    while (divisionIter.hasNext())
+    { METSDivision division = (METSDivision) divisionIter.next();
+
+      // get the open namespace for this division
+      METSNamespace namespaceMetadata = division.findNamespace(namespace, true, this.metadata);
+
+      // then post the metadata to it...
+      namespaceMetadata.addMetadata(label, value);
+    }
+  }
+
+  /**
+   *  Get the metadata structure of the document
+   *
+   *  @return <code>METSDescriptive</code> the metadata holder for the document.
+   */
+  public METSDescriptiveSet getDocumentMetadata()
+  { return this.metadata;
+  }
+
+  /**
+   *  Set the metadata structure for this document
+   *
+   *  @param <code>METSDescriptive</code> the new metadata holder for the document.
+   */
+  public void setDocumentMetadata(METSDescriptiveSet metadata)
+  { this.metadata = metadata;
+    this.isModified = true;
+  }
+
+  /**
+   *  Get the metadata structure of the document
+   *
+   *  @return <code>METSStructureSet</code> the metadata holder for the document.
+   */
+  public METSStructureSet getDocumentStructure()
+  { return this.structureSet;
+  }
+
+  public void setDocumentStructure(METSStructureSet structureSet)
+  { this.structureSet = structureSet;
+  }
+
+  /**
+   *  Get the values associated with a particular metadata value.
+   *
+   *  @param <code>String</code> the namespace to find the values in.
+   *  @param <code>String</code> the label to match to find the values.
+   *
+   *  @return <code>List</code> the values.
+   */
+  public List getDocumentMetadataItem(String namespace, String label)
+  { return this.metadata.getMetadata("default", namespace, label);
+  }
+
+  /**
+   *  Get the values associated with a particular metadata value.
+   *
+   *  @param <code>String</code> the namespace and label separated by a
+   *         colon.
+   *
+   *  @return <code>List</code> the values.
+   */
+  public List getDocumentMetadataItem(String namespaceLabel)
+  { String namespace, label;
+  
+    int colonAt = namespaceLabel.indexOf(':');
+    if (colonAt < 0)
+    { namespace = GSDL3Namespace.GSDL3_NAMESPACE_ID;
+      label     = namespaceLabel;
+    }
+    else
+    { namespace = namespaceLabel.substring(0, colonAt);
+      label     = namespaceLabel.substring(colonAt+1);
+    }
+    return this.metadata.getMetadata("default", namespace, label);
+  }
+
+  /**
+   *  @see DocumentInterface:getDocumentFiles
+   */
+  public METSFileSet getDocumentFiles()
+  { return this.fileSet;
+  }
+
+  public void setDocumentFiles(METSFileSet fileSet)
+  { this.fileSet = fileSet;
+  }
+
+  /**
+   *  This is just a dummy function that does nothing at this level...
+   */
+  public org.w3c.dom.Document getDOMDocument()
+  { return null;
+  }
+  
+  /**
+   *  @see DocumentInterface:isMETSCompatible
+   */
+  public boolean isMETSCompatible()
+  { return true;
+  }
+
+  /**
+   *  Use a default document writer - this may be overridden for subclasses...
+   *
+   *  @see DocumentInterface:writeMETSObject
+   */
+  public DocumentWriter getMETSWriter()
+  { return new DocumentWriter();
+  }
+
+  /**
+   *  Use a default SQL document writer - this may be overridden for subclasses...
+   *
+   */
+  public DocumentSQLWriter getSQLWriter()
+  { return new DocumentSQLWriter();
+  }
+
+  /**
+   *  Obtain a document from the SQL database
+   */
+    public static AbstractDocument readSQL(GS3SQLConnection connection, ResultSet sqlResult)
+  { try {
+      DocumentID id = new DocumentID(sqlResult.getString("DocID"));
+      String     type = sqlResult.getString("docType");
+
+      // Use a factory method to create the correct subtype...
+      AbstractDocument document = DocumentFactory.createDocument(type, id);
+      // Append the document date information
+      document.indexDate    = sqlResult.getTimestamp("IndexedDate");
+      document.firstDate    = sqlResult.getTimestamp("AccessionDate");
+      document.modifiedDate = sqlResult.getTimestamp("ModifiedDate");
+
+      // Get the individual components of the document
+      METSFileSet fileSet = METSFileSet.readSQL(document, connection);
+      document.setDocumentFiles(fileSet);
+      METSDescriptiveSet descriptiveSet = METSDescriptiveSet.readSQL(document, connection);
+      document.setDocumentMetadata(descriptiveSet);
+      METSStructureSet structureSet = METSStructureSet.readSQL(document, connection);
+      document.setDocumentStructure(structureSet);
+
+      // indicate that the document is not currently modified
+      document.setChanged(false);
+      return document;
+    }
+    catch (SQLException sqlEx) {
+      System.err.println("AbstractDocument.readSQL(): Failure to load document: " + sqlEx);
+    }
+    return null;
+  }
+
+  /**
+   *  
+   */
+  public boolean isChanged()
+  { return this.isModified;
+  }
+
+  public void setChanged(boolean isModified)
+  { this.isModified = isModified;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/AbstractRecogniser.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/AbstractRecogniser.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/AbstractRecogniser.java	(revision 13666)
@@ -0,0 +1,95 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.util.ArrayList;
+import java.net.URL;
+import org.w3c.dom.Element;
+
+import org.greenstone.gsdl3.gs3build.metadata.*;
+import org.greenstone.gsdl3.gs3build.util.HTTPTools;
+/**
+   A simple base class for Recognisers
+   A new recogniser should set preferred_mime_type, filename_extensions, and document_type in the constructor. 
+   The DocumentFactory class needs to be modified to map the documentType to 
+   the corresponding document
+   And thats all for simple recognisers.
+   More complicated recognisers can just implement from scratch RecogniserInterface
+*/
+abstract public class AbstractRecogniser implements RecogniserInterface
+{
+
+    DocumentList list_repository = null;
+    String preferred_mime_type = "SET THIS IN THE CONCRETE CLASS"; 
+    ArrayList filename_extensions = null;
+    String document_type = "SET THIS IN THE CONCRETE CLASS";
+    
+    /** The constructor should set the variables 
+     * preferredMimeType, filename_extensions and documentType
+     */
+    public AbstractRecogniser() {
+
+    }
+    
+    /** configure by default does nothing */
+    public boolean configure(Element config_elem){
+	return true;
+    }
+    public void setListRepository(DocumentList docList) {
+	this.list_repository = docList;
+    }
+
+    protected boolean isAcceptedFilename(String filename) {
+	if (filename_extensions == null) {
+	    return false; // or should this be true??
+	}
+	for (int i=0; i<filename_extensions.size(); i++) {
+	    if (filename.endsWith((String)filename_extensions.get(i))) {
+		return true;
+	    }
+	}
+	return false;
+    }
+    
+    public boolean parseDocument(METSFile file)
+    {
+	String MIMEType = file.getMIMEType();
+	if (MIMEType == null || 
+	    MIMEType.equals(this.preferred_mime_type)) {
+	    URL location = file.getLocation();
+	    return this.parseDocument(location);
+	}
+	return false;
+    }
+
+    public boolean parseDocument(URL url)
+    { 
+	String filename = null;
+	
+	if (url.getProtocol().equals("file")) {
+	    filename = url.getPath();
+	}
+	
+	if (filename != null) {
+	    if ( isAcceptedFilename(filename)) {
+		
+		System.out.println("Posting "+document_type+" Document " + filename);
+		AbstractDocument doc = DocumentFactory.createDocument(document_type, url);
+		this.list_repository.addDocument(doc);
+		return true;
+	    }
+	} else {
+	    // Get Mime type remotely, and then proceed if required
+	    String mimeType = HTTPTools.getMIMEType(url);
+	    
+	    if (mimeType == this.preferred_mime_type) {
+		System.out.println("Posting "+document_type+" Document " + url.toString());
+		
+		AbstractDocument doc = DocumentFactory.createDocument(document_type, url);
+		this.list_repository.addDocument(doc);
+		return true;
+	    }
+	}
+	return false;
+    }
+}
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentFactory.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentFactory.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentFactory.java	(revision 13666)
@@ -0,0 +1,80 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.ResultSet;
+import java.net.URL;
+
+import org.greenstone.gsdl3.gs3build.database.GS3SQLConnection;
+
+public class DocumentFactory {
+    
+    public static AbstractDocument createDocument(String type, DocumentID id) {
+	
+	if (type.equals(HTMLDocument.HTML_DOCUMENT_TYPE)) {
+	    return new HTMLDocument(id);
+	} else if (type.equals(TextDocument.TEXT_DOCUMENT_TYPE)) {
+	    return new TextDocument(id);
+	} else if (type.equals(JPEGDocument.JPEG_DOCUMENT_TYPE)) {
+	    return new JPEGDocument(id);
+	} else if (type.equals(IndexDocument.INDEX_DOCUMENT_TYPE)) {
+	    return new IndexDocument(id);
+	} else if (type.equals(MetadataDocument.METADATA_DOCUMENT_TYPE)) {
+	    return new MetadataDocument(id);
+	} else if (type.equals(METSDocument.METS_DOCUMENT_TYPE)) {
+	    return new METSDocument(id);
+	} else if (type.equals(GMLDocument.GML_DOCUMENT_TYPE)) {
+	    return new GMLDocument(id);
+	}
+	
+	/*
+	  else if (type.equals(ExtXMLDocument.EXTXML_DOCUMENT_TYPE))
+	  { return new ExtXMLDocument(id);
+	  }*/
+	return null;
+    }
+    public static AbstractDocument createDocument(String type, URL url) {
+	
+	if (type.equals(HTMLDocument.HTML_DOCUMENT_TYPE)) {
+	    return new HTMLDocument(url);
+	} else if (type.equals(TextDocument.TEXT_DOCUMENT_TYPE)) {
+	    return new TextDocument(url);
+	} else if (type.equals(JPEGDocument.JPEG_DOCUMENT_TYPE)) {
+	    return new JPEGDocument(url);
+	} else if (type.equals(IndexDocument.INDEX_DOCUMENT_TYPE)) {
+	    return new IndexDocument(url);
+	} else if (type.equals(MetadataDocument.METADATA_DOCUMENT_TYPE)) {
+	    return new MetadataDocument(url);
+	} else if (type.equals(METSDocument.METS_DOCUMENT_TYPE)) {
+	    return new METSDocument(url);
+	} else if (type.equals(GMLDocument.GML_DOCUMENT_TYPE)) {
+	    return new GMLDocument(url);
+	}
+	
+	/*
+	  else if (type.equals(ExtXMLDocument.EXTXML_DOCUMENT_TYPE))
+	  { return new ExtXMLDocument(id);
+	  }*/
+	return null;
+    }
+    
+  public static DocumentInterface readSQLDocument(GS3SQLConnection connection, DocumentID id)
+  {
+    String query = "SELECT * FROM document WHERE DocID=\""+id.toString()+"\";";
+    try {
+	Statement statement = connection.createStatement();
+	ResultSet results = statement.executeQuery(query);
+	
+	DocumentInterface di = null;
+	if (results.first()) {
+	    di = AbstractDocument.readSQL(connection, results);
+	}
+	statement.close();
+	return di;
+    }
+    catch (SQLException sqlEx) {
+      System.err.println("AbstractDocument.readSQLDocument():"+sqlEx);
+    }
+    return null;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentID.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentID.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentID.java	(revision 13666)
@@ -0,0 +1,14 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+public class DocumentID
+{
+	String id;
+
+	public DocumentID(String id)
+	{	this.id = id;
+	}
+
+	public String toString()
+	{	return this.id;
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentIDFactory.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentIDFactory.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentIDFactory.java	(revision 13666)
@@ -0,0 +1,20 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import org.greenstone.gsdl3.gs3build.CollectionManager;
+
+public class DocumentIDFactory implements DocumentIDFactoryInterface
+{ private CollectionManager collection;
+
+  public DocumentIDFactory(CollectionManager collection)
+  { this.collection = collection;
+  }
+
+  public DocumentID getNewDocumentID(DocumentInterface document)
+  { DocumentID id;
+
+    String idString = this.collection.getNextDocumentID();
+    id = new DocumentID(idString);
+    
+    return id;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentIDFactoryInterface.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentIDFactoryInterface.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentIDFactoryInterface.java	(revision 13666)
@@ -0,0 +1,6 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+public interface DocumentIDFactoryInterface
+{
+	public DocumentID getNewDocumentID(DocumentInterface document);
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentInterface.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentInterface.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentInterface.java	(revision 13666)
@@ -0,0 +1,282 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.util.List;
+import java.util.Map;
+
+import java.net.URL;
+
+import org.greenstone.gsdl3.gs3build.metadata.*;
+
+import org.greenstone.gsdl3.gs3build.util.MultiMap;
+import org.greenstone.gsdl3.gs3build.database.GS3SQLConnection;
+
+public interface DocumentInterface
+{
+  /**
+   *  Get the immediate document type of the document.  The type may be derived/inherited
+   *  from other DocumentInterface types, but that cannot be checked here.
+   *
+   *  @return <code>String</code> the document type as a string
+   */
+  public String getDocumentType();
+  
+  /**
+   *  Check if this document is of a particular type, or is derived from a particular
+   *  type - i.e. inheritance is considered as well as the immediate type.
+   *
+   *  @param  <code>String</code> the type to check against.
+   *  @return <code>boolean</code> if the document matches the given type.
+   */
+  public boolean isDocumentType(String documentType);
+  
+  public void setID(DocumentID id);
+  public DocumentID getID();
+
+  /**
+   *  Get the METS type of the document.
+   *
+   *  @return <code>String</code> the document type as a string
+   */
+  public String getMETSType();
+  
+  public void setHeader(METSHeader header);
+  public METSHeader getHeader();
+
+  /**
+   *  Whether the document is indexed or not.
+   *
+   *  @return <code>boolean</code> <code>true</code> by default.
+   */
+  public boolean isIndexed();
+
+  /**
+   *  Get the latest date that a component file was modified...
+   */
+  public long getFilesDatestamp();
+
+  /**
+   *  Get the stored modified date for the files datestamp...
+   */
+  public long getModifiedDatestamp();
+
+  /**
+   *
+   */
+  public void setModifiedDatestamp();
+
+  /**
+   *  Get the date that this document was first indexed
+   */
+  public long getAccessionDate();
+
+  /**
+   *  Get the date that this document was last indexed
+   */
+  public long getLastIndexedDate();
+
+  /**
+   *  Set the last indexed date for this document;
+   */
+  public void setLastIndexedDate(long date);
+
+  /**
+   *  Check if the document matches another in the database
+   */
+  public String getDuplicateID(GS3SQLConnection connection);
+    
+  /**
+   *  The plain text of the document.
+   *
+   *  @return <code>String</code> This value may be <code>null</code>
+   *          for documents which have no textual component - e.g.
+   *          an image file
+   */
+  public String getDocumentText();
+
+  /**
+   *  The document as a dom object
+   */
+  public org.w3c.dom.Document getDOMDocument();
+
+  /**
+   *  Get the text of a section of this document
+   *
+   *  @return <code>String</code> the text as a string - for sections
+   *          that have no textual components, this value may be
+   *          <code>null</code>
+   */
+  public String getSectionText(String sectionId);
+	
+  /**
+   *  The metadata for the document, encoded as a map.
+   *
+   *  The returned Map may have the following properties:
+   *  1) It may be <code>null</code> - e.g. for plain text documents
+   *  2) Any value in the map may be a <code>List</code> object containing
+   *     more than one possible value - e.g. they key 'Author' may associated
+   *     with a List of several people.
+   *  3) Any value in the map may itself be a <code>Map</code> where the
+   *     encoding scheme permits groupings of hierarchical metadata items.
+   *  4) Where the namespace for a metadata item is known, its key will
+   *     include the namespace.  Hence Dublin Core 'Author' would be encoded
+   *     as "dc.Author" as the key.
+   *
+   *  @return <code>METSDescriptive</code> the metadata of the document
+   */
+  public METSDescriptiveSet getDocumentMetadata();
+  
+  /**
+   *  The metadata for a particular given upon the document, encoded as a <code>List</code>
+   *
+   *  @param <code>String</code> the namespace of the metadata
+   *  @param <code>String</code> the label of the values to obtain
+   *
+   *  @return <code>List</code> the metadata values
+   */
+  public List getDocumentMetadataItem(String namespace, String label);
+  
+  /**
+   *  The metadata for the document, encoded as a map.
+   *
+   *  @param <code>String</code> the namespace and label of the metadata, separated
+   *                             by a colon.  If no namespace is given, it is 
+   *                             defaulted
+   *
+   *  @return <code>List</code> the metadata values
+   */
+  public List getDocumentMetadataItem(String namespaceLabel);
+  
+  /**
+   *  Facilitate the decoration of a document with external or extracted
+   *  metadata.  This is a "cheap" form which doesn't have a separate
+   *  namespace element.  Either the data is to be stored in the "open"
+   *  Greenstone metadata namespace, or the namespace is encoded within
+   *  the label.
+   *
+   *  @param <code>MetadataLabel</code> label of the metadata, with a '.' to deliminate
+   *                             sub-component structures.  The label may commence
+   *                             with a namespace followed by a colon. 
+   *                             <p>e.g. "dc:title" for Dublin Core Title.</p>
+   *  @param <code>String</code> value of the metadata
+   */
+  public void addDocumentMetadata(MetadataLabel label, String value);
+  
+  /**
+   *  Facilitate the decoration of a document with external or extracted
+   *  metadata.  This is a "cheap" form which doesn't have a separate
+   *  namespace element.  Either the data is to be stored in the "open"
+   *  Greenstone metadata namespace, or the namespace is encoded within
+   *  the label.
+   *
+   *  @param <code>MetadataLabel</code> label of the metadata, with a '.' to deliminate
+   *                             sub-component structures.  The label may commence
+   *                             with a namespace followed by a colon. 
+   *                             <p>e.g. "dc:title" for Dublin Core Title.</p>
+   *  @param <code>String</code> value of the metadata
+   */
+  public void setDocumentMetadata(MetadataLabel label, String value);
+  
+  /**
+   *  Facilitate the decoration of a document with external or extracted
+   *  metadata.
+   *
+   *  @param <code>String</code> namespace of the metadata
+   *  @param <code>String</code> label of the metadata, with a '.' to deliminate
+   *                             sub-component structures
+   *  @param <code>String</code> value of the metadata
+   */
+  public void addDocumentMetadata(String namespace, String label, String value);
+
+  /**
+   *  Facilitate the decoration of a document with external or extracted
+   *  metadata.
+   *
+   *  @param <code>String</code> namespace of the metadata
+   *  @param <code>String</code> label of the metadata, with a '.' to deliminate
+   *                             sub-component structures
+   *  @param <code>String</code> value of the metadata
+   */
+  public void setDocumentMetadata(String namespace, String label, String value);
+
+  /**
+   *  Facilitate the removal of document metadata.
+   *
+   *  @param <code>String</code> namespace of the metadata
+   *  @param <code>String</code> label of the metadata, with a '.' to deliminate
+   *                             sub-component structures
+   */
+  public void removeDocumentMetadata(String namespace, String label);
+  
+  /**
+   *  Facilitate the removal of all metadata of a given label from the document.
+   *
+   *  @param <code>String</code> namespace of the metadata
+   *  @param <code>String</code> label of the metadata, with a '.' to deliminate
+   *                             sub-component structures
+   */
+  public void removeAllMetadata(String namespace, String label);
+  
+  /**
+   *  Post metadata to a file in this document - the appropriate changes
+   *  should be made...
+   *
+   *  @param <code>URL</code> the location of the file...
+   *  @param <code>String</code> the namespace of the metadata
+   *  @param <code>String</code> label of the metadata, with a '.' to deliminate
+   *                             sub-component structures
+   *  @param <code>String</code> value of the metadata
+   */
+  public void postFileMetadata(URL fileLocation, String namespace, String label, String value);
+
+  /**
+   *  The constituent files for the document: each should be wrapped up
+   *  as a URL
+   *
+   *  @return <code>METSFileSet</code> the files which constitute the document
+   */
+  public METSFileSet getDocumentFiles();
+
+  /**
+   *  Set the constituent files for the document.
+   */
+  public void setDocumentFiles(METSFileSet fileSet);
+
+  /**
+   *  Obtain the structural information on the document
+   *
+   *  @return <code>METSStructureSet</code> the structural information on the
+   *          document.
+   */
+  public METSStructureSet getDocumentStructure();
+  
+  /**
+   *  Indicate whether the document can be stored in a native form in
+   *  a METS wrapper
+   *
+   *  @return <code>boolean</code> <code>true</code> if the document
+   *          is just to be wrapped in a METS shell.
+   */
+  public boolean isMETSCompatible();
+  
+  /**
+   *  Write the document into a METS wrapper - for many document types,
+   *  this will not actually be done by the document itself, but rather
+   *  by the default writer
+   */
+  public DocumentWriter getMETSWriter();
+  
+  /**
+   *  Get the writer to send the document to an SQL database
+   */
+  public DocumentSQLWriter getSQLWriter();
+
+  /**
+   *  Check if the document is changed or not
+   */
+  public boolean isChanged();
+
+  /**
+   *  Set the document modified state
+   */
+  public void setChanged(boolean isModified);
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentList.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentList.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentList.java	(revision 13666)
@@ -0,0 +1,535 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.ArrayList;
+
+import java.io.PrintWriter;
+import java.io.FileWriter;
+import java.io.File;
+import java.io.IOException;
+
+import java.net.URL;
+
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.ResultSet;
+
+import org.greenstone.gsdl3.gs3build.metadata.METSFileGroup;
+
+import org.greenstone.gsdl3.gs3build.database.GS3SQLConnection;
+import org.greenstone.gsdl3.gs3build.database.GS3SQLSelect;
+import org.greenstone.gsdl3.gs3build.database.GS3SQLWhereItem;
+import org.greenstone.gsdl3.gs3build.database.GS3SQLWhere;
+import org.greenstone.gsdl3.gs3build.database.GS3SQLField;
+
+public class DocumentList
+{
+  DocumentInterface []       list;       // what is currently cached
+  int                        size;       // the maximum number in the cache
+  int                        used;       // the actual number in the cache
+  int                        count;      // the total number of known documents
+  DocumentIDFactoryInterface idFactory;  // A manufacturer of novel document IDs
+  GS3SQLConnection           connection; // used to query the SQL database
+
+  private static final int maxSize = 3;
+
+  public DocumentList(GS3SQLConnection connection)
+  { this.idFactory = null;
+    this.list  = new DocumentInterface[3];
+    this.used  = 0;
+    this.size  = 3;
+    this.count = 0;
+    this.connection = connection;
+  }
+
+  public DocumentList(DocumentIDFactoryInterface idFactory, GS3SQLConnection connection)
+  { this.idFactory = idFactory;
+    this.list  = new DocumentInterface[3];
+    this.used  = 0;
+    this.size  = 3;
+    this.count = 0;
+    this.connection = connection;
+  }
+
+  /**
+   *  Obtain the list of <code>DocumentID</code> objects representing the unique
+   *  document identifiers of documents that refer to the file given as a parameter.
+   *
+   *  @param <code>URL</code> the location of the file to match
+   *
+   *  @return <code>List</code> of <code>DocumentID</code> reference identifiers.
+   */
+  public List getDocumentIdsWithFile(URL fileLocation)
+  { List reply = new ArrayList();
+
+    GS3SQLSelect select = new GS3SQLSelect("files");
+    select.addField("*");
+    GS3SQLWhere  where  = new GS3SQLWhere(new GS3SQLWhereItem("FileLocation", "=", fileLocation.toString()));
+    select.setWhere(where);
+
+    try {
+	Statement statement = connection.createStatement();
+	ResultSet results = statement.executeQuery(select.toString());
+    
+	select = new GS3SQLSelect("filegroups");
+	select.addField("DocID");
+	select.setDistinct(true);
+      
+	where = new GS3SQLWhere();
+	where.setCondition(GS3SQLWhere.OR_CONDITION);
+	
+	GS3SQLWhereItem whereItem = null;
+
+      	results.first();
+	do {
+	  int fileGroupRef = results.getInt("FileGroupRef");
+	  whereItem = new GS3SQLWhereItem("FileGroupRef", "=", Integer.toString(fileGroupRef), GS3SQLField.INTEGER_TYPE);
+	  where.add(whereItem);
+	}
+	while (results.next());
+	select.setWhere(where);
+	
+	results = statement.executeQuery(select.toString());
+	
+	results.first();
+	do {
+	  String docId = results.getString("DocID");
+	  reply.add(docId);
+	} while (results.next());
+	statement.close();
+    }
+    catch (SQLException sqlEx) {
+	System.err.println("DocumentList.getDocumentIdsWithFile(): "+sqlEx);
+    }
+    
+    return reply;
+  }
+
+  /**
+   *  Get a list of documents that match a given set of patterns,
+   *  within a given URL node.
+   *
+   *  @param <code>List</code> the list of patterns to match
+   *  @param <code>String</code> the partial URL of the root node under which o
+   *         match files.  NB: this is a <code>String</code> as the URL may be
+   *         incomplete and not properly match the strict requirements for <code>URL</code>
+   */
+  public List findDocumentIdsUsingFiles(List fileRefs, String withinNode)
+  {
+    StringBuffer queryBuffer = new StringBuffer("SELECT FileGroupRef FROM files WHERE FileLocation ");
+
+    Iterator files = fileRefs.iterator();
+    while (files.hasNext()) {
+      String file = files.next().toString();
+
+      if (withinNode != null) {
+	queryBuffer.append("REGEXP \"^");
+	queryBuffer.append(withinNode);
+	queryBuffer.append(".*");
+      }
+      else {
+	queryBuffer.append("REGEXP \"");
+      }
+      queryBuffer.append(file);
+      queryBuffer.append("\"");
+
+      if (files.hasNext()) {
+	queryBuffer.append(" OR ");
+      }
+    }
+    queryBuffer.append(";");
+    return this.findDocumentIdsUsingFileQuery(queryBuffer.toString());
+  }
+
+  public List findDocumentIdsUsingFile(String fileRef, String withinNode)
+  { String query = "SELECT FileGroupRef FROM files WHERE FileLocation REGEXP \"^"+withinNode+".*"+fileRef+"\";";
+    return this.findDocumentIdsUsingFileQuery(query);
+  }
+
+  /**
+   *  Return a list of document identifiers against a simple pattern.  No root node is given, so
+   *  any file matching the pattern given will be returned. USE WITH CAUTION!!!
+   *
+   *  @param <code>String</code> a fragment of file pathname to match against.
+   *
+   *  @return <code>List</code> of <code>DocumentID</code> objects.
+   */
+  public List findDocumentIdsUsingFile(String fileRef)
+  { 
+    // Get the simple list of file objects & their file group reference
+    String query = "SELECT FileGroupRef FROM files WHERE FileLocation REGEXP \"" + fileRef +"\";";
+
+    return this.findDocumentIdsUsingFileQuery(query);
+  }
+
+  public List findDocumentIdsUsingFileExact(String fileRef)
+  { 
+    // Get the simple list of file objects & their file group reference
+    String query = "SELECT FileGroupRef FROM files WHERE FileLocation=\"" + fileRef +"\";";
+
+    return this.findDocumentIdsUsingFileQuery(query);
+  }
+
+    private List findDocumentIdsUsingFileQuery(String query) {
+    
+	try {
+	
+	Statement statement = connection.createStatement();
+	ResultSet results = statement.executeQuery(query);
+
+	if (!results.first()) {
+	    statement.close();
+	    return null;
+	}
+      
+      // get a list of group ids first and turn it into a query on filegroups
+      StringBuffer queryBuffer = new StringBuffer("SELECT * FROM filegroups WHERE ");
+      boolean first = true;
+      
+      do {
+	int groupRef = results.getInt("FileGroupRef");
+	
+	if (first) {
+	  first = false;
+	}
+	else {
+	  queryBuffer.append(" OR ");
+	}
+	queryBuffer.append("FileGroupRef=" + Integer.toString(groupRef));
+      } while (results.next());
+      queryBuffer.append(";");
+      
+      // make a holder for the actual file section identifiers
+      List divisions = new ArrayList();
+      
+      // expand (or, in fact, contract) through the document
+      // structures...recreating new filegroup queries as necessary
+      while (queryBuffer.length() > 0) {
+	results = statement.executeQuery(queryBuffer.toString());
+	
+	if (!results.first()) {
+	    statement.close();
+	    return null;
+	}
+	
+	queryBuffer = new StringBuffer();
+	do {
+	  String type = results.getString("ParentType");
+	  String parentRef = results.getString("ParentRef");
+	  if (type.equals(METSFileGroup.SECTION_PARENT)) {
+	    divisions.add(parentRef);
+	  }
+	  else {
+	    if (queryBuffer.length() > 0) {
+	      queryBuffer.append(" OR ");
+	    }
+	    queryBuffer.append("FileGroupRef=" + parentRef);
+	  }
+	} while (results.next());
+	
+	if (queryBuffer.length() > 0) {
+	  queryBuffer.insert(0, "SELECT * FROM filegroups WHERE ");
+	  queryBuffer.append(";");
+	}
+      }
+      
+      // ok, now find all the sections in which we are interested...
+      queryBuffer.setLength(0);
+      queryBuffer.append("SELECT DISTINCT DocID FROM filesection WHERE ");
+      Iterator iterator = divisions.iterator();
+      first = true;
+      
+      while (iterator.hasNext()) {
+	String ref = iterator.next().toString();
+	
+	if (first) {
+	  first = false;
+	}
+	else {
+	  queryBuffer.append(" OR ");
+	}
+	
+	queryBuffer.append("FileSectionRef="+ref);
+      }
+      queryBuffer.append(";");
+      
+      // execute the division query
+      results = statement.executeQuery(queryBuffer.toString());
+      
+      if (!results.first()) {
+	  statement.close();
+	  return null;
+      }
+
+      List reply = new ArrayList();
+      do {
+	reply.add(results.getString("DocID"));
+      } while (results.next());
+      
+      statement.close();
+      return reply;
+    }
+    catch (SQLException ex) {
+      System.err.println("DocumentList.findDocumentIdsUsingFileQuery()"+ ex);
+    }
+    return null;
+  }
+
+  /**
+   *  Cache a document into the cache, without writing it to the database.
+   *  Used directly by other parts of DocumentList when they know that the
+   *  document is in the database already, or they are going to write it
+   *  themselves...
+   *
+   *  @param <code>DocumentInterface</code> the document to cache
+   */
+  private void cacheDocument(DocumentInterface document)
+  { // increase cache size, etc. as necessary
+    if (this.used == this.size) {
+      if (this.size >= maxSize) {
+	for (int i = 0; i < this.size - 1; i ++) {
+	  this.list[i] = this.list[i+1];
+	}
+	this.used --;
+      }
+      else {
+	this.ensureSize((this.size * 2) > maxSize ? maxSize : (this.size * 2));
+      }
+    }
+    
+    // insert the document itself
+    this.list[this.used] = document;    
+  }
+
+  /**
+   *  Write the document into the document list (cache) and the database.
+   *
+   *  @param <code>DocumentInterface</code> the document itself
+   */
+  public void addDocument(DocumentInterface document)
+  { // initially, test if the document has a duplicate...
+    String duplicateDocID = document.getDuplicateID(this.connection);
+    if (duplicateDocID.length() > 0) {
+      System.out.println("Found duplicate document ");
+      return;
+    }
+
+    // first cache it...
+    this.cacheDocument(document);
+
+    // set the document identifier, if not already set
+    if (document.getID() == null) {
+      System.out.println("Posting new docuument ID");
+      DocumentID id = this.idFactory.getNewDocumentID(document);
+      document.setID(id);
+    }
+
+    // add to the database as well, if it is modified...
+    if (document.isChanged()) {
+      System.out.println("Document was changed");
+      document.getSQLWriter().writeDocument(document, this.connection);
+    }
+
+    // Remember that we've used one more item from the cache.
+    this.used ++;
+
+    // Note additional document
+    this.count ++;
+  }
+
+  /**
+   *  Note that an individual document is modified, and act accordingly
+   *
+   *  @param <code>DocumentInterface</code> the document
+   */
+  public void storeChangedDocument(DocumentInterface document)
+  { document.getSQLWriter().writeDocument(document, this.connection);
+  }
+
+  /**
+   *  Get an iterator across all the documents, not merely those in
+   *  the cache.  Note that this <code>Iterator</code> does <b>not</b>
+   *  support the <code>remove()</code> function, and will raise an
+   *  <code>UnsupportedOperationException</code> if you attempt to do
+   *  so.
+   *
+   *  @return <code>Iterator</code> the iterator across the documents.
+   */
+  public Iterator iterator()
+  { return new DocumentListIterator(connection);
+  }
+
+  /**
+   *  Get the nth member of the <b>cached</b> document list.
+   *
+   *  @deprecated
+   */
+  public DocumentInterface getDocument(int index)
+  { if (index < 0 || index >= this.used)
+    { return null;
+    }
+    return this.list[index];
+  }
+
+  /**
+   *  Simple "obtain a document" function
+   */
+  public DocumentInterface getDocument(DocumentID documentId)
+  {
+    DocumentInterface document = DocumentFactory.readSQLDocument(connection, documentId);
+    if (document != null) {
+      this.cacheDocument(document);
+    }
+    return document;
+  }
+
+  /**
+   *  Update timestamps on an entire document list - done at the beginning of a build cycle
+   *
+   *  @param <code>The date of the new build cycle</code>
+   */
+  public void updateTimestamps(long buildTimeStamp)
+  { Iterator documents = this.iterator();
+    int item = 0;
+
+    while (documents.hasNext())
+    { DocumentInterface document = (DocumentInterface) documents.next();
+      
+      long thisTimeStamp = document.getFilesDatestamp();
+      long lastTimeStamp = document.getModifiedDatestamp();
+
+      if (thisTimeStamp > lastTimeStamp) {
+	System.out.println("Updating timestamps " + thisTimeStamp + " " + lastTimeStamp);
+
+	DocumentSQLWriter.touchDocument(document.getID(), this.connection, buildTimeStamp, thisTimeStamp);
+      }
+    }
+  }
+
+  /**
+   *  A convenience method to map onto the old Vector source code...
+   */
+  protected void ensureSize(int size)
+  { DocumentInterface [] newList = new DocumentInterface[size];
+    System.arraycopy(this.list, 0, newList, 0, this.size);
+    this.list = newList;
+    this.size = size;
+  }
+
+  /**
+   *  Write the documents into a directory as METS/XML
+   */
+  public void writeDocuments(File directory)
+  { Iterator documents = this.iterator();
+    int item = 0;
+
+    while (documents.hasNext())
+    { DocumentInterface document = (DocumentInterface) documents.next();
+      try
+      { item ++;
+	File localFile = new File(directory, "Doc"+Integer.toString(item)+".xml");
+	FileWriter fileWriter = new FileWriter(localFile);
+	PrintWriter writer = new PrintWriter(fileWriter);
+	document.getMETSWriter().writeDocument(document, writer);
+	writer.close();
+	fileWriter.close();
+      }
+      catch (IOException io)
+      {	
+      }
+    }
+  }
+
+  public void writeSQLDocuments(GS3SQLConnection connection)
+  { for (int i = 0; i < this.used; i ++)
+    { this.list[i].getSQLWriter().writeDocument(this.list[i], connection);
+    }
+  }
+
+  public static DocumentList readSQLDocuments(GS3SQLConnection connection)
+  { DocumentList list = new DocumentList(connection);
+
+    GS3SQLSelect select = new GS3SQLSelect("document");
+    select.addField("*");
+    
+    try {
+	Statement statement = connection.createStatement();
+	ResultSet documents = statement.executeQuery(select.toString());
+	if (documents.first()) { 
+	    do {
+		DocumentInterface document = AbstractDocument.readSQL(connection, documents);
+		list.addDocument(document);
+	    }
+	    while (documents.next());
+	}
+	statement.close();
+    }
+    catch (java.sql.SQLException ex) {
+	System.out.println("DocumentList.writeSQLDocuments(): "+ex);
+	return null;
+    }
+
+    return list;
+  }
+
+  public int getCount()
+  { return this.count;
+  }
+
+  public int size()
+  { return this.used;
+  }
+}
+
+class DocumentListIterator implements Iterator
+{
+  private boolean hasNext;
+  private Statement statement;
+  private ResultSet resultSet;
+  private GS3SQLConnection connection;
+
+  public DocumentListIterator(GS3SQLConnection connection)
+  {
+    this.connection = connection;
+
+    GS3SQLSelect select = new GS3SQLSelect("document");
+    select.addField("*");
+
+    try {
+	this.statement = connection.createStatement();
+      this.resultSet = statement.executeQuery(select.toString());
+      this.hasNext = this.resultSet.first();
+    } catch (SQLException ex) {
+      System.err.println("DocumentListIterator(): "+ex);
+      this.hasNext = false;
+    }
+  }
+
+  public boolean hasNext()
+  { return this.hasNext;
+  }
+
+  public Object next()
+  {
+    // get the 'next' document first
+    DocumentInterface document = AbstractDocument.readSQL(connection, this.resultSet);
+
+    // now actually step forward to the next item, so that we know if we have one!
+    try {
+      this.hasNext = this.resultSet.next();
+
+      if (!this.hasNext) {
+	  this.statement.close(); // be a good citizen & close used statement 
+      }
+    } catch (SQLException ex) {
+	System.err.println("DocumentList.iterator.next(): "+ex);
+      this.hasNext = false;
+    }
+    return document;
+  }
+  
+  public void remove() throws UnsupportedOperationException
+  { throw new UnsupportedOperationException("DocumentList does not support iterator removal of documents");
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentLoader.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentLoader.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentLoader.java	(revision 13666)
@@ -0,0 +1,58 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.io.*;
+import java.net.URL;
+
+public class DocumentLoader
+{
+  public static String getAsString(InputStream in)
+  { StringBuffer reply;
+    byte 	data[] = new byte[1024];
+    int		databytes;
+
+    reply	= new StringBuffer();
+    
+    try
+    {
+      do
+      { databytes = in.read(data);
+        if (databytes > 0)
+	{ reply.append(new String(data, 0, databytes));
+	}
+      } while (databytes >= 0);
+    }
+    catch (IOException io)
+    {
+    }
+    
+    return reply.toString();
+  }
+
+  public static String getAsString(File file)
+  { FileInputStream in;
+    String          reply = null;
+
+    try
+    { in	= new FileInputStream(file);
+      if (in == null)
+	{	return null;
+	}
+      reply = getAsString(in);
+      
+      in.close();
+    }
+    catch (IOException io)
+    { return null;
+    }
+    return reply;
+  }
+
+  public static String getAsString(URL url)
+  { if (url.getProtocol().equals("file"))
+    { File file = new File(url.getPath());
+      return getAsString(file);
+    }
+  
+    return null;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentMetadata.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentMetadata.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentMetadata.java	(revision 13666)
@@ -0,0 +1,20 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+public class DocumentMetadata
+{
+	String name;
+	String value;
+
+	public DocumentMetadata(String name, String value)
+	{	this.name = name;
+		this.value = value;
+	}
+
+	public String getName()
+	{	return this.name;
+	}
+
+	public String getValue()
+	{	return this.value;
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentSQLWriter.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentSQLWriter.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentSQLWriter.java	(revision 13666)
@@ -0,0 +1,98 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.io.PrintWriter;
+
+import java.sql.*;
+
+import org.greenstone.gsdl3.gs3build.util.XMLTools;
+import org.greenstone.gsdl3.gs3build.database.*;
+
+public class DocumentSQLWriter
+{
+  public DocumentSQLWriter()
+  {
+  }
+
+  public static boolean touchDocument(DocumentID docID, GS3SQLConnection connection, long touchTime, long modTime)
+  { GS3SQLUpdate update = new GS3SQLUpdate("document");
+    update.setWhere(new GS3SQLWhere(new GS3SQLWhereItem("DocID", "=", docID.toString())));
+    update.addDate("IndexedDate", new java.sql.Timestamp(touchTime));
+    update.addDate("ModifiedDate", new java.sql.Timestamp(modTime));
+    try {
+	Statement statement = connection.createStatement();
+	statement.execute(update.toString());
+	statement.close();
+    } catch (SQLException e) {
+	System.err.println("DocumentSQLWriter.touchDocument() Error: "+ e);
+	return false;
+    }
+    System.out.println(update.toString());
+    return true;
+  }
+
+  /**
+   * Just write the document to the database, assuming that it is not already there
+   */
+  public boolean writeDocument(DocumentInterface document, GS3SQLConnection connection)
+  {		
+    // TODO: output document in METS format, with Greenstone-specific metadata
+    // placed in a wrapper inside the descriptive metadata block
+
+    // put the document into the database
+    try {
+      if (document.getID() != null)
+      { //tag = XMLTools.addAttribute(tag, "OBJID", document.getID().toString());
+	GS3SQLSelect select = new GS3SQLSelect("document");
+	select.addField("*");
+	select.setWhere(new GS3SQLWhere(new GS3SQLWhereItem("DocID", "=", document.getID().toString())));
+	
+	Statement statement = connection.createStatement();
+	ResultSet results = statement.executeQuery(select.toString());
+	if (!results.first()) { // empty result
+	  GS3SQLInsert insert = new GS3SQLInsert("document");
+	  insert.addValue("DocID", document.getID().toString());
+	  insert.addValue("DocType", document.getDocumentType());
+
+	  insert.addDate("AccessionDate", new java.sql.Timestamp(document.getAccessionDate()));
+	  insert.addDate("IndexedDate", new java.sql.Timestamp(document.getLastIndexedDate()));
+	  insert.addDate("ModifiedDate", new java.sql.Timestamp(document.getModifiedDatestamp()));
+
+	  statement.execute(insert.toString());
+	}
+	else {
+	  /* redundant code - not used... */
+	  //	  GS3SQLUpdate update = new GS3SQLUpdate("document");
+	  //	  update.setWhere(new GS3SQLWhere(new GS3SQLWhereItem("DocID", "=", document.getID().toString())));
+	  //	  connection.execute(update.toString());
+	}
+	statement.close();
+      }
+    } catch (SQLException ex) {
+	System.out.println("DocumentSQLWriter.writeDocument() Error:"+ex);
+    }
+    //    output.println(tag);
+    
+    // Write the structural metadata:
+    //   if in "Create METS" mode:
+    //     take all the documents as being in the one group, of the "physical"
+    //     document; particular document plugins may extend this behaviour,
+    //     which would suggest placing it in the AbstractDocument or similar
+    //     class?!
+    if (document.getDocumentMetadata() == null) {
+      System.out.println("Null metadata document");
+    }
+    document.getDocumentMetadata().writeSQL(document, connection);
+
+    document.getDocumentFiles().writeSQL(document, connection);
+
+    document.getDocumentStructure().writeSQL(document, connection);
+
+    // Write the body information
+    // TODO: only output the document if there is some
+    // content/formatting change between the original and
+    // what greenstone actually does; if the original is
+    // good, then place a marker saying "get the document
+    // "from the original file"
+    return true;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentWriter.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentWriter.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/DocumentWriter.java	(revision 13666)
@@ -0,0 +1,65 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.io.PrintWriter;
+
+import org.greenstone.gsdl3.gs3build.util.XMLTools;
+
+public class DocumentWriter
+{
+    public DocumentWriter()
+    {
+    }
+
+    public boolean writeDocument(DocumentInterface document, PrintWriter output)
+    {		
+	// TODO: output <xml header>
+	String xml_header ="<?xml ";
+	xml_header = XMLTools.addAttribute(xml_header, "version", "1.0");
+	xml_header = XMLTools.addAttribute(xml_header, "encoding", "UTF-8");
+	xml_header = XMLTools.addAttribute(xml_header, "standalone", "no");
+	xml_header = xml_header+"?>";
+	output.println(xml_header);
+
+	// TODO: output document in METS format, with Greenstone-specific metadata
+	// placed in a wrapper inside the descriptive metadata block
+	String tag = XMLTools.getOpenTag("mets", "mets");
+	if (document.getID() != null){
+	    tag = XMLTools.addAttribute(tag,"xmlns:mets","http://www.loc/gov/METS/");
+	    tag = XMLTools.addAttribute(tag,"xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
+	    tag = XMLTools.addAttribute(tag,"xmlns:gsdl3","http://www.greenstone.org/gsdlmetadata/1.0/");
+	    tag = XMLTools.addAttribute(tag,"xmlns:xlink","http://www.w3.org/TR/xlink/");
+	    tag = XMLTools.addAttribute(tag,"xsi:schemaLocation","http://www.loc.gov/METS/ http://www.loc.gov/standards/mets/mets.xsd http://www.greenstone.org/gsdlmetadata/1.0/ http://www.greenstone.org/gsdlmetadata/1.0/gsdl_metadata_schema.xsd");
+	    tag = XMLTools.addAttribute(tag, "OBJID", document.getID().toString());
+	}
+	output.println(tag);
+	
+	// Writing the structural metadata:
+	//   if in "Create METS" mode:
+	//     take all the documents as being in the one group, of the "physical"
+	//     document; particular document plugins may extend this behaviour,
+	//     which would suggest placing it in the AbstractDocument or similar
+	//     class?!
+	document.getDocumentMetadata().write(output);
+
+	// TODO: only output the document if there is some
+	// content/formatting change between the original and
+	// what greenstone actually does; if the original is
+	// good, then place a marker saying "get the document
+	// "from the original file"
+	if  (document.isMETSCompatible()){
+	    document.getDocumentFiles().write(output);
+	    document.getDocumentStructure().write(output);
+	}
+	else {
+	    DocumentWriter writer = document.getMETSWriter();
+	    
+	    // ensure that this call isn't recursive - 
+	    // TODO: This is a rather naive check and needs improving
+	    if (writer != this) {
+		writer.writeDocument(document, output);
+	    }
+	}
+	output.write("</mets:mets>\n");
+	return true;
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/GMLDocument.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/GMLDocument.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/GMLDocument.java	(revision 13666)
@@ -0,0 +1,51 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.greenstone.gsdl3.gs3build.metadata.METSDescriptiveSet;
+import org.greenstone.gsdl3.gs3build.util.MultiMap;
+
+/**
+ *  A metadata-pure document - it only contains metadata
+ *  on other documents, and this will be added to them during
+ *  the "extract" phase.  The decoration of the other documents
+ *  with this extra metadata will only occur later, as at the
+ *  point that this document/file is loaded, we may not in fact
+ *  have come across them yet...
+ */
+
+public class GMLDocument extends AbstractDocument
+{
+  public static final String GML_DOCUMENT_TYPE = "GML";
+
+  public GMLDocument(DocumentID id)
+  { super(id);
+  }
+
+  public GMLDocument(URL url)
+  { super(url);
+  }
+
+  public String getDocumentType()
+  { return GML_DOCUMENT_TYPE;
+  }
+
+  /**
+   *  A pretty minimal and lazy document text extraction process.
+   */
+  public String getDocumentText()
+  { return "";
+  }
+
+  public String getSectionText(String sectionId)
+  { return "";
+  }
+
+  public METSDescriptiveSet getDocumentMetadata()
+  { return null;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/GMLRecogniser.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/GMLRecogniser.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/GMLRecogniser.java	(revision 13666)
@@ -0,0 +1,42 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+
+import java.io.*;
+import java.net.*;
+import java.util.ArrayList;
+
+import org.greenstone.gsdl3.gs3build.metadata.*;
+
+public class GMLRecogniser extends  AbstractRecogniser
+{
+    
+    public GMLRecogniser()   { 
+	this.preferred_mime_type = "text/xml";
+	this.filename_extensions = new ArrayList();
+	this.filename_extensions.add(".gml");
+	this.document_type = GMLDocument.GML_DOCUMENT_TYPE;
+    }
+    
+    
+    public boolean parseDocument(URL url)
+    { 
+	String filename = null;
+	if (url.getProtocol().equals("file")) {
+	    filename = url.getPath();
+	}
+	if (filename != null) {
+	    if (isAcceptedFilename(filename)) {
+		
+		System.out.println("Posting GML Document " + filename);
+		GMLDocument doc = new GMLDocument(url);
+		this.list_repository.addDocument(doc);
+		// TODO: spawn knowledge of children too...
+		// System.out.println(doc.getDocumentText());
+		return true;
+	    }
+	} else {
+	    // TODO: get Mime type remotely, and then proceed if required
+	}
+	return false;
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/GS2METSRecogniser.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/GS2METSRecogniser.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/GS2METSRecogniser.java	(revision 13666)
@@ -0,0 +1,35 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.util.ArrayList;
+
+public class GS2METSRecogniser extends AbstractRecogniser
+{
+    public GS2METSRecogniser() 
+    {
+	this.preferred_mime_type = "text/xml";
+	this.filename_extensions = new ArrayList();
+	this.filename_extensions.add("docmets.xml");
+	this.document_type = METSDocument.METS_DOCUMENT_TYPE;
+    }
+    
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/HTMLDocument.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/HTMLDocument.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/HTMLDocument.java	(revision 13666)
@@ -0,0 +1,354 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.io.File;
+import java.net.URL;
+import java.net.MalformedURLException;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.ArrayList;
+
+import org.greenstone.gsdl3.gs3build.metadata.*;
+import org.greenstone.gsdl3.gs3build.util.*;
+import org.greenstone.gsdl3.gs3build.xpointer.XPointer;
+import org.greenstone.gsdl3.util.XMLConverter;
+
+import org.w3c.dom.*;
+
+public class HTMLDocument extends AbstractDocument
+{
+  public static final String HTML_DOCUMENT_TYPE = "HTML";
+  Document domDocument;
+
+  public HTMLDocument(DocumentID id)
+  { super(id);
+    this.domDocument = null;
+  }
+
+  /**
+   *  Create the HTMLDocument from a given URL - the URL may in fact be a reference
+   *  to a local file.
+   *
+   *  @param <code>URL</code> The location from which to load the file
+   */
+  public HTMLDocument(URL url)
+  { super(url);
+
+    this.loadDocument(url);
+
+    this._extractDocumentFiles();
+    this._extractDocumentMetadata();
+    // extract the files before resolving the images
+    resolveImages();
+    HTMLDocumentTools docTools = new HTMLDocumentTools(this.domDocument);
+    docTools.setMetsDocument(this);
+    docTools.setUrl(this.fileSet.getFile(0).getLocation());
+    docTools.findSections();
+    METSStructure sectionStruct = docTools.getStructure();
+
+    if (sectionStruct.size() > 0) {
+      METSStructureSet structureSet = this.getDocumentStructure();
+      structureSet.addStructure(sectionStruct);
+    }
+  }
+
+  private void loadDocument(URL url)
+  {
+    //    HTMLDoc htmlDoc;
+
+    HTMLTidy tidyDoc;
+    if (url.getProtocol().equals("file"))
+    { tidyDoc = new HTMLTidy(new File(url.getPath()));
+    }
+    else
+    { //htmlDoc = new HTMLDoc(url);
+      tidyDoc = new HTMLTidy(url);
+    }
+    
+    //    System.out.println(Runtime.getRuntime().freeMemory() + " " + Runtime.getRuntime().totalMemory());
+
+    this.domDocument = tidyDoc.getDocument(); 
+    Runtime.getRuntime().gc();
+    //    System.out.println(Runtime.getRuntime().freeMemory() + " " + Runtime.getRuntime().totalMemory());
+ }
+
+  private void _extractDocumentMetadata()
+  { 
+    NodeList metadata = this.domDocument.getElementsByTagName("META");
+    for (int n = 0; n < metadata.getLength(); n ++) {
+      Node node = metadata.item(n);
+      Element element = (Element) node;
+
+      String name = element.getAttribute("name");
+      if (name == null || name.length() == 0) {
+	continue;
+      }
+
+      String value = element.getAttribute("content");
+      if (value == null || value.length() == 0) {
+	value = name;
+      }
+
+      this.addDocumentMetadata(new MetadataLabel(name), value);
+    }
+    
+    NodeList titles = this.domDocument.getElementsByTagName("TITLE");
+    StringBuffer title = new StringBuffer();
+    for (int n = 0; n < titles.getLength(); n ++) {
+      Node node = titles.item(n);
+      Element element = (Element) node;
+
+      NodeList childNodes = node.getChildNodes();
+      for (int c = 0; c < childNodes.getLength(); c ++) {
+	Node child = childNodes.item(c);
+	if (child.getNodeType() == org.w3c.dom.Node.TEXT_NODE) {
+	  title.append(child.getNodeValue());
+	}
+      }
+    }
+
+    if (title.length() > 0)
+    { this.addDocumentMetadata(new MetadataLabel("Title"), title.toString());
+    }
+
+    /* Old HTMLDoc based parsing...
+    HTMLBlock codedContent = htmlDoc.getCodedContent();
+    boolean inTitle = false;
+    title = new StringBuffer();
+
+    for (int e = 0; e < codedContent.size(); e ++)
+    { if (codedContent.elementAt(e) instanceof HTMLTag)
+      {	HTMLTag tag = (HTMLTag) codedContent.elementAt(e);
+
+        if (tag.tagName().equals("meta"))
+	{ // check that the name of the metadata item exists
+	  String name = tag.idValue("name");
+	  if (name == null || name.length() == 0) {
+	    continue;
+	  }
+
+	  // get the value, if it exists
+	  String value = tag.idValue("content");
+
+	  // if value does not exist, default it to being the same
+	  // as the name.
+	  if (value == null || value.length() > 0) {
+	    value = name;
+	  }
+	}
+	else 
+	if (tag.tagName().equals("title"))
+	{ inTitle = true;
+	}
+	else if (tag.tagName().equals("/title"))
+	{ inTitle = false;
+	}
+	// cut off when real body content appears - not a perfect
+        // implementation, just cheap & cheerful
+	else if (tag.tagName().equals("/head"))
+	{ break;
+	}
+	else if (tag.tagName().equals("body"))
+	{ break;
+	}
+      }
+      else if (inTitle == true)
+      { title.append(codedContent.elementAt(e).toString());
+      }
+    }
+      */
+  }
+
+  private void _extractDocumentFiles()
+  { URL homeUrl = this.fileSet.getFile(0).getLocation();
+
+    NodeList metadata = this.domDocument.getElementsByTagName("img");
+    for (int n = 0; n < metadata.getLength(); n ++) {
+      Node node = metadata.item(n);
+      Element element = (Element) node;
+
+      String location = element.getAttribute("src");
+      if (location == null || location.length() == 0) {
+	System.out.println("No name");
+	continue;
+      }
+      try 
+      { // make the url for the image, and then add it to the document list of
+	// 
+	URL imgUrl = new URL(homeUrl, location);
+	METSFile file = this.fileSet.addFile(imgUrl);
+	this.structureSet.getStructure("All").getDivision("All").addFileReference(file.getID());
+      }
+      catch (MalformedURLException ex)
+      { // TODO: report exception/failure to resolve...
+      }
+    }
+
+  
+    /**    
+    HTMLBlock codedContent = htmlDoc.getCodedContent();
+    for (int e = 0; e < codedContent.size(); e ++)
+    { if (codedContent.elementAt(e) instanceof HTMLTag)
+      { HTMLTag tag = (HTMLTag) codedContent.elementAt(e);
+
+        if (tag.tagName().equals("img"))
+	{ String location = tag.idValue("src");
+
+	  try 
+	  { // make the url for the image, and then add it to the document list of
+	    // 
+	    URL imgUrl = new URL(homeUrl, location);
+	    METSFile file = this.fileSet.addFile(imgUrl);
+	    this.structureSet.getStructure("All").getDivision("All").addFileReference(file.getID());
+	  }
+	  catch (MalformedURLException ex)
+	  { // TODO: report exception/failure to resolve...
+	  }
+	}
+      }
+    }
+    */
+  }
+
+  public String getDocumentType()
+  { return HTML_DOCUMENT_TYPE;
+  }
+
+    // I think this is used for single section documents, while getSectionText
+    // is used for sectioned documents
+    // we will use the domDocument rather than reading it in again to another HTMLDoc.
+  public String getDocumentText()
+  { 
+      XMLConverter converter = new XMLConverter();
+      return converter.getPrettyString(this.domDocument.getDocumentElement());
+      /*  HTMLDoc htmlDoc;
+    URL     url =(URL) this.fileSet.getFile(0).getLocation();
+
+    this.getSectionText("1");
+
+    if (url.getProtocol().equals("file"))
+    { htmlDoc = new HTMLDoc(url, url.getPath());
+    }
+    else
+    { htmlDoc = new HTMLDoc(url);
+    }
+    return htmlDoc.getContent();
+      */ 
+  }
+
+    private void resolveImages() {
+
+	// find the path of the url relative to the collection
+	URL full_path = this.fileSet.getFile(0).getLocation();
+       
+	String base_url;
+	if (full_path.getProtocol().equals("file")) {
+	    base_url = full_path.getPath();
+	    int import_pos = base_url.indexOf("import");
+	    base_url = base_url.substring(import_pos);
+	    base_url = "_httpcollection_/"+base_url;
+	} else {
+	    base_url = full_path.toString();
+	}
+
+	// need to take off the last part
+	base_url = base_url.substring(0, base_url.lastIndexOf("/")+1);
+
+	NodeList metadata = this.domDocument.getElementsByTagName("img");
+	for (int n = 0; n < metadata.getLength(); n ++) {
+	    Node node = metadata.item(n);
+	    Element element = (Element) node;
+	    
+	    String location = element.getAttribute("src");
+	    if (location != null && location.length() > 0 && isRelative(location)) {
+		// modify the source url
+		element.setAttribute("src", base_url+location);
+	    }
+	}
+    }
+
+    private boolean isRelative(String location) {
+
+	if ( location.startsWith("http:") || location.startsWith("file:")) {
+	    return false;
+	}
+	return true;
+    }
+    
+    public Document getDOMDocument()
+    {    
+      if (this.domDocument == null) {
+      URL     url =(URL) this.fileSet.getFile(0).getLocation();
+      this.loadDocument(url);
+      resolveImages();
+    }
+    return this.domDocument;
+  }
+
+  private XPointer getXPointer(METSDivision division)
+  { String fileId = division.getDefaultFileReference();
+
+    if (fileId == null) {
+      System.err.println("Unable to obtain file reference for section " + division.getLabel());
+      return null;
+    }
+
+    METSFileGroup fileGroup = this.getDocumentFiles().getGroup(fileId);
+    if (fileGroup == null) {
+      System.err.println("Unable to obtain file reference for filegroup " + fileId);
+      return null;
+    }
+
+    METSFile file = fileGroup.getFile(0);
+    if (file == null) {
+      System.err.println("Unable to obtain any files within filegroup " + fileId);
+      return null;
+    }
+
+    URL url = file.getLocation();
+    XPointer xpointer = XPointer.processXPointer(this.domDocument, url);
+
+    return xpointer;
+  }
+
+  private XPointer getXPointer(String sectionId)
+  { if (this.domDocument == null) {
+      URL     url =(URL) this.fileSet.getFile(0).getLocation();
+      this.loadDocument(url);
+      resolveImages();
+    }
+
+    METSDivision division = 
+      this.getDocumentStructure().getDivision(METSStructureSet.GSDL3_SECTION_STRUCTURE, 
+					      sectionId);
+    if (division == null) {
+      //      System.err.println("Unable to locate section " + sectionId);
+      return null; 
+    }
+
+    return this.getXPointer(division);
+  }
+  
+  public Node getSectionStartNode(METSDivision division)
+  { XPointer xpointer = this.getXPointer(division);
+    return xpointer.getStartNode();
+  }
+
+  public Node getSectionStartNode(String sectionId)
+  { XPointer xpointer = this.getXPointer(sectionId);
+
+    return xpointer.getStartNode();
+  }
+
+  public String getSectionText(String sectionId)
+  { XPointer xpointer = this.getXPointer(sectionId);
+
+    if (xpointer == null) {
+      return "";
+    }
+
+    // get the XML content of the xpointer...
+    return xpointer.toString();
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/HTMLDocumentTools.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/HTMLDocumentTools.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/HTMLDocumentTools.java	(revision 13666)
@@ -0,0 +1,328 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import org.w3c.dom.*;
+
+import java.net.URL;
+
+import java.util.List;
+import java.util.ArrayList;
+
+import org.greenstone.gsdl3.gs3build.metadata.METSStructureSet;
+import org.greenstone.gsdl3.gs3build.metadata.AbstractStructure;
+import org.greenstone.gsdl3.gs3build.metadata.METSStructure;
+import org.greenstone.gsdl3.gs3build.metadata.METSDivision;
+import org.greenstone.gsdl3.gs3build.metadata.METSDescriptive;
+import org.greenstone.gsdl3.gs3build.metadata.METSFileSet;
+import org.greenstone.gsdl3.gs3build.metadata.METSFileGroup;
+import org.greenstone.gsdl3.gs3build.metadata.METSFile;
+import org.greenstone.gsdl3.gs3build.metadata.METSFilePos;
+import org.greenstone.gsdl3.gs3build.metadata.METSFileID;
+import org.greenstone.gsdl3.gs3build.metadata.MetadataLabel;
+import org.greenstone.gsdl3.gs3build.doctypes.AbstractDocument;
+import org.greenstone.gsdl3.gs3build.util.*;
+
+public class HTMLDocumentTools
+{
+  Document          document;
+  URL               documentUrl;
+  int               sectionLevel;
+  StringBuffer      sectionLabel;
+  List              sectionSeq;
+  HTMLSection       rootSection;
+  HTMLSection       currentSection;
+  int               sectionSeqNo;
+  METSStructure     metsStructure;
+  AbstractStructure currentMets;
+  AbstractDocument  metsDocument;
+
+  /**
+   *
+   */
+  class HTMLSection
+  { String startLocation;
+    String endLocation;
+    String label;
+    List   children;
+    HTMLSection parent;
+    int         seqNo;
+
+    public HTMLSection(String label, int seqNo)
+    { this.label = label;
+      this.seqNo = seqNo;
+      this.parent = null;
+      this.children = new ArrayList();
+    }
+    
+    public void setStartLocation(String location)
+    { this.startLocation = location;
+    }
+    
+    public void setEndLocation(String location)
+    { this.endLocation = location;
+    }
+
+    public void addChild(HTMLSection child)
+    { this.children.add(child);
+      child.parent = this;
+    }
+    
+    public HTMLSection getParent()
+    { return this.parent;
+    }
+
+    public String getLabel()
+    { return this.label;
+    }
+
+    public String getXPointer()
+    { StringBuffer xPointerBuffer = new StringBuffer();
+    
+      xPointerBuffer.append("xpointer(");
+      xPointerBuffer.append(this.startLocation);
+      xPointerBuffer.append("/range-to(");
+      xPointerBuffer.append(this.endLocation);
+      xPointerBuffer.append("))");
+      
+      return xPointerBuffer.toString();
+    }
+  }
+
+  public HTMLDocumentTools(Document document)
+  { this.document = document;
+    this.sectionLevel = 0;
+    this.sectionSeq   = new ArrayList();
+    this.sectionSeq.add(new Integer(0));
+    this.sectionLabel = new StringBuffer();
+    this.rootSection = new HTMLSection("", 0);
+    this.currentSection = this.rootSection;
+    this.metsStructure  = new METSStructure(METSStructureSet.GSDL3_SECTION_STRUCTURE, 
+					    "Section", "Section");
+    this.currentMets    = this.metsStructure;
+    this.metsDocument   = null;
+  }
+
+  public void setMetsDocument(AbstractDocument document)
+  { this.metsDocument = document;
+  }
+
+  public void setUrl(URL url)
+  { this.documentUrl = url;
+  }
+
+  public Object findSections()
+  { this.findSections(document.getDocumentElement(), "/1");
+    return this.rootSection;
+  }
+
+  public void findSections(Node node, String location)
+  { // if at an element, then we aren't going to find section information,
+    // but we do need to recurse into the children to find the section markers
+    // there
+    if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
+      NodeList children = node.getChildNodes();
+      StringBuffer locationBuffer = new StringBuffer();
+      locationBuffer.append(location);
+      locationBuffer.append("/");
+
+      int elementNo = 1;
+      int commentNo = 1;
+      for (int c = 0; c < children.getLength(); c++)
+      {
+	locationBuffer.setLength(location.length()+1);
+	if (children.item(c).getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
+	  locationBuffer.append(Integer.toString(elementNo));
+	  elementNo ++;
+	}
+	else if (children.item(c).getNodeType() == org.w3c.dom.Node.COMMENT_NODE) {
+	  locationBuffer.append("comment()[");
+	  locationBuffer.append(Integer.toString(commentNo));
+	  locationBuffer.append("]");
+	  commentNo ++;
+	}
+	this.findSections(children.item(c), locationBuffer.toString());
+      }
+    }
+    // if at a comment node, then one needs to dissect it to discover if
+    // any section markings are included...
+    else if (node.getNodeType() == org.w3c.dom.Node.COMMENT_NODE) {
+      String commentText = node.getNodeValue();
+      
+      // parse the node now...checking first for any 'section' items in
+      // it - this is a crude check...
+      if (commentText.indexOf("<Section>") >= 0 ||
+	  commentText.indexOf("</Section>") >= 0) {
+	// parse the section roughly using the primitive HTMLDoc form...      
+	HTMLDoc innerDoc     = HTMLDoc.fromString("dummy", commentText);
+	HTMLBlock innerHtml  = innerDoc.getCodedContent();
+	boolean   inMetadata = false;
+	StringBuffer metaValue = new StringBuffer();
+	String       metaLabel = null;
+
+	// Now just go through the content in sequence...
+	for (int e = 0; e < innerHtml.size(); e ++) {
+	  Object element = innerHtml.elementAt(e);
+
+	  if (element instanceof HTMLTag) {
+	    HTMLTag tag = (HTMLTag) element;
+
+	    if (tag.tagName().equals("section")) {
+	      // get the counters sorted out for the sections...
+	      this.sectionSeq.set(this.sectionLevel, new Integer(((Integer) this.sectionSeq.get(this.sectionLevel)).intValue() + 1));
+	      this.sectionLevel ++;
+	      if (sectionSeq.size() == this.sectionLevel) {
+		this.sectionSeq.add(new Integer(0));
+	      }
+	      else {
+		this.sectionSeq.set(this.sectionLevel, new Integer(0));
+	      }
+
+	      // create the label for the new section...
+	      this.sectionLabel.setLength(0);
+	      for (int s = 0; s < sectionLevel; s ++) {
+		if (s > 0) {
+		  this.sectionLabel.append(".");
+		}
+		this.sectionLabel.append(this.sectionSeq.get(s).toString());
+	      }
+
+	      // note the new section in a new data structure...
+	      HTMLSection newSection = new HTMLSection(this.sectionLabel.toString(), this.sectionSeqNo);
+
+	      newSection.setStartLocation(location);
+	      this.currentSection.addChild(newSection);
+	      this.currentSection = newSection;
+
+	      // do the same for mets...
+	      METSDivision newDivision = new METSDivision("DS" + Integer.toString(this.sectionSeqNo), Integer.toString(this.sectionSeqNo),
+							  this.sectionLabel.toString(), this.sectionLabel.toString(), "Section");
+	      this.currentMets.addDivision(newDivision);
+	      this.currentMets = newDivision;
+
+	      this.sectionSeqNo ++;
+	    }
+	    else if (tag.tagName().equals("/section")) {
+	      // cope with poorly formed metadata...
+	      if (inMetadata) {
+		this.postMetadata(metaLabel, metaValue.toString());
+	      }
+
+	      // note the end position of the section
+	      this.currentSection.setEndLocation(location);
+
+	      // now post that section to the file list...
+	      this.postFilePtr(this.currentSection);
+
+	      // backtrack up the section tree...
+	      this.currentSection = this.currentSection.getParent();
+	      this.currentMets = this.currentMets.getParent();
+	      this.sectionLevel --;
+
+	      // trim the section label
+	      int cutTo = this.sectionLabel.toString().lastIndexOf('.');
+	      if (cutTo >= 0) {
+		this.sectionLabel.setLength(cutTo);
+	      }
+	      else {
+		this.sectionLabel.setLength(0);
+	      }
+
+	      // we can't be in metadata either...
+	      inMetadata = false;
+	    }
+	    else if (tag.tagName().equals("metadata")) {
+	      if (inMetadata) {
+		// post the metadata
+		this.postMetadata(metaLabel, metaValue.toString());
+	      }
+	      metaValue.setLength(0);
+	      metaLabel = tag.idValue("name");
+	      inMetadata = (metaLabel != null);
+	    }
+	    else if (tag.tagName().equals("/metadata")) {
+	      // post the metadata
+	      this.postMetadata(metaLabel, metaValue.toString());
+	      inMetadata = false;
+	    }
+	  }
+	  else {
+	    if (inMetadata) {
+	      metaValue.append(element.toString());
+	    }
+	  }
+	}
+      }
+    }
+  }
+
+  private String makeXPointer(HTMLSection section)
+  { StringBuffer xPointerBuffer = new StringBuffer();
+
+    if (this.documentUrl != null)
+    { xPointerBuffer.append(this.documentUrl.toString());
+      xPointerBuffer.append("#");
+    }
+    xPointerBuffer.append(section.getXPointer());
+
+    return xPointerBuffer.toString();
+  }
+
+  private void postFilePtr(HTMLSection section)
+  { String xPointer = this.makeXPointer(section);
+
+    if (this.metsDocument == null) {
+      return;
+    }
+
+    try {
+      URL url = new URL(xPointer);
+
+      METSFileSet fileSet = this.metsDocument.getDocumentFiles();
+
+      METSFilePos filePos = new METSFilePos(url);
+      METSFile    file = fileSet.createFile(filePos, "text/html");
+      
+      METSFileGroup fileGroup;
+      String fileRef = ((METSDivision) this.currentMets).getDefaultFileReference();
+
+      if (fileRef == null) {
+	fileGroup = fileSet.createGroup();
+	fileSet.addGroup(fileGroup);
+	((METSDivision) this.currentMets).addFileReference(fileGroup.getId());
+      }
+      else {
+	// simple call - the group should be at the 'root' level, immediately below
+	// the FileSet itself...
+	fileGroup = fileSet.getGroup(fileRef);
+      }
+      fileGroup.addFile(file);
+
+      
+    }
+    catch (java.net.MalformedURLException ex) {
+      System.err.println(ex + " " + xPointer);
+    }
+  }
+
+  private void postMetadata(String label, String value)
+  {
+    if (this.metsDocument == null) {
+      return;
+    }
+
+    String metadataRef = ((METSDivision) this.currentMets).getDefaultMetadataReference();
+    METSDescriptive descriptive;
+    if (metadataRef == null) {
+      descriptive = this.metsDocument.getDocumentMetadata().createDescriptive(this.currentSection.getLabel());
+      ((METSDivision) this.currentMets).addMetadataReference(descriptive.getID());
+    }
+    else {
+      descriptive = this.metsDocument.getDocumentMetadata().getDescriptiveById(metadataRef);
+    }
+    descriptive.addMetadata(MetadataLabel.getDefaultNamespace(), label, value);
+  }
+
+  public METSStructure getStructure()
+  { return this.metsStructure;
+  }
+}
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/HTMLRecogniser.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/HTMLRecogniser.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/HTMLRecogniser.java	(revision 13666)
@@ -0,0 +1,19 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.util.ArrayList;
+
+public class HTMLRecogniser extends AbstractRecogniser
+{
+    
+    public HTMLRecogniser()
+    { 
+	this.preferred_mime_type = "text/html";
+	this.filename_extensions = new ArrayList();
+	this.filename_extensions.add(".htm");
+	this.filename_extensions.add(".html");
+	this.document_type = HTMLDocument.HTML_DOCUMENT_TYPE;
+	
+    }
+    
+
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/IndexDocument.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/IndexDocument.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/IndexDocument.java	(revision 13666)
@@ -0,0 +1,58 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.greenstone.gsdl3.gs3build.metadata.METSDescriptiveSet;
+import org.greenstone.gsdl3.gs3build.util.MultiMap;
+
+/**
+ *  A metadata-pure document - it only contains metadata
+ *  on other documents, and this will be added to them during
+ *  the "extract" phase.  The decoration of the other documents
+ *  with this extra metadata will only occur later, as at the
+ *  point that this document/file is loaded, we may not in fact
+ *  have come across them yet...
+ */
+
+public class IndexDocument extends AbstractDocument
+{
+  public static final String INDEX_DOCUMENT_TYPE = "GSINDEX";
+
+  public IndexDocument(DocumentID id)
+  { super(id);
+  }
+
+  public IndexDocument(URL url)
+  { super(url);
+  }
+  
+  public String getDocumentType()
+  { return INDEX_DOCUMENT_TYPE;
+  }
+
+  /**
+   *  A pretty minimal and lazy document text extraction process.
+   */
+  public String getDocumentText()
+  { return "";
+  }
+
+  public String getSectionText(String sectionId)
+  { return "";
+  }
+
+  /**
+   *  Indicate whether this document is indexed.
+   *
+   *  @see: DocumentInterface.isIndexed
+   */
+  public boolean isIndexed()
+  {
+    return true;
+  }
+
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/IndexRecogniser.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/IndexRecogniser.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/IndexRecogniser.java	(revision 13666)
@@ -0,0 +1,52 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.io.*;
+import java.net.*;
+import java.util.ArrayList;
+
+import org.greenstone.gsdl3.gs3build.metadata.*;
+
+public class IndexRecogniser extends AbstractRecogniser
+{
+    
+    public IndexRecogniser(DocumentList listRepository)
+    { 
+	this.preferred_mime_type = "text/plain";
+	this.filename_extensions = new ArrayList();
+	this.filename_extensions.add("index.txt");
+	this.document_type = IndexDocument.INDEX_DOCUMENT_TYPE;
+    }
+    
+
+    public boolean parseDocument(URL url)
+    { 
+	String filename = null;
+
+	if (url.getProtocol().equals("file")) {
+	    filename = url.getPath();
+	}
+	
+	if (filename != null) {
+	    String leafName;
+	    int leafAt = filename.lastIndexOf(File.separator);
+	    if (leafAt >= 0) {
+		leafName = filename.substring(leafAt+1);
+	    } else {
+		leafName = filename;
+	    }
+
+	    if (leafName.equals("index.txt")) {
+		
+		System.out.println("Posting Index Document " + filename);
+		IndexDocument doc = new IndexDocument(url);
+		this.list_repository.addDocument(doc);
+		// TODO: spawn knowledge of children too...
+		//				System.out.println(doc.getDocumentText());
+		return true;
+	    }
+	} else {
+	    // TODO: get Mime type remotely, and then proceed if required
+	}
+	return false;
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/JPEGDocument.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/JPEGDocument.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/JPEGDocument.java	(revision 13666)
@@ -0,0 +1,42 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.io.File;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+import java.util.ArrayList;
+
+/**
+ *  Another fairly basic class for representing JPEG documents.
+ */
+
+public class JPEGDocument extends AbstractDocument
+{
+  public static final String JPEG_DOCUMENT_TYPE = "JPEG";
+
+  public JPEGDocument(DocumentID id)
+  { super(id);
+  }
+  
+  public JPEGDocument(URL url)
+  { super(url);
+  }
+
+  public String getDocumentType()
+  { return JPEG_DOCUMENT_TYPE;
+  }
+
+  public String getDocumentText()
+  { // Just a dummy function for JPEGs
+    return "";
+  }
+
+  public String getSectionText(String sectionId)
+  { // Just a dummy function for JPEGs
+    return "";
+  }
+
+  public boolean isMETSCompatible()
+  { return true;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/JPEGRecogniser.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/JPEGRecogniser.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/JPEGRecogniser.java	(revision 13666)
@@ -0,0 +1,17 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.util.ArrayList;
+
+public class JPEGRecogniser extends AbstractRecogniser
+{
+    
+    public JPEGRecogniser()
+    { 
+	this.preferred_mime_type = "image/jpeg";
+	this.filename_extensions = new ArrayList();
+	this.filename_extensions.add(".jpg");
+	this.filename_extensions.add(".jpeg");
+	this.document_type = JPEGDocument.JPEG_DOCUMENT_TYPE;
+    }
+    
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/METSDocument.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/METSDocument.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/METSDocument.java	(revision 13666)
@@ -0,0 +1,249 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.io.*;
+
+import java.net.URL;
+
+import javax.xml.parsers.*;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import org.greenstone.gsdl3.gs3build.metadata.*;
+import org.greenstone.gsdl3.gs3build.util.HTMLDoc;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+import org.greenstone.gsdl3.gs3build.xpointer.XPointer;
+
+public class METSDocument extends AbstractDocument {
+
+    public static final String METS_DOCUMENT_TYPE = "METS";
+    Document domDocument;
+    public METSDocument(DocumentID id) {
+    	super(id);
+	//domDocument = null;
+    }
+
+    public METSDocument(URL url) {
+	super(url);
+	
+	if (url.getProtocol().equals("file")) {
+	    this._parseFile(new File(url.getPath()));
+	} else {
+	    System.err.println("Error: METSDocument must currently be a file");
+	    System.err.println("       URL = " + url.getPath());
+	}
+    }
+    
+    private void _parseFile(File file) {
+	
+	String parseFilePath;
+	try {
+	    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+	    DocumentBuilder builder = factory.newDocumentBuilder();
+	    domDocument = builder.parse(file);
+
+	    int filePosition = file.getPath().indexOf("import/")+7;
+	    parseFilePath = file.getPath().substring(0, filePosition);
+	    // TODO: get all the types in the tree
+      
+	    // TODO: do a traverse, and thus cope with elements-within-elements if needsbe, but
+	    // this shouldn't happen except in a directly defined situation - actually doing the
+	    // parsing in part inside each node would work well provided one checked for a node
+	    // having already been done...
+	    System.out.println("Read");
+      
+	    // Get METSDmdSec metadata sections
+	    NodeList dmdSecs = domDocument.getElementsByTagName("mets:dmdSec");
+	    
+	    this.metadata = METSDescriptiveSet.parseXML(dmdSecs);
+
+	    // Get METSFileSec sections
+	    NodeList fileSecs = domDocument.getElementsByTagName("mets:fileSec");
+	    this.fileSet = METSFileSet.parseXML(fileSecs, fileSet, parseFilePath);
+	    // Get METSStructureMap Sections
+	    NodeList structMapSecs = domDocument.getElementsByTagName("mets:structMap");
+	    this.structureSet = METSStructureSet.parseXML(structMapSecs);
+
+	    //for (int g = 0; g < fileSecs.getLength(); g ++) {
+		//Schema schema = new Schema(schemas.item(s));
+		//this._parseFileSec(fileSecs.item(g));
+	    //}
+      
+	    // Get document metadata sections
+	    //NodeList dmdSecs = document.getElementsByTagName("mets:dmdSec");
+      
+	    //Schema schema = new Schema(schemas.item(s));
+	    //this.metadata = METSDescriptiveSet.parseXML(fileSecs);
+	} catch (FactoryConfigurationError e) {
+	    System.out.println(e);
+	} catch (ParserConfigurationException ex) {
+	    System.out.println(ex);
+	} catch (SAXException ex) {
+	    System.out.println(ex);
+	} catch (IOException ex) {
+	    System.out.println(ex);
+	}
+    }
+    /*
+    private void _parseFileSec(Node fileSec) {
+	// this is in effect a group without a sense of 'self'...
+	this._parseFileGroup((Element) fileSec, null);
+    }
+
+    private void _parseFileGroup(Element groupTag, METSFileGroup group) {
+	NodeList children = groupTag.getChildNodes();
+
+	for (int c = 0; c < children.getLength(); c ++) {
+	    if (children.item(c).getNodeType() != org.w3c.dom.Node.ELEMENT_NODE) {
+		continue;
+	    }
+
+	    System.out.println(children.item(c));
+    
+	    Element element = (Element) children.item(c);
+
+	    if (element.getNodeName().equals("mets:File")) {
+		if (group != null) {
+		    METSFile file = METSFile.parseXML(element, group);
+		} else {
+		    // TODO: error
+		}
+	    } else if (element.getNodeName().equals("mets:fileGrp")) {
+		// recurse
+		METSFileGroup childGroup = new METSFileGroup(element.getAttribute("ID"));
+
+		this._parseFileGroup(element, childGroup);
+		if (group != null) {
+		    group.addGroup(childGroup);
+		} else { 
+		    this.fileSet.addGroup(childGroup);
+		}
+	    }
+	}
+	}*/
+	
+    public String getDocumentType() {
+	return METS_DOCUMENT_TYPE;
+    }
+	
+    public String getDocumentText() {
+	// TODO: make this more than a dummy function!
+	HTMLDoc metsDoc;
+	URL url = (URL) this.fileSet.getFile(0).getLocation();
+
+	this.getSectionText("1");
+	
+	if (url.getProtocol().equals("file")) {
+	    metsDoc = new HTMLDoc(url,url.getPath());
+	} else {
+	    metsDoc = new HTMLDoc(url);
+	}
+	return metsDoc.getContent();
+    }
+    public Document getDOMDocument() 
+    {
+	if (domDocument == null) {
+	    URL url = (URL) this.fileSet.getFile(0).getLocation();
+	    try {
+		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+		DocumentBuilder builder = factory.newDocumentBuilder();
+		domDocument = builder.parse(new File(url.getPath()));
+	    } catch (FactoryConfigurationError e) {
+		System.out.println(e);
+	    } catch (ParserConfigurationException ex) {
+		System.out.println(ex);
+	    } catch (SAXException ex) {
+		System.out.println(ex);
+	    } catch (IOException ex) {
+		System.out.println(ex);
+	    }
+	}
+	return domDocument;
+    }
+
+    private XPointer getXPointer(METSDivision division)
+    {
+	String fileId = division.getDefaultFileReference();
+
+	if (fileId == null) {
+	    System.err.println("Unable to obtain file reference for section " + division.getLabel());
+	    return null;
+	}
+	
+	METSFileGroup fileGroup = this.getDocumentFiles().getGroup(fileId);
+	if (fileGroup == null) {
+	    System.err.println("Unable to obtain file reference for filegroup " + fileId);
+	    return null;
+	}
+	METSFile file = fileGroup.getFile(0);
+	if (file == null) {
+	    System.err.println("Unable to obtain any files within filegroup " + fileId);
+	    return null;
+	}
+	URL url = file.getLocation();
+	XPointer xpointer = XPointer.processXPointer(domDocument, url);
+	
+	return xpointer;
+    }
+    
+    private XPointer getXPointer(String sectionId)
+    {
+	if (domDocument == null) {
+	    URL url = (URL) this.fileSet.getFile(0).getLocation();
+	    try {
+		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+		DocumentBuilder builder = factory.newDocumentBuilder();
+		domDocument = builder.parse(new File(url.getPath()));
+	    } catch (FactoryConfigurationError e) {
+		System.out.println(e);
+	    } catch (ParserConfigurationException ex) {
+		System.out.println(ex);
+	    } catch (SAXException ex) {
+		System.out.println(ex);
+	    } catch (IOException ex) {
+		System.out.println(ex);       
+	    }
+	}
+	
+	METSDivision division = 
+	    this.getDocumentStructure().getDivision(METSStructureSet.GSDL3_SECTION_STRUCTURE, sectionId);
+	
+	if(division == null) {
+	    return null;
+	}
+      	return this.getXPointer(division);
+    }
+
+    public Node getSectionStartNode(METSDivision division)
+    {
+	XPointer xpointer = this.getXPointer(division);
+	return xpointer.getStartNode();
+    }
+
+    public Node getSectionStartNode(String sectionId)
+    {
+	XPointer xpointer = this.getXPointer(sectionId);
+	return xpointer.getStartNode();
+    }
+    
+    public String getSectionText(String sectionId) 
+    {
+	XPointer xpointer = this.getXPointer(sectionId);
+	
+	if (xpointer == null) {
+	    return "";
+	}
+
+	//get the XML content of the xpointer
+	return xpointer.toString();
+    }
+}
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/MetadataDocument.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/MetadataDocument.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/MetadataDocument.java	(revision 13666)
@@ -0,0 +1,58 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.greenstone.gsdl3.gs3build.metadata.METSDescriptiveSet;
+import org.greenstone.gsdl3.gs3build.util.MultiMap;
+
+/**
+ *  A metadata-pure document - it only contains metadata
+ *  on other documents, and this will be added to them during
+ *  the "extract" phase.  The decoration of the other documents
+ *  with this extra metadata will only occur later, as at the
+ *  point that this document/file is loaded, we may not in fact
+ *  have come across them yet...
+ */
+
+public class MetadataDocument extends AbstractDocument
+{
+  public static final String METADATA_DOCUMENT_TYPE = "GSMETADATA";
+
+  public MetadataDocument(DocumentID id)
+  { super(id);
+  }
+
+  public MetadataDocument(URL url)
+  { super(url);
+  }
+  
+  public String getDocumentType()
+  { return METADATA_DOCUMENT_TYPE;
+  }
+
+  /**
+   *  A pretty minimal and lazy document text extraction process.
+   */
+  public String getDocumentText()
+  { return "";
+  }
+
+  public String getSectionText(String sectionId)
+  { return "";
+  }
+
+  /**
+   *  Indicate whether this document is indexed.
+   *
+   *  @see: DocumentInterface.isIndexed
+   */
+  public boolean isIndexed()
+  {
+    return false;
+  }
+
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/MetadataRecogniser.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/MetadataRecogniser.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/MetadataRecogniser.java	(revision 13666)
@@ -0,0 +1,42 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+//import java.io.*;
+import java.net.URL;
+import java.util.ArrayList;
+
+
+public class MetadataRecogniser extends AbstractRecogniser
+{
+
+    public MetadataRecogniser()
+    { 
+	this.preferred_mime_type = "text/xml";
+	this.filename_extensions = new ArrayList();
+	this.filename_extensions.add("metadata.xml");
+	this.document_type = MetadataDocument.METADATA_DOCUMENT_TYPE;
+    }
+
+    public boolean parseDocument(URL url)
+    { 
+	String filename = null;
+	
+	if (url.getProtocol().equals("file")) {
+	    filename = url.getPath();
+	}
+	
+	if (filename != null) {
+	    if (isAcceptedFilename(filename)) {
+		
+		System.out.println("Posting Metadata Document " + filename);
+		MetadataDocument doc = new MetadataDocument(url);
+		this.list_repository.addDocument(doc);
+		// TODO: spawn knowledge of children too...
+		// System.out.println(doc.getDocumentText());
+		return true;
+	    }
+	} else {
+	    // TODO: get Mime type remotely, and then proceed if required
+	}
+	return false;
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/RecogniserInterface.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/RecogniserInterface.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/RecogniserInterface.java	(revision 13666)
@@ -0,0 +1,19 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.net.URL;
+import org.w3c.dom.Element;
+
+import org.greenstone.gsdl3.gs3build.metadata.*;
+
+/** Interface for Recogniser Objects
+ *
+ * A skeleton class is provided for simple Recognisers (AbstractRecogniser)
+ * 
+*/
+public interface RecogniserInterface
+{
+    public boolean configure(Element config_elem);
+    public void setListRepository(DocumentList docList);
+    public boolean parseDocument(METSFile fileReference);
+    public boolean parseDocument(URL fileReference);
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/RecogniserManager.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/RecogniserManager.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/RecogniserManager.java	(revision 13666)
@@ -0,0 +1,89 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import org.greenstone.gsdl3.gs3build.FileCrawlObserver;
+
+import java.io.File;
+import java.net.URL;
+
+import org.greenstone.gsdl3.gs3build.util.URLTools;
+
+public class RecogniserManager implements FileCrawlObserver
+{
+  RecogniserInterface list[];
+  int                 used;
+  int                 size;
+    DocumentList docList;
+  public RecogniserManager(DocumentList documentList)
+  { this.list = new RecogniserInterface[10];
+    this.used = 0;
+    this.size = 10;
+    this.docList = documentList;
+  }
+
+  /**
+   *  Add a recogniser to this manager
+   */
+    public RecogniserInterface addRecogniser(String documentType)
+    { 
+	ClassLoader loader = ClassLoader.getSystemClassLoader();
+	java.lang.Class thisClass = null;
+	try {
+	    thisClass = loader.loadClass("org.greenstone.gsdl3.gs3build.doctypes." + documentType + "Recogniser");
+	    Object instance = thisClass.newInstance();
+	    this.addRecogniser((RecogniserInterface) instance);
+	    return (RecogniserInterface)instance;
+	}
+	catch (ClassNotFoundException ex) {
+	    System.err.println(ex);
+	    return null;
+	}
+	catch (InstantiationException instEx) {
+	    System.err.println(instEx);
+	}
+	catch (IllegalAccessException accEx) {
+	    System.err.println(accEx);
+	}
+	return null;
+    }
+    
+  /**
+   *
+   */
+    public void addRecogniser(RecogniserInterface recogniser)
+    {  
+	recogniser.setListRepository(this.docList);
+	this.ensureCapacity(this.used + 1);
+  
+	this.list[this.used] = recogniser;
+	this.used ++;
+    }
+
+  public void processFile(URL url)
+  { boolean result;
+
+    for (int r = 0; r < this.used; r ++)
+    { if (list[r].parseDocument(url)) {
+        break;
+      }
+    }
+  }
+ 
+  public void processFile(File file)
+  { 
+      System.err.println("processing file "+file.getPath());
+      URL url = URLTools.getFileURL(file);
+    
+    if (url != null) 
+    { this.processFile(url);
+    }
+  }
+
+  private void ensureCapacity(int size)
+  { while (size >= this.size)
+    { RecogniserInterface newList [] = new RecogniserInterface[this.size*2];
+      this.size *= 2;
+      System.arraycopy(this.list, 0, newList, 0, this.size);
+      this.list = newList;
+    }
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/TextDocument.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/TextDocument.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/TextDocument.java	(revision 13666)
@@ -0,0 +1,45 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *  A pretty basic DocumentInterface class - just able to
+ *  provide unsophisticated access to the document as plain
+ *  text, and no attempt at metadata extraction
+ */
+
+public class TextDocument extends AbstractDocument
+{
+  public static final String TEXT_DOCUMENT_TYPE = "Text";
+
+  public TextDocument(DocumentID id)
+  { super(id);
+  }
+
+  public TextDocument(URL url)
+  { super(url);
+  }
+
+  public String getDocumentType()
+  { return TEXT_DOCUMENT_TYPE;
+  }
+
+  /**
+   *  A pretty minimal and lazy document text extraction process.
+   */
+  public String getDocumentText()
+  { return DocumentLoader.getAsString((URL) this.fileSet.getFile(0).getLocation());
+  }
+
+  /**
+   *  Text documents don't actually have more than one section (at present), so
+   *  this is a dummy function...
+   */
+  public String getSectionText(String sectionId)
+  { return null;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/TextRecogniser.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/TextRecogniser.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/doctypes/TextRecogniser.java	(revision 13666)
@@ -0,0 +1,22 @@
+package org.greenstone.gsdl3.gs3build.doctypes;
+
+import java.io.*;
+import java.net.*;
+import java.util.ArrayList;
+
+import org.greenstone.gsdl3.gs3build.metadata.*;
+import org.greenstone.gsdl3.gs3build.util.HTTPTools;
+
+public class TextRecogniser extends AbstractRecogniser
+{
+    
+    public TextRecogniser()
+    { 
+	this.preferred_mime_type = "text/plain";
+	this.filename_extensions = new ArrayList();
+	this.filename_extensions.add(".txt");
+	this.filename_extensions.add(".text");
+	this.document_type = TextDocument.TEXT_DOCUMENT_TYPE;
+    }
+    
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/expander/ExpanderInterface.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/expander/ExpanderInterface.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/expander/ExpanderInterface.java	(revision 13666)
@@ -0,0 +1,28 @@
+package org.greenstone.gsdl3.gs3build.expander;
+
+import java.io.File;
+import java.net.URL;
+
+import org.greenstone.gsdl3.gs3build.BuildManager;
+
+public interface ExpanderInterface
+{
+	/**
+	 *  Record the build manager to use for this expander - this is used
+	 *  to pass back any new directories into which expanded files are placed.
+	 */
+	public void configure(BuildManager manager);
+
+	/**
+	 *  Attempt to expand a file.  The returned result is <code>true</code> if the
+	 *  file was actually expanded.
+	 *
+	 *  @param <code>URL</code> the name of the file, or its URL
+	 *  @param <code>File</code> the directory to expand files into - the expander
+	 *         should create its own sub-directory to ensure that no later conflicts
+	 *         emerge.
+	 *
+	 *  @return <code>boolean</code> whether the file was expanded.
+	 */
+	public boolean expandFile(URL fileReference, File expansionDirectory);
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/expander/ZipExpander.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/expander/ZipExpander.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/expander/ZipExpander.java	(revision 13666)
@@ -0,0 +1,81 @@
+package org.greenstone.gsdl3.gs3build.expander;
+
+import java.io.*;
+import java.net.URL;
+import java.util.*;
+
+import org.greenstone.gsdl3.gs3build.BuildManager;
+
+public class ZipExpander implements ExpanderInterface
+{ BuildManager buildManager;
+
+	public ZipExpander()
+	{
+	}
+
+	public void configure(BuildManager manager)
+	{	this.buildManager = manager;
+	}
+
+	public boolean expandFile(URL url, java.io.File expansionDirectory)
+	{ if (url.toString().startsWith("file://")) 
+		{	String fileName = url.toString().substring(7);
+
+			if (fileName.endsWith(".zip"))
+		  {	System.out.println("Expanding Zip file " + fileName);
+
+				// determine which directory to use
+
+				// get the leaf name
+				String leafName;
+				int leafAt = fileName.lastIndexOf(System.getProperty("file.separator"));
+				
+				if (leafAt >= 0)
+				{ leafName = fileName.substring(leafAt+1);
+				}
+				else
+				{	leafName = fileName;
+				}
+
+			  int extensionAt = leafName.lastIndexOf('.');
+				if (extensionAt >= 0)
+				{	leafName = leafName.substring(0, extensionAt);
+				}
+
+				File targetDir = new File(expansionDirectory, leafName);
+				if (targetDir.exists())
+				{	// find alternative name
+					int  extension = 1;
+					File expandedTarget;
+
+					do
+					{ expandedTarget = new File(targetDir.toString() + Integer.toString(extension));
+					} while (expandedTarget.exists());
+
+					targetDir = expandedTarget;
+				}
+				if (!targetDir.mkdir())
+				{	// TODO: pass/log error - unable to make directory to
+					//       expand file.
+					return false;
+				}
+
+				// Call zip expansion
+				try
+				{
+					Runtime.getRuntime().exec("unzip -d "+targetDir.toString());
+				}
+				catch (IOException io)
+				{ // TODO: handle errors - report to log, etc.
+					return false;
+				}
+
+				// ensure that the build manager knows about the new directory,
+				// and will expand any content in it, etc. in turn
+				this.buildManager.addInputDirectory(targetDir.toString());
+				return true;
+			}
+		}
+		return false;
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/extractor/ExtractorInterface.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/extractor/ExtractorInterface.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/extractor/ExtractorInterface.java	(revision 13666)
@@ -0,0 +1,15 @@
+package org.greenstone.gsdl3.gs3build.extractor;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentList;
+
+public interface ExtractorInterface
+{
+  public void configure(String outputDir);
+  public void configure(DocumentList list);
+  public void startPass(int passNumber);
+  public void extractDocument(DocumentID documentID, DocumentInterface document);
+  public void endPass(int passNumber);
+  public int getNumberOfPasses();
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/extractor/ExtractorManager.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/extractor/ExtractorManager.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/extractor/ExtractorManager.java	(revision 13666)
@@ -0,0 +1,62 @@
+package org.greenstone.gsdl3.gs3build.extractor;
+
+import java.util.Iterator;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentList;
+
+public class ExtractorManager
+{
+  public static final String ACCUMULATE_MODE = "accumulate";
+
+  DocumentList          documents;
+  ExtractorInterface [] list;
+  int                   size;
+  int                   used;
+
+  public ExtractorManager(DocumentList documentList)
+  { this.list = new ExtractorInterface[10];
+    this.size = 10;
+    this.used = 0;
+    this.documents = documentList;
+  }
+
+  public void addExtractor(ExtractorInterface extractor)
+  { this.ensureSize(this.used + 1);
+    this.list[this.used] = extractor;
+    this.used ++;
+
+    extractor.configure(this.documents);
+  }
+
+  public void extractDocument(DocumentID docId, DocumentInterface document)
+  { for (int i = 0; i < this.used; i ++)
+    { this.list[i].extractDocument(docId, document);
+    }
+  }
+
+  public void extractDocuments()
+  { for (int i = 0; i < this.used; i ++)
+    { for (int p = 0; p < this.list[i].getNumberOfPasses(); p ++)
+      {	this.list[i].startPass(p);
+
+        Iterator iterator = documents.iterator();
+	while (iterator.hasNext()) {
+	  DocumentInterface document = (DocumentInterface) iterator.next();
+	  this.list[i].extractDocument(document.getID(), document);
+	}
+	this.list[i].endPass(p);
+      }
+    }
+  }
+
+  public void ensureSize(int size)
+  { while (size >= this.size)
+    { ExtractorInterface newList [] = new ExtractorInterface[this.size*2];
+      this.size *= 2;
+      System.arraycopy(this.list, 0, newList, 0, this.size);
+      this.list = newList;
+    }
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/extractor/GMLExtractor.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/extractor/GMLExtractor.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/extractor/GMLExtractor.java	(revision 13666)
@@ -0,0 +1,167 @@
+package org.greenstone.gsdl3.gs3build.extractor;
+
+import java.io.FileReader;
+
+import java.util.List;
+import java.util.ArrayList;
+
+import org.xml.sax.XMLReader;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.Attributes;
+import org.xml.sax.helpers.XMLReaderFactory;
+import org.xml.sax.helpers.DefaultHandler;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentList;
+import org.greenstone.gsdl3.gs3build.doctypes.GMLDocument;
+
+public class GMLExtractor implements ExtractorInterface
+{
+  public static final String ACCUMULATE_MODE = "accumulate";
+
+  /**
+   *  An inner class to handle GML files
+   */
+  class GMLHandler extends DefaultHandler
+  { List   files;
+    String label;
+    StringBuffer value;
+    boolean inElement;
+    boolean accumulate;
+
+    GMLHandler()
+    { super();
+    
+      this.label = null;
+      this.value = null;
+    }
+
+    public void startElement(String URI, String localName, String qName, Attributes attributes)
+    { if (localName.equals("FileName"))
+      {	this.value = new StringBuffer();
+      }
+      else if (localName.equals("FileSet"))
+      { this.files = new ArrayList();
+      }
+      else if (localName.equals("Description"))
+      {
+      }
+      else if (localName.equals("Metadata"))
+      { this.label = attributes.getValue("name");
+        this.value = new StringBuffer();
+
+	String mode = attributes.getValue("mode");
+	this.accumulate = mode.equals(ExtractorManager.ACCUMULATE_MODE);	
+      }
+    }
+
+    public void endElement(String URI, String localName, String qName)
+    { if (localName.equals("FileName"))
+      {	String file = this.value.toString();
+        this.value = null;
+	this.files.add(file);
+      }
+      else if (localName.equals("FileSet"))
+      { // post the existing files item...
+      }
+      else if (localName.equals("Description"))
+      {
+      }
+      else if (localName.equals("Metadata"))
+      { GMLExtractor.postMetadata(this.files, this.label, this.value.toString());
+        this.value = null;
+	this.label = null;
+      }
+    }
+
+    public void characters(char c[], int start, int length)
+    { if (this.value != null)
+      { String string = new String(c, start, length);
+        this.value.append(string);
+      }
+    }
+  }
+
+  /**
+   *  Construct of extractor
+   */
+  public GMLExtractor()
+  { // Intentionally left blank
+  }
+
+  /**
+   *  This extractor doesn't need to do any preparation/completion work,
+   *  so this member function is empty.
+   */
+  public void configure(String outputDir)
+  { // Intentionally left blank
+  }
+
+  public void configure(DocumentList documentList)
+  { // Intentionally left blank
+  }
+
+  /**
+   *  This extractor doesn't need to do any preparation/completion work,
+   *  so this member function is empty.
+   */
+  public void startPass(int passNo)
+  { // Intentionally left blank
+  }
+
+  /**
+   *  Process the document - for a GML document, this results in the
+   *  decoration of other files, for other documents, it does nothing.
+   */
+  public void extractDocument(DocumentID docID, DocumentInterface document)
+  {	
+    if (document.getDocumentType().equals(GMLDocument.GML_DOCUMENT_TYPE))
+    { // Extract the content from the GML file
+      try {
+	XMLReader reader = XMLReaderFactory.createXMLReader();
+	GMLHandler handler = new GMLHandler();
+	reader.setContentHandler(handler);
+	reader.setErrorHandler(handler);
+	  
+	// A GML document consists of one file only - get it from the 'default'
+	// file group
+	FileReader fileReader = new FileReader(document.getDocumentFiles().getFile(0).toString());
+	reader.parse(new InputSource(fileReader));
+      }
+      catch (SAXException saxException)
+      { // TODO: log error
+      }
+      catch (java.io.FileNotFoundException fileException)
+      {
+      }
+      catch (java.io.IOException ioException)
+      {
+      }
+      // for each document post it to the corresponding document
+    }
+  }
+
+  protected static void postMetadata(List files, String value, String label)
+  {
+    
+  }
+
+  /**
+   *  This extractor doesn't need to do any preparation/completion work,
+   *  so this member function is empty.
+   */
+  public void endPass(int passNo)
+  { // Intentionally left blank
+  }
+
+  /**
+   *  This extractor is a simple, single-pass extractor
+   *
+   *  @see: org.greenstone.gsdl3.gs3build.extractor.ExtractorInterface:getNumberOfPasses
+   */
+  public int getNumberOfPasses()
+  { return 1;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/extractor/IndexExtractor.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/extractor/IndexExtractor.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/extractor/IndexExtractor.java	(revision 13666)
@@ -0,0 +1,256 @@
+package org.greenstone.gsdl3.gs3build.extractor;
+
+import java.io.FileReader;
+
+import java.net.URL;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.greenstone.gsdl3.gs3build.util.GS2TextFileHandler;
+
+import org.xml.sax.XMLReader;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.Attributes;
+import org.xml.sax.helpers.XMLReaderFactory;
+import org.xml.sax.helpers.DefaultHandler;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+import org.greenstone.gsdl3.gs3build.doctypes.IndexDocument;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentLoader;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentList;
+
+import org.greenstone.gsdl3.gs3build.metadata.MetadataLabel;
+
+public class IndexExtractor implements ExtractorInterface
+{
+  class IndexHandlerException extends Exception
+  { public IndexHandlerException(String value)
+    { super(value);
+    }
+  }
+
+  /**
+   *  An inner class to handle GML files
+   */
+  class IndexHandler extends GS2TextFileHandler
+  { List    labels;
+    URL     base;
+
+    IndexHandler(String content, URL url, DocumentList documentList) throws IndexHandlerException
+    { 
+      super(content);
+
+      this.labels  = new ArrayList();
+      this.base    = url;
+
+      String parentDir;
+      int leaf = this.base.toString().lastIndexOf('/');
+      if (leaf >= 0) {
+	parentDir = this.base.toString().substring(0, leaf+1);
+      }
+      else {
+	parentDir = this.base.toString();
+      }
+
+      // get the first line
+      this.getLine();
+
+      if (!this.hasMore())
+      { throw new IndexHandlerException("No title line");
+      }
+      
+      // get the first totem - it should be "key:"
+      String entry = this.getEntry(true);
+      
+      // now get all the labels
+      while (this.hasMore())
+      { String label = this.getEntry(true);
+        if (label == null || label.length() == 0) {
+	  continue;
+	}
+	
+	this.labels.add(label);
+	System.out.println("Adding label: " + label);
+      }
+
+      while (this.hasMoreLines()) {
+	this.getLine();
+
+	// Get the file pattern itself
+	String filePattern = this.getEntry(true);
+	if (filePattern == null || filePattern.length() == 0) {
+	  continue;
+	}
+
+	// get a list of documents that match the file pattern
+	List documentIds = documentList.findDocumentIdsUsingFile(filePattern);
+	if (documentIds != null) {
+	  Iterator iterator = documentIds.iterator();
+	  while (iterator.hasNext()) {
+	    System.out.println("Matches file " + iterator.next().toString());
+	  }
+	}
+
+	// if no files match this data, then skip this row
+	// TODO: raise a quality error message
+	if (documentIds == null || documentIds.size() == 0) {
+	  continue;
+	}
+
+	// cache up the documents that match for speed improvements...
+	List documents = new ArrayList();
+	Iterator idIterator = documentIds.iterator();
+	while (idIterator.hasNext()) {
+	  String docIdString = idIterator.next().toString();
+	  System.out.println(docIdString);
+	  DocumentID docId   = new DocumentID(docIdString);
+	  DocumentInterface document = documentList.getDocument(docId);
+	  if (document != null) {
+	    documents.add(document);
+	  }
+	}
+
+	// Next, split the row into the separate metadata items
+	int entryNo = 0;
+	while (this.hasMore()) {
+	  String item = this.getEntry(true);
+	  if (item == null || item.length() == 0) {
+	    entryNo ++;
+	    continue;
+	  }
+
+	  String label = null;
+	  if (item.startsWith("<")) {
+	    int labelEnd = item.indexOf('>');
+	    if (labelEnd >= 0) {
+	      label = item.substring(1, labelEnd);
+
+	      item = item.substring(labelEnd+1, item.length());
+
+	      // eliminate any weird whitespace
+	      item.trim();
+
+	      // cope with a solo 'item' label with no following string
+	      if (item.length() == 0) {
+		entryNo ++;
+		continue;
+	      }
+	    }
+	    // starts with a bracketed label
+	  }
+	  else if (entryNo < this.labels.size()) {
+	    label = (String) this.labels.get(entryNo);
+	  }
+
+	  // Actually post the metadata -
+	  // it may be good to have cached all the documents that we're going to change
+	  // in order to minimise rewrites...
+	  if (label != null) {
+	    Iterator docIterator = documents.iterator();
+	    while (docIterator.hasNext()) {
+	      DocumentInterface document = (DocumentInterface) docIterator.next();
+
+	      // Post to document
+	      // TODO: tailor this to posting documents to *sections* as required...
+	      document.addDocumentMetadata(new MetadataLabel(label), item);
+	      System.out.println("Posting " + label + "=" + item + " to " + parentDir + filePattern);
+	    }
+	  }
+	  entryNo ++;
+	}
+	
+	// write out the modified documents
+	// TODO: nicer/more generalised interface for this and related activity in
+	//       extractor manager (actually, enricher manager);
+	Iterator docIterator = documents.iterator();
+	while (docIterator.hasNext()) {
+	  DocumentInterface document = (DocumentInterface) docIterator.next();
+
+	  System.out.println("Writing modified document " + document.getID());
+	  documentList.storeChangedDocument(document);
+	}
+      }
+    }
+
+  }
+
+  private DocumentList documentList;
+
+  /**
+   *  Construct of extractor
+   */
+  public IndexExtractor()
+  { // Intentionally left blank
+  }
+
+  /**
+   *  This extractor doesn't need to do any preparation/completion work,
+   *  so this member function is empty.
+   */
+  public void configure(String outputDir)
+  { // Intentionally left blank
+  }
+
+  public void configure(DocumentList list)
+  { this.documentList = list;
+  }
+
+  /**
+   *  This extractor doesn't need to do any preparation/completion work,
+   *  so this member function is empty.
+   */
+  public void startPass(int passNo)
+  { // Intentionally left blank
+  }
+
+  /**
+   *  Process the document - for a GML document, this results in the
+   *  decoration of other files, for other documents, it does nothing.
+   */
+  public void extractDocument(DocumentID docID, DocumentInterface document)
+  { if (document.getDocumentType().equals(IndexDocument.INDEX_DOCUMENT_TYPE))
+    { // Extract the content from the index file
+      
+      // get the file
+      String documentText = 
+	DocumentLoader.getAsString(document.getDocumentFiles().getFile(0).getURL());
+	
+      if (documentText == null) {
+	System.err.println("IndexExtractor: Unable to load any content for " + document.getDocumentFiles().getFile(0).toString());
+	return;
+      }
+
+      try {
+	IndexHandler handler = new IndexHandler(documentText, document.getDocumentFiles().getFile(0).getURL(), this.documentList);
+      }
+      catch (IndexHandlerException ex) {
+      }
+      
+      // for each document post it to the corresponding document
+    }
+  }
+
+  protected static void postMetadata(String file, String value, String label)
+  {
+  }
+
+  /**
+   *  This extractor doesn't need to do any preparation/completion work,
+   *  so this member function is empty.
+   */
+  public void endPass(int passNo)
+  { // Intentionally left blank
+  }
+
+  /**
+   *  This extractor is a simple, single-pass extractor
+   *
+   *  @see: org.greenstone.gsdl3.gs3build.extractor.ExtractorInterface:getNumberOfPasses
+   */
+  public int getNumberOfPasses()
+  { return 1;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/extractor/MetaXMLExtractor.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/extractor/MetaXMLExtractor.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/extractor/MetaXMLExtractor.java	(revision 13666)
@@ -0,0 +1,268 @@
+package org.greenstone.gsdl3.gs3build.extractor;
+
+import java.io.FileReader;
+
+import java.net.URL;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.greenstone.gsdl3.gs3build.util.GS2TextFileHandler;
+
+import org.apache.xerces.parsers.SAXParser;
+import org.xml.sax.XMLReader;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.Attributes;
+import org.xml.sax.helpers.XMLReaderFactory;
+import org.xml.sax.helpers.DefaultHandler;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+import org.greenstone.gsdl3.gs3build.doctypes.MetadataDocument;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentLoader;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentList;
+
+import org.greenstone.gsdl3.gs3build.metadata.MetadataLabel;
+
+public class MetaXMLExtractor implements ExtractorInterface
+{
+  /**
+   *  An inner class to handle Metadata files
+   */
+  class MetadataHandler extends DefaultHandler
+  { List         files;
+    String       label;
+    StringBuffer value;
+    URL          url;
+    boolean      inElement;
+    boolean      accumulate;
+    DocumentList documentList;
+    List         documentIds;
+    List         documents;
+
+    MetadataHandler(DocumentList documentList)
+    { super();
+    
+      this.label = null;
+      this.value = null;
+      this.documentList = documentList;
+    }
+
+    public void startElement(String URI, String localName, String qName, Attributes attributes)
+    { if (localName.equals("FileName"))
+      {	this.value = new StringBuffer();
+      }
+      else if (localName.equals("FileSet"))
+      { this.files = new ArrayList();
+      }
+      else if (localName.equals("Description"))
+      { this.documentIds = this.documentList.findDocumentIdsUsingFiles(this.files, this.url.toString());	
+
+	if (documentIds != null && documentIds.size() > 0) {
+	  this.documents = new ArrayList();
+	  
+	  Iterator idIterator = documentIds.iterator();
+	  while (idIterator.hasNext()) {
+	    String docIdString = idIterator.next().toString();
+	    DocumentID docId   = new DocumentID(docIdString);
+	    DocumentInterface document = documentList.getDocument(docId);
+	    if (document != null) {
+	      documents.add(document);
+	    }
+	  }
+	}
+      }
+      else if (localName.equals("Metadata"))
+      { this.label = attributes.getValue("name");
+        this.value = new StringBuffer();
+
+	String mode = attributes.getValue("mode");
+	this.accumulate = mode.equals(ExtractorManager.ACCUMULATE_MODE);	
+      }
+    }
+
+    public void endElement(String URI, String localName, String qName)
+    { if (localName.equals("FileName"))
+      {	String file = this.value.toString();
+        this.value = null;
+	this.files.add(file);
+      }
+      else if (localName.equals("FileSet"))
+      { // post the existing files item...
+      }
+      else if (localName.equals("Description"))
+      {
+	if (this.documents != null && documents.size() > 0) {
+	  // write out the modified documents
+	  // TODO: nicer/more generalised interface for this and related activity in
+	  //       extractor manager (actually, enricher manager);
+	  Iterator docIterator = documents.iterator();
+	  while (docIterator.hasNext()) {
+	    DocumentInterface document = (DocumentInterface) docIterator.next();
+
+	    //  System.out.println("Writing modified document " + document.getID());
+	    documentList.storeChangedDocument(document);
+	  }
+	}
+      }
+      else if (localName.equals("Metadata"))
+      { MetaXMLExtractor.postMetadata(this.url, this.files, 
+				      this.label, this.value.toString(), 
+				      this.accumulate);
+	/*
+	if (documentIds != null) {
+	  Iterator iterator = documentIds.iterator();
+	  while (iterator.hasNext()) {
+	    System.out.println("Matches file " + iterator.next().toString());
+	  }
+	}
+	*/
+	
+	if (documentIds != null && documentIds.size() > 0) {
+	  Iterator docIterator = this.documents.iterator();
+	  while (docIterator.hasNext()) {
+	    DocumentInterface document = (DocumentInterface) docIterator.next();
+	    
+	    // Post to document
+	    // TODO: tailor this to posting documents to *sections* as required...
+	    if (accumulate) {
+ 	      document.addDocumentMetadata(new MetadataLabel(this.label), this.value.toString());
+	    }
+	    else {
+ 	      document.setDocumentMetadata(new MetadataLabel(this.label), this.value.toString());
+	    }
+	  }	
+	}
+
+	// flatten the metadata items again...
+        this.value = null;
+	this.label = null;
+      }
+    }
+
+    public void characters(char c[], int start, int length)
+    { if (this.value != null)
+      { String string = new String(c, start, length);
+        this.value.append(string);
+      }
+    }
+
+    public void setUrl(URL url)
+    { this.url = url;
+    }
+  }
+
+  private DocumentList documentList;
+
+  /**
+   *  Construct of extractor
+   */
+  public MetaXMLExtractor()
+  { // Intentionally left blank
+  }
+
+  /**
+   *  This extractor doesn't need to do any preparation/completion work,
+   *  so this member function is empty.
+   */
+  public void configure(String outputDir)
+  { // Intentionally left blank
+  }
+
+  public void configure(DocumentList list)
+  { this.documentList = list;
+  }
+
+  /**
+   *  This extractor doesn't need to do any preparation/completion work,
+   *  so this member function is empty.
+   */
+  public void startPass(int passNo)
+  { // Intentionally left blank
+  }
+
+  /**
+   *  Process the document - for a metadata document, this results in the
+   *  decoration of other files, for other documents, it does nothing.
+   */
+  public void extractDocument(DocumentID docID, DocumentInterface document)
+  { if (document.getDocumentType().equals(MetadataDocument.METADATA_DOCUMENT_TYPE))
+    { // Extract the content from the metadata file
+      URL url;
+
+      try {
+	SAXParser parser = new SAXParser();
+	MetadataHandler handler = new MetadataHandler(this.documentList);
+        /*
+	XMLReader reader = XMLReaderFactory.createXMLReader();
+	reader.setContentHandler(handler);
+	reader.setErrorHandler(handler);*/
+	parser.setContentHandler(handler);
+	  
+	// Get path of file; we cheat here by assuming that the url is a file - this
+	// really ought to be done better [TODO: fix to handle full paths & URLs]
+	url = document.getDocumentFiles().getFile(0).getURL();
+	String filePath = url.getPath();
+	handler.setUrl(new URL(url, "."));
+
+	// A metadata document consists of one file only - get it from the 'default'
+	// file group
+	/*
+	FileReader fileReader = new FileReader(filePath);
+	reader.parse(new InputSource(fileReader));
+	*/
+	parser.parse(filePath);
+      }
+      catch (SAXException saxException)
+      { // TODO: log error
+	System.err.println(saxException);
+      }
+      catch (java.io.FileNotFoundException fileException)
+      { System.err.println(fileException);
+      }
+      catch (java.io.IOException ioException)
+      { System.err.println(ioException);
+      }
+      /*      catch (java.net.MalformedURLException malEx) {
+	System.err.println("Unable to get parent of URL "+url.toString()+" in metadata extraction.");
+	return;
+      }
+      */
+
+      // for each document post it to the corresponding document
+    }
+  }
+
+  protected static void postMetadata(URL url, List files, String label, String value, boolean accumulate)
+  { String file;
+
+    Iterator fileIter = files.iterator();
+    while (fileIter.hasNext()) {
+      file = fileIter.next().toString();
+
+      System.out.println(url.toString() + " " + file + ": " + label + "=" + value);
+    }
+  }
+
+  /**
+   *  This extractor doesn't need to do any preparation/completion work,
+   *  so this member function is empty.
+   */
+  public void endPass(int passNo)
+  { // Intentionally left blank
+  }
+
+  /**
+   *  This extractor is a simple, single-pass extractor
+   *
+   *  @see: org.greenstone.gsdl3.gs3build.extractor.ExtractorInterface:getNumberOfPasses
+   */
+  public int getNumberOfPasses()
+  { return 1;
+  }
+}
+
+
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/indexers/AbstractIndexer.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/indexers/AbstractIndexer.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/indexers/AbstractIndexer.java	(revision 13666)
@@ -0,0 +1,82 @@
+package org.greenstone.gsdl3.gs3build.indexers;
+
+import java.util.*;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+import org.greenstone.gsdl3.gs3build.util.DOMUtils;
+import org.greenstone.gsdl3.util.GSXML;
+
+public abstract class AbstractIndexer implements IndexerInterface
+{ 
+  class CollectionIndex
+  { String level;
+    String name;
+    List fields;
+
+    public CollectionIndex(String indexName, Node node)
+    { this.fields = new ArrayList();
+      this.name = indexName;
+      this.level = IndexerManager.DEFAULT_LEVEL;
+    
+      NodeList children = node.getChildNodes();
+      for (int c = 0; c < children.getLength(); c ++) {
+	Node child = children.item(c);
+	
+	if (child.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
+	  String name = child.getNodeName();
+	  
+	  if (name.equals(GSXML.LEVEL_ELEM)) {
+	    String levelName = DOMUtils.getNodeChildText(children.item(c));
+	    this.level = levelName;
+	  }
+	  else if (name.equals(GSXML.FIELD_ELEM)) {
+	    String fieldName = DOMUtils.getNodeChildText(children.item(c));
+	    this.fields.add(fieldName.toString());
+	  }
+	}
+      }
+      if (this.fields.size() == 0) {
+	this.fields.add(IndexerManager.DEFAULT_FIELD);
+      }
+    }
+
+    public void prepareIndexer(IndexerInterface indexer)
+      { //indexer.addIndex(this.name, this.level, this.fields.get(0).toString());
+    }
+  }
+
+
+  public boolean configure(org.w3c.dom.Node searchNode)
+  {
+    NodeList indexChildren = searchNode.getChildNodes();
+
+    // check for <index> tag children
+    for (int i = 0; i < indexChildren.getLength(); i ++) {
+      String childName = indexChildren.item(i).getNodeName();
+
+      if (childName.equals(GSXML.INDEX_ELEM))
+      { NamedNodeMap atts = indexChildren.item(i).getAttributes();
+	
+	Node attribute = atts.getNamedItem(GSXML.NAME_ATT);
+	String indexName = attribute.getNodeValue();
+	      
+	// create the local indexer representation
+	CollectionIndex index = new CollectionIndex(indexName, indexChildren.item(i));
+	     
+	// prepare it...
+	index.prepareIndexer(this);
+      }
+    }
+    return true;
+  }
+
+  public void tidyup()
+  {
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/indexers/IndexerFactory.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/indexers/IndexerFactory.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/indexers/IndexerFactory.java	(revision 13666)
@@ -0,0 +1,13 @@
+package org.greenstone.gsdl3.gs3build.indexers;
+
+public class IndexerFactory
+{ public static final IndexerInterface makeIndexer(String type, String name)
+  { if (type.equals(MGIndexer.MG_INDEX_TYPE)) 
+    { return new MGIndexer(name);
+    }
+    else if (type.equals(MGPPIndexer.MGPP_INDEX_TYPE)) {
+      return new MGPPIndexer(name);
+    }
+    return null;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/indexers/IndexerInterface.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/indexers/IndexerInterface.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/indexers/IndexerInterface.java	(revision 13666)
@@ -0,0 +1,29 @@
+package org.greenstone.gsdl3.gs3build.indexers;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+
+public interface IndexerInterface
+{
+  public static final String DOCUMENT_LEVEL = "document";
+  public static final String SECTION_LEVEL = "section";
+  public static final String PARAGRAPH_LEVEL = "paragraph";
+
+  public static final String GS2_INDEX_LABEL = "Index";  
+
+  public String  getIndexType();
+  public String  getName();
+  public int     getNumberOfPasses();
+  // TODO: add a function call to provide appropriate XML for the service description
+  public boolean addServiceDescriptions(org.w3c.dom.Element service_rack_list);
+  public void    tidyup();
+
+  public boolean configure(String label, String value);
+  public boolean configure(org.w3c.dom.Node node);
+    //  public boolean addIndex(String name, String level, String field);
+
+  public boolean startPass(int passNumber);
+  public boolean indexDocument(DocumentID id, DocumentInterface document);
+  public boolean endPass(int passNumber);
+
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/indexers/IndexerManager.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/indexers/IndexerManager.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/indexers/IndexerManager.java	(revision 13666)
@@ -0,0 +1,100 @@
+package org.greenstone.gsdl3.gs3build.indexers;
+
+import java.util.Iterator;
+
+import org.w3c.dom.Element;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentList;
+
+public class IndexerManager
+{
+  IndexerInterface indexers[];
+  int size;
+  int used;
+  DocumentList documentList;
+
+  public static final String outputDir = "outputDir";
+  public static final String DEFAULT_LEVEL = "document";
+  public static final String DEFAULT_FIELD = "text";
+
+  public IndexerManager(DocumentList documentList)
+  { this.indexers  = new IndexerInterface[10];
+    this.size      = 10;
+    this.used      = 0;
+    this.documentList = documentList;
+  }
+
+  public void addIndexer(IndexerInterface indexer)
+  { this.ensureCapacity(this.used + 1);
+
+    this.indexers[this.used] = indexer;
+    this.used ++;
+  }
+
+  public void indexDocument(DocumentID docId, DocumentInterface document)
+  { if (!document.isIndexed())
+      return;
+	  
+    for (int i = 0; i < this.used; i ++)
+    { this.indexers[i].indexDocument(docId, document);
+    }
+  }
+
+  public void indexDocuments()
+  { for (int i = 0; i < this.used; i ++)
+    { for (int p = 0; p < this.indexers[i].getNumberOfPasses(); p ++)
+      {	
+	if (!this.indexers[i].startPass(p)) {
+	  continue;
+	}
+
+	Iterator iterator = this.documentList.iterator();
+
+	while (iterator.hasNext()) {
+	  DocumentInterface document = (DocumentInterface) iterator.next();
+
+	  if (document.isIndexed()) {
+	    if (!this.indexers[i].indexDocument(document.getID(), document)) {
+	      System.out.println("Ending document " + document.getID());
+	    }
+	    
+	    // note any changes made to this document...
+	    if (document.isChanged()) {
+	      //System.out.println("Writing document "+document.getID());
+	      this.documentList.storeChangedDocument(document);
+	    }
+	    /**
+	    if (p == 0) {
+	      System.out.println("Writing document "+document.getID());
+	    }
+	    */
+	  }
+	}
+	this.indexers[i].endPass(p);
+      }
+    }
+  }
+
+  public void ensureCapacity(int needSize)
+  { while (needSize >= this.size)
+    { int newSize = this.size * 2;
+      IndexerInterface newIndexers [] = new IndexerInterface[newSize];
+      System.arraycopy(indexers, 0, newIndexers, 0, this.used);
+      this.indexers = newIndexers;
+      this.size = newSize;
+    }
+  }
+
+    public boolean addServiceDescriptions(Element service_class_list) {
+	boolean success = true;
+	for (int i = 0; i < this.used; i ++) {
+	    if (!this.indexers[i].addServiceDescriptions(service_class_list)) {
+		success = false;
+	    }
+	}
+	return success;
+    }
+}
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/indexers/MGIndexer.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/indexers/MGIndexer.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/indexers/MGIndexer.java	(revision 13666)
@@ -0,0 +1,740 @@
+package org.greenstone.gsdl3.gs3build.indexers;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+import org.w3c.dom.*;
+
+import org.greenstone.mg.*;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+import org.greenstone.gsdl3.gs3build.doctypes.HTMLDocument;
+import org.greenstone.gsdl3.gs3build.doctypes.METSDocument;
+import org.greenstone.gsdl3.gs3build.metadata.*;
+import org.greenstone.gsdl3.gs3build.xpointer.XPointer;
+import org.greenstone.gsdl3.gs3build.util.DOMUtils;
+import org.greenstone.gsdl3.util.GSXML;
+import org.greenstone.gsdl3.util.Misc;
+import org.greenstone.gsdl3.util.Processing;
+
+// for debug
+import org.greenstone.gsdl3.util.XMLConverter;
+
+public class MGIndexer //extends AbstractIndexer
+    implements IndexerInterface
+{ 
+    int          pass;
+    int          documentSeqNo;
+    int          sectionSeqNo;
+    boolean      firstDocument;
+    String       outputDirectory;
+    StringBuffer indexBuffer;
+    File         textDirectory;
+    File         indexDirectory;
+    String       indexStem;
+    String       textStem;
+    List         indexes;
+    String       overallName; 
+    
+    MGIndex current_index = null;
+    MGPassesWrapper mgPasses;
+    
+    static final char END_OF_DOCUMENT = (char) 2;
+    //static final char END_OF_SECTION  = (char) 3; // actually this is end of para for mg - don't use this yet
+    static final char END_OF_STREAM   = (char) 4;
+
+    public static final String MG_INDEX_TYPE = "mg";
+    public static final String INDEX_FILE_STEM = "index";
+    
+    class MGIndex
+    { 
+	String name=null;
+	String level=null;
+	List fields=null;
+	boolean error = false;// assume built until we get an error
+	
+	public MGIndex(Element index_element) {
+	    
+	    this.fields = new ArrayList();
+	    this.name = index_element.getAttribute(GSXML.NAME_ATT);
+	    if (this.name.equals("")) {
+		// TODO make this dynamic
+		this.name = "xx";
+	    }
+	    NodeList children = index_element.getChildNodes();
+	    for (int c = 0; c < children.getLength(); c ++) {
+		Node child = children.item(c);
+		
+		if (child.getNodeType() == Node.ELEMENT_NODE) {
+		    String name = child.getNodeName();
+	  
+		    if (name.equals(GSXML.LEVEL_ELEM)) {
+			this.level = DOMUtils.getNodeChildText(children.item(c));
+		    }
+		    else if (name.equals(GSXML.FIELD_ELEM)) {
+			String fieldName = DOMUtils.getNodeChildText(children.item(c));
+			this.fields.add(fieldName);
+		    }
+		}
+	    }
+	}
+
+	public MGIndex(String name, String level, List fields)
+	{ 
+	    this.name  = name;
+	    this.level = level;
+	    this.fields = fields;
+	}
+	
+	// old gs2 style config - can we get rid of this??
+	public MGIndex(String indexLabel)
+	{ 
+	    int colonAt = indexLabel.indexOf(':');
+	    
+	    if (colonAt < 0) {
+		System.err.println("MGIndex(): invalid index specification: "+indexLabel);
+		return;
+	    }
+	    String field_string = indexLabel.substring(colonAt+1);
+	    String [] field_list = field_string.split(",");
+	    this.fields = new ArrayList();
+	    for (int i=0; i<field_list.length; i++) {
+		this.fields.add(field_list[i]);
+	    }
+	    this.level = indexLabel.substring(0, colonAt);
+	    //createIndexName
+	    StringBuffer new_name = new StringBuffer();
+	    new_name.append(Character.toLowerCase((char) this.level.charAt(0)));
+	    int c, w;
+	    w = 0;
+	    c = 0;
+	    while (c < field_string.length() && w < 2) {
+		char ch = field_string.charAt(c);
+		
+		ch = Character.toLowerCase(ch);
+		if (Character.isLetter(ch)) {
+		    if (ch != 'a' && ch != 'e' && ch != 'i' &&
+			ch != 'o' && ch != 'u') {
+			new_name.append(ch);
+			w++;
+		    }
+		}
+		c ++;
+	    }
+	    this.name = new_name.toString();
+	}
+
+	
+	public String getLevel()
+	{ 
+	    return this.level;
+	}
+
+	public List getFields()
+	{ 
+	    return this.fields;
+	}
+
+	public String getName()
+	{ 
+// 	    if (this.name==null || this.name.equals("")) {
+// 		createIndexName();
+// 	    }
+	    return this.name;
+	}
+
+	public boolean hasError() {
+	    return this.error;
+	}
+	public void setError(boolean b) {
+	    this.error = b;
+	}
+
+// 	private void createIndexName() {
+// 	    StringBuffer new_name = new StringBuffer();
+// 	    new_name.append(Character.toLowerCase((char) this.level.charAt(0)));
+
+// 	    int c, w;
+// 	    w = 0;
+// 	    c = 0;
+// 	    String [] fields_concat = this.fields.toArray
+// 	    while (c < this.field.length() && w < 2) {
+// 		char ch = this.field.charAt(c);
+
+// 		ch = Character.toLowerCase(ch);
+// 		if (Character.isLetter(ch)) {
+// 		    if (ch != 'a' && ch != 'e' && ch != 'i' &&
+// 			ch != 'o' && ch != 'u') {
+// 			new_name.append(ch);
+// 			w++;
+// 		    }
+// 		}
+// 		c ++;
+// 	    }
+// 	    this.name = new_name.toString();
+// 	}
+ 
+
+    } // MGIndex
+
+    public MGIndexer(String name)
+    { 
+	this.indexes = new ArrayList();
+	this.overallName = name; 
+    }
+
+    public String getIndexType()
+    { 
+	return MG_INDEX_TYPE;
+    } 
+
+    public String getName()
+    { 
+	return this.overallName; 
+    }
+    
+    public boolean configure(Node search_node)
+    {
+	NodeList index_children = GSXML.getChildrenByTagName(search_node, GSXML.INDEX_ELEM);
+	
+	// add a text 'index' - we should be able to turn this off in the config file? actually mg needs a text index
+	ArrayList list = new ArrayList();
+	list.add("text");
+	MGIndex index = new MGIndex("text", "section", list);
+	indexes.add(index);
+	for (int i = 0; i < index_children.getLength(); i ++) {
+	    Element index_elem = (Element)index_children.item(i);
+	    index = new MGIndex(index_elem);
+	    if (index.getName() != null && index.getLevel() != null && index.getFields()!= null) {
+		
+		indexes.add(index);
+	    } else {
+		System.err.println("invalid index spec, not including"+new XMLConverter().getPrettyString(index_elem));
+	    }
+	}
+	// TODO make sure all index names are unique
+	return true;
+    }
+
+    /**
+     *  The output directory should be (collection)/building/text/ for
+     *  normal Greenstone builds.
+     *
+     *  @param <code>String</code> the label to configure
+     *  @param <code>String</code> the value...
+     */ 
+    public boolean configure(String label, String value)
+    { 
+	if (label.equals(IndexerManager.outputDir)) {
+	    this.outputDirectory = value;
+	    this.pass = 0;
+    
+	    // attempt to ensure that the text subdirectory exists
+	    this.textDirectory = new File(outputDirectory, "text");
+	    if (!textDirectory.exists()) {
+		if (!textDirectory.mkdir()) {
+		    return false;
+		}
+	    }
+	    else if (!textDirectory.isDirectory()) {
+		return false;
+	    }
+	    this.textStem = this.textDirectory.getPath() + File.separator + INDEX_FILE_STEM;
+
+	    // Sign to the user which mg directory is being used...
+	    System.out.println("Output MG directory is " + this.textStem);
+	}
+	else if (label.equals(IndexerInterface.GS2_INDEX_LABEL)) {
+	    this.indexes.add(new MGIndex(value));
+	}
+
+	return true;
+    }
+
+
+    private Node recurseDOM(DocumentInterface metsDoc, Node node, 
+			    AbstractStructure structure, StringBuffer textBuffer,
+			    StringBuffer extraBuffer, String namespace) 
+	//String name, String namespace, String field)
+    {
+	List fields = current_index.getFields();
+	// send out the ctrl-c...if this is
+	if (structure.getStructureType().equals(METSDivision.DIVISION_TYPE)) {
+	    // try doing this for all index types
+	    // actually we should only need to do this once ????
+	    if (this.pass == 0) {
+	    //if ((this.currentIndexName != null)) { // && this.level != null && this.level.equals(IndexerInterface.SECTION_LEVEL)) { //name.startsWith("s")) {
+		METSDivision division = (METSDivision) structure;
+
+		// get the division metadata block
+		METSDescriptive descriptive;
+		String metadataId = division.getDefaultMetadataReference();
+		if (metadataId == null) {
+		    descriptive = metsDoc.getDocumentMetadata().createDescriptive(division.getLabel());
+		    division.addMetadataReference(descriptive.getID());
+		}
+		else {
+		    // Get the descriptive item...
+		    descriptive = metsDoc.getDocumentMetadata().getDescriptiveById(metadataId);
+		}
+	    
+		descriptive.addMetadata("gsdl3", "mgseqno", this.overallName + "." + Integer.toString(this.sectionSeqNo));
+	    
+		metsDoc.setChanged(true);
+		//metsDoc.setModified(true);
+		//	System.out.println("Assigning " + this.sectionSeqNo + " to " + metsDoc.getID() + " " + division.getLabel());
+	    } // section level
+	
+	    // append an 'end of section' marker
+	    //textBuffer.append(END_OF_SECTION);
+	    this.sectionSeqNo ++;
+	
+	    // for document-level indexes, always append an 'end of document' tag at the
+	    // end of the document for each section.  Otherwise, each section is followed
+	    // by an end of document character.  This ensures that all indexes use the
+	    // same document numbering...
+	    if (this.current_index.getLevel().equals(IndexerInterface.DOCUMENT_LEVEL)) {
+		extraBuffer.append(END_OF_DOCUMENT);
+	    }
+	    else {
+		textBuffer.append(END_OF_DOCUMENT);
+		this.documentSeqNo ++;
+	    }
+	    
+	    // produce the body here for metadata output of divisions - in the case of
+	    // text output, that will happen below...
+	    
+	    if (fields.size()>1 || !((String)fields.get(0)).equals("text")) {
+		// if there is only text, don't do this
+		METSDescriptive descriptive;
+	
+		METSDivision division = (METSDivision) structure;
+
+		String metadataId = division.getDefaultMetadataReference();
+		// are there other metadata refs to get??
+		descriptive = metsDoc.getDocumentMetadata().getDescriptiveById(metadataId);
+		if (descriptive != null) {
+		    for (int i=0; i<fields.size(); i++) {
+			String field = (String)fields.get(i);
+			if (field.equals("text")) {
+			    continue;
+			}
+			List values = descriptive.getMetadata(namespace, field);
+			if (values != null) {	
+			    Iterator valueIter = values.iterator();
+			    while (valueIter.hasNext()) {
+				String value = valueIter.next().toString();
+				textBuffer.append(value);
+				textBuffer.append(" ");
+			    }
+			}
+		    }
+		}
+	    }
+	}
+	
+	// go through our children as required...
+	Iterator children = structure.getChildIterator();
+	Node startNode;
+	boolean index_text = fields.contains("text");
+	while (children.hasNext()) {
+	    AbstractStructure child = (AbstractStructure) children.next();
+      
+	    // get xpointer for child 
+	    // get start position node
+	    if (metsDoc.getDocumentType() == "METS"){
+		startNode = ((METSDocument) metsDoc).getSectionStartNode((METSDivision) child);	  
+	    } else {
+		startNode = ((HTMLDocument) metsDoc).getSectionStartNode((METSDivision) child);
+	    }
+	    
+	    // while this node isn't the child's start node, produce the 
+	    // HTML node text, if in text field mode...
+	    if (index_text) {
+		while (node != startNode) {
+		    XPointer.printNode(node, textBuffer, false);
+		    node = XPointer.getNextNode(node);
+		}
+	    }
+	    
+	    // recurse to child
+	    node = this.recurseDOM(metsDoc, node, child, textBuffer, extraBuffer, namespace); // name, namespace, field);
+	} // while next child
+
+	// close a document - the actual closing \B will be done by the main
+	// loop, so only a required \C is printed here...
+	// why have we got STRUCTURE_TYPE here and DIVISION_TYPE above????
+	if (structure.getStructureType().equals(METSStructure.STRUCTURE_TYPE)) {
+	    if (index_text) {
+		while (node != null) {
+		    XPointer.printNode(node, textBuffer, false);
+		    node = XPointer.getNextNode(node);
+		}
+	    }
+      
+	    //textBuffer.append(END_OF_SECTION);
+	    this.sectionSeqNo ++;
+      
+	}
+	return node;
+    }
+
+    private String prepareDOM(DocumentInterface metsDoc, Document document, METSStructure structure, String namespace)
+    {
+	//  String name, String namespace, String field)
+	StringBuffer extraBuffer = new StringBuffer();
+	Node node = document.getDocumentElement();
+	StringBuffer textBuffer = new StringBuffer();
+	
+	this.recurseDOM(metsDoc, node, structure, textBuffer, extraBuffer, namespace); //name, namespace, field);
+	textBuffer.append(extraBuffer.toString());
+	return textBuffer.toString();
+    }
+
+    /**
+     *  Index a single document; the document interface can be used to extract individual
+     *  metadata items etc. as required or desired and index those instead or as well as
+     *  the body text of the document.
+     */
+    public boolean indexDocument(DocumentID docID, DocumentInterface document)
+    {
+	
+	if (!this.firstDocument) {
+	    this.indexBuffer.append(END_OF_DOCUMENT);
+	    mgPasses.processDocument(indexBuffer.toString());
+	    this.indexBuffer.delete(0, this.indexBuffer.length());
+	    
+	}
+
+	String docText = null;
+	// set the mgseqno if first pass
+	if (this.pass == 0) {
+	    document.removeAllMetadata("gsdl3", "mgseqno");
+	    document.addDocumentMetadata("gsdl3", "mgseqno", this.overallName+"."+Integer.toString(this.sectionSeqNo));
+	}
+
+	this.sectionSeqNo ++;
+	
+	//long start = System.currentTimeMillis();
+	Document domDocument = document.getDOMDocument();
+	if (domDocument != null) {
+	    System.err.println("dom doc is not null");
+	    METSStructure sections = document.getDocumentStructure().getStructure("Section");
+	    if (sections != null) {
+		System.err.println("sections are not null");
+		docText = this.prepareDOM(document, domDocument, sections, "gsdl3"); //this.name, "gsdl3", this.field);
+		//	System.out.println(docText);
+	    }
+	}
+	//long finish = System.currentTimeMillis();
+	//System.err.println("dom doc = "+ Long.toString(finish-start));
+	//start = System.currentTimeMillis();
+	if (docText == null) {
+	    System.err.println("dom doc or sections was null - asking for doc text");
+	    StringBuffer doc_text_buffer = new StringBuffer();
+	    List fields = this.current_index.getFields();
+	    for (int i=0; i<fields.size(); i++) {
+		String field = (String)fields.get(i);
+		if (field.equals("text")) {
+		    doc_text_buffer.append(document.getDocumentText());
+		}  else {
+		    // its a metadata - do namespace properly!!
+		    List values = document.getDocumentMetadataItem("gsdl3", field);
+		    if (values != null) {
+			Iterator valueIter = values.iterator();
+			while (valueIter.hasNext()) {
+			    String value = valueIter.next().toString();
+			    doc_text_buffer.append(value);
+			}
+		    }
+		}
+	    } // for each field
+	    docText = doc_text_buffer.toString();
+	    sectionSeqNo ++;
+	}
+	//finish = System.currentTimeMillis();
+	//System.err.println("whole doc = "+ Long.toString(finish-start));
+	
+	this.indexBuffer.append(docText);
+	// remember that we're not on the first document, 
+	this.firstDocument = false;
+	this.documentSeqNo ++;
+
+	return true;
+    }
+
+    /**
+     *  Initialise the pass: open required files, check status
+     */
+    public boolean startPass(int passNumber) {
+    	
+	
+	this.pass = passNumber;
+	this.firstDocument = true;
+	this.documentSeqNo = 1;
+	this.sectionSeqNo  = 1;
+	
+	this.mgPasses = new MGPassesWrapper();
+	this.indexBuffer = new StringBuffer();
+	int indexNo = this.pass/2;
+	this.current_index = null;
+	
+	this.current_index = (MGIndex) this.indexes.get(indexNo);
+	if (this.current_index.hasError()) {
+	    // an error has already occurred for this index, don't continue
+	    System.out.println("pass "+this.pass+": aborted due to errors in the previous pass");
+	    return false;
+	}
+	// attempt to ensure that the text/index subdirectory exists
+	this.indexDirectory = new File(outputDirectory, current_index.getName());
+	if (!indexDirectory.exists()) {
+	    if (!indexDirectory.mkdir()) {
+		return false;
+	    }
+	}
+	else if (!indexDirectory.isDirectory()) {
+	    return false;
+	}
+
+	this.indexStem = this.indexDirectory.getPath() + File.separatorChar + INDEX_FILE_STEM;  // TODO: modify for index
+	if (this.pass == 0) {
+	    // first pass, also set up the textStem
+	    this.textDirectory = this.indexDirectory;
+	    this.textStem = this.indexStem;
+	}
+	mgPasses.setFileName(this.indexStem);
+	if (!Misc.isWindows()) {
+	    mgPasses.setBasePath("/");
+	}
+	int mgPass = this.pass < 2 ? this.pass : ((this.pass % 2) + 2);
+	
+	mgPasses.setBufferSize(100000);
+ 	
+	switch (mgPass) {
+	case 0:
+	    // -b 100000 -T1
+	    mgPasses.addPass(MGPassesWrapper.TEXT_PASS_1);
+	    
+	    
+	    break;
+	    
+	case 1:
+	    // -b 100000 -T2
+	    mgPasses.addPass(MGPassesWrapper.TEXT_PASS_2);
+	    break;
+	    
+	case 2:
+	    // -b 100000 -2 -m 32 -s 0 -G -t 10 -N1
+	    mgPasses.addPass(MGPassesWrapper.INDEX_PASS_1);
+	    mgPasses.setInvfLevel(MGPassesWrapper.INVF_LEVEL_2);
+	    mgPasses.setStemOptions(MGPassesWrapper.STEMMER_ENGLISH, MGPassesWrapper.NO_STEM_OR_CASE);
+	    mgPasses.setInversionMemLimit(32);
+	    mgPasses.ignoreSGMLTags(true);
+	    break;
+	    
+	case 3:
+	    // -b 100000 -2 -c 3 -G -t 10 -N2
+	    mgPasses.addPass(MGPassesWrapper.INDEX_PASS_2);
+	    mgPasses.setInvfLevel(MGPassesWrapper.INVF_LEVEL_2);
+	    mgPasses.ignoreSGMLTags(true);
+	    break;
+	}
+	
+	mgPasses.init();
+	System.out.println("Starting Pass " + this.pass);
+	return true;
+    }
+  
+    /**
+     *  Complete a pass - reset file counters, close files, etc.
+     */
+    public boolean endPass(int passNumber) {
+	try {
+	    this.indexBuffer.append(END_OF_DOCUMENT);
+	    mgPasses.processDocument(indexBuffer.toString());
+	    this.indexBuffer.delete(0, this.indexBuffer.length());
+	    Thread.sleep(1000); // what for??
+	}
+	catch (InterruptedException ex) {
+	    System.out.println(ex);
+	}
+	mgPasses.finish();
+	try {
+	    Thread.sleep(1000);
+	} catch (Exception e) {}
+	
+	int exit_value = 0;
+	System.out.println("Pass " + this.pass + " completed with " + exit_value);
+	if (exit_value !=0) {
+	    //assume something has gone wrong, don't continue
+	    current_index.setError(true);
+	    return false;
+	}
+	int mgPass = this.pass < 2 ? this.pass : ((this.pass % 2) + 2);
+	String osextra = "";
+	if (!Misc.isWindows()) {
+	    osextra = " -d / ";
+	}
+	
+	switch (mgPass) {
+	    
+	case 0:
+	    System.out.println("Compressing dictionary");
+	    exit_value = Processing.runProcess("mg_compression_dict -f " + this.textStem + osextra + " -S -H -2 -k 5120");
+	    if (exit_value == 0) {
+		System.out.println("Compressed dictionary successfully written");
+	    } else {
+		System.err.println("Error from mg_compression_dict: " + exit_value);
+		current_index.setError(true);
+		
+		return false;
+	    }
+	    break;
+	    
+	case 2:
+	    System.out.println("Creating perfect hash");
+	    exit_value = Processing.runProcess("mg_perf_hash_build -f " + this.indexStem+osextra);
+	    if (exit_value ==0) {
+		System.out.println("Perfect hashes completed");
+	    } else {
+		System.err.println("Unable to build the perfect hash");
+		current_index.setError(true);
+		return false;
+	    }
+	    break;
+	    
+	case 3:
+	    System.out.println("Writing weights file");
+	    exit_value = Processing.runProcess("mg_weights_build -f " + this.indexStem + " -t " + this.textStem + osextra);
+	    if (exit_value ==0) {
+		System.out.println("Weights file successfully written");
+	    } else {
+		System.err.println("Unable to create weights file");
+		current_index.setError(true);
+		return false;
+	    }
+	    
+	    System.out.println("Creating inverted dictionary");
+	    exit_value = Processing.runProcess("mg_invf_dict -f " + this.indexStem + osextra);
+	    if (exit_value ==0) {
+		System.out.println("Inverted dictionary file successfully written");
+	    } else {
+		System.out.println("Unable to create inverted dictionary file");
+		current_index.setError(true);
+		return false;
+	    }
+	    
+	    System.out.println("Creating Stem indexes");
+	    exit_value = Processing.runProcess("mg_stem_idx -b 4096 -s1 -f " + this.indexStem+osextra);
+	    if (exit_value == 0) {
+		System.out.println("Stemmed index 1 successfully written");
+	    } else {
+		System.out.println("Unable to create stemmed index 1");
+		current_index.setError(true);
+		return false;
+	    }
+	    
+	    exit_value = Processing.runProcess("mg_stem_idx -b 4096 -s2 -f " + this.indexStem+osextra);
+	    if (exit_value == 0) {
+		System.out.println("Stemmed index 2 successfully written");
+	    } else {
+		System.out.println("Unable to create stemmed index 2");
+		current_index.setError(true);
+		return false;
+	    }
+	    exit_value = Processing.runProcess("mg_stem_idx -b 4096 -s3 -f " + this.indexStem+osextra);
+	    if (exit_value == 0) {
+		System.out.println("Stemmed index 3 successfully written");
+	    } else {
+		System.out.println("Unable to create stemmed index 3");
+		current_index.setError(true);
+		return false;
+	    }
+	    
+	    break;
+	} // switch
+
+	mgPasses = null;
+	return true;
+    }
+    
+    /**
+     *  Do any tidying up
+     */
+    public void tidyup()
+    {
+    }
+    
+    /**
+     *  Return the number of passes required for this index.
+     */
+    public int getNumberOfPasses()
+    { 
+	//return 2 + this.indexes.size() * 2;
+	return this.indexes.size()*2;
+    }
+
+    public boolean addServiceDescriptions(org.w3c.dom.Element service_rack_list)
+    {
+	Document doc = service_rack_list.getOwnerDocument();
+
+	// generate the list of indexes
+	Element index_list = doc.createElement(GSXML.INDEX_ELEM+GSXML.LIST_MODIFIER);
+	boolean found_index = false;
+	String def_index = ""; // the default index will just be the first one created for now.
+	for (int i=1; i<this.indexes.size(); i++) {
+	    // start at 1: 0 will be the text index
+	    MGIndex index = (MGIndex)this.indexes.get(i);
+	    if (!index.hasError()) {
+		Element e = doc.createElement(GSXML.INDEX_ELEM);
+		e.setAttribute(GSXML.NAME_ATT, index.getName());
+		index_list.appendChild(e);
+		if (found_index == false) {
+		    // this is the first index
+		    found_index = true;
+		    def_index = index.getName();
+		}
+	    }
+	}
+	
+	if (!found_index) {
+	    // no indexes were able to be created, so we can't use them or the text
+	    return false;
+	}
+	Element default_index = doc.createElement("defaultIndex");
+	default_index.setAttribute(GSXML.NAME_ATT, def_index);
+	Element base_index_name = doc.createElement("baseIndexPrefix");
+	base_index_name.setAttribute(GSXML.NAME_ATT, overallName);
+	Element index_stem = doc.createElement("indexStem");
+	index_stem.setAttribute(GSXML.NAME_ATT, INDEX_FILE_STEM);
+	
+	Element search_service_elem = doc.createElement(GSXML.SERVICE_CLASS_ELEM);
+	Element retrieve_service_elem = doc.createElement(GSXML.SERVICE_CLASS_ELEM);
+	service_rack_list.appendChild(search_service_elem);
+	service_rack_list.appendChild(retrieve_service_elem);
+
+	search_service_elem.setAttribute(GSXML.NAME_ATT, "GS3MGSearch");  
+	search_service_elem.appendChild(index_list);
+	search_service_elem.appendChild(default_index);
+	search_service_elem.appendChild(base_index_name);
+	search_service_elem.appendChild(index_stem);
+	
+	retrieve_service_elem.setAttribute(GSXML.NAME_ATT, "GS3MGRetrieve");
+	retrieve_service_elem.appendChild(default_index.cloneNode(true));
+	retrieve_service_elem.appendChild(base_index_name.cloneNode(true));
+	retrieve_service_elem.appendChild(index_stem.cloneNode(true));
+
+	return true;
+    }
+    
+}
+    
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/indexers/MGPPIndexer.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/indexers/MGPPIndexer.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/indexers/MGPPIndexer.java	(revision 13666)
@@ -0,0 +1,732 @@
+package org.greenstone.gsdl3.gs3build.indexers;
+
+import org.greenstone.mgpp.MGPPPassesWrapper;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+import org.greenstone.gsdl3.gs3build.doctypes.HTMLDocument;
+import org.greenstone.gsdl3.gs3build.doctypes.METSDocument;
+import org.greenstone.gsdl3.util.Misc;
+import org.greenstone.gsdl3.util.GSXML;
+import org.greenstone.gsdl3.util.Processing;
+import org.greenstone.gsdl3.gs3build.xpointer.XPointer;
+import org.greenstone.gsdl3.gs3build.metadata.*;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.io.File;
+import java.util.Iterator;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Document;
+
+public class MGPPIndexer extends AbstractIndexer
+{ 
+    int          pass;
+    int          documentSeqNo;
+    int          sectionSeqNo;
+    String       name;
+    boolean      firstDocument;
+    File indexDirectory;
+    File textDirectory;
+    String       indexStem;
+    String       textStem;
+    StringBuffer indexBuffer;
+    String       outputDirectory;
+    //String       outputStem;
+//     String       passExtra;
+//     InputStream	 indexerFeedback;
+//     InputStream  indexerErrors;
+//     OutputStream indexerTextfeed;
+//     Process      mgpp_passes;
+    //String       overallName; 
+    String       currentIndexName;
+    String       currentIndexLevel;
+       String       currentIndexField; 
+    MGPPPassesWrapper mgppPasses;
+    
+
+    static final String documentSeparator = "<Document>";
+    static final String sectionSeparator = "<Section>";
+
+    static final String START_OF_DOCUMENT = "<Document>";
+    static final String END_OF_DOCUMENT = "</Document>";
+    static final String START_OF_SECTION = "<Section>";
+    static final String END_OF_SECTION = "</Section>";
+    
+    
+    public static final String MGPP_INDEX_TYPE = "mgpp";
+    public static final String INDEX_FILE_STEM = "index";
+
+
+    class MGPPIndex
+    {
+	public String name = null;
+	public String doc_level = null; 
+	public ArrayList levels = null;
+	public ArrayList fields = null;
+	boolean error = false;// assume built until we get an error
+	
+	public MGPPIndex(String name) {
+	    this.name = name;
+	    doc_level = "Document";
+	}
+
+	public void setDocLevel(String doc_level) {
+	    this.doc_level = doc_level;
+	}
+
+	public void addLevel(String level) {
+	    this.levels.add(level);
+	}
+
+	// change to allow nested fields
+	public void addField(String field) {
+	    this.fields.add(field);
+	}
+
+	public boolean hasError() {
+	    return this.error;
+	}
+	public void setError(boolean b) {
+	    this.error = b;
+	}
+
+    }
+    
+    
+    public MGPPIndexer(String name)
+    { 
+	this.name = name;
+	//this.passExtra = "";
+    }
+
+    public String getName()
+    { 
+	return this.name;
+    }
+
+    /**
+     *  The output directory should be (collection)/building/text/ for
+     *  normal Greenstone builds
+     */ 
+    public boolean configure(String label, String value)
+    { 
+	if (label.equals(IndexerManager.outputDir)) {
+	    this.outputDirectory = value;
+	    
+	    // attempt to ensure that the text subdirectory exists
+	    this.textDirectory = new File(outputDirectory, "text");
+	    if (!textDirectory.exists()) {
+		if (!textDirectory.mkdir()) {
+		    return false;
+		}
+	    }
+	    else if (!textDirectory.isDirectory()) {
+		return false;
+	    }
+	    this.textStem = this.textDirectory.getPath() + File.separator + INDEX_FILE_STEM;
+	    
+	    // attempt to ensure that the index subdir exists
+	    this.indexDirectory = new File(outputDirectory, "idx");
+	    if (!indexDirectory.exists()) {
+		if (!indexDirectory.mkdir()) {
+		    return false;
+		}
+	    }
+	    else if (!indexDirectory.isDirectory()) {
+		return false;
+	    }
+	    this.indexStem = this.indexDirectory.getPath() + File.separator + INDEX_FILE_STEM;
+	    
+	    // Sign to the user which mg directory is being used...
+	    System.out.println("Output MGPP text directory is " + this.textStem);
+	    System.out.println("Output MGPP index directory is " + this.indexStem); 
+	}
+	this.pass = 0;
+	return true;
+    }
+
+    public String getIndexType()
+    { 
+	return MGPP_INDEX_TYPE;
+    }
+
+    public boolean addIndex(String name, String level, String field)
+    { 
+// 	if (level == "doc_level") {
+// 	    passExtra = " -J " + level;
+// 	}
+// 	else {
+// 	    passExtra = " -K " + level;
+// 	}
+	return true;
+    }
+
+    /**
+     *  Index a single document; the document interface can be used to extract individual
+     *  metadata items etc. as required or desired and index those instead or as well as
+     *  the body text of the document.
+     */
+    public boolean indexDocument(DocumentID docID, DocumentInterface document)
+    {
+	if (this.pass == 0) {
+	    document.removeAllMetadata("gsdl3", "mgseqno");
+	}
+
+	// why do this at the start and not at the end???
+	if (!this.firstDocument) {
+	    // Send a '</Document>' at the end of the doc
+	    this.indexBuffer.append(END_OF_DOCUMENT);
+	    mgppPasses.processDocument(indexBuffer.toString());
+	    this.indexBuffer.delete(0, this.indexBuffer.length());
+	}
+
+	String docText = null;
+	
+	//int startSeqNo = this.sectionSeqNo;
+	//this.sectionSeqNo ++;
+	int startSeqNo = this.documentSeqNo;
+
+	Document domDocument = document.getDOMDocument();
+	if (domDocument != null) {
+	    System.err.println("dom doc is not null");
+	    METSStructure sections = document.getDocumentStructure().getStructure("Section");
+	    if (sections != null) {
+		System.err.println("sections are not null");
+		docText = this.prepareDOM(document, domDocument, sections, "gsdl3"); //this.name, "gsdl3", this.field);
+		//	System.out.println(docText);
+	    }
+	}
+	if (docText == null) {
+	    System.err.println("dom doc or sections was null - asking for doc text");
+	    //if (this.currentIndexField.equals("text")) {
+		//docText = Character.toString(END_OF_DOCUMENT) + document.getDocumentText(); 
+		docText = document.getDocumentText();
+		//}
+// 	    else {
+// 		StringBuffer textBuffer = new StringBuffer();
+// 		//textBuffer.append(END_OF_DOCUMENT);
+// 		List values = document.getDocumentMetadataItem("gsdl3", this.currentIndexField);
+// 		if (values != null) {
+// 		    Iterator valueIter = values.iterator();
+// 		    while (valueIter.hasNext()) {
+// 			String value = valueIter.next().toString();
+			
+// 			textBuffer.append(value);
+// 			if (valueIter.hasNext()) {
+// 			    //textBuffer.append(END_OF_SECTION);
+// 			    //	      sectionSeqNo ++;
+// 			}
+// 		    }
+// 		}
+// 		else {
+// 		    textBuffer.append("No data");
+// 		}
+// 		docText = textBuffer.toString();
+// 	    }
+	    sectionSeqNo ++;
+	}
+
+	    //try {					
+	    //	this.indexerTextfeed.write(documentSeparator.getBytes(), 0, documentSeparator.getBytes().length);
+	    // }
+// 	    catch (IOException ex) {
+// 		System.out.println("Bad output on end of document" + ex);
+// 		ex.printStackTrace();
+// 		return false;
+// 	    }
+// 	}
+
+	this.indexBuffer.append(START_OF_DOCUMENT);
+	//String docText = document.getDocumentText();
+	this.indexBuffer.append(docText);
+	//int startSeqNo = this.documentSeqNo;
+	
+// 	byte [] bytes = docText.getBytes();
+// 	int pos = 0, end = bytes.length;
+	
+// 	try {
+// 	    while (pos < end) {
+// 		this.indexerTextfeed.write(bytes, pos, (end - pos > 512 ? 512 : end - pos));
+// 		pos = pos + 512;
+	
+// 		try {
+// 		    while (this.indexerFeedback.available() > 0) {
+// 			byte b[] = new byte[this.indexerFeedback.available()];
+// 			System.out.println("Feedback of " + this.indexerFeedback.available());
+// 			this.indexerFeedback.read(b);
+// 			System.out.println(b);
+// 		    }
+// 		}
+// 		catch (IOException ex) {
+		    
+// 		}
+
+
+// 		try {
+// 		    while (this.indexerErrors.available() > 0) {
+// 			byte b[] = new byte[this.indexerErrors.available()];
+// 			System.out.println("Feedback of " + this.indexerErrors.available());
+// 			this.indexerErrors.read(b);
+// 			System.out.println(new String(b));
+// 		    }
+// 		}
+// 		catch (IOException ex){
+		    
+// 		}
+// 	    }
+// 	}
+// 	catch (IOException ex) {
+// 	    System.out.println("Bad output during document write " + ex + " " + pos + " " + end);
+// 	    ex.printStackTrace();
+// 	    return false;
+// 	}
+	this.firstDocument = false;
+
+	if (this.pass == 0) {    
+	    document.addDocumentMetadata("gsdl3", "mgseqno", "dtx."+Integer.toString(startSeqNo));
+	}
+	this.documentSeqNo++;
+	
+// 	try {
+// 	    while (this.indexerErrors.available() > 0) {
+// 		char c = (char) this.indexerErrors.read();
+// 		System.out.println(c);
+// 	    }
+// 	    while (this.indexerFeedback.available() > 0) {
+// 		byte b[] = new byte[this.indexerFeedback.available()];
+// 		System.out.println("Feedback of " + this.indexerFeedback.available());
+// 		this.indexerFeedback.read(b);
+// 	    }
+// 	}
+// 	catch (IOException ex) {
+	    
+// 	}
+	return true;
+    }
+
+    /**
+     *  Initialise the pass: open required files, check status
+     */
+    public boolean startPass(int passNumber)
+    { 
+	this.pass = passNumber;
+	this.firstDocument = true;
+	this.documentSeqNo = 1;
+	this.sectionSeqNo = 1;
+
+	this.mgppPasses = new MGPPPassesWrapper();
+	this.indexBuffer = new StringBuffer();
+	
+	MGPPIndex index = null; // do something with this!!
+	
+	// get the parameters for this execution of mg_passes
+	mgppPasses.setFileName((this.pass < 2 ? this.textStem : this.indexStem ));
+	if (!Misc.isWindows()) {
+	    mgppPasses.setBasePath("/");
+	}
+	
+	mgppPasses.setDocumentTag("Document");
+	//mgppPasses.addLevelTag("Section");
+
+	this.currentIndexLevel = "Document";// index.getLevel();
+	this.currentIndexField = "text";//index.getField();
+	this.currentIndexName = "idx"; //index.getName();
+	    
+
+	switch (this.pass) {
+	case 0:
+	    // -T1
+	    mgppPasses.addPass(MGPPPassesWrapper.TEXT_PASS_1);
+	    //mgpp_passes = Runtime.getRuntime().exec("mgpp_passes " + passExtra + " -f " + this.outputStem + " -T1");
+	    break;
+	    
+	case 1:
+	    // -T2
+	    mgppPasses.addPass(MGPPPassesWrapper.TEXT_PASS_2);
+	    //mgpp_passes = Runtime.getRuntime().exec("mgpp_passes " + passExtra + " -f " + this.outputStem +" -T2");
+	    break;
+	    
+	case 2:
+	    // -I1
+	    mgppPasses.addPass(MGPPPassesWrapper.INDEX_PASS_1);
+	    //mgpp_passes = Runtime.getRuntime().exec("mgpp_passes " + passExtra + " -f " + this.outputStem +" -I1");
+	    break;
+	    
+	case 3:
+	    //Process p = Runtime.getRuntime().exec("mgpp_perf_hash_build -f " + this.outputStem);
+	    //p.waitFor();
+	    // -I2
+	    mgppPasses.addPass(MGPPPassesWrapper.INDEX_PASS_2);
+	    //mgpp_passes = Runtime.getRuntime().exec("mgpp_passes " + passExtra + " -f " + this.outputStem +" -I2");
+	    break;
+	}
+	    
+	//this.indexerFeedback = mgpp_passes.getInputStream();
+	//   this.indexerErrors   = mgpp_passes.getErrorStream();
+	//   this.indexerTextfeed = mgpp_passes.getOutputStream();
+	//	}
+	//catch (IOException ex) {
+	//   System.out.println(ex);
+	//   ex.printStackTrace();
+	//   return false;
+	//}/	
+	//catch (InterruptedException ex) {
+	//   System.out.println(ex);
+	//   ex.printStackTrace();
+	//   return false;
+	//}
+	mgppPasses.init();
+	System.out.println("Pass " + this.pass);
+	return true;
+    }
+
+    /**
+     *  Complete a pass - reset file counters, close files, etc.
+     */
+    public boolean endPass(int passNumber)
+    { 
+	// TODO: end pass
+	Process p;
+	MGPPIndex index = null; // do something with this!!
+	try {
+	    this.indexBuffer.append(END_OF_DOCUMENT);
+	    mgppPasses.processDocument(indexBuffer.toString());
+	    this.indexBuffer.delete(0, this.indexBuffer.length());
+	    Thread.sleep(1000); // what for??
+	}
+	catch (InterruptedException ex) {
+	    System.out.println(ex);
+	}
+	mgppPasses.finish();
+	try {
+	    Thread.sleep(1000);
+	} catch (Exception e) {}
+	
+	int exit_value = mgppPasses.exitValue();
+	System.out.println("Pass " + this.pass + " completed with " + exit_value);
+	if (exit_value !=0) {
+	    //assume something has gone wrong, don't continue
+// 	    if (index != null) {
+// 		index.setError(true);
+// 		return false;
+// 	    }
+	}
+	
+	String osextra = "";
+	if (!Misc.isWindows()) {
+	    osextra = " -d / ";
+	}
+
+	switch (this.pass) {
+	case 0:
+	    //System.exit(1);
+	    System.out.println("Compressing dictionary");
+	    exit_value = Processing.runProcess("mgpp_compression_dict -f " + this.textStem + " -S -H -2 -k 5120"+ osextra);
+	    
+	    if (exit_value == 0) {
+		System.out.println("Compressed dictionary successfully written");
+	    } else {
+		System.err.println("Error from mgpp_compression_dict: " + exit_value);
+		//index.setError(true);
+		return false;
+	    }
+	    break;
+	    
+	case 2:
+	    System.out.println("Creating perfect hash");
+	    exit_value = Processing.runProcess("mgpp_perf_hash_build -f " + this.indexStem + osextra);
+	    if (exit_value ==0) {
+		System.out.println("Perfect hashes completed");
+	    } else {
+		System.err.println("Unable to build the perfect hash");
+		//index.setError(true);
+		return false;
+	    }
+	    break;
+	    
+	case 3:
+	    System.out.println("Writing weights file");
+	    exit_value = Processing.runProcess("mgpp_weights_build -f " + this.indexStem + osextra);
+	    if (exit_value ==0) {
+		System.out.println("Weights file successfully written");
+	    } else {
+		System.err.println("Unable to create weights file");
+		//index.setError(true);
+		return false;
+	    }
+	    
+	    System.out.println("Creating inverted dictionary");
+	    exit_value = Processing.runProcess("mgpp_invf_dict -f " + this.indexStem + osextra);
+	    if (exit_value ==0) {
+		System.out.println("Inverted dictionary file successfully written");
+	    } else {
+		System.out.println("Unable to create inverted dictionary file");
+		//index.setError(true);
+		return false;
+	    }
+	    
+	    System.out.println("Creating Stem indexes");
+	    exit_value = Processing.runProcess("mgpp_stem_idx -b 4096 -s1 -f " + this.indexStem +osextra);
+	    if (exit_value == 0) {
+		System.out.println("Stemmed index 1 successfully written");
+	    } else {
+		System.out.println("Unable to create stemmed index 1");
+		//index.setError(true);
+		return false;
+	    }
+	    
+	    exit_value = Processing.runProcess("mgpp_stem_idx -b 4096 -s2 -f " + this.indexStem + osextra);
+	    if (exit_value == 0) {
+		System.out.println("Stemmed index 2 successfully written");
+	    } else {
+		System.out.println("Unable to create stemmed index 2");
+		//index.setError(true);
+		return false;
+	    }
+	    exit_value = Processing.runProcess("mgpp_stem_idx -b 4096 -s3 -f " + this.indexStem + osextra);
+	    if (exit_value == 0) {
+		System.out.println("Stemmed index 3 successfully written");
+	    } else {
+		System.out.println("Unable to create stemmed index 3");
+		//index.setError(true);
+		return false;
+	    }
+	    
+	    break;
+	} // switch
+	
+	return true;
+    }
+	
+    /**
+     *  Do any tidying up
+     */
+    public void tidyup()
+    {
+    }
+    
+    /**
+     *  Return the number of passes required for this index.
+     */
+    public int getNumberOfPasses()
+    { 
+	return 4;
+    }
+
+    public boolean addServiceDescriptions(Element service_rack_list) {
+	Document doc = service_rack_list.getOwnerDocument();
+
+	// generate the list of indexes
+	Element index_list = doc.createElement(GSXML.INDEX_ELEM+GSXML.LIST_MODIFIER);
+	Element e = doc.createElement(GSXML.INDEX_ELEM);
+	e.setAttribute(GSXML.NAME_ATT, "idx");
+	index_list.appendChild(e);
+	String def_index = "idx";
+	
+// 	boolean found_index = false;
+// 	String def_index = ""; // the default index will just be the first one created for now.
+// 	for (int i=0; i<this.indexes.size(); i++) {
+// 	    MGIndex index = (MGIndex)this.indexes.get(i);
+// 	    if (!index.hasError()) {
+// 		Element e = doc.createElement(GSXML.INDEX_ELEM);
+// 		e.setAttribute(GSXML.NAME_ATT, index.getName());
+// 		index_list.appendChild(e);
+// 		if (found_index == false) {
+// 		    // this is the first index
+// 		    found_index = true;
+// 		    def_index = index.getName();
+// 		}
+// 	    }
+// 	}
+	
+// 	if (!found_index) {
+// 	    // no indexes were able to be created, so we can't use them or the text
+// 	    return false;
+// 	}
+
+	Element f = doc.createElement(GSXML.FIELD_ELEM+GSXML.LIST_MODIFIER);
+	
+	Element default_index = doc.createElement("defaultIndex");
+	default_index.setAttribute(GSXML.NAME_ATT, def_index);
+
+	Element base_index_name = doc.createElement("baseIndexPrefix");
+	base_index_name.setAttribute(GSXML.NAME_ATT, "dtx");  //overallName);
+
+	Element index_stem = doc.createElement("indexStem");
+	index_stem.setAttribute(GSXML.NAME_ATT, "index");
+
+	Element search_service_elem = doc.createElement(GSXML.SERVICE_CLASS_ELEM);
+	Element retrieve_service_elem = doc.createElement(GSXML.SERVICE_CLASS_ELEM);
+	Element default_level = doc.createElement("defaultLevel");
+	default_level.setAttribute(GSXML.NAME_ATT, "Document");
+
+	Element level_list = doc.createElement("levelList");
+	Element level = doc.createElement("level");
+	level.setAttribute(GSXML.NAME_ATT, "Document");
+	level_list.appendChild(level);
+
+	Element field_list = doc.createElement("fieldList");
+	Element field = doc.createElement("field");
+	field.setAttribute(GSXML.NAME_ATT, "ZZ");
+	field_list.appendChild(field);
+
+	service_rack_list.appendChild(search_service_elem);
+	service_rack_list.appendChild(retrieve_service_elem);
+
+	search_service_elem.setAttribute(GSXML.NAME_ATT, "GS3MGPPSearch");  
+	search_service_elem.appendChild(index_list);
+	search_service_elem.appendChild(default_index);
+	search_service_elem.appendChild(level_list);
+	search_service_elem.appendChild(default_level);
+search_service_elem.appendChild(field_list); // do we need this??
+	search_service_elem.appendChild(base_index_name);
+	search_service_elem.appendChild(index_stem);
+
+	retrieve_service_elem.setAttribute(GSXML.NAME_ATT, "GS3MGPPRetrieve");
+	retrieve_service_elem.appendChild(default_level.cloneNode(true));
+	retrieve_service_elem.appendChild(base_index_name.cloneNode(true));
+	retrieve_service_elem.appendChild(index_stem.cloneNode(true));
+
+	return true;
+    }
+ 
+ 
+  private Node recurseDOM(DocumentInterface metsDoc, Node node, 
+			  AbstractStructure structure, StringBuffer textBuffer,
+			  StringBuffer extraBuffer, String namespace) 
+			  //String name, String namespace, String field)
+  {
+    // send out the ctrl-c...if this is
+    if (structure.getStructureType().equals(METSDivision.DIVISION_TYPE)) {
+	// try doing this for all index types
+	if ((this.currentIndexName != null)) { // && this.level != null && this.level.equals(IndexerInterface.SECTION_LEVEL)) { //name.startsWith("s")) {
+	    METSDivision division = (METSDivision) structure;
+
+	    // get the division metadata block
+	    METSDescriptive descriptive;
+	    String metadataId = division.getDefaultMetadataReference();
+	    if (metadataId == null) {
+		descriptive = metsDoc.getDocumentMetadata().createDescriptive(division.getLabel());
+		division.addMetadataReference(descriptive.getID());
+	    }
+	    else {
+		// Get the descriptive item...
+		descriptive = metsDoc.getDocumentMetadata().getDescriptiveById(metadataId);
+	    }
+	    
+	    descriptive.addMetadata("gsdl3", "mgseqno", this.name + "." + Integer.toString(this.sectionSeqNo));
+	    
+	    metsDoc.setChanged(true);
+	    //metsDoc.setModified(true);
+	    //	System.out.println("Assigning " + this.sectionSeqNo + " to " + metsDoc.getID() + " " + division.getLabel());
+	} // section level
+	
+	// append an 'end of section' marker
+	//textBuffer.append(END_OF_SECTION);
+	this.sectionSeqNo ++;
+	
+	// for document-level indexes, always append an 'end of document' tag at the
+	// end of the document for each section.  Otherwise, each section is followed
+	// by an end of document character.  This ensures that all indexes use the
+	// same document numbering...
+	if (this.currentIndexLevel == null ||
+	    this.currentIndexLevel.equals(IndexerInterface.DOCUMENT_LEVEL)) {
+	    extraBuffer.append(END_OF_DOCUMENT);
+	}
+	else {
+	    textBuffer.append(END_OF_DOCUMENT);
+	    this.documentSeqNo ++;
+	}
+	
+	// produce the body here for metadata output of divisions - in the case of
+      // text output, that will happen below...
+      if (!this.currentIndexField.equals("text")) 
+      { METSDescriptive descriptive;
+	
+	METSDivision division = (METSDivision) structure;
+
+	String metadataId = division.getDefaultMetadataReference();
+	    
+	descriptive = metsDoc.getDocumentMetadata().getDescriptiveById(metadataId);
+	if (descriptive != null) {
+	  List values = descriptive.getMetadata(namespace, this.currentIndexField);
+	  
+	  if (values != null) {	
+	    Iterator valueIter = values.iterator();
+	    while (valueIter.hasNext()) {
+	      String value = valueIter.next().toString();
+	      
+	      textBuffer.append(value);
+	      if (valueIter.hasNext()) {
+		  //textBuffer.append(END_OF_SECTION);
+	      }
+	    }
+	  }
+	}
+      }
+    }
+
+    // go through our children as required...
+    Iterator children = structure.getChildIterator();
+    Node startNode;
+    while (children.hasNext()) {
+      AbstractStructure child = (AbstractStructure) children.next();
+      
+      // get xpointer for child 
+      // get start position node
+      if (metsDoc.getDocumentType() == "METS"){
+	  startNode = ((METSDocument) metsDoc).getSectionStartNode((METSDivision) child);	  
+      } else {
+	  startNode = ((HTMLDocument) metsDoc).getSectionStartNode((METSDivision) child);
+      }
+	    //Node startNode = ((HTMLDocument) metsDoc).getSectionStartNode((METSDivision) child);
+      
+      // while this node isn't the child's start node, produce the HTML node text, if
+      // in text field mode...
+      if (this.currentIndexField.equals("text")) {
+	while (node != startNode) {
+	  XPointer.printNode(node, textBuffer, false);
+
+	  // print buffer to node
+	  node = XPointer.getNextNode(node, (this.currentIndexField.equals("text") ? textBuffer : null));
+	}
+      }
+      
+      // recurse to child
+      node = this.recurseDOM(metsDoc, node, child, textBuffer, extraBuffer, namespace); // name, namespace, field);
+    } // while next child
+
+    // close a document - the actual closing \B will be done by the main
+    // loop, so only a required \C is printed here...
+    if (structure.getStructureType().equals(METSStructure.STRUCTURE_TYPE)) {
+      while (node != null) {
+	if (this.currentIndexField.equals("text")) {
+	  XPointer.printNode(node, textBuffer, false);
+	}
+	node = XPointer.getNextNode(node, (this.currentIndexField.equals("text") ? textBuffer : null));
+      }
+      
+      //textBuffer.append(END_OF_SECTION);
+      this.sectionSeqNo ++;
+      
+    }
+    return node;
+  }
+
+    private String prepareDOM(DocumentInterface metsDoc, Document document, METSStructure structure, String namespace)
+    //  String name, String namespace, String field)
+  { StringBuffer extraBuffer = new StringBuffer();
+    Node node = document.getDocumentElement();
+    StringBuffer textBuffer = new StringBuffer();
+
+    this.recurseDOM(metsDoc, node, structure, textBuffer, extraBuffer, namespace); //name, namespace, field);
+    textBuffer.append(extraBuffer.toString());
+    return textBuffer.toString();
+  }
+
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/AbstractIdentifierFactory.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/AbstractIdentifierFactory.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/AbstractIdentifierFactory.java	(revision 13666)
@@ -0,0 +1,30 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+public abstract class AbstractIdentifierFactory
+{
+  private String idPrelude;
+  private int    idSeqNo;
+
+  public AbstractIdentifierFactory(String idPrelude)
+  { this.idPrelude = idPrelude;
+    this.idSeqNo   = 1;
+  }
+
+  public String getNextIdentifier()
+  { int id = this.idSeqNo ++;
+
+    return idPrelude + Integer.toString(id);
+  }
+
+  public void noteIdentifier(String identifier)
+  { if (!identifier.startsWith(this.idPrelude)) 
+      return;
+  
+    identifier = identifier.substring(this.idPrelude.length());
+
+    int value = Integer.parseInt(identifier);
+    if (value >= this.idSeqNo) {
+      this.idSeqNo = value + 1;
+    }
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/AbstractMetadataGroup.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/AbstractMetadataGroup.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/AbstractMetadataGroup.java	(revision 13666)
@@ -0,0 +1,9 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+public abstract class AbstractMetadataGroup
+{ private String ID;
+
+  public AbstractMetadataGroup(String ID)
+  { this.ID = ID;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/AbstractStructure.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/AbstractStructure.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/AbstractStructure.java	(revision 13666)
@@ -0,0 +1,66 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+import java.io.PrintWriter;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.LinkedHashMap;
+import java.util.Iterator;
+
+/**
+ *  A helpful 'superclass' of METSStructure and METSDivision which allows for some
+ *  simple generalisation of the two classes.
+ */
+
+public abstract class AbstractStructure
+{ Map               children;
+  AbstractStructure parent;
+  String            ID;     // the unique identifier for this division (unique within the
+                            // document, not necessarily unique within the collection).
+
+  public AbstractStructure(String ID)
+  { this.children = new LinkedHashMap();
+    this.parent   = null;
+    this.ID       = ID;
+  }
+
+  public AbstractStructure getParent()
+  { return this.parent;
+  }
+
+  public void setParent(AbstractStructure parent)
+  { this.parent = parent;
+  }
+
+  /**
+   *  Get the identifer of this structure
+   *
+   *  @param <code>String</code> the identifier.
+   */
+  public String getID()
+  { return this.ID;
+  }
+
+  public abstract String getStructureType();
+
+  /**
+   *  Add a child division, or sub-division to the document.  For example,
+   *  sections within a chapter.
+   *
+   *  @param <code>METSDivision</code> the child division.
+   */
+  public void addDivision(METSDivision child)
+  { this.children.put(child.getLabel(), child);
+    child.setParent(this);
+  }
+
+  public Iterator getChildIterator()
+  { return this.children.values().iterator();
+  }
+    
+  public int size()
+  { return this.children.size();
+  }
+}
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/FileIdentifierFactory.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/FileIdentifierFactory.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/FileIdentifierFactory.java	(revision 13666)
@@ -0,0 +1,18 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+/**
+ *  TODO: complete a class to create file identifiers
+ */
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+
+public class FileIdentifierFactory extends AbstractIdentifierFactory
+{
+    public static final String FILE_IDENTIFIER_PRELUDE = "FILE";
+        
+    public FileIdentifierFactory()
+    { 
+	super(FILE_IDENTIFIER_PRELUDE);
+    }
+}
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/GSDL3Namespace.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/GSDL3Namespace.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/GSDL3Namespace.java	(revision 13666)
@@ -0,0 +1,113 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+import java.io.PrintWriter;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+import org.greenstone.gsdl3.gs3build.util.MultiMap;
+import org.greenstone.gsdl3.gs3build.util.XMLTools;
+
+/**
+ *  Implement a simple, unordered, namespace in METS.
+ *
+ *  @see: org.greenstone.gsdl3.gs3build.metadata.METSNamespace
+ */
+
+public class GSDL3Namespace extends SimpleNamespace
+{
+    public static String GSDL3_NAMESPACE_ID = "gsdl3";
+    private static String GSDL3_METADATA_TAG = "Metadata";
+    
+    public GSDL3Namespace()
+    { 
+	super(GSDL3_NAMESPACE_ID);
+    }
+    
+    public GSDL3Namespace(METSLocation location)
+    { 
+	super(GSDL3_NAMESPACE_ID, location);
+    }
+    
+    public GSDL3Namespace(Element mdWrapTag)
+    {	
+	super(GSDL3_NAMESPACE_ID);
+	
+	NodeList childNodes = mdWrapTag.getChildNodes();
+	for (int c = 0; c < childNodes.getLength(); c ++){
+	    // a metadata node
+	    if (childNodes.item(c).getNodeType() == org.w3c.dom.Node.ELEMENT_NODE){
+		String metadataLabel = childNodes.item(c).getNodeName();
+
+		// cull any leading "GSDL3" tag and its colon...
+		if (metadataLabel.startsWith(GSDL3_NAMESPACE_ID + ":")){
+		    metadataLabel = metadataLabel.substring(this.name.length() + 1);
+		}
+		
+		// TODO: throw error: bad metadata type
+		if (metadataLabel.equals(GSDL3_METADATA_TAG) == false){
+		    continue;
+		}
+		
+		// Get the label - if the name isn't set, abort.
+		// TODO: throw error: incomplete metadata tag
+		metadataLabel = ((Element) childNodes.item(c)).getAttribute("name");
+		if (metadataLabel == null) {
+		    continue;
+		}
+		
+		// now build the associated value.
+		String metadataValue = "";
+		
+		Element childElement = (Element) childNodes.item(c);
+		for (int i = 0; i < childElement.getChildNodes().getLength(); i ++) {
+		    metadataValue = metadataValue + childElement.getChildNodes().item(i).toString();
+		}
+		
+		this.addMetadata(metadataLabel, metadataValue);
+	    }
+	}
+    }
+    
+    /**
+     *  Write out a single element - this may be overloaded to provide for the
+     *  appropriate formatting for this metadata.
+     */
+    protected boolean writeItem(PrintWriter writer, String label)
+    {	
+	if (this.location == null){
+	    // just place the metadata in a simple wrapper
+	    Iterator values = this.metadataMap.getAll(label).iterator();
+	    
+	    while (values.hasNext()){
+		String tag;
+		String value = values.next().toString();
+		
+		tag = XMLTools.getOpenTag(GSDL3_NAMESPACE_ID, GSDL3_METADATA_TAG);
+		tag = XMLTools.addAttribute(tag, "name", label);
+		writer.print(tag);
+		writer.print(value);
+		
+		writer.println(XMLTools.getCloseTag(this.name, GSDL3_METADATA_TAG));
+	    }
+	}
+	else {
+	    String tag = XMLTools.getOpenTag("mets", "mdRef");
+	    tag = XMLTools.addAttribute(tag, "LOCTYPE", this.location.getType());
+	    tag = XMLTools.addAttribute(tag, "xlink:href", this.location.getLocation().toString());
+	    tag = XMLTools.addAttribute(tag, "MDTYPE", this.getName());
+	    tag = XMLTools.makeSingleton(tag);
+	    writer.println(tag);
+	}
+	return true;
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSAdmin.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSAdmin.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSAdmin.java	(revision 13666)
@@ -0,0 +1,11 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+/**
+ *  METS Administrative metadata
+ *
+ *  May contain zero or more instances of administrative metadata
+ */
+
+public class METSAdmin
+{
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSAgent.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSAgent.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSAgent.java	(revision 13666)
@@ -0,0 +1,64 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+public class METSAgent
+{
+	String name;
+	String note;
+
+	String role;
+	String otherrole;
+	String type;
+	String othertype;
+
+	public METSAgent(String name, String note, String role, String type)
+	{	this.name = name;
+		this.note = note;
+
+		this.setRole(role);
+		this.setType(type);
+	}
+
+	/**
+	 *  Check if the role matches one of the standard offerings
+	 */
+	private boolean validateRole(String role)
+	{	return true;
+	}
+
+	/**
+	 *  Check if the type matches one of the standard offerings
+	 */
+	private boolean validateType(String role)
+	{	if (role.equals("INDIVIDUAL") ||
+		    role.equals("ORGANIZATION")) {
+			return true;
+		}
+		return false;
+	}
+
+	public void setRole(String otherRole)
+	{	// automatically use 'OTHER' if either the role or type of agent don't
+		// validate against the standard list
+		if (this.validateRole(role)) {
+			this.role = role;
+			this.otherrole = null;
+		}
+		else {
+			this.role = "OTHER";
+			this.otherrole = role;
+		}
+	}
+
+	public void setType(String otherType)
+	{	// automatically use 'OTHER' if either the role or type of agent don't
+		// validate against the standard list
+		if (this.validateType(type)) {
+			this.type = type;
+			this.othertype = null;
+		}
+		else {
+			this.type = "OTHER";
+			this.othertype = type;
+		}
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSDate.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSDate.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSDate.java	(revision 13666)
@@ -0,0 +1,153 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+public class METSDate
+{
+	String era;
+	String year;
+	String month;
+	String day;
+	String hour;
+	String minute;
+	String second;
+	String timezone;
+
+	public void METSDate(String string)
+	{	String date;
+
+		int timeAt = string.indexOf('T');
+
+		// if we've got a time signature, get it
+		if (timeAt >= 0) {
+		  // get the date for later use
+			date = string.substring(0, timeAt);
+
+			// extract the time string
+			String time = string.substring(timeAt+1);
+
+			// check for time zone usage - currently '+' and '-' only...
+			int zoneAt = time.indexOf('+');
+			if (zoneAt == -1) {	
+				zoneAt = time.indexOf('-');
+			}
+			if (zoneAt >= 0) {
+				this.timezone = time.substring(zoneAt);
+				time = time.substring(0, zoneAt);
+			}
+
+			// finally, divide into hours, minutes etc.
+			int hourAt = time.indexOf(':');
+			if (hourAt >= 0) {
+				this.hour = time.substring(0, hourAt);
+
+				time = time.substring(hourAt+1);
+				int minuteAt = time.indexOf(':');
+				if (minuteAt >= 0)
+				{	this.minute = time.substring(0, minuteAt);
+					this.second = time.substring(minuteAt+1);
+				}
+				else
+				{ this.minute = time;
+					this.second = null;
+				}
+			}
+		}
+		else 
+		{ this.timezone = null;
+			this.hour     = null;
+			this.minute   = null;
+			this.second   = null;
+
+			date = string;
+		}
+
+		// get the era
+		int prefixEnds = 0;
+		while (!Character.isDigit(date.charAt(prefixEnds)))
+		{ prefixEnds ++;
+		}
+
+		if (prefixEnds != 0) {
+			this.era = date.substring(0, prefixEnds);
+			date = date.substring(prefixEnds);
+		}
+		else {
+			this.era = null;
+		}
+
+		// finally, get the date
+		
+		// now try dividing up by '-'
+		int yearAt = date.indexOf('-');
+		if (yearAt >= 0) {
+			this.year = date.substring(0, yearAt);
+			date = date.substring(yearAt+1);
+
+			int monthAt = date.indexOf('-');
+			if (monthAt >= 0) {
+				this.month = date.substring(0, monthAt);
+				this.day = date.substring(monthAt+1);
+			}
+			else {
+				this.month = date;
+				this.day   = null;
+			}
+		}
+		else {
+			// try dividing by YYYYMMDD - any part of which may be missing...
+			if (date.length() >= 4) {
+				this.year = date.substring(0, 4);
+				if (date.length() >= 6) {
+					this.month = date.substring(4, 6);
+					this.day = date.substring(6);
+				}
+				else {
+					this.month = date.substring(4);
+					this.day   = null;
+				}
+			}
+			// we just have a day in this case...
+			else {
+				this.year = date;
+				this.month = null;
+				this.day = null;
+			}
+		}
+	}
+
+	public String toString()
+	{	if (this.year == null) {
+			return "";
+		}
+
+		StringBuffer buffer = new StringBuffer();
+
+		if (this.era != null) {
+			buffer.append(era);
+		}
+		buffer.append(year);
+		if (this.month != null) {
+			buffer.append("-");
+			buffer.append(this.month);
+			if (this.day != null) {
+				buffer.append("-");
+				buffer.append(this.day);
+
+				if (this.hour != null) {
+					buffer.append("T");
+					buffer.append(this.hour);
+					buffer.append(":");
+					buffer.append(this.minute);
+					if (this.second != null) {
+						buffer.append(":");
+						buffer.append(this.second);
+
+						if (this.timezone != null) {
+							buffer.append(this.timezone);
+						}
+					}
+				}
+			}
+		}
+		return buffer.toString();
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSDescriptive.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSDescriptive.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSDescriptive.java	(revision 13666)
@@ -0,0 +1,494 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import java.io.PrintWriter;
+
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.ResultSet;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+
+import org.greenstone.gsdl3.gs3build.util.XMLTools;
+import org.greenstone.gsdl3.gs3build.database.*;
+
+/**
+ *  Support the descriptive metadata of a given document
+ *
+ *  The descriptive metadata can occur multiple times, so this 'wrapper' is
+ *  in fact a holder for a number of individual metadata sets.  Individual
+ *  metadata groups are found in METSNamespace items.
+ *
+ *  
+ */
+
+import org.greenstone.gsdl3.gs3build.util.MultiMap;
+
+public class METSDescriptive
+{ 
+    MultiMap map;
+    String   ID;
+    String   name;
+    
+    public METSDescriptive(String ID, String name)
+    { 
+	this.map  = new MultiMap();
+	this.ID   = ID;
+	this.name = name;
+    }
+    
+    public String getID()
+    { 
+	return this.ID;
+    }
+    
+    public String getName()
+    { 
+	return this.name;
+    }
+    
+    public void addNamespace(METSNamespace namespace)
+    { 
+	this.map.put(namespace.getName(), namespace);
+    }
+    
+    public METSNamespace getNamespace(String namespace)
+    {
+	return (METSNamespace) this.map.get(namespace);
+    }
+    
+    /**
+     *  Get the version of a metadata namespace that can be used for
+     *  adding new values to the document.  Remember, each namespace may
+     *  occur more than once, but only one of the occurrences can be 'open'.
+     *
+     *  @param <code>String</code> the name of the namespace
+     */
+    public METSNamespace getOpenNamespace(String namespace)
+    { 
+	if (this.map.getAll(namespace) == null) {
+	    return null;
+	}
+	
+	Iterator namespaces = ((List) this.map.getAll(namespace)).iterator();
+	
+	while (namespaces.hasNext()) {
+	    METSNamespace namespaceData = (METSNamespace) namespaces.next();
+	    
+	    if (namespaceData.isEditable()){
+		return namespaceData;
+	    }
+	}
+	return null;
+    }
+    
+    /**
+     *  Add a piece of metadata to this document.  Existing values are preserved.
+     *
+     *  @param <code>String</code> the namespace in which the metadata occurs
+     *  @param <code>String</code> the label of the metadata   
+     *  @param <code>String</code> the value of the metadata
+     */
+    public void addMetadata(String namespace, String label, String value)
+    { 
+	METSNamespace namespaceData = this.getOpenNamespace(namespace);
+	
+	if (namespaceData == null ||
+	    namespaceData.isEditable() == false) {
+	    namespaceData = NamespaceFactory.initNamespace(namespace);
+	    this.addNamespace(namespaceData);
+	}
+	namespaceData.addMetadata(label, value);
+    }
+    
+    /**
+     *  Add a piece of metadata to this document.  Existing values in editable
+     *  parts of the document's metadata are destroyed.
+     *
+     *  @param <code>String</code> the namespace in which the metadata occurs
+     *  @param <code>String</code> the label of the metadata   
+     *  @param <code>String</code> the value of the metadata
+     */
+    public void setMetadata(String namespace, String label, String value)
+    { 
+	METSNamespace namespaceData = this.getOpenNamespace(namespace);
+	
+	if (namespaceData == null ||
+	    namespaceData.isEditable() == false) {
+	    namespaceData = NamespaceFactory.initNamespace(namespace);
+	    this.addNamespace(namespaceData);
+	}
+	namespaceData.setMetadata(label, value);
+    }
+    
+    /**
+     *  Remove the metadata for a particular label.
+     *
+     *  @param <code>String</code> the namespace in which the metadata occurs
+     *  @param <code>String</code> the label of the metadata
+     */
+    public void removeMetadata(String namespace, String label)
+    { 
+	METSNamespace namespaceData = this.getOpenNamespace(namespace);
+	
+	if (namespaceData != null && namespaceData.isEditable() == true) {
+	    namespaceData.removeMetadata(label);
+	}
+    }
+    
+    /**
+     *  Fetch a <code>List</code> of the values matching the given label in
+     *  the requisite namespace.
+     *
+     *  @param <code>String</code> namespace
+     *  @param <code>String</code> label of metadata to match
+     *
+     *  @return <code>List</code> the corresponding values found.
+     */
+    public List getMetadata(String namespace, String label)
+    {
+	// Simple case - no metadata
+	if (!this.map.containsKey(namespace)){
+	    return null;
+	}
+	
+	// if there's just one instance of the requisite namespace,
+	// then again it is a simple case
+	if (this.map.getAll(namespace).size() == 1){
+	    return this.getNamespace(namespace).getMetadata(label);
+	}
+	
+	// otherwise, step through and accumulate
+	List accumulatedValues = new ArrayList();
+	Iterator namespaceIterator = this.map.getAll(namespace).iterator();
+	while (namespaceIterator.hasNext()){
+	    METSNamespace localNamespace = (METSNamespace) namespaceIterator.next();
+	    
+	    List localList = localNamespace.getMetadata(label);
+	    if (localList != null && localList.size() > 0){
+		accumulatedValues.addAll(localList);
+	    }
+	}
+	
+	// if the result of the accumulation is empty, return a null item
+	if (accumulatedValues.size() == 0){
+	    return null;
+	}
+	
+	return accumulatedValues;
+    }
+    
+    protected void parse_xmlData(METSNamespace namespace, Element element) 
+    {
+	if (namespace==null) {
+	    System.err.println("namespace is null!!!!");
+	}
+	NodeList children = element.getChildNodes();
+	
+	for (int c = 0; c < children.getLength(); c++) {
+	    if (children.item(c).getNodeType() != org.w3c.dom.Node.ELEMENT_NODE) {
+		continue;
+	    }
+	    
+	    Element child  = (Element) children.item(c);
+	    String childName = child.getNodeName();
+	    
+	    // if (childName.equals("gsdl2:Metadata")) {
+	    if (childName.equals("gsdl3:Metadata")) {
+		String metaName = child.getAttribute("name");
+		Text text = (Text) child.getFirstChild();
+		String metaValue = text.getData();
+		
+		addMetadata(namespace.getName(),metaName, metaValue);
+	    }
+	}
+    }
+    
+    public void parse_mdWrap(Element element)
+    {
+	// deal with mets:mdWrap
+	
+	METSNamespace namespace = NamespaceFactory.parseXML(element);
+	
+	NodeList children = element.getChildNodes();
+	
+	for (int c = 0; c < children.getLength(); c ++) {
+	    if (children.item(c).getNodeType() != org.w3c.dom.Node.ELEMENT_NODE) {
+		continue;
+	    }
+	    
+	    Element child  = (Element) children.item(c);
+	    String childName = child.getNodeName();
+
+	    if (childName.equals("mets:xmlData")) {
+		parse_xmlData(namespace, child);
+	    } else {
+		System.err.println("Warning: unrecognised tag " + childName 
+				   + "in mets:mdWrap");
+	    }
+	}
+    }
+
+    /**
+     *  Parse an XML Element as a METS Descriptive Metadata section
+     *
+     *  @param <code>Element</code> the XML element which represents the dmdSec itself
+     */
+    public static METSDescriptive parseXML(Element element) 
+    {
+	// Note: no parsing of attributes required, we just move onto
+	// the metadata namespaces/sections themselves
+
+	// deal with mets:dmdSec
+	String ID = element.getAttribute("ID");
+	String label = element.getAttribute("GROUPID");
+	
+	METSDescriptive thisDescriptive = new METSDescriptive(ID, label);
+
+	//thisDescriptive = new METSDescriptive(ID, label);
+	
+	NodeList children = element.getChildNodes();
+
+	for (int c = 0; c < children.getLength(); c ++) {
+	    if (children.item(c).getNodeType() != org.w3c.dom.Node.ELEMENT_NODE) {
+		continue;
+	    }
+	    
+	    Element child = (Element) children.item(c);
+	    String childName = child.getNodeName();
+	    
+	    if (childName.equals("mets:mdRef")) {
+		//for External Descriptive Metadata
+		METSNamespace namespace = NamespaceFactory.parseXML(element);
+		System.err.println("*** mets::mdRef does not appear to be implemented yet");
+	    } else if (childName.equals("mets:mdWrap")) {
+		thisDescriptive.parse_mdWrap(child);
+	    } else {
+		// TODO: raise an error!
+		System.out.println("Error: METSDescriptive: unrecognised tag "+childName);
+	    }
+	}
+	return thisDescriptive;
+    }
+    /**
+     *  Write the document metadata to a <code>PrintWriter</code> in METS
+     *  XML format.
+     *  
+     *  @param <code>PrintWriter</code> the writer to use for output
+     */
+    public void write(PrintWriter output)
+    { 
+	String tag = XMLTools.getOpenTag("mets", "dmdSec");
+	tag = XMLTools.addAttribute(tag, "ID", this.ID);
+	tag = XMLTools.addAttribute(tag, "GROUPID", this.name);
+	output.println(tag);
+	
+	Iterator keys = this.map.keySet().iterator();
+	
+	// get the keys one by one
+	while (keys.hasNext()){
+	    Object nextKey = keys.next();
+	    if (nextKey == null){
+		continue;
+	    }
+	    String key = nextKey.toString();
+	
+	    // get every copy of the current namespace name - namespaces may
+	    // occur more than once, so this is a List
+	    Iterator namespaces = this.map.getAll(key).iterator();
+	    
+	    // namespaces will write themselves...
+	    while (namespaces.hasNext()){
+		METSNamespace namespace = (METSNamespace) namespaces.next();
+	
+		namespace.write(output);
+	    }
+	}
+	
+	tag = XMLTools.getCloseTag("mets", "dmdSec");
+	output.println(tag);
+    }
+    
+    public void copy_metadata(METSDescriptive dst) 
+    {
+	Iterator keys = this.map.keySet().iterator();
+	
+	// get the keys one by one
+	while (keys.hasNext()) {
+	    Object nextKey = keys.next();
+	    if (nextKey == null) {
+		continue;
+	    }
+	    String key = nextKey.toString();
+	    
+	    // get every copy of the current namespace name - namespaces may
+	    // occur more than once, so this is a List
+	    Iterator namespaces = this.map.getAll(key).iterator();
+      
+	    while (namespaces.hasNext()) {
+		METSNamespace namespace = (METSNamespace) namespaces.next();
+		
+		// for each metadata name 
+
+		Iterator mdnIter = namespace.getMetadataNames();
+		while (mdnIter.hasNext()) {
+
+		    String md_name = mdnIter.next().toString();
+		    
+		    List values = getMetadata(key, md_name);
+		    
+		    if (values != null) {	
+			Iterator valueIter = values.iterator();
+			while (valueIter.hasNext()) {
+			    String value = valueIter.next().toString();
+			    dst.addMetadata("gsdl3",md_name,value);
+			}
+		    }
+		}
+	    }
+	}
+    }
+
+
+    public boolean writeSQL(DocumentInterface document, GS3SQLConnection connection)
+    { 
+	// check if this node is in the
+	int sqlId = -1;
+	
+	//    System.out.println("Writing " + connection.toString());
+	
+	GS3SQLSelect select = new GS3SQLSelect("metadata");
+	select.addField("*");
+	GS3SQLWhereItem whereItem = new GS3SQLWhereItem("MetaID", "=", this.ID);
+	GS3SQLWhereItem item = new GS3SQLWhereItem("DocID", "=", document.getID().toString());
+	GS3SQLWhere where = new GS3SQLWhere(whereItem);
+	where.add(item);
+	select.setWhere(where);
+	
+	try {
+	    Statement statement = connection.createStatement();
+	    ResultSet resultSet = statement.executeQuery(select.toString());
+	    GS3SQLAction action;
+	    
+	    if (resultSet.first()) {
+		// the node already exists - no need to do anything as such
+		GS3SQLUpdate update = new GS3SQLUpdate("metadata");
+		update.setWhere(where);
+		action = update;
+	    }
+	    else { // Set result set to null, just in case first() didn't work above...
+		// It is a new node and needs writing
+		action = new GS3SQLInsert("metadata");
+		
+		action.addValue("DocID", document.getID().toString());
+		action.addValue("MetaID", this.ID);
+	    }
+	    
+	    // always set the group identifier
+	    action.addValue("GroupID", this.name);
+	    
+	    // execute the action as required
+	    statement.execute(action.toString());
+	    
+	    // get the resultSet again
+	    // now execute the select statement again to get the new identifier
+	    // 'MetadataRef'
+	    // System.out.println(select.toString());
+	    resultSet = statement.executeQuery(select.toString());
+	    
+	    if (resultSet.first()) {
+		// get the reference for this item...
+		sqlId = resultSet.getInt("MetadataRef");
+	    }
+	    statement.close();
+	}
+	catch (SQLException sql){
+	    System.err.println("METSDescriptive.writeSQL(): "+sql);
+	}
+	if (sqlId == -1) {
+	    return false;
+	}
+	
+	Iterator keys = this.map.keySet().iterator();
+	
+	// get the keys one by one
+	while (keys.hasNext()){
+	    Object nextKey = keys.next();
+	    if (nextKey == null){
+		continue;
+	    }
+	    String key = nextKey.toString();
+	    
+	    // get every current namespace - namespaces may
+	    // occur more than once, so this is a List
+	    Iterator namespaces = this.map.getAll(key).iterator();
+	    
+	    // namespaces will write themselves...
+	    while (namespaces.hasNext()){
+		METSNamespace namespace = (METSNamespace) namespaces.next();
+		
+		if (!namespace.writeSQL(sqlId, connection)){
+		    return false;
+		}
+	    }
+	}
+	return true;
+    }
+    
+    public static METSDescriptive readSQL(DocumentInterface document, GS3SQLConnection connection,
+					  ResultSet resultSet)
+    {
+	try {
+	    String ID   = resultSet.getString("MetaID");
+	    String name = resultSet.getString("GroupID");
+	    
+	    // create the metadata block object
+	    METSDescriptive descriptive = new METSDescriptive(ID, name);
+	    
+	    // get its metadata reference to retrieve namespaces
+	    int metadataRef = resultSet.getInt("MetadataRef");
+	    
+	    // query the database for matching namespaces for this metadata block
+	    GS3SQLSelect select = new GS3SQLSelect("namespaces");
+	    select.addField("*");
+	    GS3SQLWhereItem whereItem = new GS3SQLWhereItem("MetadataRef", "=", Integer.toString(metadataRef),
+							    GS3SQLField.INTEGER_TYPE);
+	    GS3SQLWhere where = new GS3SQLWhere(whereItem);
+	    select.setWhere(where);
+	    
+	    Statement statement = connection.createStatement();
+	    ResultSet namespaceSet = statement.executeQuery(select.toString());
+	    
+	    // parse through the namespaces, calling the namespace class to create instances as it will
+	    if (namespaceSet.first()) {
+		do {
+		    METSNamespace namespace = METSNamespace.readSQL(connection, namespaceSet);
+		    if (namespace != null) {
+			descriptive.addNamespace(namespace);
+		    }
+		    else {
+			System.err.println("Null namespace output");
+		    }
+		}
+		while (namespaceSet.next());
+	    }
+	    statement.close();
+	    return descriptive;
+	}
+	catch (SQLException sqlEx){
+	    System.err.println("METSDescriptive.readSQL(): "+sqlEx);
+	    System.exit(1);
+	}
+	return null;
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSDescriptiveSection.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSDescriptiveSection.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSDescriptiveSection.java	(revision 13666)
@@ -0,0 +1,22 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+public abstract class METSDescriptiveSection
+{ 
+    METSLocation location;
+    String       type;
+    String       otherType;
+    
+    public METSDescriptiveSection(String type)
+    {	
+	this.location  = null;
+	this.type      = type;
+	this.otherType = null;
+    }
+	
+    public METSDescriptiveSection(METSLocation location, String type)
+    {	
+	this.location  = location;
+	this.type      = type;
+	this.otherType = null;
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSDescriptiveSet.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSDescriptiveSet.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSDescriptiveSet.java	(revision 13666)
@@ -0,0 +1,266 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+import java.io.PrintWriter;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Iterator;
+
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.ResultSet;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+
+import org.greenstone.gsdl3.gs3build.database.*;
+
+public class METSDescriptiveSet
+{ 
+    Map children;
+    Map childrenById;
+    DescriptiveIdentifierFactory identifierFactory;
+    
+    class DescriptiveIdentifierFactory extends AbstractIdentifierFactory
+    { 
+	public DescriptiveIdentifierFactory()
+	{ 
+	    super("DM");
+	}
+    }
+    
+    public METSDescriptiveSet()
+    { 
+	this.children = new HashMap();
+	this.childrenById = new HashMap();
+	
+	this.identifierFactory = new DescriptiveIdentifierFactory();
+	
+	this.createDescriptive("default");
+    }
+    
+    /**
+     *  Create a new descriptive child, adding it automatically to this descriptive set.
+     *
+     *  @param <code>String</code> a name to describe the descriptive set.
+     */
+    public METSDescriptive createDescriptive(String name)
+    { 
+	METSDescriptive descriptive = new METSDescriptive(this.identifierFactory.getNextIdentifier(), name);
+	
+	this.children.put(name, descriptive);
+	this.childrenById.put(descriptive.getID(), descriptive);
+	return descriptive;
+    }
+    
+    /**
+     *  Add a descriptive item to this set.
+     *
+     *  @param <code>METSDescriptive</code> the descriptive set
+     */
+    public void addDescriptive(METSDescriptive metadata)
+    { 
+	// insert the item into both maps...
+	this.children.put(metadata.getName(), metadata);
+	this.childrenById.put(metadata.getID(), metadata);
+	
+	// when a descriptive block is added, check that it hasn't been used before...
+	//this.identifierFactory.noteIdentifier(metadata.getID());
+	this.identifierFactory.noteIdentifier(metadata.getName());
+    }
+    
+    /**
+     *  Get a descriptive item by its name(GROUPID in METS file)
+     */
+    public METSDescriptive getDescriptive(String name)
+    { 
+	
+	return (METSDescriptive) this.children.get(name);
+    }
+    
+    /**
+     *  Get a descriptive item by its identifier
+     */
+    public METSDescriptive getDescriptiveById(String id)
+    { 
+	return (METSDescriptive) this.childrenById.get(id);
+    }
+    
+    public void addNamespace(String descriptiveName, METSNamespace namespace)
+    { 
+	METSDescriptive descriptive = this.getDescriptive(descriptiveName);
+	if (descriptive != null){
+	    descriptive.addNamespace(namespace);
+	}
+    }
+    
+    public METSNamespace getNamespace(String descriptiveName, String namespace)
+    { 
+	METSDescriptive descriptive = this.getDescriptive(descriptiveName);
+	if (descriptive != null){
+	    return descriptive.getNamespace(namespace);
+	}
+	return null;
+    }
+    
+    public METSNamespace getOpenNamespace(String descriptiveName, String namespace)
+    { 
+	METSDescriptive descriptive = this.getDescriptive(descriptiveName);
+	
+	if (descriptive != null){
+	    return descriptive.getOpenNamespace(namespace);
+	}
+	return  null;
+    }
+    
+    public void addMetadata(String descriptiveName, String namespace, String label, String value)
+    { 
+	METSDescriptive descriptive = this.getDescriptive(descriptiveName);
+	
+	if (descriptive != null){
+	    descriptive.addMetadata(namespace, label, value);
+	}
+    }
+    
+    public void setMetadata(String descriptiveName, String namespace, String label, String value)
+    { 
+	METSDescriptive descriptive = this.getDescriptive(descriptiveName);
+	
+	if (descriptive != null){
+	    descriptive.setMetadata(namespace, label, value);
+	}
+    }
+    
+    public void removeMetadata(String descriptiveName, String namespace, String label)
+    { 
+	METSDescriptive descriptive = this.getDescriptive(descriptiveName);
+	
+	if (descriptive != null){
+	    descriptive.removeMetadata(namespace, label);
+	}
+    }
+    
+    public void removeAllMetadata(String namespace, String label)
+    { 
+	Iterator descriptiveIter = this.children.values().iterator();
+	
+	while (descriptiveIter.hasNext()) {
+	    METSDescriptive descriptive = (METSDescriptive) descriptiveIter.next();
+	    
+	    descriptive.removeMetadata(namespace, label);
+	}
+    }
+    
+    public List getMetadata(String descriptiveName, String namespace, String label)
+    { 
+	METSDescriptive descriptive = this.getDescriptive(descriptiveName);
+	
+	if (descriptive != null){
+	    return descriptive.getMetadata(namespace, label);
+	}
+	return null;
+    }
+    
+    public void write(PrintWriter writer)
+    { 
+	Iterator groups = this.children.values().iterator();
+	
+	while (groups.hasNext()){
+	    METSDescriptive group = (METSDescriptive) groups.next();
+	    
+	    group.write(writer);
+	}
+    }
+    
+    
+    public boolean writeSQL(DocumentInterface document, GS3SQLConnection connection)
+    { 
+	Iterator groups = this.children.values().iterator();
+	
+	while (groups.hasNext()){
+	    METSDescriptive group = (METSDescriptive) groups.next();
+	    
+	    if (!group.writeSQL(document, connection)){
+		return false;
+	    }
+	}
+	return true;
+    }
+
+    public static METSDescriptiveSet parseXML(NodeList dmdSecs) 
+    {
+	METSDescriptiveSet set = new METSDescriptiveSet();
+	
+	for (int g = 0; g < dmdSecs.getLength(); g ++) {
+	    METSDescriptive metadata = METSDescriptive.parseXML((Element) dmdSecs.item(g));
+	    
+	    set.addDescriptive(metadata);
+	}
+    
+	System.err.println("******** Away to do transfer!!!!!!");
+	  
+	METSDescriptive top_level_metadata = set.getDescriptive("1");
+	METSDescriptive tl2_metadata = set.getDescriptive("1");
+	METSDescriptive opo_metadata = set.getDescriptive("1.1");
+	METSDescriptive default_metadata = set.getDescriptive("default");
+	
+	if (top_level_metadata != null) {
+	    if (default_metadata != null) {
+		top_level_metadata.copy_metadata(default_metadata);
+	    }
+	    else {
+		System.err.println("Warning: Could not find default metadata");
+	    }
+	}
+	else {
+	    System.err.println("Warning: Could not find top level metadata for groupID=1");
+	}
+	return set;
+    } 
+    
+    public static METSDescriptiveSet readSQL(DocumentInterface document, GS3SQLConnection connection)
+    {
+	METSDescriptiveSet set = new METSDescriptiveSet();
+	
+	GS3SQLSelect select = new GS3SQLSelect("metadata");
+	select.addField("*");
+	GS3SQLWhereItem whereItem = new GS3SQLWhereItem("DocID", "=", document.getID().toString());
+	select.setWhere(new GS3SQLWhere(whereItem));
+
+	// start going through the matching metadata blocks
+	try {
+	    Statement statement = connection.createStatement();
+	    ResultSet resultSet = statement.executeQuery(select.toString());
+	    if (resultSet.first()) {
+		do {
+		    METSDescriptive descriptive = METSDescriptive.readSQL(document, connection, resultSet);
+		    if (descriptive != null) {
+			set.addDescriptive(descriptive);
+		    }
+		    else {
+			System.out.println("Null descriptive");
+		    }
+		} while (resultSet.next());
+	    }
+	    statement.close();
+	}
+	catch (SQLException sqlEx) {
+	    System.err.println("METSDescriptiveSet.readSQL(): "+sqlEx);
+	    System.exit(1);
+	}
+	
+	
+	return set;
+    }
+}
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSDivision.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSDivision.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSDivision.java	(revision 13666)
@@ -0,0 +1,681 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+import java.io.PrintWriter;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.LinkedHashMap;
+
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.ResultSet;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+import org.greenstone.gsdl3.gs3build.util.XMLTools;
+import org.greenstone.gsdl3.gs3build.database.*;
+
+public class METSDivision extends AbstractStructure
+{
+    String       order;       // see the METS documentation for the meaning of the different
+    String       orderLabel;  // label types.
+    String       userLabel;
+    String       type;        // e.g. section, chapter, physical or logical, etc.
+    List         metadataRefs;
+    List         adminRefs;
+    List         fileRefs;
+    
+    public static final String DIVISION_TYPE  = "Division";
+    public static final String DIVISION_TAG   = "div";
+    public static final String FPTR_TAG       = "fptr";
+    
+    public METSDivision(String ID, String order, String orderLabel, String userLabel, String type)
+    { 
+	super(ID);
+	
+	this.order = order;
+	this.orderLabel = orderLabel;
+	this.userLabel = userLabel;
+	this.type = type;
+	this.fileRefs = new ArrayList();
+	this.metadataRefs = new ArrayList();
+    }
+    
+    public String getStructureType()
+    { 
+	return DIVISION_TYPE;
+    }
+    
+    public String getLabel()
+    { 
+	return this.orderLabel;
+    }
+    
+    /**
+     *  Find all the divisions that match a given list of file group
+     *  identifiers...
+     *
+     *  @param <code>List</code> the list of identifiers to find
+     *  @param <code>List</code> the list into which to place any
+     *         matching divisions.
+     */
+    public void findDivisionsForFiles(List listOfFileIdentifiers, List resultList)
+    { 
+	Iterator iterator = this.fileRefs.iterator();
+	
+	// get the references on this division, and mark if necessary
+	while (iterator.hasNext()) {
+	    String reference = iterator.next().toString();
+	    
+	    Iterator fileIterator = listOfFileIdentifiers.iterator();
+	    while (fileIterator.hasNext()){
+		String fileRef = fileIterator.next().toString();
+		
+		if (fileRef.equals(reference)){
+		    resultList.add(this);
+		}
+	    }
+	}
+	
+	// get the child groups, and check each in turn...
+	Iterator groups = this.children.values().iterator();
+	while (groups.hasNext()){
+	    METSDivision group = (METSDivision) groups.next();
+	    
+	    group.findDivisionsForFiles(listOfFileIdentifiers, resultList);
+	}    
+    }
+    
+    /**
+     *  Get the namespace from the given set of descriptive blocks...
+     */
+    public METSNamespace findNamespace(String namespaceName, boolean isOpenNamespace, 
+				       METSDescriptiveSet descriptiveSet)
+    { 
+	METSNamespace namespace = null;
+	
+	// Special case - no existing metadata references
+	if (this.metadataRefs.size() == 0) {
+	    // Create new Descriptive and add it to the descriptive set
+	    METSDescriptive descriptive = new METSDescriptive("DM"+this.ID, this.orderLabel);
+	    descriptiveSet.addDescriptive(descriptive);
+	    
+	    // Create the namespace and add it to the Descriptive
+	    namespace = NamespaceFactory.initNamespace(namespaceName);
+	    if (namespace != null){
+		descriptive.addNamespace(namespace);
+	    }
+	    
+	    return namespace;
+	}
+	
+	Iterator descriptiveIterator = this.metadataRefs.iterator();
+	
+	while (descriptiveIterator.hasNext()){
+	    String descriptiveRef = descriptiveIterator.next().toString();
+	    
+	    METSDescriptive descriptive = descriptiveSet.getDescriptiveById(descriptiveRef);
+	    
+	    if (isOpenNamespace) {
+		namespace = descriptive.getOpenNamespace(namespaceName);
+	    }
+	    else {
+		namespace = descriptive.getNamespace(namespaceName);
+	    }
+	    
+	    if (namespace != null)
+		break;
+	}
+	
+	// Special case - no such namespace in any descriptive list...
+	if (namespace == null){
+	    // take the first descriptive area...
+	    METSDescriptive descriptive = descriptiveSet.getDescriptiveById(this.metadataRefs.get(0).toString());
+	    
+	    // create the namespace, and add it to the METSDescriptive
+	    namespace = NamespaceFactory.initNamespace(namespaceName);
+	    if (namespace != null){
+		descriptive.addNamespace(namespace);
+	    }
+	}
+	
+	return namespace;
+    }
+    
+    /**
+     *  Add a new file reference to the structure
+     *
+     *  @param <code>METSFileID</code> the file to be referenced.
+     */
+    public void addFileReference(METSFileID fileRef)
+    { 
+	this.addFileReference(fileRef.toString());
+    }
+    
+    public void addFileReference(String fileRef)
+    { 
+	this.fileRefs.add(fileRef);
+    }
+    
+    /**
+     *  Add a new metadata reference to the structure
+     */
+    public void addMetadataReference(String metadataRef)
+    { 
+	// TODO: correct the type
+	this.metadataRefs.add(metadataRef);
+    }
+
+    /**
+     *  Get all the metadata references
+     *
+     *  @return <code>List</code> containing all the references
+     */
+    public List getMetadataReferences()
+    { 
+	return this.metadataRefs;
+    }
+
+    /**
+     *  Get all the default (first) metadata reference...
+     *
+     *  @return <code>List</code> containing all the references
+     */
+    //TODO: check for this first *open* metadata item...
+    public String getDefaultMetadataReference()
+    { 
+	if (this.metadataRefs.size() == 0) {
+	return null;
+    }
+    return this.metadataRefs.get(0).toString();
+    }
+
+    /**
+     *  Get all the default (first) first filegroup reference...
+     *
+     *  @return <code>List</code> containing all the references
+     */
+    public String getDefaultFileReference()
+    { 
+	if (this.fileRefs.size() == 0) {
+	return null;
+    }
+    return this.fileRefs.get(0).toString();
+    }
+
+    /**
+     *  Get a child or descendant division
+     *
+     *  @param <code>String</code> the path to the child division
+     *  @return <code>METSDivision</code> the division found.
+     */
+    public METSDivision getDivision(String divisionLabel)
+    { 
+	// if the division ID equals this, then process it
+	if (divisionLabel.equals(this.orderLabel)) {
+	    return this;
+	}
+
+	// if we just shouldn't be here, then error...
+	if (!divisionLabel.startsWith(this.orderLabel + ".")) {
+	    return null;
+	}
+
+	// get the next division in the division path...
+	String subdivisionPath = divisionLabel.substring(this.orderLabel.length() + 1);
+	String nextDivision = getTopDivisionName(subdivisionPath);
+	String nextLabel;
+
+	// first try the current division name with an appended '.' and the next child id...
+	METSDivision child = (METSDivision) this.children.get(this.orderLabel + "." + nextDivision);
+	if (child == null){
+	    // if that didn't work, try the next division on its own
+	    child = (METSDivision) this.children.get(nextDivision);
+	    
+	    // if neither worked, then abort...
+	    if (child == null) {
+		return null;
+	    }
+	    else {
+		// set the next identifier
+		nextLabel = METSDivision.getSubDivisionName(divisionLabel);
+	    }
+	} 
+	else {
+	    // set the next identifier...
+	    nextLabel = divisionLabel;
+	}
+	
+	return child.getDivision(nextLabel);
+    }
+    
+    /**
+     *  A convenience method for splitting a division name - this gives the name
+     *  without the leading division label...  To be used when division identifiers
+     *  are given as '.' separated paths and division names do not contain the
+     *  full path of their parents.
+     *
+     *  @return <code>String</code>
+     */
+    public static String getSubDivisionName(String divisionName)
+    { 
+	int at = divisionName.indexOf('.');
+
+	if (at >= 0){
+	    return divisionName.substring(at+1);
+	}
+	else {
+		return null;
+	}
+    }
+
+    /**
+     *  Get the parent division name.  Division identifiers
+     *  concatenate the ancestor's names with intervening
+     *  '.' characters.
+     *
+     *  @return <code>String</code> the division name
+     */
+    public static String getParentName(String divisionName)
+    { 
+	int at = divisionName.lastIndexOf('.');
+
+	if (at >= 0) {
+	    return divisionName.substring(0, at);
+	} 
+	return "";
+    }
+    
+    /**
+     *  Get the top division name.
+     *
+     *  @return <code>String</code> the division name
+     */
+    public static String getTopDivisionName(String divisionName)
+    { 
+	int at = divisionName.indexOf('.');
+
+	if (at >= 0){
+	    return divisionName.substring(0, at);
+	}
+	else {
+	    return divisionName;
+	}
+    }
+
+    /*  Parse an XML Element as a METSDivision section
+     *
+     *  @param <code>Element</code> the XML element which represents
+     *  the mets:div itself 
+     */
+    
+    public static METSDivision parseXML(Element element) 
+    {
+ 	METSDivision thisDivision = null;
+ 
+ 	String divId = element.getAttribute("ID");
+ 	String divType = element.getAttribute("TYPE");
+ 	String divOrder = element.getAttribute("ORDER");
+ 	String divOrderLabel = element.getAttribute("ORDERLABEL");
+ 	String divUserLabel = element.getAttribute("LABEL");
+ 	String divMetaRef = element.getAttribute("DMDID");
+ 	
+ 	thisDivision = new METSDivision(divId, divOrder,divOrderLabel, divUserLabel, divType);
+ 		
+ 	thisDivision.addMetadataReference(divMetaRef);
+ 
+ 	NodeList children = element.getChildNodes();
+ 
+ 	for (int c = 0; c < children.getLength(); c++){
+ 	    if (children.item(c).getNodeType() != org.w3c.dom.Node.ELEMENT_NODE){
+ 		continue;
+ 	    }
+ 	    Element child = (Element) children.item(c);
+ 	    String childName = child.getNodeName();
+ 
+ 	    if (childName.equals("mets:fptr")) {
+ 		
+ 		METSDivision.fptr_parseXML(thisDivision, child);
+ 	    } else if (childName.equals("mets:div")) {
+ 		METSDivision division = METSDivision.parseXML(child);
+ 		thisDivision.addDivision(division);
+ 	    } else {
+ 		System.err.println("Error: mets:div expected mets:div or mets:fptr, but got " + childName);
+ 	    } 
+ 	}
+ 	return thisDivision;
+    }
+ 
+ 
+    /**
+     * Parse an XML element as a  METSFptr Section
+     * @param <code>Element</code> the XML element which represents the mets:fptr itself
+     */
+    private static void fptr_parseXML(METSDivision thisDivision, Element element) 
+    {
+ 	String fileRef = element.getAttribute("FILEID");
+ 	thisDivision.addFileReference(fileRef);
+    }
+ 
+    /**
+
+
+    /**
+    *  Write the METS file in an XML to a text-output sink.
+    *
+    *  @param <code>PrintWriter</code> the destination of the output
+    */
+    public boolean write(PrintWriter writer)
+    { 
+	// Get the main tag for the division
+	String tag = XMLTools.getOpenTag("mets", DIVISION_TAG);
+	tag = XMLTools.addAttribute(tag, "ID", this.ID.toString());
+	tag = XMLTools.addAttribute(tag, "TYPE", this.type);
+	tag = XMLTools.addAttribute(tag, "ORDER", this.order);
+	if (this.orderLabel != null){
+	    tag = XMLTools.addAttribute(tag, "ORDERLABEL", this.orderLabel);
+	}
+	if (this.userLabel != null){ 
+	    tag = XMLTools.addAttribute(tag, "LABEL", this.userLabel);
+	}
+	
+	// Add a metadata reference attribute
+	if (this.metadataRefs.size() > 0){
+	    String metaList = this.writeList(this.metadataRefs);
+	    tag = XMLTools.addAttribute(tag, "DMDID", metaList);
+	}
+	
+	// write the central tag
+	writer.print("   ");  //indentation
+	writer.println(tag);
+
+	// write the list of file pointers for this structural element
+	if (this.fileRefs.size() > 0) {
+	    String fileList = this.writeTagList("mets", "fptr", "FILEID", this.fileRefs);
+	    writer.print("      ");  //indentation
+	    writer.println(fileList);
+	}
+	
+	// write out any children in turn
+	Iterator groups = this.children.values().iterator();
+	
+	while (groups.hasNext()){
+	    METSDivision group = (METSDivision) groups.next();
+	    
+	    if (!group.write(writer)) {
+		return false;
+	    }
+	}
+    
+	// close the div element
+	writer.print("   ");  //indentation
+	writer.println(XMLTools.getCloseTag("mets", DIVISION_TAG));
+
+	return true;
+    }
+
+    /**
+     *  A convenience method for writing a <code>List</code> as a series of tags...
+     */
+    private String writeTagList(String namespace, String tagname, 
+				String attribute, List list)
+    { 
+	StringBuffer listString = new StringBuffer();
+	
+	Iterator iterator = list.iterator();
+	while (iterator.hasNext()){
+	    String item = iterator.next().toString();
+	    
+	    String tag = XMLTools.getOpenTag(namespace, tagname);
+	    tag = XMLTools.addAttribute(tag, attribute, item);
+	    tag = XMLTools.makeSingleton(tag);
+	    
+	    listString.append(tag);
+	}
+	return listString.toString();
+    }
+
+    /**
+     *  A convenience method for writing a <code>List</code> as a space-separated <code>String</code>.
+     */
+    private String writeList(List list)
+    { 
+	StringBuffer listString = new StringBuffer();
+	
+	Iterator iterator = list.iterator();
+	while (iterator.hasNext()){
+	    String item = iterator.next().toString();
+	    
+	    if (listString.length() > 0) {
+		listString.append(" ");
+	    }
+	    
+	    listString.append(item);
+	}
+	return listString.toString();
+    }
+    
+    public boolean writeSQL(DocumentID docId, int parentRef, boolean parentIsStructure, 
+			    GS3SQLConnection connection)
+    { 
+	int sqlRef = -1;
+	
+	// set the "where" to find the reference for this division
+	GS3SQLSelect select = new GS3SQLSelect("divisions");
+	select.addField("DivisionRef");
+	GS3SQLWhereItem whereItem = new GS3SQLWhereItem("ParentRef", "=", Integer.toString(parentRef), GS3SQLField.INTEGER_TYPE);
+	GS3SQLWhereItem parentItem = new GS3SQLWhereItem("ParentType", "=", parentIsStructure ? METSStructure.STRUCTURE_TYPE : METSDivision.DIVISION_TYPE);
+	GS3SQLWhereItem item = new GS3SQLWhereItem("SectionID", "=", this.ID.toString());
+	GS3SQLWhere where = new GS3SQLWhere(whereItem);
+	where.add(parentItem);
+	where.add(item);
+	select.setWhere(where);
+	
+	Statement statement = null;
+	ResultSet resultSet = null;
+	
+	// Do the actual writing
+	GS3SQLAction action;
+	
+	try {
+	    statement = connection.createStatement();
+	    resultSet = statement.executeQuery(select.toString());
+	    if (!resultSet.first()) {
+		
+		GS3SQLInsert insert = new GS3SQLInsert("divisions");
+		insert.addValue("DocID", docId.toString());
+		insert.addValue("SectionID", this.ID.toString());
+		insert.addValue("ParentRef", Integer.toString(parentRef));
+		insert.addValue("ParentType", parentIsStructure == true ? METSStructure.STRUCTURE_TYPE : METSDivision.DIVISION_TYPE);
+		
+		action = insert;
+	    }
+	    else {
+		sqlRef = resultSet.getInt("DivisionRef");
+		
+		GS3SQLUpdate update = new GS3SQLUpdate("divisions");
+		GS3SQLWhere  updateWhere = 
+		    new GS3SQLWhere(new GS3SQLWhereItem("DivisionRef", "=", Integer.toString(sqlRef), GS3SQLField.INTEGER_TYPE));
+		update.setWhere(updateWhere);
+		action = update;
+	    }
+	}
+	catch (SQLException sql) {
+	    System.err.println(sql + " " + select.toString());
+	    return false;
+	}
+	
+	action.addValue("DivisionType", this.type.toString());
+	action.addValue("LabelOrder", this.order);
+	action.addValue("ShortLabel", this.orderLabel);
+	action.addValue("UserLabel", this.userLabel);
+	
+	try {
+	    statement.execute(action.toString());
+	} catch (SQLException e) {
+	    System.err.println("METSDivision.writeSQL(): "+e);
+	    return false;
+	}
+	
+	// if doing a fresh item, get the new structure reference...
+	if (sqlRef == -1){
+	    // get the new structure reference
+	    try {
+		// read in the structure reference
+		resultSet = statement.executeQuery(select.toString());
+		if (resultSet.first()) {
+		    sqlRef = resultSet.getInt("DivisionRef");
+		}
+	    }
+	    catch (SQLException sqlex) {
+		System.err.println("METSDIVISION.writeSQL(): Unable to retrieve reference for Division " + sqlex);
+		return false;
+	    }
+	}
+	
+	// delete the old file/metadata references
+	try {
+	    GS3SQLWhere referenceWhere = 
+		new GS3SQLWhere(new GS3SQLWhereItem("DivisionRef", "=", Integer.toString(sqlRef), 
+						    GS3SQLField.INTEGER_TYPE));
+	    
+	    GS3SQLDelete delete = new GS3SQLDelete("divisionfilerefs");
+	    delete.setWhere(referenceWhere);
+	    
+	    statement.execute(delete.toString());
+	    
+	    delete = new GS3SQLDelete("divisionmetarefs");
+	    delete.setWhere(referenceWhere);
+	    statement.execute(delete.toString());
+	
+	    // write the new file references
+	    if (this.fileRefs.size() > 0){
+		Iterator iterator = this.fileRefs.iterator();
+		
+		while (iterator.hasNext()) {
+		    GS3SQLInsert fileinsert = new GS3SQLInsert("divisionfilerefs");
+		    fileinsert.addValue("DocID", docId.toString());
+		    fileinsert.addValue("DivisionRef", Integer.toString(sqlRef), GS3SQLField.INTEGER_TYPE);
+		    fileinsert.addValue("DivisionType", "Group");
+		    fileinsert.addValue("FileID", iterator.next().toString());
+		    statement.execute(fileinsert.toString());
+		}
+	    }
+	    
+	    // write the metadata references
+	    if (this.metadataRefs.size() > 0){
+		Iterator iterator = this.metadataRefs.iterator();
+		
+		while (iterator.hasNext()) {
+		    GS3SQLInsert metainsert = new GS3SQLInsert("divisionmetarefs");
+		    metainsert.addValue("DocID", docId.toString());
+		    metainsert.addValue("DivisionRef", Integer.toString(sqlRef), GS3SQLField.INTEGER_TYPE);
+		    metainsert.addValue("DivisionType", "Group");
+		    metainsert.addValue("MetaID", iterator.next().toString());
+		    statement.execute(metainsert.toString());
+		}
+	    }
+	    statement.close();
+	} catch (SQLException e) {
+	    System.err.println("METSDIVISION.writeSQL(): "+e);
+	    return false;
+	}
+	// write out any children in turn
+	Iterator groups = this.children.values().iterator();
+	
+	while (groups.hasNext()){
+	    METSDivision group = (METSDivision) groups.next();
+	    
+	    if (!group.writeSQL(docId, sqlRef, false, connection)) {
+		return false;
+	    }
+	}
+	return true;
+    }
+    
+    public static METSDivision readSQL(GS3SQLConnection connection, ResultSet resultSet)
+    {
+	METSLocation metsLocation = null;
+	
+	GS3SQLSelect select = null;
+	try {
+	    // read the basic information
+	    String ID   = resultSet.getString("SectionID");
+	    String type = resultSet.getString("DivisionType");
+	    String order = resultSet.getString("LabelOrder"); 
+	    String orderLabel = resultSet.getString("ShortLabel");
+	    String userLabel  = resultSet.getString("UserLabel");
+      
+	    // construct the division object
+	    METSDivision division = new METSDivision(ID, order, orderLabel, userLabel, type);
+      
+	    // obtain a list of child divisions
+	    int divisionRef = resultSet.getInt("DivisionRef");
+
+	    select = new GS3SQLSelect("divisions");
+	    select.addField("*");
+	    GS3SQLWhereItem whereItem = new GS3SQLWhereItem("ParentRef", "=", Integer.toString(divisionRef),
+							    GS3SQLField.INTEGER_TYPE);
+	    GS3SQLWhere where = new GS3SQLWhere(whereItem);
+	    whereItem = new GS3SQLWhereItem("ParentType", "=", METSDivision.DIVISION_TYPE);
+	    where.add(whereItem);
+	    select.setWhere(where);
+
+	    Statement statement = connection.createStatement();
+	    ResultSet childSet = statement.executeQuery(select.toString());
+      
+	    // circulate through to obtain further children
+	    if (childSet.first())
+		{
+		    do {
+			METSDivision childDivision = METSDivision.readSQL(connection, childSet);
+			division.addDivision(childDivision);
+		    }
+		    while (childSet.next());
+		}
+	    select = new GS3SQLSelect("divisionfilerefs");
+	    select.addField("*");
+	    where = new GS3SQLWhere(new GS3SQLWhereItem("DivisionRef", "=", Integer.toString(divisionRef), 
+							GS3SQLField.INTEGER_TYPE));
+	    select.setWhere(where);
+
+	    ResultSet fileSet = statement.executeQuery(select.toString());
+
+	    if (fileSet.first()){
+		do {
+		    String reference = fileSet.getString("FileID");
+		    division.fileRefs.add(reference);
+		}
+		while (fileSet.next());  
+	    }
+	    
+	    select = new GS3SQLSelect("divisionmetarefs");
+	    select.addField("*");
+	    where = new GS3SQLWhere(new GS3SQLWhereItem("DivisionRef", "=", Integer.toString(divisionRef), 
+							GS3SQLField.INTEGER_TYPE));
+	    select.setWhere(where);
+
+	    ResultSet metaSet = statement.executeQuery(select.toString());
+
+	    if (metaSet.first()){
+		do {
+		    String reference = metaSet.getString("MetaID");
+		    division.metadataRefs.add(reference);
+		}
+		while (metaSet.next());  
+	    }
+        
+	    statement.close();
+	    return division;
+	}
+	catch (SQLException sqlEx){
+	    System.out.println(sqlEx + " " +select.toString());
+	}    
+	return null;
+    }
+}
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSDocument.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSDocument.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSDocument.java	(revision 13666)
@@ -0,0 +1,75 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+/**
+ *  A METS document representation - the METS objects are represented
+ *  by hand-coded classes rather than JAXB products due to the fact
+ *  that we want wrappers to provide higher-level abstractions than
+ *  the basic METS XML mark-up.
+ */
+
+import java.util.Map;
+import java.util.HashMap;
+
+import java.io.File;
+import java.net.URL;
+
+public class METSDocument
+{
+	// TODO: add use of 'ID'
+	String objectID;
+	String label;
+	String type;
+	// TODO: add use of 'PROFILE';
+
+	METSHeader      header;
+	METSDescriptiveSet descriptiveSet;
+	METSAdmin       admin;
+	METSFileSet     fileSet;
+
+	public METSDocument(String identifier)
+	{
+		this.objectID = identifier; // In Greenstone land, this should be a unique identifier within
+		                            // the current collection
+		this.type = "document"; // Types in METS are just strings - we currently use
+		                        // 'Document' as a standard representation.
+                            // Individual options should be defined in a published
+														// METS Profile - in Greenstone we currently 'cheat'
+														// and bodge the system
+		this.header      = new METSHeader();
+		this.descriptiveSet = new METSDescriptiveSet();
+		this.fileSet     = new METSFileSet();
+	}
+
+	/**
+	 *  Set the document identifier for this document
+	 *
+	 *  @param <code>String</code> the identifier
+	 */
+	public void setDocId(String id)
+	{	this.objectID = id;
+	}
+
+	public String getDocId()
+	{	return this.objectID;
+	}
+
+	public METSHeader getHeader()
+	{	return this.header;
+	}	
+
+	public void setHeader(METSHeader header)
+	{	this.header = header;
+	}
+
+	public void addFile(METSFile file)
+	{	this.fileSet.addFile(file);
+	}
+
+	public void addFile(URL url)
+	{	this.fileSet.addFile(url);
+	}
+
+	public void addFile(METSFile file, String toGroup)
+	{	this.fileSet.addFile(file, toGroup);
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFile.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFile.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFile.java	(revision 13666)
@@ -0,0 +1,352 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+import java.io.PrintWriter;
+
+import java.util.List;
+import java.util.ArrayList;
+
+import java.net.URL;
+import java.net.URLConnection;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+import org.greenstone.gsdl3.gs3build.util.HTTPTools;
+import org.greenstone.gsdl3.gs3build.util.XMLTools;
+import org.greenstone.gsdl3.gs3build.database.*;
+
+/**
+ *  An individual METS component file for a document.  Many features of METS are not
+ *  currently fully supported/used here, but member variables exist for all of the
+ *  standard members.
+ */
+
+public class METSFile
+{
+    METSFileID    id;
+    METSFilePos   location;
+    String        MIMEType;
+    int           sequenceNo;
+    long          size;
+    METSDate      created;
+    long          checkSum;
+    List          adminRefs;
+    List          describeRefs;
+    METSFileGroup group;
+    
+    /**
+     *  Create a new METSFile object, with the given properties.  The remaining
+     *  fields are filled in with default values.
+     *
+     *  @param <code>String</code> the id of the file
+     *  @param <code>METSFilePos</code> the location of the file
+     *  @param <code>String</code> the MIME type of the file
+     */
+    public METSFile(METSFileID id,  METSFilePos location, String mimeType)
+    {
+	this.id           = id;        // required
+	this.location     = location;  // the location
+	this.MIMEType     = mimeType;  // the MIME type;
+	this.sequenceNo   = -1;       // -1 indicates unset
+	this.size         = -1;        // -1 indicates unset
+	this.checkSum     = -1;        // -1 indicates unset
+	this.created      = null;
+	this.adminRefs    = new ArrayList();
+	this.describeRefs = new ArrayList();
+	this.group        = null;
+    }
+    
+    public boolean equals(URL url)
+    { 
+	return this.location.equals(url);
+    }
+    
+    /**
+     *  Set the parent group
+     *
+     *  @param <code>METSFileGroup</code> the new holding file group
+     */
+    public void setGroup(METSFileGroup group)
+    { 
+	this.group = group;
+    }
+    
+    /**
+     *  Get the parent group of this file
+     *
+     *  @return <code>METSFileGroup</code> the holding file group
+     */
+    public METSFileGroup getGroup()
+    { 
+	return this.group;
+    }
+    
+    /**
+     *  Get the identifier of this file
+     *
+     *  @return <code>METSFileID</code> the file identifier
+     */
+    public METSFileID getID()
+    { 
+	return this.id;
+    }
+    
+    /**
+     *  Set the identifier of this file
+     *
+     *  @param <code>METSFileID</code> the file identifier
+     */
+    public void setID(METSFileID id)
+    { 
+	this.id = id;
+    }
+    
+    /**
+     *  @return <code>String</code> the MIME (content) type of the file
+     */
+    public String getMIMEType()
+    { 
+	return this.MIMEType;
+    }
+    
+    /**
+     *  @return <code>URL</code> the location of the file.  This will often be in
+     *          "file://" form.
+     */
+    public URL getLocation()
+    { 
+	return this.location.getLocation();
+    }
+    
+    /**
+     *  Take a url and make a METSFile object out of it - works out
+     *  details such as the Mime type, identifiers and other necessary
+     *  information to call the constructor for METSFile
+     *
+     *  @param <code>URL</code> the url of the object - this may be a 
+     *                          reference to a file on the local filestore
+     *
+     *  @return <code>METSFile</code> the METS file object for the corresponding
+     *                                document component.
+     */
+    public static METSFile makeMETSFile(URL url, String mimeType)
+    {	
+	METSFile reply = new METSFile(new METSFileID(), new METSFilePos(url), mimeType);
+	return reply;
+    }
+    
+    public static METSFile makeMETSFile(URL url)
+    { 
+	String mimeType;
+	
+	if (url.getProtocol().equals("file")){
+	    // TODO: Work out the MIME type
+	    mimeType = URLConnection.getFileNameMap().getContentTypeFor(url.toString().substring(7));
+	    if (mimeType == null) {
+		mimeType = "text/plain";
+	    }
+	} else { 
+	    // TODO: look up the MIME type through the pertinent connection
+	    mimeType = HTTPTools.getMIMEType(url);
+	}
+	// TODO: make the identifier...
+	
+	return makeMETSFile(url, mimeType);
+    }
+    
+    /**
+     *  Write the METS file in an XML to a text-output sink
+     *
+     *  @param <code>PrintWriter</code> the destination of the output
+     */
+    public void write(PrintWriter writer)
+    { 
+	String tag = XMLTools.getOpenTag("mets", "file");
+	tag = XMLTools.addAttribute(tag, "MIMETYPE", this.MIMEType);
+	tag = XMLTools.addAttribute(tag, "ID", this.id.toString());
+	writer.print("      ");   //indentation
+	writer.println(tag);
+	
+	tag = XMLTools.getOpenTag("mets", "FLocat");
+	tag = XMLTools.addAttribute(tag, "LOCTYPE", this.location.getType());
+	tag = XMLTools.addAttribute(tag, "xlink:href", this.location.getLocation().toString());
+	
+	tag = XMLTools.makeSingleton(tag);
+	writer.print("         ");  //indentation
+	writer.println(tag);
+	
+	writer.print("      ");   //indentation
+	writer.println(XMLTools.getCloseTag("mets", "file"));
+    }
+    
+    
+    public boolean writeSQL(int groupReference, GS3SQLConnection connection)
+    { 
+	// check if this file is in the table already...
+	GS3SQLAction action;
+	
+	GS3SQLSelect select = new GS3SQLSelect("files");
+	select.addField("*");
+	GS3SQLWhereItem whereItem = new GS3SQLWhereItem("FileGroupRef", "=", Integer.toString(groupReference),
+							GS3SQLField.INTEGER_TYPE);
+	GS3SQLWhere  where  = new GS3SQLWhere(whereItem);
+	whereItem = new GS3SQLWhereItem("FileID","=", this.id.toString());
+	where.add(whereItem);
+	select.setWhere(where);
+
+	Statement statement = null;
+	
+	// if not, then make an insert action
+	try {
+	    statement = connection.createStatement();
+	    ResultSet results = statement.executeQuery(select.toString());
+	    if (!results.first()){
+		GS3SQLInsert insert = new GS3SQLInsert("files");
+		
+		insert.addValue("FileGroupRef", Integer.toString(groupReference), GS3SQLField.INTEGER_TYPE);
+		insert.addValue("FileID", this.id.toString());
+		
+		action = insert;
+	    }
+	    else {
+		GS3SQLUpdate update = new GS3SQLUpdate("files");
+		
+		update.setWhere(where);
+		action = update;
+	    }
+	}
+	catch (SQLException ex){
+	    System.err.println("METSFile.writeSQL(): "+ex);
+	    return false;
+	}
+	action.addValue("FileLocType", this.location.getType());
+	action.addValue("FileLocation", this.location.getLocation().toString());
+	action.addValue("MIMEType", this.MIMEType);
+	
+	try {
+	    statement.execute(action.toString());
+	    statement.close();
+	    
+	} catch (SQLException e) {
+	    System.err.println("METSFile.writeSQL():"+e);
+	    return false;
+	}
+	return true;
+    }
+    
+    public static METSFile readSQL(GS3SQLConnection connection, ResultSet parentSet)
+    { 
+	try {
+	    String locType = parentSet.getString("FileLocType");
+	    String location = parentSet.getString("FileLocation");
+	    String mimeType = parentSet.getString("MIMEType");
+	    String id = parentSet.getString("FileID");
+	
+	    METSFileID metsID = new METSFileID(id);
+	    METSFilePos metsFilePos = new METSFilePos(locType, location);
+	    
+	    METSFile reply = new METSFile(metsID, metsFilePos, mimeType);
+	    return reply;
+	}
+	catch (SQLException ex){
+	    System.out.println("METSFile.readSQL(): "+ex);
+	}
+	catch (java.net.MalformedURLException urlEx){
+	    System.out.println("METSFile.readSQL(): "+urlEx);
+	}
+	return null;
+    }
+    
+    public static METSFile parse_file(Element element, METSFileGroup group, String parseFilePath)
+    {
+	NodeList children = element.getChildNodes();
+
+	METSFile thisFile = null;
+	
+	for (int c = 0; c < children.getLength(); c++){
+	    if (children.item(c).getNodeType() != org.w3c.dom.Node.ELEMENT_NODE){
+		continue;
+	    }  
+	    Element child = (Element) children.item(c);
+	    String childName = child.getNodeName();
+	    
+	    if (childName.equals("mets:file")){
+		METSFile.parse_file(child, group, parseFilePath);
+	    } else if (childName.equals("mets:FLocat")) {
+		String mimeType = element.getAttribute("MIMETYPE");
+		String fileId = element.getAttribute("ID");   
+		
+		METSFilePos thisFilePos = METSFile.parse_flocateXML(child, parseFilePath, fileId);
+	   	thisFile = new METSFile(new METSFileID(fileId), thisFilePos, mimeType);    
+		group.addFile(thisFile);
+	    } else {
+		System.err.println("Warning: unrecognised tag " +childName);
+	    }
+	}
+	return thisFile;
+    }
+    
+    public static METSFilePos parse_flocateXML(Element element, String parseFilePath, String fileId)
+    {
+	METSFilePos thisFilePos = null;
+	
+	// get most of the information from the child FLocat node
+	String locationType = element.getAttribute("LOCTYPE");
+	String href = element.getAttribute("xlink:href");
+	//String fileId = element.getAttribute("ID");
+	try {
+	    thisFilePos = new METSFilePos(locationType, href);
+	    
+	    if (fileId.startsWith("default.")) {
+		//retrieve the string after ..import/
+		int importPosition = href.indexOf("import/")+7;
+		href.substring(importPosition);
+		if (fileId.equals("default.1")) {
+		    href = "file:" + parseFilePath+ "doctxt.xml";
+		} else {
+		    href = "file:" + parseFilePath + href.substring(importPosition);
+		}
+	    }
+            thisFilePos = new METSFilePos(locationType, href);
+	} catch (java.net.MalformedURLException ex) {
+	    // TODO: raise error
+	    System.err.println("METSFile.parse_flocateXML(): "+ex);
+	}
+	return thisFilePos;
+    }
+    
+    
+    /**
+     *  Get the location of this file as a URL
+     */
+    public URL getURL()
+    { 
+	return this.location.getLocation();
+    }
+    
+    /**
+     *  Get modified file date
+     */
+    public long getModifiedDatestamp()
+    { 
+	return this.location.getModifiedDatestamp();
+    }
+    
+    /**
+     *  Overridden <code>toString</code> for convenience - returns the location of the file.
+     *
+     *  @return <code>String</code> the location of the file as a string
+     */
+    public String toString()
+    {
+	return this.location.toString();
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFileGroup.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFileGroup.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFileGroup.java	(revision 13666)
@@ -0,0 +1,408 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import java.net.URL;
+
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.ResultSet;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+
+import java.io.PrintWriter;
+
+import org.greenstone.gsdl3.gs3build.util.XMLTools;
+import org.greenstone.gsdl3.gs3build.database.*;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+
+/**
+ *  Child groups are indicated by colons.  E.g. Chapter1:Section1 would indicate
+ *  the group "Section1" inside the "Chapter1" group...
+ */
+
+public class METSFileGroup
+{ 
+    List   children;
+    List   childGroups;
+    String id;
+    
+    public static final String SECTION_PARENT = "Section";
+    public static final String GROUP_PARENT = "Group";
+    
+    public METSFileGroup(String id)
+    { 
+	this.children = new ArrayList();
+	this.childGroups = new ArrayList();
+	this.id = id;
+    }
+    
+    /**
+     *  Get the modified datestamp that applies for this file group.  An empty group
+     *  will return <code>0</code>.
+     *
+     *  @return <code>long</code> the date modified as milliseconds from the 1st January 1970
+     */
+    public long getModifiedDatestamp()
+    { 
+	long reply = 0; // empty groups reply '0'
+	
+	Iterator childIter = children.iterator();
+	while (childIter.hasNext()){
+	    METSFile file = (METSFile) childIter.next();
+	    long fileStamp = file.getModifiedDatestamp();
+	    if (fileStamp > reply) {
+		reply = fileStamp;
+	    }
+	}
+	
+	childIter = childGroups.iterator();
+	while (childIter.hasNext()){
+	    METSFileGroup fileGroup = (METSFileGroup) childIter.next();
+	    long fileStamp = fileGroup.getModifiedDatestamp();
+	    if (fileStamp > reply) {
+		reply = fileStamp;
+	    }
+	}
+	
+	return reply;
+    }
+    
+    /**
+     *  Find all the occurrences of a given file, and place them
+     *  in a <code>List</code>.
+     */
+    public void findGroups(URL findFile, List resultList)
+    { 
+	// find in this particular group
+	Iterator childIter = children.iterator();
+	while (childIter.hasNext()){
+	    METSFile file = (METSFile) childIter.next();
+	    if (file.equals(findFile))
+		{ resultList.add(this.id);
+		}
+	}
+	
+	// iterate over the child groups
+	childIter = childGroups.iterator();
+	while (childIter.hasNext()){
+	    METSFileGroup fileGroup = (METSFileGroup) childIter.next();
+	    
+	    fileGroup.findGroups(findFile, resultList);
+	}
+    }
+    
+    /**
+     *  Get a sub group of this METSFileGroup.
+     *
+     *  @param <code>String</code> the name of the subgroup
+     *  @return <code>METSFileGroup</code> the child group, which will
+     *          be <code>null</code> if the group is not known.
+     */
+    public METSFileGroup getSubgroup(String id)
+    { 
+	String childId;
+	
+	int dotAt = id.indexOf(':');
+	if (dotAt == -1){
+	    childId = null;
+	}
+	else{ 
+	    childId = id.substring(dotAt+1);
+	    id = id.substring(0, dotAt);
+	}
+	
+	// iterate over the child groups
+	Iterator childIter = childGroups.iterator();
+	while (childIter.hasNext()){
+	    METSFileGroup group = (METSFileGroup) childIter.next();
+	    
+	    if (group.id.equals(id)) {
+		if (childId == null) {
+		    return group;
+		}
+		else {
+		    return group.getSubgroup(childId);
+		}
+	    }
+	}
+	return null;
+    }
+    
+    /**
+     *  Add a filegroup to this group of files.
+     *
+     *	@param <code>METSFileGroup</code> the filegroup.
+     */
+    public void addGroup(METSFileGroup group)
+    { 
+	this.childGroups.add(group);
+    }
+    
+    /**
+     *  Add a file to this group of files.
+     *
+     *	@param <code>METSFile</code> the file in a METS File object.
+     */
+    public void addFile(METSFile file)
+    { 
+	this.children.add(file);
+	file.setGroup(this);
+	if (!file.getID().isDefined()){
+	    file.setID(new METSFileID(this.id + "." + Integer.toString(this.children.size())));
+	}
+    }
+    
+    /**
+     *  Get the nth child of the group
+     *
+     *  @param <code>int</code> the index into the group
+     *  @return <code>METSFile</code> the corresponding child.  This may be <code>null</code>
+     *          particularly if the index given falls outside of the valid range of child
+     *          indexes.
+     */
+    public METSFile getFile(int index)
+    { 
+	if (index < 0 || index >= this.children.size()){
+	    return null;
+	}
+	
+	return (METSFile) this.children.get(index);
+    }
+    
+    /**
+     *  Get all the files in the group as a <code>List</code>
+     *
+     *  @return <code>List</code> the file childen of the group.
+     */
+    public List getFiles()
+    { 
+	return this.children;
+    }
+    
+    /**
+     *  Get all the subgroups as a <code>List</code>
+     */
+    public List getSubgroups()
+    { 
+	return this.childGroups;
+    }
+    
+    /**
+     *  Get the number of files in the group
+     *
+     *  @return <code>int</code> the count
+     */
+    public int noOfFiles()
+    { 
+	return this.children.size();
+    }
+    
+    /**
+     *  Get the number of subgroups.
+     */
+    public int noOfSubgroups()
+    { 
+	return this.childGroups.size();
+    }
+    
+    /**
+     *  @return <code>String</code> the name of this group
+     */
+    public String getId()
+    { 
+	return this.id;
+    }
+    
+    public static METSFileGroup parse_groupXML(Element element, METSFileSet set, String parseFilePath, METSFileGroup group)
+    {
+ 	//deal with mets:fileGrp
+ 	NodeList children = element.getChildNodes();
+ 	
+ 	for (int c = 0; c < children.getLength(); c++) {
+ 	    if (children.item(c).getNodeType() != org.w3c.dom.Node.ELEMENT_NODE){
+ 		continue;
+ 	    }
+ 	    Element child = (Element) children.item(c);
+ 	    String childName = child.getNodeName();
+	    
+ 	    if (childName.equals("mets:fileGrp")) {
+ 		String groupId = child.getAttribute("ID");
+ 		METSFileGroup childGroup = new METSFileGroup(groupId);
+		
+ 		if (group != null){
+ 		    group.addGroup(childGroup);
+ 		} else {
+ 		    set.addGroup(childGroup);
+ 		}
+ 		METSFile file = METSFile.parse_file(child, childGroup, parseFilePath);
+ 	    }
+ 	}
+ 	return group;
+    }
+
+    /**
+     *  Write the object in an XML METS format.
+     *
+     *  @param <code>PrintWriter</code> the printwriter being used to write the object
+     */
+    public void write(PrintWriter writer)
+    { 
+	String tag = XMLTools.getOpenTag("mets","fileGrp");
+	tag = XMLTools.addAttribute(tag, "ID", this.id);
+	writer.print("   ");   //indentation
+	writer.println(tag);
+	
+	Iterator childIter = children.iterator();
+	while (childIter.hasNext()){
+	    METSFile file = (METSFile) childIter.next();
+	    file.write(writer);
+	}
+	writer.print("   ");   //indentation
+	writer.println(XMLTools.getCloseTag("mets","fileGrp"));
+    }
+    
+    public boolean writeSQL(DocumentInterface document, String parentRef, boolean parentIsSection, 
+			    GS3SQLConnection connection)
+    { 
+	int sqlId = -1;
+	// check if this node is in the database already
+	GS3SQLSelect select = new GS3SQLSelect("filegroups");
+	select.addField("*");
+	GS3SQLWhereItem whereItem = new GS3SQLWhereItem("FileGroupID", "=", this.id);
+	GS3SQLWhereItem whereDoc  = new GS3SQLWhereItem("DocID", "=", document.getID().toString());
+	GS3SQLWhere where = new GS3SQLWhere(whereItem);
+	where.add(whereDoc);
+	select.setWhere(where);
+	
+	ResultSet results = null;
+	Statement statement = null;
+	
+	try {
+	    statement = connection.createStatement();
+	    results = statement.executeQuery(select.toString());
+	    if (!results.first()) {
+		GS3SQLInsert insert = new GS3SQLInsert("filegroups");
+		
+		insert.addValue("DocID", document.getID().toString());
+		insert.addValue("FileGroupID", this.id);
+		insert.addValue("ParentRef", parentRef, GS3SQLField.INTEGER_TYPE);
+		insert.addValue("ParentType", parentIsSection ? SECTION_PARENT : GROUP_PARENT);
+		
+		statement.execute(insert.toString());
+	    }
+	    else {
+		// TODO: update the data for this file group...
+	    }
+	}
+	catch (SQLException ex){
+	    System.err.println("METSFileGroup.writeSQL(): "+ex);
+	    return false;
+	}
+	
+	// get the filegroup reference now
+	try {
+	    results = statement.executeQuery(select.toString());
+	    if (results.first()) {
+		sqlId = results.getInt("FileGroupRef");
+	    } else {
+		statement.close();
+		return false;
+	    }
+	    statement.close();
+	} catch (SQLException sqlex) {
+	    System.err.println("METSFileGroup.writeSQL(): "+sqlex);
+	    return false;
+	}
+	// iterate over the child groups
+	Iterator childIter = childGroups.iterator();
+	while (childIter.hasNext()){
+	    METSFileGroup fileGroup = (METSFileGroup) childIter.next();
+	    
+	    if (!fileGroup.writeSQL(document, Integer.toString(sqlId), false, connection)){
+		System.err.println("METSFileGroup.writeSQL(): Couldn't write FileGroup");
+		return false;
+	    }
+	}
+	
+	// iterate over the child files
+	childIter = children.iterator();
+	while (childIter.hasNext()){
+	    METSFile file = (METSFile) childIter.next();	    
+	    if (!file.writeSQL(sqlId, connection)){
+		System.err.println("METSFileGroup.writeSQL(): Couldn't write File");
+		return false;
+	    }
+	}
+	
+	return true;
+    }
+    
+    public static METSFileGroup readSQL(DocumentInterface document, GS3SQLConnection connection,
+					ResultSet resultSet)
+    {
+	try {
+	    String ID         = resultSet.getString("FileGroupID");
+	    String parentType = resultSet.getString("ParentType");
+	    String parentRef  = resultSet.getString("ParentRef");
+	    
+	    // create the metadata block object
+	    METSFileGroup group = new METSFileGroup(ID);
+	    
+	    // get its metadata reference to retrieve divisions
+	    int groupRef = resultSet.getInt("FileGroupRef");
+	    
+	    // query the database for matching groups which are children of this one
+	    GS3SQLSelect select = new GS3SQLSelect("filegroups");
+	    select.addField("*");
+	    GS3SQLWhereItem whereItem = new GS3SQLWhereItem("ParentRef", "=", Integer.toString(groupRef),
+							    GS3SQLField.INTEGER_TYPE);
+	    GS3SQLWhere where = new GS3SQLWhere(whereItem);
+	    whereItem = new GS3SQLWhereItem("ParentType", "=", METSFileGroup.GROUP_PARENT);
+	    where.add(whereItem);
+	    select.setWhere(where);
+	    
+	    Statement statement = connection.createStatement();
+	    
+	    // parse through the child groups
+	    ResultSet childSet = statement.executeQuery(select.toString());
+	    if (childSet.first()) {
+		do {
+		    METSFileGroup fileGroup = METSFileGroup.readSQL(document, connection, childSet);
+		    if (fileGroup != null) {
+			group.addGroup(fileGroup);
+		    }
+		}
+		while (childSet.next());
+	    }
+	    // now scan for file members
+	    select = new GS3SQLSelect("files");
+	    select.addField("*");
+	    whereItem = new GS3SQLWhereItem("FileGroupRef", "=", Integer.toString(groupRef), GS3SQLField.INTEGER_TYPE);
+	    where = new GS3SQLWhere(whereItem);
+	    select.setWhere(where);
+	    ResultSet childFileSet = statement.executeQuery(select.toString());
+	    if (childFileSet.first()) {
+		do {
+		    METSFile file = METSFile.readSQL(connection, childFileSet);
+		    if (file != null) {
+			group.addFile(file);
+		    }
+		}
+		while (childFileSet.next());
+	    }
+	    statement.close();
+	    return group;
+	}
+	catch (SQLException sqlEx){
+	    System.err.println("METSFileGroup.readSQL(): "+sqlEx);
+	    System.exit(1);
+	}
+	return null;
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFileID.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFileID.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFileID.java	(revision 13666)
@@ -0,0 +1,30 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+/**
+ *  A type-safe wrapper for METS File identifiers.
+ */
+
+public class METSFileID
+{	
+    String id;
+    
+    public METSFileID()
+    {	
+	this.id = null;
+    }
+    
+    public METSFileID(String id)
+    {	
+	this.id = id;
+    }
+    
+    public String toString()
+    {	
+	return this.id;
+    }
+    
+    public boolean isDefined()
+    {	
+	return this.id != null;
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFilePointer.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFilePointer.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFilePointer.java	(revision 13666)
@@ -0,0 +1,27 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ *  Notes: Greenstone doesn't currently use/support the SEQ or AREA 
+ *  file pointer types hence, one can use only a simple file reference
+ */
+
+public class METSFilePointer
+{
+	public static final String SIMPLE = "";
+	public static final String SEQUENCE = "seq";
+	public static final String AREA = "area";
+
+	String type;
+	String ID;
+	String fileId;
+	List   children;
+
+	public METSFilePointer(String ID, String fileId)
+	{	this.ID = ID;
+		this.fileId = fileId;
+		this.type = METSFilePointer.SIMPLE;
+	}	
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFilePos.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFilePos.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFilePos.java	(revision 13666)
@@ -0,0 +1,41 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+import java.io.File;
+import java.net.URL;
+
+public class METSFilePos
+{
+  METSLocation location;
+
+  public METSFilePos(File file) throws java.net.MalformedURLException
+  { this.location = new METSLocation(file);
+  }
+
+  public METSFilePos(URL url)
+  { this.location = new METSLocation(url);
+  }
+
+  public METSFilePos(String locationType, String location) throws java.net.MalformedURLException
+  { this.location = new METSLocation(locationType, location);
+  }
+  
+  public URL getLocation()
+  { return this.location.getLocation();
+  }
+
+  public String getType()
+  { return this.location.getType();
+  }
+
+  public long getModifiedDatestamp()
+  { return this.location.getModifiedDatestamp();
+  }
+
+  public String toString()
+  { return this.location.getLocation().toString();
+  }
+
+  public boolean equals(URL filePos)
+  { return this.location.equals(filePos);
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFileRef.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFileRef.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFileRef.java	(revision 13666)
@@ -0,0 +1,13 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+public class METSFileRef
+{	String label;
+
+	public METSFileRef(String label)
+	{	this.label = label;
+	}
+
+	public String toString()
+	{	return this.label;
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFileSet.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFileSet.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSFileSet.java	(revision 13666)
@@ -0,0 +1,344 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+/**
+ *  A class to hold all the alternative file structures
+ *  for a particular METS Document
+ */
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import java.io.File;
+import java.io.PrintWriter;
+
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.ResultSet;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+
+import java.net.URL;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+
+import org.greenstone.gsdl3.gs3build.database.*;
+
+public class METSFileSet
+{ 
+    Map    fileGroups;
+    String reference;
+    FileIdentifierFactory identifierFactory;
+    FileGroupIdentifierFactory groupIdentifierFactory;
+    
+    class FileGroupIdentifierFactory extends AbstractIdentifierFactory
+    {
+	public static final String FILEGROUP_PRELUDE = "FG";
+	
+	public FileGroupIdentifierFactory()
+	{
+	    super("FILEGROUP_PRELUDE");
+	}
+    }
+    
+    public METSFileSet()
+    { 
+	this.fileGroups = new HashMap();
+	this.fileGroups.put("default", new METSFileGroup("default"));
+	this.reference = null;
+	this.identifierFactory = new FileIdentifierFactory();
+	this.groupIdentifierFactory = new FileGroupIdentifierFactory();
+    }
+    
+    public long getModifiedDatestamp()
+    { 
+	long reply = 0;
+	
+	Iterator groupsIter = this.fileGroups.values().iterator();
+	while (groupsIter.hasNext()) {
+		METSFileGroup group = (METSFileGroup) groupsIter.next();
+		long groupStamp = group.getModifiedDatestamp();
+		if (groupStamp > reply){
+		    reply = groupStamp;
+		}
+	    }
+	return reply;
+    }
+    
+    
+    /**
+     *  Get a new FileGroup to lie within this fileset.  The group is not initialised with
+     *  a parent, etc. - all that is done is the allocation of a unique group identifier.
+     *
+     *  @return <code>METSFileGroup</code> the new group.
+     */
+    public METSFileGroup createGroup()
+    { 
+	METSFileGroup group = new METSFileGroup(this.groupIdentifierFactory.getNextIdentifier());
+	return group;
+    }
+    
+    public METSFile createFile(METSFilePos filePos, String type)
+    { 
+	METSFile file = new METSFile(new METSFileID(this.identifierFactory.getNextIdentifier()), filePos, type);
+	return file;
+    }
+    
+    /**
+     *  Get the group that corresponds to the given name...
+     *
+     *  @param <code>String</code> the name of the group.
+     *  @return <code>METSFileGroup</code> the group object - this will be
+     *          <code>null</code> if the group is not found
+     */
+    public METSFileGroup getGroup(String name)
+    { 
+	if (!this.fileGroups.containsKey(name)){
+	    return null;
+	}
+	return (METSFileGroup) this.fileGroups.get(name);
+    }
+    
+    /**
+     *  Get the Nth file from the default group...
+     *
+     *  @param <code>int</code> the index into the default group to use...
+     *  @return <code>METSFile</code> the file.
+     */
+    public METSFile getFile(int index)
+    { 
+	METSFileGroup group = this.getGroup("default");
+
+	if (group == null) {
+	    return null;
+	}
+	return group.getFile(0);
+    }
+    
+    /**
+     *  Add a file to the default file group
+     */
+    public void addFile(METSFile file)
+    { 
+	METSFileGroup defaultGroup = (METSFileGroup) this.fileGroups.get("default");
+	defaultGroup.addFile(file);
+    }
+    
+    /**
+     *  Add a file to the default file group
+     *
+     *  @return <code>METSFile</code> an object that wraps the given url into
+     *          a METS file object
+     */
+    public METSFile addFile(URL url)
+    { 
+	METSFile file = METSFile.makeMETSFile(url);
+	this.addFile(file);
+	return file;
+    }
+    
+    public void addFile(METSFile file, String toGroup)
+    { 
+	METSFileGroup destGroup = (METSFileGroup) this.fileGroups.get(toGroup);
+	
+	if (destGroup == null){
+	    destGroup = new METSFileGroup(toGroup);
+	    this.fileGroups.put(destGroup.getId(), destGroup);
+	}
+	
+	destGroup.addFile(file);
+    }
+    
+    public void addFile(URL url, String toGroup)
+    { 
+	METSFile file = METSFile.makeMETSFile(url);
+	this.addFile(file, toGroup);
+    }
+    
+    /**
+     *  Add a group at the top level of the METS File set.
+     *
+     *  @param <code>METSFileGroup</code> the file group to add.
+     */
+    public void addGroup(METSFileGroup group)
+    { 
+	this.fileGroups.put(group.getId(), group);
+    }
+    
+    /**
+     *  Get all the groups that contain a given URL/file.
+     *
+     *  @param <code>URL</code> the location of the file.
+     *  @return <code>List</code> the list of group references that contain the file.
+     */
+    public List findGroups(URL file)
+    { 
+	List resultList = new ArrayList();
+	
+	Iterator groups = this.fileGroups.values().iterator();
+	
+	while (groups.hasNext()){
+	    METSFileGroup group = (METSFileGroup) groups.next();
+	    
+	    group.findGroups(file, resultList);
+	}
+	return resultList;
+    }
+    
+    /*
+     *
+     *
+     */
+    public static METSFileSet parseXML(NodeList fileSecs, METSFileSet fileSet, String parseFilePath) 
+    {
+ 	//METSFileSet set = new METSFileSet();> 
+ 	// this is in effect a group without a sense of 'self'...
+ 	for (int c = 0; c < fileSecs.getLength(); c++) {
+ 	    if (fileSecs.item(c).getNodeType() != org.w3c.dom.Node.ELEMENT_NODE){
+ 		continue;
+ 	    }
+	    
+ 	    METSFileGroup groups = METSFileGroup.parse_groupXML((Element)fileSecs.item(c), fileSet, parseFilePath, null);
+ 	}
+ 	return fileSet;
+    }
+    
+
+    public void write(PrintWriter writer)
+    { 
+	Iterator groups = this.fileGroups.values().iterator();
+	
+	writer.println("<mets:fileSec>");
+	while (groups.hasNext()){
+	    METSFileGroup group = (METSFileGroup) groups.next();
+	    
+	    group.write(writer);
+	}
+	writer.println("</mets:fileSec>");
+    }
+    
+    public boolean writeSQL(DocumentInterface document, GS3SQLConnection connection)
+    { 
+	Iterator groups = this.fileGroups.values().iterator();
+	
+	// write the set if the reference does not already exist...
+	if (this.reference == null){
+	    // Insert the file section into the database
+	    GS3SQLInsert insert = new GS3SQLInsert("filesection");
+	    insert.addValue("DocID", document.getID().toString());
+	    insert.addValue("FileSecID", "test"); // TODO: remove magic string
+	    
+	    Statement statement = null;
+	    try {
+		statement = connection.createStatement();
+		statement.execute(insert.toString());
+	    } catch (SQLException e) {
+		System.err.println("METSFileSet.writeSQL(): "+e);
+		return false;
+	    }
+	    
+	    // find the file section number
+	    GS3SQLSelect select = new GS3SQLSelect("filesection");
+	    select.addField("*");
+	    GS3SQLWhereItem whereItem = new GS3SQLWhereItem("FileSecID", "=", "test");
+	    GS3SQLWhereItem whereDoc  = new GS3SQLWhereItem("DocID", "=", document.getID().toString());
+	    GS3SQLWhere where = new GS3SQLWhere(whereItem);
+	    where.add(whereDoc);
+	    select.setWhere(where);
+	    
+	    try {
+		ResultSet set = statement.executeQuery(select.toString());
+		if (set.first()) {
+		    int sectionRef = set.getInt("FileSectionRef");
+		    
+		    this.reference = Integer.toString(sectionRef);
+		}
+		statement.close();
+	    }
+	    catch (SQLException ex){
+		System.out.println("METSFileSet.writeSQL(): "+ex);
+		return false;
+	    }
+	}
+	
+	if (this.reference == null) {
+	    return false;
+	}
+	// write out the children
+	while (groups.hasNext()){
+	    METSFileGroup group = (METSFileGroup) groups.next();
+	    
+	    if (!group.writeSQL(document, this.reference, true, connection)){
+		return false;
+	    }
+	}
+	
+	return true;
+    }
+    
+    public static METSFileSet readSQL(DocumentInterface document, GS3SQLConnection connection)
+    { 
+	METSFileSet set = new METSFileSet();    
+	
+	// Get file sections from the filesection table (currently redundant)
+	GS3SQLSelect select = new GS3SQLSelect("filesection");
+	select.addField("*");
+	GS3SQLWhereItem whereItem = new GS3SQLWhereItem("DocID", "=", document.getID().toString());
+	select.setWhere(new GS3SQLWhere(whereItem));
+
+	Statement statement = null;
+	
+	// Get the identifier for this file set, etc.
+	int fileSetRef = -1;
+	try {
+	    statement = connection.createStatement();
+	    ResultSet sections = statement.executeQuery(select.toString());
+	    if (sections.first()) {
+		fileSetRef = sections.getInt("FileSectionRef");
+		set.reference = Integer.toString(fileSetRef);
+	    } else {
+		statement.close();
+		return null;
+	    }
+	    
+	}
+	catch (SQLException ex){
+	    System.err.println("METSFileSet.readSQL() "+ex);
+	    return null;
+	}
+	// Get child file groups
+	select = new GS3SQLSelect("filegroups");
+	select.addField("*");
+	whereItem = new GS3SQLWhereItem("DocID", "=", document.getID().toString());    
+	GS3SQLWhere where = new GS3SQLWhere(whereItem);
+	whereItem = new GS3SQLWhereItem("ParentRef", "=", Integer.toString(fileSetRef), 
+					GS3SQLField.INTEGER_TYPE);
+	where.add(whereItem);
+	whereItem = new GS3SQLWhereItem("ParentType", "=", METSFileGroup.SECTION_PARENT);
+	where.add(whereItem);
+	select.setWhere(where);
+	// start going through the matching file groups
+	try {
+	    ResultSet resultSet = statement.executeQuery(select.toString());
+	    if (resultSet.first()) {
+		do {
+		    METSFileGroup filegroup = METSFileGroup.readSQL(document, connection, resultSet);
+		    if (filegroup != null) {
+			set.addGroup(filegroup);
+		    }
+		} while (resultSet.next());
+	    }
+	    statement.close();
+	}
+	catch (SQLException sqlEx) {
+	    System.out.println("METSFileSet.readSQL(): "+sqlEx);
+	    System.exit(1);
+	}
+	return set;
+    }
+    
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSHeader.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSHeader.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSHeader.java	(revision 13666)
@@ -0,0 +1,32 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class METSHeader
+{
+    List agents;
+    METSDate createDate;
+    METSDate lastModDate;
+    
+    public METSHeader()
+    {
+	this.agents = new ArrayList();
+    }
+    
+    public METSHeader(METSAgent defaultAgent)
+    {	
+	this();
+	this.agents.add(defaultAgent);
+    }
+    
+    public void setCreateDate(METSDate createDate)
+    {	
+	this.createDate = createDate;
+    }
+    
+    public void setModifiedDate(METSDate modifiedDate)
+    {	
+	this.lastModDate = modifiedDate;
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSLocation.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSLocation.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSLocation.java	(revision 13666)
@@ -0,0 +1,59 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLConnection;
+
+import org.greenstone.gsdl3.gs3build.util.URLTools;
+
+public class METSLocation
+{
+  String type;
+  URL    location;
+
+  public METSLocation(String type, String location) throws java.net.MalformedURLException
+  { this.type = type;
+    this.location = new URL(location);
+  }
+
+  public METSLocation(URL url)
+  { this.type = "URL";
+    this.location = url;
+  }
+
+  public METSLocation(File file)
+  { this.type = "URL";
+    this.location = URLTools.getFileURL(file);
+  }
+
+  public boolean equals(URL url)
+  { return this.location.equals(url);
+  }
+
+  public URL getLocation()
+  { return this.location;
+  }
+
+  public long getModifiedDatestamp()
+  { if (this.location != null) {
+      if (this.location.getProtocol().equals("file")) {
+	File file = new File(this.location.getPath());
+	return file.lastModified();
+      }
+      else {
+	try {
+	  URLConnection connection = this.location.openConnection();
+	  return connection.getLastModified();
+	}
+	catch (java.io.IOException io)
+	{ // TODO: report error
+	}
+      }
+    }
+    return System.currentTimeMillis();
+  }
+
+  public String getType()
+  { return this.type;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSMetaParams.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSMetaParams.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSMetaParams.java	(revision 13666)
@@ -0,0 +1,6 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+public class METSMetaParams
+{
+	
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSNamespace.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSNamespace.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSNamespace.java	(revision 13666)
@@ -0,0 +1,232 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+import java.io.PrintWriter;
+
+import java.util.List;
+import java.util.Iterator;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.ResultSet;
+
+import org.greenstone.gsdl3.gs3build.database.*;
+
+/**
+ *  Implement a single namespace
+ */
+
+public abstract class METSNamespace
+{
+    protected String       type;        // the type of the metadata
+    protected String       otherType;   // if a non-standard type, then...
+    protected String       name;        // e.g. "DC" for Dublin Core
+    protected METSLocation location;    // the location of the corresponding file
+    protected String       group;       // the group of metadata namespaces to which
+    // this namespace belongs
+    protected String       id;          // the ID for this namespace
+
+    public METSNamespace(String name)
+    { 
+	this.name        = name;
+	this.location    = null;
+	this.group       = null;
+	this.id          = null;
+    }
+    
+    public METSNamespace(String name, METSLocation location)
+    { 
+	this.location    = location;
+	this.name        = name;
+	this.group       = null;
+	this.id          = null;
+    }
+    
+    /**
+     *  Get the name of the namespace...
+     *
+     *  @return <code>String</code> the name of the namespace
+     */
+    public String getName()
+    { 
+	return this.name;
+    }
+    
+    /**
+     *  Get the group of namespaces to which this namespace belongs.
+     *
+     *  @return <code>String</code> the name of the namespace group
+     */
+    public String getGroup()
+    {
+	return this.group;
+    }
+    
+    /**
+     *  Set the group of namespaces to which this namespace belongs.
+     *
+     *  @param <code>String</code> the name of the namespace group
+     */
+    public void setGroup(String group)
+    { 
+	this.group = group;
+    }
+    
+    /**
+     *  Get the ID for this namespace.
+     *
+     *  @return <code>String</code> the id of the namespace
+     */
+    public String getID()
+    {
+	return this.id;
+    }
+    
+    /**
+     *  Set the id of this namespace.
+     *
+     *  @param <code>String</code> the name of the namespace group
+     */
+    public void setID(String id)
+    {
+	this.id = id;
+    }
+
+    /**
+     *  <p>Indicate whether this namespace is open to being changed or not.</p>
+     *  <p>Metadata which is created from a distinct file cannot be changed,
+     *  only those which have no associated file can be modified.
+     *
+     *	@return <code>boolean</code> whether this namespace can be altered.
+     */
+    public boolean isEditable()
+    { 
+	return (this.location == null);
+    }
+    
+    public abstract boolean addMetadata(String label, String value);
+    public abstract boolean setMetadata(String label, String value);
+    public abstract boolean removeMetadata(String label);
+    public abstract boolean removeMetadata(String label, String value);
+    public abstract List    getMetadata(String label);
+    public abstract Iterator getMetadataNames();
+    public abstract boolean write(PrintWriter writer);
+    //  public abstract boolean writeSQL(GS3SQLConnection connection);
+
+    /**
+     *  Write out the metadata to an SQL database through a <code>GS3SQLConnection</code>.
+     *
+     *  @param <code>int</code> the sql identifier of the parent object (in "metadata") table.
+     *  @param <code>GS3SQLConnection</code> the SQL database to use.
+     */
+    public boolean writeSQL(int parentId, GS3SQLConnection connection)
+    { 
+	GS3SQLAction action;
+
+	// If the namespace is not null, then set it...
+	if (this.id != null) {
+	    // use an update action in this case...
+	    GS3SQLUpdate update = new GS3SQLUpdate("namespaces");
+	    update.addValue("NamespaceID", this.id);
+
+	    // set up the where clause
+	    GS3SQLWhere where = 
+		new GS3SQLWhere(new GS3SQLWhereItem("NamespaceRef", "=", this.id, 
+						    GS3SQLField.INTEGER_TYPE));
+	    update.setWhere(where);
+	    action = update;
+	}
+	else {
+	    GS3SQLInsert insert = new GS3SQLInsert("namespaces");
+	    action = insert;
+	}
+
+	if (this.location != null) {
+	    action.addValue("FileLoc", this.location.getLocation().toString());
+	    action.addValue("FileType", "URL");
+	}
+	else {
+	    // no location stuff
+	}
+	action.addValue("MetadataRef", Integer.toString(parentId), GS3SQLField.INTEGER_TYPE);
+	action.addValue("NamespaceType", this.name);
+
+	// Execute the action
+	Statement statement = null;
+	try {
+	    statement = connection.createStatement();
+	    statement.execute(action.toString());
+	} catch (SQLException e) {
+	    System.err.println("METSNamespace.writeSQL(): "+e);
+	    return false;
+	}
+	// then get the namespace reference number if needsbe...
+	if (this.id == null) {
+	    GS3SQLSelect select = new GS3SQLSelect("namespaces");
+	    select.addField("NamespaceRef");
+	    GS3SQLWhereItem whereItem = new GS3SQLWhereItem("MetadataRef", "=", Integer.toString(parentId), GS3SQLField.INTEGER_TYPE);
+	    GS3SQLWhere where = new GS3SQLWhere(whereItem);
+	    whereItem = new GS3SQLWhereItem("NamespaceType", "=", this.name);
+	    where.add(where);
+	    try {
+		ResultSet result  = statement.executeQuery(select.toString());
+      		if (result.last()) {
+		    this.id = Integer.toString(result.getInt("NamespaceRef"));
+		}
+		statement.close();
+	    }
+	    catch (SQLException sqlex){
+		this.id = null;
+		System.err.println("METSNamespace.writeSQL(): "+sqlex);
+		return false;
+	    }
+	}
+	
+	return true;
+    }
+    
+    public static METSNamespace readSQL(GS3SQLConnection connection, ResultSet resultSet)
+    {
+	METSLocation metsLocation = null;
+	
+	try {
+	    String name = resultSet.getString("NamespaceType");
+	    String id = resultSet.getString("NamespaceRef");
+	    String location = resultSet.getString("FileLoc");
+	    String type = resultSet.getString("FileType");
+	    if (location != null && type != null) {
+		metsLocation = new METSLocation(type, location);
+	    }
+	    
+	    METSNamespace namespace = NamespaceFactory.initNamespace(name, metsLocation);
+	    namespace.id = id;
+
+	    int namespaceRef = resultSet.getInt("NamespaceRef");
+      
+	    GS3SQLSelect select = new GS3SQLSelect("mdvalues");
+	    select.addField("*");
+	    GS3SQLWhere where = new GS3SQLWhere(new GS3SQLWhereItem("NamespaceRef", "=", Integer.toString(namespaceRef),
+								    GS3SQLField.INTEGER_TYPE));
+	    select.setWhere(where);
+
+	    Statement statement = connection.createStatement();
+	    ResultSet valuesSet = statement.executeQuery(select.toString());
+	    if (valuesSet.first()) {
+		do {
+		    String label = valuesSet.getString("Label");
+		    String value = valuesSet.getString("Value");
+
+		    namespace.addMetadata(label, value);
+		}
+		while (valuesSet.next());
+	    }
+	    statement.close();
+	    return namespace;
+	}
+	catch (java.net.MalformedURLException urlEx){
+	    System.err.println("METSNamespace.readSQL(): "+urlEx);
+	}
+	catch (SQLException sqlEx){
+	    System.err.println("METSNamespace.readSQL(): "+sqlEx);
+	}    
+	return null;
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSPointer.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSPointer.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSPointer.java	(revision 13666)
@@ -0,0 +1,19 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ *  Notes: Greenstone doesn't currently use/support the SEQ file pointer type;
+ *         hence, one can use only 'area' or 
+ */
+
+public class METSPointer
+{
+	String ID;
+	METSLocation location; // Or something similar...?
+
+	public METSPointer ()
+	{
+	}	
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSStructure.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSStructure.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSStructure.java	(revision 13666)
@@ -0,0 +1,323 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+import java.io.PrintWriter;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.LinkedHashMap;
+import java.util.Iterator;
+
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.ResultSet;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+
+import org.greenstone.gsdl3.gs3build.util.XMLTools;
+import org.greenstone.gsdl3.gs3build.database.*;
+
+public class METSStructure extends AbstractStructure
+{
+    String label;
+    String type;
+    METSDivision divGroup;
+
+    public static final String STRUCTURE_TYPE = "Structure";
+  
+    public METSStructure(String id, String label, String type)
+    { 
+	super(id);
+	
+	this.label    = label;
+	this.type     = type;
+	this.divGroup = null;
+    }
+
+    /**
+     *  Show what sort of <code>AbstractStructure</code> this structure is...
+     *
+     *  @return <code>String The identifying string for a <code>METSStructure</code> type.
+     */
+    public String getStructureType()
+    { return STRUCTURE_TYPE;
+    }
+  
+    /**
+     *  Find all the divisions that match a given list of file group
+     *  identifiers...
+     *
+     *  @param <code>List</code> the list of identifiers to find
+     *  @param <code>List</code> the list into which to place any
+     *         matching identifiers.
+     */
+    public void findDivisionsForFiles(List listOfFileIdentifiers, List resultList)
+    { Iterator groups = this.children.values().iterator();
+    while (groups.hasNext())
+	{ METSDivision group = (METSDivision) groups.next();
+
+	group.findDivisionsForFiles(listOfFileIdentifiers, resultList);
+	}    
+    }
+
+    /**
+     *  Add a division further into this structure.
+     *
+     *  @param <code>String</code> the identifier label for the division
+     *         within which the division is to be added.
+     *  @param <code>METSDivision</code> the division to add.   
+     */
+    public void addSubDivision(String divisionLabel, METSDivision division)
+    { String topDivision = METSDivision.getTopDivisionName(divisionLabel);
+
+    METSDivision child = (METSDivision) this.children.get(topDivision);
+    if (child == null)
+	{ return;
+	}
+
+    child = child.getDivision(divisionLabel);
+
+    if (child != null) {
+	child.addDivision(division);
+    }
+    }
+
+    /**
+     *  Get a subdivision of a given identifier...
+     * 
+     *  @param <code>String</code> the identifier of the division
+     *  @return <code>METSDivision</code> the division, which will be
+     *          <code>null</code> if it is not found.
+     */
+    public METSDivision getDivision(String divisionLabel)
+    { String topDivision = METSDivision.getTopDivisionName(divisionLabel);
+
+    if (!topDivision.equals("All"))
+	System.out.println("Top division is " + topDivision);
+    METSDivision child = (METSDivision) this.children.get(topDivision);
+    if (child == null)
+	{ System.out.println("No child found");
+	Iterator groups = this.children.keySet().iterator();
+	while (groups.hasNext()) {
+	    System.out.println(groups.next().toString());
+	}
+	return null;
+	}
+
+
+    child = child.getDivision(divisionLabel);
+
+    return child;
+    }
+
+
+    /*
+     *
+     * parse an XML Element as a METSStructure Section
+     *
+     * @param <code>Element</code> the XML element which represents
+     *  the mets:structMap itself 
+     */
+    
+    public static METSStructure parseXML(Element element) 
+    {
+ 	String structId = element.getAttribute("ID");
+ 	String structLabel = element.getAttribute("LABEL");
+	String structType = element.getAttribute("TYPE");
+ 
+ 	METSStructure thisStruct = new METSStructure (structId, structLabel, structType);
+ 	
+ 	NodeList divSecs = element.getChildNodes();
+ 	if (divSecs != null) {
+ 	    for (int c = 0; c < divSecs.getLength(); c++) {
+ 		if (divSecs.item(c).getNodeType() != org.w3c.dom.Node.ELEMENT_NODE){
+ 		    continue;
+ 		}
+ 		Element divElement = (Element) divSecs.item(c);
+ 		String divName = divElement.getNodeName();
+ 		if (divName.equals("mets:div")) {
+ 		    METSDivision division = METSDivision.parseXML(divElement);
+ 		    thisStruct.addDivision(division);
+ 		} else {
+ 		    System.err.println("Error: mets:structMap was expecting mets:div but got "+divName);
+ 		}
+ 	    }
+ 	}
+ 	return thisStruct;
+    }
+ 
+    /**
+     *  Write this structure in XML(METS) format to a <code>PrintWriter</code>
+     */
+    public void write(PrintWriter writer)
+    { 
+	Iterator groups = this.children.values().iterator();
+	
+	String tag = XMLTools.getOpenTag("mets", "structMap");
+	tag = XMLTools.addAttribute(tag, "ID", this.ID.toString());
+	tag = XMLTools.addAttribute(tag, "TYPE", this.type);
+	tag = XMLTools.addAttribute(tag, "LABEL", this.label);
+	
+	writer.println(tag);
+	while (groups.hasNext()){
+	    METSDivision group = (METSDivision) groups.next();
+	    
+	    group.write(writer);
+	}
+	writer.println("</mets:structMap>");
+    }
+    
+    
+    /**
+     *  Write this METSStructure to an SQL database....
+     *
+     *  @param <code>DocumentInterface</code> the enclosing document.
+     *  @param <code>GS3SQLConnection</code> the SQL database connection.
+     */
+    public boolean writeSQL(DocumentInterface document, GS3SQLConnection connection)
+    { 
+	int sqlRef = -1;
+	ResultSet results = null;
+	Statement statement = null;
+	
+	// Prepare query to see if this structure has already been written
+	GS3SQLSelect select = new GS3SQLSelect("structure");
+	select.addField("StructureRef");
+	GS3SQLWhereItem whereItem = new GS3SQLWhereItem("DocID", "=", document.getID().toString());
+	GS3SQLWhereItem item = new GS3SQLWhereItem("StructureID", "=", this.ID.toString());
+	GS3SQLWhere where = new GS3SQLWhere(whereItem);
+	where.add(item);
+	select.setWhere(where);
+	
+	// attempt to execute the query & get the current structure's reference
+	try {
+	    statement = connection.createStatement();
+	    results = statement.executeQuery(select.toString());
+	    if (results.first()){
+		sqlRef = results.getInt("structureRef");
+	    }
+	}
+	catch (SQLException sqlEx) {
+	    System.err.print("METSStructure.writeSQL(): "+sqlEx);
+	    return false;
+	}
+	
+	// insert a new structure if it wasn't there previously
+	if (sqlRef == -1) {
+	    GS3SQLInsert insert = new GS3SQLInsert("structure");
+	    insert.addValue("DocID", document.getID().toString());
+	    insert.addValue("StructureID", this.ID.toString());
+	    insert.addValue("StructureType", this.type);
+	    insert.addValue("Label", this.label);
+	    
+	    try {
+		statement.execute(insert.toString());
+		
+		// get the new structure reference by re-running the original select object
+		results = statement.executeQuery(select.toString());
+		if (results.first()) {
+		    sqlRef = results.getInt("StructureRef");
+		} 
+	    } catch (SQLException sqlEx) {
+		System.err.print("METSStructure.writeSQL(): "+sqlEx);
+		return false;
+	    }
+	    
+	}
+	else {
+	    GS3SQLUpdate update = new GS3SQLUpdate("structure");
+	    update.setWhere(where);
+	    
+	    update.addValue("StructureType", this.type);
+	    update.addValue("Label", this.label);
+	    
+	    try {
+		statement.execute(update.toString());
+	    } catch (SQLException sqlEx) {
+		System.err.print("METSStructure.writeSQL(): "+sqlEx);
+		return false;
+	    }
+	}
+	
+	// close the statement
+	try {
+	    statement.close();
+	} catch (SQLException e) {
+	    System.err.println("METSStructure.writeSQL(): "+e);
+	}
+	// write out the child groups (Divisions) now...    
+	Iterator groups = this.children.values().iterator();
+	
+	while (groups.hasNext()){
+	    METSDivision group = (METSDivision) groups.next();
+	    
+	    if (!group.writeSQL(document.getID(), sqlRef, true, connection)){
+		return false;
+	    }
+	}
+	return true;
+    }
+    
+    /**
+     *  Read a METSStructure from a database - on entry, the current item in the
+     *  <code>ResultSet</code> holds the row in the database with the structure's
+     *  data.
+     *
+     *  @param <code>DocumentInterface</code> the document which owns the structure
+     *  @param <code>GS3SQLConnection</code> the database connection itself, to load
+     *         child objects through, etc.
+     *  @param <code>ResultSet</code> pointing to the current row in the database.
+     */
+    public static METSStructure readSQL(DocumentInterface document, GS3SQLConnection connection,
+					ResultSet resultSet)
+    {
+	GS3SQLSelect select = null;
+	
+	try {
+	    String ID    = resultSet.getString("StructureID");
+	    String type  = resultSet.getString("StructureType");
+	    String label = resultSet.getString("Label");
+
+	    // create the metadata block object
+	    METSStructure structure = new METSStructure(ID, label, type);
+      
+	    // get its metadata reference to retrieve divisions
+	    int structureRef = resultSet.getInt("StructureRef");
+
+	    // query the database for matching division for this structure block
+	    select = new GS3SQLSelect("divisions");
+	    select.addField("*");
+	    GS3SQLWhereItem whereItem = new GS3SQLWhereItem("ParentRef", "=", Integer.toString(structureRef),
+							    GS3SQLField.INTEGER_TYPE);
+	    GS3SQLWhere where = new GS3SQLWhere(whereItem);
+	    whereItem = new GS3SQLWhereItem("ParentType", "=", METSStructure.STRUCTURE_TYPE);
+	    where.add(whereItem);
+	    select.setWhere(where);
+
+	    Statement statement = connection.createStatement();
+	    ResultSet divisionSet = statement.executeQuery(select.toString());
+
+	    // parse through the divisions
+	    if (divisionSet.first()) {
+		do {
+		    METSDivision division = METSDivision.readSQL(connection, divisionSet);
+		    if (division != null) {
+			structure.addDivision(division);
+		    }
+		}
+		while (divisionSet.next());
+	    }
+	    statement.close();
+	    return structure;
+	}
+	catch (SQLException sqlEx) {
+	    System.err.println("METSStructure.readSQL(): "+ sqlEx + " " + select.toString());
+	    System.exit(1);
+	}
+	return null;
+    }
+}
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSStructureSet.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSStructureSet.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/METSStructureSet.java	(revision 13666)
@@ -0,0 +1,181 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+import java.io.PrintWriter;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.ResultSet;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+
+import org.greenstone.gsdl3.gs3build.database.*;
+
+public class METSStructureSet
+{ 
+    Map children;
+
+    public static final String GSDL3_SECTION_STRUCTURE = "Section";
+
+    public METSStructureSet()
+    { 
+	this.children = new HashMap();
+    }
+
+    public void addStructure(METSStructure structure)
+    { 
+	this.children.put(structure.getID(), structure);
+    }
+
+    public METSStructure getStructure(String name)
+    { 
+	return (METSStructure) this.children.get(name);
+    }
+
+    /**
+     *  Find the divisions that contain a list of given files
+     *
+     *  @param <code>List</code> the list of files to find...
+     *  @return <code>List</code> the matching divisions.
+     */
+    public List findDivisionsForFiles(List listOfFileIdentifiers)
+    { 
+	List reply = new ArrayList();
+
+	// iterate across all the children...
+	Iterator structures = this.children.values().iterator();
+	
+	while (structures.hasNext()){
+	    METSStructure structure = (METSStructure) structures.next();
+	    
+	    structure.findDivisionsForFiles(listOfFileIdentifiers, reply);      
+	}    
+	return reply;
+    }
+    
+    /**
+     *  Add a division to an indicated structure.
+     *
+     *  @param <code>String</code> the structure identifier
+     *  @param <code>METSDivision</code> the division to be added.
+     */
+    public void addDivision(String structureId, METSDivision division)
+    {
+	METSStructure structure = (METSStructure) this.children.get(structureId);
+	
+	if (structure != null){
+	    structure.addDivision(division);
+	}
+    }
+
+    /**
+     *  Add a division to an indicated division within structure.
+     *
+     *  @param <code>String</code> the structure identifier
+     *  @param <code>String</code> the division identifer, within which the division
+     *         is to be placed.
+     *  @param <code>METSDivision</code> the division to be added.
+     */
+    public void addSubDivision(String structureId, String divisionID, METSDivision division)
+    { 
+	METSStructure structure = (METSStructure) this.children.get(structureId);
+
+	if (structure != null){
+	    structure.addSubDivision(divisionID, division);
+	}
+    }
+
+    /**
+     *  Get a division from within a given structure
+     *
+     *  @param <code>String</code> the structure identifier
+     *  @param <code>String</code> the division identifer
+     *
+     *  @return <code>METSDivision</code> the division
+     */
+    public METSDivision getDivision(String structureId, String divisionId)
+    { 
+	METSStructure structure = (METSStructure) this.children.get(structureId);
+
+	if (structure != null){
+	    return structure.getDivision(divisionId);
+	}
+	return null;
+    }
+    public static METSStructureSet parseXML(NodeList structMapSecs)
+    {
+ 	METSStructureSet set = new METSStructureSet();
+ 
+ 	for (int c = 0; c < structMapSecs.getLength(); c++) {
+ 	    METSStructure structure = METSStructure.parseXML((Element) structMapSecs.item(c));
+ 	    set.addStructure(structure);
+ 	}
+ 	return set;
+    }
+        
+
+    public void write(PrintWriter writer)
+    { 
+	Iterator structures = this.children.values().iterator();
+
+	while (structures.hasNext()){
+	    METSStructure group = (METSStructure) structures.next();
+	    
+	    group.write(writer);
+	}
+    }
+    
+    public boolean writeSQL(DocumentInterface document, GS3SQLConnection connection)
+    { 
+	Iterator structures = this.children.values().iterator();
+    
+	while (structures.hasNext()){
+	    METSStructure group = (METSStructure) structures.next();
+
+	    if (!group.writeSQL(document, connection)){
+		return false;
+	    }
+	}
+	return true;
+    }
+
+    public static METSStructureSet readSQL(DocumentInterface document, GS3SQLConnection connection)
+    { 
+	METSStructureSet set = new METSStructureSet();
+
+	GS3SQLSelect select = new GS3SQLSelect("structure");
+	select.addField("*");
+	GS3SQLWhereItem whereItem = new GS3SQLWhereItem("DocID", "=", document.getID().toString());
+	select.setWhere(new GS3SQLWhere(whereItem));
+	
+	// start going through the matching metadata blocks
+	try {
+	    Statement statement = connection.createStatement();
+	    ResultSet resultSet = statement.executeQuery(select.toString());
+	    if (resultSet.first()) {
+		do {
+		    METSStructure structure = METSStructure.readSQL(document, connection, resultSet);
+		    if (structure != null) {
+			set.addStructure(structure);
+		    }
+		} while (resultSet.next());
+	    }
+	    statement.close();
+	}
+	catch (SQLException sqlEx) {
+	    System.err.println("METSStructureSet.readSQL(): "+sqlEx);
+	    System.exit(1);
+	}
+	return set;
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/MetaElement.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/MetaElement.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/MetaElement.java	(revision 13666)
@@ -0,0 +1,66 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.NamedNodeMap;
+
+import java.util.List;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.greenstone.gsdl3.gs3build.schema.Schema;
+import org.greenstone.gsdl3.gs3build.schema.SchemaNode;
+
+public class MetaElement
+{
+	Map    attributes;
+	List   children;
+	String name;
+
+	public MetaElement(Element element, Schema schema)
+	{	
+		// basic setup
+		this.attributes = new HashMap();
+		this.children   = new ArrayList();
+		this.name = element.getNodeName();
+		StringBuffer contentBuffer = new StringBuffer();
+		
+		// split the name into namespace/workspace
+		String workSpace = SchemaNode.getNamespace(name);
+		name = SchemaNode.getElementName(name);
+
+		// get attributes
+		NamedNodeMap attributes = element.getAttributes();
+		for (int a = 0; a < attributes.getLength(); a ++)
+		{	Node attribute = attributes.item(a);
+
+			this.attributes.put(attribute.getNodeName(), attribute.getNodeValue());
+		}
+
+		// get children
+		NodeList children = element.getChildNodes();
+		for (int c = 0; c < children.getLength(); c++)
+		{	Node child = children.item(c);
+
+			if (child.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE)
+			{	// make a child
+				if (contentBuffer.length() > 0) {
+					this.children.add(contentBuffer.toString());
+					contentBuffer.setLength(0);
+				}
+				Object childElement = new MetaElement((Element) child, schema);
+				this.children.add(childElement);
+			}
+			else
+			{	// append to content if not an element - this may be wasteful & type of
+				// element should be checked
+ 				contentBuffer.append(child.getNodeValue());
+			}
+		}
+		if (contentBuffer.length() > 0) {
+			this.children.add(contentBuffer.toString());
+		}
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/MetaTools.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/MetaTools.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/MetaTools.java	(revision 13666)
@@ -0,0 +1,9 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+
+/**
+ *  A class which provides metadata-centric tools for handling XML objects
+ */
+public class MetaTools
+{
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/MetadataLabel.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/MetadataLabel.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/MetadataLabel.java	(revision 13666)
@@ -0,0 +1,33 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+public class MetadataLabel
+{
+  String namespace;
+  String label;
+
+  public MetadataLabel(String label)
+  { int colonAt = label.indexOf(":");
+    String namespace;
+		
+    if (colonAt > 0) {
+      this.namespace = label.substring(0, colonAt);
+      this.label     = label.substring(colonAt+1);
+    }
+    else {
+      this.namespace = GSDL3Namespace.GSDL3_NAMESPACE_ID;
+      this.label = label;
+    }
+  }
+
+  public String getNamespace()
+  { return this.namespace;
+  }
+
+  public String getLabel()
+  { return this.label;
+  }
+
+  public static String getDefaultNamespace()
+  { return GSDL3Namespace.GSDL3_NAMESPACE_ID;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/NamespaceFactory.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/NamespaceFactory.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/NamespaceFactory.java	(revision 13666)
@@ -0,0 +1,71 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+public class NamespaceFactory
+{
+    public static METSNamespace initNamespace()
+    {	
+	return new GSDL3Namespace();
+    }
+    
+    public static METSNamespace initNamespace(String name)
+    {	
+	if (name.equals(GSDL3Namespace.GSDL3_NAMESPACE_ID)) {
+	    return new GSDL3Namespace();
+	}
+	return new SimpleNamespace(name);
+    }
+    
+    public static METSNamespace initNamespace(String name, METSLocation location)
+    {	
+	if (name.equals(GSDL3Namespace.GSDL3_NAMESPACE_ID)){
+	    return new GSDL3Namespace(location);
+	}
+	return new SimpleNamespace(name, location);
+    }
+    
+    /**
+     *  TODO: parse the document in based upon its namespace
+     */
+    public static METSNamespace initNamespace(String name, Element element)
+    {	
+	//return null;
+	return new SimpleNamespace(name);
+    }
+    
+    public static METSNamespace parseXML(Element element)
+    {
+	METSNamespace namespace = null;
+	
+	//String mdType = element.getAttribute("MDType");
+	//String mdType =element.getAttribute("MDTYPE");
+
+	String othermdType = element.getAttribute("OTHERMDTYPE");
+	String mimeType = element.getAttribute("mimeType");
+	
+	if (element.getNodeName().equals("mets:mdWrap")) {
+	    namespace = initNamespace(othermdType, element);
+	}
+	else if (element.getNodeName().equals("mets:mdRef")) {
+	    String mdType = element.getAttribute("MDType");
+	    // just a file wrapper on the metadata...
+	    String location = element.getAttribute("xlink:href");
+	    String locationType = element.getAttribute("LOCTYPE");
+	    
+	    try {
+		METSLocation metsLocation = new METSLocation(locationType, location);
+		namespace = initNamespace(mdType, metsLocation);
+	    }
+	    catch (java.net.MalformedURLException ex) {
+		// TODO: Error, should never happen in the case of Greenstone-exported XML
+	    }
+	}
+	return namespace;
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/NamespaceItem.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/NamespaceItem.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/NamespaceItem.java	(revision 13666)
@@ -0,0 +1,24 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+/**
+ *  A simple metadata item with a label and one value to fit...
+ */
+
+public class NamespaceItem
+{
+	private String label;
+	private String value;
+
+	public NamespaceItem(String label, String value)
+	{	this.label = label;
+		this.value = value;
+	}
+
+	public String getLabel()
+	{	return this.label;
+	}
+
+	public String getValue()
+	{	return this.value;
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/OrderedNamespace.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/OrderedNamespace.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/OrderedNamespace.java	(revision 13666)
@@ -0,0 +1,259 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+import java.io.PrintWriter;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.greenstone.gsdl3.gs3build.util.MultiMap;
+import org.greenstone.gsdl3.gs3build.util.XMLTools;
+
+/**
+ *  Implement a generic, ordered namespace in METS.
+ *
+ *  @see: org.greenstone.gsdl3.gs3build.metadata.METSNamespace
+ */
+
+public class OrderedNamespace extends METSNamespace
+{
+    List metadataList;
+    
+    public OrderedNamespace(String name)
+    { 
+	super(name);
+	this.metadataList = new ArrayList();
+    }
+    
+    public OrderedNamespace(String name, METSLocation location)
+    { 
+	super(name, location);
+	this.metadataList = new ArrayList();
+    }
+    
+    public boolean validate(String field, String value)
+    { 
+	return true;
+    }
+    
+    /**
+     *  Add a metadata item.  Whether the field and value validate for this
+     *  schema will also be tested.
+     *
+     *  @param <code>String</code> the name of the field to be given the value
+     *  @param <code>String</code> the value to be assigned
+     *
+     *  @return <code>boolean</code> whether the field value was added.  This
+     *          would return <code>false</code> if the values did not validate,
+     *          for example.
+     */
+    public boolean addMetadata(String label, String value)
+    { 
+	if (!this.validate(label, value)) {
+	    return false;
+	}
+	
+	this.metadataList.add(new NamespaceItem(label, value));
+	return true;
+    }
+    
+    /**
+     *  Assign a metadata item.  Whether the field and value validate for this
+     *  schema will also be tested.  Any existing metadata for that field will
+     *  be destroyed if the new value validates.
+     *
+     *  @param <code>String</code> the name of the field to be given the value
+     *  @param <code>String</code> the value to be assigned
+     *
+     *  @return <code>boolean</code> whether the field value was added.  This
+     *          would return <code>false</code> if the values did not validate,
+     *          for example.
+     */
+    public boolean setMetadata(String label, String value)
+    { 
+	if (!this.validate(label, value)){
+	    return false;
+	}
+	
+	// TODO:		this.metadataMap.setOnly(label, value);
+	int itemNo = this.findItem(label);
+	if (itemNo >= 0){
+	    this.metadataList.set(itemNo, new NamespaceItem(label, value));
+	    return true;
+	}
+	return false;
+    }
+    
+    /**
+     *  Remove all metadata values for a given field name
+     *
+     *  @param <code>String</code> the field to delete
+     *
+     *  @return <code>boolean</code> whether the field was actually deleted; 
+     *          will return <code>true</code> if the field was already empty.
+     */
+    public boolean removeMetadata(String label)
+    { 
+	int itemNo;
+	
+	itemNo = this.findItem(label);
+	while (itemNo >= 0){
+	    this.metadataList.remove(itemNo);
+	    itemNo = this.findItem(label);
+	}
+	return true;
+    }
+    
+    /**
+     *  Remove a particular incidence of a given metadata field for a document.
+     *  If an exact match for the given value is not found, nothing changes.
+     *  N.B. if a value occurs twice, only the first incidence of it will be
+     *  deleted from the list.
+     *
+     *  @param <code>String</code> the field to have the value removed
+     *  @param <code>String</code> the value to be removed from a given field
+     *
+     *  @return <code>boolean</code> <code>true</code> if an actual metadata text
+     *          is matched against the given value and is thus deleted.
+     */
+    public boolean removeMetadata(String label, String value)
+    { 
+	int itemNo;
+	
+	itemNo = this.findItem(label);
+	if (itemNo >= 0) {
+	    this.metadataList.remove(itemNo);
+	    return true;
+	}
+	return false;
+    }
+    
+    /**
+     *  Get the metadata items for a particular label
+     *
+     *  @param <code>String</code> the label to fetch values for - must be devoid
+     *                             of namespace prologue (i.e. "title" rather than
+     *                             e.g. "dc:title").
+     *  
+     *  @return <code>List</code> the list of corresponding values.  May be
+     *          <code>null</code> if no values are found for the metadata
+     */
+    public List getMetadata(String label)
+    { 
+	List resultList = new ArrayList();
+	
+	for (int i = 0; i < this.metadataList.size(); i ++) {
+	    NamespaceItem item = (NamespaceItem) this.metadataList.get(i);
+	    
+	    if (item.getLabel().equals(label)){
+		resultList.add(item.getValue());
+	    }
+	}
+	if (resultList.size() > 0){
+	    return resultList;
+	}
+	return null;
+    }
+    
+    private int findItem(String label)
+    { 
+	for (int i = 0; i < this.metadataList.size(); i ++) {
+	    if (((NamespaceItem) this.metadataList.get(i)).getLabel().equals(label)){
+		return i;
+	    }
+	}
+	return -1;
+    }
+    
+    private int findItem(String label, String value)
+    { 
+	for (int i = 0; i < this.metadataList.size(); i ++){
+	    NamespaceItem item = (NamespaceItem) this.metadataList.get(i);
+	    if (item.getLabel().equals(label) && item.getValue().equals(value)){
+		return i;
+	    }
+	}
+	return -1;
+    }
+    
+    public Iterator getMetadataNames() 
+    {
+ 	return this.metadataList.iterator();
+    }
+    
+    
+    /**
+     *  Write out the metadata to an XML file through a <code>PrintWriter</code>.
+     *
+     *  @param <code>PrintWriter</code> the writer to use.
+     */
+    public boolean write(PrintWriter writer)
+    { 
+	// if this is a non-file block of metadata, write it out in long hand
+	if (this.location == null){
+	    String tag = XMLTools.getOpenTag("mets", "mdWrap");
+	    tag = XMLTools.addAttribute(tag, "MDTYPE", "OTHER");
+	    tag = XMLTools.addAttribute(tag, "OTHERMDTYPE", this.name);
+	    if (this.id != null) {
+		this.id = "gsdl"+this.id;
+		tag = XMLTools.addAttribute(tag, "ID", this.id);
+	    }
+	    writer.print("   ");  //indentation
+	    writer.println(tag);
+	    
+	    Iterator items = this.metadataList.iterator();
+	    
+	    while (items.hasNext()){
+		NamespaceItem item = (NamespaceItem) items.next();
+		this.writeItem(writer, item);
+	    }
+	    writer.print("   ");  //indentation
+	    writer.println("</mets:mdWrap>");
+	}
+	// otherwise, drop the metadata out in a simplified file-reference
+	// form only
+	else
+	    { 
+		String tag = XMLTools.getOpenTag("mets", "mdRef");
+		tag = XMLTools.addAttribute(tag, "LOCTYPE", this.location.getType());
+		tag = XMLTools.addAttribute(tag, "xlink:href", this.location.getLocation().toString());
+		tag = XMLTools.addAttribute(tag, "MDTYPE", this.name);
+		//tag = XMLTools.addAttribute (tag, "MDTYPE", "OTHER");
+		//tag = XMLTools.addAttribute(tag, "OTHERMDTYPE", this.name); 
+		if (this.id != null) {
+		    tag = XMLTools.addAttribute(tag, "ID", this.id);
+		}
+		tag = XMLTools.makeSingleton(tag);
+	    }
+	return true;
+    }
+    
+    /**
+     *  Write out a single element - this may be overloaded to provide for the
+     *  appropriate formatting for this metadata.
+     */
+    protected boolean writeItem(PrintWriter writer, NamespaceItem item)
+    { 
+	// Do some default sillinesses
+	//writer.write("         "); 
+	writer.write(XMLTools.getOpenTag(this.name, item.getLabel()));
+	
+	writer.write(item.getValue());
+	
+	writer.write(XMLTools.getCloseTag(this.name, item.getLabel()));
+	return true;
+    }
+    
+    /**
+     *  <p>Indicate whether this metadata is open to being changed or not.</p>
+     *  <p>Metadata which is created from a distinct file cannot be changed,
+     *  only those which have no associated file can be modified.
+     *
+     *	@return <code>boolean</code> whether this namespace can be altered.
+     */
+    public boolean isEditable()
+    { 
+	return (this.location == null);
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/SimpleNamespace.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/SimpleNamespace.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/SimpleNamespace.java	(revision 13666)
@@ -0,0 +1,347 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+import java.io.PrintWriter;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.ResultSet;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+import org.greenstone.gsdl3.gs3build.util.MultiMap;
+import org.greenstone.gsdl3.gs3build.util.XMLTools;
+import org.greenstone.gsdl3.gs3build.database.*;
+
+/**
+ *  Implement a simple, unordered, namespace in METS.
+ *
+ *  @see: org.greenstone.gsdl3.gs3build.metadata.METSNamespace
+ */
+
+public class SimpleNamespace extends METSNamespace
+{
+    MultiMap metadataMap;
+    
+    public SimpleNamespace(String name)
+    { 
+	super(name);
+	this.metadataMap = new MultiMap();
+    }
+    
+    public SimpleNamespace(String name, METSLocation location)
+    { 
+	super(name, location);
+	this.metadataMap = new MultiMap();
+    }
+    
+    public SimpleNamespace(String name, Element mdWrapTag)
+    { 
+	super(name);
+	this.metadataMap = new MultiMap();
+	
+	NodeList childNodes = mdWrapTag.getChildNodes();
+	for (int c = 0; c < childNodes.getLength(); c ++) {
+	    // a metadata node
+	    if (childNodes.item(c).getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
+		// get the name of the metadata from the node
+		String metadataLabel = childNodes.item(c).getNodeName();
+		
+		// skip blank labels
+		// TODO: raise an error: metadata item without metadata label set
+		if (metadataLabel == null || metadataLabel.length() == 0) {
+		    continue;
+		}
+		
+		// build the value
+		String metadataValue = "";
+		
+		Element childElement = (Element) childNodes.item(c);
+		for (int i = 0; i < childElement.getChildNodes().getLength(); i ++) {
+		    metadataValue = metadataValue + childElement.getChildNodes().item(i).toString();
+		}
+		
+		// trim any leading namespace identifiers in "namespace:label" metadata
+		if (metadataLabel.startsWith(this.name + ":")) {
+		    metadataLabel = metadataLabel.substring(this.name.length() + 1);
+		}
+		
+		this.addMetadata(metadataLabel, metadataValue);
+	    }
+	}
+    }
+    
+    public boolean validate(String field, String value)
+    { 
+	return true;
+    }
+    
+    /**
+     *  Add a metadata item.  Whether the field and value validate for this
+     *  schema will also be tested.
+     *
+     *  @param <code>String</code> the name of the field to be given the value
+     *  @param <code>String</code> the value to be assigned
+     *
+     *  @return <code>boolean</code> whether the field value was added.  This
+     *          would return <code>false</code> if the values did not validate,
+     *          for example.
+     */
+    public boolean addMetadata(String label, String value)
+    {
+	if (!this.validate(label, value)) {
+	    return false;
+	}
+	
+	this.metadataMap.put(label, value);
+	return true;
+    }
+    
+    /**
+     *  Assign a metadata item.  Whether the field and value validate for this
+     *  schema will also be tested.  Any existing metadata for that field will
+     *  be destroyed if the new value validates.
+     *
+     *  @param <code>String</code> the name of the field to be given the value
+     *  @param <code>String</code> the value to be assigned
+     *
+     *  @return <code>boolean</code> whether the field value was added.  This
+     *          would return <code>false</code> if the values did not validate,
+     *          for example.
+     */
+    public boolean setMetadata(String label, String value)
+    { 
+	if (!this.validate(label, value)) {
+	    return false;
+	}
+	
+	this.metadataMap.setOnly(label, value);
+	return true;
+    }
+    
+    /**
+     *  Remove all metadata values for a given field name
+     *
+     *  @param <code>String</code> the field to delete
+     *
+     *  @return <code>boolean</code> whether the field was actually deleted; 
+     *          will return <code>true</code> if the field was already empty.
+     */
+    public boolean removeMetadata(String label)
+    { 
+	this.metadataMap.remove(label);
+	return true;
+    }
+    
+    /**
+     *  Remove a particular incidence of a given metadata field for a document.
+     *  If an exact match for the given value is not found, nothing changes.
+     *  N.B. if a value occurs twice, only the first incidence of it will be
+     *  deleted from the list.
+     *
+     *  @param <code>String</code> the field to have the value removed
+     *  @param <code>String</code> the value to be removed from a given field
+     *
+     *  @return <code>boolean</code> <code>true</code> if an actual metadata text
+     *          is matched against the given value and is thus deleted.
+     */
+    public boolean removeMetadata(String label, String value)
+    { 
+	return this.metadataMap.remove(label, value);
+    }
+    
+    /**
+     *  Get the metadata items for a particular label
+     *
+     *  @param <code>String</code> the label to fetch values for
+     *  
+     *  @return <code>List</code> the list of corresponding values.  May be
+     *          <code>null</code>
+     */
+    public List getMetadata(String label)
+    { 
+	return this.metadataMap.getAll(label);
+    }
+    
+    public Iterator getMetadataNames() 
+    {
+ 	return this.metadataMap.keySet().iterator();
+    }
+    
+    /**
+     *  Write out the metadata to an XML file through a <code>PrintWriter</code>.
+     *
+     *  @param <code>PrintWriter</code> the writer to use.
+     */
+    public boolean write(PrintWriter writer)
+    { 
+	// if this is a non-file block of metadata, write it out in long hand
+	if (this.location == null){
+	    String tag = XMLTools.getOpenTag("mets", "mdWrap");
+	    
+	    tag = XMLTools.addAttribute(tag, "MDTYPE", "OTHER");
+	    tag = XMLTools.addAttribute(tag, "OTHERMDTYPE", this.name);
+	    if (this.id != null) {
+		this.id = "gsdl"+this.id;
+		tag = XMLTools.addAttribute(tag, "ID", this.id);
+	    }
+	    writer.print("   ");  //indentation
+	    writer.println(tag);
+	    
+	    tag = XMLTools.getOpenTag("mets", "xmlData");
+	    writer.print("      ");  //indentation 
+	    writer.println(tag);
+	    
+	    Iterator keys = this.metadataMap.keySet().iterator();
+	    while (keys.hasNext()){
+		String thisKey = keys.next().toString();
+		writer.print("         "); //indentation
+		this.writeItem(writer, thisKey);
+	    }
+	    
+	    writer.print("      ");  //indentation 
+	    writer.println(XMLTools.getCloseTag("mets", "xmlData"));
+	    
+	    writer.print("   ");  //indentation
+	    writer.println(XMLTools.getCloseTag("mets", "mdWrap"));
+	}
+	// otherwise, drop the metadata out in a simplified file-reference
+	// form only
+	else
+	    { 
+		String tag = XMLTools.getOpenTag("mets","mdRef");
+		tag = XMLTools.addAttribute(tag, "LOCTYPE", "URL");
+		tag = XMLTools.addAttribute(tag, "xlink:href", location.getLocation().toString());
+		//tag = XMLTools.addAttribute(tag, "MDTYPE", "OTHER");
+		//tag = XMLTools.addAttribute(tag, "OTHERMDTYPE", this.name);
+		tag = XMLTools.addAttribute(tag, "MDTYPE", this.name);	
+		if (this.id != null) {
+		    tag = XMLTools.addAttribute(tag, "ID", this.id);
+		}
+		writer.println(tag);
+		writer.print("   ");  //indentation	
+		writer.println("</mets:mdRef>");
+	    }
+	return true;
+    }
+    
+    /**
+     *  Write out a single element - this may be overloaded to provide for the
+     *  appropriate formatting for this metadata.
+     */
+    protected boolean writeItem(PrintWriter writer, String label)
+    { 
+	if (this.location == null) {
+	    // just place the metadata in a simple wrapper
+	    Iterator values = this.metadataMap.getAll(label).iterator();
+	    
+	    while (values.hasNext()) {
+		String value = values.next().toString();
+		String metaTagName = "Metadata name=" +'"'+ label +'"';
+		//writer.write(XMLTools.getOpenTag(this.name, label));
+		writer.write(XMLTools.getOpenTag(this.name, metaTagName));
+		writer.write(value);
+		
+		//writer.println(XMLTools.getCloseTag(this.name, label));
+		writer.println(XMLTools.getCloseTag(this.name, "Metadata"));
+	    }
+	}
+	else {
+	    String tag = XMLTools.getOpenTag("mets", "mdRef");
+	    tag = XMLTools.addAttribute(tag, "LOCTYPE", this.location.getType());
+	    tag = XMLTools.addAttribute(tag, "xlink:href", this.location.getLocation().toString());
+	    tag = XMLTools.addAttribute(tag, "MDTYPE", this.getName());
+	    tag = XMLTools.makeSingleton(tag);
+	    writer.print("      "); //indentation 
+	    writer.println(tag);
+	}
+	return true;
+    }
+    
+    /**
+     *  Write out the metadata to an SQL database through a <code>GS3SQLConnection</code>.
+     *
+     *  @param <code>GS3SQLConnection</code> the SQL database to use.
+     */
+    public boolean writeSQL(int parentId, GS3SQLConnection connection)
+    { 
+	// write the general stuff
+	String sqlId;
+	
+	if (!super.writeSQL(parentId, connection)) {
+	    return false;
+	}
+	
+	Statement statement = null;
+	ResultSet results = null;
+	try {
+	    statement = connection.createStatement();
+	    if (this.id == null) {
+		GS3SQLSelect select = new GS3SQLSelect("namespaces");
+		select.setWhere(new GS3SQLWhere(new GS3SQLWhereItem("MetadataRef", "=", Integer.toString(parentId), GS3SQLField.INTEGER_TYPE)));
+		select.addField("NamespaceRef");
+		results = statement.executeQuery(select.toString());
+		if (results.first()) {
+		    sqlId = Integer.toString(results.getInt("NamespaceRef"));
+		} else {
+		    statement.close();
+		    return false;
+		}
+	    }
+	    else {
+		sqlId = this.id;
+	    }
+	    
+	    // clear all the existing metadata items for this namespace
+	    GS3SQLDelete delete = new GS3SQLDelete("mdvalues");
+	    GS3SQLWhere where = new GS3SQLWhere(new GS3SQLWhereItem("NamespaceRef", "=", sqlId, GS3SQLField.INTEGER_TYPE));
+	    delete.setWhere(where);
+	    statement.execute(delete.toString());
+	    
+	    // write out the metadata for this namespace
+	    Iterator keys = this.metadataMap.keySet().iterator();
+	    while (keys.hasNext()){
+		String thisKey = keys.next().toString();
+		
+		Iterator values = this.metadataMap.getAll(thisKey).iterator();
+		
+		while (values.hasNext()){
+		    String value = values.next().toString();
+		    
+		    GS3SQLInsert insert = new GS3SQLInsert("mdvalues");
+		    insert.addValue("NamespaceRef", sqlId, GS3SQLField.INTEGER_TYPE);
+		    insert.addValue("Label", thisKey);
+		    insert.addValue("Value", value);
+		    statement.execute(insert.toString());
+		}
+	    }
+	    statement.close();
+	}
+	catch (SQLException sql) {
+	    System.out.println("SimpleNamespace.writeSQL(): "+sql);
+	}
+	return true;
+    }
+    
+    
+    /**
+     *  <p>Indicate whether this metadata is open to being changed or not.</p>
+     *  <p>Metadata which is created from a distinct file cannot be changed,
+     *  only those which have no associated file can be modified.
+     *
+     *	@return <code>boolean</code> whether this namespace can be altered.
+     */
+    public boolean isEditable()
+    { 
+	return (this.location == null);
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/StructureIdentifierFactory.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/StructureIdentifierFactory.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/metadata/StructureIdentifierFactory.java	(revision 13666)
@@ -0,0 +1,17 @@
+package org.greenstone.gsdl3.gs3build.metadata;
+
+/**
+ *  TODO: complete a class to create file identifiers
+ */
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+
+public class StructureIdentifierFactory extends AbstractIdentifierFactory
+{
+    public static final String STRUCTURE_IDENTIFIER_PRELUDE = "DS";
+    
+    public StructureIdentifierFactory()
+    {
+	super(STRUCTURE_IDENTIFIER_PRELUDE);
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/notifier/NotifierManager.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/notifier/NotifierManager.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/notifier/NotifierManager.java	(revision 13666)
@@ -0,0 +1,166 @@
+package org.greenstone.gsdl3.gs3build.notifier;
+
+import java.io.*;
+import java.net.*;
+import java.sql.*;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.greenstone.gsdl3.gs3build.CollectionManager;
+import org.greenstone.gsdl3.gs3build.database.GS3SQLConnection;
+
+public class NotifierManager {
+
+    public NotifierManager() {
+    }
+    
+    public void detectEvents(CollectionManager collManager) {
+	String notifyHost = collManager.getNotifyHost();
+	if (notifyHost == null)
+	    return;
+	
+	System.out.println("detecting events");
+	
+	String collectionName = collManager.getCollectionName();
+	String host = "http://localhost:8080/soap/servlet/rpcrouter";
+	
+	String lastBuild = dateToSqlString(collManager.getBuildDate());
+	System.out.println("last build was " + lastBuild);
+        try {
+	    Statement statement = collManager.getDatabase().createStatement();
+            // detect all new documents. A document is new if and only if
+            // AccessionDate >= CollectionLastRebuiltDate
+	    ResultSet results = statement.executeQuery("SELECT DocID FROM document WHERE DocType != 'GSMETADATA' AND AccessionDate >= " + lastBuild);
+	    notify(collectionName, host, notifyHost, results, collManager.getDatabase(), collManager.getBuildDate(), "new_document");
+	    
+	    // detect modified documents. A document is modified if and only if
+	    // AccessionDate < CollectionLastRebuiltDate (ie, it is not new) and 
+	    // IndexedDate >= CollectionLastRebuiltDate 
+	    results = statement.executeQuery("SELECT DocID FROM document WHERE DocType != 'GSMETADATA' AND AccessionDate < " + lastBuild + " AND IndexedDate >= " + lastBuild);
+	    notify(collectionName, host, notifyHost, results, collManager.getDatabase(), collManager.getBuildDate(), "document_modified");
+	    
+	    statement.close();
+	    // TODO deleted docs?
+        } catch (SQLException e) {
+	    // TODO Auto-generated catch block
+	    e.printStackTrace();
+        }
+    }
+    
+    /**
+     * @param collName
+     * @param hostURL
+     * @param results
+     * @param date
+     * @param eventType TODO
+     * @throws MalformedURLException
+     * @throws IOException
+     * @throws ProtocolException
+     * @throws SQLException
+     */
+    private void notify(String collName, String hostURL, String notifyHost, ResultSet results, GS3SQLConnection database, Date date, String eventType) {
+	try {
+	    System.out.println("notifyHost is " + notifyHost);
+	    URL url = new URL("http://" + notifyHost + "/alerting/service");
+	    System.out.println("trying to send to " + url);
+	    
+	    while(results.next()) {
+		System.out.println(eventType + ": " + results.getString("DocID"));
+	            
+                String documentID = results.getString("DocID");
+                
+		try {
+                    HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // TODO what about proxies?
+                    conn.setUseCaches(false);
+                    conn.setDoInput(true);
+                    conn.setDoOutput(true);
+                    conn.setRequestMethod("POST");
+                    conn.connect();
+                    // Construct data
+                    OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
+                    
+                    writer.write("action=receiveEvent&");
+                    writer.write("documentID=");
+                    writer.write(URLEncoder.encode(documentID, "UTF-8"));
+                    writer.write("&type=");
+                    writer.write(URLEncoder.encode(eventType, "UTF-8"));
+                    writer.write("&collectionID=");
+                    writer.write(URLEncoder.encode(collName, "UTF-8"));
+                    writer.write("&hostID=");
+                    writer.write(URLEncoder.encode(hostURL, "UTF-8"));
+                    writer.write("&document_title=");
+                    writer.write(URLEncoder.encode(getDocumentTitle(documentID, database), "UTF-8"));
+                    writer.write("&document_url=");
+                    writer.write(URLEncoder.encode("http://localhost:8080/gsdl3/library?a=d&c=" + collName + "&d=" + documentID, "UTF-8"));
+                    writer.write("&timestamp=");
+                    writer.write(URLEncoder.encode(new SimpleDateFormat("yyyy-MM-dd HH:mm z").format(date), "UTF-8"));
+                    writer.flush();
+                    System.out.println(conn.getResponseCode());
+                    InputStream fromReceiver = conn.getInputStream();
+                    int i;
+                    while ((i = fromReceiver.read()) != -1) {
+                        System.out.write(i);
+                    }
+                    conn.disconnect();
+                } catch (ProtocolException e1) {
+                    // TODO Auto-generated catch block
+                    e1.printStackTrace();
+                } catch (UnsupportedEncodingException e1) {
+                    // TODO Auto-generated catch block
+                    e1.printStackTrace();
+                } catch (IOException e1) {
+                    // TODO Auto-generated catch block
+                    e1.printStackTrace();
+                }
+	    }
+	} catch (SQLException e) {
+	    // TODO Auto-generated catch block
+	    e.printStackTrace();
+	} catch (MalformedURLException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * @param documentID
+     * @return
+     * @throws SQLException
+     */
+    private String getDocumentTitle(String documentID, GS3SQLConnection database) {
+        System.out.println("getting title for document " + documentID + " from database");
+
+        try {
+	    Statement statement = database.createStatement();
+            String sqlString = "SELECT mdvalues.value " +
+		"FROM structure s JOIN divisions d ON (s.structureref = d.parentref) " +
+		"                 JOIN divisionmetarefs USING (divisionref) " + 
+		"                 JOIN metadata m USING (metaid) " +
+		"                 JOIN namespaces USING (metadataref) " + 
+		"                 JOIN mdvalues USING (namespaceref) " +
+		"  WHERE mdvalues.label = 'Title' AND s.docid = '" + documentID + "'" + 
+		"                                 AND s.structureType = 'Whole Document' " +
+		"                                 AND d.parenttype = 'Structure' " + 
+		"                                 AND m.docID = s.docid;";
+            ResultSet results = statement.executeQuery(sqlString);
+            if (results.first()) {
+                String title = results.getString("value");
+                System.out.println("title is " + title);
+                return title;
+            }
+	    statement.close();
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        return "";
+    }
+
+    /**
+     * @param date
+     * @return
+     */
+    private String dateToSqlString(Date date) {
+        return new SimpleDateFormat("yyyyMMddHHmmss").format(date);
+    }
+}
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/ChildWrapper.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/ChildWrapper.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/ChildWrapper.java	(revision 13666)
@@ -0,0 +1,28 @@
+package org.greenstone.gsdl3.gs3build.schema;
+
+public class ChildWrapper
+{
+    int minOccurs;
+    int maxOccurs;
+
+
+    /**
+     *  The default number of occurrences for an element is 1 (one) for
+     *  both minimum and maximum counts.
+     */
+    public ChildWrapper()
+    {
+	this.minOccurs = 1;
+	this.maxOccurs = 1;
+    }
+
+    public void setMinOccurs(int minOccurs)
+    {
+	this.minOccurs = minOccurs;
+    }
+
+    public void setMaxOccurs(int maxOccurs)
+    {
+	this.maxOccurs = maxOccurs;
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/EnumConstraint.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/EnumConstraint.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/EnumConstraint.java	(revision 13666)
@@ -0,0 +1,22 @@
+package org.greenstone.gsdl3.gs3build.schema;
+
+import java.util.*;
+
+public class EnumConstraint
+{
+    List options;
+
+    public EnumConstraint()
+    { this.options = new ArrayList();
+    }
+
+  public void addOption(String option)
+  {
+    this.options.add(option);
+  }
+
+  public boolean validate(String value)
+  {
+	  return this.options.contains(value);
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/RangeConstraint.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/RangeConstraint.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/RangeConstraint.java	(revision 13666)
@@ -0,0 +1,34 @@
+package org.greenstone.gsdl3.gs3build.schema;
+
+public class RangeConstraint
+{
+    public static final int RANGE_MIN_EXCLUSIVE = 0x00;
+    public static final int RANGE_MAX_EXCLUSIVE = 0x01;
+    public static final int RANGE_MIN_INCLUSIVE = 0x10;
+    public static final int RANGE_MAX_INCLUSIVE = 0x11;
+
+    int type;
+    double value;
+
+    public RangeConstraint(int type, double value)
+    {
+	    this.type = type;
+	    this.value = value;
+    }
+
+  public boolean validate(double value)
+  {
+  	switch (this.type) {
+	  case RANGE_MIN_EXCLUSIVE:
+	    return (value > this.value);
+  	case RANGE_MAX_EXCLUSIVE:
+	    return (value < this.value);
+   case RANGE_MIN_INCLUSIVE:
+	    return (value >= this.value);
+   case RANGE_MAX_INCLUSIVE:
+	    return (value <= this.value);
+	}
+	return false;
+}
+
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/Schema.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/Schema.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/Schema.java	(revision 13666)
@@ -0,0 +1,78 @@
+package org.greenstone.gsdl3.gs3build.schema;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class Schema
+{
+	List children;
+
+	public Schema(Node node)
+	{
+		this.children = new ArrayList();
+
+		NodeList elements = node.getChildNodes();
+
+		System.out.println("Schema has " + elements.getLength() + " children");
+		for (int e = 0; e < elements.getLength(); e++) {
+			System.out.println("Subcomponent " + e);
+			// TODO: actually test what is being parsed here!
+			if (elements.item(e).getNodeType() != org.w3c.dom.Node.ELEMENT_NODE) {
+				continue;
+			}
+
+			System.out.println(elements.item(e));
+
+			Element element = (Element) elements.item(e);
+
+			String elementName = element.getLocalName();
+			String fullName = element.getNodeName();
+			String valueName = element.getNodeValue();
+
+			System.out.println(elementName + " " + fullName + " " + valueName);
+
+			if (elementName == null) {
+				elementName = fullName;
+			}
+
+			System.out.println(elementName);
+			elementName = SchemaNode.getElementName(elementName);
+
+			if (elementName.equals("element")) {
+
+				SchemaElement thisElement = new SchemaElement(element);
+/*			
+				NodeList attributes = element.getElementsByTagName("attribute");
+
+				for (int i = 0; i < attributes.getLength(); i++) {
+			    Element attribute = (Element) attributes.item(i);
+					// handle that attribute, create its node and check what you get out
+					try {
+						SchemaAttribute thisAttribute = new SchemaAttribute(attribute);
+						thisElement.addAttribute(thisAttribute);
+					}
+					catch (SchemaException ex) {
+						// do nothing at the moment - though a malformed attribute should be
+						// cause for throwing everything in the air
+					}
+				}*/
+				this.children.add(thisElement);
+			}
+			else {
+				try {
+					Object child = SchemaNodeFactory.makeNode(element);
+					if (child != null) {
+						this.children.add(child);
+					}
+				}
+				catch (SchemaException metaEx)
+				{
+				}
+			}
+		}
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaAll.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaAll.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaAll.java	(revision 13666)
@@ -0,0 +1,22 @@
+package org.greenstone.gsdl3.gs3build.schema;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class SchemaAll extends SchemaNode
+{
+	List compulsory;
+
+	public SchemaAll(Element element) throws SchemaException
+	{	super(element);
+	}
+
+	protected List _allocate()
+	{	this.compulsory = new ArrayList();
+		return this.compulsory;
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaAttribute.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaAttribute.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaAttribute.java	(revision 13666)
@@ -0,0 +1,37 @@
+package org.greenstone.gsdl3.gs3build.schema;
+
+import org.w3c.dom.Element;
+
+public class SchemaAttribute
+{ 
+	public final static String ATTRIBUTE_TYPE_STRING = "String";
+
+  String name;
+  String type;
+  boolean required;
+
+	public SchemaAttribute(Element element) throws SchemaException
+	{
+		// get the name - things are totally unworkable if it doesn't exist!
+		this.name = element.getAttribute("name");
+		if (this.name == null) {
+			throw new SchemaException("All attributes must have names");
+		}
+
+		// ids are quite important in some metadata schema - copy that too
+		String id = element.getAttribute("id");
+
+		// get the required field - we don't actually cope with "prohibited" at the moment!
+		String use = element.getAttribute("use");
+		this.required = (use != null && use.equals("required"));
+
+		// and the type - we don't reflect any further upon this, actually
+		this.type = element.getAttribute("type");
+		if (this.type == null) {
+			this.type = SchemaAttribute.ATTRIBUTE_TYPE_STRING;
+		}
+
+		// Constraints should now be added, but at present that is not done, as we
+		// are non-validating!
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaChoice.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaChoice.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaChoice.java	(revision 13666)
@@ -0,0 +1,23 @@
+package org.greenstone.gsdl3.gs3build.schema;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class SchemaChoice extends SchemaNode
+{
+	List alternatives;
+
+	public SchemaChoice(Element element) throws SchemaException
+	{
+		super(element);
+	}
+
+	protected List _allocate()
+	{	this.alternatives = new ArrayList();
+		return this.alternatives;
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaComplexType.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaComplexType.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaComplexType.java	(revision 13666)
@@ -0,0 +1,65 @@
+package org.greenstone.gsdl3.gs3build.schema;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class SchemaComplexType implements SchemaType
+{
+	public String name;
+	public List children;
+
+	public SchemaComplexType(Element element) throws SchemaException
+	{
+		this.name = element.getAttribute("name");
+		if (name == null)	
+		{ throw new SchemaException("Type defined without name");
+		}
+
+		this.children = new ArrayList();
+
+		NodeList childNodes = element.getChildNodes();
+		for (int i = 0; i < childNodes.getLength(); i ++) {
+			Node node = childNodes.item(i);
+
+			if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
+				String nodeName = node.getNodeName();
+
+				if (nodeName == null) {
+					continue;
+				}
+
+				nodeName = SchemaNode.getElementName(nodeName);
+				// a simple-based type
+				if (node.getNodeName().equals("simpleContent")) {
+					// we're really just a simple type with attributes - nothing more to do
+				}
+				// a complex-based type
+				else if (node.getNodeName().equals("complexContent")) {
+					// we just contain elements, no text
+				}
+				// the following pretty much speak for themselves
+				else {
+					try {
+						Object child = SchemaNodeFactory.makeNode((Element) node);
+						if (child != null) {
+							this.children.add(child);
+						}
+					}
+					catch (SchemaException ex)
+					{	
+					}
+				}
+			}
+		}
+
+		SchemaTypeMap.theMap.addType(this);
+	}
+	
+	public String getName()
+	{	return this.name;
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaElement.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaElement.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaElement.java	(revision 13666)
@@ -0,0 +1,104 @@
+package org.greenstone.gsdl3.gs3build.schema;
+
+import java.util.*;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class SchemaElement
+{ 
+	// the following may contain duplicates when compared to SchemaAttribute, but this is
+	// deliberate...
+	public static final String ELEMENT_TYPE_STRING = "String";
+
+  String name;
+	String type;
+  List   attributes;
+  List   childElements;
+	int    minOccurs;
+	int    maxOccurs;
+
+	public SchemaElement(Element element)
+	{
+		// get the name of this element
+		this.name = element.getAttribute("name");
+		if (this.name == null) {
+			// TODO: this is a reference object
+			String ref = element.getAttribute("ref");
+
+			if (ref != null) {
+				// TODO: fetch the actual object
+			}
+			else {
+				// TODO: abort
+			}
+		}
+
+		this.type = element.getAttribute("type");
+		if (this.type == null || this.type.length() == 0)
+		{ this.type = SchemaElement.ELEMENT_TYPE_STRING;
+		}
+
+		String temp;
+		temp = element.getAttribute("minOccurs");
+		if (temp != null && temp.length() > 0) {
+			this.minOccurs = Integer.parseInt(temp);
+			this.minOccurs = 1;
+		}
+		temp = element.getAttribute("maxOccurs");
+		if (temp != null && temp.length() > 0) {
+			this.maxOccurs = Integer.parseInt(temp);
+		}
+		else {
+			this.maxOccurs = 1;
+		}
+
+		this.expand(element);
+	}
+
+	private void expand(Element element)
+	{ // TODO
+		// get the first child element
+		NodeList children = element.getChildNodes();
+		if (children != null) {
+			for (int i = 0; i < children.getLength(); i ++)
+			{ if (children.item(i).getNodeType() != org.w3c.dom.Node.ELEMENT_NODE) {
+					// TODO: raise an error
+					continue;
+				}
+
+				String name = children.item(i).getNodeName();
+				if (name == null) {
+					continue;
+				}
+				
+				try {
+					Object child = SchemaNodeFactory.makeNode((Element) children.item(i));
+					if (child != null) {
+						this.childElements.add(child);
+					}
+				}
+				catch (SchemaException ex)
+				{
+				}
+			}
+		}
+	}
+
+  public SchemaElement(String name)
+  { this.name = name;
+    this.attributes = new ArrayList();
+    this.childElements = new ArrayList();
+  }
+
+  public void addAttribute(SchemaAttribute attribute)
+  {
+	  this.attributes.add(attribute);
+  }
+
+    public void addElement(SchemaElement element)
+    {
+			this.childElements.add(element);
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaException.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaException.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaException.java	(revision 13666)
@@ -0,0 +1,9 @@
+package org.greenstone.gsdl3.gs3build.schema;
+
+public class SchemaException extends Exception
+{
+	public SchemaException(String name)
+	{
+		super(name);
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaGroup.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaGroup.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaGroup.java	(revision 13666)
@@ -0,0 +1,21 @@
+package org.greenstone.gsdl3.gs3build.schema;
+
+import org.w3c.dom.Element;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class SchemaGroup extends SchemaNode
+{
+	List members;
+
+  public SchemaGroup(Element element) throws SchemaException
+  {
+		super(element);
+  }
+
+	public List _allocate()
+	{	this.members = new ArrayList();
+		return this.members;
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaNode.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaNode.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaNode.java	(revision 13666)
@@ -0,0 +1,68 @@
+package org.greenstone.gsdl3.gs3build.schema;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.util.List;
+
+public abstract class SchemaNode
+{
+	public SchemaNode(Element element) throws SchemaException
+	{	List childList = this._allocate();
+		this.initialise(element, childList);
+		System.out.println(element.getNodeName());
+	}
+	
+	abstract protected List _allocate();
+
+	protected void initialise(Element element, List childList) throws SchemaException
+	{
+		// TODO: check minimum, maximum occurrences etc.
+
+		NodeList children = element.getChildNodes();
+		if (children != null) {
+			System.out.println("  " + children.getLength() + " children");
+			for (int i = 0; i < children.getLength(); i ++)
+			{ if (children.item(i).getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
+					Node child = children.item(i);
+
+					String type = child.getNodeName();
+					System.out.println("Child is " + type);
+
+					if (type == null) {
+						throw new SchemaException("Badly defined child - no name");
+					}
+
+					type = SchemaNode.getElementName(type);
+
+					if (type.equals("element")) {
+						SchemaElement elementChild = new SchemaElement((Element) children.item(i));
+						childList.add(elementChild);
+					}
+					else {
+						Object elementChild = SchemaNodeFactory.makeNode((Element) child);
+						if (elementChild != null) {
+							childList.add(elementChild);
+						}
+					}
+					// TODO: do an abstraction between here and SchemaElement
+				}
+			}
+		}
+	}
+
+	public static String getElementName(String fullname)
+	{	if (fullname.indexOf(':') >= 0) {
+			return fullname.substring(fullname.indexOf(':') + 1);
+		}
+		return fullname;
+	}
+
+	public static String getNamespace(String fullname)
+	{	if (fullname.indexOf(':') >= 0) {
+			return fullname.substring(0, fullname.indexOf(':'));
+		}
+		return null;
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaNodeFactory.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaNodeFactory.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaNodeFactory.java	(revision 13666)
@@ -0,0 +1,33 @@
+package org.greenstone.gsdl3.gs3build.schema;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+public class SchemaNodeFactory
+{
+	public static Object makeNode(Element element) throws SchemaException
+	{
+		String elementName = element.getNodeName();
+
+		System.out.println("Element name " + elementName);
+
+		elementName = SchemaNode.getElementName(elementName);
+
+		if (elementName.equals("choice")) {			
+			return new SchemaChoice(element);
+		}
+		else if (elementName.equals("group")) {
+			return new SchemaGroup(element);
+		}
+		else if (elementName.equals("all")) {
+			return new SchemaAll(element);
+		}
+		else if (elementName.equals("sequence")) {
+			return new SchemaSequence(element);
+		}
+		else if (elementName.equals("element")) {
+			return new SchemaElement(element);
+		}
+		return null;
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaParser.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaParser.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaParser.java	(revision 13666)
@@ -0,0 +1,73 @@
+package org.greenstone.gsdl3.gs3build.schema;
+
+import java.io.*;
+
+import javax.xml.parsers.*;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+public class SchemaParser
+{
+	public SchemaParser(File file, String namespace)
+	{
+	  try {
+			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+			DocumentBuilder builder = factory.newDocumentBuilder();
+			Document document = builder.parse(file);
+
+			// TODO: get all the types in the tree
+
+			// TODO: do a traverse, and thus cope with elements-within-elements if needsbe, but
+			// this shouldn't happen except in a directly defined situation - actually doing the
+			// parsing in part inside each node would work well provided one checked for a node
+			// having already been done...
+			System.out.println("Read");
+
+			NodeList schemas = document.getElementsByTagName("xs:schema");
+			if (schemas.getLength() == 0) {
+				schemas = document.getElementsByTagName("xsd:schema");
+			}
+			if (schemas.getLength() == 0) {
+				schemas = document.getElementsByTagName("schema");
+			}
+
+			System.out.println(" " + schemas.getLength() + " schemas");
+
+			for (int s = 0; s < schemas.getLength(); s ++) {
+				Schema schema = new Schema(schemas.item(s));
+			}
+		}
+		catch (FactoryConfigurationError e) {
+			System.out.println(e);
+		}
+		catch (ParserConfigurationException ex) {
+			System.out.println(ex);
+		}
+		catch (SAXException ex) {
+			System.out.println(ex);
+		}
+		catch (IOException ex) {
+			System.out.println(ex);
+		}
+	}
+
+	public static void main(String args[])
+	{	try
+		{	File file = new File(args[0]);
+
+			SchemaParser parser = new SchemaParser(file, "");			
+		}
+		catch (Exception ex)
+		{ System.out.println(ex);
+		}
+		return;
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaRefMap.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaRefMap.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaRefMap.java	(revision 13666)
@@ -0,0 +1,22 @@
+package org.greenstone.gsdl3.gs3build.schema;
+
+import java.util.HashMap;
+
+public class SchemaRefMap
+{
+	HashMap map;
+
+	public SchemaRefMap()
+	{
+		this.map = new HashMap();
+	}
+
+	public void addItem(String reference, Object item)
+	{
+		this.map.put(reference, item);
+	}
+
+	public Object getItem(String reference)
+	{	return this.map.get(reference);
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaSequence.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaSequence.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaSequence.java	(revision 13666)
@@ -0,0 +1,20 @@
+package org.greenstone.gsdl3.gs3build.schema;
+
+import org.w3c.dom.Element;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class SchemaSequence extends SchemaNode
+{
+	List sequence;
+
+	public SchemaSequence(Element element) throws SchemaException
+	{	super(element);
+	}
+
+	public List _allocate()
+	{	this.sequence = new ArrayList();
+		return this.sequence;
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaSimpleType.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaSimpleType.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaSimpleType.java	(revision 13666)
@@ -0,0 +1,30 @@
+package org.greenstone.gsdl3.gs3build.schema;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class SchemaSimpleType implements SchemaType
+{
+	String name;
+
+	public void SchemaSimpleType(Element element) throws SchemaException
+	{
+		this.name = element.getAttribute("name");
+		if (name == null)	
+		{ throw new SchemaException("Type defined without name");
+		}
+
+		NodeList childNodes = element.getChildNodes();
+		for (int i = 0; i < childNodes.getLength(); i ++) {
+			Node node = childNodes.item(i);
+
+			if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
+			}
+		}
+	}
+
+	public String getName()
+	{	return this.name;
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaType.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaType.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaType.java	(revision 13666)
@@ -0,0 +1,6 @@
+package org.greenstone.gsdl3.gs3build.schema;
+
+public interface SchemaType
+{
+	public String getName();
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaTypeMap.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaTypeMap.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/schema/SchemaTypeMap.java	(revision 13666)
@@ -0,0 +1,26 @@
+package org.greenstone.gsdl3.gs3build.schema;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class SchemaTypeMap
+{
+	Map map;
+	public static final SchemaTypeMap theMap;
+
+	static {
+		theMap = new SchemaTypeMap();
+	}
+
+	public SchemaTypeMap()
+	{	this.map = new HashMap();
+	}
+
+	public void addType(SchemaType type)
+	{	this.map.put(type.getName(), type);
+	}
+
+	public SchemaType getType(String name)
+	{	return (SchemaType) this.map.get(name);
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/DOMUtils.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/DOMUtils.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/DOMUtils.java	(revision 13666)
@@ -0,0 +1,37 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+public class DOMUtils
+{
+  public static String getNodeAttribute(Node node, String attribute)
+  {
+    NamedNodeMap atts = node.getAttributes();
+    if (atts == null) {
+      return null;
+    }
+    Node attributeNode = atts.getNamedItem(attribute);
+    if (attributeNode == null) {
+      return null;
+    }
+    return attributeNode.getNodeValue();
+  }
+    
+  public static String getNodeChildText(Node node)
+  {
+    StringBuffer fieldName = new StringBuffer();
+
+    NodeList fieldChildren = node.getChildNodes();
+    for (int f = 0; f < fieldChildren.getLength(); f ++) {
+      if (fieldChildren.item(f).getNodeType() == org.w3c.dom.Node.TEXT_NODE) {
+	fieldName.append(fieldChildren.item(f).getNodeValue());
+      }
+    }
+    return fieldName.toString();
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/FileTrie.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/FileTrie.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/FileTrie.java	(revision 13666)
@@ -0,0 +1,145 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+
+public class FileTrie
+{	String   stem;
+	List     childTries;
+	List     childDocs;
+	FileTrie parent;
+
+	public FileTrie(String stem)
+	{	this.childTries = new ArrayList();
+		this.childDocs  = new ArrayList();
+		this.stem = stem;
+		this.parent = null;
+	}
+
+	public void setParent(FileTrie trie)
+	{	this.parent = trie;
+	}
+
+	public FileTrie getParent()
+	{	return this.parent;
+	}
+
+	public void addChild(FileTrie trie)
+	{	trie.setParent(this);
+		this.childTries.add(trie);
+	}
+
+	public void replaceChild(FileTrie oldChild, FileTrie newChild)
+	{	for (int i = 0; i < this.childTries.size(); i ++)
+		{	FileTrie thisChild = (FileTrie) this.childTries.get(i);
+			if (thisChild == oldChild)
+			{	this.childTries.set(i, newChild);
+				return;
+			}
+		}
+	}
+
+	public void addDocument(DocumentID documentID)
+	{	this.childDocs.add(documentID);
+	}
+
+	public boolean postDocument(String filename, DocumentID documentID)
+	{	int common = 0;
+		int i;
+		
+		while (common < filename.length() &&
+		       common < this.stem.length() &&
+					  filename.charAt(common) == stem.charAt(common))
+		{	common ++;
+		}
+
+		if (common == 0)
+		{ return false;
+		}
+
+		if (common == this.stem.length())
+		{	// post it in this node
+			filename = filename.substring(this.stem.length());
+
+			// select which sub-trie to attempt...
+			for (i = 0; i < this.childTries.size(); i ++)
+			{	FileTrie child = (FileTrie) this.childTries.get(i);
+				
+				if (child.postDocument(filename, documentID))
+				{	break;
+				}
+			}
+
+			if (i == this.childTries.size())
+			{ FileTrie newChild = new FileTrie(filename);
+				this.addChild(newChild);
+
+				newChild.addDocument(documentID);
+			}
+		}
+		else
+		{	// divide this node at the 'common' point...
+			FileTrie parentTrie = new FileTrie(this.stem.substring(0, common));
+			this.parent.replaceChild(this, parentTrie);
+
+			// truncate our root
+			this.stem = this.stem.substring(common);
+
+			// add ourselves to our new parent
+			parentTrie.addChild(this);
+
+			// trim back the file name
+			filename = filename.substring(common);
+
+			// recurse into posting the document
+			this.postDocument(filename, documentID);
+		}
+		return true;
+	}
+
+	public boolean postFile(String filename)
+	{	return this.postDocument(filename, null);
+	}
+
+	public List getDocuments(String filename)
+	{	FileTrie leaf = this.getNode(filename);
+		return leaf.childDocs;
+	}
+
+	public FileTrie getNode(String filename)
+	{	int common = 0;
+		int i;
+		
+		while (common < filename.length() &&
+		       common < this.stem.length() &&
+					 filename.charAt(common) == stem.charAt(common))
+		{	common ++;
+		}
+
+		if (common == 0)
+		{ return null;
+		}
+
+		if (common == this.stem.length())
+		{	if (common == filename.length())
+			{	return this;
+			}
+
+			filename = filename.substring(this.stem.length());
+
+			// select which sub-trie to attempt...
+			for (i = 0; i < this.childTries.size(); i ++)
+			{	FileTrie child = (FileTrie) this.childTries.get(i);
+				
+				child = child.getNode(filename);
+
+				if (child != null)
+				{	return child;
+				}
+			}
+		}
+		return null;
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/GS2TextFileHandler.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/GS2TextFileHandler.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/GS2TextFileHandler.java	(revision 13666)
@@ -0,0 +1,111 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+public class GS2TextFileHandler
+{
+  String  content;
+  String  line;
+
+  public GS2TextFileHandler(String content)
+  { this.content = content;
+  }
+    
+  public boolean hasMore()
+  { return this.line != null;
+  }
+
+  public boolean hasMoreLines()
+  { return this.content != null;
+  }
+
+  public String getEntry()
+  { return this.getEntry(false);
+  }
+
+  public String getEntry(boolean breakSpace)
+  { String reply;
+    int start, tab = 0;
+    boolean quoted = false;
+
+    if (!this.hasMore()) {
+      return null;
+    }
+
+    start = 0;
+    while (start < this.line.length() &&
+	   this.line.charAt(start) == ' ') {
+      start ++;
+    }
+
+    if (start == this.line.length()) {
+      this.line = null;
+      return null;
+    }
+    
+    if (this.line.charAt(start) == '"') {
+      quoted = true;
+      breakSpace = false;
+      start ++;
+    }
+    tab = start;
+
+    while (tab != this.line.length() &&
+	   this.line.charAt(tab) != '\t' &&
+	   !(quoted && this.line.charAt(tab) == '"') &&
+	   !(this.line.charAt(tab) == ' ' && breakSpace))
+    { tab ++;
+    }
+
+    if (start > 0) {
+      this.line = this.line.substring(start);
+      tab -= start;
+    }
+    
+    if (tab == this.line.length()) {
+      reply = this.line;
+      this.line = null;
+    }
+    else {
+      reply = this.line.substring(0, tab);
+      this.line = this.line.substring(tab+1);
+    }
+
+    reply.trim();
+    
+    return reply;
+  }
+
+  public String getLine()
+  { if (this.content == null) {
+      this.line = null;
+      return null;
+    }
+	
+    do {
+      int eol = this.content.indexOf('\n');
+      if (eol < 0) {
+	this.line = this.content;
+	this.content = null;
+      }
+      else {
+	this.line = this.content.substring(0, eol);
+	this.content = this.content.substring(eol+1);
+	while (this.content.length() > 0 &&
+	       this.content.charAt(0) < ' ')
+	{ this.content = this.content.substring(1);
+	}
+      }
+
+      if (this.line != null) {
+	this.line.trim();
+      }
+      if (this.line.length() > 0 &&
+	  this.line.charAt(this.line.length() - 1) == (char) 13) {
+	this.line = this.line.substring(0, this.line.length()-1);
+	this.line.trim();
+      }
+    } while (this.content != null && this.line != null && this.line.length() == 0);
+    
+    return this.line;
+  }
+}
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLBlock.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLBlock.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLBlock.java	(revision 13666)
@@ -0,0 +1,383 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+import java.util.*;
+
+public class HTMLBlock
+{
+    Vector content;
+    int    tagpos;
+    int    endpos;
+
+    public HTMLBlock(int docpos)
+    { 
+	this.content = new Vector(1);
+	this.tagpos  = docpos;
+    }
+    
+    public HTMLBlock(int docpos, int endpos)
+    { 
+	this.content = new Vector(1);
+	this.tagpos  = docpos;
+	this.endpos  = endpos;
+    }
+
+    public void addTag(HTMLTag tag)
+    { 
+	if (tag.endPos() > this.endpos){
+	    this.endpos = tag.endPos();
+	}
+	content.addElement(tag);
+    }
+
+    /**
+     *  @deprecccate
+     public void addText(String text)
+     { content.addElement(text);
+     }
+    */
+
+    public void addText(HTMLCText text)
+    { 
+	if (text.endPos() > this.endpos){
+	    this.endpos	= text.endPos();
+	}
+	content.addElement(text);
+    }
+    
+    /**
+     * @return HTML encoded <code>String</code> of the document
+     */
+    public String contentString()
+    { 
+	int member;
+	StringBuffer reply;
+	String type;
+	
+	reply = new StringBuffer();
+	for (member = 1; member < content.size() - 1; member ++){
+	    /*if (content.elementAt(member) instanceof String){
+	      reply.append((String) content.elementAt(member));
+	      }
+	      else 
+	  */
+	    if (content.elementAt(member) instanceof HTMLCText){
+		reply.append(((HTMLCText) content.elementAt(member)).toString());
+	    }
+	}
+	return reply.toString();
+    }
+    
+    /**
+     * Returns document position of start of the block
+     */
+    public int startPos()
+    { 
+	return this.tagpos;
+    }
+
+    /**
+     * Returns document position of end of the block
+     */
+    public int endPos()
+    { 
+	return this.tagpos;
+    }
+
+    /**
+     * @return head (first) tag of the block
+     */
+    public HTMLTag headTag()
+    { 
+	return ((HTMLTag) content.elementAt(0));
+    }
+
+    /**
+     * @return name (as a <code>String</code>) of the tag at the head of the block
+     */
+    public String headTagName()
+    { 
+	return ((HTMLTag) content.elementAt(0)).tagName();
+    }
+
+    /**
+     * @return name of the tail (last) tag of the block as a <code>String</code>
+     */
+    public String tailTagName()
+    { 
+	return (((HTMLTag) content.elementAt(content.size() - 1)).tagName());
+    }
+	
+	
+    /**
+     *  @return: starting element character position of the item-th item
+     */
+    private int elementStartPos(int item)
+    { 
+	Object element;
+	int	pos = -1;
+		
+	element = this.content.elementAt(item);
+	if (element instanceof HTMLTag){
+	    pos	= ((HTMLTag) element).startPos();
+	}
+	else if (element instanceof HTMLCText){
+	    pos	= ((HTMLCText) element).startPos();
+	}
+	return pos;		
+    }
+    
+    /**
+     *  @return: ending element character position of the item-th item
+     */
+    private int elementEndPos(int item)
+    { 
+	Object	element;
+	int		pos = -1;
+	
+	element = this.content.elementAt(item);
+	if (element instanceof HTMLTag){
+	     pos = ((HTMLTag) element).endPos();
+	}
+	else if (element instanceof HTMLCText){
+	     pos = ((HTMLCText) element).endPos();
+	}
+	return pos;		
+    }
+
+    /**
+     *  @return the HTMLBlock of the indicated subitems
+     */
+    public HTMLBlock subBlock(int startitem, int enditem)
+    { 
+	int       i;
+	Object    element;
+	HTMLBlock reply;
+	reply = new HTMLBlock(this.elementStartPos(startitem),
+			      this.elementEndPos(enditem-1));
+	// copy all the bits
+	for (i = startitem; i < enditem; i++){
+	    element = this.content.elementAt(i);
+	    if (element instanceof HTMLTag){
+		reply.addTag((HTMLTag) element);
+	    }
+	    else if (element instanceof HTMLCText){
+		reply.addText((HTMLCText) element);
+	    }
+	/*
+	  else if (element instanceof String)
+	  {	reply.addText((String) element);
+	  }
+	*/
+	}
+	return reply;
+    }
+
+    /**
+     * Return the position of the given <code>HTMLBlock</code> within this block
+     * @return the tag index of the child block; or < 0 if not a chile
+     */
+    public int find(HTMLBlock subblock)
+    { 
+	int start, end, at, attag;
+	HTMLTag tag;
+	
+	start = 0;
+	end = this.content.size();
+	while (start != end){
+	     /* compare positions */
+	    at = (start + end) / 2;
+	    attag = at;
+	    while (attag < end &&
+		   (content.elementAt(attag) instanceof HTMLTag) == false){
+		attag ++;
+	    }
+	    
+	    if (attag == end){
+		end = at;
+		continue;
+	    }
+	    tag =	(HTMLTag) content.elementAt(attag);
+	    if (tag.startPos() > subblock.startPos()){
+		end = at;				
+	    }
+	    else if (tag.startPos() < subblock.startPos()){
+		start = attag + 1;
+	    }
+	    else { 
+		return attag;
+	    }
+	}
+	return -1;
+    }
+    
+    /**
+     * @return The raw HTML of the block
+     */
+    public String HTMLString()
+    { 
+	int loop;
+	StringBuffer reply;
+
+	reply	= new StringBuffer();
+	for (loop = 0; loop < this.content.size(); loop ++){
+	    /*
+	      if (content.elementAt(loop) instanceof String)
+	      {	reply.append((String) content.elementAt(loop));
+	      }
+	      else 
+	    */
+	    if (content.elementAt(loop) instanceof HTMLCText){
+		reply.append(((HTMLCText) content.elementAt(loop)).toString());
+	    }
+	    else if (content.elementAt(loop) instanceof HTMLTag){
+		reply.append(((HTMLTag) content.elementAt(loop)).toString());
+	    }
+	}
+	return reply.toString();
+    }
+    
+    /**
+     * @return The text of the block - no HTML tags.  If no text is present, any
+     *         <code>alt</code> information for <code>img</code> tags will be given 
+     *         instead
+     */
+    public String toString()
+    {
+	int member;
+	StringBuffer reply;
+	StringBuffer ireply;
+	
+	reply = new StringBuffer("");
+	ireply = new StringBuffer("");
+	for (member = 0; member < content.size(); member ++){
+	     /*if (content.elementAt(member) instanceof String)
+	       { reply.append((String) content.elementAt(member));
+	       }
+	     */
+	    if (content.elementAt(member) instanceof HTMLCText){
+		reply.append(((HTMLCText) content.elementAt(member)).toString());
+	    }
+	    else if (content.elementAt(member) instanceof HTMLTag){
+		if (((HTMLTag) content.elementAt(member)).tagName().equals("img")){
+		    ireply.append(((HTMLTag) content.elementAt(member)).idValue("alt"));
+		}
+	    }
+	}
+	reply = HTMLCText.cleanString(reply);
+	ireply = HTMLCText.cleanString(ireply);
+	//		reply = reply.trim();
+	if (reply == null || reply.length() == 0){
+	    return ireply.toString();
+	}
+	return reply.toString();
+    }
+    
+    public HTMLObject elementAt(int at)
+    { 
+	return (HTMLObject) this.content.elementAt(at);
+    }
+
+    /**
+     * @return the number of elements in the block
+     */
+    public int size()
+    { 
+	return this.content.size();
+    }
+
+    /**
+     * @return an enumeration of all elements in the block
+     */
+    public Enumeration elements()
+    { 
+	Enumeration enumer;
+  
+	enumer = new HTMLBlockEnumerator(this);
+	return enumer;
+    }
+
+    /**
+     * @return an enumeration of all tags in the block
+     */
+    public Enumeration tagElements()
+    { 
+	Enumeration enumer;
+	
+	enumer = new HTMLBlockTagEnumerator(this);
+	return enumer;
+    }
+
+    /**
+     * Finalization method
+     */
+    protected void finalize() throws Throwable
+    { 
+	this.content	= null;
+	super.finalize();
+    }
+}
+
+final class HTMLBlockEnumerator implements Enumeration
+{ 
+    private HTMLBlock block;
+    int			member;
+
+    public HTMLBlockEnumerator(HTMLBlock block)
+    { 
+	this.block	= block;
+	this.member	= 0;
+    }
+
+    public Object nextElement()
+    { 
+	Object element;
+
+	element = this.block.content.elementAt(member);
+	member ++;
+	return element;
+    }
+
+    public boolean hasMoreElements()
+    {
+	if (block == null || this.member == this.block.content.size()){
+	    return false;
+	}
+	return true;
+    }
+}
+
+final class HTMLBlockTagEnumerator implements Enumeration
+{
+    private HTMLBlock block;
+    int	member;
+    
+    public HTMLBlockTagEnumerator(HTMLBlock block)
+    { 
+	this.block = block;
+	this.member = 0;
+	while ( this.member < this.block.content.size() &&
+		this.block.content.elementAt(this.member) instanceof HTMLTag == false){
+	    this.member ++;
+	}
+    }
+
+    public Object nextElement()
+    { 
+	Object element;
+	
+	element = this.block.content.elementAt(member);
+	do {
+	    member ++;
+	} while (this.block.content.elementAt(member) instanceof HTMLTag == false);
+	return element;
+    }
+    
+    public boolean hasMoreElements()
+    { 
+	if (block == null || this.member == this.block.content.size()){
+	    return false;
+	}
+	return true;
+    }
+}
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLBlockList.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLBlockList.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLBlockList.java	(revision 13666)
@@ -0,0 +1,409 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+import java.util.*;
+
+public class HTMLBlockList
+{ Vector blocks;
+	String title;
+	protected static HTMLTagVector anchorStartTags;
+	protected static HTMLTagVector anchorEndTags;
+	protected static HTMLTagVector anchorOptEndTags;
+	protected static HTMLTagVector headingStartTags;
+	protected static HTMLTagVector headingEndTags;
+
+	static
+	{	anchorStartTags 	= new HTMLTagVector("a");
+		anchorEndTags			= new HTMLTagVector("a,h1,h2,h3,h4,h5,h6,table,hr,p,ul,ol,dl,dt,dd,li,tr,td,th,map");
+		anchorOptEndTags 	= new HTMLTagVector("div,center,form");
+		headingStartTags 	= new HTMLTagVector("h1,h2,h3,h4,h5,h6");
+		headingEndTags	 	= new HTMLTagVector("h1,h2,h3,h4,h5,h6,table,hr,p,ul,ol,dl,dt,dd,li,tr,td,th,map");
+	}
+
+	// opening   opentag  incontent	result
+	//    T					T					T				*       {if opening, incontent must be false}
+	//    T					T					F				T
+	//    T					F					T				*       {if opening, incontent must be false}
+	//    T					F					F				F
+	//    F					T					T				T
+	//    F					T					F				F				{if getting an opening tag
+	//		F					F					T				T
+	//		F					F					F				T
+	private boolean inTagList(HTMLTag tag, Vector tags, boolean opening)
+	{ int tagref;
+
+		for (tagref = 0; tagref < tags.size(); tagref ++)
+		{ if ((tag.xtagName().equals((String) tags.elementAt(tagref))) &&
+		      (tag.tagIsOpening() || !opening))
+			{ return true;
+			}
+		}
+		return false;
+	}
+
+	//
+	// Common initialisation; parse the document for text surrounded by
+	// pairs of <starttag>....<endtag/starttag> combos
+	//
+	protected void initialise(HTMLDoc doc, HTMLTagVector starttags, HTMLTagVector endtags, HTMLTagVector optendtags)
+	{ boolean intag;
+		boolean incontent;
+		HTMLCText		text;
+		HTMLTag			tag;
+		HTMLTag 		starttag;
+		HTMLBlock 	block;
+		HTMLBlock		docBlock;
+		Enumeration	elements;
+		Object			element;
+
+		this.blocks = new Vector(1);
+		block				= null;
+		intag				= false;
+		incontent		= false;
+		starttag		= null;
+
+		docBlock		= doc.getCodedContent();
+		elements		= docBlock.elements();
+
+		while (elements.hasMoreElements())
+		{ element	= elements.nextElement();
+
+			// if it's a tag
+			if (element instanceof HTMLTag)
+			{ tag = (HTMLTag) element;
+			
+				// end the fragment if getting a closing tag
+				if (intag)
+				{ if (endtags.matches(tag, false) ||
+							(incontent && optendtags.matches(tag, false)))
+					{ block.addTag(starttag.endTag());
+						intag = false;
+						incontent = false;
+					}
+					else
+					{ block.addTag(tag);
+					}
+				}
+
+				// !intag is checked for explicitly, as it may have been
+				// switched off by a non-partner opening tag above: eg:
+				//   <H2>A Heading<H3>A Smaller Heading</H3>
+				//                ^^^^
+				//                here
+
+				// start fragment if the tag is a starter
+				if (!intag)
+				{ if (starttags.matches(tag, true))
+					{ block = new HTMLBlock(tag.startPos(), tag.endPos());
+						this.blocks.addElement((Object) block);
+						block.addTag(tag);
+						starttag = tag;
+						intag = true;
+						incontent = false;
+					}
+				}
+			}	
+			// if the parse returned text
+			else
+			{ text	= (HTMLCText) element;
+
+				if (intag)
+				{ block.addText(text);
+					if (!text.nullString())
+					{ incontent = true;
+					}
+				}
+			}
+		}
+
+		// if a tag wasn't "finished");
+		if (intag)
+		{ block.addTag(starttag.endTag());
+		}
+
+		this.title = doc.urlString();
+	}
+
+	protected HTMLBlockList()
+	{
+	}
+	
+	//
+	// constructor for given vectors of tags: startlist elements always start a new
+	// block [ending an open one if necessary]; endlist elements always end an open 
+	// block; optendlist elements close a block iff a block has been started, and
+	// some non-blank content (ie. some "real" text, not just returns/spaces) has
+	// been read since the beginning of the block
+	//
+	public HTMLBlockList(HTMLDoc doc, Vector starttags, Vector endtags, Vector optendtags)
+	{ HTMLTagVector _starttags;
+		HTMLTagVector _endtags;
+		HTMLTagVector _optendtags;
+
+		_starttags	= new HTMLTagVector(starttags);
+		_endtags		= new HTMLTagVector(starttags);
+		_optendtags	= new HTMLTagVector(starttags);
+		this.initialise(doc, _starttags, _endtags, _optendtags);
+	}
+	
+	//
+	// constructor for explicit lists; a tagVector is created for each list;
+	// see above for list roles
+	//
+	public HTMLBlockList(HTMLDoc doc, String startlist, String endlist, String optendlist)
+	{ HTMLTagVector starttags;
+		HTMLTagVector endtags;
+		HTMLTagVector optendtags;
+
+		starttags		= new HTMLTagVector(startlist);
+		endtags			= new HTMLTagVector(endlist);
+		optendtags	= new HTMLTagVector(optendlist);
+		this.initialise(doc, starttags, endtags, optendtags);
+	}
+
+	//
+	// constructor; get all HTMLBlocks for h{level} through to h1;
+	// eg hlevel==3 test h3,h2,h1
+	//
+	public HTMLBlockList(HTMLDoc doc, int hlevel)
+	{ int loop;
+		StringBuffer levelstring;
+		HTMLTagVector starttags;
+		HTMLTagVector endtags;
+		HTMLTagVector optendtags;
+
+		levelstring = new StringBuffer("h1");
+		for (loop = 2; loop <= hlevel; loop ++)
+		{ levelstring.append(",h");
+		  levelstring.append(Integer.toString(loop));
+		}
+
+		starttags		= new HTMLTagVector(levelstring.toString());
+		levelstring.append(",table,hr,p,ul,ol,dl,dt,dd,li,tr,td,th,map");
+		endtags			= new HTMLTagVector(levelstring.toString());
+		optendtags	= new HTMLTagVector("div,center,form");
+
+		this.initialise(doc, starttags, endtags, optendtags);
+	}
+
+	/**
+	 * Static method returning list of anchors of a document
+	 */
+	public static synchronized HTMLBlockList anchorlist(HTMLDoc doc)
+	{ HTMLBlockList anchors;
+		HTMLTagVector starttags;
+		HTMLTagVector endtags;
+		HTMLTagVector optendtags;
+
+		anchors = new HTMLBlockList();
+
+		anchors.initialise(doc, anchorStartTags, anchorEndTags, anchorOptEndTags);
+
+		return anchors;
+	}
+
+	//
+	// return how many tags are in the block list
+	//
+	public int size()
+	{ if (this.blocks == null)
+		{ return 0;
+		}
+
+		return this.blocks.size();
+	}
+
+	/**
+	 * @return number of blocks in the block list
+	 * @deprecated
+	 */
+	public int tagCount()
+	{	return this.size();
+	}
+
+	//
+	// return the position of the tag in the document
+	//
+	public int tagPos(int tag)
+	{ HTMLBlock block;
+
+		if (this.blocks == null)
+		{ return 0;
+		}
+		block = (HTMLBlock)	this.blocks.elementAt(tag);
+		return block.startPos();
+	}
+
+	//
+	// return the nth block in the list
+	//
+	public HTMLBlock tagBlock(int tag)
+	{ HTMLBlock block;
+
+		block = (HTMLBlock) this.blocks.elementAt(tag);
+		return block;
+	}
+
+	//
+	// return the index of the next blocklist of the same level
+	//
+	public int tagNext(int attag)
+	{ HTMLBlock block;
+		String		headTag;
+		int				nextTag;
+
+		block = (HTMLBlock) this.blocks.elementAt(attag);
+		headTag = block.headTagName();
+		nextTag	= attag+1;
+
+		while (nextTag < this.blocks.size())
+		{	block	=	(HTMLBlock) this.blocks.elementAt(nextTag);
+			if (block.headTagName().equals(headTag))
+			{	break;
+			}
+			nextTag ++;
+		}
+		return nextTag;
+	}
+
+	//
+	// return the number of children at the next heading level
+	// 
+	public int tagChildren(int fromtag, int level)
+	{ int sibling;
+		int descendent;
+		int children;
+		int	atlevel;
+		HTMLTag tag;
+
+		// get current tag level; level 6 headings cannot have
+		// children
+		if (level == 6)
+		{ return 0;
+		}
+
+		// now, if the next tag at this level is the next tag in
+		// the document, then we can't have any children
+		if (fromtag > 0)
+		{ sibling	= this.tagNext(fromtag-1);
+		}
+		else
+		{	sibling	= this.size();
+		}
+		if (sibling == fromtag)
+		{ children = 0;
+		}
+		// if the next tag at this level is *not* next, then we have
+		// at least one child (ie the next tag in sequence), even if
+		// it is not at the next heading level down.
+		//
+		// if no further children occur at the next level down, we
+		// have only one child.  If any further children occur at the
+		// next level down, then they are counted, except where it is
+		// the next tag in sequence, which is automatically accounted
+		// for
+		else
+		{	children	= 1;
+			for (descendent = fromtag+1; descendent < sibling; descendent ++)
+			{ tag	= this.tagBlock(descendent).headTag();
+				
+				if (tag.tagLevel() ==	level + 1)
+				{	children ++;
+				}
+			}
+		}
+		return children;
+	}
+
+
+	public int tagChildren(int attag)
+	{ int sibling;
+		int descendent;
+		int children;
+		int	atlevel;
+		HTMLTag tag;
+
+		// get current tag level; level 6 headings cannot have
+		// children
+		atlevel		=	this.tagBlock(attag).headTag().tagLevel();
+		if (atlevel == 6)
+		{ return 0;
+		}
+
+		// now, if the next tag at this level is the next tag in
+		// the document, then we can't have any children
+		sibling		= this.tagNext(attag);
+		if (sibling == attag + 1)
+		{ children = 0;
+		}
+		// if the next tag at this level is *not* next, then we have
+		// at least one child (ie the next tag in sequence), even if
+		// it is not at the next heading level down.
+		//
+		// if no further children occur at the next level down, we
+		// have only one child.  If any further children occur at the
+		// next level down, then they are counted, except where it is
+		// the next tag in sequence, which is automatically accounted
+		// for
+		else
+		{	children	= 1;
+			for (descendent = attag + 2; descendent < sibling; descendent ++)
+			{ tag	= this.tagBlock(descendent).headTag();
+				
+				if (tag.tagLevel() ==	atlevel + 1)
+				{	children ++;
+				}
+			}
+		}
+		return children;
+	}
+
+	//
+	// write out a structured output onto System.out
+	//
+  public void sysoutList()
+	{ int item;
+		HTMLBlock block;
+
+		if (this.blocks == null)
+		{ return;
+		}
+
+		for (item = 0; item < this.blocks.size(); item ++)
+		{ block = (HTMLBlock) this.blocks.elementAt(item);
+			System.out.println("  @"+ block.startPos()+":"+block.headTagName() +":"+ block);
+		}
+	}
+
+	//
+	// write out HTMLBlocks as an Enumeration
+	//
+	public Enumeration elements()
+	{ return new HTMLBlockListEnumerator(this);
+	}
+}
+
+final class HTMLBlockListEnumerator implements Enumeration
+{ private HTMLBlockList blocklist;
+	private int						member;
+
+	public HTMLBlockListEnumerator(HTMLBlockList blocklist)
+	{ this.blocklist	= blocklist;
+		this.member			= 0;
+	}
+
+	public Object nextElement()
+	{ Object element;
+
+		element = this.blocklist.blocks.elementAt(member);
+		member ++;
+		return element;
+	}
+
+	public boolean hasMoreElements()
+	{ if (this.blocklist == null || this.member == this.blocklist.blocks.size())
+		{ return false;
+		}
+		return true;
+	}
+}
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLCText.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLCText.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLCText.java	(revision 13666)
@@ -0,0 +1,105 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+public class HTMLCText implements HTMLObject
+{ String text;
+  int    start;
+  int    end;
+
+  public static final String HTML_TEXT_TYPE = "Text";
+
+  public HTMLCText(String text, int start, int end)
+  { this.text  = text;
+    this.start = start;
+    this.end   = end;
+  }
+
+  public String getHTMLType()
+  { return HTML_TEXT_TYPE;
+  }
+
+  public int startPos()
+  { return this.start;
+  }
+
+  public int endPos()
+  { return this.end;
+  }
+
+  public boolean isEmpty()
+  { return emptyString(this.text);
+  }
+
+  public static boolean emptyString(String s)
+  { int c;
+
+    for (c = 0; c < s.length(); c ++)
+    { if (s.charAt(c) > 32)
+      { return false;
+      }
+    }
+    return true;
+  }
+
+  public static StringBuffer cleanString(StringBuffer buffer)
+  { int c;
+    int w;
+
+    w = 0;	
+    for (c = 0; c < buffer.length(); c ++)
+    { if (buffer.charAt(c) >= 32)
+      { if (buffer.charAt(c) == 32)
+	{ if (w > 0 && buffer.charAt(w-1) > 32)
+	  { buffer.setCharAt(w, buffer.charAt(c));
+	    w ++;
+	  }
+	}
+        else
+	{ if (c != w)
+	  { buffer.setCharAt(w, buffer.charAt(c));
+	  }
+	  w ++;
+	}
+      }
+      else
+      { if (w > 0 && buffer.charAt(w-1) > 32)
+	{ buffer.setCharAt(w,' ');
+	  w ++;
+	}
+      }
+    }
+    buffer.setLength(w);
+    return buffer;
+  }
+
+  /**
+   * nullString; used by initialisation for checking for
+   * non-blank content (ie. text other than just spaces/returns)
+   * see constructor (ie HTMLBlockList) methods below for role of
+   * this in the larger plan of things
+   */
+  public boolean nullString()
+  { int ch;
+
+    if (text != null)
+    { for (ch = 0; ch < text.length(); ch ++)
+      { if (text.charAt(ch) > ' ')
+	{ return false;
+	}
+      }
+    }
+    return true;
+  }
+
+  public String toString()
+  { return this.text;
+  }
+
+  public String toString(boolean cleaned)
+  { if (cleaned == false)
+    { return toString();
+    }
+    else
+    { return HTMLEntity.decodeText(this.text);
+    }
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLContext.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLContext.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLContext.java	(revision 13666)
@@ -0,0 +1,201 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+public class HTMLContext
+{ boolean valid;
+	StringBuffer	text;
+	
+	public static	HTMLTagVector breakTags = new HTMLTagVector("a,h1,h2,h3,h4,h5,h6,table,hr,p,ul,ol,dl,dt,dd,li,tr,td,th,map");
+
+	private int offset (String string, int direction)
+	{	int offset;
+
+		if (direction > 0)
+		{	offset = string.indexOf('.');
+		}
+		else
+		{	offset = string.lastIndexOf('.');
+		}
+		return offset;
+	}
+
+	public HTMLContext(HTMLBlock parent, HTMLBlock child, int scope)
+	{ int pos;
+		int start, startoffset;
+		int	end, endoffset;
+		int	length;
+		String	string;
+		HTMLTag	tag;
+
+		this.text	= null;
+
+		// if we can't match it, give up!
+		pos = parent.find(child);
+		if (pos < 0)
+		{ this.valid	= false;
+			return;
+		}
+
+		// get start!
+		if (pos > 0)
+		{ start = pos - 1;
+		}
+		else
+		{	start	= 0;
+		}	
+		startoffset	= -1;
+		length	= 0;
+		while (	start > 0)
+		{	
+		  /*
+		  if (parent.elementAt(start) instanceof String)
+			{	string = (String) parent.elementAt(start);
+
+				startoffset	= offset(string, -1);
+				if (startoffset > 0)
+				{	break;
+				}
+
+				length += string.length();
+				
+				if (length >= scope)
+				{	break;
+				}
+				}
+				else 
+		  */
+			if (parent.elementAt(start) instanceof HTMLCText)
+			{	string = ((HTMLCText) parent.elementAt(start)).toString();
+
+				startoffset	= offset(string, -1);
+				if (startoffset > 0)
+				{	break;
+				}
+
+				length += string.length();
+
+				if (length >= scope)
+				{	break;
+				}
+			}
+			else if (parent.elementAt(start) instanceof HTMLTag)
+			{	// do some checks
+				tag = (HTMLTag) parent.elementAt(start);
+
+				if (breakTags.matches(tag, false))
+				{	startoffset	= -1;
+					break;
+				}
+			}
+			start --;
+		}
+
+		// get end!
+		pos = pos + child.size();
+		if (pos < parent.size())
+		{ end	= pos + 1;
+		}
+		else
+		{	end	= parent.size();
+		}	
+		endoffset	= -1;
+		length	= 0;
+		string	= null;
+		while (end < parent.size())
+		{	if (parent.content.elementAt(start) instanceof String)
+			{	string = (String) parent.content.elementAt(start);
+
+				endoffset	= offset(string, +1);
+				if (endoffset >= 0)
+				{	break;
+				}
+
+				length += string.length();
+
+				if (length >= scope)
+				{	break;
+				}
+			}
+			else if (parent.content.elementAt(start) instanceof HTMLCText)
+			{	string = ((HTMLCText) parent.content.elementAt(start)).toString();
+
+				endoffset	= offset(string, +1);
+				if (endoffset >= 0)
+				{	break;
+				}
+
+				length += string.length();
+
+				if (length >= scope)
+				{	break;
+				}
+			}
+			else if (parent.content.elementAt(start) instanceof HTMLTag)
+			{	tag = (HTMLTag) parent.elementAt(start);
+
+				if (breakTags.matches(tag, false))
+				{	endoffset	= -1;
+					end	= end - 1;
+					break;
+				}
+			}
+			System.out.println("String:"+string);
+			end ++;
+		}
+
+		this.text	= new StringBuffer();
+		if (startoffset >= 0)
+		{	string	= null;
+
+			if (parent.content.elementAt(start) instanceof String)
+			{	string = (String) parent.content.elementAt(start);
+			}
+			else if (parent.content.elementAt(start) instanceof HTMLCText)
+			{	string = ((HTMLCText) parent.content.elementAt(start)).toString();
+			}
+			
+			if (string != null)
+			{ this.text.append(string.substring(startoffset+1));
+			}
+			start ++;
+		}
+
+		for (pos = start; pos <= end; pos ++)
+		{ if (pos == end && endoffset >= 0)
+			{	break;
+			}
+
+			if (parent.content.elementAt(pos) instanceof String)
+			{	this.text.append((String) parent.content.elementAt(pos));
+			}
+			else if (parent.content.elementAt(pos) instanceof HTMLCText)
+			{	this.text.append(((HTMLCText) parent.content.elementAt(pos)).toString());
+			}
+			else if (parent.content.elementAt(pos) instanceof HTMLTag)
+			{ // don't add it!
+			}
+		}
+
+		if (pos == end && endoffset > 0)	// this deliberately ignore endoffset == 0
+																		 	// 'cos nothing should happen anyhow!
+		{	string	= null;
+
+			if (parent.content.elementAt(pos) instanceof String)
+			{	string = (String) parent.content.elementAt(pos);
+			}
+			else if (parent.content.elementAt(pos) instanceof HTMLCText)
+			{	string = ((HTMLCText) parent.content.elementAt(pos)).toString();
+			}
+		
+			if (string != null)
+			{	this.text.append(string.substring(0, endoffset));
+			}
+		}
+	}
+
+	public String toString()
+	{	if (this.text == null)
+		{ return "";
+		}
+		return this.text.toString();
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLDoc.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLDoc.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLDoc.java	(revision 13666)
@@ -0,0 +1,658 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+import java.net.*;
+import java.io.*;
+import java.applet.*;
+import java.util.*;
+
+/** 
+ *  HTMLDOC: handles an individual HTML document
+ */
+
+public class HTMLDoc
+{ 
+    String        content;
+    String        title;
+    URL           url;
+    int           pos;
+    int           status;
+    HTMLBlockList blocklist;
+    List          urls_out;
+    List          urls_in;
+    Object        note;
+    HTMLLoader    loader;
+    HTMLBlock     coded;
+
+    /**
+     * Constructor which loads a given document; the ref indicates from where!
+     */
+    public HTMLDoc(URL url, int ref)
+    { 
+	URLConnection connect;
+	int length, i, c;
+	byte inbuffer[];
+	InputStream in;
+
+	this.url = url;
+	this.pos = 0;
+	this.blocklist = null;
+	this.title = null;
+	this.urls_out = null;
+	this.urls_in = null;
+	this.note = null;
+	this.status = 0;
+
+	if (ref >= 0){
+	    int attempts;
+	    
+	    attempts = 0;
+	    loader = new HTMLLoader(url);
+	    loader.load();
+	    if (ref == 0){
+		while(this.ready() == false){
+		    try {
+			Thread.sleep(100);
+		    }
+		    catch (InterruptedException ex){
+			
+		    }
+		}
+	    }
+	}
+	else {
+	    this.content = "";
+	}
+    }
+    
+    public HTMLDoc(URL url)
+    {	
+	this(url, 0);
+    }
+    
+    /**
+     * @return <code>true</code> when a document has finished loading.
+     */
+    public synchronized boolean ready()
+    {
+	if (this.loader == null){
+	    return true;
+	}
+	
+	boolean loaded 	= loader.loaded();
+	
+	if (loaded == true){
+	    // reload if necessary
+	    if (this.loader.error == true){
+		if (this.status < 3 && this.loader.notFound == false){
+		    this.status ++;
+		    this.loader = new HTMLLoader(this.url);
+		    loader.load();
+		    return false;
+		}
+		else {
+		    this.status 	= 4;
+		    this.content	= null;
+		    this.loader		= null;
+		    return true;
+		}
+	    }
+	    this.content 	= loader.HTML();
+	    this.loader		= null;
+	}
+	return loaded;
+    }
+    
+    /**
+     * Create a document from a file
+     */
+    public HTMLDoc(URL url, String file)
+    { 
+	FileInputStream _in;
+	byte[] data = new byte[128];
+	int databytes;
+	StringBuffer content;
+	
+	try {
+	    _in = new FileInputStream(file);
+	    if (_in != null){
+		content = new StringBuffer();
+		do{  
+		    databytes = _in.read(data);
+		    if (databytes > 0){
+			content.append(new String(data, 0, databytes));
+		    }		
+		} while (databytes >= 0);
+		this.content		= content.toString();
+	    }
+	}
+	catch (IOException ex){
+	    this.content = null;
+	    System.out.println(ex);
+	}
+	this.url = url;
+	this.pos = 0;
+	this.status = 0;
+	this.note = null;
+	this.blocklist	= null;
+	this.title = null;
+	this.urls_out = null;
+	this.urls_in = null;
+    }
+
+    /**
+     * Create a url-only document: the document body is not stored
+     */
+    public HTMLDoc(String url)
+    {
+	if (url != null){
+	    try{
+		this.url = new URL(url);
+	    }
+	    catch (MalformedURLException ex){
+		this.url = null;
+	    }
+	}
+	else {
+	    this.url = null;
+	}
+	this.pos = 0;
+	this.status = 0;
+	this.note = null;
+	this.content = null;
+	this.blocklist = null;
+	this.title = null;
+	this.urls_out = null;
+	this.urls_in = null;
+    }
+    
+    static public HTMLDoc fromString(String url, String string)
+    {	
+	HTMLDoc reply;
+	
+	reply = new HTMLDoc(url);
+	reply.content = string;
+	return reply;
+    }
+    
+    static public boolean validExtension(String url)
+    {	
+	String extension;
+	
+	// get file extension
+	extension = URLString.extension(url);
+	if (extension != null){
+	    extension = extension.toLowerCase();
+	}
+	
+	if (extension == null ||
+	    extension.indexOf("htm") >= 0 || 
+	    extension.indexOf("asp") >= 0){
+	    return true;
+	}
+	return false;
+    }
+    
+    static boolean validExtension(URL url)
+    {	
+	return validExtension(url.toString());
+    }
+
+    /**
+     * Uncache a single document
+     */
+    public static HTMLDoc uncacheDoc(String filebase, String url)
+    {	
+	String 	pathname;
+	String	filename;
+	HTMLDoc	doc;
+	
+	pathname = URLString.pathName(url);
+	if (pathname == null){
+	    return null;
+	}
+	
+	filename = filebase + pathname.replace('/', File.pathSeparatorChar);
+	doc = new HTMLDoc(URLString.toURL(url), filename);
+	
+	return doc;
+    }
+
+    /**
+     * @return URL (ie. Java URL object) of the document
+     */
+    public URL getUrl()
+    { 
+	return this.url;
+    }
+
+    // Report url to AppletContext
+    public void show(AppletContext ac)
+    { 
+	URL url;
+
+	url = this.getUrl();
+	if (url != null){
+	    ac.showDocument(url);
+	}
+    }
+    
+    // Get a HTMLBlock list of the wanted text in an HTMLdoc
+    public void getSelectContent(int level)
+    { 
+	HTMLBlockList list;
+
+	list = new HTMLBlockList(this, level);
+	this.blocklist = list;
+    }
+    
+    /**
+     * return the selected content
+     */
+    public HTMLBlockList selectContent()
+    { 
+	return this.blocklist;
+    }
+
+    /**
+     * get header blocks as selected content
+     */
+    public HTMLBlockList headerBlocks()
+    {	
+	if (this.blocklist == null){
+	    this.getSelectContent(6);
+	}
+	return this.blocklist;
+    }
+    
+    /**
+     * return a tagged-up select with an <A NAME=> at the beginning of each Hx
+     */
+    public String taggedSelectContent()
+    {
+	int heading, offset, pos;
+	String reply;
+	
+	if (this.blocklist == null || 
+	    this.blocklist.size() == 0){
+	    return this.content;
+	}
+	
+	reply = "";
+	offset	= 0;
+	for (heading = 0; heading < this.blocklist.size(); heading ++){
+	    reply = reply + 
+		this.content.substring(offset, this.blocklist.tagPos(heading)) +
+		"<A NAME=\"_L"+heading+"\"></A>";
+	    offset = this.blocklist.tagPos(heading);
+	}
+	reply = reply + this.content.substring(offset, this.content.length());
+	return reply;
+    }
+    
+    /**
+     * Return enumeration of headings in document
+     */
+    public Enumeration headings()
+    {
+	if (this.blocklist == null){
+	    this.getSelectContent(6);
+	}
+	return this.blocklist.elements();
+    }
+    
+    /**
+     *	@return HTMLBlock of the child text underneath a heading
+     */
+    public HTMLBlock headingChildText(int headref)
+    { 
+	HTMLBlock pageblock;
+	HTMLBlock headblock;
+	HTMLBlock childblock;
+	int blockstart, blockend;
+	
+	pageblock = this.getCodedContent(); // get all the coded bits of the page
+	headblock = this.headerBlocks().tagBlock(headref);
+	
+	blockstart = pageblock.find(headblock);
+	blockstart += headblock.size();
+	if (headref == this.headerBlocks().size() - 1) {
+	    blockend = pageblock.size();
+	}
+	else {
+	    blockend = pageblock.find(this.headerBlocks().tagBlock(headref+1));
+	}
+	childblock = pageblock.subBlock(blockstart, blockend);
+	
+	return childblock;
+    }
+    
+    /**
+     * Add incoming url to list of incoming references
+     */
+    public void addUrlIn(String url)
+    {
+	if (this.urls_in == null){
+	    this.urls_in = new ArrayList();
+	}
+	this.urls_in.add(url);
+    }
+    
+    /**
+     * @return a String of all incoming urls
+     */
+    public String urlsInString()
+    { 
+	if (this.urls_in != null){
+	    return this.urls_in.toString();
+	}
+	return "";
+    }
+    
+    /**
+     * @return an enumeration of all incoming urls as Strings
+     */
+    public Iterator urlsIn()
+    {
+	if (this.urls_in == null){
+	    return null;
+	}
+	return this.urls_in.iterator();
+    }
+    
+    /**
+     * @return the <code>StringVector</code> of all incoming urls
+     */
+    public List urlsInList()
+    {	
+	return this.urls_in;
+    }
+
+    /**
+     * @return <code>true</code> if the given url is linked to by this
+     *  document
+     */
+    public boolean linkedTo(URL url)
+    {	
+	if (this.urls_out != null &&
+	    this.urls_out.indexOf(url.toString()) >= 0){
+	    return true;
+	}
+	return false;
+    }
+    
+    /**
+     * See above: returns <code>true</code> if the document is linked to
+     * by this document.
+     */
+    public boolean linkedTo(HTMLDoc doc)
+    {
+	return linkedTo(doc.getUrl());
+    }
+
+    /**
+     * Add outgoing url to list of outgoing references
+     */
+    public void addUrlOut(String url)
+    { 
+	if (this.urls_out == null){
+	    this.urls_out = new ArrayList();
+	}
+	this.urls_out.add(url);
+    }
+    
+    /**
+     * @return a String of all outgoing urls
+     */
+    public String urlsOutString()
+    { 
+	if (this.urls_out != null){
+	    return this.urls_out.toString();
+	}
+	return "";
+    }
+    
+    /**
+     * @return the <code>StringVector</code> of all outgoing urls
+     */
+    public List urlsOutList()
+    {	
+	return this.urls_out;
+    }
+
+    /**
+     * Return an enumeration of outbound urls
+     */
+    public Iterator urlsOut()
+    { 
+	if (this.urls_out == null){
+	    return null;
+	}
+	return this.urls_out.iterator();
+    }
+
+    private static int urlListPos(List urlList, String url)
+    {	
+	for (int i = 0; i < urlList.size(); i ++){
+	    if (((String) urlList.get(i)).equals(url)){
+		return i;
+	    }
+	}
+	return -1;
+    }
+    
+    // Rename internally the content of a list
+    private void __renameUrl(List urlList, String oldUrl, String newUrl)
+    {	
+	if (urlList != null){
+	    int oldPos = urlListPos(urlList, oldUrl);
+	    
+	    if (oldPos >= 0){
+		if (urlListPos(urlList, newUrl) >= 0){
+		    // delete oldUrl: now duplicate
+		    urlList.remove(oldPos);
+		}
+		else {
+		    // rename oldUrl
+		    urlList.set(oldPos, newUrl);
+		}
+	    }
+	}
+    }
+    
+    /**
+     * Rename inbound/outbound url references
+     */
+    public void renameUrl(String oldUrl, String newUrl)
+    {	
+	this.__renameUrl(this.urls_in, oldUrl, newUrl);
+	this.__renameUrl(this.urls_out, oldUrl, newUrl);
+    }
+    
+    /**
+     * Save document
+     */
+    public boolean save(String filename, boolean select)
+    {	
+	FileOutputStream fout;
+	PrintWriter pout;
+	
+	String flattened = URLString.flattenedUrl(filename);
+	
+	try{	
+	    HTMLDocAnchorList anchorList = new HTMLDocAnchorList(this);
+
+	    anchorList.flattenLinks();
+			
+	    fout = new FileOutputStream(flattened);
+	    pout = new PrintWriter(fout);
+	    if (select == true) {
+		pout.print(this.taggedSelectContent());
+	    }
+	    else {
+		pout.print(this.content);
+	    }
+	    pout.close();
+	    fout.close();
+	}
+	catch (IOException ex) {
+	    System.out.println(ex);
+	    return false;
+	}
+	return true;
+    }
+    
+    /**
+     * Save document content
+     */
+    public boolean save(String base)
+    {
+	return this.save(base, false);
+    }
+    
+    /**
+     * Save selected content
+     */
+    public boolean saveSelect(String base)
+    {	
+	return this.save(base, true);
+    }
+
+    /**
+     * Get title of page
+     */
+    public void getTitle()
+    { 
+	HTMLDocTitle doctitle;
+
+	if (this.content != null){
+	    doctitle = new HTMLDocTitle(this);
+	    this.title	= doctitle.Title();
+	}
+    }
+    
+    /**
+     * @return: title of page
+     */
+    public String titleString()
+    {
+	if (this.title == null){
+	    this.getTitle();
+	}
+	return this.title;
+    }
+    
+    /**
+     * @return a <code>String</code> of the url of the page
+     */
+    public String urlString()
+    {
+	return this.url.toString();
+    }
+
+    /**
+     * 	Replace the HTML text of the page with the provided HTML string
+     *	content.  This is an extremely dangerous call to use, as dependent
+     *	objects such as tag objects will be immediately rendered inaccurate
+     *	in terms of pointers held to the original text.
+     */
+    protected void setContent(String newContent)
+    { 
+	this.content = newContent;
+    }
+
+    /**
+     * @return a <code>String</code> of the HTML text of the page
+     */
+    public String getContent()
+    { 
+	return this.content;
+    }
+
+    /**
+     * @return a <code>HTMLBlock</code> of the page content
+     */
+    public HTMLBlock getCodedContent()
+    {	
+	// if we haven't already got it, code the bugger up right now!
+	if (this.coded == null){
+	    HTMLParser parser;
+	    String next;
+	    HTMLBlock coded;
+	    HTMLTag tag;
+	    HTMLCText text;
+
+	    if (this.content == null){
+		return null;
+	    }
+	    
+	    parser = new HTMLParser(this);
+	    coded = new HTMLBlock(0, this.content.length());
+
+	    parser.startParse();
+	    next = parser.fullParse();
+	    while (next != null){
+		if (HTMLTag.isTag(next)){
+		    tag = new HTMLTag(next, parser.lastParse(), parser.atParse());
+		    coded.addTag(tag);
+		}
+		else {
+		     text = new HTMLCText(next, parser.lastParse(), parser.atParse());
+		     coded.addText(text);
+		}
+		next = parser.fullParse();
+	    }
+	    this.coded	= coded;
+	}
+	return this.coded;
+    }
+    
+    /**
+     * @return <code>true</code> if this document is not errored from loading
+     * etc.
+     */
+    public boolean valid()
+    {	
+	return (this.status < 4 && this.content != null && this.content.equals("null") == false);
+    }
+    
+    /**
+     * HTMLString: returns content
+     */
+    public String HTMLString()
+    { 
+	return this.content;
+    }
+    
+    /**
+     * Return text of document as ascii text;
+     */
+    /*
+      public String toString()
+      {	StringBuffer	reply = new StringBuffer();
+      int						parastart = 0;
+
+      return reply.toString();
+      }
+    */
+
+    /**
+     * Set current note on this page
+     * @return old note object
+     */
+    public Object setNote(Object note)
+    {
+	Object oldnote;
+	
+	oldnote	= this.note;
+	this.note = note;
+	return oldnote;
+    }
+    
+    /**
+     * @return current note <code>Object</code> on this page
+     */
+    public Object getNote()
+    {
+	return this.note;
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLDocAnchorList.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLDocAnchorList.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLDocAnchorList.java	(revision 13666)
@@ -0,0 +1,160 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+
+
+public class HTMLDocAnchorList extends HTMLBlockList
+
+{ HTMLDoc doc;
+
+	public HTMLDocAnchorList(HTMLDoc doc)
+
+	{ super();
+
+		this.doc = doc;	// remember the document reference
+
+
+
+		super.initialise(doc, anchorStartTags, anchorEndTags, anchorOptEndTags);
+
+	}
+
+
+
+	/**
+	 *	Return the HTMLBlock containing the named local anchor and it's
+	 *	child (contained) tags.
+	 *
+	 *	@param <code>String</code> name of the local anchor to find.
+	 *	@return <code>HTMLBlock</code> the corresponding block of HTML
+	 *					contained by the anchor.  If the local anchor does not
+	 *					exist, this value will be <code>null</code>.
+	 */
+	public HTMLBlock localAnchor(String name)
+
+	{	int block;
+
+		String	localname;
+
+
+
+		for (block = 0; block < this.size(); block ++)
+
+		{ localname = this.tagBlock(block).headTag().idValue("name");
+
+			if (localname == null)
+
+			{ continue;
+
+			}
+
+			if (name.equalsIgnoreCase(localname))
+
+			{	return this.tagBlock(block);
+
+			}
+
+		}
+
+		return null;
+
+	}
+
+	private int indexOf(String base, String subString, int from)
+	{	int i, j;
+
+		for (i = from; i < base.length() - subString.length(); i ++)
+		{	if (Character.toLowerCase(base.charAt(i)) == subString.charAt(0))
+			{	j = 0;
+				for (j = 1; j < subString.length(); j ++)
+				{	if (Character.toLowerCase(base.charAt(i+j)) != subString.charAt(j))
+					{	break;
+					}
+				}
+
+				if (j == subString.length())
+				{	return i;
+				}
+			}
+		}
+		return -1;
+	}
+
+	public void flattenLinks()
+	{	int 					block;
+		String				url;
+		char					endsWith;
+		StringBuffer	newContent = new StringBuffer(doc.getContent());
+		boolean				changed = false;
+
+//		System.out.println("Flattening");
+
+		for (block = 0; block < this.size(); block ++)
+		{ HTMLTag tag;
+			int			tagPos;
+			int			valueStart, valueEnd;
+
+			tag = this.tagBlock(block).headTag();	// get the <A> tag itself
+
+			url = tag.idValue("href"); 						// if there is no HREF member, abandon this one
+			if (url == null)
+			{ System.out.println("No href");
+				continue;
+			}
+	
+			tagPos	= tag.startPos();
+			tagPos	=	indexOf(doc.getContent(), "href", tagPos);	// get the HREF itself
+			if (tagPos > tag.endPos() || tagPos < 0)					// if none in the tag, skip it
+			{	System.out.println("Didn't get href");
+				continue;
+			}
+			tagPos += "href".length();												// skip past it
+
+			while (	doc.getContent().charAt(tagPos) <= ' ' ||		// skip pass equals, etc.
+							doc.getContent().charAt(tagPos) == '=')
+			{	tagPos ++;
+			}
+
+			if (doc.getContent().charAt(tagPos) == '"' ||				// get the demarcating whitespace/quotes
+					doc.getContent().charAt(tagPos) == '\'')
+			{	endsWith	= doc.getContent().charAt(tagPos);
+				tagPos ++;
+			}
+			else
+			{	endsWith  = ' ';
+			}
+			valueStart = tagPos;
+
+			//			System.out.println("Flattening " + doc.getContent().length() + " " + tagPos);
+
+			while (tagPos < doc.getContent().length() &&
+			       doc.getContent().charAt(tagPos) != endsWith)	// read it in
+			{	if (doc.content.charAt(tagPos) == '?' ||				// replace special characters			
+						doc.content.charAt(tagPos) == '&')
+				{	newContent.setCharAt(tagPos, '_');						//   and note that we've done so
+					changed	= true;
+				}
+				tagPos ++;
+			}
+			valueEnd = tagPos;
+
+			tagPos = indexOf(doc.getContent(), ".html", valueStart);
+			if (tagPos >= 0 && tagPos < valueEnd)
+			{	// shuffle around the html bit
+				while (tagPos < valueEnd - 5)
+				{	newContent.setCharAt(tagPos, newContent.charAt(tagPos + 5));
+					tagPos ++;
+				}
+				newContent.setCharAt(tagPos ++, '.');
+				newContent.setCharAt(tagPos ++, 'h');
+				newContent.setCharAt(tagPos ++, 't');
+				newContent.setCharAt(tagPos ++, 'm');
+				newContent.setCharAt(tagPos ++, 'l');
+			}
+		}
+
+		if (changed == true)																// replace the document as needsbe
+		{	doc.setContent(newContent.toString());
+		}
+	}
+
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLDocHeadingList.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLDocHeadingList.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLDocHeadingList.java	(revision 13666)
@@ -0,0 +1,25 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+
+
+public class HTMLDocHeadingList extends HTMLBlockList
+
+{ public HTMLDocHeadingList(HTMLDoc doc)
+
+	{ super();
+
+
+
+		super.initialise(doc, headingStartTags, headingEndTags, anchorOptEndTags);
+
+	}
+
+
+
+	public int headingLevel(int element)
+
+	{	return this.tagBlock(element).headTag().tagLevel();
+
+	}
+
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLDocLocalHeading.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLDocLocalHeading.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLDocLocalHeading.java	(revision 13666)
@@ -0,0 +1,187 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+
+
+import java.util.*;
+
+
+
+public class HTMLDocLocalHeading
+
+{	String		heading;
+
+	HTMLBlock	block;
+
+
+
+	public HTMLDocLocalHeading(HTMLDoc doc, String local)
+
+	{	HTMLBlock 				nextheading, lastheading, anchor;
+
+		Enumeration				headings;
+
+		HTMLDocAnchorList	anchors;
+
+		HTMLBlock					docBlock;
+
+		int								_start, _end, _pos;
+
+
+
+		// initialise (to undefined)
+
+		this.heading	= null;
+
+		this.block		= null;
+
+
+
+		// get anchors
+
+		anchors	= new HTMLDocAnchorList(doc);
+
+		anchor	= anchors.localAnchor(local);
+
+		if (anchor == null)
+
+		{	return;
+
+		}
+
+
+
+		// get headings position; lastheading will be previous, nextheading will be next
+
+		headings		= doc.headings();
+
+		lastheading	= null;
+
+		nextheading	= null;
+
+
+
+		while (headings.hasMoreElements())
+
+		{	nextheading	= (HTMLBlock) headings.nextElement();
+
+			if (nextheading.startPos() > anchor.startPos())
+
+			{	break;
+
+			}
+
+			
+
+
+
+			lastheading	= nextheading;
+
+		}
+
+
+
+		// didn't get any actual headings; abort.
+
+		if (nextheading == null)
+
+		{	return;
+
+		}
+
+
+
+		// got to the end
+
+		if (nextheading == lastheading)
+
+		{	this.block = nextheading;
+
+		}
+
+		else
+
+		{	// now see where anchor is; try to find null textual content between anchor
+
+			// and heading
+
+			docBlock	= doc.getCodedContent();
+
+			_start		= docBlock.find(anchor);
+
+			_end			= docBlock.find(nextheading);
+
+			for (_pos = _start; _pos < _end; _pos ++)
+
+			{	// HTML tag
+
+				if (docBlock.elementAt(_pos) instanceof HTMLTag)
+
+				{	
+
+				}
+
+				// HTML text - if non-blank, abort
+
+				else
+
+				{	if (((HTMLCText) docBlock.elementAt(_pos)).nullString() == false)
+
+					{	break;
+
+					}
+
+				}
+
+			}
+
+
+
+			// assign
+
+			if (_pos != _end)
+
+			{	this.block	=	lastheading;
+
+			}
+
+			else
+
+			{	this.block	= nextheading;
+
+			}
+
+		}
+
+		this.heading	= this.block.toString();
+
+	}
+
+
+
+	public String toString()
+
+	{	return this.heading;
+
+	}
+
+
+
+	public HTMLBlock block()
+
+	{	return this.block;
+
+	}
+
+
+
+	protected void finalize() throws Throwable
+
+	{	this.heading	= null;
+
+		this.block		= null;
+
+		super.finalize();
+
+	}
+
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLDocTitle.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLDocTitle.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLDocTitle.java	(revision 13666)
@@ -0,0 +1,89 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+import java.util.*;
+
+public class HTMLDocTitle
+{ StringBuffer title;
+	private static HTMLTagVector titleStartTags;
+	private static HTMLTagVector titleEndTags;
+	private static HTMLTagVector titleOptEndTags;
+
+	static
+	{	titleStartTags 	= new HTMLTagVector("title,h1,h2,h3,h4,h5,h6");
+		titleEndTags 		= new HTMLTagVector("title,h1,h2,h3,h4,h5,h6,body,head,table,hr,p,ul,ol,dl,dt,dd,li,tr,td,th,map");
+		titleOptEndTags	= new HTMLTagVector("div,center,form");
+	}
+
+	/**
+	 * Constructor: generates a title for the supplied <code>HTMLDoc</code>.
+	 */
+	public HTMLDocTitle(HTMLDoc doc)
+	{ boolean				intitle;
+		boolean				incontent;
+		HTMLCText			text;
+		HTMLTag				tag;
+		HTMLBlock			parser;
+		Enumeration		elements;
+		Object				element;
+		
+		this.title 	= null;
+		intitle			= false;
+		incontent		= false;
+		
+		parser		=	doc.getCodedContent();
+		if (parser == null)
+		{	return;
+		}
+		elements	= parser.elements();
+
+		while (elements.hasMoreElements())
+		{ //System.out.println(read + ":" +  read.charAt(0));
+			element	= elements.nextElement();
+			
+			if (element instanceof HTMLTag)
+			{ tag = (HTMLTag) element;
+
+				if (intitle)
+				{	if (titleEndTags.matches(tag, false) ||
+							(incontent && titleOptEndTags.matches(tag, false))) // if closing
+					{ intitle = false;
+						break;
+					}
+					else // else ignore it
+					{
+					}
+				}
+				else
+				{	if (titleStartTags.matches(tag, true) == true)
+					{ intitle			= true;
+						incontent		= false;
+						this.title	= new StringBuffer();
+					}
+				}
+			}
+			else
+			{ text	= (HTMLCText) element;
+
+				if (intitle == true)
+				{	this.title.append(text.toString());
+					if (!text.nullString())
+					{ incontent	= true;
+					}
+				}
+			}
+		}
+		if (this.title != null)
+		{ this.title = HTMLCText.cleanString(this.title);
+		}
+	}
+
+	/**
+	 * @return the Title as a <code>String</code>.
+	 */
+	public String Title()
+	{	if (this.title == null)
+		{ return null;
+		}
+		return this.title.toString();
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLEntity.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLEntity.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLEntity.java	(revision 13666)
@@ -0,0 +1,346 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+import java.io.*;
+import java.util.*;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentLoader;
+
+public class HTMLEntity
+{ String  name;
+  int     code;
+  static Vector entities = null;
+  static Vector	nmapping = null;
+
+  public HTMLEntity(String name, int code)
+  { int start, end, at;
+    HTMLEntity compareEntity;
+
+    if (HTMLEntity.entities == null)
+    { HTMLEntity.entities = new Vector();
+    }
+    if (HTMLEntity.nmapping == null)
+    { HTMLEntity.nmapping = new Vector();
+    }
+
+    this.name	= name;
+    this.code	= code;
+
+    entities.addElement(this);
+    start = 0;
+    end   = nmapping.size();
+    while (start != end)
+    { at = (start + end) / 2;
+	
+      compareEntity = 
+	(HTMLEntity) entities.elementAt(((Integer) nmapping.elementAt(at)).intValue());
+      if (compareEntity.code > code)
+      { end = at;
+      }
+      else
+      { start = at + 1;
+      }
+    }
+    if (end == nmapping.size())
+    { nmapping.addElement(new Integer(nmapping.size()));
+    }
+    else
+    { nmapping.insertElementAt(new Integer(nmapping.size()), start);
+    }
+  }
+
+  public String toString()
+  { Character c;
+
+    c = new Character((char) this.code);
+    return c.toString();
+  }
+
+  public static String codeString(char c)
+  { StringBuffer 	reply;
+    String        codestring;
+
+    if (c < 128 || c == '&' || c == '<' || c == '>')
+    { return null;
+    }
+    codestring = Integer.toString((int) c);
+    reply      = new StringBuffer("&#");
+    reply.append(codestring);
+    reply.append(";");
+
+    return reply.toString();
+  }
+
+  public static String nameCodeString(char c)
+  { int start, end, at, compare;
+    HTMLEntity compareEntity;
+
+    start = 0;
+    end		= nmapping.size();
+    while (start != end)
+    { at	= (start + end) / 2;
+      
+      compareEntity = 
+	(HTMLEntity) entities.elementAt(((Integer) nmapping.elementAt(at)).intValue());
+      if (compareEntity.code == (int) c)
+      { StringBuffer reply;
+
+        reply = new StringBuffer("&");
+	reply.append(compareEntity.name);
+	reply.append(";");
+	return reply.toString();
+      }
+      else if (compareEntity.code < c)
+      {	end	= at;
+      }
+      else
+      {	start	= at + 1;
+      }
+    }
+    return codeString(c);
+  }
+
+  public static void getEntities(String source)
+  { HTMLEntity 	newentity;
+    int         pos;
+    int					start;
+    String			name;
+    int					code;
+    
+    if (source == null)
+    { return;
+    }
+
+    start = 0;
+    while (start < source.length())
+    { pos = start;
+      while (source.charAt(pos) != ':')
+      { pos ++;
+      }
+      name = source.substring(start, pos);
+
+      // skip colon and reset
+      pos ++;
+      start = pos;
+
+      while(pos < source.length() && source.charAt(pos) > ' ')
+      { pos ++;
+      }
+      code = Integer.parseInt(source.substring(start, pos));
+
+      newentity = new HTMLEntity(name, code);
+      
+      while ( pos < source.length() && source.charAt(pos) < ' ')
+      { pos ++;
+      }
+      start = pos;
+    }
+  }
+
+  public static void getEntities(InputStream in)
+  { getEntities(DocumentLoader.getAsString(in));
+  }
+
+  public static void getEntities(File file)
+  { FileInputStream in;
+
+    try
+    { in = new FileInputStream(file);
+      getEntities(in);
+      in.close();
+    }
+    catch (IOException io)
+    { System.out.println("No entities");
+    }
+  }
+
+  public static void getEntities()
+  { ClassLoader loader;
+    InputStream	in;
+
+    in = ClassLoader.getSystemResourceAsStream("org\\greenstone\\gsdl3\\gs3build\\util\\Entities.map");
+    if (in == null)
+    { System.out.println("Unable to load Entities.map from org.greenstone.gsdl3.gs3build.util");
+    }
+    getEntities(in);
+  }
+
+  public static String encodeText(String source, boolean named)
+  { StringBuffer reply;
+    int          start,at;
+
+    if (source == null)
+    { return null;
+    }
+
+    if (HTMLEntity.entities == null)
+    {	getEntities();
+    }
+
+    reply	= new StringBuffer();
+    at 		= 0;
+    start	= 0;
+    while (at < source.length())
+    { if (source.charAt(at) > 128)
+      {	if (at != start)
+	{ reply.append(source.substring(start, at));
+	}
+
+        if (named)
+	{ reply.append(nameCodeString(source.charAt(at)));
+	}
+	else
+	{ reply.append(codeString(source.charAt(at)));
+	}
+	start	= at + 1;
+      }
+      at ++;
+    }
+		
+    return reply.toString();
+  }
+
+  public static String decodeText(String source)
+  { int start, end, loff, roff;
+    int sstart, send, test;
+    int startoff, endoff, baseoff;
+    boolean matched;
+    String  tail;
+    StringBuffer reply;
+
+    if (source == null)
+    { return null;
+    }
+
+    if (HTMLEntity.entities == null)
+    {	getEntities();
+    }
+
+    reply   = new StringBuffer();
+    baseoff = 0;
+
+    tail = source;
+    do
+    { // get next ampersand
+	    startoff = tail.indexOf('&');
+      if (startoff < 0 || startoff == tail.length() - 1)
+      { break;
+      }
+
+      // if it's followed by a hash, evaluate as a number
+      if (tail.charAt(startoff + 1) == '#')
+      { if (startoff < tail.length() - 2 &&
+      			tail.charAt(startoff+2) >= '0' &&
+            tail.charAt(startoff+2) <= '9')
+      	{ int code;
+
+        	loff = startoff + 2;
+        	while (tail.charAt(loff) >= '0' &&
+          				tail.charAt(loff) <= '9')
+        	{ loff ++;
+          }
+
+          code = Integer.parseInt(tail.substring(startoff+2, loff));
+        	reply.append(tail.substring(0, startoff));
+					reply.append(new Character((char) code));
+
+          if (tail.charAt(loff) == ';')
+          { loff ++;
+          }
+          loff = loff - startoff - 1;
+        }
+        else
+        { loff = 0;
+        	reply.append(tail.substring(0, startoff+1));
+        }
+      }
+      else
+      {	start = 0;
+        end   = HTMLEntity.entities.size();
+        loff  = 0;
+
+	while (startoff+1+loff < tail.length() && start != end)
+	{ sstart = start;
+	  send   = end;
+          test	 = (sstart + send) >> 1;
+
+	  matched	= false;
+		      
+	  roff	= startoff + 1 + loff;
+
+	  while (sstart != send)
+	  { test = (sstart + send) >> 1;
+
+	    if (tail.charAt(roff) < ((HTMLEntity) HTMLEntity.entities.elementAt(test)).name.charAt(loff))
+	    { send = test;
+	    }
+	    else if (tail.charAt(roff) > ((HTMLEntity) HTMLEntity.entities.elementAt(test)).name.charAt(loff))
+	    { sstart	= test + 1;
+	    }
+	    else
+	    { break;
+	    }
+	  }
+
+	  //					System.out.println(sstart+">"+send+":"+loff);
+
+	  if (sstart != send) // found a match
+	  { sstart = test;
+	    while (sstart >= start &&
+		   tail.charAt(roff) ==
+		   ((HTMLEntity) HTMLEntity.entities.elementAt(sstart)).name.charAt(loff))
+	    { sstart --;
+	    }
+	    sstart ++;
+
+	    send = test + 1;
+	    while (send < end &&
+		   tail.charAt(roff) ==
+		   ((HTMLEntity) HTMLEntity.entities.elementAt(send)).name.charAt(loff))
+	    { send ++;
+	    }
+
+//						System.out.println(sstart+"!"+send+":"+loff);
+
+	    start = sstart;
+	    end	= send;
+	  }
+	  else
+	  { loff	= 0;
+	    reply.append(tail.substring(0, startoff+1));
+	    break;
+	  }
+
+//					System.out.println(start+">"+end+":"+loff);
+	  
+	  loff ++;
+	  if (end == start + 1 &&
+	      ((HTMLEntity) HTMLEntity.entities.elementAt(test)).name.length() == loff)
+	  { reply.append(tail.substring(0, startoff));
+	    reply.append(((HTMLEntity) HTMLEntity.entities.elementAt(test)).toString());
+	    if (roff < tail.length() - 1 && tail.charAt(roff+1) == ';')
+	    { loff ++;
+	    }
+	    break;
+	  }
+	}
+      }
+
+      tail = tail.substring(startoff + 1 + loff);
+    } while (tail != null && tail.length() > 0);
+    
+    if (tail != null)
+    { reply.append(tail);
+    }
+    return reply.toString();
+  }
+
+  public static void main(String args[])
+  { String reply;
+
+    getEntities();
+    
+    reply = decodeText(args[0]);
+    System.out.println(reply);
+  }
+}
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLLoadManager.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLLoadManager.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLLoadManager.java	(revision 13666)
@@ -0,0 +1,208 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+import java.net.*;
+import java.util.*;
+
+class HTMLLoadManager implements Runnable
+{	Vector		 	toLoad;
+	Vector			loading;
+	Vector			loaded;
+	boolean			stopFlag;
+	boolean			started;
+	Thread			thread;
+	static int	running;
+
+	static
+	{	running	= 0;
+	}
+
+	/**
+	 *	Vanilla constructor of an object to load HTML documents in the background
+	 */
+	public HTMLLoadManager()
+	{	this.toLoad		= new Vector();
+		this.loading 	= new Vector();
+		this.loaded		= new Vector();
+		this.thread		= null;
+		this.stopFlag	= false;
+		this.started	= false;
+	}
+
+	/**
+	 *	Check if a given document is loading
+	 *
+	 *	@return <code>boolean</code> whether the document is loading or not
+	 */
+	public boolean isLoading(String docURL)
+	{	int i;
+
+		for (i = 0; i < this.toLoad.size(); i ++)
+		{	if (this.toLoad.elementAt(i).toString().equals(docURL))
+			{	return true;
+			}
+		}
+
+		for (i = 0; i < this.loading.size(); i ++)
+		{	if (((HTMLDoc) this.loading.elementAt(i)).urlString().equals(docURL))
+			{	return true;
+			}
+		}
+
+		for (i = 0; i < this.loaded.size(); i ++)
+		{	if (((HTMLDoc) this.loaded.elementAt(i)).urlString().equals(docURL))
+			{	return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 *	Start this object as a thread
+	 */
+	public synchronized void start()
+	{	if (this.thread == null)
+		{	this.thread	= new Thread(this);
+			this.thread.start();		// start the thread
+			this.stopFlag	= false;	// reset the stop flag as it could have been reset
+			this.started 	= true;		// note that we're running
+			running ++;
+		}
+	} 
+
+	/**
+	 *	The main thread function; it calls a number of private service functions to
+	 *  achieve it's affect.  Once the stop flag is set, it runs until all loading
+	 *  documents are loaded, then stops.
+	 */
+	public void run()
+	{ int i;
+
+		while (this.stopFlag == false || this.loading.size() > 0)
+		{	// slumber while there's nothing to do
+			while (this.toLoad.size() == 0 && this.loading.size() == 0)
+			{	try
+				{
+					thread.sleep(100);
+				}
+				catch (InterruptedException ex)
+				{
+				}
+			}
+
+			// first check for finished documents
+			i = 0;
+			while (i < this.loading.size())
+			{	HTMLDoc doc = (HTMLDoc) this.loading.elementAt(i);
+
+				if (doc.ready())
+				{	this.deschedule(i);
+				}
+				else
+				{	i ++;
+				}
+			}
+
+			// then check for a document to load
+			while (this.stopFlag == false &&
+						 this.toLoad.size() > 0 &&
+						 this.loading.size() < 10)
+			{	this.scheduleNext();
+			}
+		}
+		this.started = false;
+		running --;
+	}
+
+	/**
+	 *	Returns the total number of loader managers running at this time
+	 *
+	 *	@return <code>int</code> the number of managers running.
+	 */
+	public synchronized int running()
+	{	return running;
+	}
+
+	private synchronized void scheduleNext()
+	{	// pop url from list to load
+		URL docURL	= (URL) this.toLoad.elementAt(0);
+		this.toLoad.removeElementAt(0);
+
+		// generate new document and add it to the "loading" vector;
+		// the document content is loaded in another thread
+		HTMLDoc	doc = new HTMLDoc(docURL, 1);
+		this.loading.addElement(doc);
+	}
+
+	private synchronized void deschedule(int i)
+	{	// get the document and place it in the loaded list
+		HTMLDoc	doc = (HTMLDoc) this.loading.elementAt(i);
+		this.loaded.addElement(doc);
+
+		// remove it from the loading list
+		this.loading.removeElementAt(i);
+	}
+
+	/**
+	 *	Get a loaded document, not blocking if nothing is ready yet.
+	 *
+	 *  @return <code>HTMLDoc</code> the document; NB. this may be <code>null</code> as
+	 *                               it is not guaranteed that there is currently a loaded
+	 *                               document.
+	 */
+	public synchronized HTMLDoc nextLoaded()
+	{	HTMLDoc reply;
+
+		// if nothing is loaded, return null
+		if (this.loaded.size() == 0)
+		{	return null;
+		}
+
+		// get the first element from the loaded vector and return it,
+		// removing it from the vector in the meantime
+		reply = (HTMLDoc) this.loaded.elementAt(0);
+		this.loaded.removeElementAt(0);
+		return reply;
+	}
+
+	/**
+	 *	Request the loading of a document; this does not block but schedules
+	 *  the document for loading.
+	 *
+	 *  @param <code>URL</code> the URL of the document to load
+	 */
+	public synchronized void load(URL docURL)
+	{	// check if it's being loaded already; if so do nothing
+		if (this.isLoading(docURL.toString()) == false)
+		{	this.toLoad.addElement(docURL);
+
+			// self-start if the loading thread isn't running
+			if (this.started == false)
+			{	this.start();
+			}
+		}
+	}
+
+	/**
+	 *	Get the total number of documents loading/loaded through this loader
+	 *
+	 *	@param <code>int</code> the number of documents
+	 */
+	public synchronized int loadingDocs()
+	{	return this.toLoad.size() + this.loading.size() + this.loaded.size();
+	}
+
+	/**
+	 *	Instruct the manager to stop loading documents
+	 */
+	public synchronized void stopLoading()
+	{	this.stopFlag = true;
+	}
+
+	protected void finalize() throws Throwable
+	{	this.thread 	= null;
+		this.loading 	= null;
+		this.toLoad		= null;
+		this.loaded		= null;
+		super.finalize();
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLLoader.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLLoader.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLLoader.java	(revision 13666)
@@ -0,0 +1,353 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+
+
+import java.net.*;
+
+import java.io.*;
+
+
+
+public class HTMLLoader implements Runnable
+
+{ URL 					from;
+
+	StringBuffer	HTML;
+
+	boolean				loaded;
+
+	boolean				error;
+
+	boolean				notFound;
+
+	Thread				thread;
+
+	static int		running;
+
+
+
+	/**
+
+	 * Constructor to load given URL
+
+	 */
+
+	public HTMLLoader(URL from)
+
+	{ this.from 	= from;
+
+		this.HTML 	= new StringBuffer();
+
+		this.loaded	= false;
+
+		this.error	= false;
+
+		this.thread = null;
+	}
+
+
+
+	/**
+
+	 * @return <code>0</code> if finished running; any other value if
+
+	 *         still executing
+
+	 */
+
+	public static synchronized int running()
+
+	{ return running;
+
+	}
+
+
+
+	/**
+
+	 * Starts the thread; the method <code>load</code> is a synonym for this
+
+	 */
+
+	public synchronized void start()
+
+	{ if (thread == null)
+
+		{ thread = new Thread(this);
+
+			thread.start();
+
+			running	++;
+
+		}
+
+//		System.out.println("Running: "+running);
+
+	}
+
+
+
+	/**
+
+	 * Do the actual loading; this will multi-thread with calling task
+
+	 */
+
+	public void run()
+
+	{	URLConnection connect;
+
+		int						length, i, c;
+
+		byte					inbuffer[];
+
+		InputStream		in;
+
+
+
+		inbuffer = new byte[128];
+
+
+
+		this.notFound	= false;
+//		System.out.println("Running loader");
+
+
+
+		// get connection and test length
+
+		try
+
+		{	connect = this.from.openConnection();
+
+		}
+
+		catch (IOException ioex)
+
+		{ this.loaded	= true;
+
+			this.error	=	true;
+
+			running --;
+			System.out.println(ioex);
+
+			return;
+
+		}
+
+
+		length = connect.getContentLength();
+
+		if (length == 0)
+
+		{ this.loaded = true;
+
+			running --;
+			System.out.println("Empty");
+
+			return;
+
+		}
+
+
+
+		// get an inputstream to the document body
+
+		try
+
+		{ in = connect.getInputStream();
+
+		}
+
+		catch (IOException ioex)
+
+		{ this.error	= true;
+
+			this.loaded	= true;
+
+			running --;
+			System.out.println("Open failed" + ioex);
+
+			return;
+
+		}
+
+
+
+		if (length < 0)
+
+		{	if (connect.getHeaderField(0) != null &&
+
+					connect.getHeaderField(0).indexOf("404") >= 0)
+
+			{	this.notFound	= true;
+
+				this.error		= true;
+
+				this.loaded		= true;
+
+				running --;
+				System.out.println("Not found");
+
+				return;
+
+			}
+
+		}
+
+//		System.out.println("Ready to read " + length);
+
+
+
+		// read in the document body
+
+		i = 0;
+
+		c = 0;
+
+		while (true || i < length)
+
+		{ // read in 128 characters (abort on IO Exception)
+
+			try
+
+			{ c = in.read(inbuffer);
+
+			}
+
+			catch (IOException ioex)
+
+			{ break;
+
+			}
+
+			// System.out.println("read " + c);
+
+
+
+			// if no characters were read, end, otherwise add it to the body
+
+			if (c != -1)
+
+			{ if (c > 0)
+
+				{ this.HTML.append(new String(inbuffer, 0, c));
+
+					i += c;
+
+				}
+
+			}
+
+			else
+
+			{ break;
+
+			}
+
+			// if an incomplete buffer was read (ie no characters remain), end
+
+/*			if (c < inbuffer.length && i >= length)
+
+			{ break;
+
+			}*/
+
+		}
+
+
+
+		// Close file
+
+		try
+
+		{	in.close();
+
+		}
+
+		catch (IOException ioex)
+
+		{	//System.out.println("Closed except "+ioex);
+
+		}
+
+	
+		this.loaded = true;
+
+  	running --;
+
+	}
+
+
+
+	/**
+
+	 * Do the actual loading (calls a Start on the Thread)
+
+	 */
+
+	public void load()
+
+	{	this.start();
+
+//		this.run();
+
+	}
+
+
+
+	/**
+
+	 * @return HTML text as a <code>String</code>.
+
+	 */
+
+	public synchronized String HTML()
+
+	{ if (this.error)
+
+		{ return "Error";
+
+		}
+
+		return this.HTML.toString();
+
+	}
+
+
+
+	/**
+
+	 * @return  <code>true</code> if the file has successfully loaded
+
+	 */
+
+	public boolean loaded()
+
+	{ return this.loaded;
+
+	}
+
+
+
+	protected void finalize() throws Throwable
+
+	{	this.thread = null;
+
+		this.from		= null;
+
+		this.HTML		= null;
+
+		super.finalize();
+
+	}
+
+
+
+	static
+
+	{ running = 0;
+
+	}
+
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLLocalAnchor.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLLocalAnchor.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLLocalAnchor.java	(revision 13666)
@@ -0,0 +1,42 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+public class HTMLLocalAnchor
+{	
+	public static int anchorRef(HTMLBlockList anchors, String name)
+	{ int loop;
+		String	idvalue;
+
+		for (loop = 0; loop < anchors.size(); loop ++)
+		{	idvalue = anchors.tagBlock(loop).headTag().idValue("name");
+			if (idvalue != null && idvalue.equalsIgnoreCase(name))  //TODO: check if this should be case senstitive
+			{ return loop;
+			}
+		}
+		return -1;
+	}
+
+	public static int header(HTMLDoc doc, String local)
+	{	HTMLBlockList anchors;
+		int						heading;
+		HTMLBlock			headingblock;
+		int						anchor;
+		HTMLBlock			anchorblock;
+
+		anchors	= HTMLBlockList.anchorlist(doc);
+		anchor	= anchorRef(anchors, local);
+		if (anchor < 0)
+		{	return -1;
+		}
+
+		anchorblock	= anchors.tagBlock(anchor);
+		for (heading = 0; heading < doc.headerBlocks().size(); heading ++)
+		{	headingblock	= doc.headerBlocks().tagBlock(heading);
+
+			if (headingblock.startPos() > anchorblock.endPos())
+			{	break;
+			}
+		}
+		return heading - 1;
+	}
+	
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLObject.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLObject.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLObject.java	(revision 13666)
@@ -0,0 +1,5 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+public interface HTMLObject
+{ public String getHTMLType();
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLParser.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLParser.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLParser.java	(revision 13666)
@@ -0,0 +1,243 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+import java.applet.*;
+
+public class HTMLParser
+{ 
+    HTMLDoc document;
+    int pos;
+    int	lastpos;
+
+    public HTMLParser(HTMLDoc document)
+    { 
+	this.document = document;
+	this.pos = 0;
+    }
+    
+    public void startParse()
+    { 
+	this.pos = 0;
+	this.lastpos = -1;
+	//System.out.println("Starting "+document.urlString());
+    }
+
+    public int atParse()
+    { 
+	return this.pos;
+    }
+
+    public int lastParse()
+    { 
+	return this.lastpos;
+    }
+
+    // do a full text/tag parse
+    public String fullParse()
+    { 
+	String reply = null;
+	int end;
+	int start;
+
+	this.lastpos = this.pos;
+	
+	if (this.pos >= this.document.getContent().length()){
+	    return reply;
+	}
+	
+	if (this.document.getContent().charAt(this.pos) == '<'){
+	    start = this.pos;
+	    
+	    // if we're not at the end of the document,
+	    // read the rest of the tag
+	    if (this.pos == this.document.getContent().length() - 1){
+		this.pos = this.document.getContent().length();
+		return reply;
+	    }
+	    
+	    // if the tag is a comment
+	    if (this.pos < this.document.getContent().length() - 3 &&
+		this.document.getContent().substring(this.pos, this.pos+4).equals("<!--")){
+		end = this.document.getContent().substring(this.pos).indexOf("-->") + 3 + this.pos;
+		reply = this.document.getContent().substring(this.pos, end);
+		this.pos = end;
+	    }
+	    else 
+		{ // read up to the end of the tag
+		    end = this.pos + 1;
+		    while (end < this.document.getContent().length() &&
+			   this.document.getContent().charAt(end) != '>'){
+			end ++;
+		    }
+
+		    // get the whole of the tag into 'reply', and
+		    // set the current pos to immediately after the tag
+		    if (end < this.document.getContent().length()){
+			reply = this.document.getContent().substring(this.pos, end + 1);
+			this.pos = end + 1;
+		    }
+		    // patch the trailing > onto the tag string
+		    else {
+			reply = this.document.getContent().substring(this.pos, end) + ">";
+			this.pos = end;
+		    }
+		}
+	}
+	else
+	    { // hunt for the beginning of the next tag
+		start = this.pos;
+		while ((this.pos < this.document.getContent().length()) &&
+		       (this.document.getContent().charAt(this.pos) != '<')){
+		    this.pos ++;
+		}
+		
+		// return everything up to that tag
+	    reply = this.document.getContent().substring(start, this.pos);
+	    }
+	return reply;
+    }
+
+    // Get the next tag to parse
+    public String nextParse()
+    { 
+	String reply = null;
+	int end;
+
+	this.lastpos = this.pos;
+
+	if (this.document.getContent() == null){
+	    return null;
+	}
+	
+	if (this.pos >= this.document.getContent().length()){
+	    return reply;
+	}
+	
+	// hunt for the beginning of the next tag
+	while ((this.pos < this.document.getContent().length()) &&
+	       (this.document.getContent().charAt(this.pos) != '<')){
+	    this.pos ++;
+	}
+	
+	// if we're not at the end of the document,
+	// read the rest of the tag
+	if (this.pos < this.document.getContent().length()){
+	    if (this.pos == this.document.getContent().length() - 1){
+		this.pos = this.document.getContent().length();
+		return reply;
+	    }
+	    
+	    end = this.pos + 1;
+	    while (end < this.document.getContent().length() &&
+			this.document.getContent().charAt(end) != '>'){
+		end ++;
+	    }
+	    
+	    // get the whole of the tag into 'reply', and
+	    // set the current pos to immediately after the tag
+	    if (end < this.document.getContent().length()){
+		reply = this.document.getContent().substring(this.pos, end + 1);
+		this.pos = end + 1;
+	    }
+	    else{ 
+		this.pos = end;
+	    }
+	}
+	return reply;
+    }
+    
+    
+    /* --
+       -- return next HREF value we come across in the document
+       --
+       -- NB: the checking of the quotes etc is rather lazy - and should be tidied
+       --
+    */
+    public String nextHREF()
+    { 
+	String reply;
+	int start, end;
+	boolean quoted;
+	HTMLTag tag;
+	
+	reply = this.nextParse();
+	while (this.pos < this.document.getContent().length()){
+	    tag = new HTMLTag(reply);
+	    
+	    if (tag.tagName().equals("a")) {
+		start = reply.indexOf("href");
+		if (start == -1) {
+		    start = reply.indexOf("HREF");
+		}
+		
+		if (start >= 0) {
+		    start += 4;
+		    quoted = false;
+		    while (reply.charAt(start) == ' ' ||
+			   reply.charAt(start) == '=' ||
+			   reply.charAt(start) == '"') {
+			if (reply.charAt(start) == '"') {
+			    quoted = true;
+			}
+			start ++;
+		    }
+		    
+		    end = -1;
+		    if (quoted) {
+			end = reply.indexOf('"', start+1);
+		    }
+		    if (end == -1) {
+			end = reply.indexOf(' ', start+1);
+			if (end == -1) {
+			    end = reply.length() - 1;
+			}
+		    }
+		    
+		    reply = reply.substring(start, end);
+		    return reply;
+		}
+	    }
+	    reply = this.nextParse();
+	}
+	return null;
+    }
+
+    // Return the next link in the page
+    public String nextLink(AppletContext ac)
+    { 
+	String reply, reply2;
+	int start, end;
+	boolean quoted;
+	HTMLTag tag;
+	
+	if (this.document.getContent() == null){
+	    return null;
+	}
+	
+	reply = this.nextParse();
+	while (this.pos < this.document.getContent().length()){
+	    tag = new HTMLTag(reply);
+	    if (tag.tagName().equals("a")){
+		reply = tag.idValue("href");
+	    }
+	    else if (tag.tagName().equals("frame")){ // image tag
+		reply = tag.idValue("src");
+	    }
+	    else if (tag.tagName().equals("area")) { // image map area
+		reply = tag.idValue("href");
+	    }
+	    else if (tag.tagName().equals("frame")){
+		reply = tag.idValue("src");
+	    }
+	    else {
+		reply	= null;
+	    }
+	    
+	    if (reply != null){
+		return reply;
+	    }
+ 
+	    reply = this.nextParse();
+	}
+	return null;
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLTag.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLTag.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLTag.java	(revision 13666)
@@ -0,0 +1,265 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+public class HTMLTag implements HTMLObject
+{ String tagtext;
+  String name;
+  int	 docpos;
+  int    endpos;
+
+  public static final String HTML_ELEMENT_TYPE = "Element";
+
+  public HTMLTag(String tagtext, int docpos, int endpos)
+  { this.tagtext = tagtext;
+    this.name    = null;
+    this.docpos  = docpos;
+    if (this.docpos < 0)
+    { this.endpos = -1;
+    }
+    else
+    { this.endpos = endpos;
+    }
+  }
+
+  public HTMLTag(String tagtext)
+  { this.tagtext 	= tagtext;
+    this.docpos		= -1;
+    this.name			= null;
+  }
+
+  public String getHTMLType()
+  { return HTML_ELEMENT_TYPE;
+  }
+
+	public HTMLTag endTag()
+	{ HTMLTag end;
+		String	endtext;
+
+		endtext = "</"+this.xtagName()+">";
+
+		end = new HTMLTag(endtext);
+		return end;
+	}
+
+	public boolean tagIsOpening()
+	{ return (this.tagtext.charAt(1) != '/');
+	}
+
+	/**
+	 *  Tells you if a tag is a singleton tag - TODO: complete list
+	 */
+	public boolean tagIsSingleton()
+	{	String tagName = this.tagName();
+		
+		return (tagName.equals("img"));
+	}
+
+	/**
+	 *  @return: the name of a tag including any leading '/'
+	 */
+	public String tagName()
+	{ int offset, start, end;
+		String reply;
+
+		if (this.name != null)
+		{	return this.name;
+		}
+	
+		// NB: a starting '<' and an ending '>' are guaranteed
+		offset = 1; // skip <
+		while (this.tagtext.charAt(offset) <= 32 ||
+					 this.tagtext.charAt(offset) == 127)
+		{ offset ++;
+		}
+		start = offset;
+		while (this.tagtext.charAt(offset) > 32 &&
+					 this.tagtext.charAt(offset) != '>' &&
+					 this.tagtext.charAt(offset) != 127)
+		{ offset ++;
+		}
+		end = offset;
+
+		reply = this.tagtext.substring(start, end);
+		reply = reply.toLowerCase();
+
+		this.name	= reply;
+
+		return reply;
+	}
+
+	// Returns the name of the tag *minus* any leading / for
+	// closing tags
+	public String xtagName()
+	{ String reply;
+
+		reply = this.tagName();
+		if (reply == null || reply.length() == 0)
+		{	return null;
+		}
+
+		if (reply.charAt(0) == '/')
+		{ if (reply.length() > 1)
+			{	reply = reply.substring(1, reply.length());
+			}
+			else
+			{ reply = "";
+			}
+		}
+		return reply;
+	}
+
+	public String endTagName()
+	{	String reply;
+
+		reply = "/" + xtagName();
+		return reply;
+	}
+
+	public boolean isClosing()
+	{ String name;
+
+		name	= this.tagName();
+		if (name.charAt(0) == '/')
+		{	return true;
+		}
+		return false;
+	}
+
+	public int tagLevel()
+	{ String	name;
+		int			level;
+
+		level = 7;
+
+		name = this.xtagName();
+		if (name.charAt(0) == 'h')
+		{ level = Integer.parseInt(name.substring(1, 2));
+		}
+		
+		return level;
+	}
+
+	public int startPos()
+	{	return this.docpos;
+	}
+
+	public int endPos()
+	{	return this.endpos;
+	}
+
+	static public boolean isTag(String text)
+	{ if (text.charAt(0) == '<')
+		{ return true;
+		}
+		return false;
+	}
+
+	public String toString()
+	{	return this.tagtext;
+	}
+
+	//
+	// Returns the value of the identifier given as a string
+	//
+	public String idValue(String idName)
+	{	int offset, start, end;
+		int idstart, idend, valuestart, valueend;
+		boolean isvalue, isquoted, isstopped;
+		char		quotechar;
+		String reply;
+
+		// NB: a starting '<' and an ending '>' are guaranteed
+		offset = 1; // skip <
+		while (this.tagtext.charAt(offset) <= 32 ||
+					 this.tagtext.charAt(offset) == 127)
+		{ offset ++;
+		}
+		start = offset;
+		while (this.tagtext.charAt(offset) > 32 &&
+					 this.tagtext.charAt(offset) != '>' &&
+					 this.tagtext.charAt(offset) != 127)
+		{ offset ++;
+		}
+		end = offset;
+		// End of tag name
+
+		if (this.tagtext.charAt(offset) == '>')
+		{ return null;
+		}
+
+		isstopped = false;
+		while (!isstopped)
+		{	isvalue		= false;
+			isquoted	= false;
+			valuestart = -1;
+			valueend = -1;
+
+			while (this.tagtext.charAt(offset) <= 32 ||
+						this.tagtext.charAt(offset) == 127)
+			{ offset ++;
+			}
+			idstart = offset;
+
+			if (this.tagtext.charAt(offset) == '>')
+			{ break;
+			}
+
+			while (this.tagtext.charAt(offset) > 32 &&
+						 this.tagtext.charAt(offset) != '=' &&
+						 this.tagtext.charAt(offset) != '>' &&
+						 this.tagtext.charAt(offset) != 127)
+			{ offset ++;
+			}
+			idend = offset;
+
+			while (this.tagtext.charAt(offset) <= 32 ||
+						 this.tagtext.charAt(offset) == 127)
+			{ offset ++;
+			}
+
+			if (this.tagtext.charAt(offset) == '=')
+			{ isvalue = true;
+				quotechar = ' ';
+				offset ++;				
+
+				while (this.tagtext.charAt(offset) <= 32 ||
+							 this.tagtext.charAt(offset) == 127)
+				{ offset ++;
+				}
+				if (this.tagtext.charAt(offset) == '"' ||
+						this.tagtext.charAt(offset) == '\'')
+				{ quotechar = this.tagtext.charAt(offset);
+					isquoted = true;
+					offset ++;
+				}
+				valuestart = offset;
+
+				while (offset < this.tagtext.length() &&
+							 (isquoted && this.tagtext.charAt(offset) != quotechar) ||
+							 (!isquoted && this.tagtext.charAt(offset) > 32 &&
+							   this.tagtext.charAt(offset) != '>'))
+				{ offset ++;
+				}
+				valueend = offset;
+			}
+
+			if (offset >= this.tagtext.length() ||
+					this.tagtext.charAt(offset) == '>')
+			{ isstopped = true;
+			}
+			offset ++;
+
+			reply = this.tagtext.substring(idstart, idend);
+			reply = reply.toLowerCase();
+
+			if (reply.equalsIgnoreCase(idName))
+			{ if (isvalue)
+				{ return this.tagtext.substring(valuestart, valueend);
+				}
+				else
+				{ return reply;
+				}
+			}
+		}
+		return null;
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLTagVector.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLTagVector.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLTagVector.java	(revision 13666)
@@ -0,0 +1,60 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+import java.util.*;
+
+public class HTMLTagVector
+{ Vector vector;
+
+	//
+	// private: creates a Vector of tags from a comma separated list
+	//
+	public HTMLTagVector(String list)
+	{ int pos;
+		String tagname;
+
+		this.vector = new Vector(1);
+
+		// get first index
+		pos = list.indexOf(',');
+
+		// add leading tag to index, if there is > 1 tag currently
+		// in the list, and discard the tag
+		while (pos >= 0)
+		{ tagname = list.substring(0, pos);
+			list		= list.substring(pos+1, list.length());
+			this.vector.addElement((Object) tagname);
+
+			pos			= list.indexOf(',');
+		}
+
+		// add the last tag to the list
+		tagname = list;
+		this.vector.addElement((Object) tagname);
+	}
+
+	public HTMLTagVector(Vector vector)
+	{ this.vector = vector;
+	}
+
+	/**
+	 * Check whether a given tag is in the tagVector.  If <CODE>opening</CODE> is false,
+	 * then the method will return true for both opening and closing versions of the tag.
+	 * If the
+	 */
+	public boolean matches(HTMLTag tag, boolean opening)
+	{ int tagref;
+
+		if (tag.xtagName() == null)
+		{	return false;
+		}
+
+		for (tagref = 0; tagref < this.vector.size(); tagref ++)
+		{ if ((tag.xtagName().equals((String) this.vector.elementAt(tagref))) &&
+		      (tag.tagIsOpening() || !opening))
+			{ return true;
+			}
+		}
+		return false;
+	}
+
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLTidy.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLTidy.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTMLTidy.java	(revision 13666)
@@ -0,0 +1,232 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+import java.io.File;
+import java.io.FileReader;
+
+import java.net.URL;
+
+import org.w3c.dom.*;
+
+import org.xml.sax.XMLReader;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.Attributes;
+import org.xml.sax.helpers.XMLReaderFactory;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.ext.LexicalHandler;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentList;
+import org.greenstone.gsdl3.gs3build.doctypes.GMLDocument;
+
+public class HTMLTidy extends DefaultHandler
+{
+    String label;
+    File   file;
+    StringBuffer value;
+    boolean inElement;
+    boolean accumulate;
+    Document document;
+    Element  currentElement;
+    Element root;
+
+    class HTMLCommentHandler implements LexicalHandler
+    {
+	HTMLTidy parent;
+
+	HTMLCommentHandler(HTMLTidy tidier)
+	{ 
+	    this.parent = tidier;
+	}
+
+	public void comment(char ch[], int start, int length)
+	{ 
+	    String comment = new String(ch, start, length);
+	    parent.comment(comment);
+	}
+	
+	public void endCDATA()
+	{
+	}
+
+	public void endDTD()
+	{
+	}
+
+	public void endEntity(String name)
+	{
+	}
+
+	public void startCDATA()
+	{
+	}
+
+	public void startDTD(String name, String publicId, String systemId)
+	{
+	}
+
+	public void startEntity(String name)
+	{
+	}
+    }
+
+    public HTMLTidy(URL url)
+    { 
+	// TODO: complete
+    }
+
+    public HTMLTidy(File file)
+    { 
+	this.file = null;
+	this.label = null;
+	this.value = null;
+	
+	this.document = new org.apache.html.dom.HTMLDocumentImpl();
+	
+	this.currentElement = this.document.getDocumentElement();
+	this.root = this.currentElement;
+	
+	try {
+	    XMLReader handler  = new org.ccil.cowan.tagsoup.Parser();
+	    HTMLCommentHandler commentHandler = new HTMLCommentHandler(this);
+	    handler.setContentHandler(this);
+	    handler.setProperty("http://xml.org/sax/properties/lexical-handler", commentHandler);
+	    handler.parse(file.toURI().toString());
+	}
+	catch (java.io.IOException io)
+	    {
+		System.out.println(io);
+	    }
+	catch (org.xml.sax.SAXException saxEx)
+	    {
+		System.out.println(saxEx);
+	    }
+    }
+    
+    public void startElement(String URI, String localName, String qName, Attributes attributes)
+    { 
+	//System.out.println("<"+localName+">");
+	
+	if (localName.equals("html") == false) {
+	    Element childElement = this.document.createElement(localName);
+	    
+	    this.currentElement.appendChild(childElement);
+	    this.currentElement = childElement;
+	    
+	    for (int a = 0; a < attributes.getLength(); a ++){
+		String name = attributes.getLocalName(a);
+		String value = attributes.getValue(a);
+		
+		childElement.setAttribute(name, value);
+	    }
+	}
+    }
+    
+    public void comment(String text)
+    {
+	Comment comment = document.createComment(text);
+	this.currentElement.appendChild(comment);
+	//System.out.println("<!-- "+text+" -->");
+    }
+    
+    public void endElement(String URI, String localName, String qName)
+    { 
+	// System.out.println("Ending " + localName);
+	// System.out.println("</"+localName+">");
+	
+	if (localName.equals("html")) {
+	    return;
+	}
+	
+	// TODO: check is the same name as current node
+	if (!this.currentElement.getTagName().equals(localName.toUpperCase())) {
+	    // TODO: error handling
+	    System.out.println("Bad end at " + localName + " " + this.currentElement.getTagName());
+	    return;
+	}
+	
+	// Optimisation: is this an empty tag?
+	boolean isEmpty = false;
+	
+	if (this.currentElement.getChildNodes().getLength() == 1){
+	    Node child = this.currentElement.getFirstChild();
+	    
+	    if (child.getNodeType() == Node.TEXT_NODE) {
+		String text = child.getNodeValue();
+		
+		int i = 0;
+		while (i < text.length()){
+		    if (text.charAt(i) > 32 && text.charAt(i) != 160) {
+			break;
+		    }
+		    i++;
+		}
+		if (text.length() == i) {
+		    isEmpty = true;
+		}
+	    }
+	}
+	else if (this.currentElement.getChildNodes().getLength() == 0){
+	    isEmpty = true;
+	}
+	
+	boolean isSingleton = false;
+	String tagName = this.currentElement.getTagName().toLowerCase();
+	
+	if (tagName.equals("img") ||
+	    tagName.equals("br") ||
+	    tagName.equals("meta") ||
+	    tagName.equals("input") ||
+	    tagName.equals("area") ||
+	    tagName.equals("link") ||
+	    tagName.equals("base") ||
+	    //tagName.equals("img") ||
+	    tagName.equals("hr")) {
+	    isSingleton = true;
+	}
+	
+	Element parent =  (Element) this.currentElement.getParentNode();
+
+	if (isEmpty == true && !isSingleton) {
+	    // trim the current child
+	    parent.removeChild(this.currentElement);
+	    //      System.out.println("***Removing child***");
+	}
+	
+	this.currentElement = parent;
+    }
+    
+    public void characters(char c[], int start, int length)
+    { 
+	String string = new String(c, start, length);
+	Node text_node = this.document.createTextNode(string);
+	this.currentElement.appendChild(text_node);
+	//    System.out.println(string);
+    }
+    
+    public void recursePrint(Element element, int indent)
+    {
+	for (int i = 0; i < indent; i++) {
+	    System.out.print(" ");
+	}
+	System.out.println(element.toString());
+	for (int c = 0; c < element.getChildNodes().getLength(); c ++){
+	    Node n = element.getChildNodes().item(c);
+	    
+	    if (n.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
+		Element e = (Element) n;
+		
+		this.recursePrint(e, indent+2);
+	    }
+	}
+    }
+    
+    public Document getDocument()
+    { 
+	//    this.recursePrint(this.root, 0);
+	//    System.out.println(this.document.toString());
+	//    System.out.println(this.root);
+	return this.document;
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTTPTools.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTTPTools.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/HTTPTools.java	(revision 13666)
@@ -0,0 +1,22 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+import java.io.IOException;
+import java.net.*;
+
+public class HTTPTools
+{
+	public static String getMIMEType(URL url)
+	{ try
+		{	// initiate the connection
+			URLConnection connection = url.openConnection();
+
+			connection.connect(); // actually make the connection
+
+			return connection.getContentType();
+		}
+		catch (IOException exception)
+		{ // TODO: Log error reading url here...
+		}
+		return null;
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/MultiMap.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/MultiMap.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/MultiMap.java	(revision 13666)
@@ -0,0 +1,74 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.HashMap;
+import java.util.ArrayList;
+
+public class MultiMap
+{	Map map;
+	
+	public MultiMap()
+	{	this.map = new HashMap();
+	}
+
+	public boolean containsKey(Object key)
+	{	return this.map.containsKey(key);
+	}
+
+	public void setOnly(Object key, Object value)
+	{	List child = new ArrayList();
+		child.add(value);
+		this.map.put(key, child);
+	}
+
+	public void put(Object key, Object value)
+	{	List children;
+
+		children = (List) this.map.get(key);
+		if (children == null)
+		{	children = new ArrayList();
+			this.map.put(key, children);
+		}
+		children.add(value);
+	}
+
+	public Object get(Object key)
+	{	List list = this.getAll(key);
+		if (list == null)
+		{	return null;
+		}
+		return list.get(0);
+	}
+
+	public List getAll(Object key)
+	{	return (List) this.map.get(key);
+	}
+
+	public void remove(Object key)
+	{	this.map.remove(key);
+	}
+
+	public boolean remove(Object key, Object value)
+	{	if (!this.map.containsKey(key))
+		{ return false;
+		}
+
+		List children = (List) this.map.get(key);
+
+		if (children != null)
+		{	for (int i = 0; i < children.size(); i ++)
+			{	if (children.get(i).equals(value))
+				{	children.remove(i);
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	public Set keySet()
+	{	return this.map.keySet();
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/SQLUtils.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/SQLUtils.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/SQLUtils.java	(revision 13666)
@@ -0,0 +1,24 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+public class SQLUtils
+{
+	public void initCollection(String collectionName)
+	{	
+		// Check if the collection already exists
+		// if so, abort
+		// else
+		//   create document table
+		//   create section table
+		//   create metadata table
+		//   create namespace table
+		//   create metadata values table
+		//   create file section table
+		//   create file groups table
+		//   create file table
+		//   create admin table...etc.
+	}
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/URLString.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/URLString.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/URLString.java	(revision 13666)
@@ -0,0 +1,619 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+import java.applet.*;
+import java.net.*;
+
+public class URLString
+{ private String url;
+
+  private String urlbase(String url)
+  { int index;
+    String tailString, bodyString;
+    int body;
+
+    index = url.indexOf("//");
+    tailString = url.substring(index+2, url.length());
+    
+    body = tailString.indexOf('/');
+    bodyString = tailString.substring(0, body+1);
+    
+    tailString = url.substring(0, index+2) + bodyString;
+    return tailString;
+  }
+  
+  public URLString(String s)
+  { this.url = s;
+  }
+
+  public URLString(String s, String target)
+  { // reconcile
+    int sref;
+    int cref;
+    int	c;
+
+    // trim fragment identifiers
+    target = noRef(target);
+    if (target == null)
+    { this.url = s;
+      return;
+    }
+
+    // test for absolute
+    cref = target.indexOf(':');
+    if (cref >= 0)
+    { for (c = 0; c < cref; c ++)
+      { if (target.charAt(c) != '+' &&
+	    target.charAt(c) != '-' &&
+	    target.charAt(c) != '.' &&
+	    Character.isLetterOrDigit(target.charAt(c)) == false)
+	{ break;
+	}
+      }
+    }
+    else
+    { c = 0;
+    }
+
+    if (c == cref)
+    { // absolute reference
+      String tmp;
+
+      tmp = target.substring(0, c);
+      tmp = tmp.toLowerCase();
+      if (target.indexOf("//") == cref + 1)
+      { if (target.lastIndexOf('/') == cref + 2)
+	{ target = target + "/";
+	}
+      }
+      /*			if (tmp.equals("http") == false)
+				{ this.url = null;
+				return;
+				}*/
+      this.url = target;
+    }
+    else if (target.indexOf("//") == 0)
+    { // absolute - implicit scheme (ie http).; also check for no trailing '/'
+      if (target.lastIndexOf('/') == 1)
+      { target = target + "/";
+      }
+      target = "http:" + target;
+      this.url = target;
+    }
+    else
+    { // relative - trim silly '/' at end
+      if (target.charAt(0) == '/')	
+      { // if we get a leading '/' then add it to the base of the url
+	s = urlbase(s);
+	target = target.substring(1);
+	this.url = s + target;
+//				System.out.println(this.url+"<"+s+"<"+target);
+	return;
+      }
+
+      while(target.length() >= 2 && target.charAt(0) == '.' && target.charAt(1) == '.')
+      { // move up a level on the left
+	
+	sref = s.lastIndexOf('/');
+	s = s.substring(0, sref);
+
+	target = target.substring(3);
+      }
+      // strip trailing leaf from s
+      sref = s.lastIndexOf('/');
+      s = s.substring(0, sref+1);
+      // append s+target
+      this.url = s + target;
+    }
+    
+    // abandon the url if it is a call to a script
+    if (this.url.indexOf('?') >= 0)
+    { this.url = null;
+    }
+  }
+
+  public static boolean dirParent(String parent, String child)
+  { while (child.length() >= parent.length())
+    { child = child.substring(0, child.lastIndexOf('/'));
+
+      if (parent.equals(child))
+      {	return true;
+      }
+    }
+    return false;
+  }
+
+  public static int dirPos(String from, String to)
+  { String fromdir;
+    String todir;
+
+    fromdir = from.substring(0, from.lastIndexOf('/'));
+    todir   = to.substring(0, to.lastIndexOf('/'));
+
+    if (fromdir.equals(todir))
+    { return 0;
+    }
+    if (fromdir.length() > todir.length())
+    { if (dirParent(todir, fromdir) == true)
+      {	return -1;
+      }
+    }
+    else 
+    { if (dirParent(fromdir, todir) == true)
+      { return 1;
+      }
+    }
+    return -2;
+  }
+
+  public static int commonLevels(String a, String b)
+  { String 	path_a, path_b;
+    int			offset_a, offset_b;
+    String	dir_a, dir_b;
+    int			common;
+
+    path_a	= path(a);
+    path_b	= path(b);
+    common	= 0;
+
+    if (path_a == null || path_b == null)
+    { return 0;
+    }
+
+    do
+    { offset_a = path_a.indexOf('/');
+      offset_b = path_b.indexOf('/');
+
+      if (offset_a > 0)
+      { dir_a		=	path_a.substring(0, offset_a);
+        if (path_a.length() > offset_a + 1)
+	{	path_a	= path_a.substring(offset_a+1);
+	}
+	else
+	{	path_a	= null;
+	}
+      }
+      else
+      {	dir_a		=	path_a;
+        path_a	= null;
+      }
+
+      if (offset_b > 0)
+      {	dir_b		=	path_b.substring(0, offset_b);
+        if (path_b.length() > offset_b + 1)
+	{	path_b	= path_b.substring(offset_b+1);
+	}
+	else
+	{	path_b	= null;
+	}
+      }
+      else
+      {	dir_b		=	path_b;
+        path_b	= null;
+      }
+
+      if (dir_a.length() != dir_b.length() ||
+	  dir_a.equals(dir_b) == false)
+      {	return common;
+      }
+      common ++;
+    } while (path_a != null && path_b != null);
+    
+    return common;
+  }
+
+	public static String dirLevelName(String url, int level)
+	{	String 	lpath;
+		String	dir;
+		int			thislevel = 0;
+		int			offset;
+
+		lpath = path(url);
+		if (lpath == null)
+		{ return null;
+		}
+		do
+		{ offset = lpath.indexOf('/');
+
+			if (offset >= 0)
+			{	dir = lpath.substring(0, offset);
+				lpath = lpath.substring(offset+1);
+			}
+			else
+			{	dir = lpath;
+			}
+
+			thislevel ++;
+
+			if (level == thislevel)
+			{ return dir;
+			}
+		} while (offset >= 0);
+
+		return null;
+	}
+
+	public static int dirLevel(String url)
+	{	String 	lpath;
+		int			level;
+		int			offset;
+
+		lpath = path(url);
+		if (lpath == null)
+		{	return 0;
+		}
+		level = 0;
+		do
+		{ offset = lpath.indexOf('/');
+			if (offset >= 0)
+			{	lpath = lpath.substring(offset+1);
+			}
+			level ++;
+		} while (offset >= 0);
+
+		return level;
+	}
+
+	public static String tidyURL(String urlString, boolean permitScript)
+	{	int cref;
+		int c;
+		int sref;
+		String tmp, s;
+
+		s = urlString;
+		cref = s.indexOf(':');
+		if (cref >= 0)
+		{ for (c = 0; c < cref; c ++)
+			{ if (s.charAt(c) != '+' &&
+						s.charAt(c) != '-' &&
+						s.charAt(c) != '.' &&
+						Character.isLetterOrDigit(s.charAt(c)) == false)
+				{ break;
+				}
+			}
+		}
+		else
+		{ c = 0;
+		}
+
+		if (cref == c)
+		{ tmp = s.substring(0, c).toLowerCase();
+			s = tmp + s.substring(c, s.length());
+			if (s.lastIndexOf('/') == cref + 2)
+			{ s = s + "/";
+			}
+		}
+		else
+		{ sref = s.indexOf("//");
+			if (sref == 0)
+			{ s = "http:" + s;
+			}
+			else
+			{ s = "http://" + s;
+			}
+			if (s.lastIndexOf('/') == 6)
+			{ s = s + "/";
+			}
+		}
+		return s;
+	}
+
+	public static String tidyURL(String urlString)
+	{	return tidyURL(urlString, false);
+	}
+
+	public static URL toURL(String urlString)
+	{ URL reply;
+
+	  try
+		{ reply = new URL(URLString.tidyURL(urlString));
+		}
+		catch (MalformedURLException ex)
+		{ return null;
+		}
+		return reply;
+	}
+
+  public void tidy()
+  { this.url = tidyURL(this.url);
+  }
+
+  public boolean isNull()
+  { if (this.url == null)
+    { return true;
+    } 
+    return false;
+  }
+
+  public static boolean isForeign(String home, URL url)
+  { if (url.toString().length() < home.length())
+    { return true;
+    }
+
+    if (home.equals(url.toString().substring(0, home.length())))
+    { return false;
+    }
+    return true;
+  }
+  
+  /**
+   *	Remove any trailing "#localanchor" local reference from a URL string
+   *
+   *  @param  <code>String</code> the original url
+   *  @return <code>String</code> the cleaned url, sans local references
+   */
+  public static String noRef(String target)
+  { if (target == null)
+    { return null;
+    }
+    if (target.indexOf('#') >= 0)
+    { if (target.indexOf('#') == 0)
+      { return null;
+      }
+      target = target.substring(0, target.indexOf('#'));
+    }
+    return target;
+  }
+
+  /**
+   *	Obtain the trailing local anchor reference from a URL, 
+   *  if it exists.
+   *    e.g. for http://www.test.mdx.ac.uk/example/index.html#credits the
+   *         response would be "credits"
+   *
+   *  @param  <code>String</code> the original url.
+   *  @return <code>String</code> the local reference.  <code>null</code> is
+   *                              returned if no local reference exists.
+   */
+  public static String subRef(String target)
+  { if (target.indexOf('#') >= 0)
+    {	return target.substring(target.indexOf('#')+1);
+    }
+    return null;
+  }
+
+  /**
+   *	Clean a URL of the form GET parameters.
+   *
+   *  @param  <code>String</code> the original url, with GET message parameters
+   *  @return <code>String</code> the cleaned url.
+   */
+  public static String noParameters(String url)
+  { int						c;
+
+    c = url.indexOf("?");
+    if (c < 0)
+    { return url;
+    }
+    return url.substring(0, c);
+  }
+
+	/**
+	 *	Obtain the form parameters from a url
+	 *
+	 *  @param  <code>String</code> the original url, with GET message parameters
+	 *  @return <code>String</code> the form "GET" parameters.  The leading '?' is
+	 *                              preserved in the reply.  If no parameters were
+	 *                              given, the result is <code>null</code>.
+	 */
+	public static String formParameters(String url)
+	{	int						c;
+
+		c = url.indexOf("?");
+		if (c < 0)
+		{	return null;
+		}
+		return url.substring(c);
+	}
+
+	/**
+	 *	Flatten a URL, making the '?' and '&' items into underscores
+	 *
+	 *  @param  <code>String</code> the original url, with GET message parameters
+	 *  @return <code>String</code> the "flattened" url
+	 */
+	public static String flattenedUrl(String oldUrl)
+	{	StringBuffer	reply;
+		int						c;
+		boolean				modified = false;
+
+		// replace ? with _
+		// replate & with _
+		reply = new StringBuffer(oldUrl);
+		for (c = 0; c < reply.length(); c ++)
+		{	if (reply.charAt(c) == '?' ||
+					reply.charAt(c) == '&')
+			{	reply.setCharAt(c, '_');
+				modified = true;
+			}
+		}
+
+		if (modified == true)
+		{	c	= oldUrl.indexOf(".html");
+			if (c >= 0)
+			{	while (c < oldUrl.length() - 5)
+				{	reply.setCharAt(c, reply.charAt(c+5));
+					c ++;
+				}
+				reply.setCharAt(c ++, '.');
+				reply.setCharAt(c ++, 'h');
+				reply.setCharAt(c ++, 't');
+				reply.setCharAt(c ++, 'm');
+				reply.setCharAt(c ++, 'l');
+			}
+		}
+
+		return reply.toString();
+	}
+
+	/**
+	 *	Provide the complete pathname in the given url
+	 *    eg. "example/index.html" for http://www.test.mdx.ac.uk/example/index.html
+	 *
+	 *  @param  <code>String</code> url of page
+	 *	@return <code>String</code> leaf file name
+	 */
+	public static String pathName(String url)
+	{	int offset;
+		String remainder;
+
+		if (url == null)
+		{ return null;
+		}
+
+		offset = url.indexOf("//");
+		if (offset < 0)
+		{ return null;
+		}
+
+		remainder = url.substring(offset + 2);
+		offset = remainder.indexOf('/');
+		if (offset < 0)
+		{	return null;
+		}
+		return remainder.substring(offset + 1);
+	}
+
+	/**
+	 *	Provide the leaf filename in the given url
+	 *    eg. "index.html" for http://www.test.mdx.ac.uk/example/index.html
+	 *
+	 *  @param  <code>String</code> url of page
+	 *	@return <code>String</code> leaf file name
+	 */
+	public static String leafName(String url)
+	{	int offset;
+		int dot;
+
+		if (url == null)
+		{	return null;
+		}
+		offset = url.lastIndexOf('/');
+		if (offset < 0)
+		{ return null;
+		}
+		if (offset == url.length() - 1)
+		{ return null;
+		}
+		dot = url.lastIndexOf('/');
+		if (dot < offset)
+		{	return null;
+		}
+		return url.substring(offset+1);
+	}
+
+	/**
+	 *	Provide the hostname in the given url
+	 *    eg. "www.test.mdx.ac.uk" for http://www.test.mdx.ac.uk/example/index.html
+	 *
+	 *  @param  <code>String</code> url of page
+	 *	@return <code>String</code> host name
+	 */
+	public static String host(String url)
+	{	String scheme, tail;
+		int		 spos;
+
+		spos = url.indexOf("//");
+		if (spos >= 0)
+		{ scheme = url.substring(0, spos + 2);
+			tail = url.substring(spos + 2, url.length());
+			// do sub-areas
+			spos = tail.indexOf('/');
+			if (spos >= 0)
+			{ tail = tail.substring(0, spos+1);
+			}
+			scheme = scheme + tail;
+			return scheme;
+		}
+		return null;
+	}
+
+	/**
+	 *	Return the logical path of the url on the remote server
+	 *    eg. "example" for http://www.test.mdx.ac.uk/example/index.html
+	 *
+	 *  @param  <code>String</code> url of page
+	 *	@return <code>String</code> logical path
+	 */
+	public static String path(String url)
+	{ String tail;
+		int offset;
+		String leaf;
+
+		if (url == null)
+		{ return null;
+		}
+
+		offset 	= url.indexOf("//");
+		if (offset < 0)
+		{	return null;
+		}
+
+		tail		= url.substring(offset+2);
+		offset	= tail.indexOf('/');
+		if (offset < 0)
+		{	return null;
+		}
+
+		tail		= tail.substring(offset+1);
+		if (tail == null || tail.length() == 0)
+		{	return null;
+		}
+
+		offset	= tail.lastIndexOf('/');
+		if (offset < 0)
+		{ return null;
+		}
+		else
+		{	tail = tail.substring(0, offset);
+		}
+		return tail;
+	}
+
+	/**
+	 *	Give the 'dot' extension of a url; 
+	 *    eg. "html" for http://www.test.mdx.ac.uk/example/index.html
+	 *
+	 *	@param <code>String</code> url
+	 *  @return <code>String</code> extension.
+	 */
+	public static String extension(String url)
+	{ int offset;
+		String leaf;
+
+		if (url == null)
+		{ return null;
+		}
+
+		offset = url.lastIndexOf('/');
+		if (offset >= 0 && offset < url.length() - 1)
+		{ leaf = url.substring(offset+1, url.length());
+			offset = leaf.lastIndexOf('.');
+
+			// if we've got an extension then use it
+			if (offset >= 0)
+			{ int poffset;
+
+				// get parameter offset
+				poffset = leaf.indexOf('?');
+				if (poffset < 0)
+				{	poffset = leaf.length();
+				}
+
+				// give leaf value
+				return leaf.substring(offset, poffset);
+			}
+			else
+			{ return null;
+			}
+		}
+		return null;
+	}
+
+  public static String extension(URL url)
+  { return extension(url.toString());
+  }
+
+  public String toString()
+  { return this.url;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/URLTools.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/URLTools.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/URLTools.java	(revision 13666)
@@ -0,0 +1,20 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+import java.net.URL;
+import java.io.File;
+
+public class URLTools
+{
+  public static URL getFileURL(File file)
+  { URL url;
+    String normalisedFileName = file.toString().replace(File.separatorChar, '/');
+
+    try {
+      url = new URL("file", "", normalisedFileName);
+    }
+    catch (java.net.MalformedURLException ex) {
+      return null;
+    }
+    return url;
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/XMLTools.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/XMLTools.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/util/XMLTools.java	(revision 13666)
@@ -0,0 +1,82 @@
+package org.greenstone.gsdl3.gs3build.util;
+
+public class XMLTools
+{
+    public static String getTag(String namespace, String label, boolean open)
+    {	
+	StringBuffer reply = new StringBuffer();
+
+	reply.append("<");
+	if (!open)
+	    {	
+		reply.append("/");
+	    }
+	if (namespace != null && namespace.length() > 0) {
+	    reply.append(namespace);
+	    reply.append(":");
+	}
+	reply.append(label);
+	reply.append(">");
+	return reply.toString();
+    }
+
+    public static String addAttribute(String tag, String attribute, String value)
+    {	
+	StringBuffer reply = new StringBuffer(tag);
+	reply.insert(reply.length() - 1 , ' ');
+	reply.insert(reply.length() - 1 , attribute);
+	reply.insert(reply.length() - 1 , "=\"");
+	reply.insert(reply.length() - 1 , value);
+	reply.insert(reply.length() - 1 , '\"');
+	return reply.toString();
+    }
+
+    public static String makeSingleton(String tag)
+    {	
+	StringBuffer reply = new StringBuffer(tag);
+	reply.insert(tag.length() - 1, " /");
+	return reply.toString();
+    }
+    
+    public static String getOpenTag(String namespace, String label)
+    {	
+	return getTag(namespace, label, true);
+    }
+    
+    public static String getCloseTag(String namespace, String label)
+    {	
+	return getTag(namespace, label, false);
+    }
+
+    /**
+     *  Clean a string to remove whitespace...
+     *
+     *  @param <code>String</code> the original text
+     *  @return <code>String</code> the 'cleaned' text
+     */
+    public static String cleanString(String original)
+    {	
+	StringBuffer buffer = new StringBuffer(original);
+
+	while (buffer.charAt(0) <= 32) {
+	    buffer.deleteCharAt(0);
+	}
+	
+	while (buffer.charAt(buffer.length() - 1) <= 32){
+	    buffer.deleteCharAt(buffer.length() - 1);
+	}
+	
+	int c = 1;
+	while (c < buffer.length()){
+	    if (buffer.charAt(c) < 32){
+		buffer.setCharAt(c, ' ');
+	    }
+	    if (buffer.charAt(c) == ' ' && buffer.charAt(c-1) == ' '){
+		buffer.deleteCharAt(c);
+		continue;
+	    }
+	    c ++;
+	}
+	return buffer.toString();
+    }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/validator/ValidatorInterface.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/validator/ValidatorInterface.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/validator/ValidatorInterface.java	(revision 13666)
@@ -0,0 +1,24 @@
+package org.greenstone.gsdl3.gs3build.validator;
+
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentInterface;
+import org.greenstone.gsdl3.gs3build.doctypes.DocumentID;
+
+public interface ValidatorInterface
+{
+	/**
+	 *  Record the build manager to use for this expander - this is used
+	 *  to pass back any new directories into which expanded files are placed.
+	 */
+	public void configure();
+
+	/**
+	 *  Attempt to expand a file.  The returned result is <code>true</code> if the
+	 *  file was actually expanded.
+	 *
+	 *  @param <code>DocumentID</code> the identity code of the document
+	 *  @param <code>DocumentInterface</code> the document itself
+	 *
+	 *  @return <code>boolean</code> whether the file was validated.
+	 */
+	public boolean validateDocument(DocumentID docID, DocumentInterface document);
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/xpointer/IdentifierXPointer.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/xpointer/IdentifierXPointer.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/xpointer/IdentifierXPointer.java	(revision 13666)
@@ -0,0 +1,59 @@
+package org.greenstone.gsdl3.gs3build.xpointer;
+
+import org.w3c.dom.*;
+import org.apache.xpath.*;
+
+public class IdentifierXPointer extends XPointer
+{ NodeList nodes;
+
+  public IdentifierXPointer(Document document, String xpointer)
+  { super(document, xpointer);
+
+    this.xpointer = XPointer.expandXPath(this.xpointer);
+
+    this.nodes = this.getNodes();
+  }
+
+  private NodeList getNodes()
+  {
+    try {
+      NodeList nodes = XPathAPI.selectNodeList(this.document, this.xpointer, 
+					       this.document.getDocumentElement());
+      return nodes;
+    }
+    catch (Exception ex)
+    { System.out.println(ex.toString());
+    }
+    return null;
+  }
+
+  public Node getStartNode()
+  { return this.nodes.item(0);
+  }
+
+  private void recurseStringify(NodeList nodes, StringBuffer buffer)
+  { 
+    for (int n = 0; n < nodes.getLength(); n ++) {
+      Node node = nodes.item(n);
+
+      // append the actual node itself
+      this.printNode(node, buffer, false);
+
+      // then process its children...
+      if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
+	NodeList children = node.getChildNodes();
+	this.recurseStringify(children, buffer);
+      }
+
+      // do the close node
+      this.printNode(node, buffer, true);
+    }
+  }
+
+  public String toString()
+  {
+    StringBuffer reply = new StringBuffer();
+    this.recurseStringify(this.nodes, reply);
+    return reply.toString();
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/xpointer/RangeToXPointer.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/xpointer/RangeToXPointer.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/xpointer/RangeToXPointer.java	(revision 13666)
@@ -0,0 +1,69 @@
+package org.greenstone.gsdl3.gs3build.xpointer;
+
+import org.w3c.dom.*;
+import org.apache.xpath.*;
+
+public class RangeToXPointer extends XPointer
+{
+  public static final String RANGE_TO = "range-to(";
+  NodeList startNodes;
+  NodeList endNodes;
+
+  public RangeToXPointer(Document document, String xpointer)
+  { super(document, xpointer);
+
+    String fromPointer, toPointer;
+
+    int rangeAt = xpointer.indexOf(RANGE_TO);
+
+    fromPointer = xpointer.substring(0, rangeAt-1);
+    toPointer = xpointer.substring(rangeAt+RANGE_TO.length(), xpointer.length()-1);
+
+    fromPointer = XPointer.expandXPath(fromPointer);
+    toPointer   = XPointer.expandXPath(toPointer);
+    //    System.out.println(fromPointer + " " + toPointer);
+    
+    this.startNodes = this.getNodes(fromPointer);
+    this.endNodes = this.getNodes(toPointer);
+    
+    //    System.out.println(this.startNodes.item(0).toString() + " " + this.endNodes.item(0).toString());
+  }
+
+  public Node getStartNode()
+  { return this.startNodes.item(0);
+  }
+
+  private NodeList getNodes(String pointer)
+  {
+    try {
+      NodeList nodes = XPathAPI.selectNodeList(document, pointer, document.getDocumentElement());
+      return nodes;
+    }
+    catch (Exception ex)
+    { System.out.println(ex.toString());
+    }
+    return null;
+  }
+
+  private void recurseStringify(Node at, Node end, StringBuffer reply)
+  {
+    while (at != end && at != null) {
+      this.printNode(at, reply, false);
+      at = this.getNextNode(at, reply);
+      //      System.out.println(at + " " + end);
+    }
+  }
+
+  public String toString()
+  { StringBuffer reply = new StringBuffer();
+
+    // skip the first node
+    Node firstNode = this.startNodes.item(0);
+    firstNode = this.getNextNode(firstNode, reply);
+    
+    // actually, we don't, as otherwise the indexed copy of 
+    // the document would be incomplete...
+    this.recurseStringify(this.startNodes.item(0), this.endNodes.item(0), reply);
+    return reply.toString();
+  }
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/xpointer/XPointer.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/xpointer/XPointer.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/gs3build/xpointer/XPointer.java	(revision 13666)
@@ -0,0 +1,281 @@
+package org.greenstone.gsdl3.gs3build.xpointer;
+
+import java.io.File; 
+
+import java.net.URL;
+
+import javax.xml.parsers.*;
+
+import org.w3c.dom.*;
+import org.apache.xpath.*;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import org.greenstone.gsdl3.gs3build.doctypes.HTMLDocumentTools;
+import org.greenstone.gsdl3.gs3build.util.HTMLTidy;
+
+public abstract class XPointer
+{
+  Document document;  
+  String   xpointer;
+
+  public XPointer(org.w3c.dom.Document document, String xpointer)
+  { this.document = document;
+    this.xpointer = xpointer;
+    // now process the type of description
+  }
+
+  public static String expandXPath(String xpath)
+  {
+    int          dashAt;
+    String       pathElement;
+    StringBuffer expandedPtr = new StringBuffer();
+
+    if (xpath.startsWith("//")) {
+      xpath = xpath.substring(2);
+      expandedPtr.append("//");
+    }
+    else if (xpath.startsWith("/")) {
+      xpath = xpath.substring(1);
+      expandedPtr.append("/");
+    }
+
+    while (xpath.length() > 0) {
+      dashAt = xpath.indexOf('/');
+      if (dashAt >= 0) {
+	pathElement = xpath.substring(0, dashAt);
+	xpath = xpath.substring(dashAt+1);
+      }
+      else {
+	pathElement = xpath;
+	xpath = "";
+      }
+
+      int c = 0;
+      while (c < pathElement.length()) {
+	if (!Character.isDigit(pathElement.charAt(c))) 
+	  break;
+	c ++;
+      }
+
+      if (c == pathElement.length()) {
+	expandedPtr.append("*[");
+	expandedPtr.append(pathElement);
+	expandedPtr.append("]");
+      }
+      else {
+	expandedPtr.append(pathElement);
+      }
+
+      if (dashAt >= 0) {
+	expandedPtr.append('/');
+      }
+    }
+    xpath = expandedPtr.toString();
+
+    return xpath;
+  }
+
+  public static XPointer processXPointer(Document document, String xpointer)
+  { // do a "cheap and dirty" detection of range-to
+    if (xpointer.indexOf("range-to") >= 0) {
+      return new RangeToXPointer(document, xpointer);
+    } 
+    return new IdentifierXPointer(document, xpointer);
+  }
+
+  public static XPointer processXPointer(Document document, URL url)
+  { String reference = url.getRef();
+
+    reference.trim();
+    if (reference.startsWith("xpointer(")) {
+      reference = reference.substring(9, reference.length() - 1);
+    }
+    else {
+      return null;
+    }
+    //    System.out.println(reference);
+    
+    return processXPointer(document, reference);
+  }
+
+  public static void printNode(Node node, StringBuffer to, boolean close)
+  {
+    if (node.getNodeType() == org.w3c.dom.Node.TEXT_NODE) {
+      if (!close) {
+	to.append(node.getNodeValue());
+	to.append(" ");
+      }
+    }
+    else if (node.getNodeType() == org.w3c.dom.Node.ENTITY_NODE) {
+      if (!close) {
+	to.append("&");
+	to.append(node.getNodeValue());
+	to.append(";");
+	to.append(" ");
+      }
+    }
+    else if (node.getNodeType() == org.w3c.dom.Node.COMMENT_NODE) {
+      if (!close) {
+	to.append("<!-- ");
+	to.append(node.getNodeValue());
+	to.append(" -->");
+      }
+    }
+    else if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
+      boolean hasChildren = (node.getChildNodes().getLength() > 0);
+
+      if (close && !hasChildren) {
+	return;
+      }
+      to.append("<");
+      if (close) {
+	to.append("/");
+      }
+      to.append(node.getNodeName());
+
+      if (!close) {
+	NamedNodeMap attributes = ((Element) node).getAttributes();
+	for (int a = 0; a < attributes.getLength(); a ++) {
+	  Node attributeNode = attributes.item(a);
+	  to.append(" ");
+	  to.append(attributeNode.getNodeName());
+	  
+	  String value = attributeNode.getNodeValue();
+	  if (value != null && value.length() > 0) {
+	    to.append("=\"");
+	    to.append(value);
+	    to.append("\"");
+	  }
+	}
+      }
+
+      if (!hasChildren) {
+	to.append(" /");
+      }
+      to.append(">");
+      if (close && node.getNodeName()=="Section") {
+	  to.append((char) 3);
+      }
+    }
+  }
+
+    public static Node getNextNode(Node currentNode) {
+	
+	// Try to get the first valid child
+	NodeList children = currentNode.getChildNodes();
+	for (int c = 0; c < children.getLength(); c++) {
+	    Node childNode = children.item(c);
+	    
+	    if (childNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE ||
+		childNode.getNodeType() == org.w3c.dom.Node.COMMENT_NODE ||
+		childNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE ||
+		childNode.getNodeType() == org.w3c.dom.Node.ENTITY_NODE) {
+		return childNode;
+	    }
+	}	
+	
+	// now try a siblings and parents siblings
+	Node siblingNode = null;
+	do {
+	    siblingNode = currentNode.getNextSibling();
+	    if (siblingNode != null) {
+		// should we be checking type??
+		return siblingNode;
+	    }
+	    
+	    currentNode = currentNode.getParentNode();
+	} while (currentNode != null);
+	
+	return null;
+    }
+
+    
+  public static Node getNextNode(Node currentNode, StringBuffer buffer)
+  { Node reply;
+
+    // Try for children only the once...
+    NodeList children = currentNode.getChildNodes();
+    for (int c = 0; c < children.getLength(); c++) {
+      Node childNode = children.item(c);
+
+      if (childNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE ||
+	  childNode.getNodeType() == org.w3c.dom.Node.COMMENT_NODE ||
+	  childNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE ||
+	  childNode.getNodeType() == org.w3c.dom.Node.ENTITY_NODE) {
+	return childNode;
+      }
+    }
+    
+    // Repeat looking for a sibling & going up until done...
+    do {
+      reply = currentNode.getNextSibling();
+      if (reply != null) {
+	return reply;
+      }
+      
+      currentNode = currentNode.getParentNode();
+      if (buffer != null && currentNode != null) {
+	printNode(currentNode, buffer, true);
+      }
+    } while (currentNode != null);
+
+    return reply;
+  }
+
+  public abstract Node getStartNode();
+
+
+  public static void main(String args[])
+  {	
+    try
+    { File file = new File(args[0]);
+
+      Document document;
+      if (args[0].endsWith(".html") || args[0].endsWith(".htm")) {
+	HTMLTidy tidier = new HTMLTidy(file);
+	document = tidier.getDocument();
+
+	HTMLDocumentTools docTools = new HTMLDocumentTools(document);
+	docTools.findSections();
+	System.out.println("Sections found");
+      }
+      else {
+	DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+	DocumentBuilder builder = factory.newDocumentBuilder();
+	document = builder.parse(file);
+      }
+      
+      XPointer pointer = null;
+      if (args.length < 2) {
+      }
+      else if (args.length == 2) {
+	pointer = XPointer.processXPointer(document, args[1]);
+      }
+      else {
+	pointer = XPointer.processXPointer(document, args[1]+"/range-to("+args[2]+")");
+      }
+      if (pointer != null) {
+	System.out.println(pointer.toString());
+      }
+    }
+    catch (FactoryConfigurationError e) {
+      System.err.println(e);
+    }
+    catch (ParserConfigurationException ex) {
+      System.err.println(ex);
+    }
+    catch (SAXException ex) {
+      System.err.println(ex);
+    }
+    catch (java.io.IOException ex) {
+      System.err.println(ex);
+    }
+  }
+}
+
+
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/service/AbstractGS3DocumentRetrieve.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/service/AbstractGS3DocumentRetrieve.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/service/AbstractGS3DocumentRetrieve.java	(revision 13666)
@@ -0,0 +1,218 @@
+/*
+ *    AbstractGS3DocumentRetrieve.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.GS3OID;
+import org.greenstone.gsdl3.util.MacroResolver;
+import org.greenstone.gsdl3.util.GS2MacroResolver;
+import org.greenstone.gsdl3.util.GSConstants;
+import org.greenstone.gsdl3.util.SQLQuery;
+
+// 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;
+
+/** Implements the generic retrieval and classifier services for GS3 
+ * 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 AbstractGS3DocumentRetrieve
+    extends AbstractDocumentRetrieve {
+    protected static final String INDEX_STEM_ELEM = "indexStem";
+
+    protected SQLQuery database = null;
+    protected String index_stem = null;
+
+
+    /** constructor */
+    protected AbstractGS3DocumentRetrieve()
+    {
+	this.database = new SQLQuery();
+	// set up a macro resolver
+    }
+    
+    public void cleanUp() {
+	super.cleanUp();
+	this.database.closeConnection();
+    }
+
+    /** configure this service */
+    public boolean configure(Element info, Element extra_info)
+    {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+
+	System.out.println("Configuring AbstractGS3DocumentRetrieve...");
+
+	// the index stem is either specified in the config file or is "index"
+	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("")) {
+	    System.err.println("GS3MGRetrieve.configure(): indexStem element not found, stem will default to 'index'");
+	    this.index_stem = "index";
+	}
+
+	// open the database for querying
+	// the database name is a combination of site name and collection name
+
+	// check that site_home is set
+	if (this.site_home == null || this.site_home.equals("")) {
+	    System.err.println("GS3Retrieve Error: site_home is not set, so cannot work out the site name and cannot determine the database name");
+	    return false;
+	}
+	String site_name = this.site_home.substring(this.site_home.lastIndexOf(File.separator)+1);
+	if (site_name.equals("")) {
+	    System.err.println("GS3Retrieve Error: Cannot extract the site name from site home: "+this.site_home);
+	    return false;
+	}
+
+	if (!database.setDatabase(site_name+"_"+this.cluster_name)) {
+	    System.err.println("GS3Retrieve Error: Could not open SQL 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) {
+	// should really use a sql query
+	return GS3OID.translateOID(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 GS3OID.getTop(node_id);
+    }
+    
+    /** returns a list of the child ids in order, null if no children */
+    protected ArrayList getChildrenIds(String node_id) {
+	if (GS3OID.isDocTop(node_id)) { // hack
+	    node_id =  GS3OID.createOID(node_id, "1");
+	}
+	ArrayList documents = database.getDocumentChildren(node_id);
+	if (documents == null || documents.size()==0) {
+	    return null;
+	}
+	return documents;
+    }
+    
+    /** returns the node id of the parent node, null if no parent */
+    protected String getParentId(String node_id){
+	String parent = GS3OID.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);
+
+	if (all_metadata) {
+	    // TODO
+	    
+
+	} else {
+	    for (int m = 0; m < metadata_names.size(); m++) {
+		String metadata = (String) metadata_names.get(m);
+		String value = null;
+		value = database.getDocumentMetadata(node_id, metadata);
+		if (value != null) {
+		    GSXML.addMetadata(this.doc, metadata_list, metadata, 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) {
+	return null; // not implemented yet
+    }
+
+    
+    /** 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) {
+	boolean hierarchical = false;
+	if (!GS3OID.isDocTop(node_id) || database.isHierarchicalDocument(node_id) ) {
+	    hierarchical = true;
+	} 
+	// what about paged???
+	if (!hierarchical) {
+	    // a simple document
+	    return GSXML.DOC_TYPE_SIMPLE;
+	} else {
+	    // a hierarchical doc
+	    return GSXML.DOC_TYPE_HIERARCHY;
+	}
+	// don't have paged yet.
+    }
+
+    protected String resolveRelativeLinks(String doc_content, String doc_id) {
+
+	String http_path  = this.site_http_address + "/collect/"+this.cluster_name;
+	doc_content = doc_content.replaceAll("_httpcollection_", http_path);
+	return doc_content;
+	
+    }
+
+    /** 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) throws GSException;
+
+}   
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/service/GS3Browse.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/service/GS3Browse.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/service/GS3Browse.java	(revision 13666)
@@ -0,0 +1,193 @@
+/*
+ *    GS3Browse.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.GS3OID;
+import org.greenstone.gsdl3.util.GSXML;
+import org.greenstone.gsdl3.util.GSFile;
+import org.greenstone.gsdl3.util.SQLQuery;
+
+// 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.io.File;
+
+/** Greenstone 3 collection classifier service
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ */
+public class GS3Browse
+    extends AbstractBrowse
+{
+
+    protected SQLQuery database = null;
+
+    /** constructor */
+    public GS3Browse()
+    {
+	this.database = new SQLQuery();
+
+    }
+
+    public void cleanUp() {
+	super.cleanUp();
+	this.database.closeConnection();
+    }
+    
+    public boolean configure(Element info, Element extra_info)
+    {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+
+	System.err.println("Configuring GS3Browse...");
+	
+	// open the database for querying
+	// the database name is a combination of site name and collection name
+
+	// check that site_home is set
+	if (this.site_home == null || this.site_home.equals("")) {
+	    System.err.println("GS3Retrieve Error: site_home is not set, so cannot work out the site name and cannot determine the database name");
+	    return false;
+	}
+	String site_name = this.site_home.substring(this.site_home.lastIndexOf(File.separator)+1);
+	if (site_name.equals("")) {
+	    System.err.println("GS3Retrieve Error: Cannot extract the site name from site home: "+this.site_home);
+	    return false;
+	}
+	if (!database.setDatabase(site_name+"_"+this.cluster_name)) {
+	    System.err.println("GS3Retrieve Error: Could not open SQL 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) {
+	// should really use a sql query
+	return GS3OID.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) {
+	boolean hierarchical = false;
+	if (!GS3OID.isDocTop(node_id) || database.isHierarchicalDocument(node_id) ) {
+	    hierarchical = true;
+	} 
+	// what about paged???
+	if (!hierarchical) {
+	    // a simple document
+	    return GSXML.DOC_TYPE_SIMPLE;
+	} else {
+	    // a hierarchical doc
+	    return GSXML.DOC_TYPE_HIERARCHY;
+	}
+	// don't have paged yet.
+   }
+    
+    /** 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 GS3OID.getDocID(node_id);
+    }
+    
+   /** returns a list of the child ids in order, null if no children */
+    protected ArrayList getChildrenIds(String node_id) {
+	ArrayList documents = database.getClassifierDocChildren(node_id);
+	if (documents == null) {
+	    documents = new ArrayList();
+	}
+	ArrayList children = database.getClassifierChildren(node_id);
+	if (children != null) {
+	    documents.addAll(children);
+	}
+	if (documents.size()==0) {
+	    return null;
+	}
+	return documents;
+    }
+
+    /** returns the node id of the parent node, null if no parent */
+    protected String getParentId(String node_id){
+	String parent = GS3OID.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) {
+	Element metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
+
+	if (all_metadata) {
+	    // TODO
+	    
+
+	} else {
+	    for (int m = 0; m < metadata_names.size(); m++) {
+		String metadata = (String) metadata_names.get(m);
+		String value = null;
+		value = database.getClassifierMetadata(node_id, metadata);
+		if (value != null) {
+		    GSXML.addMetadata(this.doc, metadata_list, metadata, 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) {
+	return null;
+    }
+
+    /** 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/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/service/GS3MGPPRetrieve.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/service/GS3MGPPRetrieve.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/service/GS3MGPPRetrieve.java	(revision 13666)
@@ -0,0 +1,121 @@
+/*
+ *    GS3MGPPRetrieve.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;
+import org.greenstone.gsdl3.util.GS3OID;
+
+// XML classes
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
+
+// General Java classes
+import java.io.File;
+
+public class GS3MGPPRetrieve
+    extends AbstractGS3DocumentRetrieve
+{
+    // 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 GS3MGPPRetrieve() {
+	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)
+    {
+	// Do generic configuration
+	if (!super.configure(info, extra_info)) {
+	    return false;
+	}
+
+	// Do specific configuration
+	System.out.println("Configuring GS3MGPPRetrieve...");
+
+	// 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.NAME_ATT);
+	}
+	if (this.default_level == null || this.default_level.equals("")) {
+	    System.err.println("Error: default level not specified!");
+	    return false;
+	}
+	// System.out.println("Default level: " + default_level_);
+	
+	// The location of the MGPP text files
+	mgpp_textdir = GSFile.collectionBaseDir(this.site_home, this.cluster_name) +
+	    File.separatorChar + GSFile.collectionTextPath(this.index_stem);
+
+	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) throws GSException {
+	if (GS3OID.isDocTop(doc_id) && database.isHierarchicalDocument(doc_id)) {
+	    // if we have a whole doc id, and the document is hierarchical,
+	    // we want to change the id to be the top id of the section 
+	    // hierarchy
+	    doc_id = GS3OID.createOID(doc_id, "1");
+	}
+
+	String doc_num = this.database.OID2MGNum(doc_id);	    
+	// doc nums have the index prefixed 
+	doc_num = doc_num.substring(doc_num.indexOf(".")+1);
+	int doc_int = Integer.parseInt(doc_num);
+
+	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_int);
+	    doc_content = resolveRelativeLinks(doc_content, doc_id);
+	} catch (Exception e) {
+	    System.out.println("exception happended with mgpp_src.getDocument()" + e);
+	    doc_content = "this is the content for section hash id "+ doc_id+", mgpp doc num "+doc_int+"\n";
+	}
+
+	Text t = this.doc.createTextNode(doc_content);
+	content_node.appendChild(t);
+	return content_node;
+
+    }
+
+
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/service/GS3MGPPSearch.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/service/GS3MGPPSearch.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/service/GS3MGPPSearch.java	(revision 13666)
@@ -0,0 +1,141 @@
+/*
+ *    GS3MGPPSearch.java
+ *    Copyright (C) 2005 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.GSXML;
+import org.greenstone.gsdl3.util.GS3OID;
+import org.greenstone.gsdl3.util.SQLQuery;
+
+// XML classes
+import org.w3c.dom.Document;
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList;
+
+// java classes
+import java.io.File;
+
+
+/**
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ */
+
+public class GS3MGPPSearch 
+    extends AbstractMGPPSearch 
+{
+    protected SQLQuery database = null;
+    /** the base index prefix */
+    protected String base_index_prefix = null;
+
+
+    /** constructor */
+    public GS3MGPPSearch()
+    {
+	this.database = new SQLQuery();
+    }
+
+    public void cleanUp() {
+	super.cleanUp();
+	this.database.closeConnection();
+    }
+
+    /** configure this service */
+    public boolean configure(Element info, Element extra_info)
+    {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+
+	// get the base prefix
+	Element def = (Element) GSXML.getChildByTagName(info, "baseIndexPrefix");
+	if (def != null) {
+	    this.base_index_prefix = def.getAttribute(GSXML.NAME_ATT);
+	}
+	if (this.base_index_prefix == null || this.base_index_prefix.equals("")) {
+	    System.err.println("Error: base index prefix not specified!");
+	    return false;
+	}
+	String site_name = this.site_home.substring(this.site_home.lastIndexOf(File.separator)+1);
+	if (site_name.equals("")) {
+	    System.err.println("GS3Search Error: Cannot extract the site name from site home: "+this.site_home);
+	    return false;
+	}
+	if (!database.setDatabase(site_name+"_"+this.cluster_name)) {
+	    System.err.println("GS3Search Error: Could not open SQL database!");
+	    return false;
+	}
+
+	return true;
+    }
+    /** 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){
+	boolean hierarchical = false;
+	if (!GS3OID.isDocTop(node_id) || database.isHierarchicalDocument(node_id) ) {
+	    hierarchical = true;
+	} 
+	// what about paged???
+	if (!hierarchical) {
+	    // a simple document
+	    return GSXML.DOC_TYPE_SIMPLE;
+	} else {
+	    // a hierarchical doc
+	    return GSXML.DOC_TYPE_HIERARCHY;
+	}
+	// don't have paged yet.
+
+    }
+    
+    /** returns true if the node has child nodes */
+    protected boolean hasChildren(String node_id){
+	return database.documentHasChildren(node_id);
+    }
+    
+    /** returns true if the node has a parent */
+    protected boolean hasParent(String node_id){
+	String parent = GS3OID.getParent(node_id);
+	if (parent.equals(node_id)) {
+	    return false;
+	}
+	return true;
+    }
+    
+   /** convert MGPP internal id to Greenstone oid */
+    protected String MGPPNum2OID(long docnum)
+    {
+	String mg_id = this.base_index_prefix+"."+docnum;
+	String doc_id = database.MGNum2OID(mg_id);
+	// hack !!!
+	if (doc_id.endsWith("-All")) {
+	    // get rid of the All bit
+	    doc_id = doc_id.substring(0,doc_id.length()-4);
+	    //doc_id=doc_id.replaceAll("All","1");
+	}
+	return doc_id;
+	
+    }
+
+}
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/service/GS3MGRetrieve.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/service/GS3MGRetrieve.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/service/GS3MGRetrieve.java	(revision 13666)
@@ -0,0 +1,133 @@
+/*
+ *    GS3MGRetrieve.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;
+import org.greenstone.gsdl3.util.GS3OID;
+
+// XML classes
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
+
+// General Java classes
+import java.io.File;
+
+public class GS3MGRetrieve
+    extends AbstractGS3DocumentRetrieve
+{
+    // Elements used in the config file that are specific to this class
+    private static final String DEFAULT_INDEX_ELEM = "defaultIndex";
+
+    private MGWrapper mg_src = null;
+    private String mg_basedir = null;
+    private String mg_textdir = null;
+    private String default_index = null;
+    
+    public GS3MGRetrieve() {
+	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)
+    {
+	// Do generic configuration
+	if (!super.configure(info, extra_info)) {
+	    return false;
+	}
+
+	// Do specific configuration
+	System.out.println("Configuring GS3MGRetrieve...");
+	// System.out.println("info:\n" + converter_.getString(info));
+	// System.out.println("extra_info:\n" + converter_.getString(extra_info));
+
+	// 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.NAME_ATT);
+	}
+	if (this.default_index == null || this.default_index.equals("")) {
+	    System.err.println("Error: default index not specified!");
+	    return false;
+	}
+
+	// System.out.println("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);
+	return true;
+    }
+    
+    /** returns the content of a node.
+     * node_id should already have been translated if necessary
+     * should return a nodeContent element:
+     * <nodeContent>text content or other elements</nodeContent>
+     */
+    protected Element getNodeContent(String doc_id) throws GSException {
+
+	if (GS3OID.isDocTop(doc_id) && database.isHierarchicalDocument(doc_id)) {
+	    // if we have a whole doc id, and the document is hierarchical,
+	    // we want to change the id to be the top id of the section 
+	    // hierarchy
+	    doc_id = GS3OID.createOID(doc_id, "1");
+	}
+
+	String doc_num = this.database.OID2MGNum(doc_id);	    
+	// doc nums have the index prefixed 
+	doc_num = doc_num.substring(doc_num.indexOf(".")+1);
+	int doc_int = Integer.parseInt(doc_num);
+	
+	String doc_content = "";
+	try {
+	    doc_content = this.mg_src.getDocument(this.mg_basedir, 
+						  this.mg_textdir, 
+						  doc_int);
+	    // remove any ctrl-c or ctrl-b 
+	    doc_content = doc_content.replaceAll("\u0002|\u0003", "");
+	    doc_content = resolveRelativeLinks(doc_content, doc_id);
+
+	} catch (Exception e) {
+	    System.out.println("exception happended with mg_src.getDocument()");
+	    throw new GSException("Couldn't get document content for id: "+ doc_int+"\n"+e.getMessage());
+	    //doc_content = "this is the content for section hash id "+ doc_id+", mg doc num "+doc_int+"\n";
+	}
+	
+	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/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/service/GS3MGSearch.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/service/GS3MGSearch.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/service/GS3MGSearch.java	(revision 13666)
@@ -0,0 +1,141 @@
+/*
+ *    GS3MGSearch.java
+ *    Copyright (C) 2005 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.GSXML;
+import org.greenstone.gsdl3.util.GS3OID;
+import org.greenstone.gsdl3.util.SQLQuery;
+
+// XML classes
+import org.w3c.dom.Document;
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList;
+
+// java classes
+import java.io.File;
+
+
+/**
+ *
+ * @author <a href="mailto:kjdon@cs.waikato.ac.nz">Katherine Don</a>
+ */
+
+public class GS3MGSearch 
+    extends AbstractMGSearch 
+{
+    protected SQLQuery database = null;
+    /** the base index prefix */
+    protected String base_index_prefix = null;
+
+
+    /** constructor */
+    public GS3MGSearch()
+    {
+	this.database = new SQLQuery();
+    }
+
+    public void cleanUp() {
+	super.cleanUp();
+	this.database.closeConnection();
+    }
+
+    /** configure this service */
+    public boolean configure(Element info, Element extra_info)
+    {
+	if (!super.configure(info, extra_info)){
+	    return false;
+	}
+
+	// get the base prefix
+	Element def = (Element) GSXML.getChildByTagName(info, "baseIndexPrefix");
+	if (def != null) {
+	    this.base_index_prefix = def.getAttribute(GSXML.NAME_ATT);
+	}
+	if (this.base_index_prefix == null || this.base_index_prefix.equals("")) {
+	    System.err.println("Error: base index prefix not specified!");
+	    return false;
+	}
+	String site_name = this.site_home.substring(this.site_home.lastIndexOf(File.separator)+1);
+	if (site_name.equals("")) {
+	    System.err.println("GS3Search Error: Cannot extract the site name from site home: "+this.site_home);
+	    return false;
+	}
+	if (!database.setDatabase(site_name+"_"+this.cluster_name)) {
+	    System.err.println("GS3Search Error: Could not open SQL database!");
+	    return false;
+	}
+
+	return true;
+    }
+    /** 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){
+	boolean hierarchical = false;
+	if (!GS3OID.isDocTop(node_id) || database.isHierarchicalDocument(node_id) ) {
+	    hierarchical = true;
+	} 
+	// what about paged???
+	if (!hierarchical) {
+	    // a simple document
+	    return GSXML.DOC_TYPE_SIMPLE;
+	} else {
+	    // a hierarchical doc
+	    return GSXML.DOC_TYPE_HIERARCHY;
+	}
+	// don't have paged yet.
+
+    }
+    
+    /** returns true if the node has child nodes */
+    protected boolean hasChildren(String node_id){
+	return database.documentHasChildren(node_id);
+    }
+    
+    /** returns true if the node has a parent */
+    protected boolean hasParent(String node_id){
+	String parent = GS3OID.getParent(node_id);
+	if (parent.equals(node_id)) {
+	    return false;
+	}
+	return true;
+    }
+    
+   /** convert MG internal id to Greenstone oid */
+    protected String MGNum2OID(long docnum)
+    {
+	String mg_id = this.base_index_prefix+"."+docnum;
+	String doc_id = database.MGNum2OID(mg_id);
+	// hack !!!
+	if (doc_id.endsWith("-All")) {
+	    // get rid of the All bit
+	    doc_id = doc_id.substring(0,doc_id.length()-4);
+	    //doc_id=doc_id.replaceAll("All","1");
+	}
+	return doc_id;
+	
+    }
+
+}
+
+
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/util/GS3OID.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/util/GS3OID.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/util/GS3OID.java	(revision 13666)
@@ -0,0 +1,64 @@
+package org.greenstone.gsdl3.util;
+
+public class GS3OID extends OID {
+
+    /**  public static boolean isTop(String oid) {
+	if (oid.equals("")) {
+	    return false;
+	}
+	int pos = oid.indexOf('.');
+	if (pos == -1) { // its the top document, not the top structure
+	    return false;
+	}
+	pos = pod.indexOf('.', pos+1);
+	if (pos == -1) {
+	    return true; // there is only one dot
+	}
+	return false; // there is more than one dot
+		
+	}*/
+
+    public static boolean isDocTop(String oid) {
+	return oid.indexOf('-')==-1;
+    }
+
+    public static String createOID(String doc_id, String section_label) {
+	return doc_id + "-"+section_label;
+    }
+
+    public static String getDocID(String oid) {
+	if (isDocTop(oid)) {
+	    return oid;
+	}
+	return oid.substring(0, oid.indexOf('-'));
+    }
+    public static String getSectionLabel(String oid) {
+
+	if (isDocTop(oid)) {
+	    return "";
+	}
+	return oid.substring(oid.indexOf('-')+1);
+
+    }
+
+    // put this here for now - may need to go with SQL stuff later
+    public static String translateOID(String oid) {
+	
+	int p = oid.lastIndexOf('.');
+	if (p != oid.length()-3) {
+	    System.out.println("translateoid error: '.' is not the third to last char!!");
+	    return oid;
+	}
+	
+	String top = oid.substring(0, p);
+	String suff = oid.substring(p+1);
+	if (suff.equals("pr")) {
+	    return getParent(top);
+	} else if (suff.equals("rt")) {
+	    return getTop(top);
+	} 
+	return oid;
+
+    }
+
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/util/GSSQL.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/util/GSSQL.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/util/GSSQL.java	(revision 13666)
@@ -0,0 +1,80 @@
+package org.greenstone.gsdl3.util;
+
+public class GSSQL {
+
+    // table names
+    public static final String DOCUMENT_TABLE = "document";
+    public static final String STRUCTURE_TABLE = "structure";
+    public static final String DIVISION_TABLE = "divisions";
+    public static final String DIVISION_FILE_TABLE = "divisionfilerefs";
+    public static final String DIVISION_METADATA_TABLE = "divisionmetarefs";
+    public static final String FILE_SECTION_TABLE = "filesection";
+    public static final String FILE_GROUP_TABLE = "filegroups";
+    public static final String FILE_TABLE = "files";
+    public static final String METADATA_TABLE = "metadata"; 
+    public static final String NAMESPACE_TABLE = "namespaces";
+    public static final String METADATA_VALUE_TABLE = "mdvalues";
+    public static final String CLASSIFIER_TABLE = "classifiers";
+    public static final String CLASS_DATA_TABLE = "classdata";
+    public static final String CLASS_DOCUMENT_TABLE = "classdocuments";
+
+    // unique key names - references to the tables
+    public static final String METADATA_REF = "MetadataRef";
+    public static final String NAMESPACE_REF = "NamespaceRef";
+    public static final String STRUCTURE_REF = "StructureRef";
+    public static final String DIVISION_REF = "DivisionRef";
+    public static final String FILE_SECTION_REF = "FileSectionRef";
+    public static final String FILE_GROUP_REF = "FileGroupRef";
+    public static final String CLASSIFIER_REF = "ClassifyRef";
+    
+    // combined refs
+    public static final String PARENT_REF = "ParentRef";
+    public static final String PARENT_TYPE = "ParentType";
+    
+    // id fields - these are unique ids per document - ie combined with docid
+    public static final String DOCUMENT_ID = "DocID";
+    public static final String METADATA_ID = "MetaID";
+    public static final String FILE_ID = "FileID";
+    public static final String STRUCTURE_ID = "StructureID";
+    public static final String SECTION_ID = "SectionID";
+    public static final String FILE_GROUP_ID = "FileID";
+    public static final String FILE_SECTION_ID = "FileID";
+    public static final String CLASSIFIER_ID = "ClassifyID";
+    public static final String PARENT_ID = "ParentID";
+    
+    // type fields
+    public static final String DOC_TYPE = "DocType";
+    public static final String NAMESPACE_TYPE = "NamespaceType";
+    public static final String STRUCTURE_TYPE = "StructureType";
+    public static final String DIVISION_TYPE = "DivisionType";
+    public static final String FILE_LOCATION_TYPE = "FileLocType";
+    public static final String MIME_TYPE = "MIMEType";
+
+    // other stuff
+    public static final String LABEL = "Label";
+    public static final String VALUE = "Value";
+    public static final String LABEL_ORDER = "LabelOrder";
+    public static final String SHORT_LABEL = "ShortLabel";
+    public static final String USER_LABEL = "UserLabel";
+    public static final String NAME = "Name";
+    public static final String DESCRIPTION = "Description";
+    public static final String FILE_LOCATION = "FileLocation";
+    public static final String CREATOR = "Creator";
+    public static final String DOCUMENT_ORDER = "DocOrder";
+    public static final String NUM_LEAF_DOCUMENTS = "NumLeafDocs";
+
+    public static final String COMMA = ",";
+    public static final String EQUALS = "=";
+    public static final String QUOTE = "'";
+    public static final String EQUALS_QUOTE = "='";
+    public static final String DOT = ".";
+    public static final String END = ";";
+    public static final String NOT="!";
+
+    // some values in the fields
+    public static final String STRUCTURE = "Structure";
+    public static final String DIVISION = "Division";
+    public static final String ALL = "All";
+    public static final String MG_NUM = "mgseqno";
+    
+}
Index: /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/util/SQLQuery.java
===================================================================
--- /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/util/SQLQuery.java	(revision 13666)
+++ /tags/start/greenstone3-extensions/gs3build/src/org/greenstone/gsdl3/util/SQLQuery.java	(revision 13666)
@@ -0,0 +1,416 @@
+package org.greenstone.gsdl3.util;
+
+import org.greenstone.gsdl3.gs3build.database.GS3SQLConnectionFactory;
+import org.greenstone.gsdl3.gs3build.database.GS3SQLConnection;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import java.util.ArrayList;
+
+public class SQLQuery {
+    GS3SQLConnection connection = null;
+    
+    public SQLQuery() {
+
+    }
+
+    public boolean setDatabase(String db_name) {
+	connection = GS3SQLConnectionFactory.getGS3SQLConnection(db_name);
+	try {
+
+	    // test the connection
+	    String query = "select * from "+GSSQL.DOCUMENT_TABLE+GSSQL.END;
+	    Statement s = connection.createStatement();
+	    s.execute(query);
+	    s.close();
+	    return true;
+	} catch (Exception e) {
+	    System.err.println("SQLQuery.setDatabase():"+e);
+	}
+	closeConnection();
+	return false;
+    }
+
+    public void closeConnection() {
+	if (connection != null) {
+	    connection.close();
+	    connection=null;
+	}
+    }
+
+    public String MGNum2OID(String mg_num) {
+	// get doc id and meta id
+	String query = "select "+ 
+	    GSSQL.METADATA_TABLE+GSSQL.DOT+GSSQL.METADATA_ID+
+	    GSSQL.COMMA+GSSQL.METADATA_TABLE+GSSQL.DOT+GSSQL.DOCUMENT_ID+
+	    " from "+GSSQL.METADATA_VALUE_TABLE+GSSQL.COMMA+GSSQL.NAMESPACE_TABLE+GSSQL.COMMA+GSSQL.METADATA_TABLE+
+	    " where "+
+	    GSSQL.METADATA_VALUE_TABLE+GSSQL.DOT+GSSQL.LABEL+GSSQL.EQUALS_QUOTE+GSSQL.MG_NUM+GSSQL.QUOTE+
+	    " and "+GSSQL.METADATA_VALUE_TABLE+GSSQL.DOT+GSSQL.VALUE+GSSQL.EQUALS_QUOTE+mg_num+GSSQL.QUOTE+
+	    " and "+GSSQL.METADATA_VALUE_TABLE+GSSQL.DOT+GSSQL.NAMESPACE_REF+GSSQL.EQUALS+GSSQL.NAMESPACE_TABLE+GSSQL.DOT+GSSQL.NAMESPACE_REF+
+	    " and "+GSSQL.NAMESPACE_TABLE+GSSQL.DOT+GSSQL.METADATA_REF+GSSQL.EQUALS+GSSQL.METADATA_TABLE+GSSQL.DOT+GSSQL.METADATA_REF+
+	    GSSQL.END;
+	
+	Statement statement = null;
+	ResultSet results = null;
+	String doc_id = null;
+	String meta_id = null;
+	try {
+	    statement = connection.createStatement();
+	    results = statement.executeQuery(query);
+	    if (results.first()) {
+		doc_id = results.getString(GSSQL.DOCUMENT_ID);
+		meta_id = results.getString(GSSQL.METADATA_ID);
+	    } else {
+		statement.close();
+		return null;
+	    }
+	} catch (java.sql.SQLException e) {
+	    System.err.println("SQLQuery.MGNum2OID(): "+e);
+	    return null;
+	}
+
+	// now get division label
+	query = "select "+
+	    GSSQL.DIVISION_TABLE+GSSQL.DOT+GSSQL.SHORT_LABEL+
+	    " from "+GSSQL.DIVISION_TABLE+GSSQL.COMMA+GSSQL.DIVISION_METADATA_TABLE+
+	    " where "+GSSQL.DIVISION_METADATA_TABLE+GSSQL.DOT+GSSQL.METADATA_ID+GSSQL.EQUALS_QUOTE+meta_id+GSSQL.QUOTE+
+	    " and "+GSSQL.DIVISION_METADATA_TABLE+GSSQL.DOT+GSSQL.DOCUMENT_ID+GSSQL.EQUALS_QUOTE+doc_id+GSSQL.QUOTE+
+	    " and "+GSSQL.DIVISION_METADATA_TABLE+GSSQL.DOT+GSSQL.DIVISION_REF+GSSQL.EQUALS+GSSQL.DIVISION_TABLE+GSSQL.DOT+GSSQL.DIVISION_REF+
+	    GSSQL.END;
+
+	
+	String short_label = null;
+	try {
+	    results = statement.executeQuery(query);
+	    if (results.first()) {
+		short_label = results.getString(GSSQL.SHORT_LABEL);
+	    } else {
+		statement.close();
+		return null;
+	    }
+	    statement.close();
+	} catch (SQLException e) {
+
+	    System.err.println("SQLQuery.MGNum2OID() Error: "+e.getMessage());
+	    return null;
+	}
+	
+	return GS3OID.createOID(doc_id, short_label);
+    }
+
+    public String OID2MGNum(String oid) {
+	String id = getDocumentMetadata(oid, "gsdl3.mgseqno");
+	return id;
+
+    }
+
+    // does the document have sections, or is it just a single page document?
+    public boolean isHierarchicalDocument(String oid) {
+	// first just check the OID - it may already have section info in it
+	if (!GS3OID.isDocTop(oid)) {
+	    return true;
+	}
+
+	// now we need to check the database
+	String query = "select * "+ 
+	    " from "+GSSQL.STRUCTURE_TABLE +
+	    " where "+ GSSQL.DOCUMENT_ID +GSSQL.EQUALS_QUOTE + oid + GSSQL.QUOTE +
+	    " and "+ GSSQL.STRUCTURE_ID +GSSQL.EQUALS_QUOTE + "Section" + GSSQL.QUOTE +
+	    GSSQL.END;
+	boolean is_hierarchical = false;
+	try {
+	    Statement statement = connection.createStatement();
+	    ResultSet results = statement.executeQuery(query);
+	    is_hierarchical = results.first();
+	    statement.close();
+	} catch (java.sql.SQLException e) {
+	    return false;
+	}
+	
+	return is_hierarchical;
+    }
+    
+    // classifier metadata is not actually metadata
+    public String getClassifierMetadata(String oid, String full_meta_name) {
+
+	if (!full_meta_name.equals("Title") && !full_meta_name.equals("numleafdocs")) {
+	    return null;
+	}
+	// get the description
+	String field_name="";
+	if (full_meta_name.equals("Title")) {
+	    field_name = GSSQL.DESCRIPTION;
+	} else {
+	    field_name = GSSQL.NUM_LEAF_DOCUMENTS;
+	}
+	
+	String query = "select "+ field_name+
+	    " from " + GSSQL.CLASSIFIER_TABLE +
+	    " where " + GSSQL.CLASSIFIER_ID + GSSQL.EQUALS_QUOTE + oid + GSSQL.QUOTE +
+	    GSSQL.END;
+	
+	String value = null;
+	try {
+	    Statement statement = connection.createStatement();
+	    ResultSet results = statement.executeQuery(query);
+	    if (results.first()) {
+		value = results.getString(field_name);
+	    }
+	    statement.close();
+	} catch (java.sql.SQLException e) {
+	    
+	    System.err.println("SQLQuery.getClassifierMetadata() Error: "+e.getMessage());
+	    return null;
+	}
+	return value;
+	
+    }
+    
+    public ArrayList getDocumentChildren(String oid) {
+
+	ArrayList children = new ArrayList();
+	String doc_id = oid;
+	String section_id = "All"; // if we are just passed a doc id
+	if (!GS3OID.isDocTop(oid)) {
+	    doc_id = GS3OID.getDocID(oid);
+	    section_id = GS3OID.getSectionLabel(oid);
+	}
+//  	int sep_index = oid.indexOf(".");
+//  	if (sep_index != -1) {
+//  	    doc_id = oid.substring(0, sep_index);
+//  	    section_id = oid.substring(sep_index+1);
+//  	}
+
+	// get the division ref for this section
+	String query = "select "+GSSQL.DIVISION_REF +
+	    " from "+GSSQL.DIVISION_TABLE+
+	    " where "+GSSQL.DOCUMENT_ID+GSSQL.EQUALS_QUOTE+doc_id+GSSQL.QUOTE+
+	    " and "+GSSQL.SHORT_LABEL+GSSQL.EQUALS_QUOTE+section_id+GSSQL.QUOTE+
+	    GSSQL.END;
+
+	ResultSet results = null;
+	Statement statement = null;
+	String div_ref = null;
+	try {
+	    statement = connection.createStatement();
+	    results = statement.executeQuery(query);
+	    if (results.first()) {
+		div_ref = results.getString(GSSQL.DIVISION_REF);
+	    } else {
+		statement.close();
+		return null;
+	    }
+	} catch (java.sql.SQLException e) {
+	    
+	    System.err.println("SQLQuery.getDocumentChildren() Error1: "+e.getMessage());
+	    return null;
+	}
+
+	// now get the list of children
+	query = "select "+GSSQL.SHORT_LABEL +
+	    " from "+GSSQL.DIVISION_TABLE+
+	    " where "+ GSSQL.DOCUMENT_ID+GSSQL.EQUALS_QUOTE+doc_id+GSSQL.QUOTE+
+	    " and "+GSSQL.PARENT_TYPE+GSSQL.EQUALS_QUOTE+GSSQL.DIVISION+GSSQL.QUOTE+
+	    " and "+GSSQL.PARENT_REF+GSSQL.EQUALS_QUOTE+div_ref+GSSQL.QUOTE+
+	    GSSQL.END;
+	try {
+	    results = statement.executeQuery(query);
+	    while (results.next()) {
+		String id = results.getString(GSSQL.SHORT_LABEL);
+		children.add(GS3OID.createOID(doc_id, id));
+	    }
+	    statement.close();
+	} catch (java.sql.SQLException e) {
+	    
+	    System.err.println("SQLQuery.getDocumentChildren() Error2: "+e.getMessage());
+	    return null;
+	}
+
+	return children;
+	
+    }
+    
+    public boolean documentHasChildren(String oid) {
+	// for now, use getChildren, but can we do this a better way??
+	ArrayList children = getDocumentChildren(oid);
+	if (children==null || children.size()==0) {
+	    return false;
+	}
+	return true;
+	
+    }
+    public ArrayList getClassifierChildren(String oid) {
+
+	ArrayList children = new ArrayList();
+
+	String query = "select "+ GSSQL.CLASSIFIER_ID +
+	    " from " + GSSQL.CLASSIFIER_TABLE +
+	    " where " + GSSQL.PARENT_ID + GSSQL.EQUALS_QUOTE + oid + GSSQL.QUOTE +
+	    " and " + GSSQL.NUM_LEAF_DOCUMENTS + GSSQL.NOT+GSSQL.EQUALS_QUOTE+ "0"+GSSQL.QUOTE +
+	    GSSQL.END; 
+	
+	try {
+	    Statement statement = connection.createStatement();
+	    ResultSet results = statement.executeQuery(query);
+	    while (results.next()) {
+		String id = results.getString(GSSQL.CLASSIFIER_ID);
+		children.add(id);
+	    }
+	    statement.close();
+	} catch (java.sql.SQLException e) {
+	    
+	    System.err.println("SQLQuery.getClassifierChildren Error: "+e.getMessage());
+	    return null;
+	}
+	return children;
+    }
+
+    public ArrayList getClassifierDocChildren(String oid) {
+	ArrayList children = new ArrayList();
+
+	String query = "select "+ GSSQL.CLASS_DOCUMENT_TABLE+GSSQL.DOT+ GSSQL.DOCUMENT_ID+
+	    " from " + GSSQL.CLASSIFIER_TABLE + GSSQL.COMMA+GSSQL.CLASS_DOCUMENT_TABLE+
+	    " where " + GSSQL.CLASSIFIER_TABLE +GSSQL.DOT+ GSSQL.CLASSIFIER_ID + GSSQL.EQUALS_QUOTE + oid + GSSQL.QUOTE +
+	    " and " + GSSQL.CLASSIFIER_TABLE +GSSQL.DOT+ GSSQL.CLASSIFIER_REF+GSSQL.EQUALS+GSSQL.CLASS_DOCUMENT_TABLE+GSSQL.DOT+ GSSQL.CLASSIFIER_REF+
+	    " order by "+GSSQL.CLASS_DOCUMENT_TABLE+GSSQL.DOT+GSSQL.DOCUMENT_ORDER+
+	    GSSQL.END;
+	try {
+	    Statement statement = connection.createStatement();
+	    ResultSet results = statement.executeQuery(query);
+	    while (results.next()) {
+		String id = results.getString(GSSQL.DOCUMENT_ID);
+		children.add(id);
+	    }
+	} catch (java.sql.SQLException e) {
+		
+	    System.err.println("SQLQuery.getClassifierDocChildren() Error: "+e.getMessage());
+	    return null;
+	}
+	
+	return children;
+    }
+    
+    public String getDocumentMetadata(String oid, String full_meta_name) {
+
+	String doc_id = oid;
+	String section_id = "All"; // if we are just passed a doc id
+	if (!GS3OID.isDocTop(oid)) {
+	    doc_id = GS3OID.getDocID(oid);
+	    section_id = GS3OID.getSectionLabel(oid);
+	}
+//  	int sep_index = oid.indexOf(".");
+//  	if (sep_index != -1) {
+//  	    doc_id = oid.substring(0, sep_index);
+//  	    section_id = oid.substring(sep_index+1);
+//  	}
+
+
+	// get the metadata block id
+	String query = "select "+ 
+	    GSSQL.DIVISION_METADATA_TABLE+GSSQL.DOT+GSSQL.METADATA_ID +
+	    " from " + GSSQL.DIVISION_METADATA_TABLE+GSSQL.COMMA+GSSQL.DIVISION_TABLE+
+	    " where " + GSSQL.DIVISION_TABLE+GSSQL.DOT+GSSQL.DIVISION_REF+GSSQL.EQUALS+GSSQL.DIVISION_METADATA_TABLE+GSSQL.DOT+GSSQL.DIVISION_REF+
+	    " and " + GSSQL.DIVISION_TABLE+GSSQL.DOT+GSSQL.SHORT_LABEL+GSSQL.EQUALS_QUOTE+section_id+GSSQL.QUOTE+
+	    " and " + GSSQL.DIVISION_TABLE+GSSQL.DOT+GSSQL.DOCUMENT_ID+GSSQL.EQUALS_QUOTE+doc_id+GSSQL.QUOTE+
+	    " and "+GSSQL.DIVISION_METADATA_TABLE+GSSQL.DOT+GSSQL.DOCUMENT_ID+GSSQL.EQUALS_QUOTE+doc_id+GSSQL.QUOTE+ 
+	    GSSQL.END;
+	
+	Statement statement = null;
+	ResultSet results = null;
+	String meta_id = null;
+	try {
+	    statement = connection.createStatement();
+	    results = statement.executeQuery(query);
+	    if (results.first()) {
+		meta_id = results.getString(GSSQL.METADATA_ID);
+	    } else {
+		statement.close();
+		return null;
+	    }
+	} catch (java.sql.SQLException e) {
+
+	    System.err.println("SQLQuery.getDocumentMetadata() Error: "+e.getMessage());
+	    return null;
+	}
+	
+	// now get the list of namespace refs for the right namespace
+	int sep_index = full_meta_name.indexOf('.');
+	String meta_ns = "gsdl3";
+	String meta_name = full_meta_name;
+	if (sep_index != -1) {
+
+	    meta_ns = full_meta_name.substring(0, sep_index);
+	    meta_name = full_meta_name.substring(sep_index+1);
+	}
+
+	query = "select * "+ 
+	    " from "+GSSQL.NAMESPACE_TABLE+GSSQL.COMMA+GSSQL.METADATA_TABLE+GSSQL.COMMA+GSSQL.METADATA_VALUE_TABLE+
+	    " where "+GSSQL.METADATA_TABLE+GSSQL.DOT+GSSQL.METADATA_ID+GSSQL.EQUALS_QUOTE+meta_id+GSSQL.QUOTE+
+	    " and "+ GSSQL.METADATA_TABLE+GSSQL.DOT+GSSQL.DOCUMENT_ID+GSSQL.EQUALS_QUOTE+doc_id+GSSQL.QUOTE+
+	    " and " + GSSQL.METADATA_TABLE+GSSQL.DOT+GSSQL.METADATA_REF+GSSQL.EQUALS+GSSQL.NAMESPACE_TABLE+GSSQL.DOT+GSSQL.METADATA_REF+
+	    " and "+ GSSQL.NAMESPACE_TABLE+GSSQL.DOT+GSSQL.NAMESPACE_TYPE+GSSQL.EQUALS_QUOTE+meta_ns+GSSQL.QUOTE+
+	    " and "+GSSQL.NAMESPACE_TABLE+GSSQL.DOT+GSSQL.NAMESPACE_REF+GSSQL.EQUALS+GSSQL.METADATA_VALUE_TABLE+GSSQL.DOT+GSSQL.NAMESPACE_REF+
+	    GSSQL.END;
+	
+	String meta_value = null;
+	try {
+	    statement = connection.createStatement();
+	    results = statement.executeQuery(query);
+	    while (results.next()) {
+		String m_name = results.getString(GSSQL.LABEL);
+		if (meta_name.equals(m_name)) {
+		    meta_value = results.getString(GSSQL.VALUE);
+		    break;
+		}
+	    }
+	    statement.close();
+	} catch (java.sql.SQLException e) {
+
+	    System.err.println("SQLQuery.getDocumentMetadata() Error: "+e.getMessage());
+	    return null;
+	}
+	
+	return meta_value;
+    }
+    public static void main (String [] args) {
+
+	SQLQuery self = new SQLQuery();
+	self.setDatabase("gs3test");
+	System.out.println("getting oid for mg num 3");
+	String oid = self.MGNum2OID("stx.3");
+	System.out.println("oid was "+oid);
+	
+	System.out.println("title metadata for mg num 3:");
+	String meta = self.getDocumentMetadata(oid, "gsdl3.title");
+	if (meta != null) {System.out.println(meta);}
+	System.out.println("subject metadata for mg num 3:");
+	meta = self.getDocumentMetadata(oid, "gsdl3.Subject");
+	if (meta != null) {System.out.println(meta);}
+
+	System.out.println("converting back to mg, oid "+oid);
+	String id = self.OID2MGNum(oid);
+	System.out.println(""+id);
+
+	System.out.println("getting oid for mg num 8");
+	oid = self.MGNum2OID("stx.8");
+	System.out.println("oid was "+oid);
+
+	System.out.println("title metadata for mg num 8:");
+	meta = self.getDocumentMetadata(oid, "gsdl3.title");
+	if (meta != null) {System.out.println(meta);}
+	System.out.println("subject metadata for mg num 8:");
+	meta = self.getDocumentMetadata(oid, "gsdl3.Subject");
+	if (meta != null) {System.out.println(meta);}
+
+	System.out.println("converting back to mg, oid "+oid);
+	id = self.OID2MGNum(oid);
+	System.out.println(""+id);
+    }
+
+
+
+
+}
Index: /tags/start/gs2build-extra/Makefile.in
===================================================================
--- /tags/start/gs2build-extra/Makefile.in	(revision 13666)
+++ /tags/start/gs2build-extra/Makefile.in	(revision 13666)
@@ -0,0 +1,106 @@
+###########################################################################
+#
+# 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.
+#
+###########################################################################
+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 = src/recpt src/txt2db src/db2txt src/hashfile src/getpw packages/mg src/phind/generate packages src/mgpp src/oaiservr
+INSTALLDIRS = src/txt2db src/db2txt src/hashfile packages/mg src/phind/generate packages src/mgpp 
+
+MODULEDIRS = @MODULEDIRS@
+
+#OTHERDIRS = packages packages/mg lib src/mgpp src/colservr src/recpt src/txt2db src/db2txt src/hashfile src/getpw src/phind/generate src/oaiservr
+
+OTHERDIRS = packages packages/mg lib src/mgpp src/txt2db src/db2txt src/hashfile src/phind/generate
+all:
+	for odir in $(OTHERDIRS) $(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/start/gs2build-extra/configure
===================================================================
--- /tags/start/gs2build-extra/configure	(revision 13666)
+++ /tags/start/gs2build-extra/configure	(revision 13666)
@@ -0,0 +1,8323 @@
+#! /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"
+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 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 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;
+
+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
+
+
+
+
+
+
+
+
+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
+
+
+# ---------------------------------------------------------------------------
+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"
+
+
+# ---------------------------------------------------------------------------
+
+
+subdirs="$subdirs packages"
+
+
+# the list of folders in the src folder
+srclist="src/mgpp/lib/Makefile src/mgpp/text/Makefile src/mgpp/Makefile src/hashfile/Makefile src/txt2db/Makefile src/db2txt/Makefile src/phind/generate/Makefile "
+
+#srclist="src/mgpp/lib/Makefile src/mgpp/text/Makefile src/mgpp/Makefile \
+#          src/hashfile/Makefile src/colservr/Makefile src/recpt/Makefile src/txt2db/Makefile \
+#          src/oaiservr/Makefile src/db2txt/Makefile src/getpw/Makefile src/phind/generate/Makefile"
+
+#AC_OUTPUT(packages/Makefile packages/mg/Makefile packages/mg/src/text/Makefile packages/mg/src/images/Makefile
+#          packages/mg/src/scripts/Makefile packages/mg/lib/Makefile
+#	  lib/Makefile Makefile $srclist $moduleDirs)
+
+
+                                                                                          ac_config_files="$ac_config_files packages/mg/Makefile packages/mg/src/text/Makefile packages/mg/src/images/Makefile packages/mg/src/scripts/Makefile packages/mg/lib/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/mg/Makefile" ) CONFIG_FILES="$CONFIG_FILES packages/mg/Makefile" ;;
+  "packages/mg/src/text/Makefile" ) CONFIG_FILES="$CONFIG_FILES packages/mg/src/text/Makefile" ;;
+  "packages/mg/src/images/Makefile" ) CONFIG_FILES="$CONFIG_FILES packages/mg/src/images/Makefile" ;;
+  "packages/mg/src/scripts/Makefile" ) CONFIG_FILES="$CONFIG_FILES packages/mg/src/scripts/Makefile" ;;
+  "packages/mg/lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES packages/mg/lib/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,@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/start/gs2build-extra/configure.in
===================================================================
--- /tags/start/gs2build-extra/configure.in	(revision 13666)
+++ /tags/start/gs2build-extra/configure.in	(revision 13666)
@@ -0,0 +1,346 @@
+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 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)
+
+
+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)
+
+# ---------------------------------------------------------------------------
+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"
+AC_CONFIG_SUBDIRS(packages)
+
+# the list of folders in the src folder
+srclist="src/mgpp/lib/Makefile src/mgpp/text/Makefile src/mgpp/Makefile src/hashfile/Makefile src/txt2db/Makefile src/db2txt/Makefile src/phind/generate/Makefile "
+
+#srclist="src/mgpp/lib/Makefile src/mgpp/text/Makefile src/mgpp/Makefile \
+#          src/hashfile/Makefile src/colservr/Makefile src/recpt/Makefile src/txt2db/Makefile \
+#          src/oaiservr/Makefile src/db2txt/Makefile src/getpw/Makefile src/phind/generate/Makefile"
+
+#AC_OUTPUT(packages/Makefile packages/mg/Makefile packages/mg/src/text/Makefile packages/mg/src/images/Makefile 
+#          packages/mg/src/scripts/Makefile packages/mg/lib/Makefile
+#	  lib/Makefile Makefile $srclist $moduleDirs)
+
+
+AC_OUTPUT(packages/mg/Makefile packages/mg/src/text/Makefile packages/mg/src/images/Makefile packages/mg/src/scripts/Makefile packages/mg/lib/Makefile lib/Makefile Makefile $srclist $moduleDirs)
Index: /tags/start/gs2build-extra/lib.Makefile.in
===================================================================
--- /tags/start/gs2build-extra/lib.Makefile.in	(revision 13666)
+++ /tags/start/gs2build-extra/lib.Makefile.in	(revision 13666)
@@ -0,0 +1,134 @@
+###########################################################################
+#
+# 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@
+MCFLAGS = -Wall -Wunused
+DEFS = @DEFS@
+INCLUDES = -I../packages/mg/lib -I..
+MICO_DIR = @MICO_DIR@
+ifeq ($(MICO_DIR), default)
+MICO_INC = -I../packages/mico/mico/include
+MICO_PATH = ../bin/linux/
+else
+ifeq ($(MICO_DIR), yes)
+MICO_INC =
+else
+MICO_INC = -I$(MICO_DIR)
+endif
+MICO_PATH =
+endif
+MINCLUDES = -I/usr/include/g++-2/ -I/usr/lib/gcc-lib/i386-slackware-linux/egcs-2.91.66/include/ -I/usr/include -I.  -I../packages/mg/lib $(MICO_INC) -I..
+RANLIB = @RANLIB@
+USE_CORBA = @USE_CORBA@
+
+COMPILE = $(CC) -c $(CCFLAGS) $(DEFS) $(INCLUDES)
+CPPCOMPILE = $(CPP) -c $(CCFLAGS) $(DEFS) $(INCLUDES)
+
+ifneq ($(USE_CORBA), 0)
+MCOMPILE = $(MICO_PATH)mico-c++ -x c++ $(MCFLAGS) $(DEFS) $(MINCLUDES) -c
+else
+MCOMPILE = $(COMPILE)
+endif
+
+.SUFFIXES:
+.SUFFIXES: .c .o
+.c.o:
+	$(COMPILE) $<
+
+.SUFFIXES: .cpp .o
+.cpp.o:
+	$(CPPCOMPILE) $< 
+
+.SUFFIXES: .mpp .o
+.mpp.o:
+	$(MCOMPILE) $<
+
+
+
+
+ifneq ($(USE_CORBA), 0)
+CORBAHEADERS = \
+  corbaconv_text_t.h corbatext_t.h
+CORBASOURCES = \
+  corbaiface.mpp    corbatext_t.mpp  corbaconv_text_t.mpp corbaiface_skel.mpp
+CORBAOBJECTS = \
+  corbaiface.o      corbatext_t.o    corbaconv_text_t.o   corbaiface_skel.o 
+else
+CORBAHEADERS = 
+CORBASOURCE = 
+CORBAOBJECTS = 
+endif
+
+HEADERS = \
+  cfgread.h      fileutil.h     gsdlunicode.h  gsdltools.h text_t.h \
+  display.h      gsdlconf.h     gsdltimes.h    cnfgable.h  cnfgator.h \
+  $(CORBAHEADERS)
+
+
+SOURCES = \
+  cfgread.cpp      fileutil.cpp     text_t.cpp     cnfgable.cpp \
+  display.cpp      gsdlunicode.cpp  gsdltimes.cpp  gsdltools.cpp \
+  cnfgator.cpp     $(CORBASOURCES)
+
+OBJECTS = \
+  cfgread.o        fileutil.o       text_t.o     cnfgable.o \
+  display.o        gsdlunicode.o    gsdltimes.o  gsdltools.o \
+  cnfgator.o       $(CORBAOBJECTS)
+
+
+all: gsdllib.a
+corbaiface_skel.h: corbaiface.idl
+	LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PATH=$(MICO_PATH):$(PATH) idl --boa --no-poa --c++-skel --c++-suffix=mpp $?
+corbaiface_skel.mpp: corbaiface.idl
+	LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PATH=$(MICO_PATH):$(PATH) idl --boa --no-poa --c++-skel --c++-suffix=mpp $?
+corbaiface.mpp: corbaiface.idl
+	LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH PATH=$(MICO_PATH):$(PATH) idl --boa --no-poa --c++-skel --c++-suffix=mpp $?
+
+#GSDLLIBOBJECTS = $(OBJECTS)
+GSDLLIBOBJECTS = text_t.o
+gsdllib.a: $(GSDLLIBOBJECTS)
+	rm -f gsdllib.a
+	$(AR) cru gsdllib.a $(GSDLLIBOBJECTS)
+	$(RANLIB) gsdllib.a
+
+clean:
+	rm -f $(OBJECTS) gsdllib.a corbaiface_skel.mpp corbaiface.h corbaiface.mpp
+
+distclean: clean
+	rm -f Makefile
+install:
+
+depend:
+	makedepend -Y -- $(DEFS) $(INCLUDES) $(CCFLAGS) -- $(SOURCES)
+
+
+
+
Index: /tags/start/gs2build-extra/packages.Makefile
===================================================================
--- /tags/start/gs2build-extra/packages.Makefile	(revision 13666)
+++ /tags/start/gs2build-extra/packages.Makefile	(revision 13666)
@@ -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/start/gs2build-extra/packages.configure
===================================================================
--- /tags/start/gs2build-extra/packages.configure	(revision 13666)
+++ /tags/start/gs2build-extra/packages.configure	(revision 13666)
@@ -0,0 +1,167 @@
+#! /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=""
+
+# 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
+
+# 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
+
+# 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
Index: /tags/start/gsdl-documentation/manuals/clean-all.sh
===================================================================
--- /tags/start/gsdl-documentation/manuals/clean-all.sh	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/clean-all.sh	(revision 13666)
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+echo "clean english version"
+cd en
+rm -r html
+rm -r pdf
+cd ..
+
+echo "clean french version"
+cd fr
+rm -r html
+rm -r pdf
+cd ..
+
+echo "clean spanish version"
+cd es
+rm -r html
+rm -r pdf
+cd ..
+
+
+echo "clean russian version"
+cd ru
+rm -r html
+rm -r pdf
+cd ..
Index: /tags/start/gsdl-documentation/manuals/generate-html.sh
===================================================================
--- /tags/start/gsdl-documentation/manuals/generate-html.sh	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/generate-html.sh	(revision 13666)
@@ -0,0 +1,139 @@
+#!/bin/sh
+
+gsdlhome=$GSDLHOME
+
+if [ "$gsdlhome" == "" ]; then
+    # assume tutorials in a subdir of gsdl
+      pushd .. > /dev/null
+      gsdlhome=`pwd`
+      popd > /dev/null
+fi
+
+echo "procesing english version"
+cd en
+mkdir html
+
+echo "User's manual (english)"
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-index.xsl User_en.xml > html/User_en_index.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-one-html.xsl User_en.xml > html/User_en_all.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-many-html.xsl User_en.xml | perl -S $gsdlhome/gli/help/splithelpdocument.pl
+mv *.htm html/
+
+echo "Installer's manual (english)"
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-index.xsl Install_en.xml > html/Install_en_index.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-one-html.xsl Install_en.xml > html/Install_en_all.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-many-html.xsl Install_en.xml | perl -S $gsdlhome/gli/help/splithelpdocument.pl
+mv *.htm html/
+
+echo "Developer's manual (english)"
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-index.xsl Develop_en.xml > html/Develop_en_index.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-one-html.xsl Develop_en.xml > html/Develop_en_all.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-many-html.xsl Develop_en.xml | perl -S $gsdlhome/gli/help/splithelpdocument.pl
+mv *.htm html/
+
+echo "From paper to collection (english)"
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-index.xsl Paper_en.xml > html/Paper_en_index.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-one-html.xsl Paper_en.xml > html/Paper_en_all.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-many-html.xsl Paper_en.xml | perl -S $gsdlhome/gli/help/splithelpdocument.pl
+mv *.htm html/
+
+cd ..
+
+
+echo "procesing french version"
+cd fr
+mkdir html
+cp -r images/ html/images
+cp ../style.css html/
+
+echo "User's manual (french)"
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-index.xsl User_fr.xml > html/User_fr_index.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-one-html.xsl User_fr.xml > html/User_fr_all.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-many-html.xsl User_fr.xml | perl -S $gsdlhome/gli/help/splithelpdocument.pl
+mv *.htm html/
+
+echo "Installer's manual (french)"
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-index.xsl Install_fr.xml > html/Install_fr_index.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-one-html.xsl Install_fr.xml > html/Install_fr_all.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-many-html.xsl Install_fr.xml | perl -S $gsdlhome/gli/help/splithelpdocument.pl
+mv *.htm html/
+
+echo "Developer's manual (french)"
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-index.xsl Develop_fr.xml > html/Develop_fr_index.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-one-html.xsl Develop_fr.xml > html/Develop_fr_all.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-many-html.xsl Develop_fr.xml | perl -S $gsdlhome/gli/help/splithelpdocument.pl
+mv *.htm html/
+
+echo "From paper to collection (french)"
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-index.xsl Paper_fr.xml > html/Paper_fr_index.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-one-html.xsl Paper_fr.xml > html/Paper_fr_all.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-many-html.xsl Paper_fr.xml | perl -S $gsdlhome/gli/help/splithelpdocument.pl
+mv *.htm html/
+
+cd ..
+
+
+echo "procesing spanish version"
+cd es
+mkdir html
+cp -r images/ html/images
+cp ../style.css html/
+
+echo "User's manual (spanish)"
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-index.xsl User_es.xml > html/User_es_index.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-one-html.xsl User_es.xml > html/User_es_all.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-many-html.xsl User_es.xml | perl -S $gsdlhome/gli/help/splithelpdocument.pl
+mv *.htm html/
+
+echo "Installer's manual (spanish)"
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-index.xsl Install_es.xml > html/Install_es_index.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-one-html.xsl Install_es.xml > html/Install_es_all.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-many-html.xsl Install_es.xml | perl -S $gsdlhome/gli/help/splithelpdocument.pl
+mv *.htm html/
+
+echo "Developer's manual (spanish)"
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-index.xsl Develop_es.xml > html/Develop_es_index.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-one-html.xsl Develop_es.xml > html/Develop_es_all.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-many-html.xsl Develop_es.xml | perl -S $gsdlhome/gli/help/splithelpdocument.pl
+mv *.htm html/
+
+echo "From paper to collection (spanish)"
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-index.xsl Paper_es.xml > html/Paper_es_index.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-one-html.xsl Paper_es.xml > html/Paper_es_all.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-many-html.xsl Paper_es.xml | perl -S $gsdlhome/gli/help/splithelpdocument.pl
+mv *.htm html/
+
+cd ..
+
+
+echo "procesing russian version"
+cd ru
+mkdir html
+cp -r images/ html/images
+cp ../style.css html/
+
+echo "User's manual (russian)"
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-index.xsl User_ru.xml > html/User_ru_index.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-one-html.xsl User_ru.xml > html/User_ru_all.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-many-html.xsl User_ru.xml | perl -S $gsdlhome/gli/help/splithelpdocument.pl
+mv *.htm html/
+
+echo "Installer's manual (russian)"
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-index.xsl Install_ru.xml > html/Install_ru_index.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-one-html.xsl Install_ru.xml > html/Install_ru_all.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-many-html.xsl Install_ru.xml | perl -S $gsdlhome/gli/help/splithelpdocument.pl
+mv *.htm html/
+
+echo "Developer's manual (russian)"
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-index.xsl Develop_ru.xml > html/Develop_ru_index.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-one-html.xsl Develop_ru.xml > html/Develop_ru_all.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-many-html.xsl Develop_ru.xml | perl -S $gsdlhome/gli/help/splithelpdocument.pl
+mv *.htm html/
+
+echo "From paper to collection (russian)"
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-index.xsl Paper_ru.xml > html/Paper_ru_index.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-one-html.xsl Paper_ru.xml > html/Paper_ru_all.html
+java -cp $gsdlhome/gli:../ ApplyXSLT ../xml-to-many-html.xsl Paper_ru.xml | perl -S $gsdlhome/gli/help/splithelpdocument.pl
+mv *.htm html/
+
+cd ..
Index: /tags/start/gsdl-documentation/manuals/generate-pdf.sh
===================================================================
--- /tags/start/gsdl-documentation/manuals/generate-pdf.sh	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/generate-pdf.sh	(revision 13666)
@@ -0,0 +1,78 @@
+#!/bin/sh
+
+gsdlhome=$GSDLHOME
+export CLASSPATH=$CLASSPATH:../packages/fop-0.20.5/build/fop.jar:../packages/fop-0.20.5/lib:../
+
+
+if [ "$gsdlhome" == "" ]; then
+    # assume tutorials in a subdir of gsdl
+      pushd .. > /dev/null
+      gsdlhome=`pwd`
+      popd > /dev/null
+fi
+
+echo "procesing english manuals"
+cd en
+mkdir pdf
+
+#echo "User's manual (english)"
+#./../packages/fop-0.20.5/fop.sh -xsl ../xml-to-pdf.xsl -xml User_en.xml -pdf pdf/User_en.pdf
+echo "Developer's manual (english)"
+./../packages/fop-0.20.5/fop.sh -xsl ../xml-to-pdf.xsl -xml Develop_en.xml -pdf pdf/Develop_en.pdf
+echo "User's manual (english)"
+./../packages/fop-0.20.5/fop.sh -xsl ../xml-to-pdf.xsl -xml Install_en.xml -pdf pdf/Install_en.pdf
+echo "From Paper to Collection (english)"
+./../packages/fop-0.20.5/fop.sh -xsl ../xml-to-pdf.xsl -xml Paper_en.xml -pdf pdf/Paper_en.pdf
+
+cd ..
+
+
+echo ""
+echo "procesing french manuals"
+cd fr
+mkdir pdf
+
+#echo "User's manual (french)"
+#./../packages/fop-0.20.5/fop.sh -xsl ../xml-to-pdf.xsl -xml User_fr.xml -pdf pdf/User_fr.pdf
+echo "Developer's manual (french)"
+./../packages/fop-0.20.5/fop.sh -xsl ../xml-to-pdf.xsl -xml Develop_fr.xml -pdf pdf/Develop_fr.pdf
+echo "User's manual (french)"
+./../packages/fop-0.20.5/fop.sh -xsl ../xml-to-pdf.xsl -xml Install_fr.xml -pdf pdf/Install_fr.pdf
+echo "From Paper to Collection (french)"
+./../packages/fop-0.20.5/fop.sh -xsl ../xml-to-pdf.xsl -xml Paper_fr.xml -pdf pdf/Paper_fr.pdf
+
+cd ..
+
+
+echo ""
+echo "procesing spanish manuals"
+cd es
+mkdir pdf
+
+#echo "User's manual (spanish)"
+#./../packages/fop-0.20.5/fop.sh -xsl ../xml-to-pdf.xsl -xml User_es.xml -pdf pdf/User_es.pdf
+echo "Developer's manual (spanish)"
+./../packages/fop-0.20.5/fop.sh -xsl ../xml-to-pdf.xsl -xml Develop_es.xml -pdf pdf/Develop_es.pdf
+echo "User's manual (spanish)"
+./../packages/fop-0.20.5/fop.sh -xsl ../xml-to-pdf.xsl -xml Install_es.xml -pdf pdf/Install_es.pdf
+echo "From Paper to Collection (spanish)"
+./../packages/fop-0.20.5/fop.sh -xsl ../xml-to-pdf.xsl -xml Paper_es.xml -pdf pdf/Paper_es.pdf
+
+cd ..
+
+
+echo ""
+echo "procesing russian manuals"
+cd ru
+mkdir pdf
+
+echo "User's manual (russian)"
+./../packages/fop-0.20.5/fop.sh -xsl ../xml-to-pdf.xsl -xml User_ru.xml -pdf pdf/User_ru.pdf
+echo "Developer's manual (russian)"
+./../packages/fop-0.20.5/fop.sh -xsl ../xml-to-pdf.xsl -xml Develop_ru.xml -pdf pdf/Develop_ru.pdf
+echo "User's manual (russian)"
+./../packages/fop-0.20.5/fop.sh -xsl ../xml-to-pdf.xsl -xml Install_ru.xml -pdf pdf/Install_ru.pdf
+echo "From Paper to Collection (russian)"
+./../packages/fop-0.20.5/fop.sh -xsl ../xml-to-pdf.xsl -xml Paper_ru.xml -pdf pdf/Paper_ru.pdf
+
+cd ..
Index: /tags/start/gsdl-documentation/manuals/processing/common.xsl
===================================================================
--- /tags/start/gsdl-documentation/manuals/processing/common.xsl	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/processing/common.xsl	(revision 13666)
@@ -0,0 +1,191 @@
+<?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"
+  xmlns:util="ExternalRef" extension-element-prefixes="util">
+  
+  <xsl:template match="Title"><p><b><i><xsl:apply-templates/></i></b></p></xsl:template>
+  
+  <xsl:template match="Title" mode="Figure">
+  	<xsl:param name="no"/>
+  	<div style="margin-right:1.7pt;" align="center"><b>Figure&#160;<xsl:value-of select="$no"/>
+  			<xsl:if test="SubTitle"><xsl:value-of select="SubTitle"/></xsl:if>&#160;
+		  	<xsl:apply-templates select="Text"/></b>
+		</div>
+  </xsl:template>
+  
+  <xsl:template match="Title" mode="Table">  	  
+    <div style="margin-right:1.7pt;" align="center">
+    <b>Table&#160;<xsl:number count="Table[not(@class='hidden')]" level="any"/>&#160;<xsl:apply-templates/></b></div>
+  </xsl:template>
+
+	<xsl:template match="NumberedList"><ol><xsl:apply-templates/></ol></xsl:template>
+  <xsl:template match="NumberedItem"><li><xsl:apply-templates/></li></xsl:template>
+
+  <xsl:template match="BulletList">
+	<xsl:if test="not(parent::Bullet)">
+    <ul style="list-style-type: disc;">
+      <xsl:for-each select="Bullet">
+		<li><xsl:apply-templates/></li>
+		<xsl:if test="BulletList">
+		<xsl:for-each select="BulletList">
+  		  <ul style="list-style-type: disc;"><xsl:for-each select="Bullet"><li><xsl:apply-templates/></li></xsl:for-each></ul>
+		</xsl:for-each>
+		</xsl:if>
+	  </xsl:for-each>
+    </ul>
+    <p/>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template match="Text">
+	<xsl:choose>
+		<xsl:when test="parent::Indented">
+		  <p style="font-size=12px; color=black; text-align=justify; margin-left=15pt;"><xsl:apply-templates/></p>
+		</xsl:when>
+		<xsl:when test="parent::Title|parent::Footnote"><xsl:apply-templates/></xsl:when>
+		<xsl:when test="not(parent::Version) and not(parent::Date) and not(parent::NumberedItem) and not(parent::Bullet)">
+			<p><xsl:apply-templates/></p>
+		</xsl:when>
+		<xsl:otherwise><xsl:apply-templates/></xsl:otherwise>
+	</xsl:choose>    
+  </xsl:template>
+
+  <xsl:template match="CodeLine">  
+  <xsl:choose>
+	<xsl:when test="parent::Figure or parent::th">
+	  <div style="margin-top:0pt; margin-right:0in; margin-bottom:0in; margin-left:2pt; margin-bottom:0pt; 
+	font-family: Courier; font-size: 11px"><xsl:apply-templates/></div>
+	</xsl:when>		
+	<xsl:when test="name(preceding-sibling::*[position()=1])='CodeLine' or name(following-sibling::*[position()=1])='CodeLine'">
+	  
+	    <div style="margin-top:0pt; margin-right:0pt; margin-bottom:0pt; margin-left:2em; font-size:10px; font-family:Courier;"><xsl:apply-templates/></div>
+	  
+	</xsl:when>      
+	<!-- a single line of code between two text paragraphs -->
+	<xsl:otherwise>
+	  <p><div style="font-size:10px; margin-right:0pt; margin-left:2em; margin-bottom:2px; margin-top:2px; font-family:Courier;">
+	<xsl:apply-templates/></div></p>	  
+  </xsl:otherwise>
+  </xsl:choose>  
+  </xsl:template>
+
+  <xsl:template match="Figure">
+    <a id="Figure_{@id}"/>
+  	<!-- number of current figure = total_number_of_previous_figure - total_number_of_previous_sub_figures-->
+    <xsl:variable name="temp_total_figs"><xsl:number count="Figure" level="any"/></xsl:variable>       
+    <xsl:variable name="temp_num_of_sub_figs">
+			<xsl:number count="Figure[Title/SubTitle and substring(translate(@id, '_0123456789', '99999999999'), string-length(@id)-1, string-length(@id))='99']" level="any"/>
+   	</xsl:variable>  	  	
+  	<xsl:variable name="no"><xsl:value-of select="$temp_total_figs - $temp_num_of_sub_figs"/></xsl:variable>   
+    <p/>        
+    <xsl:apply-templates select="Title" mode="Figure"><xsl:with-param name="no" select="$no"/></xsl:apply-templates>
+    <xsl:choose>    
+    <xsl:when test="CodeLine">
+      <table class="figure_code" align="center">
+      <xsl:for-each select="*[not(name()='Title')]">
+        <tr>
+        <xsl:if test="parent::Figure[@class='withLineNumber']">
+        <td><div style="linenumber"><xsl:number value="position()" format="1"/>&#160;&#160;</div></td></xsl:if>
+        <td><xsl:apply-templates select="."/></td></tr>
+      </xsl:for-each>
+      </table>
+    </xsl:when>
+    <xsl:when test="File"><div align="center"><xsl:apply-templates select="File"/></div><br/>
+		</xsl:when>    
+    </xsl:choose>
+    <br/>
+  </xsl:template> 
+
+  <xsl:template match="Table">
+    <p/>
+    <a id="Table_{@id}"/>
+    <xsl:if test="not(@class='hidden') and not(normalize-space(Title/Text)='')"><xsl:apply-templates select="Title" mode="Table"/></xsl:if>
+    <table cellpadding="2pt" cellspacing="2pt">
+        <xsl:if test="not(@class='hidden')">
+	  <xsl:if test="not(../../@class='hidden')"><xsl:attribute name="style">border-collapse:collapse;border:1px solid black;</xsl:attribute></xsl:if>
+	  <xsl:attribute name="rules">rows</xsl:attribute><xsl:attribute name="align">center</xsl:attribute>		
+	</xsl:if>
+	<xsl:if test="@class='hidden'"><xsl:attribute name="width">90%</xsl:attribute><xsl:attribute name="align">center</xsl:attribute></xsl:if>
+        <xsl:for-each select="TableContent/tr">
+          <tr>
+	  <xsl:if test="not(../../@class='hidden')"><xsl:attribute name="style">border-collapse:collapse;border:1px solid black;</xsl:attribute></xsl:if>
+          <xsl:for-each select="th"><td valign="top"><xsl:if test="File"><xsl:attribute name="align">right</xsl:attribute></xsl:if>
+          <xsl:apply-templates select="node()"/></td></xsl:for-each>
+	  </tr>
+	</xsl:for-each>
+    </table>
+    <br/>
+  </xsl:template>
+    
+  <xsl:template match="Section">     
+    <a name="Section_{@id}"/>
+    <h3><xsl:if test="not(starts-with(../../@id, 'appendix'))">
+    <xsl:number level="multiple" format="1.1" count="//Chapter|//Chapter//Section"/>&#160;</xsl:if>
+    <xsl:apply-templates select="Title/Text"/></h3>
+    <xsl:apply-templates select="Content/*"/>
+  </xsl:template>
+
+  <xsl:template match="Section" mode="preface">    
+    <h3><xsl:apply-templates select="Title/Text"/></h3>
+    <xsl:apply-templates select="Content/*"/>
+  </xsl:template>
+
+  <xsl:template match="Subsection">
+    <a name="Subsection_{@id}"/>
+    <h4><xsl:apply-templates select="Title/Text"/></h4>
+    <xsl:apply-templates select="Content/*"/>
+  </xsl:template>
+  
+  <xsl:template match="Part"><a id="Part_{@id}"/><xsl:apply-templates/></xsl:template>    
+
+  <xsl:template match="Comment"><xsl:apply-templates/></xsl:template>  
+  <xsl:template match="Indented"><p><div style="margin-left: 1em;"><xsl:apply-templates/></div></p></xsl:template>
+  <xsl:template match="img|table|br|td|tr|th">
+  	<xsl:copy><xsl:for-each select="@*"><xsl:copy/></xsl:for-each><xsl:apply-templates/></xsl:copy>
+  </xsl:template> 
+  <xsl:template match="i|b|u"><xsl:element name="{name()}"><xsl:apply-templates/></xsl:element></xsl:template>  
+  <xsl:template match="File"><a href="{@url}" target="_blank"><img src="../{@url}" width="{@width}" height="{@height}" border="0"/></a></xsl:template>
+  
+  
+  
+  <xsl:template match="text()"><xsl:value-of select="."/></xsl:template>
+  
+  <xsl:template match="Author"><b><xsl:apply-templates/></b></xsl:template>
+  <xsl:template match="Affiliation"><i><xsl:apply-templates/></i></xsl:template>
+  <xsl:template name="version_and_date"><p><b><xsl:apply-templates select="Version/Text"/></b>&#160;&#160;<xsl:apply-templates select="Date/Text"/></p></xsl:template>
+  
+  <xsl:template match="Chapter|Appendix|Bibliography" mode="index">
+  <dt><a href="#Chapter_{@id}"><xsl:apply-templates select="Title/Text"/></a></dt>
+  <xsl:for-each select="Content/Section"><dd><a href="#Section_{@id}"><xsl:apply-templates select="Title/Text"/></a></dd></xsl:for-each>
+</xsl:template>
+
+  <xsl:template match="Section" mode="index">
+  <dt><a href="#Section_{@id}"><xsl:apply-templates select="Title/Text"/></a></dt>  
+  </xsl:template>
+
+<xsl:template match="Chapter">
+  <a id="Chapter_{@id}"/>    
+  <h2><xsl:if test="not(starts-with(@id, 'appendix')) and not(starts-with(@id, 'biblio'))">
+  <xsl:value-of select="position()"/></xsl:if>&#160;<xsl:apply-templates select="Title/Text"/></h2>
+  <xsl:apply-templates select="Content/*"/>
+</xsl:template>
+
+  
+
+<xsl:template match="Figure" mode="ref">
+  	<xsl:variable name="temp_total_figs"><xsl:number count="Figure" level="any"/></xsl:variable>       
+	<xsl:variable name="temp_num_of_sub_figs">
+	<xsl:number count="Figure[Title/SubTitle and substring(translate(@id, '_0123456789', '99999999999'), string-length(@id)-1, string-length(@id))='99']" level="any"/>
+   	</xsl:variable>	  	
+  	<xsl:variable name="no"><xsl:value-of select="$temp_total_figs - $temp_num_of_sub_figs"/></xsl:variable>
+  	<xsl:variable name="subtitle">
+  	<xsl:if test="Title/SubTitle"><xsl:value-of select="substring-before(substring-after(Title/SubTitle, '('), ')')"/></xsl:if>
+  	</xsl:variable>
+  	<xsl:value-of select="concat($no, $subtitle)"/>
+  </xsl:template>  
+  <xsl:template match="Table" mode="ref"><xsl:number level="any"/></xsl:template>
+  <xsl:template match="Chapter" mode="ref"><xsl:number level="any"/></xsl:template>
+  <xsl:template match="Section" mode="ref"><xsl:number count="//Chapter|//Chapter//Section" format="1.1" level="multiple"/></xsl:template>
+  <xsl:template match="Subsection" mode="ref"><xsl:number level="multiple" format="1.1.1" count="//Chapter|//Chapter//Section|//Chapter//Section//Subsection"/></xsl:template>
+</xsl:stylesheet>
Index: /tags/start/gsdl-documentation/manuals/processing/crossref-inter.xsl
===================================================================
--- /tags/start/gsdl-documentation/manuals/processing/crossref-inter.xsl	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/processing/crossref-inter.xsl	(revision 13666)
@@ -0,0 +1,63 @@
+<?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"
+  xmlns:util="ExternalRef" extension-element-prefixes="util">
+
+<xsl:template match="CrossRef">
+    <xsl:variable name="ref" select="@ref"/>
+    <xsl:if test="@external">	    	
+	    <xsl:variable name="external" select="@external"/>	    
+	    <!--<a><xsl:attribute name="href"><xsl:value-of select="java:getRef($util, '@external', '@lang', '@target', '$ref')"/></xsl:attribute></a>-->
+	    <a><xsl:attribute name="href"><xsl:value-of select="concat(@external, '_', @lang, '_all.html#', @target, '_', @ref)"/></xsl:attribute><xsl:value-of select="util:getRef($external, @lang, @target, $ref)"/></a>    
+	  </xsl:if>
+	
+	<xsl:variable name="current_chapter" select="ancestor-or-self::Chapter[position()=1]/@id"/>
+
+	<xsl:variable name="target_chapter">
+		<xsl:choose>
+  		<xsl:when test="@target='Figure'"><xsl:value-of select="//Figure[@id=$ref]/ancestor-or-self::Chapter[position()=1]/@id"/></xsl:when>
+  		<xsl:when test="@target='Table'"><xsl:value-of select="//Table[@id=$ref]/ancestor-or-self::Chapter[position()=1]/@id"/></xsl:when>
+  		<xsl:when test="@target='Chapter'"><xsl:value-of select="//Chapter[@id=$ref]/ancestor-or-self::Chapter[position()=1]/@id"/></xsl:when>
+  		<xsl:when test="@target='Section'"><xsl:value-of select="//Section[@id=$ref]/ancestor-or-self::Chapter[position()=1]/@id"/></xsl:when> 		
+  		<xsl:when test="@target='Subsection'"><xsl:value-of select="//Subsection[@id=$ref]/ancestor-or-self::Chapter[position()=1]/@id"/></xsl:when>
+  		</xsl:choose>
+	</xsl:variable>
+  	
+	<a>
+	<xsl:attribute name="href">
+	<xsl:if test="not($current_chapter=$target_chapter)"><xsl:value-of select="concat('Chapter_', $target_chapter, '.htm#', @target, '_', @ref)"/></xsl:if>
+	<xsl:if test="$current_chapter=$target_chapter"><xsl:value-of select="concat('#', @target, '_', @ref)"/></xsl:if>
+	</xsl:attribute>
+  		<xsl:choose>
+  		<xsl:when test="@target='Figure'"><xsl:apply-templates select="//Figure[@id=$ref]" mode="ref"/></xsl:when>
+  		<xsl:when test="@target='Table'"><xsl:apply-templates select="//Table[@id=$ref]" mode="ref"/></xsl:when>
+  		<xsl:when test="@target='Chapter'"><xsl:apply-templates select="//Chapter[@id=$ref]" mode="ref"/></xsl:when>
+  		<xsl:when test="@target='Section'"><xsl:apply-templates select="//Section[@id=$ref]" mode="ref"/></xsl:when> 		
+  		<xsl:when test="@target='Subsection'"><xsl:apply-templates select="//Subsection[@id=$ref]" mode="ref"/></xsl:when>
+  		</xsl:choose>
+  	</a>
+  </xsl:template>
+  
+  <!--
+  <xsl:template match="FootnoteList">  
+  <xsl:for-each select="Footnote">
+  	<xsl:variable name="number">
+  		<xsl:apply-templates select="//FootnoteRef[@id=@id]" mode="getid"/>
+  	</xsl:variable>
+  	
+    <a name="fn{@id}"/><a href="#fnref{@id}">[<xsl:value-of select="$number"/>]</a>
+    <xsl:apply-templates/>
+    <br/>
+  </xsl:for-each>
+  </xsl:template>-->
+  
+  <xsl:template match="FootnoteRef">  	
+  	<a name="fnref{@id}"/><a href="#fn{@id}">[<xsl:number count="FootnoteRef" level="any" from="Chapter"/>]</a>
+  </xsl:template>     
+ 
+  <xsl:template match="FootnoteRef" mode="getid">
+  	<xsl:number count="FootnoteRef" level="any" from="Chapter"/>
+  </xsl:template>
+
+  </xsl:stylesheet>
Index: /tags/start/gsdl-documentation/manuals/processing/crossref-pdf.xsl
===================================================================
--- /tags/start/gsdl-documentation/manuals/processing/crossref-pdf.xsl	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/processing/crossref-pdf.xsl	(revision 13666)
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
+  xmlns:java="http://xml.apache.org/xalan/java" xmlns:util="ExternalRef" extension-element-prefixes="util">
+
+  <xsl:template match="CrossRef">
+    <xsl:variable name="ref" select="@ref"/>
+    <xsl:if test="@external">	    	
+	    <xsl:variable name="external" select="@external"/>
+	    <xsl:value-of select="util:getRef($external, @lang, @target, $ref)"/>
+	  </xsl:if>
+    
+  	<fo:basic-link color="blue" internal-destination="{@target}_{@ref}">
+  		<xsl:choose>
+  		<xsl:when test="@target='Figure'"><xsl:apply-templates select="//Figure[@id=$ref]" mode="ref"/></xsl:when>
+  		<xsl:when test="@target='Table'"><xsl:apply-templates select="//Table[@id=$ref]" mode="ref"/></xsl:when>
+  		<xsl:when test="@target='Chapter'"><xsl:apply-templates select="//Chapter[@id=$ref]" mode="ref"/></xsl:when>
+  		<xsl:when test="@target='Section'"><xsl:apply-templates select="//Section[@id=$ref]" mode="ref"/></xsl:when> 		
+  		<xsl:when test="@target='Subsection'"><xsl:apply-templates select="//Subsection[@id=$ref]" mode="ref"/></xsl:when>
+  		</xsl:choose>
+  	</fo:basic-link>
+  </xsl:template>
+  
+  <xsl:template match="FootnoteList">  
+  <xsl:for-each select="Footnote">
+    <a name="fn{@id}"/><a href="#fnref{@id}">[<xsl:value-of select="@id"/>]</a>
+    <xsl:apply-templates/>
+    <br/>
+  </xsl:for-each>
+  </xsl:template>
+  <xsl:template match="FootnoteRef"><a name="fnref{@id}"/><a href="#fn{@id}">[<xsl:value-of select="@id"/>]</a></xsl:template>
+  
+  <xsl:template match="Figure" mode="ref">
+  	<xsl:variable name="temp_total_figs"><xsl:number count="Figure" level="any"/></xsl:variable>       
+	<xsl:variable name="temp_num_of_sub_figs">
+	<xsl:number count="Figure[Title/SubTitle and substring(translate(@id, '_0123456789', '99999999999'), string-length(@id)-1, string-length(@id))='99']" level="any"/>
+   	</xsl:variable>	  	
+  	<xsl:variable name="no"><xsl:value-of select="$temp_total_figs - $temp_num_of_sub_figs"/></xsl:variable>
+  	<xsl:variable name="subtitle">
+  	<xsl:if test="Title/SubTitle"><xsl:value-of select="substring-before(substring-after(Title/SubTitle, '('), ')')"/></xsl:if>
+  	</xsl:variable>
+  	<xsl:value-of select="concat($no, $subtitle)"/>
+  </xsl:template>  
+  
+  <xsl:template match="Table" mode="ref"><xsl:number level="any"/></xsl:template>
+  
+  <xsl:template match="Chapter" mode="ref"><xsl:number level="any"/></xsl:template>
+  
+  <xsl:template match="Section" mode="ref"><xsl:number count="//Chapter|//Chapter//Section" format="1.1" level="multiple"/></xsl:template>  
+  
+  <xsl:template match="Subsection" mode="ref"><xsl:number level="multiple" format="1.1.1" count="//Chapter|//Chapter//Section|//Chapter//Section//Subsection"/></xsl:template>
+  </xsl:stylesheet>
Index: /tags/start/gsdl-documentation/manuals/processing/crossref.xsl
===================================================================
--- /tags/start/gsdl-documentation/manuals/processing/crossref.xsl	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/processing/crossref.xsl	(revision 13666)
@@ -0,0 +1,34 @@
+<?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"
+  xmlns:util="ExternalRef" extension-element-prefixes="util">
+
+  <xsl:template match="CrossRef">
+    <xsl:variable name="ref" select="@ref"/>
+    <xsl:if test="@external">	    	
+	    <xsl:variable name="external" select="@external"/>	    
+	    <!--<a><xsl:attribute name="href"><xsl:value-of select="java:getRef($util, '@external', '@lang', '@target', '$ref')"/></xsl:attribute></a>-->
+	    <a><xsl:attribute name="href"><xsl:value-of select="concat(@external, '_', @lang, '_all.html#', @target, '_', @ref)"/></xsl:attribute><xsl:value-of select="util:getRef($external, @lang, @target, $ref)"/></a>    
+	  </xsl:if>
+    
+  	<a href="#{@target}_{@ref}">
+  		<xsl:choose>
+  		<xsl:when test="@target='Figure'"><xsl:apply-templates select="//Figure[@id=$ref]" mode="ref"/></xsl:when>
+  		<xsl:when test="@target='Table'"><xsl:apply-templates select="//Table[@id=$ref]" mode="ref"/></xsl:when>
+  		<xsl:when test="@target='Chapter'"><xsl:apply-templates select="//Chapter[@id=$ref]" mode="ref"/></xsl:when>
+  		<xsl:when test="@target='Section'"><xsl:apply-templates select="//Section[@id=$ref]" mode="ref"/></xsl:when> 		
+  		<xsl:when test="@target='Subsection'"><xsl:apply-templates select="//Subsection[@id=$ref]" mode="ref"/></xsl:when>
+  		</xsl:choose>
+  	</a>
+  </xsl:template>
+  
+  <xsl:template match="FootnoteList">  
+  <xsl:for-each select="Footnote">
+    <a name="fn{@id}"/><a href="#fnref{@id}">[<xsl:value-of select="@id"/>]</a>
+    <xsl:apply-templates/>
+    <br/>
+  </xsl:for-each>
+  </xsl:template>
+  <xsl:template match="FootnoteRef"><a name="fnref{@id}"/><a href="#fn{@id}">[<xsl:value-of select="@id"/>]</a></xsl:template>
+  </xsl:stylesheet>
Index: /tags/start/gsdl-documentation/manuals/processing/fo-common.xsl
===================================================================
--- /tags/start/gsdl-documentation/manuals/processing/fo-common.xsl	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/processing/fo-common.xsl	(revision 13666)
@@ -0,0 +1,444 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
+
+<xsl:variable name="font" select="Cyrillic"/>
+
+<!-- display title in different formats -->
+<xsl:template match="Title">
+<xsl:choose>
+<!-- manual title -->
+<xsl:when test="parent::Manual">
+  <fo:block font-size="24.0pt" line-height="24pt" space-after.optimum="25pt" text-align="right" padding-top="3pt"><xsl:apply-templates/></fo:block>
+</xsl:when>
+
+<!-- chapter title -->
+<xsl:when test="parent::Chapter">
+<fo:block font-size="24.0pt" line-height="24pt" text-align="right" padding-top="3pt" id="Chapter_{../@id}">
+<xsl:if test="not(starts-with(@id, 'appendix')) and not(starts-with(@id, 'biblio'))"><xsl:number count="Chapter" format="1"/></xsl:if>
+</fo:block>
+<fo:block font-size="24.0pt" line-height="24pt" space-before.optimum="25pt" text-align="right" padding-top="3pt" text-indent="3cm"><xsl:apply-templates/></fo:block>
+</xsl:when>
+
+<!-- sections' title, with section number -->
+<xsl:when test="parent::Section and not(../Manual)">
+<fo:block font-size="12.0pt" text-align="left" padding-top="3pt" space-before.optimum="25pt" id="Section_{../@id}">
+<xsl:if test="not(starts-with(../../../@id, 'appendix'))"><xsl:number level="multiple" count="Chapter|Chapter/Content/Section" format="1.1"/>&#160;&#160;</xsl:if>
+<xsl:apply-templates select="Text"/>
+</fo:block>
+</xsl:when>
+
+<!-- tables(not hidden) title, in grey background and with unique number -->
+<xsl:when test="parent::Table">
+<fo:block id="Table_{../@id}" font-size="10.0pt" font-weight="bold" line-height="15pt" background-color="grey" margin-left="25pt" space-before="10pt" space-after="3pt">
+Table&#160;<xsl:number level="any" count="Table[not(@class='hidden')]"/>&#160;&#160;<xsl:apply-templates select="Text"/><xsl:value-of select="SubTitle"/>
+</fo:block>
+</xsl:when>
+
+<!-- title of subsections -->
+<xsl:when test="parent::Subsection">
+<fo:block font-size="10pt" font-weight="bold" text-align="left" id="{../@id}" space-before.optimum="25pt">
+<xsl:apply-templates select="Text"/>
+</fo:block>
+</xsl:when>
+
+<!-- title of parts -->
+<xsl:when test="parent::Part">
+<fo:block font-size="10pt" font-weight="bold" text-align="left" id="{../@id}" space-before.optimum="15pt">
+<xsl:apply-templates select="Text"/>
+</fo:block>
+</xsl:when>	
+</xsl:choose>
+</xsl:template>
+
+
+
+<xsl:template match="Title" mode="Figure">
+<xsl:param name="no"/>
+<fo:block id="Figure_{../@id}" font-size="10.0pt" font-weight="bold" line-height="15pt" background-color="grey" margin-left="25pt" space-before="10pt" space-after="3pt">
+Figure&#160;<xsl:value-of select="$no"/><xsl:if test="SubTitle"><xsl:value-of select="SubTitle"/></xsl:if>&#160;<xsl:apply-templates select="Text"/>
+</fo:block>
+</xsl:template>
+
+
+
+<!-- deal with various text paragraph formats -->
+<xsl:template match="Text">
+<xsl:choose>
+<!-- these text display directly -->
+<xsl:when test="parent::Title|parent::Author|parent::Affiliation|parent::Version|parent::Date|parent::Bullet|parent::Footnote"><xsl:apply-templates/></xsl:when>
+
+<!-- text in table cells display with 11pt font size -->
+<xsl:when test="parent::th">
+<fo:block font-size="11.0pt"><xsl:apply-templates select="node()"/></fo:block>
+</xsl:when>
+
+<!-- indented text -->
+<xsl:when test="parent::Indented">
+<fo:block font-size="11.0pt" color="black" text-align="justify" space-before.optimum="15pt" margin-left="35pt">
+<xsl:apply-templates/>
+</fo:block>
+</xsl:when>
+
+<!-- normal text paragraphs -->
+<xsl:otherwise>
+<fo:block font-size="11.0pt" color="black" text-align="justify" space-before.optimum="15pt" margin-left="25pt">
+<xsl:apply-templates/>
+</fo:block>
+</xsl:otherwise>
+</xsl:choose>
+</xsl:template>
+
+
+
+<xsl:template match="Section|Content"><xsl:apply-templates/></xsl:template>
+
+
+<xsl:template match="Version">
+<fo:block font-size="12.0pt" font-weight="bold" color="gray" space-before.optimum="15pt" padding-top="3pt" margin-left="25pt" text-align-last="justify">
+<xsl:apply-templates/><fo:leader leader-pattern="space"/><xsl:value-of select="following-sibling::Date"/>
+</fo:block>
+</xsl:template>
+
+
+<xsl:template match="BulletList">
+<xsl:if test="not(parent::Bullet)">
+<fo:list-block start-indent="2cm" provisional-distance-between-starts="12pt" font-family="{$font}" space-before.optimum="15pt">
+<xsl:for-each select="Bullet">
+<fo:list-item><fo:list-item-label end-indent="label-end()">
+<fo:block><fo:inline font-family="Symbol">&#x2022;</fo:inline></fo:block>
+</fo:list-item-label>
+<fo:list-item-body start-indent="body-start()">				
+<fo:block><xsl:apply-templates/></fo:block>
+
+<!-- if contains a child BulletList node -->
+<xsl:if test="BulletList">					
+<xsl:for-each select="BulletList">
+<fo:list-block start-indent="3cm" provisional-distance-between-starts="12pt" font-family="{$font}" space-before.optimum="5pt">
+<xsl:for-each select="Bullet">
+<fo:list-item><fo:list-item-label end-indent="label-end()">
+<fo:block><fo:inline font-family="Symbol">&#x2022;</fo:inline></fo:block>
+</fo:list-item-label>
+<fo:list-item-body start-indent="body-start()">
+<fo:block><xsl:apply-templates/></fo:block>
+</fo:list-item-body>
+</fo:list-item>
+</xsl:for-each>
+</fo:list-block>	
+</xsl:for-each>
+</xsl:if>
+
+</fo:list-item-body>
+</fo:list-item>
+</xsl:for-each>
+</fo:list-block>
+</xsl:if>
+</xsl:template>
+
+
+
+<xsl:template match="NumberedList">
+<fo:list-block start-indent="2cm" provisional-distance-between-starts="12pt" font-family="{$font}" space-before.optimum="15pt">
+<xsl:for-each select="NumberedItem">
+<fo:list-item><fo:list-item-label end-indent="label-end()">
+<fo:block><fo:inline font-family="Symbol"><xsl:number/>.</fo:inline></fo:block>
+</fo:list-item-label>
+<fo:list-item-body start-indent="body-start()">
+<xsl:choose>
+<!-- does not contain child (indented) Text or CodeLines -->
+<xsl:when test="(count(Text)+count(CodeLine))=1">
+<fo:block><xsl:apply-templates select="Text/node()"/></fo:block>
+</xsl:when>
+
+<!-- contains child (indented) Text or CodeLines -->
+<xsl:otherwise>
+<fo:block><xsl:apply-templates select="Text[1]/node()"/></fo:block>
+<fo:list-block start-indent="3cm" provisional-distance-between-starts="12pt" font-family="{$font}" space-before.optimum="15pt" space-after.optimum="15pt">
+<xsl:for-each select="child::*[position()>1]">
+<fo:list-item><fo:list-item-label end-indent="label-end()"><fo:block/></fo:list-item-label>
+<fo:list-item-body><fo:block><xsl:apply-templates/></fo:block></fo:list-item-body>
+</fo:list-item>
+</xsl:for-each>
+</fo:list-block>
+</xsl:otherwise>
+</xsl:choose>
+</fo:list-item-body>
+</fo:list-item>
+</xsl:for-each>
+</fo:list-block>
+</xsl:template>
+
+
+
+<xsl:template match="b"><fo:inline font-weight="bold"><xsl:apply-templates/></fo:inline></xsl:template>
+
+<xsl:template match="i"><fo:inline font-style="italic"><xsl:apply-templates/></fo:inline></xsl:template>
+
+<xsl:template match="u"><fo:inline text-decoration="underline" color="blue"><xsl:apply-templates/></fo:inline></xsl:template>
+
+<xsl:template match="CodeLine">
+<fo:block font-size="8.0pt" font-family="Courier" color="black" text-align="left">
+<xsl:choose>
+<xsl:when test="parent::NumberedItem or parent::Bullet"/>
+<!-- normal code lines -->
+<xsl:when test="not(parent::Figure) and not(parent::th)">
+<xsl:attribute name="margin-left">50pt</xsl:attribute>
+<xsl:if test="not(name(preceding-sibling::*[position()=1])='CodeLine')">
+<xsl:attribute name="space-before.optimum">8pt</xsl:attribute>
+</xsl:if>
+</xsl:when>
+
+<!-- codeline in a hidden table -->
+<xsl:when test="parent::th and ../../../../@class='hidden'">
+<xsl:attribute name="margin-left">10pt</xsl:attribute>
+<xsl:attribute name="space-before.optimum">8pt</xsl:attribute>
+<xsl:attribute name="space-after.optimum">8pt</xsl:attribute>
+</xsl:when>
+<!-- normal table -->
+<xsl:otherwise>
+<xsl:if test="not(parent::th)">
+<xsl:attribute name="space-before.optimum">3pt</xsl:attribute>
+</xsl:if>
+</xsl:otherwise>
+</xsl:choose>
+
+<xsl:apply-templates/>
+</fo:block>
+
+<!--
+<xsl:param name="withLineNumber">n</xsl:param>
+<xsl:choose>
+<xsl:when test="not(parent::Figure) and not(parent::th)">
+<fo:block font-size="8.0pt" font-family="Courier" color="black" text-align="left" margin-left="50pt">
+<xsl:if test="not(name(preceding-sibling::*[position()=1])='CodeLine')">
+<xsl:attribute name="space-before.optimum">8pt</xsl:attribute>
+</xsl:if>
+<xsl:apply-templates/>
+</fo:block>
+</xsl:when>
+
+<xsl:when test="parent::th and ../../../../@class='hidden'">
+<fo:block font-size="8.0pt" font-family="Courier" color="black" 
+text-align="left" margin-left="10pt" space-before.optimum="8pt" space-after.optimum="8pt">
+<xsl:apply-templates/>
+</fo:block>
+</xsl:when>
+
+<xsl:otherwise>
+<fo:block font-size="8.0pt" font-family="Courier" color="black" text-align="left">
+<xsl:if test="not(parent::th)">
+<xsl:attribute name="space-before.optimum">3pt</xsl:attribute>
+</xsl:if>
+<xsl:if test="$withLineNumber='y'"><xsl:number/></xsl:if>
+<xsl:apply-templates/>
+</fo:block>
+</xsl:otherwise>
+</xsl:choose>
+-->
+</xsl:template>
+
+
+
+
+
+<!-- table -->
+<xsl:template match="Table">
+<fo:table table-layout="fixed" width="100%">
+<fo:table-column column-width="proportional-column-width(1)"/>
+<fo:table-body>
+
+<!-- table title -->
+
+<fo:table-row>
+<!-- always keep the table title with the table -->
+<xsl:if test="not(normalize-space(Title/Text)='')"><xsl:attribute name="keep-with-next">always</xsl:attribute></xsl:if>				
+<fo:table-cell>
+<fo:block>
+<xsl:if test="not(normalize-space(Title/Text)='')"><xsl:apply-templates select="Title"/></xsl:if>
+</fo:block>
+</fo:table-cell>
+</fo:table-row>
+
+<!-- table content -->
+
+<fo:table-row>
+<fo:table-cell>
+<fo:block>
+<!-- use nested table to center-align the table -->
+<fo:table table-layout="fixed" width="100%">
+<fo:table-column column-width="25pt"/>
+<fo:table-column column-width="60pt"/>				
+<fo:table-body>
+<fo:table-row>
+<fo:table-cell column-number="1"/>
+<fo:table-cell column-number="2">
+<fo:table table-layout="fixed">
+<xsl:for-each select="TableContent/tr[1]/th">
+<fo:table-column>
+
+<!-- calculate the column width based on the width in the original html file -->
+
+<xsl:attribute name="column-width">
+<xsl:value-of select="concat(number(@width) * 0.8, 'px')"/>
+</xsl:attribute>
+</fo:table-column>
+</xsl:for-each>
+<fo:table-body>
+<xsl:for-each select="TableContent/tr">
+
+<!-- this is to ensure no breaks in the table -->
+
+<fo:table-row keep-with-next="always">
+<xsl:for-each select="th">
+<xsl:choose>
+
+<!-- when the cell contains only text -->
+
+<xsl:when test="not(../../../@class='hidden') and not(File)">
+<fo:table-cell column-number="{position()}" vertical-align="top" padding="2pt" border="0.5pt" border-color="black" border-style="solid">
+<xsl:if test="position()=1 and normalize-space(../../tr[1]/th[1])=''"><xsl:attribute name="text-align">right</xsl:attribute></xsl:if>
+<xsl:if test="position()>1 and not(last())"><xsl:attribute name="text-align">left</xsl:attribute></xsl:if>
+<xsl:if test="last()"><xsl:attribute name="text-align">justify</xsl:attribute></xsl:if>
+<xsl:apply-templates/>
+</fo:table-cell>
+</xsl:when>
+
+<!-- when the cell is an image --> 
+
+<xsl:when test="not(../../../@class='hidden') and File">
+<fo:table-cell column-number="{position()}" vertical-align="top" text-align="right" padding="2pt" border="0.5pt" border-color="black" border-style="solid">
+<xsl:apply-templates/>
+</fo:table-cell>
+</xsl:when>
+
+<!-- deal with hidden table -->
+
+<xsl:when test="../../../@class='hidden'">
+<fo:table-cell column-number="{position()}" vertical-align="top" padding="2pt">
+<xsl:if test="position()=1"><xsl:attribute name="text-align">left</xsl:attribute></xsl:if>
+<xsl:if test="position()>1"><xsl:attribute name="text-align">justify</xsl:attribute></xsl:if>
+<xsl:apply-templates/>
+</fo:table-cell></xsl:when></xsl:choose></xsl:for-each></fo:table-row></xsl:for-each></fo:table-body></fo:table></fo:table-cell>
+</fo:table-row></fo:table-body></fo:table></fo:block></fo:table-cell></fo:table-row></fo:table-body></fo:table>
+</xsl:template>
+
+
+
+<!-- Figure -->
+<xsl:template match="Figure">
+<fo:table table-layout="fixed" width="100%">
+<fo:table-column column-width="proportional-column-width(1)"/>
+<fo:table-body>
+
+<!-- figure title -->
+<!-- number of current figure = total_number_of_previous_figure - total_number_of_previous_sub_figures-->
+<xsl:variable name="temp_total_figs"><xsl:number count="Figure" level="any"/></xsl:variable>       
+<xsl:variable name="temp_num_of_sub_figs">
+  <xsl:number count="Figure[Title/SubTitle and substring(translate(@id, '_0123456789', '99999999999'), string-length(@id)-1, string-length(@id))='99']" level="any"/>
+</xsl:variable>  	  	
+<xsl:variable name="no"><xsl:value-of select="$temp_total_figs - $temp_num_of_sub_figs"/></xsl:variable>
+
+<fo:table-row keep-with-next="always"><fo:table-cell><fo:block>
+<xsl:apply-templates select="Title" mode="Figure"><xsl:with-param name="no" select="$no"/></xsl:apply-templates>
+</fo:block></fo:table-cell></fo:table-row>
+
+
+<fo:table-row><fo:table-cell>
+<xsl:if test="File"><xsl:apply-templates select="File"/></xsl:if>
+<xsl:if test="CodeLine">
+<fo:block text-align="left">
+<fo:table start-indent="3pt" table-layout="fixed" width="100%" border-spacing="3pt">
+<fo:table-column column-width="proportional-column-width(1)"/>
+<fo:table-column column-width="100mm"/>
+<fo:table-column column-width="proportional-column-width(1)"/>
+<fo:table-body>
+<fo:table-row>
+<fo:table-cell column-number="2">
+
+<xsl:if test="not(@calss='withLineNumber')">
+<xsl:attribute name="border-width">0.1pt</xsl:attribute><xsl:attribute name="border-style">solid</xsl:attribute>
+<xsl:attribute name="border-color">black</xsl:attribute><xsl:attribute name="border-collapse">separate</xsl:attribute>
+</xsl:if>
+
+<xsl:choose>
+<!-- display the codeline number besides each codeline using nested table -->
+<xsl:when test="@class='withLineNumber'">
+<fo:table start-indent="3pt" table-layout="fixed" width="100%" border-spacing="3pt">
+<fo:table-column column-width="28pt"/>											  
+<fo:table-column column-width="proportional-column-width(1)" border-width="0.1pt" border-style="solid" border-color="black" border-collapse="separate"/>
+<fo:table-body>
+<xsl:for-each select="CodeLine">
+<fo:table-row>
+<fo:table-cell column-number="1">
+<fo:block font-size="8pt" font-family="Courier" space-before.optimum="3pt" text-align="right"><xsl:number/></fo:block>
+</fo:table-cell>
+<fo:table-cell column-number="2"><xsl:apply-templates select="."/></fo:table-cell>
+</fo:table-row>
+</xsl:for-each>
+</fo:table-body>
+</fo:table>										
+</xsl:when>
+
+<xsl:otherwise><xsl:apply-templates select="CodeLine"/></xsl:otherwise>
+</xsl:choose></fo:table-cell></fo:table-row></fo:table-body></fo:table></fo:block></xsl:if>
+</fo:table-cell></fo:table-row></fo:table-body></fo:table>
+</xsl:template>
+
+
+
+
+<xsl:template match="File">
+<xsl:variable name="height"><xsl:value-of select="@height"/>em</xsl:variable>
+<xsl:variable name="width"><xsl:value-of select="@width"/>em</xsl:variable>
+<fo:block display-align="center" text-align="center" space-after.optimum="15pt" space-before.optimum="3pt">
+<fo:external-graphic display-align="center" src="{@url}" content-height="{$height}" content-width="{$width}"/>
+</fo:block>
+</xsl:template>
+
+
+
+<!-- reference in the text to a footnote -->
+<xsl:template match="FootnoteRef">
+<xsl:variable name="no"><xsl:value-of select="@id"/></xsl:variable>
+<fo:footnote>
+<fo:inline baseline-shift="super" font-size="smaller">(<xsl:value-of select="$no"/>)</fo:inline>
+<fo:footnote-body>
+<fo:list-block provisional-label-separation="0pt" provisional-distance-between-starts="18pt" space-after.optimum="6pt">
+<fo:list-item>
+<fo:list-item-label end-indent="label-end()">
+<fo:block>(<xsl:number count="//FootnoteRef" level="any"/>)</fo:block>
+</fo:list-item-label>
+<fo:list-item-body start-indent="body-start()">
+<fo:block><xsl:apply-templates select="//Footnote[@id=$no]"/></fo:block>
+</fo:list-item-body>
+</fo:list-item>
+</fo:list-block>
+</fo:footnote-body>
+</fo:footnote>
+</xsl:template>
+
+
+<xsl:template match="Footnote"><xsl:apply-templates/></xsl:template>
+
+
+<xsl:template match="BibItem">
+<fo:block font-size="11.0pt" color="black" text-align="justify" space-before.optimum="15pt" margin-left="25pt"><xsl:apply-templates/></fo:block>
+</xsl:template>
+
+
+<xsl:template match="Author">
+<fo:block font-size="15pt" color="black" text-align="right" space-before.optimum="25pt"><xsl:apply-templates/></fo:block>
+</xsl:template>
+
+
+<xsl:template match="Affiliation">
+<fo:block font-size="10.0pt" color="black" text-align="right" space-after.optimum="125pt" space-before.optimum="25pt"><xsl:apply-templates/></fo:block>
+</xsl:template>
+
+
+<xsl:template match="Text" mode="heading"><fo:block font-size="18.0pt" color="gray" text-align="right"><xsl:apply-templates/></fo:block></xsl:template>
+
+
+<xsl:template match="text()"><xsl:value-of select="."/></xsl:template>
+
+<xsl:template match="br"><fo:block/></xsl:template>
+</xsl:stylesheet>
Index: /tags/start/gsdl-documentation/manuals/processing/style.css
===================================================================
--- /tags/start/gsdl-documentation/manuals/processing/style.css	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/processing/style.css	(revision 13666)
@@ -0,0 +1,27 @@
+/* CSS Document */
+
+h1{ font-family:arial,sans-serif; font-weight:normal; font-size:25px; margin:0; }
+h2{ font-family:arial,sans-serif; font-weight:normal; font-size:22px; margin:0; }
+h3{ font-family:arial,sans-serif; font-weight:normal; font-size:18px; }
+h4{ font-family:arial,sans-serif; font-size:14px; }
+
+p{ FONT-SIZE: 13px; FONT-FAMILY: Arial, Helvetica, sans-serif; COLOR: #000000}
+
+table.figure_code{
+	padding-bottom:2pt; padding-left:2pt; padding-right:2pt; padding-top:2pt;	
+	border-collapse: collapse; border: solid; color:black; border-width: 1pt;
+}
+
+div.linenumber{
+	margin-top:0pt; margin-right:0in; margin-bottom:0in; margin-left:0pt; margin-bottom:0pt; font-family:Courier; FONT-SIZE: 8pt
+}
+
+li {FONT-SIZE: 12px; FONT-FAMILY: Arial, Helvetica, sans-serif; COLOR: #000000}
+
+ul {list-style-type: decimal}
+
+dd {margin-top: 2pt; margin-bottom: 0pt; font-size: 12px}
+dt {margin-top: 1pt; margin-bottom: 0pt; font-size: 12px}
+a {font-size: 12px}
+
+img{border: 0px}
Index: /tags/start/gsdl-documentation/manuals/processing/xml-to-index.xsl
===================================================================
--- /tags/start/gsdl-documentation/manuals/processing/xml-to-index.xsl	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/processing/xml-to-index.xsl	(revision 13666)
@@ -0,0 +1,42 @@
+<?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/xslt/java"
+  extension-element-prefixes="java"
+  exclude-result-prefixes="java">
+  
+  <xsl:variable name="mode">cd</xsl:variable>
+  <xsl:output method="html"/>
+  <xsl:include href="common.xsl"/>
+  
+  <xsl:template match="Manual">
+    <html>
+      <head><title><xsl:value-of select="Title/Text"/></title></head>
+      <link rel="stylesheet" href="../../style.css" type="text/css"/>
+      <body>
+	<h2><xsl:apply-templates select="Heading/Text"/></h2>
+	<h1><xsl:apply-templates select="Title/Text"/></h1>
+	
+	<xsl:apply-templates select="Author"/>
+	<xsl:apply-templates select="Affiliation"/>
+  <xsl:apply-templates select="Text"/>
+	<xsl:apply-templates select="Comment"/>
+	<xsl:call-template name="version_and_date"/>		<br/>
+
+	<xsl:apply-templates select="Section" mode="preface"/>
+		
+	<dl>
+	  <xsl:apply-templates select="Chapter"/>
+	</dl>
+  </body>
+</html>
+</xsl:template>
+
+  <xsl:template match="Chapter">
+    <dt><a href="Chapter_{@id}.htm"><xsl:apply-templates select="Title/Text"/></a></dt>
+    <dd><xsl:for-each select="Title">
+			<xsl:apply-templates/><br/>
+			</xsl:for-each>
+    </dd>
+  </xsl:template>
+</xsl:stylesheet>
Index: /tags/start/gsdl-documentation/manuals/processing/xml-to-many-html.xsl
===================================================================
--- /tags/start/gsdl-documentation/manuals/processing/xml-to-many-html.xsl	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/processing/xml-to-many-html.xsl	(revision 13666)
@@ -0,0 +1,50 @@
+<?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/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+  <xsl:include href="common.xsl"/>
+  <xsl:include href="crossref-inter.xsl"/>
+
+  <xsl:output method="html"/> 
+  
+  <xsl:template match="Chapter|FootnoteList">    
+    <html>
+      <head>
+	<title><xsl:apply-templates select="Title/Text"/></title>
+	<link rel="stylesheet" href="../../style.css" type="text/css"/>
+      </head>
+      <body>
+        <table width="90%" border="0" align="center"><tr><td>
+	<h2><xsl:value-of select="/Manual/Heading/Text"/>&#160;<xsl:value-of select="/Manual/Title/Text"/></h2>
+	<a name="Chapter_{@id}"/><h1>
+	  <xsl:if test="not(starts-with(@id, 'appendix') or starts-with(@id, 'biblio'))">
+	  Chapter <xsl:number/>&#160;</xsl:if><xsl:apply-templates select="Title/Text"/></h1>
+	
+	<xsl:if test="Content/Section">
+	<h3>Contents</h3>	
+	<xsl:apply-templates select="Content/Section" mode="index"/>
+	</xsl:if>
+
+	<xsl:apply-templates select="Content/*"/>	
+	
+	<xsl:if test="descendant::FootnoteRef and not(name()='FootnoteList')">
+  	<hr/>
+	  <xsl:for-each select="descendant::FootnoteRef">
+	  <xsl:variable name="fnrefname"><xsl:value-of select="@id"/></xsl:variable>
+	  <xsl:variable name="number"><xsl:number count="FootnoteRef" level="any" from="Chapter"/></xsl:variable>  		  
+	  <xsl:for-each select="/Manual/FootnoteList/Footnote[@id=$fnrefname]">
+		<!--<a name="fn{@id}"/><a href="#fnref{@id}">[<xsl:number/>]</a>&#160;-->		
+    <a name="fn{@id}"/><a href="#fnref{@id}">[<xsl:value-of select="$number"/>]</a>
+		<xsl:apply-templates/>
+		<br/>		
+     </xsl:for-each>     
+	  </xsl:for-each>
+	</xsl:if>
+	</td></tr></table>
+      </body>
+    </html>    
+  </xsl:template>  
+</xsl:stylesheet> 
Index: /tags/start/gsdl-documentation/manuals/processing/xml-to-one-html.xsl
===================================================================
--- /tags/start/gsdl-documentation/manuals/processing/xml-to-one-html.xsl	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/processing/xml-to-one-html.xsl	(revision 13666)
@@ -0,0 +1,44 @@
+<?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/xslt/java"
+  xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+  extension-element-prefixes="java util"
+  exclude-result-prefixes="java util">
+
+  <xsl:include href="common.xsl"/>
+  <xsl:include href="crossref.xsl"/>
+  <xsl:output method="html"/>
+  
+  <xsl:template match="Manual">
+    <html>
+      <head>
+      <title><xsl:value-of select="Title/Text"/></title>
+      <link rel="stylesheet" href="../../style.css" type="text/css"/>
+      </head>
+    <body>
+    <table width="90%" border="0" align="center">
+      <tr><td>
+    	<h2><xsl:apply-templates select="Heading/Text"/></h2>
+			<h1><xsl:apply-templates select="Title/Text"/></h1>
+			<xsl:apply-templates select="Author"/>
+			<xsl:apply-templates select="Affiliation"/>
+			<xsl:apply-templates select="Text"/>
+			<xsl:apply-templates select="Comment"/>
+			<xsl:call-template name="version_and_date"/>		
+			<br/>			
+			<xsl:apply-templates select="Section" mode="preface"/>
+			<h3>Contents</h3>
+			<a name="index"/>
+			<dl>
+	  		<xsl:apply-templates select="Chapter[not(@hidden)]|Appendix|Bibliography" mode="index"/>
+			</dl>
+			<xsl:apply-templates select="Chapter"/>
+			<xsl:apply-templates select="Appendix"/>
+			<xsl:apply-templates select="Bibliography"/>	
+			<xsl:if test="FootnoteList"><hr/><xsl:apply-templates select="FootnoteList"/></xsl:if>	
+			</td></tr></table>
+    </body>
+  </html>
+</xsl:template>  
+</xsl:stylesheet>
Index: /tags/start/gsdl-documentation/manuals/processing/xml-to-pdf.xsl
===================================================================
--- /tags/start/gsdl-documentation/manuals/processing/xml-to-pdf.xsl	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/processing/xml-to-pdf.xsl	(revision 13666)
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
+
+<xsl:include href="fo-common.xsl"/>
+<xsl:include href="crossref-pdf.xsl"/>
+
+<xsl:variable name="font" select="sans-serif"/>
+
+<xsl:template match="Manual">
+
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+<fo:layout-master-set>
+<!-- template set for different types of pages -->
+<!-- the first page template -->
+<fo:simple-page-master master-name="first" page-height="29.7cm" page-width="21cm" margin-top="1cm" margin-bottom="2cm" margin-left="2.5cm" margin-right="2.5cm">
+<fo:region-start extent="1cm"/>
+<fo:region-body margin-top="3cm" margin-left="2cm"/>
+<fo:region-before precedence="true" extent="3cm"/>
+<fo:region-after extent="1.5cm"/>
+</fo:simple-page-master>
+
+<!-- the preface page template -->
+<fo:simple-page-master master-name="preface" page-height="29.7cm" page-width="21cm" margin-top="1cm" margin-bottom="2cm" margin-left="2.5cm" margin-right="2.5cm">
+<fo:region-body margin-top="3cm"/>
+<fo:region-before extent="3cm"/>
+<fo:region-after extent="1.5cm"/>
+</fo:simple-page-master>
+
+<!-- the acknowledgements page template -->
+<fo:simple-page-master master-name="acknowledgements" page-height="29.7cm" page-width="21cm"
+margin-top="1cm" margin-bottom="2cm" margin-left="2.5cm" margin-right="2.5cm">
+<fo:region-body margin-top="3cm"/>
+<fo:region-before extent="3cm"/>
+<fo:region-after extent="1.5cm"/>
+</fo:simple-page-master>
+
+<!-- the table of content page template -->
+<fo:simple-page-master master-name="ToC" page-height="29.7cm" page-width="21cm" margin-top="1cm" margin-bottom="2cm" margin-left="2.5cm" margin-right="2.5cm">
+<fo:region-body margin-top="3cm"/>
+<fo:region-before extent="3cm"/>
+<fo:region-after extent="1.5cm"/>
+</fo:simple-page-master>
+
+<!-- the document page template -->
+<fo:simple-page-master master-name="document" page-height="29.7cm" page-width="21cm" margin-top="1cm" margin-bottom="2cm" margin-left="2.5cm" margin-right="2.5cm">
+<fo:region-body margin-top="3cm"/>
+<fo:region-before extent="3cm" precedence="true" display-align="after"/>
+<fo:region-after extent="1.5cm"/>
+</fo:simple-page-master>
+</fo:layout-master-set>
+
+
+
+<!-- Cover Page-->
+
+<fo:page-sequence master-reference="first">
+<fo:static-content flow-name="xsl-region-start">
+<!-- left banner image -->
+<fo:block-container height="29cm" width="2cm" left="0cm" top="0cm">
+<fo:block><fo:external-graphic src="url('Install_files/image001.jpg')" height="29cm"/></fo:block>
+</fo:block-container>
+</fo:static-content>
+<fo:flow flow-name="xsl-region-body">
+<xsl:apply-templates select="Heading/Text" mode="heading"/>
+<xsl:apply-templates select="Title"/>
+<xsl:apply-templates select="Author"/>
+<xsl:apply-templates select="Affiliation"/>
+<xsl:apply-templates select="Text"/>
+<xsl:apply-templates select="Comment"/>
+<xsl:apply-templates select="Version"/>
+</fo:flow>
+</fo:page-sequence>
+
+
+
+<!-- Preface -->
+
+<fo:page-sequence master-reference="preface">
+<fo:flow flow-name="xsl-region-body">
+<xsl:for-each select="Section[not(@id='acknowledgements')]"><xsl:apply-templates/></xsl:for-each>
+</fo:flow>
+</fo:page-sequence>
+
+<fo:page-sequence master-reference="acknowledgements">
+<fo:flow flow-name="xsl-region-body"><xsl:apply-templates select="Section[@id='acknowledgements']"/></fo:flow>
+</fo:page-sequence>
+
+
+
+<!-- ToC Page -->
+
+<fo:page-sequence master-reference="ToC">
+<fo:flow flow-name="xsl-region-body">
+<fo:block text-align="right" font-size="24.0pt" line-height="24pt" space-after.optimum="25pt" padding-top="3pt">Contents</fo:block>
+<xsl:for-each select="Chapter">
+  <xsl:variable name="show_number">
+    <xsl:if test="starts-with(@id, 'appendix') or starts-with(@id, 'biblio')">n</xsl:if>
+    <xsl:if test="not(starts-with(@id, 'appendix')) and not(starts-with(@id, 'biblio'))">y</xsl:if>
+  </xsl:variable>
+  <fo:block text-align="start" font-size="15.0pt" line-height="15pt" text-align-last="justify" space-before.optimum="15pt" padding-top="3pt">
+  <fo:basic-link color="black" internal-destination="Chapter_{@id}">
+  <xsl:if test="$show_number='y'"><xsl:number/>&#160;&#160;</xsl:if>
+  <xsl:apply-templates select="Title/Text"/>
+  <fo:leader leader-pattern="space"/>
+  <fo:page-number-citation ref-id="Chapter_{@id}"/>
+  </fo:basic-link>
+  </fo:block>
+
+  <xsl:for-each select="Content/Section">
+    <fo:block text-align="start" font-size="10.0pt" font-weight="bold" text-align-last="justify" padding-top="3pt" space-before.optimum="15pt" margin-left="12pt">
+    <fo:basic-link color="black" internal-destination="Section_{@id}">
+    <xsl:if test="$show_number='y'"><xsl:number level="multiple" count="Chapter|Chapter/Content/Section" format="1.1"/>&#160;&#160;</xsl:if>
+    <xsl:apply-templates select="Title/Text"/>
+    <fo:leader leader-pattern="space"/>
+    <fo:page-number-citation ref-id="Section_{@id}"/>
+    </fo:basic-link>
+    <xsl:for-each select="Content/Subsection"><xsl:call-template name="SubsectionLink"/></xsl:for-each>
+    </fo:block>
+  </xsl:for-each>
+</xsl:for-each>
+
+
+
+<!-- figure and table lists -->
+<!--
+<xsl:if test="not(count(//Figure[not(normalize-space(Title/Text)='')])=0)">
+<fo:block break-before="page" space-before.optimum="50pt" space-after.optimum="15pt" font-size="15pt" font-weight="bold">Figures</fo:block>
+<xsl:for-each select="//Figure">
+<fo:block text-align="start" font-size="10.0pt" font-weight="bold" text-align-last="justify">
+<fo:basic-link color="black" internal-destination="Figure_{@id}">
+<xsl:apply-templates select="Title/Text"/>
+<fo:leader leader-pattern="space"/>
+<fo:page-number-citation ref-id="Figure_{@id}"/>
+</fo:basic-link>
+</fo:block>
+</xsl:for-each>
+</xsl:if>
+
+<xsl:if test="not(count(//Table[not(normalize-space(Title/Text)='')])=0)">
+<fo:block break-before="page" space-before.optimum="50pt" space-after.optimum="15pt" font-size="15pt" font-weight="bold">Tables</fo:block>
+<xsl:for-each select="//Table[not(@class='hidden')]">
+<fo:block text-align="start" font-size="10.0pt" font-weight="bold" text-align-last="justify">
+<fo:basic-link color="black" internal-destination="Table_{@id}">
+<xsl:apply-templates select="Title/Text"/>
+<fo:leader leader-pattern="space"/>
+<fo:page-number-citation ref-id="Table_{@id}"/>
+</fo:basic-link>
+</fo:block>
+</xsl:for-each>
+</xsl:if>
+-->
+
+</fo:flow>
+</fo:page-sequence>
+
+
+
+<!-- Document -->
+
+<fo:page-sequence master-reference="document" initial-page-number="1">
+<!-- defines header of a page -->
+<fo:static-content flow-name="xsl-region-before">
+<xsl:variable name="pageno"><fo:page-number/></xsl:variable>
+<xsl:choose>
+<xsl:when test="$pageno='1'">
+<fo:block-container height="1cm" width="18cm" left="0cm" top="0cm" display-align="after">
+<fo:block text-align="start" font-size="10pt" font-family="{$font}" line-height="14pt">greenstone.org<fo:external-graphic src="url('_files/header.gif')"/>
+</fo:block>
+</fo:block-container>
+</xsl:when>
+<xsl:otherwise>
+<fo:block-container height="1cm" width="18cm" left="0cm" top="0cm" display-align="after">
+<fo:block text-align="start" font-size="10pt" font-family="{$font}" line-height="14pt">
+<fo:page-number/>&#160;&#160;
+<fo:retrieve-marker retrieve-class-name="head" retrieve-position="first-including-carryover" retrieve-boundary="page-sequence"/>
+</fo:block>
+</fo:block-container>
+</xsl:otherwise>
+</xsl:choose>
+</fo:static-content>
+
+<!-- footer of a page -->
+<fo:static-content flow-name="xsl-footnote-separator">
+<fo:block><fo:leader leader-pattern="rule" leader-length="100%" rule-style="solid" rule-thickness="0.5pt"/></fo:block>
+</fo:static-content>
+
+<fo:flow flow-name="xsl-region-body">
+<xsl:for-each select="Chapter">
+<!-- header -->
+<fo:block><fo:marker marker-class-name="head"><xsl:value-of select="Title"/></fo:marker></fo:block>
+<xsl:apply-templates/>
+<xsl:if test="not(count(following-sibling::*[not(name()='FootnoteList')])=0)">
+<fo:block break-after="page"/>
+</xsl:if>
+</xsl:for-each>
+
+</fo:flow>
+</fo:page-sequence>
+</fo:root>
+</xsl:template>
+
+
+
+<xsl:template name="SubsectionLink">
+<fo:block text-align="start" font-size="10.0pt" text-align-last="justify" margin-left="25pt" padding-top="3pt">
+<fo:basic-link color="black">
+<xsl:attribute name="internal-destination">Subsection_<xsl:value-of select="@id"/></xsl:attribute>
+<xsl:apply-templates select="Title/Text"/>
+<fo:leader leader-pattern="space"/>
+<fo:page-number-citation ref-id="Subsection_{@id}"/>
+</fo:basic-link>
+</fo:block>
+</xsl:template>
+</xsl:stylesheet>
Index: /tags/start/gsdl-documentation/manuals/xml-source/en/Develop_en.xml
===================================================================
--- /tags/start/gsdl-documentation/manuals/xml-source/en/Develop_en.xml	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/xml-source/en/Develop_en.xml	(revision 13666)
@@ -0,0 +1,5208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Manual>
+<Heading>
+<Text id="1">GREENSTONE DIGITAL LIBRARY</Text>
+</Heading>
+<Title>
+<Text id="2">DEVELOPER'S GUIDE</Text>
+</Title>
+<Author>
+<Text id="3">David Bainbridge, Dana McKay and Ian H. Witten</Text>
+</Author>
+<Affiliation>
+<Text id="4">Department of Computer Science<br/>University of Waikato, New Zealand</Text>
+</Affiliation>
+<Text id="5">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 New Zealand Digital Library Project at the University of Waikato, and developed 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.</Text>
+<Comment>
+<Text id="6">We want to ensure that this software works well for you. Please report any problems to <i>greenstone@cs.waikato.ac.nz</i></Text>
+</Comment>
+<Version>
+<Text id="7">Greenstone gsdl-2.50</Text>
+</Version>
+<Date>
+<Text id="8">March 2004</Text>
+</Date>
+<Section id="about_this_manual">
+<Title>
+<Text id="9">About this manual</Text>
+</Title>
+<Content>
+<Text id="10">This manual explains how Greenstone works. It is aimed at those who wish to customise collections and to develop and maintain the software.</Text>
+<Text id="11">Section <CrossRef target="Chapter" ref="understanding_the_collection-building_process"/> gives an insider's account of the collection-building process, including the directory structure, the internal document format, and the configuration file that governs the structure of each collection. Section <CrossRef target="Chapter" ref="getting_the_most_out_of_your_documents"/> describes the parts of Greenstone that process source documents (and metadata) and dictate how the information is accessed through the user interface. It also describes âexternalâ software components that are distributed with Greenstone. Section <CrossRef target="Chapter" ref="the_greenstone_runtime_system"/> explains the structure of the Greenstone runtime system, and also gives details of the software that help to understand how it works and how to modify the system to suit different needs. Section <CrossRef target="Chapter" ref="configuring_your_greenstone_site"/> describes the Greenstone configuration files, and an Appendix introduces the C++ Standard Template Library.</Text>
+<Text id="12">When working with the Greenstone software, you may encounter references to features that are not described in this manual, for Greenstone is under constant development. To learn about current work, join the Greenstone mailing list (instructions at greenstone.org).</Text>
+</Content>
+</Section>
+<Section id="companion_documents">
+<Title>
+<Text id="13">Companion documents</Text>
+</Title>
+<Content>
+<Text id="14">The complete set of Greenstone documents includes five volumes:</Text>
+<BulletList>
+<Bullet>
+<Text id="15">Greenstone Digital Library Installer's Guide</Text>
+</Bullet>
+<Bullet>
+<Text id="16">Greenstone Digital Library User's Guide</Text>
+</Bullet>
+<Bullet>
+<Text id="17">Greenstone Digital Library Developer's Guide <i>(this document)</i></Text>
+</Bullet>
+<Bullet>
+<Text id="18">Greenstone Digital Library: From Paper to Collection</Text>
+</Bullet>
+<Bullet>
+<Text id="19">Greenstone Digital Library: Using the Organizer</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Section>
+<Section id="acknowledgements">
+<Title>
+<Text id="20">Acknowledgements</Text>
+</Title>
+<Content>
+<Text id="21">The Greenstone software is a collaborative effort between manypeople. Rodger McNab and Stefan Boddie are the principal architects andimplementors. Contributions have been made by David Bainbridge, GeorgeBuchanan, Hong Chen, Michael Dewsnip, Katherine Don, Elke Duncker, Carl Gutwin, Geoff Holmes, Dana McKay, JohnMcPherson, Craig Nevill-Manning, Dynal Patel, Gordon Paynter, Bernhard Pfahringer, ToddReed, Bill Rogers, John Thompson, and Stuart Yeates. Other members of the New ZealandDigital Library project provided advice and inspiration in the design ofthe system: Mark Apperley, Sally Jo Cunningham, Matt Jones, Steve Jones, Te TakaKeegan, Michel Loots, Malika Mahoui, Gary Marsden, Dave Nichols and Lloyd Smith. We would also like toacknowledge all those who have contributed to the GNU-licensed packagesincluded in this distribution: MG, GDBM, PDFTOHTML, PERL, WGET, WVWARE and XLHTML.</Text>
+</Content>
+</Section>
+<Chapter id="understanding_the_collection-building_process">
+<Title>
+<Text id="22">Understanding the collection-building process</Text>
+</Title>
+<Content>
+<Text id="23">End users of Greenstone can build collections using the Collector, described in the <i>Greenstone Digital Library User's Guide</i>(Section 3). This makes it very easy to build collections modelled after existing ones but with new content. However, it is not really feasible to use the Collector to create collections with completely new structures. It does invite you to edit the collection configuration file, which governs the collection's structure, but you need to know quite a lot about Greenstone to make radical yet effective changes. This section tells you what you need to know to do this. It also describes the Greenstone directory structure and the format in which documents are stored internally.</Text>
+<Text id="24">We assume throughout this manual that you have installed Greenstone on your computer, be it Windows or Unix. If you have not yet done this you should consult the <i>Greenstone Digital Library Installer's Guide</i>. The name <i>GSDLHOME</i> is used throughout to refer to the Greenstone home directory, which is called <i>%GSDLHOME%</i> on Windows systems and <i>$GSDLHOME</i> on Unix ones. You set this directory during the installation procedure.</Text>
+<Section id="building_collections_from_the_command_line">
+<Title>
+<Text id="25">Building collections from the command line</Text>
+</Title>
+<Content>
+<Text id="26">Let us begin by walking through the operations involved in building a collection from the command line, to help understand the process better. Of course, for more user-friendly collection building, you should use the Collector instead. The collection we take as an example is one that comes on the Greenstone software distribution CD-ROM, and contains the WWW home pages of many of the people who have worked on the New Zealand Digital Library Project and the Greenstone software.</Text>
+<Text id="27">Separate subsections follow for building under Windows and Unix. In fact, the two subsections are very nearly identicalâyou need only go through the one that pertains to your system. When following the walkthrough, you may find some operations mysterious and arcane, but follow them closelyâtheir meaning will be explained later on. After the walkthroughs is a brief summary of the differences between building a collection under the two systems.</Text>
+<Subsection id="collection_building_under_windows">
+<Title>
+<Text id="28">Collection building under Windows</Text>
+</Title>
+<Content>
+<Text id="29">The first challenge when building a Greenstone collection from the command line under Windows is to get at the âcommand prompt,â the place where you type commands. Try looking in the <i>Start</i> menu, or under the <i>Programs</i> submenu, for an entry like <i>MS-DOS Prompt</i>, <i>DOS Prompt</i>, or <i>Command Prompt</i>. If you can't find it, invoke the <i>Run</i> entry and try typing <i>command</i> (or <i>cmd</i>) in the dialog box. If all else fails, seek help from one who knows, such as your system administrator.</Text>
+<Text id="30">Change into the directory where Greenstone has been installed. Assuming Greenstone was installed in its default location, you can move there by typing</Text>
+<CodeLine>cd "C:\Program Files\gsdl "</CodeLine>
+<Text id="31">(You need the quotation marks because of the space in <i>Program Files</i>.) Next, at the prompt type</Text>
+<CodeLine>setup.bat</CodeLine>
+<Text id="32">This batch file (which you can read if you like) tells the system where to look for Greenstone programs.<FootnoteRef id="1"/>If, later on in your interactive session at the DOS prompt, you wish to return to the top level Greenstone directory you can accomplish this by typing <i>cd "%GSDLHOME%"</i> (again, the quotation marks are here because of spaces in the filename). If you close your DOS window and start another one, you will need to invoke <i>setup.bat</i> again.</Text>
+<Text id="33">Now you are in a position to make, build and rebuild collections. The first program we will look at is the Perl program <i>mkcol.pl</i>, whose name stands for âmake a collection.â First run the program by typing <i>perl âS mkcol.pl</i> to cause a description of usage and a list of arguments to appear on the screen âif your Windows environment is set up to associate the Perl application with files ending in <i>.pl</i>, this can be more concisely expressed by entering <i>mkcol.pl</i>. As you can see from the usage statement, the only required argument is <i>creator</i>, which is used to specify who built the collection.</Text>
+<Text id="34">Let us now use the command to create the initial files and subdirectories necessary for our home page collection of Greenstone Digital Library project members. To assign the collection the name <i>dlpeople</i>, I typed</Text>
+<CodeLine>perl âS mkcol.pl âcreator me@cs.waikato.ac.nz dlpeople</CodeLine>
+<Text id="35">(or <i>mkcol.pl âcreator me@cs.waikato.ac.nz dlpeople</i> if Perl is associated with the <i>.pl</i> file extension). Please substitute your email address for mine!</Text>
+<Text id="36">To view the newly created files, move to the newly created collection directory by typing</Text>
+<CodeLine>cd "%GSDLHOME%\collect\dlpeople"</CodeLine>
+<Figure id="collection_configuration_file_created_by_mkcol">
+<Title>
+<Text id="37">Collection configuration file created by <i>mkcol.pl</i></Text>
+</Title>
+<CodeLine>creatorÂ Â Â Â Â Â Â Â Â Â Â Â Â me@cs.waikato.ac.nz</CodeLine>
+<CodeLine>maintainerÂ Â Â Â Â Â Â Â Â Â me@cs.waikato.ac.nz</CodeLine>
+<CodeLine>publicÂ Â Â Â Â Â Â Â Â Â Â Â Â Â true</CodeLine>
+<CodeLine>betaÂ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â true</CodeLine>
+<CodeLine>indexesÂ Â Â Â Â Â Â Â Â Â Â Â Â document:text</CodeLine>
+<CodeLine>defaultindexÂ Â Â Â Â Â Â Â document:text</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â ZIPPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â GAPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â TEXTPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â HTMLPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â EMAILPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â ArcPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â RecPlug</CodeLine>
+<CodeLine>classifyÂ Â Â Â Â Â Â Â Â Â Â Â AZList -metadata "Title"</CodeLine>
+<CodeLine>collectionmetaÂ collectionnameÂ Â Â Â "dlpeople"</CodeLine>
+<CodeLine>collectionmetaÂ iconcollectionÂ Â Â Â ""</CodeLine>
+<CodeLine>collectionmetaÂ collectionextraÂ Â Â ""</CodeLine>
+<CodeLine>collectionmetaÂ .document:textÂ Â Â Â "documents "</CodeLine>
+</Figure>
+<Text id="38">You can list the contents of this directory by typing <i>dir</i>. There should be seven subdirectories: <i>archives</i>, <i>building</i>, <i>etc</i>, <i>images</i>, <i>import</i>, <i>index</i> and <i>perllib</i>.</Text>
+<Text id="39">Now we must populate the collection with sample documents. Source material for the <i>dlpeople</i> collection can be found on the Greenstone distribution CD-ROM under the directory <i>collect\dlpeople</i>. First, insert the CD-ROM into the drive (e.g. into <i>D:\</i>). Next, copy the contents of the <i>D:\collect\dlpeople</i> directory into the <i>dlpeople</i> collection's <i>import</i> directory. You can do this as follows:</Text>
+<Indented>
+<Text id="40">select the contents of the <i>dlpeople</i> directory <br/>and drag them into the <i>dlpeople</i> collection's <i>import</i> directory.</Text>
+</Indented>
+<Text id="41">Alternatively, you can type the command</Text>
+<CodeLine>xcopy /s d:\collect\dlpeople\* import</CodeLine>
+<Text id="42">In the collection's <i>etc</i> directory there is a file called <i>collect.cfg</i>. Open it using your favourite text editor âa basic but commonly available one is called <i>edit</i>. It should look something like Figure <CrossRef target="Figure" ref="collection_configuration_file_created_by_mkcol"/>, which shows the collection configuration file that was created by using the command <i>perl âS mkcol.pl âcreator me@cs.waikato.ac.nz dlpeople</i>.</Text>
+<Text id="43">Now you are ready to âimportâ the collection. This is the process of bringing the documents into the Greenstone system, standardising the document format, the way that metadata is specified, and the file structure in which the documents are stored. Type <i>perl âS import.pl</i> at the prompt to get a list of all the options for the import program. The -<i>remove old</i> option is used to ensure that any previously imported documents are removed first.</Text>
+<CodeLine>perl âS import.pl -removeold dlpeople</CodeLine>
+<Text id="44">Don't worry about all the text that scrolls pastâit's just reporting the progress of the import. Be aware that importing this collection takes about five minutes on a 1 GHz computer, and correspondingly longer on slower machines. Note that you do not have to be in either the <i>collect</i> or <i>dlpeople</i> directories when this command is entered; because GSDLHOME is already set, the Greenstone software can work out where the necessary files are.</Text>
+<Text id="45">Now let's make some changes to the collection configuration file to customize its appearance. First, give the collection a name. This will be treated by web browsers as the page title for the front page of the collection, and used as the collection icon in the absence of a picture. Change the line that reads <i>collectionmeta collectionname "dlpeople"</i> to something like <i>collectionmeta collectionname "The People of the NZDL project"</i>.</Text>
+<Text id="46">Add a description of your collection between the quotes of the line that reads <i>collectionmeta collectionextra ""</i>. This is used as the <i>About this collection</i> text on the collection's home page. I added âThis collection is made up of the home pages of some of the people who have worked on the NZDL project.â It is important to enter this as a single line in the editor âdon't be tempted to press enter if the cursor reaches the right-hand side of the editor window even though there is more text to add, just keep on typing âotherwise the configuration file cannot be parsed correctly. If you want your collection to be usable with different language interfaces, there is a way to make this text come out differently depending on the interface language chosen. This is described in Section <CrossRef target="Section" ref="configuration_file"/> below.</Text>
+<Text id="47">You can use any picture you can view in a web browser for a collection iconâthe image I created is shown in Figure <CrossRef target="Figure" ref="collection_icon"/>. Put the location of the image between the quotes of the line <i>collectionmeta iconcollection ""</i> in the configuration file. As shorthand, and to aid portability <i>_httpprefix_</i> can be used as the start of a URL that points to an image within the Greenstone file area. For example you could enter: <i>_httpprefix_/collect/dlpeople/images/icon.gif</i> if you have put a suitable image in the collection's <i>images</i> directory (<i>collect\dlpeople\images</i> in our example).</Text>
+<Text id="48">Save the collection configuration file, and close itâyou won't need to look at it again during this tutorial.</Text>
+<Text id="49">The next phase is to âbuildâ the collection, which creates all the indexes and files that make the collection work. Type <i>perl âS buildcol.pl</i> at the command prompt for a list of collection-building options. These options are explained more fully in Section <CrossRef target="Section" ref="import_and_build_processes"/>. For now, stick to the defaults by typing</Text>
+<CodeLine>perl âS buildcol.pl dlpeople</CodeLine>
+<Text id="50">Again, don't worry about the âprogress reportâ text that scrolls past.</Text>
+<Text id="51">Make the collection âliveâ as follows:</Text>
+<Text id="52">select the contents of the <i>dlpeople</i> collection's <i>building</i> directory and drag them into the <i>index</i> directory.</Text>
+<Text id="53">Alternatively, you can remove the <i>index</i> directory (and all its contents) by typing the command</Text>
+<CodeLine>rd /s index                 # on Windows NT/2000</CodeLine>
+<CodeLine>deltree /Y index       # on Windows 95/98</CodeLine>
+<Text id="54">and then change the name of the <i>building</i> directory to <i>index</i> with</Text>
+<CodeLine>ren building index</CodeLine>
+<Text id="55">Finally, type</Text>
+<CodeLine>mkdir building</CodeLine>
+<Text id="56">in preparation for any future rebuilds. It is important that these commands are issued from the correct directory (unlike the Greenstone commands <i>mkcol.pl</i>, <i>import.pl</i> and <i>buildcol.pl</i>). If the current working directory is not <i>dlpeople</i>, type <i>cd "%GSDLHOME%\collect\dlpeople"</i> before going through the <i>rd</i>, <i>ren</i> and <i>mkdir</i> sequence above.</Text>
+<Text id="57">You should be able to access the newly built collection from your Greenstone homepage. You will have to reload the page if you already had it open in your browser, or perhaps even close the browser and restart it (to prevent caching problems). Alternatively, if you are using the âlocal libraryâ version of Greenstone you will have to restart the library program. To view the new collection, click on the image. The result should look something like Figure <CrossRef target="Figure" ref="about_page_for_the_new_collection"/>.</Text>
+<Figure id="collection_icon">
+<Title>
+<Text id="58">Collection icon</Text>
+</Title>
+<File width="156" height="120" url="images/Dev_Fig_2.gif"/>
+</Figure>
+<Text id="59">In summary then, the commands typed to produce the <i>dlpeople</i> collection are:</Text>
+<CodeLine>cd "C:\Program Files\gsdl " # assuming default location</CodeLine>
+<CodeLine>setup.bat</CodeLine>
+<CodeLine>perl âS mkcol.pl âcreator me@cs.waikato.ac.nz dlpeople</CodeLine>
+<CodeLine>cd "%GSDLHOME%\collect\dlpeople "</CodeLine>
+<CodeLine>xcopy   /s   d:\collect\dlpeople\*   import # assuming D drive</CodeLine>
+<CodeLine>perl âS import.pl dlpeople</CodeLine>
+<CodeLine>perl âS buildcol.pl dlpeople</CodeLine>
+<CodeLine>rd /s index           # on Windows NT/2000</CodeLine>
+<CodeLine>deltree /Y index # on Windows 95/98</CodeLine>
+<CodeLine>ren building index</CodeLine>
+<CodeLine>mkdir building</CodeLine>
+</Content>
+</Subsection>
+<Subsection id="collection_building_under_unix">
+<Title>
+<Text id="60">Collection building under Unix</Text>
+</Title>
+<Content>
+<Text id="61">First change into the directory where Greenstone has been installed. For example, if Greenstone is installed under its default name at the top level of your home account you can move there by typing</Text>
+<CodeLine>cd ~/gsdl</CodeLine>
+<Text id="62">Next at the prompt, type</Text>
+<CodeLine>source setup.bash     # if you're running the BASH shell</CodeLine>
+<CodeLine>source setup.csh       # if you're running the C shell</CodeLine>
+<Text id="63">These batch files (which you can read if you like) tell the system where to look for Greenstone programs. If, later on in your command-line session with Greenstone, you wish to return to the top level Greenstone directory you can accomplish this by typing <i>cd $GSDLHOME</i>.</Text>
+<Text id="64">If you are unsure of the shell type you are using, enter <i>echo $0</i> at your command-line prompt âit will print out the sought information. If you are using a different shell contact your system administrator for advice.</Text>
+<Text id="65">With the appropriate setup file sourced, we are now in a position to make, build and rebuild collections. The first program we will look at is the Perl program <i>mkcol.pl</i>, whose name stands for âmake a collection.â First run the program by typing <i>mkcol.pl</i> on its own to cause a description of usage and a list of arguments to appear on the screen. As you can see from the usage statement, the only required argument is <i>creator</i>, which is used to specify who built the collection.</Text>
+<Figure id="about_page_for_the_new_collection">
+<Title>
+<Text id="66">âAboutâ page for the new collection</Text>
+</Title>
+<File width="389" height="409" url="images/Dev_Fig_3.png"/>
+</Figure>
+<Text id="67">Let us now use the command to create the initial files and directories necessary for our home page collection of Greenstone Digital Library project members. To assign the collection the name <i>dlpeople</i>, I typed</Text>
+<CodeLine>mkcol.pl âcreator me@cs.waikato.ac.nz dlpeople</CodeLine>
+<Text id="68">Please substitute your email address for mine!</Text>
+<Text id="69">To view the newly created files, move to the newly created collection directory by typing</Text>
+<CodeLine>cd $GSDLHOME/collect/dlpeople</CodeLine>
+<Text id="70">You can list the contents of this directory by typing <i>ls</i>. There should be seven subdirectories: <i>archives</i>, <i>building</i>, <i>etc</i>, <i>images</i>, <i>import</i>, <i>index</i> and <i>perllib</i>.</Text>
+<Text id="71">Now we must populate the collection with sample documents. Source material for the <i>dlpeople</i> collection can be found on the Greenstone distribution CD-ROM under the directory <i>collect/dlpeople</i>. To get information from a CD-ROM under Linux, insert the disk into the drive and type</Text>
+<CodeLine>mount /cdrom</CodeLine>
+<Text id="72">at the prompt (this command may differ from one system to another). Once mounted, the CD-ROM can be used like any other directory, so type <i>ls /cdrom/collect</i>. This should reveal a directory called <i>dlpeople</i> on the CD-ROM.</Text>
+<Text id="73">Next, copy the contents of the <i>/cdrom/collect/dlpeople</i> directory into the <i>GSDLHOME/collect/dlpeople/import</i> directory. To do this, type the command</Text>
+<CodeLine>cp âr /cdrom/collect/dlpeople/*   import/</CodeLine>
+<Text id="74">Then type</Text>
+<CodeLine>umount /cdrom</CodeLine>
+<Text id="75">to close the CD-ROM drive.</Text>
+<Text id="76">In the collection's <i>etc</i> directory there is a file called <i>collect.cfg</i>. Open this using your favourite text editor âemacs is a popular editor on Linux. It should look something like Figure <CrossRef target="Figure" ref="collection_configuration_file_created_by_mkcol"/>, which shows the collection configuration file that was created by using the command <i>mkcol.pl âcreator me@cs.waikato.ac.nz dlpeople</i>.</Text>
+<Text id="77">Now you are ready to âimportâ the collection. This is the process of bringing the documents into the Greenstone system, standardising the document format, the way that metadata is specified, and the file structure in which the documents are stored. Type <i>import.pl</i> at the prompt to get a list of all the options for the import program. The -<i>remove old</i> option is used to ensure that any previously imported documents are removed first</Text>
+<CodeLine>import.pl âremoveold dlpeople</CodeLine>
+<Text id="78">Don't worry about all the text that scrolls pastâit's just reporting the progress of the import. Be aware that importing this collection takes about five minutes on a 1 GHz computer, and correspondingly longer on slower machines. Note, you do not have to be in either the <i>collect</i> or <i>dlpeople</i> directories when this command is entered; because GSDLHOME is already set, the Greenstone software can work out where the necessary files are.</Text>
+<Text id="79">Now let's make some changes to the collection configuration file to customize its appearance. First, give the collection a name. This will be treated by web browsers as the page title for the front page of the collection, and used as the collection icon in the absence of a picture. Change the line that reads <i>collectionmeta collectionname "dlpeople"</i> to something like <i>collectionmeta collectionname "The People of the NZDL project"</i>.</Text>
+<Text id="80">Add a description of your collection between the quotes of the line that reads <i>collectionmeta collectionextra ""</i>. This is used as the <i>About this collection</i> text on the collection's home page. I added âThis collection is made up of the home pages of some of the people who have worked on the NZDL project.â It is important to enter this as a single line in the editorâdon't be tempted to press enter if the cursor reaches the right-hand side of the editor window even though there is more text to add, just keep on typing âotherwise the configuration file cannot be parsed correctly. If you want your collection to be usable with different language interfaces, there is a way to make this text come out differently depending on the interface language chosen. This is described in Section <CrossRef target="Section" ref="configuration_file"/> below.</Text>
+<Text id="81">You can use any picture you can view in a web browser for a collection iconâthe image I created is shown in Figure <CrossRef target="Figure" ref="collection_icon"/>. Put the location of the image between the quotes of the line <i>collectionmeta iconcollection ""</i> in the configuration file. As shorthand, and to aid portability <i>_httpprefix_</i> can be used as the start of a URL that points to an image within the Greenstone file area. For example you could enter: <i>_httpprefix_/collect/dlpeople/images/icon.gif</i> if you have put a suitable image in the collection's <i>images</i> directory (<i>collect/dlpeople/images</i> in our example).</Text>
+<Text id="82">Save the collection configuration file, and close itâyou won't need to look at it again during this tutorial.</Text>
+<Text id="83">The next phase is to âbuildâ the collection, which creates all the indexes and files that make the collection work. Type <i>buildcol.pl</i> at the command prompt for a list of collection-building options. These options are explained more fully in Section <CrossRef target="Section" ref="import_and_build_processes"/>. For now, stick to the defaults by typing</Text>
+<CodeLine>buildcol.pl dlpeople</CodeLine>
+<Text id="84">at the prompt. Again, don't worry about the âprogress reportâ text that scrolls past.</Text>
+<Text id="85">Make the collection âliveâ by putting all the material that has just been put in the collection's <i>building</i> directory into the <i>index</i> directory. If you have built this collection before, first remove the old index using</Text>
+<CodeLine>rm âr index/*</CodeLine>
+<Text id="86">(assuming you are in the <i>dlpeople</i> directory) at the prompt. Then type</Text>
+<CodeLine>mv building/* index/</CodeLine>
+<Table id="collection-building_differences_between_windows_and_linux">
+<Title>
+<Text id="87">Collection-building differences between Windows and Linux</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="265">
+<Text id="88"><b>Windows</b></Text>
+</th>
+<th width="265">
+<Text id="89"><b>Linux</b></Text>
+</th>
+</tr>
+<tr>
+<th width="265">
+<Text id="90">Run <i>setup.bat</i> to make Greenstone programs available</Text>
+</th>
+<th width="265">
+<Text id="91">Source <i>setup.bash</i> or <i>setup.csh</i> to make programs available</Text>
+</th>
+</tr>
+<tr>
+<th width="265">
+<Text id="92">Copy files from CD-ROM using the visual manager or Windows commands</Text>
+</th>
+<th width="265">
+<Text id="93">Copy files from CD-ROM using <i>mount</i> and Unix commands</Text>
+</th>
+</tr>
+<tr>
+<th width="265">
+<Text id="94">Old collection index replaced by typing <i>rd /s index</i> then <i>ren building index</i> followed by <i>mkdir building</i>, or by using visual file manager.</Text>
+</th>
+<th width="265">
+<Text id="95">Old collection index replaced by typing <i>rm âr index/*</i> then <i>mv building/* index</i></Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="96">You should be able to access the collection from your Greenstone homepage. You will have to reload the page if you already had it open in your browser, or perhaps even close the browser and restart it (to prevent caching problems). To view the new collection, click on the image. The result should look something like Figure <CrossRef target="Figure" ref="about_page_for_the_new_collection"/>.</Text>
+<Text id="97">In summary then, the commands typed to produced the <i>dlpeople</i> collection are:</Text>
+<CodeLine>cd ~/gsdl # assuming default Greenstone in home directory</CodeLine>
+<CodeLine>source setup.bash     # if you're running the BASH shell</CodeLine>
+<CodeLine>source setup.csh       # if you're running the C shell</CodeLine>
+<CodeLine>mkcol.pl âcreator me@cs.waikato.ac.nz dlpeople</CodeLine>
+<CodeLine>cd $GSDLHOME/collect/dlpeople</CodeLine>
+<CodeLine>mount /cdrom # assuming this is where CD-ROM is mapped to</CodeLine>
+<CodeLine>cp âr /cdrom/collect/dlpeople/* import/</CodeLine>
+<CodeLine>umount /cdrom</CodeLine>
+<CodeLine>import.pl dlpeople</CodeLine>
+<CodeLine>buildcol.pl dlpeople</CodeLine>
+<CodeLine>rm -r index/*</CodeLine>
+<CodeLine>mv building/* index</CodeLine>
+</Content>
+</Subsection>
+<Subsection id="differences_between_windows_and_unix">
+<Title>
+<Text id="98">Differences between Windows and Unix</Text>
+</Title>
+<Content>
+<Text id="99">The collection building process under Unix is very similar to that under Windows, but there are some small differences which are summarised in Table <CrossRef target="Table" ref="collection-building_differences_between_windows_and_linux"/>.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="greenstone_directories">
+<Title>
+<Text id="100">Greenstone directories</Text>
+</Title>
+<Content>
+<Text id="101">Figure <CrossRef target="Figure" ref="structure_of_the_gsdlhome_directory"/> shows the structure of the <i>GSDLHOME</i> directory. Table <CrossRef target="Table" ref="where_to_find_information_about_directories"/> gives a brief description of the contents of each of the directories shown in the diagram. Some directories are more fully described in a later section of the manualâuse the section guide in Table <CrossRef target="Table" ref="where_to_find_information_about_directories"/> to see where to find more information.</Text>
+<Figure id="structure_of_the_gsdlhome_directory">
+<Title>
+<Text id="102">Structure of the <i>GSDLHOME</i> directory</Text>
+</Title>
+<File width="415" height="143" url="images/Dev_Fig_4.gif"/>
+</Figure>
+<Table id="where_to_find_information_about_directories">
+<Title>
+<Text id="103">Where to find information about directories</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="331">
+<Text id="104"><b>Contents</b></Text>
+</th>
+<th width="66">
+<Text id="105">Section</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="106"><i>bin</i></Text>
+</th>
+<th width="331">
+<Text id="107">Executable code, including binaries in the directory with your O/S name.</Text>
+</th>
+<th width="66">
+<Text id="108">â</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="109"><i>bin/script</i></Text>
+</th>
+<th width="331">
+<Text id="110">Perl scripts used for creating and building collections (for example <i>import.pl</i> and <i>buildcol.pl</i>). To get a description of any of these programs, type their name at the command prompt.</Text>
+</th>
+<th width="66">
+<Text id="111">1.3</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="112"><i>perllib</i></Text>
+</th>
+<th width="331">
+<Text id="113">Perl modules used at import and build time (plugins, for example).</Text>
+</th>
+<th width="66">
+<Text id="114">2.1</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="115"><i>perllib/plugins</i></Text>
+</th>
+<th width="331">
+<Text id="116">Perl code for document processing plugins.</Text>
+</th>
+<th width="66">
+<Text id="117">2.1</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="118"><i>perllib/classify</i></Text>
+</th>
+<th width="331">
+<Text id="119">Perl code for classifiers (for example the AZList code that makes a document list based on the alphabetical order of some attribute).</Text>
+</th>
+<th width="66">
+<Text id="120">2.2</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="121"><i>cgi-bin</i></Text>
+</th>
+<th width="331">
+<Text id="122">All Greenstone CGI scripts, which are moved to the system cgi-bin directory.</Text>
+</th>
+<th width="66">
+<Text id="123">â</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="124"><i>tmp</i></Text>
+</th>
+<th width="331">
+<Text id="125">Directory used by Greenstone for storing temporary files.</Text>
+</th>
+<th width="66">
+<Text id="126">â</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="127"><i>etc</i></Text>
+</th>
+<th width="331">
+<Text id="128">Configuration files, initialisation and error logs, user authorisation databases.</Text>
+</th>
+<th width="66">
+<Text id="129">â</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="130"><i>src</i></Text>
+</th>
+<th width="331">
+<Text id="131">C++ code used for serving collections via a web server.</Text>
+</th>
+<th width="66">
+<Text id="132">3</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="133"><i>src/colservr</i></Text>
+</th>
+<th width="331">
+<Text id="134">C++ code for serving collectionsâanswering queries and the like.</Text>
+</th>
+<th width="66">
+<Text id="135"><CrossRef target="Section" ref="protocol"/></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="136"><i>src/recpt</i></Text>
+</th>
+<th width="331">
+<Text id="137">C++ code for getting queries from the user interface and formatting query responses for the interface.</Text>
+</th>
+<th width="66">
+<Text id="138">3.9</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="139"><i>packages</i></Text>
+</th>
+<th width="331">
+<Text id="140">Source code for non-Greenstone software packages that are used by Greenstone.</Text>
+</th>
+<th width="66">
+<Text id="141">2.5</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="142"><i>packages/mg</i></Text>
+</th>
+<th width="331">
+<Text id="143">The source code for mg , the compression and indexing software used by Greenstone.</Text>
+</th>
+<th width="66">
+<Text id="144">2.5</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="145"><i>mappings</i></Text>
+</th>
+<th width="331">
+<Text id="146">Unicode translation tables (for example for the GB Chinese character set).</Text>
+</th>
+<th width="66">
+<Text id="147">â</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="148"><i>macros</i></Text>
+</th>
+<th width="331">
+<Text id="149">The macro files used for the user interface.</Text>
+</th>
+<th width="66">
+<Text id="150">2.4</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="151"><i>collect</i></Text>
+</th>
+<th width="331">
+<Text id="152">Collections being served from this copy of Greenstone</Text>
+</th>
+<th width="66">
+<Text id="153">1.1</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="154"><i>lib</i></Text>
+</th>
+<th width="331">
+<Text id="155">C++ source code used by both the collection server and the receptionist.</Text>
+</th>
+<th width="66">
+<Text id="156">3.1</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="157"><i>images</i></Text>
+</th>
+<th width="331">
+<Text id="158">Images used in the user interface.</Text>
+</th>
+<th width="66">
+<Text id="159">â</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="160"><i>docs</i></Text>
+</th>
+<th width="331">
+<Text id="161">Documentation.</Text>
+</th>
+<th width="66">
+<Text id="162">â</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Section>
+<Section id="import_and_build_processes">
+<Title>
+<Text id="163">Import and build processes</Text>
+</Title>
+<Content>
+<Text id="164">In the command-line collection-building process of Section <CrossRef target="Section" ref="building_collections_from_the_command_line"/>, one command, <i>import.pl</i>, is used for importing documents and another, <i>buildcol.pl</i>, for building the collection. Here we learn more about what these programs do and the options that they support. We use the variable <i>col_name</i> to refer to the collection being built or imported.</Text>
+<Text id="165">The import and build processes have many similarities, and as a result take many of the same options, described in Table <CrossRef target="Table" ref="options_for_the_import_and_build_processes"/>. (Remember that to see the options for any Greenstone script you just type its name with no options at the command prompt).</Text>
+<Table id="options_for_the_import_and_build_processes">
+<Title>
+<Text id="166">Options for the <i>import</i> and <i>build</i> processes</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="104">
+<Text id="167"><b>Argument</b></Text>
+</th>
+<th width="293">
+<Text id="168"><b>Function</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="169"><i>-verbosity</i></Text>
+</th>
+<th width="104">
+<Text id="170">Number 0-3</Text>
+</th>
+<th width="293">
+<Text id="171">Control how much information about the process is printed to standard error; 0 gives a little, 3 gives lots.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="172"><i>-archivedir</i></Text>
+</th>
+<th width="104">
+<Text id="173">Directory name</Text>
+</th>
+<th width="293">
+<Text id="174">Specify where the Greenstone archive files are storedâthat is, where <i>import.pl</i> puts them and where <i>buildcol.pl</i> finds them. Defaults to <i>GSDLHOME/collect/col_name/archives</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="175"><i>-maxdocs</i></Text>
+</th>
+<th width="104">
+<Text id="176">Number &gt;0</Text>
+</th>
+<th width="293">
+<Text id="177">Indicates the maximum number of documents to be imported or built. Useful when testing a new collection configuration file, or new plugins.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="178"><i>-collectdir</i></Text>
+</th>
+<th width="104">
+<Text id="179">Directory name</Text>
+</th>
+<th width="293">
+<Text id="180">Specify where the collection can be found. Defaults to <i>GSDLHOME/collect</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="181"><i>-out</i></Text>
+</th>
+<th width="104">
+<Text id="182">Filename</Text>
+</th>
+<th width="293">
+<Text id="183">Specify a file to which to write all output messages, which defaults to standard error (the screen). Useful when working with debugging statements.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="184"><i>-keepold</i></Text>
+</th>
+<th width="104">
+<Text id="185">None</Text>
+</th>
+<th width="293">
+<Text id="186">Do not remove the result of the previous import or build operation. In the case of import, do not remove the contents of the <i>archives</i> directory; when building, do not remove the content of the <i>building</i> directory.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="187"><i>âdebug</i></Text>
+</th>
+<th width="104">
+<Text id="188">None</Text>
+</th>
+<th width="293">
+<Text id="189">Print plugin output to standard output.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Subsection id="the_import_process">
+<Title>
+<Text id="190">The import process</Text>
+</Title>
+<Content>
+<Text id="191">The import process's primary responsibility is to convert documents from their native format into the Greenstone Archive Format used within Greenstone, and write a summary file (called <i>archives.inf</i>) which will be used when the collection is built. <i>Import.pl</i> needs to know what plugins should be used, and where to find the original document files. Table <CrossRef target="Table" ref="options_for_the_import_and_build_processes"/> shows the options common to both import and build processes; Table <CrossRef target="Table" ref="additional_options_for_the_import_process"/> shows additional options applicable to the import process only. The <i>OIDtype</i> option deserves some explanation. Each document has an associated Object Identifier or OID. This is best computed by hashing the contents of the document (<i>hash</i>). However, this is slow, so a simpler alternative (<i>incremental</i>) is provided which simply numbers the documents sequentially in the order in which they are imported. You can use <i>incremental</i> for speed, but use <i>hash</i> if you intend adding documents to your collection at a later date (without re-importing).</Text>
+<Table id="additional_options_for_the_import_process">
+<Title>
+<Text id="192">Additional options for the <i>import</i> process</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="104">
+<Text id="193"><b>Argument</b></Text>
+</th>
+<th width="293">
+<Text id="194"><b>Function</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="195"><i>-importdir</i></Text>
+</th>
+<th width="104">
+<Text id="196">Directory name</Text>
+</th>
+<th width="293">
+<Text id="197">Where material to be imported is found. Defaults to <i>GSDLHOME/collect/col_name/import</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="198"><i>-removeold</i></Text>
+</th>
+<th width="104">
+<Text id="199">None</Text>
+</th>
+<th width="293">
+<Text id="200">Remove the contents of the <i>archives</i> directory before importing.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="201"><i>-gzip</i></Text>
+</th>
+<th width="104">
+<Text id="202">None</Text>
+</th>
+<th width="293">
+<Text id="203">Zip up the Greenstone archive documents produced by <i>import</i> (ZIPPlug must be included in the plugin list, and <i>gzip</i> must be installed on your machine).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="204"><i>-groupsize</i></Text>
+</th>
+<th width="104">
+<Text id="205">Number &gt;0</Text>
+</th>
+<th width="293">
+<Text id="206">Number of documents to group together into one Greenstone archive file, defaults 1 (that is, one document per file).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="207"><i>âsortmeta</i></Text>
+</th>
+<th width="104">
+<Text id="208">Metadata tag name</Text>
+</th>
+<th width="293">
+<Text id="209">Sort the documents alphabetically by the named metadata tag. However, if the collection has more than one group in the collection (i.e. <i>groupsize</i> &gt;1), this functionality is disabled.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="210"><i>-OIDtype</i></Text>
+</th>
+<th width="104">
+<Text id="211"><i>hash</i> or <br/><i>incremental</i></Text>
+</th>
+<th width="293">
+<Text id="212">Method of creating OIDs for documents: <i>hash</i> hashes the content but is slow; <i>incremental</i> simply assigns document numbers sequentially, and is faster.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Figure id="steps_in_the_import_process">
+<Title>
+<Text id="213">Steps in the <i>import</i> process</Text>
+</Title>
+<File width="402" height="379" url="images/Dev_Fig_5.gif"/>
+</Figure>
+<Text id="214">Figure <CrossRef target="Figure" ref="steps_in_the_import_process"/> represents the import process implemented by the <i>import.pl</i> program. Each oval represents a module used to perform tasks that relate to a specific part of the Greenstone system. All these modules can be found in the <i>GSDLHOME/perllib</i> directory.</Text>
+<Text id="215">For step 3, note that import variables like <i>importdir</i> and <i>archivedir</i> can be set from the collection configuration file or from the command line. If set in the command line, any configuration file setting is ignored.</Text>
+<Text id="216">In step 6, the archives information file (<i>archives.inf</i>) is created.</Text>
+<Text id="217">Step 7 creates an object that knows where documents are to be saved, and obeys any special saving instructions (such as <i>sortmeta</i>, which sorts the documents according to a specified metadata tag).</Text>
+<Text id="218">Most of the work done in the import process is actually accomplished by plugins, which are called by the <i>plugin</i> module. This module creates a pipeline of the plugins specified in the collection configuration file. It also handles the writing of Greenstone archive documents (using a <i>document</i> object).</Text>
+</Content>
+</Subsection>
+<Subsection id="the_build_process">
+<Title>
+<Text id="219">The build process</Text>
+</Title>
+<Content>
+<Text id="220">During the building process the text is compressed, and the full-text indexes that are specified in the collection configuration file are created. Furthermore, information about how the collection is to appear on the web is precalculated and incorporated into the collectionâfor example information about icons and titles, and information produced by classifiers. <i>Buildcol.pl</i> has many options that it shares with <i>import.pl</i>, shown in Table <CrossRef target="Table" ref="options_for_the_import_and_build_processes"/>, and some that are specific to its purpose, in Table <CrossRef target="Table" ref="additional_options_for_the_build_process"/>.</Text>
+<Table id="additional_options_for_the_build_process">
+<Title>
+<Text id="221">Additional options for the <i>build</i> process</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="104">
+<Text id="222"><b>Argument</b></Text>
+</th>
+<th width="293">
+<Text id="223"><b>Function</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="224"><i>-builddir</i></Text>
+</th>
+<th width="104">
+<Text id="225">Directory name</Text>
+</th>
+<th width="293">
+<Text id="226">Specify where the result of building is to be stored (defaults to <i>GSDLHOME/collect/col_name/building</i>).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="227"><i>-index</i></Text>
+</th>
+<th width="104">
+<Text id="228">Index name (e.g.<br/><i>section:Title</i>)</Text>
+</th>
+<th width="293">
+<Text id="229">Specify which indexes to build. This defaults to all the indexes indicated in the collection configuration file.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="230"><i>-allclassifications</i></Text>
+</th>
+<th width="104">
+<Text id="231">None</Text>
+</th>
+<th width="293">
+<Text id="232">Prevent the build process from removing classifications that include no documents (for example, the âXâ classification in titles if there are no documents whose titles start with the letter <i>X</i>).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="233"><i>-create_images</i></Text>
+</th>
+<th width="104">
+<Text id="234">None</Text>
+</th>
+<th width="293">
+<Text id="235">Create collection icons automatically (to use this, GIMP, and the Gimp Perl module, must be installed).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="236"><i>-mode</i></Text>
+</th>
+<th width="104">
+<Text id="237"><i>all</i>, <br/><i>compress_text</i>, <br/><i>infodb</i>, or <br/><i>build_index</i></Text>
+</th>
+<th width="293">
+<Text id="238">Determine what the build process is to do (defaults to <i>all</i>). <i>All</i> does a full build, <i>compress_text</i> only compresses the document text, <i>infodb</i> creates a database of information pertaining to the collectionâname, files, associated files, classification information and the likeâand <i>build_index</i> builds the indexes specified in the collection configuration file or on the command line.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="239"><i>âno_text</i></Text>
+</th>
+<th width="104"/>
+<th width="293">
+<Text id="240">Don't store compressed text. This option is useful for minimizing the size of the built indexes if you intend always to display the original documents at run-time.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Figure id="steps_in_the_build_process">
+<Title>
+<Text id="241">Steps in the <i>build</i> process</Text>
+</Title>
+<File width="308" height="234" url="images/Dev_Fig_6.gif"/>
+</Figure>
+<Text id="242">The diagram in Figure <CrossRef target="Figure" ref="steps_in_the_build_process"/> represents the execution of <i>buildcol.pl</i>. Many of the steps are common to the import process. The first one that is not is step 4 (to the left). This is performed only if the <i>create_images</i> option has been set. Then, the images are created and registered in the collection configuration file by a function in the <i>buildcol.pl</i> script. For this to work properly, GIMP (Gnu Image Manipulation Program), and the Gimp Perl module, must be installed and properly configured. Also, there must be write (as well as read) access to the collection configuration file.</Text>
+<Text id="243">Step 5 first checks to see whether there is a collection-specific build procedure. A few collections require special build-time processing, in which case a collection-specific builder must be written and placed in the collection's <i>perllib</i> directory, named by the collection name with âbuilderâ suffixed. Collection-specific builders are derived from <i>mgbuilder</i>. In step 5 the builder (be it the default or a collection-specific one) is initialised with information such as how many documents are to be included, whether or not the old version of the collection is to be retained, and where the <i>building</i> and <i>archive</i> directories are located.</Text>
+<Text id="244">Step 6 is the building step, in which the document text is compressed and indexed, collection titles and icons are stored in a collection information database, and data structures are built to support the classifiers that are called for in the collection's plugins. All these steps are handled by <i>mgbuilder</i> (or the collection-specific builder), which in turn uses the mg (âManaging Gigabytes,â see Witten <i>et al</i>., 1999) software for compressing and indexing.</Text>
+<Text id="245">The parts of the collection that are built can be specified by the <i>mode</i> option, but the default is to build everythingâcompressed text, indexes, and collection information database.</Text>
+<Text id="246">To make a collection available over the web once it is built, you must move it from the collection's <i>building</i> directory to the <i>index</i> directory. Collections are not built directly into <i>index</i> because large collections may take hours or days to build. It is important that the building process does not affect an existing copy of the collection until the build is complete.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="greenstone_archive_documents">
+<Title>
+<Text id="247">Greenstone archive documents</Text>
+</Title>
+<Content>
+<Text id="248">All source documents are brought into the Greenstone system by converting them to a format known as the Greenstone Archive Format. This is an XML style that marks documents into sections, and can hold metadata at the document or section level. You should not have to create Greenstone archive files manuallyâthat is the job of the document processing plugins described in the next chapter. However, it may be helpful to understand the format of Greenstone files, and so we describe it here.</Text>
+<Text id="249">In XML, tags are enclosed in angle brackets for markup. The Greenstone archive format encodes documents that are already in html, and any embedded &lt;, &gt;, or " characters within the original text ar7e escaped using the standard convention <i>&amp;lt;</i>, <i>&amp;gt;</i> and <i>&amp;quot;</i>.</Text>
+<Figure id="greenstone_archive_format">
+<Title>
+<Text id="250">Greenstone archive format: (a) Document Type Definition (DTD); (b) Example document</Text>
+<SubTitle>
+<Text id="251">(a)</Text>
+</SubTitle>
+</Title>
+<CodeLine>&lt;!DOCTYPE GreenstoneArchive [</CodeLine>
+<CodeLine>Â Â Â &lt;!ELEMENT Section (Description,Content,Section*)&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;!ELEMENT Description (Metadata*)&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;!ELEMENT Content (#PCDATA)&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;!ELEMENT Metadata (#PCDATA)&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;ATTLIST Metadata name CDATA #REQUIRED&gt;</CodeLine>
+<CodeLine>]&gt;</CodeLine>
+</Figure>
+<Figure id="greenstone_archive_format_1">
+<Title>
+<Text id="252"/>
+<SubTitle>
+<Text id="253">(b)</Text>
+</SubTitle>
+</Title>
+<CodeLine>&lt;?xml version="1.0"?&gt;</CodeLine>
+<CodeLine>&lt;!DOCTYPE GreenstoneArchive SYSTEM</CodeLine>
+<CodeLine>"http://greenstone.org/dtd/GreenstoneArchive/1.0/GreenstoneArchive.dtd" &gt;</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Metadata name= "gsdlsourcefilename"&gt;ec158e.txt&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Metadata name= "Title"&gt;Freshwater Resources in Arid Lands&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Metadata name= "Identifier"&gt;HASH0158f56086efffe592636058&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Metadata name= "gsdlassocfile"&gt;cover.jpg:image/jpeg:&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Metadata name= "gsdlassocfile"&gt;p07a.png:image/png:&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â &lt;Metadata name= "Title"&gt;Preface&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Content&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <i>This is the text of the preface</i>
+</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;/Content&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;/Section&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â &lt;Metadata name= "Title"&gt;First and only chapter&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &lt;Metadata name= "Title"&gt;Part 1&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â &lt;Content&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <i>This is the first part of the first and only chapter</i>
+</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â &lt;/Content&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;/Section&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â &lt;Metadata name= "Title"&gt;Part 2&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â &lt;Content&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <i>This is the second part of the first and only chapter</i>
+</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â &lt;/Content&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;/Section&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;/Section&gt;</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+</Figure>
+<Text id="254">Figure <CrossRef target="Figure" ref="greenstone_archive_format"/> gives the XML Document Type Definition (DTD) for the Greenstone archive format. Basically, a document is split up into <i>Sections</i>, which can be nested. Each <i>Section</i> has a <i>Description</i> that comprises zero or more <i>Metadata</i> items, and a <i>Content</i> part (which may be null)âthis is where the actual document's contents go. With each <i>Metadata</i> element is associated a name attribute (the name can be anything), and some textual data. In XML, <i>PCDATA</i> stands for âparsed character dataâ: basically text.</Text>
+<Text id="255">Figure <CrossRef target="Figure" ref="greenstone_archive_format_1"/> shows a simple document in this format, comprising a short book with two associated images. The book has two sections called <i>Preface</i> and <i>First and only chapter</i> respectively, the second of which has two subsections. Note that there is no notion of a âchapterâ as such: it is represented simply as a top-level section</Text>
+<Table id="greenstone_archive_format_values">
+<Title>
+<Text id="256">Greenstone archive format: Values for the <i>name</i> attribute of the <i>Metadata</i> tag</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="130">
+<Text id="257"><i>gsdlsourcefilename</i></Text>
+</th>
+<th width="400">
+<Text id="258">Original file from which the Greenstone archive file was generated</Text>
+</th>
+</tr>
+<tr>
+<th width="130">
+<Text id="259"><i>gsdlassocfile</i></Text>
+</th>
+<th width="400">
+<Text id="260">File associated with the document (e.g. an image file)</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="261">The <i>&lt;Section&gt;</i> tag denotes the start of each document section, and the corresponding <i>&lt;/Section&gt;</i> closing tag marks the end of that section. Following each <i>&lt;Section&gt;</i> tag is a <i>&lt;Description&gt;</i> section. Within this come any number of <i>&lt;Metadata&gt;</i> elements. Thus different metadata can be associated with individual sections of a document. Most of these are for particular metadata types such as <i>&lt;Title&gt;</i>. The two values of the <i>name</i> attribute shown in Table <CrossRef target="Table" ref="greenstone_archive_format_values"/> are treated specially by Greenstone; all others are considered to be metadata that is attached to that section.</Text>
+<Text id="262">In some collections documents are split into individual pages. These are treated as sections. For example, a book might have first-level sections that correspond to chapters, within each of which are defined a number of âsectionsâ that actually correspond to the individual pages of the chapter.</Text>
+<Subsection id="document_metadata">
+<Title>
+<Text id="263">Document metadata</Text>
+</Title>
+<Content>
+<Text id="264">Metadata is descriptive information such as author, title, date, keywords, and so on, that is associated with a document. It has already been mentioned that metadata is stored with documents. Looking at Figure <CrossRef target="Figure" ref="greenstone_archive_format"/>, you can see that <i>&lt;Metadata&gt;</i> tags specify the name of the metadata type, and give a value for that metadata. One example is the line <i>&lt;Metadata name="Title"&gt;First and only chapter&lt;/Metadata&gt;</i> in Figure <CrossRef target="Figure" ref="greenstone_archive_format_1"/>âthe title of a document is a piece of metadata associated with it. The Dublin Core metadata standard is used for defining metadata types (Dublin Core, 2001; Weibel, 1999; Thiele, 1997).</Text>
+<Text id="265">Table <CrossRef target="Table" ref="dublin_core_metadata_standard"/> shows what types are available in the standardâstarred entries are used in collections available from the New Zealand Digital Library web site today. If there is no type that aptly describes a particular kind of metadata, metadata types that are not in the Dublin Core may be used too. For example, the Demo collection contains <i>how to</i> and <i>Magazine</i> metadata.</Text>
+<Table id="dublin_core_metadata_standard">
+<Title>
+<Text id="266">Dublin Core metadata standard</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="133">
+<Text id="267"><b>Name</b></Text>
+</th>
+<th width="94">
+<Text id="268"><b>Metadata <br/>subtag</b></Text>
+</th>
+<th width="305">
+<Text id="269"><b>Definition</b></Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="270">*Title</Text>
+</th>
+<th width="94">
+<Text id="271">Title</Text>
+</th>
+<th width="305">
+<Text id="272">A name given to the resource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="273">*Creator</Text>
+</th>
+<th width="94">
+<Text id="274"><i>Creator</i></Text>
+</th>
+<th width="305">
+<Text id="275">An entity primarily responsible for making the content of the resource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="276">*Subject and keywords</Text>
+</th>
+<th width="94">
+<Text id="277"><i>Subject</i></Text>
+</th>
+<th width="305">
+<Text id="278">The topic of the content of the resource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="279">*Description</Text>
+</th>
+<th width="94">
+<Text id="280"><i>Description</i></Text>
+</th>
+<th width="305">
+<Text id="281">An account of the content of the resource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="282">*Publisher</Text>
+</th>
+<th width="94">
+<Text id="283"><i>Publisher</i></Text>
+</th>
+<th width="305">
+<Text id="284">An entity responsible for making the resource available</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="285">Contributor</Text>
+</th>
+<th width="94">
+<Text id="286"><i>Contributor</i></Text>
+</th>
+<th width="305">
+<Text id="287">An entity responsible for making contributions to the content of the resource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="288">*Date</Text>
+</th>
+<th width="94">
+<Text id="289"><i>Date</i></Text>
+</th>
+<th width="305">
+<Text id="290">The date that the resource was published or some other important date associated with the resource.</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="291">Resource type</Text>
+</th>
+<th width="94">
+<Text id="292"><i>Type</i></Text>
+</th>
+<th width="305">
+<Text id="293">The nature or genre of the content of the resource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="294">Format</Text>
+</th>
+<th width="94">
+<Text id="295"><i>Format</i></Text>
+</th>
+<th width="305">
+<Text id="296">The physical or digital manifestation of the resource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="297">*Resource identifier</Text>
+</th>
+<th width="94">
+<Text id="298"><i>Identifier</i></Text>
+</th>
+<th width="305">
+<Text id="299">An unambiguous reference to the resource within a given context: this is the object identifier or OID</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="300">*Source</Text>
+</th>
+<th width="94">
+<Text id="301"><i>Source</i></Text>
+</th>
+<th width="305">
+<Text id="302">A reference to a resource from which the present resource is derived</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="303">*Language</Text>
+</th>
+<th width="94">
+<Text id="304"><i>Language</i></Text>
+</th>
+<th width="305">
+<Text id="305">A language of the intellectual content of the resource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="306">Relation</Text>
+</th>
+<th width="94">
+<Text id="307"><i>Relation</i></Text>
+</th>
+<th width="305">
+<Text id="308">A reference to a related resource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="309">*Coverage</Text>
+</th>
+<th width="94">
+<Text id="310"><i>Coverage</i></Text>
+</th>
+<th width="305">
+<Text id="311">The extent or scope of the content of the resource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="312">Rights management</Text>
+</th>
+<th width="94">
+<Text id="313"><i>Rights</i></Text>
+</th>
+<th width="305">
+<Text id="314">Information about rights held in and over the resource</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+<Subsection id="inside_greenstone_archive_documents">
+<Title>
+<Text id="315">Inside Greenstone archive documents</Text>
+</Title>
+<Content>
+<Text id="316">Within a single document, the Greenstone archive format imposes a limited amount of structure. Documents are divided into paragraphs. They can be split hierarchically into sections and subsections; these may be nested to any depth. Each document has an associated Object Identifier or OIDâthese are extended to identify sections and subsections by appending section and subsection numbers, separated by periods, to the document's OID. For example, subsection 3 of section 2 of document HASHa7 is referred to as HASHa7.2.3.</Text>
+<Text id="317">When you read a book in a Greenstone collection, the section hierarchy is manifested in the table of contents of the book. For example, books in the Demo collection have a hierarchical table of contents showing chapters, sections, and subsections, as illustrated in Figure <CrossRef target="Figure" ref="hierarchical_structure_in_the_demo_collection"/>. Documents in the Computer Science Technical Reports collection do not have a hierarchical subsection structure, but each document is split into pages and you can browse around the pages of a retrieved document. Chapters, sections, subsections, and pages are all implemented simply as âsectionsâ within the document.</Text>
+<Figure id="hierarchical_structure_in_the_demo_collection">
+<Title>
+<Text id="318">Hierarchical structure in the Demo collection</Text>
+<SubTitle>
+<Text id="318a">(a)</Text>
+</SubTitle>
+</Title>
+<File width="373" height="251" url="images/Dev_Fig_8a.gif"/>
+</Figure>
+<Figure id="hierarchical_structure_in_the_demo_collection_1">
+<Title>
+<Text id="318b">Hierarchical structure in the Demo collection</Text>
+<SubTitle>
+<Text id="318c">(b)</Text>
+</SubTitle>
+</Title>
+<File width="373" height="251" url="images/Dev_Fig_8b.gif"/>
+</Figure>
+<Text id="319">The document structure is also used for searchable indexes. There are three possible levels of index: <i>document</i>, <i>section</i>, and <i>paragraph</i>, though most collections do not use all three levels. A <i>document</i> index contains the full documentâyou use it to find all documents that contain a particular set of words (the words may be scattered far and wide throughout the document). When a <i>section</i> index is created, each portion of text that is indexed stretches from a <i>&lt;Section&gt;</i> tag to the next-occurring <i>&lt;Section&gt;</i> tagâthus a chapter that immediately begins with a new section will produce an empty document in the index. Sections and subsections are treated alike: the hierarchical document structure is flattened for the purposes of creating searchable indexes. Paragraph-level indexes consider each paragraph as a separate document, and are useful for doing more focused searches.</Text>
+<Text id="320">The pulldown menu in Figure <CrossRef target="Figure" ref="hierarchical_structure_in_the_demo_collection_1"/> shows the searchable indexes for the Demo collection. âChaptersâ and âsection titlesâ are section-level indexes, while âentire booksâ is a document-level index. As well as indexes of text, indexes of any kind of metadata can also be created. For example, some collections offer searchable indexes of section titles, and Figure <CrossRef target="Figure" ref="hierarchical_structure_in_the_demo_collection_1"/> illustrates this.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="configuration_file">
+<Title>
+<Text id="321">configuration file</Text>
+</Title>
+<Content>
+<Text id="322">The collection configuration file governs the structure of a collection as seen by the user, allowing you to customise the âlook and feelâ of your collection and the way in which its documents are processed and presented. A simple collection configuration file is created when you run <i>mkcol.pl</i>, which records your E-mail address as the creator and maintainer. Remember from the earlier walkthrough that the <i>creator</i> argument is mandatoryâunless specified separately, the same information is recorded as the maintainer.</Text>
+<Table id="items_in_the_collection_configuration_file">
+<Title>
+<Text id="323">Items in the collection configuration file</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<CodeLine>creator</CodeLine>
+</th>
+<th width="397">
+<Text id="324">E-mail address of the collection's creator</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>maintainer</i></CodeLine>
+</th>
+<th width="397">
+<Text id="325">E-mail address of the collection's maintainer</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>public</i></CodeLine>
+</th>
+<th width="397">
+<Text id="326">Whether collection is to be made public or not</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>beta</i></CodeLine>
+</th>
+<th width="397">
+<Text id="327">Whether collection is beta version or not</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>indexes</i></CodeLine>
+</th>
+<th width="397">
+<Text id="328">List of indexes to build</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>defaultindex</i></CodeLine>
+</th>
+<th width="397">
+<Text id="329">The default index</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>subcollection</i></CodeLine>
+</th>
+<th width="397">
+<Text id="330">Define a subcollection based on metadata</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>indexsubcollections</i></CodeLine>
+</th>
+<th width="397">
+<Text id="331">Specify which subcollections to index</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>defaultsubcollection</i></CodeLine>
+</th>
+<th width="397">
+<Text id="332">The default indexsubcollection</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>languages</i></CodeLine>
+</th>
+<th width="397">
+<Text id="333">List of languages to build indexes in</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>defaultlanguage</i></CodeLine>
+</th>
+<th width="397">
+<Text id="334">Default index language</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>collectionmeta</i></CodeLine>
+</th>
+<th width="397">
+<Text id="335">Defines collection-level metadata</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>plugin</i></CodeLine>
+</th>
+<th width="397">
+<Text id="336">Specify a plugin to use at build time</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>format</i></CodeLine>
+</th>
+<th width="397">
+<Text id="337">A format string (explained below)</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>classify</i></CodeLine>
+</th>
+<th width="397">
+<Text id="338">Specify a classifier to use at build time</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="339">Each line of the collection configuration file is essentially an âattribute, valueâ pair. Each attribute gives a piece of information about the collection that affects how it is supposed to look or how documents are to be processed. Table <CrossRef target="Table" ref="items_in_the_collection_configuration_file"/> shows the items that can be included in a collection configuration file, and what each is used for. As well as these, all the command-line options for <i>import.pl</i> and <i>buildcol.pl</i> may be specified in a collection configuration fileâe.g. a line reading <i>no_text true</i> will set <i>buildcol.pl</i>'s <i>no_text</i> option.</Text>
+<Text id="340">The collection configuration file created by the <i>mkcol.pl</i> script, shown in Table <CrossRef target="Table" ref="collection_configuration_file_created_by_mkcd"/>, is a very simple one and contains a bare minimum of information. Lines 1 and 2 stem from the <i>creator</i> value supplied to the <i>mkcol.pl</i> program, and contain the E-mail addresses of the person who created the collection and the person responsible for maintaining it (not necessarily the same person).</Text>
+<Table id="collection_configuration_file_created_by_mkcd">
+<Title>
+<Text id="341">Collection configuration file created by <i>mkcd.pl</i></Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="342"><b>Attribute</b></Text>
+</th>
+<th width="265">
+<Text id="343"><b>Value</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>1</CodeLine>
+</th>
+<th width="132">
+<CodeLine>creator</CodeLine>
+</th>
+<th width="265">
+<Text id="344">username@email.com</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>2</CodeLine>
+</th>
+<th width="132">
+<CodeLine>maintainer</CodeLine>
+</th>
+<th width="265">
+<Text id="345">username@email.com</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>3</CodeLine>
+</th>
+<th width="132">
+<CodeLine>public</CodeLine>
+</th>
+<th width="265">
+<Text id="346">True</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>4</CodeLine>
+</th>
+<th width="132">
+<CodeLine>beta</CodeLine>
+</th>
+<th width="265">
+<Text id="347">True</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>5</CodeLine>
+</th>
+<th width="132">
+<CodeLine>indexes</CodeLine>
+</th>
+<th width="265">
+<Text id="348">document:text</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>6</CodeLine>
+</th>
+<th width="132">
+<CodeLine>defaultindex</CodeLine>
+</th>
+<th width="265">
+<Text id="349">document:text</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>7</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="350">ZIPPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>8</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="351">GAPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>9</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="352">TextPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>10</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="353">HTMLPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>11</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="354">EMAILPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>12</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="355">ArcPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>13</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="356">RecPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>14</CodeLine>
+</th>
+<th width="132">
+<CodeLine>classify</CodeLine>
+</th>
+<th width="265">
+<Text id="357">AZList metadata Title</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>15</CodeLine>
+</th>
+<th width="132">
+<CodeLine>collectionmeta</CodeLine>
+</th>
+<th width="265">
+<Text id="358">collectionname       "sample collection"</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>16</CodeLine>
+</th>
+<th width="132">
+<CodeLine>collectionmeta</CodeLine>
+</th>
+<th width="265">
+<Text id="359">iconcollection       ""</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>17</CodeLine>
+</th>
+<th width="132">
+<CodeLine>collectionmeta</CodeLine>
+</th>
+<th width="265">
+<Text id="360">collectionextra     ""</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>18</CodeLine>
+</th>
+<th width="132">
+<CodeLine>collectionmeta</CodeLine>
+</th>
+<th width="265">
+<Text id="361">.document:text     "documents"</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="362">Line 3 indicates whether the collection will be available to the public when it is built, and is either <i>true</i> (the default, meaning that the collection is publicly available), or <i>false</i> (meaning that it is not). This is useful when building collections to test software, or building collections of material for personal use. Line 4 indicates whether the collection is beta or not (this also defaults to <i>true</i>, meaning that the collection is a beta release).</Text>
+<Text id="363">Line 5 determines what collection indexes are created at build time: in this example only the document text is to be indexed. Indexes can be constructed at the <i>document</i>, <i>section</i>, and <i>paragraph</i> levels. They can contain the material in <i>text</i>, or in any metadataâmost commonly <i>Title</i>. The form used to specify an index is <i>level:data</i>. For example, to include an index of section titles as well, you should change line 5 to <i>indexes document:text section:Title</i>. More than one type of data can be included in the same index by separating the data types with commas. For example, to create a section-level index of titles, text and dates, the line should read <i>indexes section:text,Title,Date.</i> The default index defined in line 6 is the default to be used on the collection's search page.</Text>
+<Text id="364">Lines 7â13 specify which plugins to use when converting documents to the Greenstone archive format and when building collections from archive files. Section <CrossRef target="Section" ref="plugins"/> gives information about what plugins are available. The order in which plugins are listed is the order in which they are tried on each document, and once a plugin that is able to process a document is found, no more are tried.</Text>
+<Text id="365">Line 14 specifies that an alphabetic list of titles is to be created for browsing purposes. Browsing structures are constructed by âclassifiersâ. Section <CrossRef target="Section" ref="classifiers"/> gives information about classifiers and what they can do.</Text>
+<Text id="366">Lines 15â18 are used to specify collection-level metadata. Specified through <i>collectionname</i>, the long form of the name is used as the collection's âtitleâ for the web browser. The <i>collectionicon</i> entry gives the URL of the collection's icon. If an index is specified (as in line 18), the string following is displayed as the name of that index on the collection's search page. A particularly important piece of collection-level metadata is <i>collectionextra</i>, which gives a stretch of text, surrounded by double quotes, describing the collection. This will be shown as the âAbout this collectionâ text. You can put in different versions of <i>collectionextra</i> for different interface languages by adding a language specification in square brackets. For example,</Text>
+<Indented>
+<Text id="367">collectionmeta collectionextra "collection description"</Text>
+</Indented>
+<Indented>
+<Text id="368">collectionmeta collectionextra [l=fr] "description in French"</Text>
+</Indented>
+<Indented>
+<Text id="369">collectionmeta collectionextra [l=mi] "description in Maori"</Text>
+</Indented>
+<Text id="370">If the interface language is set to âfrâ or âmiâ, the appropriate version of the description will be displayed. For other languages the default version will appear.</Text>
+<Text id="371">This simple collection configuration file does not include any examples of format strings, nor of the subcollection and language facilities provided by the configuration file. Format strings are covered more thoroughly in Section <CrossRef target="Section" ref="formatting_greenstone_output"/>, but we will look at subcollections and languages here.</Text>
+<Subsection id="subcollections">
+<Title>
+<Text id="372">Subcollections</Text>
+</Title>
+<Content>
+<Text id="373">Greenstone allows you to define subcollections and build separate indexes for each one. For example, in one collection there is a large subset of documents called <i>Food and Nutrition Bulletin</i>. We use this collection as an example.</Text>
+<Text id="374">This collection has three indexes, all at the section level: one for the whole collection, one for the <i>Food and Nutrition Bulletin</i>, and the third for the remaining documents. The relevant lines from the collection configuration file can be seen below.</Text>
+<CodeLine>indexes                           section:text</CodeLine>
+<CodeLine>subcollection               fn "Title/^Food and Nutrition Bulletin/i "</CodeLine>
+<CodeLine>subcollection               other "!Title/^Food and Nutrition Bulletin/i "</CodeLine>
+<CodeLine>indexsubcollections fn   other   fn,other</CodeLine>
+<Text id="375">The second and third lines define subcollections called <i>fn</i>, which contains the <i>Food and Nutrition Bulletin</i> documents, and <i>other</i>, which contains the remaining documents. The third field of these definitions is a Perl regular expression that identifies these subsets using the <i>Title</i> metadata: we seek titles that begin with <i>Food and Nutrition Bulletin</i> in the first case and ones that do not in the second case (note the â!â). The final <i>i</i> makes the pattern-matching case-insensitive. The metadata field, in this case <i>Title</i>, can be any valid field, or <i>Filename</i> to match against the document's original filename. The fourth line, <i>indexsubcollections</i>, specifies three indexes: one for the <i>fn</i> subcollection, one for the <i>other</i> subcollection, and the third for both subcollections (i.e. all the documents). Note that if two entries had been specified on the <i>indexes</i> line, the total number of indexes generated would have been six rather than three.</Text>
+<Text id="376">If a collection contains documents in different languages, separate indexes can be built for each language. Language is a metadata statement; values are specified using the ISO 639 standard two-letter codes for representing the names of languagesâfor example, <i>en</i> is English, <i>zh</i> is Chinese, and <i>mi</i> is Maori. Since metadata values can be specified at the section level, parts of a document can be in different languages.</Text>
+<Text id="377">For example, if the configuration file contained</Text>
+<CodeLine>indexes section:text section:Title document:text paragraph:text</CodeLine>
+<CodeLine>languages en zh mi</CodeLine>
+<Text id="378">section text, section title, document text, and paragraph text indexes would be created for English, Chinese, and Maoriâtwelve indexes altogether. Adding a couple of subcollections multiplies the number of indexes again. Care is necessary to guard against index bloat.</Text>
+<Text id="379">(This index specification could be defined using the <i>subcollection</i> facility rather than the <i>languages</i> facility. However, since the syntax precludes creating subcollections of subcollections, it would then be impossible to index each language in the subcollections separately.)</Text>
+</Content>
+</Subsection>
+<Subsection id="cross-collection_searching">
+<Title>
+<Text id="380">Cross-collection searching</Text>
+</Title>
+<Content>
+<Text id="381">Greenstone has a facility for âcross-collection searching,â which allows several collections to be searched at once, with the results combined behind the scenes as though you were searching a single unified collection. Any subset of the collections can be searched: the Preferences page allows you to choose which collections are included in the searches.</Text>
+<Text id="382">Cross-collection searching is enabled by a line</Text>
+<CodeLine>supercollection col _1 col _2 âŠ.</CodeLine>
+<Text id="383">where the collections involved are called <i>col_1</i>, <i>col_2</i>, âŠ The same line should appear in the configuration file of every collection that is involved.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="getting_the_most_out_of_your_documents">
+<Title>
+<Text id="384">Getting the most out of your documents</Text>
+</Title>
+<Content>
+<Text id="385">Collections can be individualised to make the information they contain accessible in different ways. This chapter describes how Greenstone extracts information from documents and presents it to the user: the document processing (Section <CrossRef target="Section" ref="plugins"/>) and classification structures (Section <CrossRef target="Section" ref="classifiers"/>), and user interface tools (Sections <CrossRef target="Section" ref="formatting_greenstone_output"/> and <CrossRef target="Section" ref="controlling_the_greenstone_user_interface"/>).</Text>
+<Section id="plugins">
+<Title>
+<Text id="386">Plugins</Text>
+</Title>
+<Content>
+<Text id="387">Plugins parse the imported documents and extract metadata from them. For example, the html plugin converts html pages to the Greenstone archive format and extracts metadata which is explicit in the document formatâsuch as titles, enclosed by <i>&lt;title&gt;&lt;/title&gt;</i> tags.</Text>
+<Text id="388">Plugins are written in the Perl language. They all derive from a basic plugin called <i>BasPlug</i>, which performs universally-required operations like creating a new Greenstone archive document to work with, assigning an object identifier (OID), and handling the sections in a document. Plugins are kept in the <i>perllib/plugins</i> directory.</Text>
+<Text id="389">To find more about any plugin, just type <i>pluginfo.pl plugin-name</i> at the command prompt. (You need to invoke the appropriate <i>setup</i> script first, if you haven't already, and on Windows you need to type <i>perl âS pluginfo.pl plugin-name</i> if your environment is not set up to associate files ending in <i>.pl</i> as Perl executables). This displays information about the plugin on the screenâwhat plugin-specific options it takes, and what general options are allowed.</Text>
+<Text id="390">You can easily write new plugins that process document formats not handled by existing plugins, format documents in some special way, or extract a new kind of metadata.</Text>
+<Subsection id="general_options">
+<Title>
+<Text id="391">General Options</Text>
+</Title>
+<Content>
+<Text id="392">Table <CrossRef target="Table" ref="options_applicable_to_all_plugins"/> shows options that are accepted by any plugin derived from BasPlug.</Text>
+<Table id="options_applicable_to_all_plugins">
+<Title>
+<Text id="393">Options applicable to all plugins</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<CodeLine><i>input_encoding</i></CodeLine>
+</th>
+<th width="397">
+<Text id="394">Character encoding of the source documents. The default is to automatically work out the character encoding of each individual document. It is sometimes useful to set this value though, for example, if you know that all your documents are plain ASCII, setting the input encoding to <i>ascii</i> greatly increases the speed at which your collection is imported and built. There are many possible values. Use <i>pluginfo.pl BasPlug</i> to get a complete list.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>default_encoding</i></CodeLine>
+</th>
+<th width="397">
+<Text id="395">The encoding that is used if <i>input_encoding</i> is <i>auto</i> and automatic encoding detection fails.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>process_exp</i></CodeLine>
+</th>
+<th width="397">
+<Text id="396">A Perl regular expression to match against filenames (for example, to locate a certain kind of file extension). This dictates which files a plugin processes. Each plugin has a default (<i>HTMLPlug</i>'s default is <i>(?i).html?</i>âthat is, anything with the extension <i>.htm</i> or <i>.html</i>).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>block_exp</i></CodeLine>
+</th>
+<th width="397">
+<Text id="397">A regular expression to match against filenames that are not to be passed on to subsequent plugins. This can prevent annoying error messages about files you aren't interested in. Some plugins have default blocking expressionsâfor example, <i>HTMLPlug</i> blocks files with <i>.gif</i>, <i>.jpg</i>, <i>.jpeg</i>, <i>.png</i>, <i>.rtf</i> and <i>.css</i> extensions.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>cover_image</i></CodeLine>
+</th>
+<th width="397">
+<Text id="398">Look for a <i>.jpg</i> file (with the same name as the file being processed) and associate it with the document as a cover image.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>extract_acronyms</i></CodeLine>
+</th>
+<th width="397">
+<Text id="399">Extract acronyms from documents and add them as metadata to the corresponding Greenstone archive documents.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>markup_acronyms</i></CodeLine>
+</th>
+<th width="397">
+<Text id="400">Add acronym information into document text.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>extract_language</i></CodeLine>
+</th>
+<th width="397">
+<Text id="401">Identify each document's language and associate it as metadata. Note that this is done automatically if <i>input_encoding</i> is <i>auto</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>default_language</i></CodeLine>
+</th>
+<th width="397">
+<Text id="402">If automatic language extraction fails, language metadata is set to this value.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>first</i></CodeLine>
+</th>
+<th width="397">
+<Text id="403">Extract a comma-separated list of the first stretch of text and add it as <i>FirstNNN</i> metadata (often used as a substitute for <i>Title</i>).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>extract_email</i></CodeLine>
+</th>
+<th width="397">
+<Text id="404">Extract E-mail addresses and add them as document metadata.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>extract_date</i></CodeLine>
+</th>
+<th width="397">
+<Text id="405">Extract dates relating to the content of historical documents and add them as <i>Coverage</i> metadata.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+<Subsection id="document_processing_plugins">
+<Title>
+<Text id="406">Document processing plugins</Text>
+</Title>
+<Content>
+<Table id="greenstone_plugins">
+<Title>
+<Text id="407">Greenstone plugins</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="60"/>
+<th width="72"/>
+<th width="236">
+<Text id="408"><b>Purpose</b></Text>
+</th>
+<th width="85">
+<Text id="409"><b>File types</b></Text>
+</th>
+<th width="76">
+<Text id="410"><b>Ignores files</b></Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="411"><b>General</b></Text>
+</th>
+<th width="72">
+<Text id="412"><i>ArcPlug</i></Text>
+</th>
+<th width="236">
+<Text id="413">Processes files named in the file <i>archives.inf</i>, which is used to communicate between the import and build processes. Must be included (unless <i>import.pl</i> will not be used).</Text>
+</th>
+<th width="85">
+<Text id="414"><i>â</i></Text>
+</th>
+<th width="76">
+<Text id="415"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="416"><i>RecPlug</i></Text>
+</th>
+<th width="236">
+<Text id="417">Recurses through a directory structure by checking to see whether a filename is a directory and if so, inserting all files in the directory into the plugin pipeline. Assigns metadata if <i>âuse_metadata_files</i> option is set and <i>metadata.xml</i> files are present.</Text>
+</th>
+<th width="85">
+<Text id="418"><i>â</i></Text>
+</th>
+<th width="76">
+<Text id="419"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="420"><i>GAPlug</i></Text>
+</th>
+<th width="236">
+<Text id="421">Processes Greenstone archive files generated by <i>import.pl.</i> Must be included (unless <i>import.pl</i> will not be used).</Text>
+</th>
+<th width="85">
+<Text id="422"><i>.xml</i></Text>
+</th>
+<th width="76">
+<Text id="423"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="424">TEXTPlug</Text>
+</th>
+<th width="236">
+<Text id="425">Processes plain text by placing it between <i>&lt;pre&gt; &lt;/pre&gt;</i> tags (treating it as preformatted).</Text>
+</th>
+<th width="85">
+<Text id="426"><i>.txt, .text</i></Text>
+</th>
+<th width="76">
+<Text id="427"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="428"><i>HTMLPlug</i></Text>
+</th>
+<th width="236">
+<Text id="429">Processes html, replacing hyperlinks appropriately. If the linked document is not in the collection, an intermediate page is inserted warning the user they are leaving the collection. Extracts readily available metadata such as <i>Title</i>.</Text>
+</th>
+<th width="85">
+<Text id="430"><i>.htm, .html, .cgi, .php, .asp, .shm, .shtml</i></Text>
+</th>
+<th width="76">
+<Text id="431"><i>.gif, .jpeg, .jpg, .png, .css, .rtf</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="432"><i>WordPlug</i></Text>
+</th>
+<th width="236">
+<Text id="433">Processes Microsoft Word documents, extracting author and title where available, and keeping diagrams and pictures in their proper places. The conversion utilities used by this plugin sometimes produce html that is poorly formatted, and we recommend that you provide the original documents for viewing when building collections of WORD files. However, the text that is extracted from the documents is adequate for searching and indexing purposes.</Text>
+</th>
+<th width="85">
+<Text id="434"><i>.doc</i></Text>
+</th>
+<th width="76">
+<Text id="435"><i>.gif, .jpeg, .jpg, .png, .css, .rtf</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="436"><i>PDFPlug</i></Text>
+</th>
+<th width="236">
+<Text id="437">Processes PDF documents, extracting the first line of text as a title. The <i>pdftohtml</i> program fails on some PDF files. What happens is that the conversion process takes an exceptionally long time, and often an error message relating to the conversion process appears on the screen. If this occurs, the only solution that we can offer is to remove the offending document from the collection and re-import.</Text>
+</th>
+<th width="85">
+<Text id="438"><i>.pdf</i></Text>
+</th>
+<th width="76">
+<Text id="439"><i>.gif, .jpeg, .jpg, .png, .css, .rtf</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="440"><i>PSPlug</i></Text>
+</th>
+<th width="236">
+<Text id="441">Processes PostScript documents, optionally extracting date, title and page number metadata.</Text>
+</th>
+<th width="85">
+<Text id="442"><i>.ps</i></Text>
+</th>
+<th width="76">
+<Text id="443"><i>.eps</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="444"><i>EMAILPlug</i></Text>
+</th>
+<th width="236">
+<Text id="445">Processes E-mail messages, recognising author, subject, date, etc. This plugin does not yet handle MIME-encoded E-mails propoerlyâalthough legible, they often look rather strange.</Text>
+</th>
+<th width="85">
+<Text id="446">Must end in digits or digits followed by <i>.Email</i></Text>
+</th>
+<th width="76">
+<Text id="447"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="448"><i>BibTexPlug</i></Text>
+</th>
+<th width="236">
+<Text id="449">Processes bibliography files in <i>BibTex</i> format</Text>
+</th>
+<th width="85">
+<Text id="450"><i>.bib</i></Text>
+</th>
+<th width="76">
+<Text id="451"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="452"><i>ReferPlug</i></Text>
+</th>
+<th width="236">
+<Text id="453">Processes bibliography files in <i>refer</i> format</Text>
+</th>
+<th width="85">
+<Text id="454"><i>.bib</i></Text>
+</th>
+<th width="76">
+<Text id="455"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="456"><i>SRCPlug</i></Text>
+</th>
+<th width="236">
+<Text id="457">Processes source code files</Text>
+</th>
+<th width="85">
+<Text id="458"><i>Makefile, Readme, .c, .cc, .cpp, .h, .hpp, .pl, .pm, .sh</i></Text>
+</th>
+<th width="76">
+<Text id="459"><i>.o, .obj, .a, .so, .dll</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="460"><i>ImagePlug</i></Text>
+</th>
+<th width="236">
+<Text id="461">Processes image files for creating a library of images. Only works on UNIX.</Text>
+</th>
+<th width="85">
+<Text id="462"><i>.jpeg, .jpg, .gif, .png, .bmp, .xbm, .tif, .tiff</i></Text>
+</th>
+<th width="76">
+<Text id="463"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="464"><i>SplitPlug</i></Text>
+</th>
+<th width="236">
+<Text id="465">Like BasPlug and ConvertToPlug, this plugin should not be called directly, but may be inherited byplugins that need to process files containing several documents</Text>
+</th>
+<th width="85">
+<Text id="466"><i>â</i></Text>
+</th>
+<th width="76">
+<Text id="467"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="468"><i>FOXPlug</i></Text>
+</th>
+<th width="236">
+<Text id="469">Processes FoxBASE dbt files</Text>
+</th>
+<th width="85">
+<Text id="470"><i>.dbt, .dbf</i></Text>
+</th>
+<th width="76">
+<Text id="471"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="472"><i>ZIPPlug</i></Text>
+</th>
+<th width="236">
+<Text id="473">Uncompresses <i>gzip</i>, <i>bzip</i>, <i>zip</i>, and <i>tar</i> files, provided the appropriate Gnu tools are available.</Text>
+</th>
+<th width="85">
+<Text id="474"><i>.gzip, .bzip, .zip, .tar, .gz, .bz, .tgz, .taz</i></Text>
+</th>
+<th width="76">
+<Text id="475"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="476"><b>Collection <br/>Specific</b></Text>
+</th>
+<th width="72">
+<Text id="477"><i>PrePlug</i></Text>
+</th>
+<th width="236">
+<Text id="478">Processes html output using PRESCRIPT, splitting documents into pages for the Computer Science Technical Reports collection.</Text>
+</th>
+<th width="85">
+<Text id="479"><i>.html, .html.gz</i></Text>
+</th>
+<th width="76">
+<Text id="480"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="481"><i>GBPlug</i></Text>
+</th>
+<th width="236">
+<Text id="482">Processes Project Gutenberg etextâwhich includes manually-entered title information.</Text>
+</th>
+<th width="85">
+<Text id="483"><i>.txt.gz, .html, .htm</i></Text>
+</th>
+<th width="76">
+<Text id="484"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="485"><i>TCCPlug</i></Text>
+</th>
+<th width="236">
+<Text id="486">Processes E-mail documents from Computists' Weekly</Text>
+</th>
+<th width="85">
+<Text id="487">Must begin with <i>tcc or cw</i></Text>
+</th>
+<th width="76">
+<Text id="488"><i>â</i></Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="489">Document processing plugins are used by the collection-building software to parse each source document in a way that depends on its format. A collection's configuration file lists all plugins that are used when building it. During the import operation, each file or directory is passed to each plugin in turn until one is found that can process itâthus earlier plugins take priority over later ones. If no plugin can process the file, a warning is printed (to standard error) and processing passes to the next file. (This is where the <i>block_exp</i> option can be usefulâto prevent these error messages for files that might be present but don't need processing.) During building, the same procedure is used, but the <i>archives</i> directory is processed instead of the <i>import</i> directory.</Text>
+<Text id="490">The standard Greenstone plugins are listed in Table <CrossRef target="Table" ref="greenstone_plugins"/>. Recursion is necessary to traverse directory hierarchies. Although the import and build programs do not perform explicit recursion, some plugins cause indirect recursion by passing files or directory names into the plugin pipeline. For example, the standard way of recursing through a directory hierarchy is to specify <i>RecPlug</i>, which does exactly this. If present, it should be the last element in the pipeline. Only the first two plugins in Table <CrossRef target="Table" ref="greenstone_plugins"/> cause indirect recursion.</Text>
+<Text id="491">Some plugins are written for specific collections that have a document format not found elsewhere, like the E-text used in the Gutenberg collection. These collection-specific plugins are found in the collection's <i>perllib/plugins</i> directory. Collection-specific plugins can be used to override general plugins with the same name.</Text>
+<Text id="492">Some document-processing plugins use external programs that parse specific proprietary formatsâfor example, Microsoft Wordâinto either plain text or html. A general plugin called <i>ConvertToPlug</i> invokes the appropriate conversion program and passes the result to either <i>TEXTPlug</i> or <i>HTMLPlug</i>. We describe this in more detail shortly.</Text>
+<Text id="493">Some plugins have individual options, which control what they do in finer detail than the general options allow. Table <CrossRef target="Table" ref="plugin-specific_options"/> describes them.</Text>
+<Table id="plugin-specific_options">
+<Title>
+<Text id="494">Plugin-specific options</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="495"><b>Option</b></Text>
+</th>
+<th width="265">
+<Text id="496"><b>Purpose</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="497"><i>HTMLPlug</i></Text>
+</th>
+<th width="132">
+<Text id="498"><i>nolinks</i></Text>
+</th>
+<th width="265">
+<Text id="499">Do not trap links within the collection. This speeds up the import/build process, but any links in the collection will be broken.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="500"><i>description_tags</i></Text>
+</th>
+<th width="265">
+<Text id="501">Interpret tagged document files as described in the subsection below.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="502"><i>keep_head</i></Text>
+</th>
+<th width="265">
+<Text id="503">Do not strip out html headers.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="504"><i>no_metadata</i></Text>
+</th>
+<th width="265">
+<Text id="505">Do not seek any metadata (this may speed up the import/build process).</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="506"><i>metadata_fields</i></Text>
+</th>
+<th width="265">
+<Text id="507">Takes a comma-separated list of metadata types (defaults to <i>Title</i>) to extract. To rename the metadata in the Greenstone archive file, use <i>tag&lt;newname&gt;</i> where <i>tag</i> is the html tag sought and <i>newname</i> its new name.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="508"><i>hunt_creator_metadata</i></Text>
+</th>
+<th width="265">
+<Text id="509">Find as much metadata as possible about authorship and put it in the Greenstone archive document as <i>Creator</i> metadata. You also need to include <i>Creator</i> using the <i>metadata_fields</i> option.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="510"><i>file_is_url</i></Text>
+</th>
+<th width="265">
+<Text id="511">Use this option if a web mirroring program has been used to create the structure of the documents to be imported.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="512"><i>assoc_files</i></Text>
+</th>
+<th width="265">
+<Text id="513">Gives a Perl regular expression that describes file types to be treated as associated files. The default types are <i>.jpg</i>, <i>.jpeg</i>, <i>.gif</i>, <i>.png</i>, <i>.css</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="514"><i>rename_assoc_files</i></Text>
+</th>
+<th width="265">
+<Text id="515">Rename files associated with documents. During this process the directory structure of any associated files will become much shallower (useful if a collection must be stored in limited space).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="516"><i>HTMLPlug</i> and <br/><i>TEXTPlug</i></Text>
+</th>
+<th width="132">
+<Text id="517"><i>title_sub</i></Text>
+</th>
+<th width="265">
+<Text id="518">Perl substitution expression to modify titles.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="519"><i>PSPlug</i></Text>
+</th>
+<th width="132">
+<Text id="520"><i>extract_date</i></Text>
+</th>
+<th width="265">
+<Text id="521">Extract the creation date from the PostScript header and store it as metadata.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="522"><i>extract_title</i></Text>
+</th>
+<th width="265">
+<Text id="523">Extract the document title from the PostScript header and store it as title metadata.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="524"><i>extract_pages</i></Text>
+</th>
+<th width="265">
+<Text id="525">Extract the page numbers from the PostScript document and add them to the appropriate sections as metadata with the tag <i>Pages.</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="526"><i>RecPlug</i></Text>
+</th>
+<th width="132">
+<Text id="527"><i>use_metadata_files</i></Text>
+</th>
+<th width="265">
+<Text id="528">Assign metadata from a file as described in the subsection below.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="529"><i>ImagePlug</i></Text>
+</th>
+<th width="132">
+<Text id="530">Various options</Text>
+</th>
+<th width="265">
+<Text id="531">See <i>ImagePlug.pm.</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="532"><i>SRCPlug</i></Text>
+</th>
+<th width="132">
+<Text id="533"><i>remove_prefix</i></Text>
+</th>
+<th width="265">
+<Text id="534">Gives a Perl regular expression of a leading pattern which is to be removed from the filename. Default behaviour is to remove the whole path.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+<Subsection id="plugins_to_import_proprietary_formats">
+<Title>
+<Text id="535">Plugins to import proprietary formats</Text>
+</Title>
+<Content>
+<Text id="536">Proprietary formats pose difficult problems for any digital library system. Although documentation may be available about how they work, they are subject to change without notice, and it is difficult to keep up with changes. Greenstone has adopted the policy of using GPL (Gnu Public License) conversion utilities written by people dedicated to the task. Utilities to convert Word and PDF formats are included in the <i>packages</i> directory. These all convert documents to either text or html. Then <i>HTMLPlug</i> and <i>TEXTPlug</i> are used to further convert them to the Greenstone archive format. <i>ConvertToPlug</i> is used to include the conversion utilities. Like <i>BasPlug</i> it is never called directly. Rather, plugins written for individual formats are derived from it as illustrated in Figure <CrossRef target="Figure" ref="plugin_inheritance_hierarchy"/>. <i>ConvertToPlug</i> uses Perl's dynamic inheritance scheme to inherit from either <i>TEXTPlug</i> or <i>HTMLPlug</i>, depending on the format to which a source document has been converted.</Text>
+<Figure id="plugin_inheritance_hierarchy">
+<Title>
+<Text id="537">Plugin inheritance hierarchy</Text>
+</Title>
+<File width="229" height="193" url="images/Dev_Fig_9.gif"/>
+</Figure>
+<Text id="538">When <i>ConvertToPlug</i> receives a document, it calls <i>gsConvert.pl</i> (found in <i>GSDLHOME/bin/script</i>) to invoke the appropriate conversion utility. Once the document has been converted, it is returned to <i>ConvertToPlug</i>, which invokes the text or html plugin as appropriate. Any plugin derived from <i>ConvertToPlug</i> has an option <i>convert_to</i>, whose argument is either <i>text</i> or <i>html</i>, to specify which intermediate format is preferred. Text is faster, but html generally looks better, and includes pictures.</Text>
+<Text id="539">Sometimes there are several conversion utilities for a particular format, and <i>gsConvert</i> may try different ones on a given document. For example, the preferred Word conversion utility <i>wvWare</i> does not cope with anything less than Word 6, and a program called <i>AnyToHTML</i>, which essentially just extracts whatever text strings can be found, is called to convert Word 5 documents.</Text>
+<Text id="540">The steps involved in adding a new external document conversion utility are:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="541">Install the new conversion utility so that it is accessible by Greenstone (put it in the <i>packages</i> directory).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="542">Alter <i>gsConvert.pl</i> to use the new conversion utility. This involves adding a new clause to the <i>if</i> statement in the <i>main</i> function, and adding a function that calls the conversion utility.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="543">Write a top-level plugin that inherits from <i>ConvertToPlug</i> to catch the format and pass it on.</Text>
+</NumberedItem>
+</NumberedList>
+</Content>
+</Subsection>
+<Subsection id="assigning_metadata_from_a_file">
+<Title>
+<Text id="544">Assigning metadata from a file</Text>
+</Title>
+<Content>
+<Text id="545">The standard plugin <i>RecPlug</i> also incorporates a way of assigning metadata to documents from manually (or automatically) created XML files. We describe this in some detail, so that you can create metadata files in the appropriate format. If the <i>use_metadata_files</i> option is specified, <i>RecPlug</i> uses an auxiliary metadata file called <i>metadata.xml</i>. Figure <CrossRef target="Figure" ref="xml_format"/> shows the XML Document Type Definition (DTD) for the metadata file format, while Figure <CrossRef target="Figure" ref="xml_format_1"/> shows an example <i>metadata.xml</i> file.</Text>
+<Figure id="xml_format">
+<Title>
+<Text id="546">XML format: (a) Document Type Definition (DTD); (b) Example metadata file</Text>
+<SubTitle>
+<Text id="547">(a)</Text>
+</SubTitle>
+</Title>
+<CodeLine>&lt;!DOCTYPE GreenstoneDirectoryMetadata [</CodeLine>
+<CodeLine>   &lt;!ELEMENT DirectoryMetadata (FileSet*)&gt;</CodeLine>
+<CodeLine>   &lt;!ELEMENT FileSet (FileName+,Description)&gt;</CodeLine>
+<CodeLine>   &lt;!ELEMENT FileName (#PCDATA)&gt;</CodeLine>
+<CodeLine>   &lt;!ELEMENT Description (Metadata*)&gt;</CodeLine>
+<CodeLine>   &lt;!ELEMENT Metadata (#PCDATA)&gt;</CodeLine>
+<CodeLine>   &lt;ATTLIST Metadata name CDATA #REQUIRED&gt;</CodeLine>
+<CodeLine>   &lt;ATTLIST Metadata mode (accumulate|override) "override"&gt;</CodeLine>
+<CodeLine>]&gt;</CodeLine>
+</Figure>
+<Figure id="xml_format_1">
+<Title>
+<Text id="548"/>
+<SubTitle>
+<Text id="549">(b)</Text>
+</SubTitle>
+</Title>
+<CodeLine>&lt;?xml version="1.0" ?&gt;</CodeLine>
+<CodeLine>&lt;!DOCTYPE GreenstoneDirectoryMetadata SYSTEM</CodeLine>
+<CodeLine>"http://greenstone.org/dtd/GreenstoneDirectoryMetadata/<br/>1.0/GreenstoneDirectoryMetadata.dtd"&gt;</CodeLine>
+<CodeLine>&lt;DirectoryMetadata&gt;</CodeLine>
+<CodeLine>   &lt;FileSet&gt;</CodeLine>
+<CodeLine>       &lt;FileName&gt;nugget.*&lt;/FileName&gt;</CodeLine>
+<CodeLine>       &lt;Description&gt;</CodeLine>
+<CodeLine>       &lt;Metadata name="Title"&gt;Nugget Point Lighthouse&lt;/Metadata&gt;</CodeLine>
+<CodeLine>           &lt;Metadata name="Place" mode="accumulate"&gt;Nugget Point&lt;/Metadata&gt;</CodeLine>
+<CodeLine>       &lt;/Description&gt;</CodeLine>
+<CodeLine>   &lt;/FileSet&gt;</CodeLine>
+<CodeLine>   &lt;FileSet&gt;</CodeLine>
+<CodeLine>       &lt;FileName&gt;nugget-point-1.jpg&lt;/FileName&gt;</CodeLine>
+<CodeLine>       &lt;Description&gt;</CodeLine>
+<CodeLine>           &lt;Metadata name="Title"&gt;Nugget Point Lighthouse , The Catlins &lt;/Metadata&gt;</CodeLine>
+<CodeLine>           &lt;Metadata name="Subject"&gt;Lighthouse&lt;/Metadata&gt;</CodeLine>
+<CodeLine>       &lt;/Description&gt;</CodeLine>
+<CodeLine>   &lt;/FileSet&gt;</CodeLine>
+<CodeLine>&lt;/DirectoryMetadata&gt;</CodeLine>
+</Figure>
+<Text id="550">The example file contains two metadata structures. In each one, the <i>filename</i> element describes files to which the metadata applies, in the form of a regular expression. Thus <i>&lt;FileName&gt;nugget.*&lt;/FileName&gt;</i> indicates that the first metadata record applies to every file whose name starts with ânuggetâ.<FootnoteRef id="2"/>For these files, <i>Title</i> metadata is set to âNugget Point Lighthouse.â</Text>
+<Text id="551">Metadata elements are processed in the order in which they appear. The second structure above sets <i>Title</i> metadata for the file named <i>nugget-point-1.jpg</i> to âNugget Point Lighthouse, The Catlins,â overriding the previous specification. It also adds a <i>Subject</i> metadata field.</Text>
+<Text id="552">Sometimes metadata is multi-valued and new values should accumulate, rather than overriding previous ones. The <i>mode=accumulate</i> attribute does this. It is applied to <i>Place</i> metadata in the first specification above, which will therefore be multi-valued. To revert to a single metadata element, write <i>&lt;Metadata name=âPlaceâ mode=âoverrideâ&gt;New Zealand&lt;/Metadata&gt;</i>. In fact, you could omit this mode specification because every element overrides unless otherwise specified. To accumulate metadata for some field, <i>mode=accumulate</i> must be specified in every occurrence.</Text>
+<Text id="553">When its <i>use_metadata_files</i> option is set, <i>RecPlug</i> checks each input directory for an XML file called <i>metadata.xml</i> and applies its contents to all the directory's files and subdirectories.</Text>
+<Text id="554">The <i>metadata.xml</i> mechanism that is embodied in RecPlug is just one way of specifying metadata for documents. It is easy to write different plugins that accept metadata specifications in completely different formats.</Text>
+</Content>
+</Subsection>
+<Subsection id="tagging_document_files">
+<Title>
+<Text id="555">Tagging document files</Text>
+</Title>
+<Content>
+<Text id="556">Source documents often need to be structured into sections and subsections, and this information needs to be communicated to Greenstone so that it can preserve the hierarchical structure. Also, metadataâtypically the titleâmight be associated with each section and subsection.</Text>
+<Text id="557">The simplest way of doing this is often simply to edit the source files. The HTML plugin has a <i>description_tags</i> option that processes tags in the text like this:</Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>   &lt;Description&gt;</CodeLine>
+<CodeLine>       &lt;Metadata name="Title"&gt; Realizing human rights for poor people: Strategies for achieving the international development targets&lt;/Metadata&gt;</CodeLine>
+<CodeLine>   &lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="558"><i>(text of section goes here)</i></Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="559">The &lt;!-- âŠ --&gt; markers are used because they indicate comments in HTML; thus these section tags will not affect document formatting. In the <i>Description</i> part other kinds of metadata can be specified, but this is not done for the style of collection we are describing here. Also, the tags can be nested, so the line marked <i>text of section goes here</i> above can itself include further subsections, such as</Text>
+<Text id="560"><i>(text of first part of section goes here)</i></Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>   &lt;Description&gt;</CodeLine>
+<CodeLine>       &lt;Metadata name="Title"&gt; The international development targets&lt;/Metadata&gt;</CodeLine>
+<CodeLine>   &lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="561"><i>(text of subsection goes here)</i></Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="562"><i>(text of last part of section goes here)</i></Text>
+<Text id="563">This functionality is inherited by any plugins that use HTMLPlug. In particular, the Word plugin converts its input to HTML form, and so exactly the same way of specifying metadata can be used in Word (and RTF) files. (This involves a bit of work behind the scenes, because when Word documents are converted to HTML care is normally taken to neutralize HTML's special interpretation of stray â&lt;â and â&gt;â signs; we have arranged to override this in the case of the above specifications.) Note that exactly the same format as above is used, even in Word files, including the surrounding â&lt;!--â and â--&gt;â. Font and spacing is ignored.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="classifiers">
+<Title>
+<Text id="564">Classifiers</Text>
+</Title>
+<Content>
+<Text id="565">Classifiers are used to create a collection's browsing indexes. Examples are the <i>dlpeople</i> collection's <i>Titles A-Z</i> index, and the <i>Subject</i>, <i>How to</i>, <i>Organisation</i> and <i>Titles A-Z</i> indexes in the Humanity Development Libraryâof which the Demo collection is a subset. The navigation bar near the top of the screenshots in Figures 3 and 8a include the <i>search</i> function, which is always provided, followed by buttons for any classifiers that have been defined. The information used to support browsing is stored in the collection information database, and is placed there by classifiers that are called during the final phase of <i>buildcol.pl</i>.</Text>
+<Figure id="azlist_classifier">
+<Title>
+<Text id="566"><i>AZList</i> classifier</Text>
+</Title>
+<File width="390" height="182" url="images/Dev_Fig_11.png"/>
+</Figure>
+<Text id="567">Classifiers, like plugins, are specified in a collection's configuration file. For each one there is a line starting with the keyword <i>classify</i> and followed by the name of the classifier and any options it takes. The basic collection configuration file discussed in Section <CrossRef target="Section" ref="configuration_file"/> includes the line <i>classify AZListâmetadata Title</i>, which makes an alphabetic list of titles by taking all those with a <i>Title</i> metadata field, sorting them and splitting them into alphabetic ranges. An example is shown in Figure <CrossRef target="Figure" ref="azlist_classifier"/>.</Text>
+<Figure id="list_classifier">
+<Title>
+<Text id="568"><i>List</i> classifier</Text>
+</Title>
+<File width="394" height="143" url="images/Dev_Fig_12.png"/>
+</Figure>
+<Text id="569">A simpler classifier, called <i>List</i>, illustrated in Figure <CrossRef target="Figure" ref="list_classifier"/>, creates a sorted list of a given metadata element and displays it without any alphabetic subsections. An example is the <i>how to</i> metadata in the Demo collection, which is produced by a line <i>classify List âmetadata Howto</i> in the collection configuration file.<FootnoteRef id="3"/> Another general-purpose list classifier is <i>DateList</i>, illustrated in Figure <CrossRef target="Figure" ref="datelist_classifier"/>, which generates a selection list of date ranges. (The <i>DateList</i> classifier is also used in the Greenstone Archives collection.)</Text>
+<Figure id="datelist_classifier">
+<Title>
+<Text id="570"><i>DateList</i> classifier</Text>
+</Title>
+<File width="390" height="159" url="images/Dev_Fig_13.png"/>
+</Figure>
+<Text id="571">Other classifiers generate browsing structures that are explicitly hierarchical. Hierarchical classifications are useful for subject classifications and subclassifications, and organisational hierarchies. The Demo collection's configuration file contains the line<br/><i>classify Hierarchy âhfile sub.txt âmetadata Subject âsort Title</i>, and Figure <CrossRef target="Figure" ref="hierarchy_classifier"/> shows the subject hierarchy browser that it produces. The bookshelf with a bold title is the one currently being perused; above it you can see the subject classification to which it belongs. In this example the hierarchy for classification is stored in a simple text format in <i>sub.txt</i>.</Text>
+<Figure id="hierarchy_classifier">
+<Title>
+<Text id="572"><i>Hierarchy</i> classifier</Text>
+</Title>
+<File width="394" height="198" url="images/Dev_Fig_14.png"/>
+</Figure>
+<Text id="573">All classifiers generate a hierarchical structure that is used to display a browsing index. The lowest levels (i.e. leaves) of the hierarchy are usually documents, but in some classifiers they are sections. The internal nodes of the hierarchy are either <i>Vlist</i>, <i>Hlist</i>, or <i>Datelist</i>. A <i>Vlist</i> is a list of items displayed vertically down the page, like the âhow toâ index in the Demo collection (see Figure <CrossRef target="Figure" ref="list_classifier"/>). An <i>Hlist</i> is displayed horizontally. For example, the <i>AZList</i> display in Figure <CrossRef target="Figure" ref="azlist_classifier"/> is a two-level hierarchy of internal nodes consisting of an <i>Hlist</i>(giving the A-Z selector) whose children are <i>Vlists</i> âand their children, in turn, are documents. A <i>Datelist</i> (Figure <CrossRef target="Figure" ref="datelist_classifier"/>) is a special kind of <i>Vlist</i> that allows selection by year and month.</Text>
+<Text id="574">The lines used to specify classifiers in collection configuration files contain a <i>metadata</i> argument that identifies the metadata by which the documents are classified and sorted. Any document in the collection that does not have this metadata defined will be omitted from the classifier (but it is still indexed, and consequently searchable). If no <i>metadata</i> argument is specified, all documents are included in the classifier, in the order in which they are encountered during the building process. This is useful if you want a list of all documents in your collection.</Text>
+<Table id="greenstone_classifiers">
+<Title>
+<Text id="575">Greenstone classifiers</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="576"><b>Argument</b></Text>
+</th>
+<th width="305">
+<Text id="577"><b>Purpose</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="578"><i>Hierarchy</i></Text>
+</th>
+<th width="92"/>
+<th width="305">
+<Text id="579">Hierarchical classification</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="580"><i>hfile</i></Text>
+</th>
+<th width="305">
+<Text id="581">Classification file</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="582"><i>metadata</i></Text>
+</th>
+<th width="305">
+<Text id="583">Metadata element to test against <i>hfile</i> identifier</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="584"><i>sort</i></Text>
+</th>
+<th width="305">
+<Text id="585">Metadata element used to sort documents within leaves (defaults to <i>Title</i>)</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="586"><i>buttonname</i></Text>
+</th>
+<th width="305">
+<Text id="587">Name of the button used to access this classifier (defaults to value of metadata argument)</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="588"><i>List</i></Text>
+</th>
+<th width="92"/>
+<th width="305">
+<Text id="589">Alphabetic list of documents</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="590"><i>metadata</i></Text>
+</th>
+<th width="305">
+<Text id="591">Include documents containing this metadata element</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="592"><i>buttonname</i></Text>
+</th>
+<th width="305">
+<Text id="593">Name of button used to access this classifier (defaults to value of metadata argument)</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="594"><i>SectionList</i></Text>
+</th>
+<th width="92"/>
+<th width="305">
+<Text id="595">List of sections in documents</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="596"><i>AZList</i></Text>
+</th>
+<th width="92"/>
+<th width="305">
+<Text id="597">List of documents split into alphabetical ranges</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="598"><i>metadata</i></Text>
+</th>
+<th width="305">
+<Text id="599">Include all documents containing this metadata element</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="600"><i>buttonname</i></Text>
+</th>
+<th width="305">
+<Text id="601">Name of button used to access this classifier (defaults to value of metadata argument)</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="602"><i>AZSectionList</i></Text>
+</th>
+<th width="92"/>
+<th width="305">
+<Text id="603">Like <i>AZList</i> but includes every section of the document</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="604"><i>DateList</i></Text>
+</th>
+<th width="92"/>
+<th width="305">
+<Text id="605">Similar to <i>AZList</i> but sorted by date</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="606">The current set of classifiers is listed in Table <CrossRef target="Table" ref="greenstone_classifiers"/>. Just as you can use the <i>pluginfo.pl</i> program to find out about any plugin, there is a <i>classinfo.pl</i> program that gives you information about any classifier, and the options it provides.</Text>
+<Text id="607">All classifiers accept the argument <i>buttonname</i>, which defines what is written on the Greenstone navigation button that invokes the classifier (it defaults to the name of the metadata argument). Buttons are provided for each Dublin Core metadata type, and for some other types of metadata.</Text>
+<Text id="608">Each classifier receives an implicit name from its position in the configuration file. For example, the third classifier specified in the file is called CL3. This is used to name the collection information database fields that define the classifier hierarchy.</Text>
+<Text id="609">Collection-specific classifiers can be written, and are stored in the collection's <i>perllib/classify</i> directory. The Development Library has a collection-specific classifier called <i>HDLList</i>, which is a minor variant of <i>AZList</i>.</Text>
+<Subsection id="list_classifiers">
+<Title>
+<Text id="610">List classifiers</Text>
+</Title>
+<Content>
+<Text id="611">The various flavours of list classifier are shown below.</Text>
+<BulletList>
+<Bullet>
+<Text id="612"><i>SectionList</i>âlike <i>List</i> but the leaves are sections rather than documents. All document sections are included except the top level. This is used to create lists of sections (articles, chapters or whatever) such as in the Computists' Weekly collection (available through <i>nzdl.org</i>), where each issue is a single document and comprises several independent news items, each in its own section.</Text>
+</Bullet>
+<Bullet>
+<Text id="613"><i>AZList</i>âgenerates a two-level hierarchy comprising an <i>HList</i> whose children are <i>VLists</i>, whose children are documents. The <i>HList</i> is an A-Z selector that divides the documents into alphabetic ranges. Documents are sorted alphabetically by metadata, and the resulting list is split into ranges.</Text>
+</Bullet>
+<Bullet>
+<Text id="614"><i>AZSectionList</i>âlike <i>AZList</i> but the leaves are sections rather than documents.</Text>
+</Bullet>
+<Bullet>
+<Text id="615"><i>DateList</i>âlike <i>AZList</i> except that the top-level <i>HList</i> allows selection by year and its children are <i>DateLists</i> rather than <i>VLists</i>. The metadata argument defaults to <i>Date</i>.</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Subsection>
+<Subsection id="the_hierarchy_classifier">
+<Title>
+<Text id="616">The hierarchy classifier</Text>
+</Title>
+<Content>
+<Text id="617">All classifiers are hierarchical. However, the list classifiers described above have a fixed number of levels, whereas the âhierarchyâ classifiers described in this section have an arbitrary number of levels. Hierarchy classifiers are more complex to specify than list classifiers.</Text>
+<Figure id="part_of_the_file_sub">
+<Title>
+<Text id="618">Part of the file <i>sub.txt</i></Text>
+</Title>
+<CodeLine>1           1       "General reference"</CodeLine>
+<CodeLine>1.2       1.2       "Dictionaries, glossaries, language courses, terminology</CodeLine>
+<CodeLine>2           2       "Sustainable Development, International cooperation, Pro</CodeLine>
+<CodeLine>2.1       2.1       "Development policy and theory, international cooperatio</CodeLine>
+<CodeLine>2.2       2.2       "Development, national planning, national plans"</CodeLine>
+<CodeLine>2.3       2.3       "Project planning and evaluation (incl. project managem</CodeLine>
+<CodeLine>2.4       2.4       "Regional development and planning incl. regional profil</CodeLine>
+<CodeLine>2.5       2.5       "Nongovernmental organisations (NGOs) in general, self-</CodeLine>
+<CodeLine>2.6       2.6       "Organisations, institutions, United Nations (general, d</CodeLine>
+<CodeLine>2.6.1   2.6.1       "United Nations"</CodeLine>
+<CodeLine>2.6.2   2.6.2       "International organisations"</CodeLine>
+<CodeLine>2.6.3   2.6.3       "Regional organisations"</CodeLine>
+<CodeLine>2.6.5   2.6.5       "European Community - European Union"</CodeLine>
+<CodeLine>2.7       2.7       "Sustainable Development, Development models and example</CodeLine>
+<CodeLine>2.8       2.8       "Basic Human Needs"</CodeLine>
+<CodeLine>2.9       2.9       "Hunger and Poverty Alleviation"</CodeLine>
+</Figure>
+<Text id="619">The <i>hfile</i> argument gives the name of a file, like that in Figure <CrossRef target="Figure" ref="part_of_the_file_sub"/>, which defines the metadata hierarchy. Each line describes one classification, and the descriptions have three parts:</Text>
+<BulletList>
+<Bullet>
+<Text id="620">Identifier, which matches the value of the metadata (given by the <i>metadata</i> argument) to the classification.</Text>
+</Bullet>
+<Bullet>
+<Text id="621">Position-in-hierarchy marker, in multi-part numeric form, e.g. 2, 2.12, 2.12.6.</Text>
+</Bullet>
+<Bullet>
+<Text id="622">The name of the classification. (If this contains spaces, it should be placed in quotation marks.)</Text>
+</Bullet>
+</BulletList>
+<Text id="623">Figure <CrossRef target="Figure" ref="part_of_the_file_sub"/> is part of the <i>sub.txt</i> file used to create the subject hierarchy in the Development Library (and the Demo collection). This example is a slightly confusing one because the number representing the hierarchy appears twice on each line. The metadata type <i>Hierarchy</i> is represented in documents with values in hierarchical numeric form, which accounts for the first occurrence. It is the second occurrence that is used to determine the hierarchy that the hierarchy browser implements.</Text>
+<Text id="624">The <i>hierarchy</i> classifier has an optional argument, <i>sort</i>, which determines how the documents at the leaves are ordered. Any metadata can be specified as the sort key. The default is to produce the list in the order in which the building process encounters the documents. Ordering at internal nodes is determined by the order in which things are specified in the <i>hfile</i> argument.</Text>
+</Content>
+</Subsection>
+<Subsection id="how_classifiers_work">
+<Title>
+<Text id="625">How classifiers work</Text>
+</Title>
+<Content>
+<Text id="626">Classifiers are Perl objects, derived from <i>BasClas.pm</i>, and are stored in the <i>perllib/classify</i> directory. They are used when the collection is built. When they are executed, the following four steps occur.</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="627">The <i>new</i> method creates the classifier object.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="628">The <i>init</i> method initialises the object with parameters such as metadata type, button name and sort criterion.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="629">The <i>classify</i> method is invoked once for each document, and stores information about the classification made within the classifier object.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="630">The <i>get_classify_info</i> method returns the locally stored classification information to the build process, which it then writes to the collection information database for use when the collection is displayed at runtime.</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="631">The <i>classify</i> method retrieves each document's OID, the metadata value on which the document is to be classified, and, where necessary, the metadata value on which the documents are to be sorted. The <i>get_classify_info</i> method performs all sorting and classifier-specific processing. For example, in the case of the <i>AZList</i> classifier, it splits the list into ranges.</Text>
+<Text id="632">The build process initialises the classifiers as soon as the <i>builder</i> object is created. Classifications are created during the build phase, when the information database is created, by <i>classify.pm</i>, which resides in Greenstone's <i>perllib</i> directory.</Text>
+<Table id="items_appearing_in_format_strings">
+<Title>
+<Text id="633">Items appearing in format strings</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="634"><i>[Text]</i></Text>
+</th>
+<th width="397">
+<Text id="635">The document's text</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="636"><i>[link] âŠ [/link]</i></Text>
+</th>
+<th width="397">
+<Text id="637">The html to link to the document itself</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="638"><i>[icon]</i></Text>
+</th>
+<th width="397">
+<Text id="639">An appropriate icon (e.g. the little text icon in a <i>Search Results</i> string)</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="640"><i>[num]</i></Text>
+</th>
+<th width="397">
+<Text id="641">The document number (useful for debugging).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="642"><i>[metadata-name]</i></Text>
+</th>
+<th width="397">
+<Text id="643">The value of this metadata element for the document, e.g. <i>[Title]</i></Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="formatting_greenstone_output">
+<Title>
+<Text id="644">Formatting Greenstone output</Text>
+</Title>
+<Content>
+<Text id="645">The web pages you see when using Greenstone are not pre-stored but are generated âon the flyâ as they are needed. The appearance of many aspects of the pages is controlled using âformat strings.â Format strings belong in the collection configuration file, introduced by the keyword <i>format</i> followed by the name of the element to which the format applies. There are two different kinds of page element that are controlled by format strings. The first comprises the items on the page that show documents or parts of documents. The second comprises the lists produced by classifiers and searches. All format strings are interpreted at the time that pages are displayed. Since they take effect as soon as any changes in <i>collect.cfg</i> are saved, experimenting with format strings is quick and easy.</Text>
+<Text id="646">Table <CrossRef target="Table" ref="items_appearing_in_format_strings"/> shows the format statements that affect the way documents look. The <i>DocumentButtons</i> option controls what buttons are displayed on a document page. Here, <i>string</i> is a list of buttons (separated by |), possible values being <i>Detach</i>, <i>Highlight</i>, <i>Expand Text</i>, and <i>Expand Contents</i>. Reordering the list reorders the buttons.</Text>
+<Table id="the_format_options">
+<Title>
+<Text id="647">The <i>format</i> options</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="246">
+<Text id="648"><i>format DocumentImages true/false</i></Text>
+</th>
+<th width="283">
+<Text id="649">If <i>true</i>, display a cover image at the top left of the document page (default <i>false</i>).</Text>
+</th>
+</tr>
+<tr>
+<th width="246">
+<Text id="650"><i>format DocumentHeading formatstring</i></Text>
+</th>
+<th width="283">
+<Text id="651">If <i>DocumentImages</i> is <i>false</i>, the format string controls how the document header shown at the top left of the document page looks (default <i>[Title]</i>).</Text>
+</th>
+</tr>
+<tr>
+<th width="246">
+<Text id="652"><i>format DocumentContents true/false</i></Text>
+</th>
+<th width="283">
+<Text id="653">Display table of contents (if document is hierarchical), or next/previous section arrows and âpage k of nâ text (if not).</Text>
+</th>
+</tr>
+<tr>
+<th width="246">
+<Text id="654"><i>format DocumentButtons string</i></Text>
+</th>
+<th width="283">
+<Text id="655">Controls the buttons that are displayed on a document page (default <i>Detach|Highlight</i>).</Text>
+</th>
+</tr>
+<tr>
+<th width="246">
+<Text id="656"><i>format DocumentText formatstring</i></Text>
+</th>
+<th width="283">
+<Text id="657">Format of the text to be displayed on a document page: default</Text>
+<CodeLine>Â Â Â Â <i>&lt;center&gt;&lt;table width=537&gt;</i></CodeLine>
+<CodeLine><i>Â Â Â Â Â Â &lt;tr&gt;&lt;td&gt;[Text]&lt;/td&gt;&lt;/tr&gt;</i></CodeLine>
+<CodeLine><i>Â Â Â Â Â Â &lt;/table&gt;&lt;/center&gt;</i></CodeLine>
+</th>
+</tr>
+<tr>
+<th width="246">
+<Text id="658"><i>format DocumentArrowsBottom true/false</i></Text>
+</th>
+<th width="283">
+<Text id="659">Display next/previous section arrows at bottom of document page (default <i>true</i>).</Text>
+</th>
+</tr>
+<tr>
+<th width="246">
+<Text id="660"><i>format DocumentUseHTML true/false</i></Text>
+</th>
+<th width="283">
+<Text id="661">If <i>true</i>, each document is displayed inside a separate frame. The Preferences page will also change slightly, adding options applicable to a collection of html documents, including the ability to go directly to the original source document (anywhere on the Web) rather than to the Greenstone copy.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Subsection id="formatting_greenstone_lists">
+<Title>
+<Text id="662">Formatting Greenstone lists</Text>
+</Title>
+<Content>
+<Text id="663">Format strings that control how lists look can apply at different levels of the display structure. They can alter all lists of a certain type within a collection (for example <i>DateList</i>), or all parts of a list (for example all the entries in the <i>Search</i> list), or specific parts of a certain list (for example, the vertical list part of an <i>AZList</i> classifier on title).</Text>
+<Text id="664">Following the keyword <i>format</i> is a two-part keyword, only one part of which is mandatory. The first part identifies the list to which the format applies. The list generated by a search is called <i>Search</i>, while the lists generated by classifiers are called <i>CL1, CL2, CL3,âŠ</i> for the first, second, third,âŠ classifier specified in <i>collect.cfg</i>. The second part of the keyword is the part of the list to which the formatting is to applyâeither <i>HList</i> (for horizontal list, like the A-Z selector in an <i>AZList</i>), <i>VList</i> (for vertical list, like the list of titles under an <i>AZList</i>), or <i>DateList</i>. For example:</Text>
+<Indented>
+<Text id="665"><i>format CL4VList ...</i>                                  applies to all <i>VLists</i> in CL4</Text>
+</Indented>
+<Indented>
+<Text id="666"><i>format CL2HList ...</i>                                applies to all <i>HLists</i> in CL2</Text>
+</Indented>
+<Indented>
+<Text id="667"><i>format CL1DateList ...</i>                      applies to all <i>DateLists</i> in CL1</Text>
+</Indented>
+<Indented>
+<Text id="668"><i>format SearchVList ...</i>                        applies to the Search Results list</Text>
+</Indented>
+<Indented>
+<Text id="669"><i>format CL3 ...</i>                                                    applies to all nodes in CL3, unless otherwise specified</Text>
+</Indented>
+<Indented>
+<Text id="670"><i>format VList ...</i>                                                applies to all <i>VLists</i> in all classifiers, unless otherwise specified</Text>
+</Indented>
+<Text id="671">The â...â in these examples stand for html format specifications that control the information, and its layout, that appear on web pages displaying the classifier. As well as html specifications, any metadata may appear within square brackets: its value is interpolated in the indicated place. Also, any of the items in Table <CrossRef target="Table" ref="the_format_options"/> may appear in format strings. The syntax for the strings also includes a conditional statement, which is illustrated in an example below.</Text>
+<Text id="672">Recall that all classifiers produce hierarchies. Each level of the hierarchy is displayed in one of four possible ways. We have already encountered <i>HList</i>, <i>VList</i>, and <i>DateList</i>. There is also <i>Invisible</i>, which is how the very top levels of hierarchies are displayedâbecause the name of the classifier is already shown separately on the Greenstone navigation bar.</Text>
+</Content>
+</Subsection>
+<Subsection id="examples_of_classifiers_and_format_strings">
+<Title>
+<Text id="673">Examples of classifiers and format strings</Text>
+</Title>
+<Content>
+<Figure id="excerpt_from_the_demo_collection_collect" class="withLineNumber">
+<Title>
+<Text id="674">Excerpt from the Demo collection's <i>collect.cfg</i></Text>
+</Title>
+<CodeLine>classify Hierarchy -hfile sub.txt -metadata Subject -sort Title</CodeLine>
+<CodeLine>classify AZList       -metadata Title</CodeLine>
+<CodeLine>classify Hierarchy -hfile org.txt -metadata Organisation -sort Title</CodeLine>
+<CodeLine>classify List           -metadata Howto</CodeLine>
+<CodeLine>format SearchVList " &lt;td valign=top [link][icon][/link]&lt;/td&gt;&lt;td&gt;{If}</CodeLine>
+<CodeLine>                                       {[parent(All':'):Title],[parent(All':'):Title]:}</CodeLine>
+<CodeLine>                                       [link][Title][/link]&lt;/td&gt; "</CodeLine>
+<CodeLine>format CL4Vlist                 "&lt;br&gt;[link][Howto][/link] "</CodeLine>
+<CodeLine>format DocumentImages   true</CodeLine>
+<CodeLine>format DocumentText       "&lt;h3&gt;[Title]&lt;/h3&gt;\\n\\n&lt;p&gt;[Text]"</CodeLine>
+<CodeLine>format DocumentButtons " Expand Text|Expand contents|Detach|Highlight"</CodeLine>
+</Figure>
+<Text id="675">Figure <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/> shows part of the collection configuration file for the Demo collection. We use this as an example because it has several classifiers that are richly formatted. Note that statements in collection configuration files must not contain newline charactersâin the Table, longer lines are broken up for readability.</Text>
+<Text id="676">Line 4 specifies the Demo collection's <i>How To</i> classifier. This is the fourth in the collection configuration file, and is therefore referred to as CL4. The corresponding format statement is line 7 of Figure <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/>. The âhow toâ information is generated from the <i>List</i> classifier, and its structure is the plain list of titles shown in Figure <CrossRef target="Figure" ref="list_classifier"/>. The titles are linked to the documents themselves: clicking a title brings up the relevant document. The children of the hierarchy's top level are displayed as a <i>VList</i>(vertical list), which lists the sections vertically. As the associated <i>format</i> statement indicates, each element of the list is on a newline (â <i>&lt;br&gt;</i> â) and contains the <i>Howto</i> text, hyperlinked to the document itself.</Text>
+<Text id="677">Line 1 specifies the Demo collection's <i>Subject</i> classification, referred to as CL1 (the first in the configuration file), and Line 3 the <i>Organisation</i> classification CL3. Both are generated by the <i>Hierarchy</i> classifier and therefore comprise a hierarchical structure of <i>VLists</i>.</Text>
+<Text id="678">Line 2 specifies the remaining classification for the Demo collection, <i>Titles A-Z</i> (CL2). Note that there are no corresponding format strings for the classifiers CL1 -CL3. Greenstone has built-in defaults for each format string type and so it's not necessary to set a format string unless you want to override the default.</Text>
+<Figure id="formatting_the_document">
+<Title>
+<Text id="679">Formatting the document</Text>
+</Title>
+<File width="394" height="277" url="images/Dev_Fig_17.gif"/>
+</Figure>
+<Text id="680">This accounts for the four <i>classify</i> lines in Figure <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/>. Coincidentally, there are also four <i>format</i> lines. We have already discussed one, the <i>CL4Vlist</i> one. The remaining three are the first type of format string, documented in Table <CrossRef target="Table" ref="items_appearing_in_format_strings"/>. For example, line 8 places the cover image at the top left of each document page. Line 9 formats the actual document text, with the title of the relevant chapter or section preceding the text itself. These are illustrated in Figure <CrossRef target="Figure" ref="formatting_the_document"/>.</Text>
+<Figure id="formatting_the_search_results">
+<Title>
+<Text id="681">Formatting the search results</Text>
+</Title>
+<File width="396" height="243" url="images/Dev_Fig_18.gif"/>
+</Figure>
+<Text id="682">Line 5 of Figure <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/> is a rather complicated specification that formats the query result list returned by a search, whose parts are illustrated in Figure <CrossRef target="Figure" ref="formatting_the_search_results"/>. A simplified version of the format string is</Text>
+<CodeLine>&lt;td valign=top&gt;[link][icon][/link]&lt;/td&gt;</CodeLine>
+<CodeLine>&lt;td&gt;[link][Title][/link]&lt;/td&gt;</CodeLine>
+<Text id="683">This is designed to appear as a table row, which is how the query results list is formatted. It gives a small icon linked to the text, as usual, and the document title, hyperlinked to the document itself.</Text>
+<Text id="684">In this collection, documents are hierarchical. In fact, the above hyperlink anchor evaluates to the title of the section returned by the query. However, it would be better to augment it with the title of the enclosing section, the enclosing chapter, and the book in which it occurs. There is a special metadata item, <i>parent</i>, which is not stored in documents but is implicit in any hierarchical document, that produces such a list. It either returns the parent document, or, if used with the qualifier <i>All</i>, the list of hierarchically enclosing parents, separated by a character string that can be given after the <i>All</i> qualifier. Thus</Text>
+<CodeLine>&lt;td valign=top&gt;[link][icon][/link]&lt;/td&gt; <br/>&lt;td&gt;{[parent(All': '):Title]: }[link][Title][/link]&lt;/td&gt;</CodeLine>
+<Text id="685">has the effect of producing a list containing the book title, chapter title, etc. that enclose the target section, separated by colons, with a further colon followed by a hyperlink to the target section's title.</Text>
+<Text id="686">Unfortunately, if the target is itself a book, there is no parent and so an empty string will appear followed by a colon. To circumvent such problems you can use <i>if</i> and <i>or âŠ else</i> statements in a format string:</Text>
+<CodeLine>{If}{[metadata], action-if-non-null, action-if-null}</CodeLine>
+<CodeLine>{Or}{action, else another-action, else another-action, etc}</CodeLine>
+<Text id="687">In either case curly brackets are used to signal that the statements should be interpreted and not just printed out as text. The <i>If</i> tests whether the metadata is empty and takes the first clause if not, otherwise the second one (if it exists). Any metadata item can be used, including the special metadata <i>parent</i>. The <i>Or</i> statement evaluates each action in turn until one is found that is non-null. That one is sent to the output and the remaining actions are skipped.</Text>
+<Text id="688">Returning to line 5 of Figure <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/>, the full format string is</Text>
+<CodeLine>&lt;td valign=top&gt;[link][icon][/link]&lt;/td&gt;</CodeLine>
+<CodeLine>&lt;td&gt;{If}{[parent(All': '):Title],</CodeLine>
+<CodeLine>           [parent(All': '):Title]:}</CodeLine>    
+<CodeLine>      [link][Title][/link]&lt;/td&gt;</CodeLine>
+<Text id="689">This precedes the <i>parent</i> specification with a conditional that checks whether the result is empty and only outputs the parent string when it is present. Incidentally, <i>parent</i> can be qualified by <i>Top</i> instead of <i>All</i>, which gives the top-level document name that encloses a sectionâin this case, the book name. No separating string is necessary with <i>Top</i>.</Text>
+<Text id="690">Some final examples illustrate other features. The <i>DateList</i> in Figure <CrossRef target="Figure" ref="datelist_classifier"/> is used in the <i>Dates</i> classification of the Computists' Weekly collection (which happens to be the second classifier, CL2). The classifier and format specifications are shown below. The <i>DateList</i> classifier differs from <i>AZList</i> in that it always sorts by <i>Date</i> metadata, and the bottom branches of the browsing hierarchy use <i>DateList</i> instead of <i>VList</i>, which causes the year and month to be added at the left of the document listings.</Text>
+<CodeLine>classify AZSectionList metadata=Creator</CodeLine>
+<CodeLine>format CL2Vlist "&lt;td&gt;[link][icon][/link]&lt;/td&gt; <br/>&lt;td&gt;[Creator]&lt;/td&gt; <br/>&lt;td&gt;&amp;nbsp;&amp;nbsp;[Title]&lt;/td&gt; <br/>&lt;td&gt;[parent(Top):Date]&lt;/td&gt; "</CodeLine>
+<Text id="691">The format specification shows these <i>VLists</i> in the appropriate way.</Text>
+<Text id="692">The format-string mechanism is flexible but tricky to learn. The best way is by studying existing collection configuration files.</Text>
+</Content>
+</Subsection>
+<Subsection id="linking_to_different_document_versions">
+<Title>
+<Text id="693">Linking to different document versions</Text>
+</Title>
+<Content>
+<Text id="694">Using the <i>[link] âŠ [/link]</i> mechanism in a format string inserts a hyperlink to the text of a document, and when the link is clicked the html version of the document is displayed. In some collections, it is useful to be able to display other versions of the document. For example, in a collection of Microsoft Word documents, it is nice to be able to display the Word version of each document rather than the html that is extracted from it; similarly for PDF documents.</Text>
+<Text id="695">The key to being able to show different versions of a document is to embed the necessary information about where the other versions reside into the Greenstone archive form of the document. The information is represented in the form of metadata. Recall that putting</Text>
+<CodeLine>[link][Title][/link]</CodeLine>
+<Text id="696">into a format string creates a link to the html form of the document, whose anchor text is the document's title. The Word and PDF plugins both generate <i>srclink</i> metadata so that if you put</Text>
+<CodeLine>[srclink][Title][/srclink]</CodeLine>
+<Text id="697">into a format string, a link is created to the Word or PDF form of the document; again the anchor in this example is the document's title. In order that the appropriate icon can be displayed for Word and PDF documents, these plugins also generate <i>srcicon</i> metadata so that</Text>
+<CodeLine>[srclink][srcicon][/srclink]</CodeLine>
+<Text id="698">creates a link which is labeled by the standard Word or PDF icon (whichever is appropriate), rather than the document's title.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="controlling_the_greenstone_user_interface">
+<Title>
+<Text id="699">Controlling the Greenstone user interface</Text>
+</Title>
+<Content>
+<Text id="700">The entire Greenstone user interface is controlled by macros which reside in the <i>GSDLHOME/macros</i> directory. They are written in a language designed especially for Greenstone, and are used run time to generate web pages. Translating the macro language into html is the last step in displaying a page. Thus changes to a macro file affect the display immediately, making experimentation quick and easy. All macro files used by Greenstone are listed in <i>GSDLHOME/etc/main.cfg</i> and are loaded every time it starts. One exception to this is when using the Windows Local LIbrary; in this case it is necessary to restart the process.</Text>
+<Text id="701">Web pages are generated on the fly for a number of reasons, and the macro system is how Greenstone implements the necessary flexibility. Pages can be presented in many languages, and a different macro file is used to store all the interface text in each language. When Greenstone displays a page the macro interpreter checks a language variable and loads the page in the appropriate language (this does not, unfortunately, extend to translating document content). Also, the values of certain display variables, like the number of documents found by a search, are not known ahead of time; these are interpolated into the page text in the form of macros.</Text>
+<Subsection id="the_macro_file_format">
+<Title>
+<Text id="702">The macro file format</Text>
+</Title>
+<Content>
+<Text id="703">Macro files have a <i>.dm</i> extension. Each file defines one or more <i>packages</i>, each containing a series of macros used for a single purpose. Like classifiers and plugins, there is a basis from which to build macros, called <i>base.dm</i> ; this file defines the basic content of a page.</Text>
+<Text id="704">Macros have names that begin and end with an underscore, and their content is defined using curly brackets. Content can be plain text, html (including links to Java applets and JavaScript), macro names, or any combination of these. This macro from <i>base.dm</i> defines the content of a page in the absence of any overriding macro:</Text>
+<CodeLine>_content_ {&lt;p&gt;&lt;h2&gt;Oops&lt;/h2&gt;_textdefaultcontent_}</CodeLine>
+<Text id="705">The page will read âOopsâ at the top, and <i>_textdefaultcontent_</i>, which is defined, in English, to be <i>The requested page could not be found. Please use your browsers 'back' button or the above home button to return to the Greenstone Digital Library,</i> and in other languages to be a suitable translation of this sentence.</Text>
+<Text id="706"><i>_textdefaultcontent_</i> and <i>_content_</i> both reside in the <i>global</i> package because they are required by all parts of the user interface. Macros can use macros from other packages as content, but they must prefix their names with their package name. For example,</Text>
+<CodeLine>_collectionextra_ {This collection contains _about:numdocs_ documents. It was last built _about:builddate_ days ago.)</CodeLine>
+<Text id="707">comes from <i>english.dm</i>, and is used as the default description of a collection. It is part of the <i>global</i> package, but <i>_numdocs_</i> and <i>_builddate_</i> are both in the <i>about</i> packageâhence the <i>about:</i> preceding their names.</Text>
+<Text id="708">Macros often contain conditional statements. They resemble the format string conditional described above, though their appearance is slightly different. The basic format is <i>_If_(x,y,z)</i>, where <i>x</i> is a condition, <i>y</i> is the macro content to use if that condition is true, and <i>z</i> the content if it is false. Comparison operators are the same as the simple ones used in Perl (less than, greater than, equals, not equals). This example from <i>base.dm</i> is used to determine how to display the top of a collection's <i>about</i> page:</Text>
+<CodeLine>_imagecollection_ {</CodeLine>
+<CodeLine>       _If_( "_iconcollection_ " ne "",</CodeLine>
+<CodeLine>                 &lt;a href = "_httppageabout_ "&gt; </CodeLine>
+<CodeLine>                         &lt;img src = "_iconcollection_ " border = 0&gt;</CodeLine>
+<CodeLine>                         &lt;/a&gt;,</CodeLine>
+<CodeLine>                 _imagecollectionv_)</CodeLine>
+<CodeLine>}</CodeLine>
+<Text id="709">This looks rather obscure. <i>_iconcollection_</i> resolves to the empty string if the collection doesn't have an icon, or the filename of an image. To paraphrase the above code: If there is a collection image, display the <i>About this Collection</i> page header (referred to by <i>_httppageabout_</i>) and then the image; otherwise use the alternative display <i>_imagecollectionv_</i>.</Text>
+<Text id="710">Macros can take arguments. Here is a second definition for the <i>_imagecollection_</i> macro which immediately follows the definition given above in the <i>base.dm</i> file:</Text>
+<CodeLine>_imagecollection_[v=1]{_imagecollectionv_}</CodeLine>
+<Text id="711">The argument <i>[v=1]</i> specifies that the second definition is used when Greenstone is running in text-only mode. The language macros work similarlyâapart from <i>english.dm</i>, because it is the default, all language macros specify their language as an argument. For example,</Text>
+<CodeLine>_textimagehome_ {Home Page}</CodeLine>
+<Text id="712">appears in the English language macro file, whereas the German version is</Text>
+<CodeLine>_textimagehome_ [l=de] {Hauptaseite}</CodeLine>
+<Text id="713">The English and German versions are in the same package, though they are in separate files (package definitions may span more than one file). Greenstone uses its <i>l</i> argument at run time to determine which language to display.</Text>
+<Figure id="part_of_the_aboutdm_macro_file">
+<Title>
+<Text id="714">Part of the <i>about.dm</i> macro file</Text>
+</Title>
+<CodeLine>package about</CodeLine>
+<CodeLine>##############################################</CodeLine>
+<CodeLine># about page content</CodeLine>
+<CodeLine>###############################################</CodeLine>
+<CodeLine>_pagetitle_ {_collectionname_}</CodeLine>
+<CodeLine>_content_ {</CodeLine>
+<CodeLine>&lt;center&gt;</CodeLine>
+<CodeLine>_navigationbar_</CodeLine>
+<CodeLine>&lt;/center&gt;</CodeLine>
+<CodeLine>_query:queryform_</CodeLine>
+<CodeLine>&lt;p&gt;_iconblankbar_</CodeLine>
+<CodeLine>&lt;p&gt;_textabout_</CodeLine>
+<CodeLine>_textsubcollections_</CodeLine>
+<CodeLine>&lt;h3&gt;_help:textsimplehelpheading_&lt;/h3&gt;</CodeLine>
+<CodeLine>_help:simplehelp_</CodeLine>
+<CodeLine>}</CodeLine>
+<CodeLine>_textabout_ {</CodeLine>
+<CodeLine>&lt;h3&gt;_textabcol_&lt;/h3&gt;</CodeLine>
+<CodeLine>_Global:collectionextra_</CodeLine>
+<CodeLine>}</CodeLine>
+</Figure>
+<Text id="715">As a final example, Figure <CrossRef target="Figure" ref="part_of_the_aboutdm_macro_file"/> shows an exerpt from the macro file <i>about.dm</i> that is used to generate the âAbout this collectionâ page for each collection. It shows three macros being defined, <i>_pagetitle_</i>, <i>_content_</i> and <i>_textabout_</i>.</Text>
+</Content>
+</Subsection>
+<Subsection id="using_macros">
+<Title>
+<Text id="716">Using macros</Text>
+</Title>
+<Content>
+<Text id="717">Macros are powerful, and can be a little obscure. However, with a good knowledge of html and a bit of practice, they become a quick and easy way to customise your Greenstone site.</Text>
+<Text id="718">For example, suppose you wanted to create a static page that looked like your current Greenstone site. You could create a new package, called <i>static</i>, for example, in a new file, and override the <i>_content_</i> macro. Add the new filename to the list of macros in <i>GSDLHOME/etc/main.cfg</i> which Greenstone loads every time it is invoked. Finally, access the new page by using your regular Greenstone URL and appending the arguments <i>?a=p&amp;p=static</i> (e.g. <i>http://servername/cgi-bin/library?a=p&amp;p=static</i>).</Text>
+<Text id="719">To change the âlook and feelâ of Greenstone you can edit the <i>base</i> and <i>style</i> packages. To change the Greenstone home page, edit the <i>home</i> package (this is described in the <i>Greenstone Digital Library Installer's Guide</i>). To change the query page, edit <i>query.dm</i>.</Text>
+<Text id="720">Experiment freely with macros. Changes appear instantly, because macros are interpreted as pages are displayed. The macro language is a useful tool that can be used to make your Greenstone site your own.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="the_packages_directory">
+<Title>
+<Text id="721">The packages directory</Text>
+</Title>
+<Content>
+<Table id="the_packages_directory_1">
+<Title>
+<Text id="722">The <i>packages</i> directory</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="217">
+<Text id="723"><b>Package</b></Text>
+</th>
+<th width="180">
+<Text id="724"><b>URL</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="725"><i>mg</i></Text>
+</th>
+<th width="217">
+<Text id="726">mg, short for âManaging Gigabytes.â Compression, indexing and search software used to manage textual information in Greenstone collections.</Text>
+</th>
+<th width="180">
+<Text id="727"><i>www.citri.edu.au/mg</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="728"><i>wget</i></Text>
+</th>
+<th width="217">
+<Text id="729">Web mirroring software for use with Greenstone. Written in C++</Text>
+</th>
+<th width="180">
+<Text id="730"><i>www.tuwien.ac.at/~prikryl/ wget.html</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="731"><i>w3mir</i></Text>
+</th>
+<th width="217">
+<Text id="732">A web mirroring program written in Perl. This is not Greenstone's preferred mirroring program because it relies on a specific outdated version of a certain Perl module (which is distributed in the <i>w3mir</i> directory).</Text>
+</th>
+<th width="180">
+<Text id="733"><i>www.math.uio.no/~janl/w3mir</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="734"><i>windows</i></Text>
+</th>
+<th width="217">
+<Text id="735">Packages used when running under Windows.</Text>
+</th>
+<th width="180">
+<Text id="736"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="737"><i>windows/gdbm</i></Text>
+</th>
+<th width="217">
+<Text id="738">Version of the Gnu Database Manager created for Windows. Gdbm comes as a standard part of Linux.</Text>
+</th>
+<th width="180">
+<Text id="739"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="740"><i>windows/crypt</i></Text>
+</th>
+<th width="217">
+<Text id="741">Encryption program used for passwords for Greenstone's administrative functions.</Text>
+</th>
+<th width="180">
+<Text id="742"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="743"><i>windows/stlport</i></Text>
+</th>
+<th width="217">
+<Text id="744">Standard Template Library, for use when compiling Greenstone with certain Windows compilers.</Text>
+</th>
+<th width="180">
+<Text id="745"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="746"><i>wv</i></Text>
+</th>
+<th width="217">
+<Text id="747">Microsoft Word converter (for building collections from Word documents) slimmed down for Greenstone.</Text>
+</th>
+<th width="180">
+<Text id="748"><i>sourceforge.net/projects/ wvware</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="749"><i>pdftohtml</i></Text>
+</th>
+<th width="217">
+<Text id="750">PDF converter used when building collections from PDF documents.</Text>
+</th>
+<th width="180">
+<Text id="751"><i>www.ra.informatik.uni-stutt gart.de/ <br/>~gosho/pdftohtml</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="752"><i>yaz</i></Text>
+</th>
+<th width="217">
+<Text id="753">Z39.50 client program being used for research in making Greenstone Z39.50 compliant. Progress is reported in the <i>README.gsdl</i> file.</Text>
+</th>
+<th width="180">
+<Text id="754"><i>www.indexdata.dk</i></Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="755">The <i>packages</i> directory, whose contents are shown in Table <CrossRef target="Table" ref="the_packages_directory_1"/>, is where all the code used by Greenstone but written by other research teams resides. All software distributed with Greenstone has been released under the Gnu Public license. The executables produced by these packages are placed in the Greenstone <i>bin</i> directory. Each package is stored in a directory of its own. Their functions vary widely, from indexing and compression to converting Microsoft Word documents to html. Each package has a README file which gives more information about it.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="the_greenstone_runtime_system">
+<Title>
+<Text id="756">The Greenstone runtime system</Text>
+</Title>
+<Content>
+<Text id="757">This chapter describes the Greenstone runtime system so that you can understand, augment and extend its capabilities. The software is written in C++ and makes extensive use of virtual inheritance. If you are unfamiliar with this language you should learn about it before proceeding. Deitel and Deitel (1994) provide a comprehensive tutorial, while Stroustroup (1997) is the definitive reference.</Text>
+<Text id="758">We begin by explaining the design philosophy behind the runtime system since this has a strong bearing on implementation. Then we provide the implementation details, which forms the main part of this chapter. The version of Greenstone described here is the CGI version (Web Library if for Windows users). The Windows Local Library uses the same source code but has a built-in webserver front end. Also, the Local Library is a persistent process.</Text>
+<Section id="process_structure">
+<Title>
+<Text id="759">Process structure</Text>
+</Title>
+<Content>
+<Figure id="overview_of_a_general_greenstone_system">
+<Title>
+<Text id="760">Overview of a general Greenstone system</Text>
+</Title>
+<File width="382" height="335" url="images/Dev_Fig_20.png"/>
+</Figure>
+<Text id="761">Figure <CrossRef target="Figure" ref="overview_of_a_general_greenstone_system"/> shows several users, represented by computer terminals at the top of the diagram, accessing three Greenstone collections. Before going online, these collections undergo the importing and building processes described in earlier chapters. First, documents, shown at the bottom of the figure, are imported into the XML-compliant Greenstone Archive Format. Then the archive files are built into various searchable indexes and a collection information database that includes the hierarchical structures that support browsing. This done, the collection is ready to go online and respond to requests for information.</Text>
+<Text id="762">Two components are central to the design of the runtime system: âreceptionistsâ and âcollection servers.â From a user's point of view, a receptionist is the point of contact with the digital library. It accepts user input, typically in the form of keyboard entry and mouse clicks; analyzes it; and then dispatches a request to the appropriate collection server (or servers). This locates the requested piece of information and returns it to the receptionist for presentation to the user. Collection servers act as an abstract mechanism that handle the content of the collection, while receptionists are responsible for the user interface.</Text>
+<Figure id="greenstone_system_using_the_null_protocol">
+<Title>
+<Text id="763">Greenstone system using the ânull protocolâ</Text>
+</Title>
+<File width="329" height="424" url="images/Dev_Fig_21.png"/>
+</Figure>
+<Text id="764">As Figure <CrossRef target="Figure" ref="overview_of_a_general_greenstone_system"/> shows, receptionists communicate with collection servers using a defined protocol. The implementation of this protocol depends on the computer configuration on which the digital library system is running. The most common case, and the simplest, is when there is one receptionist and one collection server, and both run on the same computer. This is what you get when you install the default Greenstone. In this case the two processes are combined to form a single executable (called <i>library</i>), and consequently using the protocol reduces to making function calls. We call this the <i>null protocol</i>. It forms the basis for the standard out-of-the-box Greenstone digital library system. This simplified configuration is illustrated in Figure <CrossRef target="Figure" ref="greenstone_system_using_the_null_protocol"/>, with the receptionist, protocol and collection server bound together as one entity, the <i>library</i> program. The aim of this chapter is to show how it works.</Text>
+<Text id="765">Usually, a âserverâ is a persistent process that, once started, runs indefinitely, responding to any requests that come in. Despite its name, however, the collection server in the null protocol configuration is not a server in this sense. In fact, every time any Greenstone web page is requested, the <i>library</i> program is started up (by the CGI mechanism), responds to the request, and then exits. We call it a âserverâ because it is also designed to work in the more general configuration of Figure <CrossRef target="Figure" ref="overview_of_a_general_greenstone_system"/>.</Text>
+<Text id="766">Surprisingly, this start-up, process and exit cycle is not as slow as one might expect, and results in a perfectly usable service. However, it is clearly inefficient. There is a mechanism called Fast-CGI (<i>www.fastcgi.com</i>) which provides a middle ground. Using it, the <i>library</i> program can remain in memory at the end of the first execution, and have subsequent sets of CGI arguments fed to it, thus avoiding repeated initialisation overheads and accomplishing much the same behaviour as a server. Using Fast-CGI is an option in Greenstone, and is enabled by recompiling the source code with appropriate libraries.</Text>
+<Text id="767">As an alternative to the null protocol, the Greenstone protocol has also been implemented using the well-known CORBA scheme (Slama <i>et al.</i>, 1999). This uses a unified object oriented paradigm to enable different processes, running on different computer platforms and implemented in different programming languages, to access the same set of distributed objects over the Internet (or any other network). Then, scenarios like Figure <CrossRef target="Figure" ref="overview_of_a_general_greenstone_system"/> can be fully implemented, with all the receptionists and collection servers running on different computers.</Text>
+<Figure id="graphical_query_interface_to_greenstone">
+<Title>
+<Text id="768">Graphical query interface to Greenstone</Text>
+</Title>
+<File width="397" height="348" url="images/Dev_Fig_22.png"/>
+</Figure>
+<Text id="769">This allows far more sophisticated interfaces to be set up to exactly the same digital library collections. As just one example, Figure <CrossRef target="Figure" ref="graphical_query_interface_to_greenstone"/> shows a graphical query interface, based on Venn diagrams, that lets users manipulate Boolean queries directly. Written in Java, the interface runs locally on the user's own computer. Using CORBA, it accesses a remote Greenstone collection server, written in C++.</Text>
+<Text id="770">The distributed protocol is still being refined and readied for use, and so this manual does not discuss it further (see Bainbridge <i>et al</i>., 2001, for more information).</Text>
+</Content>
+</Section>
+<Section id="conceptual_framework">
+<Title>
+<Text id="771">Conceptual framework</Text>
+</Title>
+<Content>
+<Figure id="generating_the_about_this_collection_page">
+<Title>
+<Text id="772">Generating the âabout this collectionâ page</Text>
+</Title>
+<File width="398" height="354" url="images/Dev_Fig_23.png"/>
+</Figure>
+<Text id="773">Figure <CrossRef target="Figure" ref="generating_the_about_this_collection_page"/> shows the âabout this collectionâ page of a particular Greenstone collection (the Project Gutenberg collection). Look at the URL at the top. The page is generated as a result of running the CGI program <i>library</i>, which is the above-mentioned executable comprising both receptionist and collection server connected by the null protocol. The arguments to <i>library</i> are <i>c=gberg</i>, <i>a=p</i>, and <i>p=about</i>. They can be interpreted as follows:</Text>
+<Indented>
+<Text id="774"><i>For the Project Gutenberg collection (c=gberg), the action is to generate a page (a=p), and the page to generate is called âaboutâ (p=about).</i></Text>
+</Indented>
+<Figure id="greenstone_runtime_system">
+<Title>
+<Text id="775">Greenstone runtime system</Text>
+</Title>
+<File width="534" height="345" url="images/Dev_Fig_24.gif"/>
+</Figure>
+<Text id="776">Figure <CrossRef target="Figure" ref="greenstone_runtime_system"/> illustrates the main parts of the Greenstone runtime system. At the top, the receptionist first initialises its components, then parses the CGI arguments to decide which action to call. In performing the action (which includes further processing of the CGI arguments), the software uses the protocol to access the content of the collection. The response is used to generate a web page, with assistance from the format component and the macro language.</Text>
+<Text id="777">The macro language, which we met in Section <CrossRef target="Section" ref="controlling_the_greenstone_user_interface"/>, is used to provide a Greenstone digital library system with a consistent style, and to create interfaces in different languages. Interacting with the library generates the bare bones of web pages; the macros in <i>GSDLHOME/macros</i> wrap them in flesh.</Text>
+<Text id="778">The Macro Language object in Figure <CrossRef target="Figure" ref="greenstone_runtime_system"/> is responsible for reading these files and storing the parsed result in memory. Any action can use this object to expand a macro. It can even create new macro definitions and override existing ones, adding a dynamic dimension to macro use.</Text>
+<Text id="779">The layout of the âabout this collectionâ page (Figure <CrossRef target="Figure" ref="generating_the_about_this_collection_page"/>) is known before runtime, and encoded in the macro file <i>about.dm</i>. Headers, footers, and the background image are not even mentioned because they are located in the <i>Global</i> macro package. However, the specific âaboutâ text for a particular collection is not known in advance, but is stored in the collection information database during the building process. This information is retrieved using the protocol, and stored as <i>_collectionextra_</i> in the <i>Global</i> macro package. Note this macro name is essentially the same name used to express this information in the collection configuration file described in Section <CrossRef target="Section" ref="configuration_file"/>. To generate the content of the page, the <i>_content_</i> macro in the <i>about</i> package (shown in Figure <CrossRef target="Figure" ref="part_of_the_aboutdm_macro_file"/>) is expanded. This in turn expands <i>_textabout_</i>, which itself accesses <i>_collectionextra_</i>, which had just been dynamically placed there.</Text>
+<Text id="780">One further important ingredient is the Format object. Format statements in the collection configuration file affect the presentation of particular pieces of information, as described in Section <CrossRef target="Section" ref="formatting_greenstone_output"/>. They are handled by the Format object in Figure <CrossRef target="Figure" ref="greenstone_runtime_system"/>. This object's main task is to parse and evaluate statements such as the format strings in Figure <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/>. As we learned in Section <CrossRef target="Section" ref="formatting_greenstone_output"/>, these can include references to metadata in square brackets (e.g. <i>[Title]</i>), which need to be retrieved from the collection server. Interaction occurs between the Format object and the Macro Language object, because format statements can include macros that, when expanded, include metadata, which when expanded include macros, and so on.</Text>
+<Text id="781">At the bottom of Figure <CrossRef target="Figure" ref="greenstone_runtime_system"/>, the collection server also goes through an initialisation process, setting up Filter and Source objects to respond to incoming protocol requests, and a Search object to assist in this task. Ultimately these access the indexes and the collection information database, both formed during collection building.</Text>
+<Text id="782">Ignoring blank lines, the receptionist contains 15,000 lines of code. The collection server contains only 5,000 lines (75% of which are taken up by header files). The collection server is more compact because content retrieval is accomplished through two pre-compiled programs. mg, a full-text retrieval system, is used for searching, and gdbm, a database management system, is used to hold the collection information database.</Text>
+<Text id="783">To encourage extensibility and flexibility, Greenstone uses inheritance widelyâin particular, within Action, Filter, Source, and Search. For a simple digital library dedicated to text-based collections, this means that you need to learn slightly more to program the system. However, it also means that mg and gdbm could easily be replaced should the need arise. Furthermore, the software architecture is rich enough to support full multimedia capabilities, such as controlling the interface through speech input, or submitting queries as graphically drawn pictures.</Text>
+</Content>
+</Section>
+<Section id="how_the_conceptual_framework_fits_together">
+<Title>
+<Text id="784">How the conceptual framework fits together</Text>
+</Title>
+<Content>
+<Text id="785">Sections <CrossRef target="Section" ref="collection_server"/> and <CrossRef target="Section" ref="receptionist"/> explain the operation of the collection server and receptionist in more detail, expanding on each module in Figure <CrossRef target="Figure" ref="greenstone_runtime_system"/> and describing how it is implemented. It is helpful to first work through examples of a user interacting with Greenstone, and describe what goes on behind the scenes. For the moment, we assume that all objects are correctly initialised. Initialisation is a rather intricate procedure that we revisit in Section <CrossRef target="Section" ref="initialisation"/>.</Text>
+<Subsection id="performing_a_search">
+<Title>
+<Text id="786">Performing a search</Text>
+</Title>
+<Content>
+<Figure id="searching_gutenberg_for_darcy">
+<Title>
+<Text id="787">Searching Gutenberg for <i>Darcy</i></Text>
+</Title>
+<File width="396" height="353" url="images/Dev_Fig_25.png"/>
+</Figure>
+<Text id="788">When a user enters a query by pressing <i>Begin search</i> on the search page, a new Greenstone action is invoked, which ends up by generating a new html page using the macro language. Figure <CrossRef target="Figure" ref="searching_gutenberg_for_darcy"/> shows the result of searching the Project Gutenberg collection for the name <i>Darcy</i>. Hidden within the html of the original search page is the statement <i>a=q</i>. When the search button is pressed this statement is activated, and sets the new action to be <i>queryaction</i>. Executing <i>queryaction</i> sets up a call to the designated collection's Filter object (<i>c=gberg</i>) through the protocol.</Text>
+<Text id="789">Filters are an important basic function of collection servers. Tailored for both searching and browsing activities, they provide a way of selecting a subset of information from a collection. In this case, the <i>queryaction</i> sets up a filter request by:</Text>
+<BulletList>
+<Bullet>
+<Text id="790">setting the filter request type to be <i>QueryFilter</i>(Section <CrossRef target="Section" ref="collection_server"/> describes the different filter types);</Text>
+</Bullet>
+<Bullet>
+<Text id="791">storing the user's search preferencesâcase-folding, stemming and so onâin the filter request;</Text>
+</Bullet>
+<Bullet>
+<Text id="792">calling the <i>filter()</i> function using the null protocol.</Text>
+</Bullet>
+</BulletList>
+<Text id="793">Calls to the protocol are synchronous. The receptionist is effectively blocked until the filter request has been processed by the collection server and any data generated has been returned.</Text>
+<Text id="794">When a protocol call of type <i>QueryFilter</i> is made, the Filter object (in Figure <CrossRef target="Figure" ref="greenstone_runtime_system"/>) decodes the options and makes a call to the Search object, which uses mg to do the actual search. The role of the Search object is to provide an abstract program interface that supports searching, regardless of the underlying search tool being used. The format used for returning results also enforces abstraction, requiring the Search object to translate the data generated by the search tool into a standard form.</Text>
+<Text id="795">Once the search results have been returned to the receptionist, the action proceeds by formatting the results for display, using the Format object and the Macro Language. As Figure <CrossRef target="Figure" ref="searching_gutenberg_for_darcy"/> shows, this involves generating: the standard Greenstone header, footer, navigation bar and background; repeating the main part of the query page just beneath the navigation bar; and displaying a book icon, title and author for each matching entry. The format of this last part is governed by the <i>format SearchVList</i> statement in the collection configuration file. Before title and author metadata can be displayed, they must be retrieved from the collection server. This requires further calls to the protocol, this time using <i>BrowseFilter</i>.</Text>
+</Content>
+</Subsection>
+<Subsection id="retrieving_a_document">
+<Title>
+<Text id="796">Retrieving a document</Text>
+</Title>
+<Content>
+<Text id="797">Following the above query for <i>Darcy</i>, consider what happens when a document is displayed. Figure <CrossRef target="Figure" ref="the_golf_course_mystery"/> shows the result of clicking on the icon beside <i>The Golf Course Mystery</i> in Figure <CrossRef target="Figure" ref="searching_gutenberg_for_darcy"/>.</Text>
+<Figure id="the_golf_course_mystery">
+<Title>
+<Text id="798"><i>The Golf Course Mystery</i></Text>
+</Title>
+<File width="393" height="349" url="images/Dev_Fig_26.png"/>
+</Figure>
+<Text id="799">The source text for the Gutenberg collection comprises one long file per book. At build time, these files are split into separate pages every 200 lines or so, and relevant information for each page is stored in the indexes and collection information database. The top of Figure <CrossRef target="Figure" ref="the_golf_course_mystery"/> shows that this book contains 104 computer-generated pages, and below it is the beginning of page one: who entered it, the title, the author, and the beginnings of a table of contents (this table forms part of the Gutenberg source text, and was not generated by Greenstone). At the top left are buttons that control the document's appearance: just one page or the whole document; whether query term highlighting is on or off; and whether or not the book should be displayed in its own window, detached from the main searching and browsing activity. At the top right is a navigation aid that supports direct access to any page in the book: simply type in the page number and press the âgo to pageâ button. Alternatively, the next and previous pages are retrieved by clicking on the arrow icons either side of the page selection widget.</Text>
+<Text id="800">The action for retrieving documents, <i>documentaction</i>, is specified by setting <i>a=d</i> and takes several additional arguments. Most important is the document to retrieve: this is specified through the <i>d</i> variable. In Figure <CrossRef target="Figure" ref="the_golf_course_mystery"/> it is set to <i>d=HASH51e598821ed6cbbdf0942b.1</i> to retrieve the first page of the document with the identifier <i>HASH51e598821ed6cbbdf0942b</i>, known in more friendly terms as <i>The Golf Course Mystery</i>. There are further variables: whether query term highlighting is on or off (<i>hl</i>) and which page within a book is displayed (<i>gt</i>). These variables are used to support the activities offered by the buttons on the page in Figure <CrossRef target="Figure" ref="the_golf_course_mystery"/>, described above. Defaults are used if any of these variables are omitted.</Text>
+<Text id="801">The action follows a similar procedure to <i>queryaction</i>: appraise the CGI arguments, access the collection server using the protocol, and use the result to generate a web page. Options relating to the document are decoded from the CGI arguments and stored in the object for further work. To retrieve the document from the collection server, only the document identifier is needed to set up the protocol call to <i>get_document()</i>. Once the text is returned, considerable formatting must be done. To achieve this, the code for <i>documentaction</i> accesses the stored arguments and makes use of the Format object and the Macro Language.</Text>
+</Content>
+</Subsection>
+<Subsection id="browsing_a_hierarchical_classifier">
+<Title>
+<Text id="802">Browsing a hierarchical classifier</Text>
+</Title>
+<Content>
+<Text id="803">Figure <CrossRef target="Figure" ref="browsing_titles_in_the_gutenberg_collection"/> shows an example of browsing, where the user has chosen <i>Titles A-Z</i> and accessed the hyperlink for the letter <i>K</i>. The action that supports this is also <i>documentaction</i>, given by the CGI argument <i>a=d</i> as before. However, whereas before a <i>d</i> variable was included, this time there is none. Instead, the node within the browsable classification hierarchy to display is specified in the variable <i>cl</i>. In our case this represents titles grouped under the letter <i>K</i>. This list was formed at build time and stored in the collection information database.</Text>
+<Figure id="browsing_titles_in_the_gutenberg_collection">
+<Title>
+<Text id="804">Browsing titles in the Gutenberg collection</Text>
+</Title>
+<File width="394" height="351" url="images/Dev_Fig_27.png"/>
+</Figure>
+<Text id="805">Records that represent classifier nodes in the database use the prefix <i>CL</i>, followed by numbers separated by periods (.) to designate where they lie within the nested structure. Ignoring the search button (leftmost in the navigation bar), classifiers are numbered sequentially in increasing order, left to right, starting at 1. Thus the top level classifier node for titles in our example is <i>CL1</i> and the page sought is generated by setting <i>cl=CL1.11</i>. This can be seen in the URL at the top of Figure <CrossRef target="Figure" ref="browsing_titles_in_the_gutenberg_collection"/>.</Text>
+<Text id="806">To process a <i>cl</i> document request, the Filter object is used to retrieve the node over the protocol. Depending on the data returned, further protocol calls are made to retrieve document metadata. In this case, the titles of the books are retrieved. However, if the node were an interior one whose children are themselves nodes, the titles of the child nodes would be retrieved. From a coding point of view this amounts to the same thing, and is handled by the same mechanism.</Text>
+<Text id="807">Finally, all the retrieved information is bound together, using the macro language, to produce the web page shown in Figure <CrossRef target="Figure" ref="browsing_titles_in_the_gutenberg_collection"/>.</Text>
+</Content>
+</Subsection>
+<Subsection id="generating_the_home_page">
+<Title>
+<Text id="808">Generating the home page</Text>
+</Title>
+<Content>
+<Figure id="greenstone_home_page">
+<Title>
+<Text id="809">Greenstone home page</Text>
+</Title>
+<File width="397" height="393" url="images/Dev_Fig_28.png"/>
+</Figure>
+<Text id="810">As a final example, we look at generating the Greenstone home page. Figure <CrossRef target="Figure" ref="greenstone_home_page"/> showsâfor the default Greenstone installation âits home page after some test collections have been installed. Its URL, which you can see at the top of the screen, includes the arguments <i>a=p</i> and <i>p=home</i>. Thus, like the âabout this collectionâ page, it is generated by a <i>pageaction</i> (<i>a=p</i>), but this time the page to produce is <i>home</i>(<i>p=home</i>). The macro language, therefore, accesses the content of <i>home.dm</i>. There is no need to specify a collection (with the <i>c</i> variable) in this case.</Text>
+<Text id="811">The purpose of the home page is to show what collections are available. Clicking on an icon takes the user to the âabout this collectionâ page for that collection. The menu of collections is dynamically generated every time the page is loaded, based on the collections that are in the file system at that time. When a new one comes online, it automatically appears on the home page when that page is reloaded (provided the collection is stipulated to be âpublicâ).</Text>
+<Text id="812">To do this the receptionist uses the protocol (of course). As part of appraising the CGI arguments, <i>pageaction</i> is programmed to detect the special case when <i>p=home</i>. Then, the action uses the protocol call <i>get_collection_list()</i> to establish the current set of online collections. For each of these it calls <i>get_collectinfo()</i> to obtain information about it. This information includes whether the collection is publicly available, what the URL is for the collection's icon (if any), and the collection's full name. This information is used to generate an appropriate entry for the collection on the home page.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="source_code">
+<Title>
+<Text id="813">Source code</Text>
+</Title>
+<Content>
+<Table id="standalone_programs_included_in_greenstone">
+<Title>
+<Text id="814">Standalone programs included in Greenstone</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="815"><i>setpasswd/</i></Text>
+</th>
+<th width="397">
+<Text id="816">Password support for Windows.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="817"><i>getpw/</i></Text>
+</th>
+<th width="397">
+<Text id="818">Password support for Unix.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="819"><i>txt2db/</i></Text>
+</th>
+<th width="397">
+<Text id="820">Convert an XML-like ASCII text format to Gnu's database format.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="821"><i>db2txt/</i></Text>
+</th>
+<th width="397">
+<Text id="822">Convert the Gnu database format to an XML-like ASCII text format.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="823"><i>phind/</i></Text>
+</th>
+<th width="397">
+<Text id="824">Hierarchical phrase browsing tool.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="825"><i>hashfile/</i></Text>
+</th>
+<th width="397">
+<Text id="826">Compute unique document ID based on content of file.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="827"><i>mgpp/</i></Text>
+</th>
+<th width="397">
+<Text id="828">Rewritten and updated version of Managing Gigabytes package in C++.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="829"><i>w32server/</i></Text>
+</th>
+<th width="397">
+<Text id="830">Local library server for Windows.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="831"><i>checkis/</i></Text>
+</th>
+<th width="397">
+<Text id="832">Specific support for installing Greenstone under Windows.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="833">The source code for the runtime system resides in <i>GSDLHOME/src</i>. It occupies two subdirectories, <i>recpt</i> for the receptionist's code and <i>colservr</i> for the collection server's. Greenstone runs on Windows systems right down to Windows 3.1, and unfortunately this imposes an eight-character limit on file and directory names. This explains why cryptic abbreviations like <i>recpt</i> and <i>colservr</i> are used. The remaining subdirectories include standalone utilities, mostly in support of the building process. They are listed in Table <CrossRef target="Table" ref="standalone_programs_included_in_greenstone"/>.</Text>
+<Text id="834">Another directory, <i>GSDLHOME/lib</i>, includes low-level objects that are used by both receptionist and collection server. This code is described in Section <CrossRef target="Section" ref="common_greenstone_types"/>.</Text>
+<Text id="835">Greenstone makes extensive use of the Standard Template Library (STL), a widely-used C++ library from Silicon Graphics (<i>www.sgi.com</i>) that is the result of many years of design and development. Like all programming libraries it takes some time to learn. Appendix A gives a brief overview of key parts that are used throughout the Greenstone code. For a fuller description, consult the official STL reference manual, available online at <i>www.sgi.com</i>, or one of the many STL textbooks, for example Josuttis (1999).</Text>
+</Content>
+</Section>
+<Section id="common_greenstone_types">
+<Title>
+<Text id="836">Common Greenstone types</Text>
+</Title>
+<Content>
+<Text id="837">The objects defined in <i>GSDLHOME/lib</i> are low-level Greenstone objects, built on top of STL, which pervade the entire source code. First we describe <i>text_t</i>, an object used to represent Unicode text, in some detail. Then we summarize the purpose of each library file.</Text>
+<Subsection id="the_text_t_object">
+<Title>
+<Text id="838">The text_t object</Text>
+</Title>
+<Content>
+<Text id="839">Greenstone works with multiple languages, both for the content of a collection and its user interface. To support this, Unicode is used throughout the source code. The underlying object that realises a Unicode string is <i>text_t</i>.</Text>
+<Figure id="the_text_t_api" class="withLineNumber">
+<Title>
+<Text id="840">The <i>text_t</i> API (abridged)</Text>
+</Title>
+<CodeLine>typedef vector&lt;unsigned short&gt; usvector;</CodeLine>
+<CodeLine/>
+<CodeLine>class text_t {</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>usvector text;</CodeLine>
+<CodeLine>unsigned short encoding; // 0 = unicode, 1 = other</CodeLine>
+<CodeLine/>
+<CodeLine>public:</CodeLine>
+<CodeLine>   // constructors</CodeLine>
+<CodeLine>   text_t ();</CodeLine>
+<CodeLine>   text_t (int i);</CodeLine>
+<CodeLine>   text_t (char *s); // assumed to be a normal c string</CodeLine>
+<CodeLine/>
+<CodeLine>   void setencoding (unsigned short theencoding);</CodeLine>
+<CodeLine>   unsigned short getencoding ();</CodeLine>
+<CodeLine/>
+<CodeLine>   // STL container support</CodeLine>
+<CodeLine>   iterator begin ();</CodeLine>
+<CodeLine>   iterator end ();</CodeLine>
+<CodeLine/>
+<CodeLine>   void erase(iterator pos);</CodeLine>
+<CodeLine>   void push_back(unsigned short c);</CodeLine>
+<CodeLine>   void pop_back();</CodeLine>
+<CodeLine/>
+<CodeLine>   void reserve (size_type n);</CodeLine>
+<CodeLine/>
+<CodeLine>   bool empty () const {return text.empty();}</CodeLine>
+<CodeLine>   size_type size() const {return text.size();}</CodeLine>
+<CodeLine/>
+<CodeLine>   // added functionality</CodeLine>
+<CodeLine>   void clear ();</CodeLine>
+<CodeLine>   void append (const text_t &amp;t);</CodeLine>
+<CodeLine/>
+<CodeLine>   // support for integers</CodeLine>
+<CodeLine>   void appendint (int i);</CodeLine>
+<CodeLine>   void setint (int i);</CodeLine>
+<CodeLine>   int getint () const;</CodeLine>
+<CodeLine/>
+<CodeLine>   // support for arrays of chars</CodeLine>
+<CodeLine>   void appendcarr (char *s, size_type len);</CodeLine>
+<CodeLine>   void setcarr (char *s, size_type len);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="841">Unicode uses two bytes to store each character. Figure <CrossRef target="Figure" ref="the_text_t_api"/> shows the main features of the <i>text_t</i> Application Program Interface (API). It fulfils the two-byte requirement using the C++ built-in type <i>short</i>, which is defined to be a two byte integer. The data type central to the <i>text_t</i> object is a dynamic array of unsigned shorts built using the STL declaration <i>vector&lt;unsigned short&gt;</i> and given the abbreviated name <i>usvector</i>.</Text>
+<Text id="842">The constructor functions (lines 10â12) explicitly support three forms of initialisation: construction with no parameters, which generates an empty Unicode string; construction with an integer parameter, which generates a Unicode text version of the numeric value provided; and construction with a <i>char*</i> parameter, which treats the argument as a null-terminated C++ string and generates a Unicode version of it.</Text>
+<Text id="843">Following this, most of the detail (lines 17â28) is taken up maintaining an STL vector-style container: <i>begin()</i>, <i>end()</i>, <i>push_back()</i>, <i>empty()</i> and so forth. There is also support for clearing and appending strings, as well as for converting an integer value into a Unicode text string, and returning the corresponding integer value of text that represents a number.</Text>
+<Figure id="overloaded_operators_to_text_t" class="withLineNumber">
+<Title>
+<Text id="844">Overloaded operators to <i>text_t</i></Text>
+</Title>
+<CodeLine>class text_t {</CodeLine>
+<CodeLine>   // ...</CodeLine>
+<CodeLine>   public:</CodeLine>
+<CodeLine>   text_t &amp;operator=(const text_t &amp;x);</CodeLine>
+<CodeLine>   text_t &amp;operator+= (const text_t &amp;t);</CodeLine>
+<CodeLine>   reference operator[](size_type n);</CodeLine>
+<CodeLine/>
+<CodeLine>   text_t &amp;operator=(int i);</CodeLine>
+<CodeLine>   text_t &amp;operator+= (int i);^ \\</CodeLine>
+<CodeLine>   text_t &amp;operator= (char *s);</CodeLine>
+<CodeLine>   text_t &amp;operator+= (char *s);</CodeLine>
+<CodeLine/>
+<CodeLine>   friend inline bool operator!=(const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>   friend inline bool operator==(const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>   friend inline bool operator&lt; (const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>   friend inline bool operator&gt; (const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>   friend inline bool operator&gt;=(const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>   friend inline bool operator&lt;=(const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>   // ...</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="845">There are many overloaded operators that do not appear in Figure <CrossRef target="Figure" ref="the_text_t_api"/>. To give a flavour of the operations supported, these are shown in Figure <CrossRef target="Figure" ref="overloaded_operators_to_text_t"/>. Line 4 supports assignment of one <i>text_t</i> object to another, and line 5 overloads the <i>+=</i> operator to provide a more natural way to append one <i>text_t</i> object to the end of another. It is also possible, through line 6, to access a particular Unicode character (represented as a <i>short</i>) using array subscripting [ ]. Assign and append operators are also provided for integers and C++ strings. Lines 12â18 provide Boolean operators for comparing two <i>text_t</i> objects: equals, does not equal, precedes alphabetically, and so on.</Text>
+<Text id="846">Member functions that take <i>const</i> arguments instead of non- <i>const</i> ones are also provided (but not shown here). Such repetition is routine in C++ objects, making the API fatter but no bigger conceptually. In reality, many of these functions are implemented as single in-line statements. For more detail, refer to the source file <i>GSDLHOME/lib/text_t.h</i>.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_greenstone_library_code">
+<Title>
+<Text id="847">The Greenstone library code</Text>
+</Title>
+<Content>
+<Text id="848">The header files in <i>GSDLHOME/lib</i> include a mixture of functions and objects that provide useful support for the Greenstone runtime system. Where efficiency is of concern, functions and member functions are declared <i>inline</i>. For the most part, implementation details are contained within a header file's <i>.cpp</i> counterpart.</Text>
+<Table class="hidden">
+<Title/>
+<TableContent>
+<tr>
+<th width="100">
+<Text id="849"><b>cfgread.h</b></Text>
+</th>
+<th width="450">
+<Text id="850">Functions to read and write configuration files. For example, <i>read_cfg_line()</i> takes as arguments the input stream to use and the <i>text_tarray</i> (shorthand for <i>vector&lt;text_t&gt;</i>) to fill out with the data that is read.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="851"><b>display.h</b></Text>
+</th>
+<th width="450">
+<Text id="852">A sophisticated object used by the receptionist for setting, storing and expanding macros, plus supporting types. Section <CrossRef target="Section" ref="receptionist"/> gives further details.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="853"><b>fileutil.h</b></Text>
+</th>
+<th width="450">
+<Text id="854">Function support for several file utilities in an operating system independent way. For example, <i>filename_cat()</i> takes up to six <i>text_t</i> arguments and returns a <i>text_t</i> that is the result of concatenating the items together using the appropriate directory separator for the current operating system.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="855"><b>gsdlconf.h</b></Text>
+</th>
+<th width="450">
+<Text id="856">System-specific functions that answer questions such as: does the operating system being used for compilation need to access <i>strings.h</i> as well as <i>string.h</i>? Are all the appropriate values for file locking correctly defined?</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="857"><b>gsdltimes.h</b></Text>
+</th>
+<th width="450">
+<Text id="858">Function support for date and times. For example, <i>time2text()</i> takes computer time, expressed as the number of seconds that have elapsed since 1 January 1970, and converts it into the form YYYY/MM/DD hh:mm:ss, which it returns as type <i>text_t</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="859"><b>gsdltools.h</b></Text>
+</th>
+<th width="450">
+<Text id="860">Miscellaneous support for the Greenstone runtime system: clarify if littleEndian or bigEndian; check whether Perl is available; execute a system command (with a few bells and whistles); and escape special macro characters in a <i>text_t</i> string.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="861"><b>gsdlunicode.h</b></Text>
+</th>
+<th width="450">
+<Text id="862">A series of inherited objects that support processing Unicode <i>text_t</i> strings through IO streams, such as Unicode to UTF-8 and <i>vice versa</i>; and the removal of zero-width spaces. Support for map files is also provided through the <i>mapconvert</i> object, with mappings loaded from <i>GSDLHOME/mappings</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="863"><b>text_t.h</b></Text>
+</th>
+<th width="450">
+<Text id="864">Primarily the Unicode text object described above. It also provides two classes for converting streams: <i>inconvertclass</i> and <i>outconvertclass</i>. These are the base classes used in <i>gsdlunicode.h</i>.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="collection_server">
+<Title>
+<Text id="865">Collection server</Text>
+</Title>
+<Content>
+<Text id="866">Now we systematically explain all the objects in the conceptual framework of Figure <CrossRef target="Figure" ref="greenstone_runtime_system"/>. We start at the bottom of the diagramâwhich is also the foundations of the systemâwith Search, Source and Filter, and work our way up through the protocol layer and on to the central components in the receptionist: Actions, Format and Macro Language. Then we focus on object initialisation, since this is easier to understand once the role of the various objects is known.</Text>
+<Text id="867">Most of the classes central to the conceptual framework are expressed using virtual inheritance to aid extensibility. With virtual inheritance, inherited objects can be passed around as their base class, but when a member function is called it is the version defined in the inherited object that is invoked. By ensuring that the Greenstone source code uses the base class throughout, except at the point of object construction, this means that different implementationsâusing, perhaps, radically different underlying technologiesâcan be slotted into place easily.</Text>
+<Text id="868">For example, suppose a base class called <i>BaseCalc</i> provides basic arithmetic: add, subtract, multiply and divide. If all its functions are declared virtual, and arguments and return types are all declared as strings, we can easily implement inherited versions of the object. One, called <i>FixedPrecisionCalc</i>, might use C library functions to convert between strings and integers and back again, implementing the calculations using the standard arithmetic operators: <i>+</i>, â, <i>*</i>, and <i>/</i>. Another, called <i>InfinitePrecisionCalc</i>, might access the string arguments a character at a time, implementing arithmetic operations that are in principal infinite in their precision. By writing a main program that uses <i>BaseCalc</i> throughout, the implementation can be switched between fixed precision and infinite precision by editing just one line: the point where the calculator object is constructed.</Text>
+<Subsection id="the_search_object">
+<Title>
+<Text id="869">The Search object</Text>
+</Title>
+<Content>
+<Figure id="search_base_class_api">
+<Title>
+<Text id="870">Search base class API</Text>
+</Title>
+<CodeLine>class searchclass {</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   searchclass ();</CodeLine>
+<CodeLine>   virtual ~searchclass ();</CodeLine>
+<CodeLine>   // the index directory must be set before any searching</CodeLine>
+<CodeLine>   // is done</CodeLine>
+<CodeLine>   virtual void setcollectdir (const text_t &amp;thecollectdir);</CodeLine>
+<CodeLine>   // the search results are returned in queryresults</CodeLine>
+<CodeLine>   // search returns 'true' if it was able to do a search</CodeLine>
+<CodeLine>   virtual bool search(const queryparamclass &amp;queryparams,</CodeLine>
+<CodeLine>                         queryresultsclass &amp;queryresults)=0;</CodeLine>
+<CodeLine>   // the document text for 'docnum' is placed in 'output'</CodeLine>
+<CodeLine>   // docTargetDocument returns 'true' if it was able to</CodeLine>
+<CodeLine>   // try to get a document</CodeLine>
+<CodeLine>   // collection is needed to see if an index from the</CodeLine>
+<CodeLine>   // collection is loaded. If no index has been loaded</CodeLine>
+<CodeLine>   // defaultindex is needed to load one</CodeLine>
+<CodeLine>   virtual bool docTargetDocument(const text_t &amp;defaultindex,</CodeLine>
+<CodeLine>                                               const text_t &amp;defaultsubcollection,</CodeLine>
+<CodeLine>                                               const text_t &amp;defaultlanguage,</CodeLine>
+<CodeLine>                                               const text_t &amp;collection,</CodeLine>
+<CodeLine>                                               int docnum,</CodeLine>
+<CodeLine>                                               text_t &amp;output)=0;</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>   querycache *cache;</CodeLine>
+<CodeLine>   text_t collectdir; // the collection directory</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="871">Figure <CrossRef target="Figure" ref="search_base_class_api"/> shows the base class API for the Search object in Figure <CrossRef target="Figure" ref="greenstone_runtime_system"/>. It defines two virtual member functions: <i>search()</i> and <i>docTargetDocument()</i>. As signified by the <i>=0</i> that follows the argument declaration, these are <i>pure</i> functionsâmeaning that a class that inherits from this object must implement both (otherwise the compiler will complain).</Text>
+<Text id="872">The class also includes two protected data fields: <i>collectdir</i> and <i>cache</i>. A Search object is instantiated for a particular collection, and the <i>collectdir</i> field is used to store where on the file system that collection (and more importantly its index files) resides. The <i>cache</i> field retains the result of a query. This is used to speed up subsequent queries that duplicate the query (and its settings). While identical queries may seem unlikely, in fact they occur on a regular basis. The Greenstone protocol is stateless. To generate a results page like Figure <CrossRef target="Figure" ref="searching_gutenberg_for_darcy"/> but for matches 11â20 of the same query, the search is transmitted again, this time specifying that documents 11â20 are returned. Caching makes this efficient, because the fact that the search has already been performed is detected and the results are lifted straight from the cache.</Text>
+<Text id="873">Both data fields are applicable to every inherited object that implements a searching mechanism. This is why they appear in the base class, and are declared within a protected section of the class so that inherited classes can access them directly.</Text>
+</Content>
+</Subsection>
+<Subsection id="search_and_retrieval_with_mg">
+<Title>
+<Text id="874">Search and retrieval with MG</Text>
+</Title>
+<Content>
+<Text id="875">Greenstone uses MG (short for Managing Gigabytes, see Witten <i>et al</i>., 1999) to index and retrieve documents, and the source code is included in the <i>GSDLHOME/packages</i> directory. MG uses compression techniques to maximise disk space utilisation without compromising execution speed. For a collection of English documents, the compressed text and full text indexes together typically occupy one third the space of the original uncompressed text alone. Search and retrieval is often quicker than the equivalent operation on the uncompressed version, because there are fewer disk operations.</Text>
+<Figure id="api_for_direct_access_to_mg">
+<Title>
+<Text id="876">API for direct access to MG (abridged)</Text>
+</Title>
+<CodeLine>enum result_kinds {</CodeLine>
+<CodeLine>   result_docs,           // Return the documents found in last search</CodeLine>
+<CodeLine>   result_docnums,     // Return document id numbers and weights</CodeLine>
+<CodeLine>   result_termfreqs, // Return terms and frequencies</CodeLine>
+<CodeLine>   result_terms           // Return matching query terms</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine>int mgq_ask(char *line);</CodeLine>
+<CodeLine>int mgq_results(enum result_kinds kind, int skip, int howmany,</CodeLine>
+<CodeLine>                               int (*sender)(char *, int, int, float, void *),</CodeLine>
+<CodeLine>                               void *ptr);</CodeLine>
+<CodeLine>int mgq_numdocs(void);</CodeLine>
+<CodeLine>int mgq_numterms(void);</CodeLine>
+<CodeLine>int mgq_equivterms(unsigned char *wordstem,</CodeLine>
+<CodeLine>                           int (*sender)(char *, int, int, float, void *),</CodeLine>
+<CodeLine>                           void *ptr);</CodeLine>
+<CodeLine>int mgq_docsretrieved (int *total_retrieved, int *is_approx);</CodeLine>
+<CodeLine>int mgq_getmaxstemlen ();</CodeLine>
+<CodeLine>void mgq_stemword (unsigned char *word);</CodeLine>
+</Figure>
+<Text id="877">MG is normally used interactively by typing commands from the command line, and one way to implement <i>mgsearchclass</i> would be to use the C library <i>system()</i> call within the object to issue the appropriate mg commands. A more efficient approach, however, is to tap directly into the mg code using function calls. While this requires a deeper understanding of the mg code, much of the complexity can be hidden behind a new API that becomes the point of contact for the object <i>mgsearchclass</i>. This is the role of <i>colserver/mgq.c</i>, whose API is shown in Figure <CrossRef target="Figure" ref="api_for_direct_access_to_mg"/>.</Text>
+<Text id="878">The way to supply parameters to mg is via <i>mgq_ask()</i>, which takes text options in a format identical to that used at the command line, such as:</Text>
+<CodeLine>mgq_ask( ".set casefold off ");</CodeLine>
+<Text id="879">It is also used to invoke a query. Results are accessed through <i>mgq_results</i>, which takes a pointer to a function as its fourth parameter. This provides a flexible way of converting the information returned in mg data structures into those needed by <i>mgsearchclass</i>. Calls such as <i>mgq_numdocs()</i>, <i>mgq_numterms()</i>, and <i>mgq_docsretrieved()</i> also return information, but this time more tightly prescribed. The last two give support for stemming.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_source_object">
+<Title>
+<Text id="880">The Source object</Text>
+</Title>
+<Content>
+<Figure id="source_base_class_api">
+<Title>
+<Text id="881">Source base class API</Text>
+</Title>
+<CodeLine>class sourceclass {</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   sourceclass ();</CodeLine>
+<CodeLine>   virtual ~sourceclass ();</CodeLine>
+<CodeLine>   // configure should be called once for each configuration line</CodeLine>
+<CodeLine>   virtual void configure (const text_t &amp;key, const text_tarray &amp;cfgline);</CodeLine>
+<CodeLine>   // init should be called after all the configuration is done but</CodeLine>
+<CodeLine>   // before any other methods are called</CodeLine>
+<CodeLine>   virtual bool init (ostream &amp;logout);</CodeLine>
+<CodeLine>   // translate_OID translates OIDs using " .pr " , . " fc " etc.</CodeLine>
+<CodeLine>   virtual bool translate_OID (const text_t &amp;OIDin, text_t &amp;OIDout, comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   // get_metadata fills out the metadata if possible, if it is not</CodeLine>
+<CodeLine>   // responsible for the given OID then it return s false.</CodeLine>
+<CodeLine>   virtual bool get_metadata (const text_t &amp;requestParams, const text_t &amp;refParams,</CodeLine>
+<CodeLine>                           bool getParents, const text_tset &amp;fields, const text_t &amp;OID,</CodeLine>
+<CodeLine>                           MetadataInfo_tmap &amp;metadata, comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual bool get_document (const text_t &amp;OID, text_t &amp;doc, </CodeLine>
+<CodeLine>                           comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="882">The role of Source in Figure <CrossRef target="Figure" ref="greenstone_runtime_system"/> is to access document metadata and document text, and its base class API is shown in Figure <CrossRef target="Figure" ref="source_base_class_api"/>. A member function maps to each task: <i>get_metadata()</i> and <i>get_document()</i> respectively. Both are declared <i>virtual</i>, so the version provided by a particular implementation of the base class is called at runtime. One inherited version of this object uses gdbm to implement <i>get_metadata()</i> and mg to implement <i>get_document()</i>: we detail this version below.</Text>
+<Text id="883">Other member functions seen in Figure <CrossRef target="Figure" ref="source_base_class_api"/> are <i>configure()</i>, <i>init()</i>, and <i>translate_OID()</i>. The first two relate to the initialisation process described in Section <CrossRef target="Section" ref="initialisation"/>.</Text>
+<Text id="884">The remaining one, <i>translate_OID()</i>, handles the syntax for expressing document identifiers. In Figure <CrossRef target="Figure" ref="the_golf_course_mystery"/> we saw how a page number could be appended to a document identifier to retrieve just that page. This was possible because pages were stored as âsectionsâ when the collection was built. Appending â.1â to an OID retrieves the first section of the corresponding document. Sections can be nested, and are accessed by concatenating section numbers separated by periods.</Text>
+<Text id="885">As well as hierarchical section numbers, the document identifier syntax supports a form of relative access. For the current section of a document it is possible to access the <i>first child</i> by appending <i>.fc</i>, the <i>last child</i> by appending <i>.lc</i>, the <i>parent</i> by appending <i>.pr</i>, the <i>next sibling</i> by appending <i>.ns</i>, and the <i>previous sibling</i> by appending <i>.ps</i>.</Text>
+<Text id="886">The <i>translate_OID()</i> function uses parameters <i>OIDin</i> and <i>OIDout</i> to hold the source and result of the conversion. It takes two further parameters, <i>err</i> and <i>logout</i>. These communicate any error status that may arise during the translation operation, and determine where to send logging information. The parameters are closely aligned with the protocol, as we shall see in Section <CrossRef target="Section" ref="protocol"/>.</Text>
+<Part id="database_retrieval_with_gdbm">
+<Title>
+<Text id="887">Database retrieval with gdbm</Text>
+</Title>
+<Content>
+<Text id="888">GDBM is the Gnu database manager program (<i>www.gnu.org</i>). It implements a flat record structure of key/data pairs, and is backwards compatible with dbm and ndbm. Operations include storage, retrieval and deletion of records by key, and an unordered traversal of all keys.</Text>
+<Figure id="gdbm_database_for_the_gutenberg_collection">
+<Title>
+<Text id="889">Gdbm database for the Gutenberg collection (excerpt)</Text>
+</Title>
+<CodeLine>[HASH01d7b30d4827b51282919e9b]</CodeLine>
+<CodeLine>&lt;doctype&gt;         doc</CodeLine>
+<CodeLine>&lt;hastxt&gt;           0</CodeLine>
+<CodeLine>&lt;Title&gt;             The Winter's Tale</CodeLine>
+<CodeLine>&lt;Creator&gt;         William Shakespeare</CodeLine>
+<CodeLine>&lt;archivedir&gt;   HASH01d7/b30d4827.dir</CodeLine>
+<CodeLine>&lt;thistype&gt;       Invisible</CodeLine>
+<CodeLine>&lt;childtype&gt;     Paged</CodeLine>
+<CodeLine>&lt;contains&gt;        " .1; " .2; " .3; " .4; " .5; " .6; " .7; " .8; " .9; " .10; " .11; " .12;            \ <br/>                           " .13; " .14; " .15; " .16; " .17; " .18; " .19; " .20; " .21; " .22;            \ <br/>                           " .23; " .24; " .25; " .26; " .27; " .28; " .29; " .30; " .31; " .32;            \ <br/>                           " .33; " .34; " .35</CodeLine>
+<CodeLine>&lt;docnum&gt;           168483</CodeLine>
+<CodeLine>âââââââââââââââââââââââ-</CodeLine>
+<CodeLine>[CL1]</CodeLine>
+<CodeLine>&lt;doctype&gt;         classify</CodeLine>
+<CodeLine>&lt;hastxt&gt;           0</CodeLine>
+<CodeLine>&lt;childtype&gt;     HList</CodeLine>
+<CodeLine>&lt;Title&gt;             Title</CodeLine>
+<CodeLine>&lt;numleafdocs&gt; 1818</CodeLine>
+<CodeLine>&lt;thistype&gt;       Invisible</CodeLine>
+<CodeLine>&lt;contains&gt;       " .1; " .2; " .3; " .4; " .5; " .6; " .7; " .8; " .9; " .10; " .11; " .12;          \ <br/>                           " .13; " .14; " .15; " .16; " .17; " .18; " .19; " .20; " .21; " .22;          \ <br/>                            " .23; " .24</CodeLine>
+<CodeLine>âââââââââââââââââââââââ-</CodeLine>
+<CodeLine>[CL1.1]</CodeLine>
+<CodeLine>&lt;doctype&gt;         classify</CodeLine>
+<CodeLine>&lt;hastxt&gt;           0</CodeLine>
+<CodeLine>&lt;childtype&gt;     VList</CodeLine>
+<CodeLine>&lt;Title&gt;             A</CodeLine>
+<CodeLine>&lt;numleafdocs&gt; 118</CodeLine>
+<CodeLine>&lt;contains&gt;      HASH0130bc5f9f90089b3723431f;HASH9cba43bacdab5263c98545;\</CodeLine>
+<CodeLine>                          HASH12c88a01da6e8379df86a7;HASH9c86579a83e1a2e4cf9736;   \</CodeLine>
+<CodeLine>                           HASHdc2951a7ada1f36a6c3aca;HASHea4dda6bbc7cdeb4abfdee;   \</CodeLine>
+<CodeLine>                          HASHce55006513c47235ac38ba;HASH012a33acaa077c0e612b9351;\</CodeLine>
+<CodeLine>                          HASH010dd1e923a123826ae30e4b;HASHaf674616785679fed4b7ee;\</CodeLine>
+<CodeLine>                         HASH0147eef4b9d1cb135e096619;HASHe69b9dbaa83ffb045d963b;\</CodeLine>
+<CodeLine>                         HASH01abc61c646c8e7a8ce88b10;HASH5f9cd13678e21820e32f3a;\</CodeLine>
+<CodeLine>                         HASHe8cbba1594c72c98f9aa1b;HASH01292a2b7b6b60dec96298bc;\</CodeLine>
+<CodeLine>                         ...</CodeLine>
+</Figure>
+<Text id="890">Figure <CrossRef target="Figure" ref="gdbm_database_for_the_gutenberg_collection"/> shows an excerpt from the collection information database that is created when building the Gutenberg collection. The excerpt was produced using the Greenstone utility <i>db2txt</i>, which converts the gdbm binary database format into textual form. Figure <CrossRef target="Figure" ref="gdbm_database_for_the_gutenberg_collection"/> contains three records, separated by horizontal rules. The first is a document entry, the other two are part of the hierarchy created by the <i>AZList</i> classifier for titles in the collection. The first line of each record is its key.</Text>
+<Text id="891">The document record stores the book's title, author, and any other metadata provided (or extracted) when the collection was built. It also records values for internal use: where files associated with this document reside (<i>&lt;archivedir&gt;</i>) and the document number used internally by mg (<i>&lt;docnum&gt;</i>).</Text>
+<Text id="892">The <i>&lt;contains&gt;</i> field stores a list of elements, separated by semicolons, that point to related records in the database. For a document record, <i>&lt;contains&gt;</i> is used to point to the nested sections. Subsequent record keys are formed by concatenating the current key with one of the child elements (separated by a period).</Text>
+<Text id="893">The second record in Figure <CrossRef target="Figure" ref="gdbm_database_for_the_gutenberg_collection"/> is the top node for the classification hierarchy of <i>Titles AâZ</i>. Its children, accessed through the <i>&lt;contains&gt;</i> field, include <i>CL1.1</i>, <i>CL1.2</i>, <i>CL1.3</i> and so on, and correspond to the individual pages for the letters <i>A</i>, <i>B</i>, <i>C</i> etc. There are only 24 children: the <i>AZList</i> classifier merged the <i>QâR</i> and <i>YâZ</i> entries because they covered only a few titles.</Text>
+<Text id="894">The children in the <i>&lt;contains&gt;</i> field of the third record, <i>CL1.1</i>, are the documents themselves. More complicated structures are possibleâthe <i>&lt;contains&gt;</i> field can include a mixture of documents and further <i>CL</i> nodes. Keys expressed relative to the current one are distinguished from absolute keys because they begin with a quotation mark (").</Text>
+</Content>
+</Part>
+<Part id="using_mg_and_gdbm_to_implement_a_source_object">
+<Title>
+<Text id="895">Using MG and GDBM to implement a Source object</Text>
+</Title>
+<Content>
+<Figure id="api_for_mg_and_gdbm_based_version_of_sourceclass">
+<Title>
+<Text id="896">API for mg and gdbm based version of <i>sourceclass</i> (abridged)</Text>
+</Title>
+<CodeLine>class mggdbmsourceclass : public sourceclass {</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>   // Omitted, data fields that store:</CodeLine>
+<CodeLine>   //     collection specific file information</CodeLine>
+<CodeLine>   //     index substructure</CodeLine>
+<CodeLine>   //     information about parent</CodeLine>
+<CodeLine>   //     pointers to gdbm and mgsearch objects</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   mggdbmsourceclass ();</CodeLine>
+<CodeLine>   virtual ~mggdbmsourceclass ();</CodeLine>
+<CodeLine>   void set_gdbmptr (gdbmclass *thegdbmptr);</CodeLine>
+<CodeLine>   void set_mgsearchptr (searchclass *themgsearchptr);</CodeLine>
+<CodeLine>   void configure (const text_t &amp;key, const text_tarray &amp;cfgline);</CodeLine>
+<CodeLine>   bool init (ostream &amp;logout);</CodeLine>
+<CodeLine>   bool translate_OID (const text_t &amp;OIDin, text_t &amp;OIDout,</CodeLine>
+<CodeLine>                                           comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   bool get_metadata (const text_t &amp;requestParams,</CodeLine>
+<CodeLine>                                           const text_t &amp;refParams,</CodeLine>
+<CodeLine>                                         bool getParents, const text_tset &amp;fields,</CodeLine>
+<CodeLine>                                         const text_t &amp;OID, MetadataInfo_tmap &amp;metadata,</CodeLine>
+<CodeLine>                                         comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   bool get_document (const text_t &amp;OID, text_t &amp;doc,</CodeLine>
+<CodeLine>                                         comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="897">The object that puts mg and gdbm together to realise an implementation of <i>sourceclass</i> is <i>mggdbmsourceclass</i>. Figure <CrossRef target="Figure" ref="api_for_mg_and_gdbm_based_version_of_sourceclass"/> shows its API. The two new member functions <i>set_gdbmptr()</i> and <i>set_mgsearchptr()</i> store pointers to their respective objects, so that the implementations of <i>get_metadata()</i> and <i>get_document()</i> can access the appropriate tools to complete the job.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="the_filter_object">
+<Title>
+<Text id="898">The Filter object</Text>
+</Title>
+<Content>
+<Figure id="api_for_the_filter_base_class">
+<Title>
+<Text id="899">API for the Filter base class</Text>
+</Title>
+<CodeLine>class filterclass {</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>   text_t gsdlhome;</CodeLine>
+<CodeLine>   text_t collection;</CodeLine>
+<CodeLine>   text_t collectdir;</CodeLine>
+<CodeLine>   FilterOption_tmap filterOptions;</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   filterclass ();</CodeLine>
+<CodeLine>   virtual ~filterclass ();</CodeLine>
+<CodeLine>   virtual void configure (const text_t &amp;key,Â const text_tarray &amp;cfgline);</CodeLine>
+<CodeLine>   virtual bool init (ostream &amp;logout);</CodeLine>
+<CodeLine>   // returns the name of this filter</CodeLine>
+<CodeLine>   virtual text_t get_filter_name ();</CodeLine>
+<CodeLine>   // returns the current filter options</CodeLine>
+<CodeLine>   virtual void get_filteroptions (InfoFilterOptionsResponse_t &amp;response,</CodeLine>
+<CodeLine>                                 comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void filter (const FilterRequest_t &amp;request,</CodeLine>
+<CodeLine>                         FilterResponse_t &amp;response,</CodeLine>
+<CodeLine>                         comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="900">The base class API for the Filter object in Figure <CrossRef target="Figure" ref="greenstone_runtime_system"/> is shown in Figure <CrossRef target="Figure" ref="api_for_the_filter_base_class"/>. It begins with the protected data fields <i>gsdlhome</i>, <i>collection</i>, and <i>collectdir</i>. These commonly occur in classes that need to access collection-specific files.</Text>
+<BulletList>
+<Bullet>
+<Text id="901"><i>gsdlhome</i> is the same as <i>GSDLHOME</i>, so that the object can locate the Greenstone files.</Text>
+</Bullet>
+<Bullet>
+<Text id="902"><i>collection</i> is the name of the directory corresponding to the collection.</Text>
+</Bullet>
+<Bullet>
+<Text id="903"><i>collectdir</i> is the full pathname of the collection directory (this is needed because a collection does not have to reside within the <i>GSDLHOME</i> area).</Text>
+</Bullet>
+</BulletList>
+<Text id="904"><i>mggdbsourceclass</i> is another class that includes these three data fields.</Text>
+<Text id="905">The member functions <i>configure()</i> and <i>init()</i> (first seen in <i>sourceclass</i>) are used by the initialisation process. The object itself is closely aligned with the corresponding filter part of the protocol; in particular <i>get_filteroptions()</i> and <i>filter()</i> match one for one.</Text>
+<Figure id="how_a_filter_option_is_stored">
+<Title>
+<Text id="906">How a filter option is stored</Text>
+</Title>
+<CodeLine>struct FilterOption_t {</CodeLine>
+<CodeLine>   void clear (); \   void check_defaultValue ();</CodeLine>
+<CodeLine>   FilterOption_t () {clear();}</CodeLine>
+<CodeLine>   text_t name;</CodeLine>
+<CodeLine>   enum type_t {booleant=0, integert=1, enumeratedt=2, stringt=3};</CodeLine>
+<CodeLine>   type_t type;</CodeLine>
+<CodeLine>   enum repeatable_t {onePerQuery=0, onePerTerm=1, nPerTerm=2};</CodeLine>
+<CodeLine>   repeatable_t repeatable;</CodeLine>
+<CodeLine>   text_t defaultValue;</CodeLine>
+<CodeLine>   text_tarray validValues;</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine>struct OptionValue_t {</CodeLine>
+<CodeLine>   void clear ();</CodeLine>
+<CodeLine>   text_t name;</CodeLine>
+<CodeLine>   text_t value;</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="907">Central to the filter options are the two classes shown in Figure <CrossRef target="Figure" ref="how_a_filter_option_is_stored"/>. Stored inside <i>FilterOption_t</i> is the <i>name</i> of the option, its <i>type</i>, and whether or not it is <i>repeatable</i>. The interpretation of <i>validValues</i> depends on the option type. For a Boolean type the first value is <i>false</i> and the second is <i>true</i>. For an integer type the first value is the minimum number, the second the maximum. For an enumerated type all values are listed. For a string type the value is ignored. For simpler situations, <i>OptionValue_t</i> is used, which records as a <i>text_t</i> the <i>name</i> of the option and its <i>value</i>.</Text>
+<Text id="908">The request and response objects passed as parameters to <i>filterclass</i> are constructed from these two classes, using associative arrays to store a set of options such as those required for <i>InfoFilterOptionsResponse_t</i>. More detail can be found in <i>GSDLHOME/src/recpt/comtypes.h</i>.</Text>
+</Content>
+</Subsection>
+<Subsection id="inherited_filter_objects">
+<Title>
+<Text id="909">Inherited Filter objects</Text>
+</Title>
+<Content>
+<Figure id="inheritance_hierarchy_for_filter">
+<Title>
+<Text id="910">Inheritance hierarchy for Filter</Text>
+</Title>
+<File width="337" height="245" url="images/Dev_Fig_38.gif"/>
+</Figure>
+<Text id="911">Two levels of inheritance are used for filters, as illustrated in Figure <CrossRef target="Figure" ref="inheritance_hierarchy_for_filter"/>. First a distinction is made between Query and Browse filters, and then for the former there is a specific implementation based on mg. To operate correctly, <i>mgqueryfilterclass</i> needs access to mg through <i>mgsearchclass</i> and to gdbm through <i>gdbmclass</i>. <i>browsefilterclass</i> only needs access to gdbm. Pointers to these objects are stored as protected data fields within the respective classes.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_collection_server_code">
+<Title>
+<Text id="912">The collection server code</Text>
+</Title>
+<Content>
+<Text id="913">Here are the header files in <i>GSDLHOME/src/colservr</i>, with a description of each. The filename generally repeats the object name defined within it.</Text>
+<Table class="hidden">
+<Title/>
+<TableContent>
+<tr>
+<th width="120">
+<Text id="914"><b>browsefilter.h</b></Text>
+</th>
+<th width="420">
+<Text id="915">Inherited from <i>filterclass</i>, this object provides access to gdbm. (Described above.)</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="916"><b>collectserver.h</b></Text>
+</th>
+<th width="420">
+<Text id="917">This object binds Filters and Sources for one collection together, to form the Collection object depicted in Figure <CrossRef target="Figure" ref="greenstone_runtime_system"/>.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="918"><b>colservrconfig.h</b></Text>
+</th>
+<th width="420">
+<Text id="919">Function support for reading the collection-specific files <i>etc/collect.cfg</i> and <i>index/build.cfg</i>. The former is the collection's configuration file. The latter is a file generated by the building process that records the time of the last successful build, an index map list, how many documents were indexed, and how large they are in bytes (uncompressed).</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="920"><b>filter.h</b></Text>
+</th>
+<th width="420">
+<Text id="921">The base class Filter object <i>filterclass</i> described above.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="922"><b>maptools.h</b></Text>
+</th>
+<th width="420">
+<Text id="923">Defines a class called <i>stringmap</i> that provides a mapping that remembers the original order of a <i>text_t</i> map, but is fast to look up. Used in <i>mggdbmsourceclass</i> and <i>queryfilterclass</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="924"><b>mggdbmsource.h</b></Text>
+</th>
+<th width="420">
+<Text id="925">Inherited from <i>sourceclass</i>, this object provides access to mg and gdbm. (Described above.)</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="926"><b>mgppqueryfilter.h</b></Text>
+</th>
+<th width="420">
+<Text id="927">Inherited from <i>queryfilterclass</i>, this object provides an implementation of <i>QueryFilter</i> based upon mg++, an improved version of mg written in C++. Note that Greenstone is set up to use mg by default, since mg++ is still under development.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="928"><b>mgppsearch.h</b></Text>
+</th>
+<th width="420">
+<Text id="929">Inherited from <i>searchclass</i>, this object provides an implementation of Search using mg++. Like <i>mgppqueryfilterclass</i>, this is not used by default.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="930"><b>mgq.h</b></Text>
+</th>
+<th width="420">
+<Text id="931">Function-level interface to the mg package. Principal functions are <i>mg_ask()</i> and <i>mg_results()</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="932"><b>mgqueryfilter.h</b></Text>
+</th>
+<th width="420">
+<Text id="933">Inherited from <i>queryfilterclass</i>, this object provides an implementation of <i>QueryFilter</i> based upon mg.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="934"><b>mgsearch.h</b></Text>
+</th>
+<th width="420">
+<Text id="935">Inherited from <i>searchclass</i>, this object provides an implementation of Search using mg. (Described above.)</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="936"><b>phrasequeryfilter.h</b></Text>
+</th>
+<th width="420">
+<Text id="937">Inherited from <i>mgqueryclass</i>, this object provides a phrase-based query class. It is not used in the default installation. Instead <i>mgqueryfilterclass</i> provides this capability through functional support from <i>phrasesearch.h</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="938"><b>phrasesearch.h</b></Text>
+</th>
+<th width="420">
+<Text id="939">Functional support to implement phrase searching as a post-processing operation.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="940"><b>querycache.h</b></Text>
+</th>
+<th width="420">
+<Text id="941">Used by <i>searchclass</i> and its inherited classes to cache the results of a query, in order to make the generation of further search results pages more efficient. (Described above.)</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="942"><b>queryfilter.h</b></Text>
+</th>
+<th width="420">
+<Text id="943">Inherited from the Filter base class <i>filterclass</i>, this object establishes a base class for Query filter objects. (Described above.)</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="944"><b>queryinfo.h</b></Text>
+</th>
+<th width="420">
+<Text id="945">Support for searching: data structures and objects to hold query parameters, document results and term frequencies.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="946"><b>search.h</b></Text>
+</th>
+<th width="420">
+<Text id="947">The base class Search object <i>searchclass</i>. (Described above.)</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="948"><b>source.h</b></Text>
+</th>
+<th width="420">
+<Text id="949">The base class Source object <i>sourceclass</i>. (Described above.)</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="protocol">
+<Title>
+<Text id="950">Protocol</Text>
+</Title>
+<Content>
+<Table id="list_of_protocol_calls">
+<Title>
+<Text id="951">List of protocol calls</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="952"><i>get_protocol_name()</i></Text>
+</th>
+<th width="397">
+<Text id="953">Returns the name of this protocol. Choices include <i>nullproto</i>, <i>corbaproto</i>, and <i>z3950proto</i>. Used by protocol-sensitive parts of the runtime system to decide which code to execute.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="954"><i>get_collection_list()</i></Text>
+</th>
+<th width="397">
+<Text id="955">Returns the list of collections that this protocol knows about.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="956"><i>has_collection()</i></Text>
+</th>
+<th width="397">
+<Text id="957">Returns <i>true</i> if the protocol can communicate with the named collection, i.e. it is within its collection list.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="958"><i>ping()</i></Text>
+</th>
+<th width="397">
+<Text id="959">Returns <i>true</i> if a successful connection was made to the named collection. In the null protocol the implementation is identical to <i>has_collection().</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="960"><i>get_collectinfo()</i></Text>
+</th>
+<th width="397">
+<Text id="961">Obtains general information about the named collection: when it was last built, how many documents it contains, and so on. Also includes metadata from the collection configuration file: âabout this collectionâ text; the collection icon to use, and so on.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="962"><i>get_filterinfo()</i></Text>
+</th>
+<th width="397">
+<Text id="963">Gets a list of all Filters for the named collection.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="964"><i>get_filteroptions()</i></Text>
+</th>
+<th width="397">
+<Text id="965">Gets all options for a particular Filter within the named collection.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="966"><i>filter()</i></Text>
+</th>
+<th width="397">
+<Text id="967">Supports searching and browsing. For a given filter type and option settings, it accesses the content of the named collections to produce a result set that is filtered in accordance with the option settings. The data fields returned also depend on the option settings: examples include query term frequency and document metadata.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="968"><i>get_document()</i></Text>
+</th>
+<th width="397">
+<Text id="969">Gets a document or section of a document.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="970"><CrossRef target="Table" ref="list_of_protocol_calls"/> lists the function calls to the protocol, with a summary for each entry. The examples in Section <CrossRef target="Section" ref="how_the_conceptual_framework_fits_together"/> covered most of these. Functions not previously mentioned are <i>has_collection()</i>, <i>ping()</i>, <i>get_protocol_name()</i> and <i>get_filteroptions()</i>. The first two provide yes/no answers to the questions âdoes the collection exists on this server?â and âis it running?â respectively. The purpose of the other two is to support multiple protocols within an architecture that is distributed over different computers, not just the null-protocol based single executable described here. One of these distinguishes which protocol is being used. The other lets a receptionist interrogate a collection server to find what options are supported, and so dynamically configure itself to take full advantage of the services offered by a particular server.</Text>
+<Figure id="null_protocol_api">
+<Title>
+<Text id="971">Null protocol API (abridged)</Text>
+</Title>
+<CodeLine>class nullproto : public recptproto {</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   virtual text_t get_protocol_name ();</CodeLine>
+<CodeLine>   virtual void get_collection_list (text_tarray &amp;collist,</CodeLine>
+<CodeLine>                comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void has_collection (const text_t &amp;collection,</CodeLine>
+<CodeLine>                bool &amp;hascollection,</CodeLine>
+<CodeLine>                comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void ping (const text_t &amp;collection,</CodeLine>
+<CodeLine>                  bool &amp;wassuccess,</CodeLine>
+<CodeLine>                  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void get_collectinfo (const text_t &amp;collection,</CodeLine>
+<CodeLine>                  ColInfoResponse_t &amp;collectinfo,</CodeLine>
+<CodeLine>                  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void get_filterinfo (const text_t &amp;collection,</CodeLine>
+<CodeLine>                   InfoFiltersResponse_t &amp;response,</CodeLine>
+<CodeLine>                   comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void get_filteroptions (const text_t &amp;collection,</CodeLine>
+<CodeLine>                   const InfoFilterOptionsRequest_t &amp;request,</CodeLine>
+<CodeLine>                   InfoFilterOptionsResponse_t &amp;response,</CodeLine>
+<CodeLine>                   comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void filter (const text_t &amp;collection,</CodeLine>
+<CodeLine>                   FilterRequest_t &amp;request,</CodeLine>
+<CodeLine>                   FilterResponse_t &amp;response,</CodeLine>
+<CodeLine>                   comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void get_document (const text_t &amp;collection,</CodeLine>
+<CodeLine>                  const DocumentRequest_t &amp;request,</CodeLine>
+<CodeLine>                  DocumentResponse_t &amp;response,</CodeLine>
+<CodeLine>                  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="972">Figure <CrossRef target="Figure" ref="null_protocol_api"/> shows the API for the null protocol. Comments, and certain low level details, have been omitted (see the source file <i>recpt/nullproto.h</i> for full details).</Text>
+<Text id="973">This protocol inherits from the base class <i>recptproto</i>. Virtual inheritance is used so that more than one type of protocolâincluding protocols not even conceived yetâcan be easily supported in the rest of the source code. This is possible because the base class object <i>recptproto</i> is used throughout the source code, with the exception of the point of construction. Here we specify the actual variety of protocol we wish to useâin this case, the null protocol.</Text>
+<Text id="974">With the exception of <i>get_protocol_name()</i>, which takes no parameters and returns the protocol name as a Unicode-compliant text string, all protocol functions include an error parameter and an output stream as the last two arguments. The error parameter records any errors that occur during the execution of the protocol call, and the output stream is for logging purposes. The functions have type <i>void</i>âthey do not explicitly return information as their final statement, but instead return data through designated parameters such as the already-introduced error parameter. In some programming languages, such routines would be defined as procedures rather than functions, but C++ makes no syntactic distinction.</Text>
+<Text id="975">Most functions take the collection name as an argument. Three of the member functions, <i>get_filteroptions()</i>, <i>filter()</i>, and <i>get_document()</i>, follow the pattern of providing a Request parameter and receiving the results in a Response parameter.</Text>
+</Content>
+</Section>
+<Section id="receptionist">
+<Title>
+<Text id="976">Receptionist</Text>
+</Title>
+<Content>
+<Text id="977">The final layer of the conceptual model is the receptionist. Once the CGI arguments are parsed, the main activity is the execution of an Action, supported by the Format and Macro Language objects. These are described below. Although they are represented as objects in the conceptual framework, Format and Macro Language objects are not strictly objects in the C++ sense. In reality, Format is a collection of data structures with a set of functions that operate on them, and the Macro Language object is built around <i>displayclass</i>, defined in <i>lib/display.h</i>, with stream conversion support from <i>lib/gsdlunicode.h</i>.</Text>
+<Subsection id="actions">
+<Title>
+<Text id="978">Actions</Text>
+</Title>
+<Content>
+<Table id="actions_in_greenstone">
+<Title>
+<Text id="979">Actions in Greenstone</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="980"><i>action</i></Text>
+</th>
+<th width="397">
+<Text id="981">Base class for virtual inheritance.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="982"><i>authenaction</i></Text>
+</th>
+<th width="397">
+<Text id="983">Supports user authentication: prompts the user for a password if one has not been entered; checks whether it is valid; and forces the user to log in again if sufficient time lapses between accesses.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="984"><i>collectoraction</i></Text>
+</th>
+<th width="397">
+<Text id="985">Generates the pages for the Collector.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="986"><i>documentaction</i></Text>
+</th>
+<th width="397">
+<Text id="987">Retrieves documents, document sections, parts of the classification hierarchy, or formatting information.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="988"><i>extlinkaction</i></Text>
+</th>
+<th width="397">
+<Text id="989">Takes a user directly to a URL that is external to a collection, possibly generating an alert page first (dictated by the Preferences).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="990"><i>pageaction</i></Text>
+</th>
+<th width="397">
+<Text id="991">Generates a page in conjunction with the macro language.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="992"><i>pingaction</i></Text>
+</th>
+<th width="397">
+<Text id="993">Checks to see whether a collection is online.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="994"><i>queryaction</i></Text>
+</th>
+<th width="397">
+<Text id="995">Performs a search.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="996"><i>statusaction</i></Text>
+</th>
+<th width="397">
+<Text id="997">Generates the administration pages.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="998"><i>tipaction</i></Text>
+</th>
+<th width="397">
+<Text id="999">Brings up a random tip for the user.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1000"><i>usersaction</i></Text>
+</th>
+<th width="397">
+<Text id="1001">Supports adding, deleting, and managing user access.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="1002">Greenstone supports the eleven actions summarised in Table <CrossRef target="Table" ref="actions_in_greenstone"/>.</Text>
+<Figure id="using_the_cgiargsinfoclass_from_pageactioncpp" class="withLineNumber">
+<Title>
+<Text id="1003">Using the <i>cgiargsinfoclass</i> from <i>pageaction.cpp</i></Text>
+</Title>
+<CodeLine>cgiarginfo arg_ainfo;</CodeLine>
+<CodeLine>arg_ainfo.shortname = " a " ;</CodeLine>
+<CodeLine>arg_ainfo.longname = " action" ;</CodeLine>
+<CodeLine>arg_ainfo.multiplechar = true;</CodeLine>
+<CodeLine>arg_ainfo.argdefault = " p" ;</CodeLine>
+<CodeLine>arg_ainfo.defaultstatus = cgiarginfo::weak;</CodeLine>
+<CodeLine>arg_ainfo.savedarginfo = cgiarginfo::must;</CodeLine>
+<CodeLine>argsinfo.addarginfo (NULL, arg_ainfo);</CodeLine>
+<CodeLine/>
+<CodeLine>arg_ainfo.shortname = " p" ;</CodeLine>
+<CodeLine>arg_ainfo.longname = " page" ;</CodeLine>
+<CodeLine>arg_ainfo.multiplechar = true;</CodeLine>
+<CodeLine>arg_ainfo.argdefault = " home" ;</CodeLine>
+<CodeLine>arg_ainfo.defaultstatus = cgiarginfo::weak;</CodeLine>
+<CodeLine>arg_ainfo.savedarginfo = cgiarginfo::must;</CodeLine>
+<CodeLine>argsinfo.addarginfo (NULL, arg_ainfo);</CodeLine>
+</Figure>
+<Text id="1004">The CGI arguments needed by an action are formally declared in its constructor function using <i>cgiarginfo</i>(defined in <i>recpt/cgiargs.h</i>). Figure <CrossRef target="Figure" ref="using_the_cgiargsinfoclass_from_pageactioncpp"/> shows an excerpt from the <i>pageaction</i> constructor function, which defines the size and properties of the CGI arguments <i>a</i> and <i>p</i>.</Text>
+<Text id="1005">For each CGI argument, the constructor must specify its short name (lines 2 and 10), which is the name of the CGI variable itself; a long name (lines 3 and 11) that is used to provide a more meaningful description of the action; whether it represents a single or multiple character value (lines 4 and 12); a possible default value (lines 5 and 13); what happens when more than one default value is supplied (lines 6 and 14) (since defaults can also be set in configuration files); and whether or not the value is preserved at the end of this action (lines 7 and 15) .</Text>
+<Text id="1006">Since it is built into the code, web pages that detail this information can be generated automatically. The <i>statusaction</i> produces this information. It can be viewed by entering the URL for the Greenstone administration page.</Text>
+<Text id="1007">The twelve inherited actions are constructed in <i>main()</i>, the top-level function for the <i>library</i> executable, whose definition is given in <i>recpt/librarymain.cpp</i>. This is also where the <i>receptionist</i> object (defined in <i>recpt/receptionist.cpp</i>) is constructed. Responsibility for all the actions is passed to the <i>receptionist</i>, which processes them by maintaining, as a data field, an associative array of the Action base class, indexed by action name.</Text>
+<Figure id="action_base_class_api">
+<Title>
+<Text id="1008">Action base class API</Text>
+</Title>
+<CodeLine>class action {</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>   cgiargsinfoclass argsinfo;</CodeLine>
+<CodeLine>   text_t gsdlhome;</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   action ();</CodeLine>
+<CodeLine>   virtual ~action ();</CodeLine>
+<CodeLine>   virtual void configure (const text_t &amp;key, const text_tarray &amp;cfgline);</CodeLine>
+<CodeLine>   virtual bool init (ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual text_t get_action_name ();</CodeLine>
+<CodeLine>   cgiargsinfoclass getargsinfo ();</CodeLine>
+<CodeLine>   virtual bool check_cgiargs (cgiargsinfoclass &amp;argsinfo,</CodeLine>
+<CodeLine>              cgiargsclass &amp;args, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual bool check_external_cgiargs (cgiargsinfoclass &amp;argsinfo,</CodeLine>
+<CodeLine>              cgiargsclass &amp;args,</CodeLine>
+<CodeLine>              outconvertclass &amp;outconvert,</CodeLine>
+<CodeLine>              const text_t &amp;saveconf,</CodeLine>
+<CodeLine>              ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void get_cgihead_info (cgiargsclass &amp;args,</CodeLine>
+<CodeLine>              recptprotolistclass *protos,</CodeLine>
+<CodeLine>              response_t &amp;response,</CodeLine>
+<CodeLine>              text_t &amp;response_data,</CodeLine>
+<CodeLine>              ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual bool uses_display (cgiargsclass &amp;args);</CodeLine>
+<CodeLine>   virtual void define_internal_macros (displayclass &amp;disp,</CodeLine>
+<CodeLine>              cgiargsclass &amp;args,</CodeLine>
+<CodeLine>              recptprotolistclass *protos,</CodeLine>
+<CodeLine>              ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void define_external_macros (displayclass &amp;disp,</CodeLine>
+<CodeLine>              cgiargsclass &amp;args,</CodeLine>
+<CodeLine>              recptprotolistclass *protos,</CodeLine>
+<CodeLine>              ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual bool do_action (cgiargsclass &amp;args,</CodeLine>
+<CodeLine>              recptprotolistclass *protos,</CodeLine>
+<CodeLine>              browsermapclass *browsers,</CodeLine>
+<CodeLine>              displayclass &amp;disp,</CodeLine>
+<CodeLine>              outconvertclass &amp;outconvert,</CodeLine>
+<CodeLine>              ostream &amp;textout,</CodeLine>
+<CodeLine>              ostream &amp;logout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="1009">Figure <CrossRef target="Figure" ref="action_base_class_api"/> shows the API for the Action base class. When executing an action, <i>receptionist</i> calls several functions, starting with <i>check_cgiargs()</i>. Most help to check, set up, and define values and macros; while <i>do_action()</i> actually generates the output page. If a particular inherited object has no definition for a particular member function, it passes through to the base class definition which implements appropriate default behaviour.</Text>
+<Text id="1010">Explanations of the member functions are as follows.</Text>
+<BulletList>
+<Bullet>
+<Text id="1011"><i>get_action_name()</i> returns the CGI <i>a</i> argument value that specifies this action. The name should be short but may be more than one character long.</Text>
+</Bullet>
+<Bullet>
+<Text id="1012"><i>check_cgiargs()</i> is called before <i>get_cgihead_info()</i>, <i>define_external_macros()</i>, and <i>do_action()</i>. If an error is found a message is written to <i>logout</i>; if it is serious the function returns <i>false</i> and no page content is produced.</Text>
+</Bullet>
+<Bullet>
+<Text id="1013"><i>check_external_cgiargs()</i> is called after <i>check_cgiargs()</i> for all actions. It is intended for use only to override some other normal behaviour, for example producing a login page when the requested page needs authentication.</Text>
+</Bullet>
+<Bullet>
+<Text id="1014"><i>get_cgihead_info()</i> sets the CGI header information. If <i>response</i> is set to <i>location</i>, then <i>response_data</i> contains the redirect address. If <i>response</i> is set to <i>content</i>, then <i>response_data</i> contains the content type.</Text>
+</Bullet>
+<Bullet>
+<Text id="1015"><i>uses_display()</i> returns <i>true</i> if the <i>displayclass</i> is needed to output the page content (the default).</Text>
+</Bullet>
+<Bullet>
+<Text id="1016"><i>define_internal_macros()</i> defines all macros that are related to pages generated by this action.</Text>
+</Bullet>
+<Bullet>
+<Text id="1017"><i>define_external_macros()</i> defines all macros that might be used by other actions to produce pages.</Text>
+</Bullet>
+<Bullet>
+<Text id="1018"><i>do_action()</i> generates the output page, normally streamed through the macro language object <i>display</i> and the output conversion object <i>textout</i>. Returns <i>false</i> if there was an error that prevented the action from outputting anything.</Text>
+</Bullet>
+</BulletList>
+<Text id="1019">At the beginning of the class definition, <i>argsinfo</i> is the protected data field (used in the code excerpt shown in Figure <CrossRef target="Figure" ref="using_the_cgiargsinfoclass_from_pageactioncpp"/>) that stores the CGI argument information specified in an inherited Action constructor function. The other data field, <i>gsdlhome</i>, records <i>GSDLHOME</i> for convenient access.<FootnoteRef id="4"/>The object also includes <i>configure()</i> and <i>init()</i> for initialisation purposes.</Text>
+</Content>
+</Subsection>
+<Subsection id="formatting">
+<Title>
+<Text id="1020">Formatting</Text>
+</Title>
+<Content>
+<Figure id="core_data_structures_in_format">
+<Title>
+<Text id="1021">Core data structures in Format</Text>
+</Title>
+<CodeLine>enum command_t {comIf, comOr, comMeta, comText, comLink, comEndLink,</CodeLine>
+<CodeLine>         comNum, comIcon, comDoc,</CodeLine>
+<CodeLine>         comHighlight, comEndHighlight};</CodeLine>
+<CodeLine>enum pcommand_t {pNone, pImmediate, pTop, pAll};</CodeLine>
+<CodeLine>enum dcommand_t {dMeta, dText};</CodeLine>
+<CodeLine>enum mcommand_t {mNone, mCgiSafe};</CodeLine>
+<CodeLine>struct metadata_t {</CodeLine>
+<CodeLine>   void clear();</CodeLine>
+<CodeLine>   metadata_t () {clear();}</CodeLine>
+<CodeLine>   text_t metaname;</CodeLine>
+<CodeLine>   mcommand_t metacommand;</CodeLine>
+<CodeLine>   pcommand_t parentcommand;</CodeLine>
+<CodeLine>   text_t parentoptions;</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine>// The decision component of an {If}{decision,true-text,false-text}</CodeLine>
+<CodeLine>// formatstring. The decision can be based on metadata or on text;</CodeLine>
+<CodeLine>// normally that text would be a macro like</CodeLine>
+<CodeLine>// _cgiargmode_.</CodeLine>
+<CodeLine>struct decision_t {</CodeLine>
+<CodeLine>   void clear();</CodeLine>
+<CodeLine>   decision_t () {clear();}</CodeLine>
+<CodeLine>   dcommand_t command;</CodeLine>
+<CodeLine>   metadata_t meta;</CodeLine>
+<CodeLine>   text_t text;</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine>struct format_t {</CodeLine>
+<CodeLine>   void clear();</CodeLine>
+<CodeLine>   format_t () {clear();}</CodeLine>
+<CodeLine>   command_t command;</CodeLine>
+<CodeLine>   decision_t decision;</CodeLine>
+<CodeLine>   text_t text;</CodeLine>
+<CodeLine>   metadata_t meta;</CodeLine>
+<CodeLine>   format_t *nextptr;</CodeLine>
+<CodeLine>   format_t *ifptr;</CodeLine>
+<CodeLine>   format_t *elseptr;</CodeLine>
+<CodeLine>   format_t *orptr;</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="1022">Although formatting is represented as a single entity in Figure <CrossRef target="Figure" ref="greenstone_runtime_system"/>, in reality it constitutes a collection of data structures and functions. They are gathered together under the header file <i>recpt/formattools.h</i>. The core data structures are shown in Figure <CrossRef target="Figure" ref="core_data_structures_in_format"/>.</Text>
+<Figure id="data_structures_built_for_sample_format_statement">
+<Title>
+<Text id="1023">Data structures built for sample <i>format</i> statement</Text>
+</Title>
+<File width="395" height="152" url="images/Dev_Fig_43.png"/>
+</Figure>
+<Text id="1024">The implementation is best explained using an example. When the format statement</Text>
+<CodeLine>format CL1Vlist</CodeLine>
+<Text id="1025" type="code">"[link][Title]{If}{[Creator], by [Creator]}[/link]} "</Text>
+<Text id="1026">is read from a collection configuration file, it is parsed by functions in <i>formattools.cpp</i> and the interconnected data structure shown in Figure <CrossRef target="Figure" ref="data_structures_built_for_sample_format_statement"/> is built. When the format statement needs to be evaluated by an action, the data structure is traversed. The route taken at <i>comIf</i> and <i>comOr</i> nodes depends on the metadata that is returned from a call to the protocol.</Text>
+<Text id="1027">One complication is that when metadata is retrieved, it might include further macros and format syntax. This is handled by switching back and forth between parsing and evaluating, as needed.</Text>
+</Content>
+</Subsection>
+<Subsection id="macro_language">
+<Title>
+<Text id="1028">Macro language</Text>
+</Title>
+<Content>
+<Text id="1029">The Macro Language entity in Figure <CrossRef target="Figure" ref="greenstone_runtime_system"/>, like Format, does not map to a single C++ class. In this case there is a core class, but the implementation of the macro language also calls upon supporting functions and classes.</Text>
+<Text id="1030">Again, the implementation is best explained using an example. First we give some sample macro definitions that illustrate macro precedence, thenâwith the aid of a diagramâwe describe the core data structures built to support this activity. Finally we present and describe the public member functions to <i>displayclass</i>, the top-level macro object.</Text>
+<Figure id="illustration_of_macro_precedence">
+<Title>
+<Text id="1031">Illustration of macro precedence</Text>
+</Title>
+<CodeLine>package query</CodeLine>
+<CodeLine>_header_ []         {_querytitle_}</CodeLine>
+<CodeLine>_header_ [l=en]     {Search page}</CodeLine>
+<CodeLine>_header_ [c=demo]   {&lt;table bgcolor=green&gt;&lt;tr&gt;&lt;td&gt;_querytitle_&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;}</CodeLine>
+<CodeLine>_header_ [v=1]      {_textquery_}</CodeLine>
+<CodeLine>_header_ [l=fr,v=1,c=hdl] {HDL Page de recherche}</CodeLine>
+</Figure>
+<Text id="1032">In a typical Greenstone installation, macro precedence is normally: <i>c</i>(for the collection) takes precedence over <i>v</i>(for graphical or text-only interface), which takes precedence over <i>l</i>(for the language). This is accomplished by the line</Text>
+<CodeLine>macroprecedence c,v,l</CodeLine>
+<Text id="1033">in the main configuration file <i>main.cfg</i>. The macro statements in Figure <CrossRef target="Figure" ref="illustration_of_macro_precedence"/> define sample macros for <i>_header_</i> in the <i>query</i> package for various settings of <i>c</i>, <i>v</i>, and <i>l</i>. If the CGI arguments given when an action is invoked included <i>c=dls</i>, <i>v=1</i>, and <i>l=en</i>, the macro <i>_header_[v=1]</i> would be selected for display. It would be selected ahead <i>of _content_[l=en]</i> because <i>v</i> has a higher precedence than <i>l</i>. The <i>_content_[l=fr,v=1,c=dls]</i> macro would not be selected because the page parameter for <i>l</i> is different.</Text>
+<Figure id="data_structures_representing_the_default_macros">
+<Title>
+<Text id="1034">Data structures representing the default macros</Text>
+</Title>
+<File width="382" height="194" url="images/Dev_Fig_45.png"/>
+</Figure>
+<Text id="1035">Figure <CrossRef target="Figure" ref="data_structures_representing_the_default_macros"/> shows the core data structure built when reading the macro files specified in <i>etc/main.cfg</i>. Essentially, it is an associative array of associative arrays of associative arrays. The top layer (shown on the left) indexes which package the macro is from, and the second layer indexes the macro name. The final layer indexes any parameters that were specified, storing each one as the type <i>mvalue</i> which records, along with the macro value, the file it came from. For example, the text defined for <i>_header_[l=en]</i> in Figure <CrossRef target="Figure" ref="illustration_of_macro_precedence"/> can be seen stored in the lower of the two <i>mvalue</i> records in Figure <CrossRef target="Figure" ref="data_structures_representing_the_default_macros"/>.</Text>
+<Figure id="displayclass_api">
+<Title>
+<Text id="1036"><i>Displayclass</i> API (abridged)</Text>
+</Title>
+<CodeLine>class displayclass</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   displayclass ();</CodeLine>
+<CodeLine>   ~displayclass ();</CodeLine>
+<CodeLine>   int isdefaultmacro (text_t package, const text_t &amp;macroname);</CodeLine>
+<CodeLine>   int setdefaultmacro (text_t package, const text_t &amp;macroname,  </CodeLine>
+<CodeLine>         text_t params, const text_t &amp;macrovalue);</CodeLine>
+<CodeLine>   int loaddefaultmacros (text_t thisfilename);</CodeLine>
+<CodeLine>   void openpage (const text_t &amp;thispageparams,</CodeLine>
+<CodeLine>         const text_t &amp;thisprecedence);</CodeLine>
+<CodeLine>   void setpageparams (text_t thispageparams,</CodeLine>
+<CodeLine>         text_t thisprecedence);</CodeLine>
+<CodeLine>   int setmacro (const text_t &amp;macroname,</CodeLine>
+<CodeLine>         text_t package,</CodeLine>
+<CodeLine>         const text_t &amp;macrovalue);</CodeLine>
+<CodeLine>   void expandstring (const text_t &amp;inputtext, text_t &amp;outputtext);</CodeLine>
+<CodeLine>   void expandstring (text_t package, const text_t &amp;inputtext,</CodeLine>
+<CodeLine>         text_t &amp;outputtext, int recursiondepth = 0);</CodeLine>
+<CodeLine>   void setconvertclass (outconvertclass *theoutc) {outc = theoutc;}</CodeLine>
+<CodeLine>   outconvertclass *getconvertclass () {return outc;}</CodeLine>
+<CodeLine>   ostream *setlogout (ostream *thelogout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="1037">The central object that supports the macro language is <i>displayclass</i>, defined in <i>lib/display.h</i>. Its public member functions are shown in Figure <CrossRef target="Figure" ref="displayclass_api"/>. The class reads the specified macro files using <i>loaddefaultmacros()</i>, storing in a protected section of the class (not shown) the type of data structure shown in Figure <CrossRef target="Figure" ref="data_structures_representing_the_default_macros"/>. It is also permissible for macros to be set by the runtime system using <i>setmacro()</i> (in the last example of Section <CrossRef target="Section" ref="how_the_conceptual_framework_fits_together"/>, <i>pageaction</i> sets <i>_homeextra_</i> to be the dynamically generated table of available collections using this function.) This is supported by a set of associative arrays similar to those used to represent macro files (it is not identical, because the former does not require the âparameterâ layer). In <i>displayclass</i>, macros read from the file are referred to as <i>default macros</i>. Local macros specified through <i>setmacro()</i> are referred to as <i>current macros</i>, and are cleared from memory once the page has been generated.</Text>
+<Text id="1038">When a page is to be produced, <i>openpage()</i> is first called to communicate the current settings of the page parameters (<i>l=en</i> and so on). Following that, text and macros are streamed through the classâtypically from within an <i>actionclass</i> âusing code along the lines of:</Text>
+<CodeLine>cout &lt;&lt; text_t2ascii &lt;&lt; display &lt;&lt; "_amacro_ "</CodeLine>
+<CodeLine>         &lt;&lt; "_anothermacro_ ";</CodeLine>
+<Text id="1039">The result is that macros are expanded according to the page parameter settings. If required, these settings can be changed partway through an action by using <i>setpageparams()</i>. The remaining public member functions provide lower level support.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_receptionist_code">
+<Title>
+<Text id="1040">The receptionist code</Text>
+</Title>
+<Content>
+<Text id="1041">The principal objects in the receptionist have now been described. Below we detail the supporting classes, which reside in <i>GSDLHOME/src/recpt</i>. Except where efficiency is paramountâin which case definitions are in-lineâimplementation details are contained within a header file's <i>.cpp</i> counterpart. Supporting files often include the word <i>tool</i> as part of the file name, as in <i>OIDtools.h</i> and <i>formattools.h</i>.</Text>
+<Text id="1042">A second set of lexically scoped files include the prefix <i>z3950</i>. The files provide remote access to online databases and catalogs that make their content publicly available using the Z39.50 protocol.</Text>
+<Text id="1043">Another large group of supporting files include the term <i>browserclass</i>. These files are related through a virtual inheritance hierarchy. As a group they support an abstract notion of browsing: serial page generation of compartmentalised document content or metadata. Browsing activities include perusing documents ordered alphabetically by title or chronologically by date; progressing through the titles returned by a query ten entries at a time; and accessing individual pages of a book using the âgo to pageâ mechanism. Each browsing activity inherits from <i>browserclass</i>, the base class:</Text>
+<BulletList>
+<Bullet>
+<Text id="1044"><i>datelistbrowserclass</i> provides support for chronological lists;</Text>
+</Bullet>
+<Bullet>
+<Text id="1045"><i>hlistbrowserclass</i> provides support for horizontal lists;</Text>
+</Bullet>
+<Bullet>
+<Text id="1046"><i>htmlbrowserclass</i> provides support for pages of html;</Text>
+</Bullet>
+<Bullet>
+<Text id="1047"><i>invbrowserclass</i> provides support for invisible lists;</Text>
+</Bullet>
+<Bullet>
+<Text id="1048"><i>pagedbrowserclass</i> provides go to page support;</Text>
+</Bullet>
+<Bullet>
+<Text id="1049"><i>vlistbrowserclass</i> provides support for vertical lists.</Text>
+</Bullet>
+</BulletList>
+<Text id="1050">Actions access <i>browserclass</i> objects through <i>browsetools.h</i>.</Text>
+<Table class="hidden">
+<Title/>
+<TableContent>
+<tr>
+<th width="140">
+<Text id="1051"><b>OIDtools.h</b></Text>
+</th>
+<th width="390">
+<Text id="1052">Function support for evaluating document identifiers over the protocol.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1053"><b>action.h</b></Text>
+</th>
+<th width="390">
+<Text id="1054">Base class for the Actions entity depicted in Figure <CrossRef target="Figure" ref="greenstone_runtime_system"/>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1055"><b>authenaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1056">Inherited action for handling authentication of a user.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1057"><b>browserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1058">Base class for abstract browsing activities.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1059"><b>browsetools.h</b></Text>
+</th>
+<th width="390">
+<Text id="1060">Function support that accesses the <i>browserclass</i> hierarchy. Functionality includes expanding and contracting contents, outputing a table of contents, and generating control such as the âgo to pageâ mechanism.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1061"><b>cgiargs.h</b></Text>
+</th>
+<th width="390">
+<Text id="1062">Defines <i>cgiarginfo</i> used in Figure <CrossRef target="Figure" ref="using_the_cgiargsinfoclass_from_pageactioncpp"/>, and other data structure support for CGI arguments.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1063"><b>cgiutils.h</b></Text>
+</th>
+<th width="390">
+<Text id="1064">Function support for CGI arguments using the data structures defined in <i>cgiargs.h</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1065"><b>cgiwrapper.h</b></Text>
+</th>
+<th width="390">
+<Text id="1066">Function support that does everything necessary to output a page using the CGI protocol. Access is through the function</Text>
+<CodeLine>void cgiwrapper (receptionist &amp;recpt, text_t collection);</CodeLine>
+<Text id="1067">which is the only function declared in the header file. Everything else in the <i>.cpp</i> counterpart is lexically scoped to be local to the file (using the C++ keyword <i>static</i>). If the function is being run for a particular collection then <i>collection</i> should be set, otherwise it should be the empty string "". The code includes support for Fast-CGI.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1068"><b>collectoraction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1069">Inherited action that facilitates end-user collection-building through the Collector. The page generated comes from <i>collect.dm</i> and is controlled by the CGI argument <i>p=page</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1070"><b>comtypes.h</b></Text>
+</th>
+<th width="390">
+<Text id="1071">Core types for the protocol.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1072"><b>converter.h</b></Text>
+</th>
+<th width="390">
+<Text id="1073">Object support for stream converters.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1074"><b>datelistbrowserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1075">Inherited from <i>browserclass</i>, this object provides browsing support for chronological lists such as that seen in the Greenstone Archives collection under âdatesâ in the navigation bar.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1076"><b>documentaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1077">Inherited action used to retrieve a document or part of a classification hierarchy.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1078"><b>extlinkaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1079">Inherited action that controls whether or not a user goes straight to an external link or passes through a warning page alerting the user to the fact that they are about to move outside the digital library system.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1080"><b>formattools.h</b></Text>
+</th>
+<th width="390">
+<Text id="1081">Function support for parsing and evaluating collection configuration <i>format</i> statements. Described in more detail in Section <CrossRef target="Subsection" ref="formatting"/> above.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1082"><b>historydb.h</b></Text>
+</th>
+<th width="390">
+<Text id="1083">Data structures and function support for managing a database of previous queries so a user can start a new query that includes previous query terms.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1084"><b>hlistbrowserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1085">Inherited from <i>browserclass</i>, this object provides browsing support for horizontal lists.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1086"><b>htmlbrowserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1087">Inherited from <i>browserclass</i>, this object provides browsing support for html pages.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1088"><b>htmlgen.h</b></Text>
+</th>
+<th width="390">
+<Text id="1089">Function support to highlight query terms in a <i>text_t</i> string.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1090"><b>htmlutils.h</b></Text>
+</th>
+<th width="390">
+<Text id="1091">Function support that converts a <i>text_t</i> string into the equivalent html. The symbols ", <i>&amp;</i>, <i>&lt;</i>, and <i>&gt;</i> are converted into <i>&amp;quot;</i>, <i>&amp;amp;</i>, <i>&amp;lt;</i> and <i>&amp;gt;</i> respectively.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1092"><b>infodbclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1093">Defines two classes: <i>gdbmclass</i> and <i>infodbclass</i>. The former provides the Greenstone API to gdbm; the latter is the object class used to store a record entry read in from a gdbm database, and is essentially an associative array of integer-indexed arrays of <i>text_t</i> strings.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1094"><b>invbrowserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1095">Inherited from <i>browserclass</i>, this object provides browsing support for lists that are not intended for display (invisible).</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1096"><b>nullproto.h</b></Text>
+</th>
+<th width="390">
+<Text id="1097">Inherited from <i>recptproto</i>, this class realises the null protocol, implemented through function calls from the receptionist to the collection server.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1098"><b>pageaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1099">Inherited action that, in conjunction with the macro file named in <i>p=page</i>, generates a web page.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1100"><b>pagedbrowserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1101">Inherited from <i>browserclass</i>, this object provides browsing support for the âgo to pageâ mechanism seen (for example) in the Gutenberg collection.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1102"><b>pingaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1103">Inherited action that checks to see whether a particular collection is responding.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1104"><b>queryaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1105">Inherited action that takes the stipulated query, settings and preferences and performs a search, generating as a result the subset of <i>o=num</i> matching documents starting at position <i>r=num</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1106"><b>querytools.h</b></Text>
+</th>
+<th width="390">
+<Text id="1107">Function support for querying.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1108"><b>receptionist.h</b></Text>
+</th>
+<th width="390">
+<Text id="1109">Top-level object for the receptionist. Maintains a record of CGI argument information, instantiations of each inherited action, instantiations of each inherited browser, the core macro language object <i>displayclass</i>, and all possible converters.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1110"><b>recptconfig.h</b></Text>
+</th>
+<th width="390">
+<Text id="1111">Function support for reading the site and main configuration files.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1112"><b>recptproto.h</b></Text>
+</th>
+<th width="390">
+<Text id="1113">Base class for the protocol.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1114"><b>statusaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1115">Inherited action that generates, in conjunction with <i>status.dm</i>, the various administration pages.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1116"><b>tipaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1117">Inherited action that produces, in conjunction with <i>tip.dm</i>, a web page containing a tip taken at random from a list of tips stored in <i>tip.dm</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1118"><b>userdb.h</b></Text>
+</th>
+<th width="390">
+<Text id="1119">Data structure and function support for maintaining a gdbm database of users: their password, groups, and so on.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1120"><b>usersaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1121">An administrator action inherited from the base class that supports adding and deleting users, as well as modifying the groups they are in.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1122"><b>vlistbrowserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1123">Inherited from <i>browserclass</i>, this object provides browsing support for vertical lists, the mainstay of classifiers. For example, the children of the node for titles beginning with the letter <i>N</i> are stipulated to be a <i>VList</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1124"><b>z3950cfg.h</b></Text>
+</th>
+<th width="390">
+<Text id="1125">Data structure support for the Z39.50 protocol. Used by <i>z3950proto.cpp</i>, which defines the main protocol class(inherited from the base class <i>recptproto</i>), and configuration file parser <i>zparse.y</i> (written using Yacc).</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1126"><b>z3950proto.h</b></Text>
+</th>
+<th width="390">
+<Text id="1127">Inherited from <i>recptproto</i>, this class realises the Z39.50 protocol so that a Greenstone receptionist can access remote library sites running Z39.50 servers.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1128"><b>z3950server.h</b></Text>
+</th>
+<th width="390">
+<Text id="1129">Further support for the Z39.50 protocol.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="initialisation">
+<Title>
+<Text id="1130">Initialisation</Text>
+</Title>
+<Content>
+<Text id="1131">Initialisation in Greenstone is an intricate operation that processes configuration files and assigns default values to data fields. In addition to inheritance and constructor functions, core objects define <i>init()</i> and <i>configure()</i> functions to help standardise the task. Even so, the order of execution can be difficult to follow. This section describes what happens.</Text>
+<Text id="1132">Greenstone uses several configuration files for different purposes, but all follow the same syntax. Unless a line starts with the hash symbol (#) or consists entirely of white space, the first word defines a keyword, and the remaining words represent a particular setting for that keyword.</Text>
+<Text id="1133">The lines from configuration files are passed, one at a time, to <i>configure()</i> as two arguments: the keyword and an array of the remaining words. Based on the keyword, a particular version of <i>configure()</i> decides whether the information is of interest, and if so stores it. For example, <i>collectserver</i>(which maps to the Collection object in Figure <CrossRef target="Figure" ref="greenstone_runtime_system"/>) processes the format statements in a collection's configuration file. When the keyword <i>format</i> is passed to <i>configure()</i>, an <i>if</i> statement is triggered that stores in the object a copy of the function's second argument.</Text>
+<Text id="1134">After processing the keyword and before the function terminates, some versions of <i>configure()</i> pass the data to <i>configure()</i> functions in other objects. The Receptionist object calls <i>configure()</i> for Actions, Protocols, and Browsers. The NullProtocol object calls <i>configure()</i> for each Collection object; Collection calls Filters and Sources.</Text>
+<Text id="1135">In C++, data fields are normally initialized by the object's constructor function. However, in Greenstone some initialisation depends on values read from configuration files, so a second round of initialisation is needed. This is the purpose of the <i>init()</i> member functions, and in some cases it leads to further calls to <i>configure()</i>.</Text>
+<Figure id="initialising_greenstone_using_the_null_protocol">
+<Title>
+<Text id="1136">Initialising Greenstone using the null protocol</Text>
+</Title>
+<CodeLine>============</CodeLine>
+<CodeLine>Main program</CodeLine>
+<CodeLine>============</CodeLine>
+<CodeLine>Statically construct Receptionist</CodeLine>
+<CodeLine>Statically construct NullProtocol</CodeLine>
+<CodeLine>Establish the value for 'gsdlhome' by reading gsdlsite.cfg</CodeLine>
+<CodeLine>Foreach directory in GSDLHOME/collect that isn't "modelcol":</CodeLine>
+<CodeLine>   Add directory name (now treated as collection name) to NullProtocol:</CodeLine>
+<CodeLine>       Dynamically construct Collection</CodeLine>
+<CodeLine>       Dynamically construct Gdbm class</CodeLine>
+<CodeLine>       Dynamically construct the Null Filter</CodeLine>
+<CodeLine>       Dynamically construct the Browse Filter</CodeLine>
+<CodeLine>       Dynamically construct MgSearch</CodeLine>
+<CodeLine>       Dynamically construct the QueryFilter</CodeLine>
+<CodeLine>       Dynamically construct the MgGdbmSource</CodeLine>
+<CodeLine>       Configure Collection with 'collection'</CodeLine>
+<CodeLine>           Passing 'collection' value on to Filters and Sources:</CodeLine>
+<CodeLine>       Configure Receptionist with 'collectinfo':</CodeLine>
+<CodeLine>           Passing 'collectinfo' value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>Add NullProtocol to Receptionist</CodeLine>
+<CodeLine>Add in UTF-8 converter</CodeLine>
+<CodeLine>Add in GB converter</CodeLine>
+<CodeLine>Add in Arabic converter</CodeLine>
+<CodeLine>Foreach Action:</CodeLine>
+<CodeLine>   Statically construct Action</CodeLine>
+<CodeLine>   Add Action to Receptionist</CodeLine>
+<CodeLine>Foreach Browsers:</CodeLine>
+<CodeLine>   Statically construct Browser</CodeLine>
+<CodeLine>   Add Browser to Receptionist</CodeLine>
+<CodeLine>Call function cgiwrapper:</CodeLine>
+<CodeLine>   =================</CodeLine>
+<CodeLine>   Configure objects</CodeLine>
+<CodeLine>   =================</CodeLine>
+<CodeLine>   Configure Receptionist with 'collection'</CodeLine>
+<CodeLine>       Passing 'collection' value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>       NullProtocol not interested in 'collection'</CodeLine>
+<CodeLine>   Configure Receptionist with 'httpimg'</CodeLine>
+<CodeLine>       Passing 'httpimg' value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>       NullProtocol passing 'httpimg' on to Collection</CodeLine>
+<CodeLine>       Passing 'httpimg' value on to Filters and Sources:</CodeLine>
+<CodeLine>   Configure Receptionist with 'gwcgi'</CodeLine>
+<CodeLine>       Passing 'gwcgi' value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>       NullProtocol passing 'gwcgi' on to Collection</CodeLine>
+<CodeLine>           Passing 'gwcgi' value on to Filters and Sources:</CodeLine>
+<CodeLine>   Reading in site configuration file gsdlsite.cfg</CodeLine>
+<CodeLine>       Configure Recptionist with 'gsdlhome'</CodeLine>
+<CodeLine>           Passing 'gsdlhome' value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>           NullProtocol passing 'gsdlhome' on to Collection</CodeLine>
+<CodeLine>               Passing 'gsdlhome' value on to Filters and Sources:</CodeLine>
+<CodeLine>       Configure Recptionist with ...</CodeLine>
+<CodeLine>       ... and so on for all entries in gsdlsite.cfg</CodeLine>
+<CodeLine>   Reading in main configuration file main.cfg</CodeLine>
+<CodeLine>       Confiugre Recptionist with ...</CodeLine>
+<CodeLine>       ... and so on for all entries in main.cfg</CodeLine>
+<CodeLine>   ====================</CodeLine>
+<CodeLine>   Initialising objects</CodeLine>
+<CodeLine>   ====================</CodeLine>
+<CodeLine>   Initialise the Receptionist</CodeLine>
+<CodeLine>       Configure Receptionist with 'collectdir'</CodeLine>
+<CodeLine>           Passing 'collectdir' value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>           NullProtocol not interested in 'collectdir'</CodeLine>
+<CodeLine>       Read in Macro files</CodeLine>
+<CodeLine>       Foreach Actions</CodeLine>
+<CodeLine>           Initialise Action</CodeLine>
+<CodeLine>       Foreach Protocol</CodeLine>
+<CodeLine>           Initialise Protocol</CodeLine>
+<CodeLine>           When Protocol==NullProtocol:</CodeLine>
+<CodeLine>               Foreach Collection</CodeLine>
+<CodeLine>                   Reading Collection's build.cfg</CodeLine>
+<CodeLine>                   Reading Collection's collect.cfg</CodeLine>
+<CodeLine>                       Configure Collection with 'creator'</CodeLine>
+<CodeLine>                           Passing 'creator' value on to Filters and Sources:</CodeLine>
+<CodeLine>                       Configure Collection with 'maintainer'</CodeLine>
+<CodeLine>                           Passing 'maintainer' value on to Filters and Sources:</CodeLine>
+<CodeLine>                       ... and so on for all entries in collect.cfg</CodeLine>
+<CodeLine>       Foreach Browsers</CodeLine>
+<CodeLine>           Initialise Browser</CodeLine>
+<CodeLine>   =============</CodeLine>
+<CodeLine>   Generate page</CodeLine>
+<CodeLine>   =============</CodeLine>
+<CodeLine>   Parse CGI arguments</CodeLine>
+<CodeLine>   Execute designated Action to produce page</CodeLine>
+<CodeLine>End.</CodeLine>
+</Figure>
+<Text id="1137">Figure <CrossRef target="Figure" ref="initialising_greenstone_using_the_null_protocol"/> shows diagnostic statements generated from a version of Greenstone augmented to highlight the initialisation process. The program starts in the <i>main()</i> function in <i>recpt/librarymain.cpp</i>. It constructs a Receptionist object and a NullProtocol object, then scans <i>gsdlsite.cfg</i>(located in the same directory as the <i>library</i> executable) for <i>gsdlhome</i> and stores its value in a variable. For each online collectionâas established by reading in the directories present in <i>GSDLHOME/collect</i> âit constructs a Collection object, through the NullProtocol object, that includes within it Filters, Search and Source, plus a few hardwired calls to <i>configure()</i>.</Text>
+<Text id="1138">Next <i>main()</i> adds the NullProtocol object to the Receptionist, which keeps a base class array of protocols in a protected data field, and then sets up several converters. <i>main()</i> constructs all Actions and Browsers used in the executable and adds them to the Receptionist. The function concludes by calling <i>cgiwrapper()</i> in <i>cgiwrapper.cpp</i>, which itself includes substantial object initialisation.</Text>
+<Text id="1139">There are three sections to <i>cgiwrapper()</i>: configuration, initialisation and page generation. First some hardwired calls to <i>configure()</i> are made. Then <i>gsdlsite.cfg</i> is read and <i>configure()</i> is called for each line. The same is done for <i>etc/main.cfg</i>.</Text>
+<Text id="1140">The second phase of <i>cgiwrapper()</i> makes calls to <i>init()</i>. The Receptionist makes only one call to its <i>init()</i> function, but the act of invoking this calls <i>init()</i> functions in the various objects stored within it. First a hardwired call to <i>configure()</i> is made to set <i>collectdir</i>, then the macro files are read. For each action, its <i>init()</i> function is called. The same occurs for each protocol stored in the receptionistâbut in the system being described only one protocol is stored, the NullProtocol. Calling <i>init()</i> for this object causes further configuration: for each collection in the NullProtocol, its collection-specific <i>build.cfg</i> and <i>collect.cfg</i> are read and processed, with a call to <i>configure()</i> for each line.</Text>
+<Text id="1141">The final phase of <i>cgiwrapper()</i> is to parse the CGI arguments, and then call the appropriate action. Both these calls are made with the support of the Receptionist object.</Text>
+<Text id="1142">The reason for the separation of the configuration, initialisation, and page generation code is that Greenstone is optimised to be run as a server (using Fast-cgi, or the Corba protocol, or the Windows Local Library). In this mode of operation, the configuration and initialisation code is executed once, then the program remains in memory and generates many web pages in response to requests from clients, without requiring re-initalisation.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="configuring_your_greenstone_site">
+<Title>
+<Text id="1143">Configuring your Greenstone site</Text>
+</Title>
+<Content>
+<Text id="1144">There are two configuration files in Greenstone that are used for configuring various aspects of your Greenstone site. These files are the âmainâ configuration file <i>main.cfg</i>, found in <i>GSDLHOME/etc</i>, and the âsiteâ configuration file <i>gsdlsite.cfg</i>, found in <i>GSDLHOME/cgi-bin</i>. These files each control specific aspects of site-wide configuration. Both can be viewed from the Greenstone administration page.</Text>
+<Section id="main_configuration_file">
+<Title>
+<Text id="1145">Main configuration file</Text>
+</Title>
+<Content>
+<Text id="1146">The main configuration file <i>main.cfg</i> is used to configure the receptionistâthat part of Greenstone that fields queries and displays pages. You can control everything from the languages that the interface can use to what logs are kept.</Text>
+<Subsection id="site_maintenance_and_logging">
+<Title>
+<Text id="1147">Site maintenance and logging</Text>
+</Title>
+<Content>
+<Text id="1148">Lines in the configuration file dictate how your Greenstone site is maintained, what facilities it offers, which events are logged, and what notification is given to the maintainer. Table <CrossRef target="Table" ref="configuration_options_for_site_maintenance_and_logging"/> details some of the options that are available; the remaining ones are described in the following sections.</Text>
+<Table id="configuration_options_for_site_maintenance_and_logging">
+<Title>
+<Text id="1149">Configuration options for site maintenance and logging</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="1150"><b>Value</b></Text>
+</th>
+<th width="246">
+<Text id="1151"><b>Purpose</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1152"><i>maintainer</i></Text>
+</th>
+<th width="151">
+<Text id="1153">NULL or an E-mail address</Text>
+</th>
+<th width="246">
+<Text id="1154">E-mail address of the site maintainer to be used for certain notification purposes. If NULL, E-mail events are disabled</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1155"><i>MailServer</i></Text>
+</th>
+<th width="151">
+<Text id="1156">NULL or a server name</Text>
+</th>
+<th width="246">
+<Text id="1157">Outgoing mail server for this site. If NULL, <i>mail.maintainer's-domain</i> is used (e.g. if the maintainer is <i>help@example.com</i> the default is <i>mail.example.com</i>.) If this doesn't resolve to a valid smtp server, E-mail events will not work</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1158"><i>status</i></Text>
+</th>
+<th width="151">
+<Text id="1159"><i>enabled</i> or <i>disabled</i></Text>
+</th>
+<th width="246">
+<Text id="1160">Determines whether the âMaintenance and administrationâ page is to be made available</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1161"><i>collector</i></Text>
+</th>
+<th width="151">
+<Text id="1162"><i>enabled</i> or <i>disabled</i></Text>
+</th>
+<th width="246">
+<Text id="1163">Determines whether the end-user collection building âcollectorâ facility is available</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1164"><i>logcgiargs</i></Text>
+</th>
+<th width="151">
+<Text id="1165"><i>true</i> or <i>false</i></Text>
+</th>
+<th width="246">
+<Text id="1166">If <i>true</i>, a usage log is kept in <i>usage.txt</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1167"><i>usecookies</i></Text>
+</th>
+<th width="151">
+<Text id="1168"><i>true</i> or <i>false</i></Text>
+</th>
+<th width="246">
+<Text id="1169">If <i>true</i>, information about the site users is collected (using cookies) and written to <i>usage.txt</i>(this only works if <i>logcgiargs</i> is <i>true</i>)</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1170"><i>LogDateFormat</i></Text>
+</th>
+<th width="151">
+<Text id="1171"><i>LocalTime</i> or <br/><i>UTCTime</i> or <br/><i>Absolute</i></Text>
+</th>
+<th width="246">
+<Text id="1172">Format in which time information is written to the log. <i>LocalTime</i> produces the format âThu Dec 07 12:34 NZDT 2000â, <i>UTCTime</i> is the same format but in GMT, and <i>absolute</i> is an integer representing the number of seconds since 00:00:00 01/01/1970 GMT</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1173"><i>LogEvents</i></Text>
+</th>
+<th width="151">
+<Text id="1174"><i>AllEvents</i> or <br/><i>CollectorEvents</i><br/>or <i>disabled</i></Text>
+</th>
+<th width="246">
+<Text id="1175">Logs certain events to <i>events.txt</i>. <i>AllEvents</i> logs all Greenstone events, <i>CollectorEvents</i> logs only events related to the Collector, and <i>disabled</i> log no events</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1176"><i>EmailEvents</i></Text>
+</th>
+<th width="151">
+<Text id="1177"><i>enabled</i> or <i>disabled</i></Text>
+</th>
+<th width="246">
+<Text id="1178">E-mail the maintainer (if there is oneâsee the maintainer option) every time an event occurs</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1179"><i>EmailUserEvents</i></Text>
+</th>
+<th width="151">
+<Text id="1180"><i>enabled</i> or <i>disabled</i></Text>
+</th>
+<th width="246">
+<Text id="1181">E-mail the user on certain eventsâsuch as the collector finishing a collection build</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1182"><i>macrofiles</i></Text>
+</th>
+<th width="151">
+<Text id="1183">list of macro filenames</Text>
+</th>
+<th width="246">
+<Text id="1184">Determine what macros are available for Greenstone's user interface software</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+<Subsection id="language_support">
+<Title>
+<Text id="1185">Language support</Text>
+</Title>
+<Content>
+<Text id="1186">Two kinds of entry in the <i>main.cfg</i> configuration file affect the way that different languages are handled. They determine which languages and encodings are available from the Preferences page. <i>Encoding</i> lines specify the different types of character encoding that can be selected. <i>Language</i> lines specify what user interface languages can be selected (of course, there must be a language macro for each possible language).</Text>
+<Text id="1187">The <i>Encoding</i> line can contain four possible values: <i>shortname</i>, <i>longname</i>, <i>map</i> and <i>multibyte</i>. The <i>shortname</i> is the standard charset label, and must be specified for all encodings. The <i>longname</i> gives the encoding name that is displayed on the Preferences page. If it is absent it defaults to the <i>shortname</i>. The <i>map</i> value is mandatory for all encodings except utf8, which is handled internally (and should always be enabled). The <i>multibyte</i> value should be set for all character sets that require more than one byte per character. The file <i>main.cfg</i> specifies many encodings, most of which are commented out. To enable an encoding, remove the comment character â#â.</Text>
+<Text id="1188">Each <i>Language</i> line can contain three possible values, <i>shortname</i>, <i>longname</i>, and <i>default_encoding</i>. The <i>shortname</i> is the ISO 639 two-letter language symbol, and is required. The <i>longname</i> is the name that is used for the language on the Preferences page. If absent, it defaults to the <i>shortname</i>. The <i>default_encoding</i> option is used to specify the preferred encoding for this language.</Text>
+</Content>
+</Subsection>
+<Subsection id="page_parameters_and_cgi_arguments">
+<Title>
+<Text id="1189">Page parameters and CGI arguments</Text>
+</Title>
+<Content>
+<Text id="1190">Page parameters and CGI arguments may be defined from within the <i>main.cfg</i> configuration file. Recall from Figure <CrossRef target="Figure" ref="using_the_cgiargsinfoclass_from_pageactioncpp"/> that most CGI arguments are defined within the library C++ code itself. However, it is occasionally useful to define new arguments or edit existing ones at configuration time, thus avoiding the need to recompile the library.</Text>
+<Text id="1191">To do this you use the <i>cgiarg</i> configuration option. <i>Cgiarg</i> may take up to six arguments; <i>shortname</i>, <i>longname</i>, <i>multiplechar</i>, <i>argdefault</i>, <i>defaultstatus</i> and <i>savedarginfo</i>. These arguments correspond to the CGI argument options described in Section <CrossRef target="Section" ref="receptionist"/>. For example, in the default <i>main.cfg</i> file the <i>cgiarg</i> configuration option is used to set the default values of the existing <i>a</i> and <i>p</i> CGI arguments to <i>p</i> and <i>home</i> respectively.</Text>
+<Text id="1192">Page parameters are special cases of CGI arguments which correspond to parameters in Greenstone's macro files. For example, the <i>l</i> CGI argument directly corresponds to the <i>l=</i> parameter in the macro files. To define a CGI argument to also be a page parameter you use the <i>pageparam</i> configuration option.</Text>
+<Text id="1193">The best way to learn about the various configuration options possible in the <i>main-cfg</i> configuration file is to experiment with the file itself. Note that if you are using the Windows local library version of Greenstone you must restart the server before any configuration files changes take effect.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="site_configuration_file">
+<Title>
+<Text id="1194">Site configuration file</Text>
+</Title>
+<Content>
+<Table id="lines_in_gsdlsitecfg">
+<Title>
+<Text id="1195">Lines in <i>gsdlsite.cfg</i></Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="1196"><b>Line</b></Text>
+</th>
+<th width="397">
+<Text id="1197"><b>Function</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1198"><i>gsdlhome</i></Text>
+</th>
+<th width="397">
+<Text id="1199">A path to the <i>GSDLHOME</i> directory.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1200"><i>httpprefix</i></Text>
+</th>
+<th width="397">
+<Text id="1201">The web address of <i>GSDLHOME</i>. If the document root on your web server is set to <i>GSDLHOME</i> you do not need this line.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1202"><i>httpimage</i></Text>
+</th>
+<th width="397">
+<Text id="1203">The web address of the directory containing the images for the user interface. If your web-server's document root is set to <i>GSDLHOME</i> this will be <i>images</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1204"><i>gwcgi</i></Text>
+</th>
+<th width="397">
+<Text id="1205">The web address of this cgi script (usually ends in <i>library</i>). This is not needed if your web server sets the environment variable <i>SCRIPT_NAME</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1206"><i>maxrequests</i></Text>
+</th>
+<th width="397">
+<Text id="1207">(Only applies if <i>fast-cgi</i> is in use.) The number of requests fast-cgi should process before it exits. When debugging the library this should be set to a small number, otherwise it should be a large number.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="1208">The site configuration file <i>gsdlsite.cfg</i> sets variables that are used by the library software and web-server at run-time, and resides in the same directory as the <i>library</i> program. Table <CrossRef target="Table" ref="lines_in_gsdlsitecfg"/> describe the lines in this file; they are explained in Section 5 of the <i>Greenstone Digital Library Installer's Guide.</i></Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="appendix_a_stl">
+<Title>
+<Text id="1209">Appendix A: The C++ Standard Template Library</Text>
+</Title>
+<Content>
+<Text id="1210">The Standard Template Library (STL) is a widely-used C++ library from Silicon Graphics (<i>www.sgi.com</i>). This Appendix gives a brief overview of key parts that are used throughout the Greenstone code. For a fuller description, consult the official STL reference manual, available online at <i>www.sgi.com</i>, or one of the many STL textbooks, for example Josuttis (1999).</Text>
+<Text id="1211">As the word âtemplateâ suggests, STL is not just a plug-and-use object library. Coupled with the template mechanism in C++, it provides a forum for programmers to concisely develop their own objects that tap into the algorithmic capabilities embedded within STL. This adds an extra layer of complexity, but it's worth it.</Text>
+<Text id="1212">To help understand the Greenstone code excerpts given in this manual, we give a few tutorial level examples that use STL.</Text>
+<Section id="lists">
+<Title>
+<Text id="1213">Lists</Text>
+</Title>
+<Content>
+<Figure id="programming_a_list_of_integers" class="withLineNumber">
+<Title>
+<Text id="1214">Programming a list of integers</Text>
+</Title>
+<CodeLine>#include &lt;iostream.h&gt;</CodeLine>
+<CodeLine/>
+<CodeLine>#define nil 0</CodeLine>
+<CodeLine/>
+<CodeLine>struct intlist {</CodeLine>
+<CodeLine>   int val;</CodeLine>
+<CodeLine>   struct intlist* next;</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine/>
+<CodeLine>int total_int_list(intlist* head)</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>   int total = 0;</CodeLine>
+<CodeLine>   intlist* curr = head;</CodeLine>
+<CodeLine>   while (curr!=nil)</CodeLine>
+<CodeLine>   {</CodeLine>
+<CodeLine>       total += curr-&gt;val;</CodeLine>
+<CodeLine>       curr = curr-&gt;next;</CodeLine>
+<CodeLine>   }</CodeLine>
+<CodeLine/>
+<CodeLine>   return total;</CodeLine>
+<CodeLine>}</CodeLine>
+<CodeLine/>
+<CodeLine>void main()</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>   intlist node1 = { 5, nil };</CodeLine>
+<CodeLine>   intlist node2 = { 4, nil };</CodeLine>
+<CodeLine>   node2.next = &amp;node1;</CodeLine>
+<CodeLine/>
+<CodeLine>   int total = total_int_list(&amp;node2);</CodeLine>
+<CodeLine>  cout &lt;&lt; " List items total to: " &lt;&lt; total &lt;&lt; endl;</CodeLine>
+<CodeLine>}</CodeLine>
+</Figure>
+<Text id="1215">First we study two programs that implement an integer list. One uses basic C++ types (the âold fashionedâ way), the other uses STL. Figure <CrossRef target="Figure" ref="programming_a_list_of_integers"/> shows the source code implementation that does <i>not</i> use STL. Lines 5â8 define the basic data structure we are going to use: the field <i>val</i> stores the integer value, and <i>next</i> points to the next element in the listâa classic implementation of a linked list.</Text>
+<Text id="1216">To demonstrate use of the data structure, the main program (lines 23â32) sets up an integer list with elements [5, 4]. It then calls the function <i>total_int_list</i> (defined over lines 10â21) which takes as its only parameter a pointer to the head of a list and sums the values in it. The returned answer (9 in our example) is printed to the screen.</Text>
+<Text id="1217">The main work is accomplished by lines 12â18. First some initialisation: the local variable <i>total</i> is set to zero, and <i>curr</i> to point to the start of the list. Then a while loop adds the current integer element in the list to the running total (<i>total += curr-&gt;val;</i>) before moving on to the next element (<i>curr = curr-&gt;next;</i>). The while loop terminates when <i>curr</i> becomes equal to <i>nil</i>, signifying that there are no more elements left to process.</Text>
+<Figure id="programming_a_list_of_integers_using_stl">
+<Title>
+<Text id="1218">Programming a list of integers using STL</Text>
+</Title>
+<CodeLine>#include &lt;iostream.h&gt;</CodeLine>
+<CodeLine>#include &lt;list&gt;</CodeLine>
+<CodeLine/>
+<CodeLine>int total_int_list(list&lt;int&gt;* head)</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>   int total = 0;</CodeLine>
+<CodeLine>   list&lt;int&gt;::iterator curr = head-&gt;begin();</CodeLine>
+<CodeLine>   while (curr!=head-&gt;end())</CodeLine>
+<CodeLine>   {</CodeLine>
+<CodeLine>       total += *curr;</CodeLine>
+<CodeLine>       curr++;</CodeLine>
+<CodeLine>   }</CodeLine>
+<CodeLine/>
+<CodeLine>   return total;</CodeLine>
+<CodeLine>}</CodeLine>
+<CodeLine/>
+<CodeLine>void main()</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>   list&lt;int&gt; vals;</CodeLine>
+<CodeLine>   vals.push_back(5);</CodeLine>
+<CodeLine>   vals.push_back(4);</CodeLine>
+<CodeLine/>
+<CodeLine>   int total = total_int_list(&amp;vals);</CodeLine>
+<CodeLine>   cout &lt;&lt; " List items total to: " &lt;&lt; total &lt;&lt; endl;</CodeLine>
+<CodeLine>}</CodeLine>
+</Figure>
+<Text id="1219">Figure <CrossRef target="Figure" ref="programming_a_list_of_integers_using_stl"/> shows an equivalent program using STL. It is no longer necessary to define a suitable data structure in the code; all that is necessary is the <i>#include &lt;list&gt;</i> directive on line 2 that includes the template version for a list defined in STL. The object is called a âcontainer classâ because when we declare a variable of this type we also specify the type we want it to store. On line 19 an integer list is realised with the statement <i>list&lt;int&gt; vals;</i>. Elements can be added to the object using the member function <i>push_back()</i>, as is done on lines 20â21.</Text>
+<Text id="1220">The main work is done by lines 6â12. There are still two initialisations and a while loop, but other than that the new syntax has little in common with the old. Central to this new way of processing is a variable of type <i>iterator</i>(line 7). In STL many classes include <i>iterator</i> types to provide a uniform way of working through a sequence of container objects. The first element is returned with <i>begin()</i> and the element just past the last one with <i>end()</i>. Moving to the next element is accomplished by the increment operation ++, which is overloaded by the iterator class to implement this task, and the value stored there is accessed through dereferencing (<i>*curr</i> on line 10), which is also overloaded.</Text>
+<Text id="1221">The STL implementation of this program is slightly smaller (25 lines verses 31) than the conventional code. The gains are more noticeable in larger projects, because the STL <i>list</i> object is more powerful than the example here illustrates. It is, for instance, a doubly linked list that supports several forms of insertion and deletionâsomething that would require additional programming effort to add to the basic integer list version.</Text>
+<Text id="1222">Note that the parameter to <i>total_int_list</i> in Figure <CrossRef target="Figure" ref="programming_a_list_of_integers_using_stl"/> was implemented as a pointer, to correspond with the pointer used in <i>total_int_list</i> in Figure <CrossRef target="Figure" ref="programming_a_list_of_integers"/>. In STL it is often more natural (and more desirable) to use references rather than pointers. Then the parameter becomes <i>list&lt;int&gt;&amp; head</i>, and its member functions are called with the syntax <i>head.begin();</i> and so on.</Text>
+</Content>
+</Section>
+<Section id="maps">
+<Title>
+<Text id="1223">Maps</Text>
+</Title>
+<Content>
+<Text id="1224">When implementing a digital library system, it is useful to be able to store elements in an array indexed by text strings rather than by numeric indexes. In Greenstone, for example, this greatly simplifies storing the macro files once they have been read; and the various configuration files. A data type that supports such access is called an <i>associative array</i>, and is often built in to modern high-level languages. It is also known by the name <i>hash array</i> (most notably in Perl), since hashing is the normal technique used to implement the text index.</Text>
+<Figure id="using_associative_arrays_in_stl" class="withLineNumber">
+<Title>
+<Text id="1225">Using associative arrays in STL</Text>
+</Title>
+<CodeLine>#include &lt;iostream.h&gt;</CodeLine>
+<CodeLine>#include &lt;map&gt;</CodeLine>
+<CodeLine/>
+<CodeLine>int total_int_table(map&lt;char*, int&gt;&amp; table)</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>   int total = 0;</CodeLine>
+<CodeLine>   map&lt;char*, int&gt;::iterator curr = table.begin();</CodeLine>
+<CodeLine>   while (curr!=table.end())</CodeLine>
+<CodeLine>   {</CodeLine>
+<CodeLine>       total += (curr-&gt;second);</CodeLine>
+<CodeLine>       curr++;</CodeLine>
+<CodeLine>   }</CodeLine>
+<CodeLine/>
+<CodeLine>   return total;</CodeLine>
+<CodeLine>}</CodeLine>
+<CodeLine/>
+<CodeLine>int main()</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>   map&lt;char*, int&gt; table;</CodeLine>
+<CodeLine>   table["Alice"] = 31;</CodeLine>
+<CodeLine>   table["Peter"] = 24;</CodeLine>
+<CodeLine>   table["Mary"]   = 47;</CodeLine>
+<CodeLine/>
+<CodeLine>   int total = total_int_table(table);</CodeLine>
+<CodeLine>   cout &lt;&lt; " Age total: " &lt;&lt; total &lt;&lt; endl;</CodeLine>
+<CodeLine>  }</CodeLine>
+</Figure>
+<Text id="1226">In STL, associative arrays are accomplished using the <i>map</i> object. Figure <CrossRef target="Figure" ref="using_associative_arrays_in_stl"/> shows a somewhat contrived example that stores the age of three people (Alice, Peter and Mary) in an associative array under their own names (lines 19â22). The problem is to write a function that calculates the total age of the people present, without knowing how many there are or what their names are. Of course, this could be solved with a standard numeric array of integers. The example is contrived to demonstrate the features of the <i>map</i> object and bring out the similarity of processing with the <i>list</i> object with an <i>iterator</i>.</Text>
+<Text id="1227">Like <i>list</i>, <i>map</i> is a container class. However, when declaring a variable of this type we must specify two<FootnoteRef id="5"/> things: the index type, and the element type. As can be seen on line 19, we obtain an associative array that stores integers using <i>char*</i>(which is how a string is declared in C++) as the index type followed by <i>int</i> as the element type.</Text>
+<Text id="1228">There are several ways to store elements in the associative array. In the example on lines 20â22 the overloaded array subscript [ ] is used to initialise the table with the ages of the three people. The similarity of <i>total_int_table</i>âwhich performs the main calculation in the programâto <i>total_int_list</i> in Figure <CrossRef target="Figure" ref="programming_a_list_of_integers"/> is striking. In fact, they are nearly identical, and this is no coincidence. STL makes heavy use of inheritance so that different objects still use the same fundamental operations. This is particularly true with iterators. The small differences between the two functions are that the iterator is now derived from <i>map&lt;char*, int&gt;</i>, and access to its elements is with <i>curr-&gt;second()</i>âbecause dereferencing the variable (<i>*curr</i>) is defined to return an object of type <i>pair</i>. This records both the index name (<i>first</i>) and the element value (<i>second</i>), but we only want the latter. Other than that, the code remains the same. The only remaining differenceâchanging the function's only argument from a pointer to a referenceâis superficial.</Text>
+<Text id="1229">Two other STL types widely used in the Greenstone code are <i>vector</i> and <i>set</i>. The former facilitates dynamic arrays, and the latter supports mathematical set operations such as union, intersection and difference.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="bibliography">
+<Title>
+<Text id="1230">Bibliography</Text>
+</Title>
+<Content>
+<Text id="1231">Aulds, C. (2000) <i>Linux Apache Web Server Administration</i>. Sybex.</Text>
+<Text id="1232">Bainbridge, D., Buchanan, G., McPherson, J., Jones, S., Mahoui, A. and Witten, I.H. (2001) âGreenstone: A platform for distributed digital library development.â Research Report, Computer Science Department, University of Waikato, New Zealand.</Text>
+<Text id="1233">Christiansen, T. Torkington, N. and Wall, L. (1998) <i>Perl Cookbook.</i> O'Reilly and Associates.</Text>
+<Text id="1234">Coar, K.A.L. (1998) <i>Apache Server For Dummies</i>. IDG Books.</Text>
+<Text id="1235">Deitel, H.M. and Deitel, P.J. (1994) <i>C++: How to Program</i>. Prentice Hall, Englewood Cliffs, New Jersey.</Text>
+<Text id="1236">Dublin Core (2001) âThe Dublin Core Metadata Initiativeâ at http://purl.org/dc/, accessed 16 January 2001.</Text>
+<Text id="1237">Josuttis, N.M. (1999) <i>The C++ standard library: a tutorial and reference.</i> Addison-Wesley, 1999.</Text>
+<Text id="1238">Keller, M. and Holden, G. (1999) <i>Apache Server for Windows Little Black Book</i>. Coriolis Group.</Text>
+<Text id="1239">Schwartz, R.L. and Christiansen, T. (1997) <i>Learning Perl</i>(2nd Edition). O'Reilly and Associates.</Text>
+<Text id="1240">Slama, D., Garbis, J. and Russell, P. (1999) <i>Enterprise CORBA</i>. Prentice Hall, Englewood Cliffs, New Jersey.</Text>
+<Text id="1241">Stroustroup, B. (1997) <i>The C++ Programming Language</i>. Addison-Wesley.</Text>
+<Text id="1242">Thiele, H. (1997) âThe Dublin Core and Warwick Framework: A Review of the Literature, March 1995âSeptember 1997.â <i>D-Lib Magazine</i>, January. &lt;http://www.dlib.org/dlib/january98/01thiele.html&gt;</Text>
+<Text id="1243">Wall, L., Christiansen, T. and Orwant, J. (2000) <i>Programming Perl</i>(3rd Edition). O'Reilly and Associates.</Text>
+<Text id="1244">Weibel, S. (1999) âThe State of the Dublin Core Metadata Initiative.â <i>D-Lib Magazine</i>, Volume 5 Number 4; April. &lt;http://www.dlib.org/dlib/april99/04weibel.html&gt;</Text>
+<Text id="1245">Witten, I.H., Moffat, A. and Bell, T.C. (1999) <i>Managing gigabytes: compressing and indexing documents and images</i>. Morgan Kaufmann, San Francisco.</Text>
+</Content>
+</Chapter>
+<FootnoteList>
+<Footnote id="1">
+<Text id="1246">On Windows 95/98 systems running <i>setup.bat</i> may fail with an <i>Out of environment space</i> error. If this happens, you should edit your system's <i>config.sys</i> file (normally found at <i>C:\config.sys</i>) and add the line <i>shell=C:\command.com /e:4096 /p</i> (where <i>C:</i> is your system drive letter) to expand the size of the environment table. You'll need to reboot for this change to take effect, and then repeat the steps above for Greenstone.</Text>
+</Footnote>
+<Footnote id="2">
+<Text id="1247">Note that in Greenstone, regular expressions are interpreted in the Perl language, which is subtly different from some other conventions. For example, â*â matches zero or more occurrences of the previous character, while â.â matches any characterâso <i>nugget.*</i> matches any string with prefix ânugget,â whether or not it contains a period after the prefix. To insist on a period you would need to escape it, and write <i>nugget\..*</i> instead.</Text>
+</Footnote>
+<Footnote id="3">
+<Text id="1248">Note that more recent versions of the Demo collection use a Hierarchy classifier to display the how to metadata. In this case they will be displayed slightly differently to what is shown in Figure <CrossRef target="Figure" ref="list_classifier"/>.</Text>
+</Footnote>
+<Footnote id="4">
+<Text id="1249">The value for <i>gsdlhome</i> comes from <i>gsdlsite.cfg</i> located in the same directory as the CGI executable <i>library</i>, whereas <i>GSDLHOME</i> is set by running the <i>setup</i> script which accesses a different file, so technically it is possible for the two values to be different. While possible, it is not desirable, and the above text is written assuming they are the same.</Text>
+</Footnote>
+<Footnote id="5">
+<Text id="1250">Technically there are four types, but the last two are optional. Since we are only giving a basic introduction to this STL class, details about these last two types are omitted.</Text>
+</Footnote>
+</FootnoteList>
+</Manual>
Index: /tags/start/gsdl-documentation/manuals/xml-source/en/Install_en.xml
===================================================================
--- /tags/start/gsdl-documentation/manuals/xml-source/en/Install_en.xml	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/xml-source/en/Install_en.xml	(revision 13666)
@@ -0,0 +1,1005 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Manual>
+<Heading>
+<Text id="1">GREENSTONE DIGITAL LIBRARY</Text>
+</Heading>
+<Title>
+<Text id="2">INSTALLER'S GUIDE</Text>
+</Title>
+<Author>
+<Text id="3">Ian H. Witten and Stefan Boddie</Text>
+</Author>
+<Affiliation>
+<Text id="4">Department of Computer Science <br/>University of Waikato, New Zealand</Text>
+</Affiliation>
+<Text id="5">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 New Zealand Digital Library Project at the University of Waikato, and developed 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.</Text>
+<Comment>
+<Text id="6">We want to ensure that this software works well for you. Please report any problems to <i>greenstone@cs.waikato.ac.nz</i></Text>
+</Comment>
+<Version>
+<Text id="7">Greenstone gsdl-2.50</Text>
+</Version>
+<Date>
+<Text id="8">March 2004</Text>
+</Date>
+<Section id="about_this_manual">
+<Title>
+<Text id="9">About this manual</Text>
+</Title>
+<Content>
+<Text id="10">This document explains how to install Greenstone so that you can run it on your own computer. It also describes how to obtain associated software that is freely availableâthe Apache Webserver and Perl. We have striven to make the installation procedure as simple as it possibly can be.</Text>
+<Text id="11">The software runs on different platforms, and in different configurations. Consequently there are many issues that affect (or might affect) the installation procedure. Section <CrossRef target="Chapter" ref="versions_of_greenstone"/> mentions some questions that you will need to consider before installing Greenstone. Section <CrossRef target="Chapter" ref="installation_procedure"/> details the installation procedure for all the different versions; you need only read the part that relates to your operating system. Section <CrossRef target="Chapter" ref="greenstone_collections"/> describes the demonstration digital library collections that are included in the distribution. Section <CrossRef target="Chapter" ref="setting_up_webserver"/> explains how to set up common webservers, Apache and Microsoft PWS/IIS, to work with Greenstone. Section <CrossRef target="Chapter" ref="configuring_your_site"/> describes various Greenstone configuration options, and Section <CrossRef target="Chapter" ref="personalizing"/> shows how to make a personalized home page for your digital library installation. Finally, an Appendix <CrossRef target="Chapter" ref="appendix_associated_software"/> lists pieces of associated software and how to obtain them.</Text>
+</Content>
+</Section>
+<Section id="companion_documents">
+<Title>
+<Text id="12">Companion documents</Text>
+</Title>
+<Content>
+<Text id="13">The complete set of Greenstone documents include five volumes:</Text>
+<BulletList>
+<Bullet>
+<Text id="14">Greenstone Digital Library Installer's Guide <i>(this document)</i></Text>
+</Bullet>
+<Bullet>
+<Text id="15">Greenstone Digital Library User's Guide</Text>
+</Bullet>
+<Bullet>
+<Text id="16">Greenstone Digital Library Developer's Guide</Text>
+</Bullet>
+<Bullet>
+<Text id="17">Greenstone Digital Library: From Paper to Collection</Text>
+</Bullet>
+<Bullet>
+<Text id="18">Greenstone Digital Library: Using the Organizer</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Section>
+<Section id="acknowledgements">
+<Title>
+<Text id="19">Acknowledgements</Text>
+</Title>
+<Content>
+<Text id="20">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, Hong Chen, Michael Dewsnip, Katherine Don, Elke Duncker, Carl Gutwin, Geoff Holmes, Dana McKay, 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, PERL, WGET, WVWARE and XLHTML.</Text>
+</Content>
+</Section>
+<Chapter id="versions_of_greenstone">
+<Title>
+<Text id="21">Versions of Greenstone</Text>
+</Title>
+<Content>
+<Text id="22">The Greenstone software runs on different platforms, and in different configurations, as summarized in Figure <CrossRef target="Figure" ref="different_options"/>.</Text>
+<Figure id="different_options">
+<Title>
+<Text id="23">The different options for Windows and Unix versions of Greenstone</Text>
+</Title>
+<File width="542" height="264" url="images/Install_Fig_1.gif"/>
+</Figure>
+<Text id="24">There are many issues that affect (or might affect) the installation procedure. Before reading on, you should consider these questions:</Text>
+<BulletList>
+<Bullet>
+<Text id="25">Are you using Windows or Unix?</Text>
+</Bullet>
+<Bullet>
+<Text id="26">If Windows, are you using Windows 3.1/3.11 or a more recent version? Although you can view collections on 3.1/3.11 machines, and serve other computers on the same network, you cannot build new collections. The full Greenstone software runs on 95/98/Me, and NT/2000.</Text>
+</Bullet>
+<Bullet>
+<Text id="27">If Unix, are you using Linux or another version of Unix? For Linux, a binary version of the complete system is provided which is easy to install. For other types of Unix you will have to install the source code and compile it. This may require you to install some additional software on your machine.</Text>
+</Bullet>
+<Bullet>
+<Text id="28">If Windows NT/2000 or Unix, can you log in as the system âadministratorâ or ârootâ? This may be required to configure a webserver appropriately for Greenstone.</Text>
+</Bullet>
+<Bullet>
+<Text id="29">Do you want the source code? If you are using Windows or Linux, you can just install binaries. But you may want the source code as wellâit's in the Greenstone distribution.</Text>
+</Bullet>
+<Bullet>
+<Text id="30">Do you want to build new digital library collections? If so, you need to have Perl, which is freely available for both Windows and Unix.</Text>
+</Bullet>
+<Bullet>
+<Text id="31">Is your computer running a webserver? The Greenstone software comes with a Windows webserver. However, if you are already running a Web server, you may want to stay with it. For Unix, you need to run a webserver.</Text>
+</Bullet>
+<Bullet>
+<Text id="32">Do you know how to reconfigure your webserver? If you don't use the Greenstone webserver, you will have to reconfigure your existing one slightly to recognize the Greenstone software.</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Chapter>
+<Chapter id="installation_procedure">
+<Title>
+<Text id="33">The Installation Procedure</Text>
+</Title>
+<Content>
+<Text id="34">Versions of Greenstone are available for both Windows and Unix, as binaries and in source code form. The Greenstone user interface uses a Web browser: Netscape Navigator or Internet Explorer (version 4.0 or greater in both cases) are both suitable. In case you don't already have a Web browser, Windows versions of Netscape are provided on the CD-ROM.</Text>
+<Section id="windows">
+<Title>
+<Text id="35">Windows</Text>
+</Title>
+<Content>
+<Text id="36">If you are a Unix user, please skip ahead to Section <CorssRef target="Section" ref="unix"/>. For Windows users, if you want just a simple, straightforward installation, go through the following âsimple installationâ procedure. The Greenstone system occupies about 40 Mb of disk space.</Text>
+<Text id="37">If you choose anything other than the default setup, you will have to decide whether you want to install the binary code or the source code. If in doubt, choose the binary code. The installation procedure is the same for both. The following sections tell you more about the options you will be presented with.</Text>
+<Text id="38">When you've finished installation you should skip ahead to Section <CorssRef target="Section" ref="how_to_find_greenstone"/>.</Text>
+<Subsection id="simple_installation">
+<Title>
+<Text id="39">Simple installation</Text>
+</Title>
+<Content>
+<Text id="40">To install the Windows version from the CD-ROM, insert the disk into the drive (e.g. into <i>D:</i>). If the installation procedure does not start automatically after about 20 seconds, click on the <i>Start</i> menu, select <i>Run</i> and type <i>D:\setup.exe</i>, where â <i>D</i> â is the letter that identifies your CD-ROM drive. For Windows 3.1, select <i>Run</i> from the âFile managerâ and type <i>D:\Windows\win3.1\setup.exe</i>.</Text>
+<Text id="41">For the simplest installation, just accept the default at each point by clicking the <i>Next</i> button. That's all you need to do! Greenstone is installed in the directory <i>C:\Program Files\gsdl</i>.</Text>
+<Text id="42">Once installation is complete, to start your Greenstone system click on the <i>Start</i> button, open the <i>Program</i> menu, and select <i>Greenstone Digital Library</i>. This brings up a dialogue box: just click <i>Enter Library.</i> This automatically starts your Internet browser and loads the Greenstone Digital Library home page, which should look something like the example in Figure <CrossRef target="Figure" ref="your_greenstone_home_page"/>. You enter the Greenstone Demo collection by clicking on its icon.</Text>
+<Figure id="your_greenstone_home_page">
+<Title>
+<Text id="43">Your Greenstone home page</Text>
+</Title>
+<File width="395" height="327" url="images/Install_Fig_2.png"/>
+</Figure>
+</Content>
+</Subsection>
+<Subsection id="windows_binaries">
+<Title>
+<Text id="44">Windows binaries</Text>
+</Title>
+<Content>
+<Text id="45">There are two separate Windows binary programs on the CD-ROM: the <i>Local Library</i> and the <i>Web Library</i>. The default installation described above selects the Local Library version. We strongly recommend that you use this version. The Web Library, which is much harder to set up, is only necessary if you already run a web server and want to use it for Greenstone. Despite its modest name, the Local Library offers a complete, self-contained, web-serving capability.</Text>
+<Text id="46">Local Library. This enables any Windows computer to serve pre-built Greenstone collections. The Greenstone Demo collection will automatically be installed; you can also install the other collections on the CD-ROM (Section <CrossRef target="Chapter" ref="greenstone_collections"/>). The Local Library software is the same as that used on CD-ROMs produced by the Greenstone system.</Text>
+<Text id="47">The Local Library is intended for use on standalone computers or computers that do not already have webserver software. It contains a small built-in webserver so that other computers on the same network can also access the library. (However, the webserver has limited configurability.)</Text>
+<Text id="48">The Local Library software automatically determines whether your computer has network software installed or is connected to a network. It operates correctly under any combinations of these conditions. However, there are two possible problems that may be encountered. Greenstone may</Text>
+<BulletList>
+<Bullet>
+<Text id="49">cause an unwanted telephone dialup operation;</Text>
+</Bullet>
+<Bullet>
+<Text id="50">fail to run because network software is installed, but installed incorrectly.</Text>
+</Bullet>
+</BulletList>
+<Text id="51">A restricted version of the Local Library is supplied which is intended for use in these situations. The restricted version only works with Netscape (not Internet Explorer). When you invoke the Local Library version of Greenstone, the dialogue box contains a button that allows you to use the restricted version instead. Unless the above problems arise, you should always use the standard version.</Text>
+<Text id="52"><b>Web Library</b>. This enables any computer with an existing webserver to serve pre-built Greenstone collections. As with the Local Library above, the Greenstone Demo collection will automatically be installed. You can also install the other collections on the CD-ROM (see Section <CrossRef target="Chapter" ref="greenstone_collections"/>).</Text>
+<Text id="53">The Web Library differs from the Local Library because it is intended for computers that already have webserver software.</Text>
+<Text id="54">To run the Web Library, you also need</Text>
+<BulletList>
+<Bullet>
+<Text id="55">Webserver software. One possibility is Apache (see Appendix <CrossRef target="Chapter" ref="appendix_associated_software"/>).</Text>
+</Bullet>
+<Bullet>
+<Text id="56"><b>The Collector</b>. This component, which is included in both the Local Library and the Web Library, allows you to build collections containing material of your choice. (You will not be able to use the Collector on a Windows 3.1/3.11 machine.)</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Subsection>
+<Subsection id="windows_webserver_configuration">
+<Title>
+<Text id="57">Windows webserver configuration (Web Library version only)</Text>
+</Title>
+<Content>
+<Text id="58">An advantage of the Local Library version of Greenstone is that it runs âout of the boxâ and does not require any special configuration. For the Web Library version, however, you will have to make some adjustments to your webserver setup.</Text>
+<Text id="59">If you already have a webserver, some small changes have to be made to its configuration to make your Greenstone installation operate. The install script explains what these are for the Apache webserverâsee Section <CrossRef target="Section" ref="pws_and_iis_webservers"/> for instructions for configuring the PWS and IIS webservers. You may need help from a system administrator to reconfigure an existing webserverâthey should be able to understand the instructions printed by the install script.</Text>
+<Text id="60">If you do not already have a webserver, you will have to install one. (See the Appendix <CrossRef target="Chapter" ref="appendix_associated_software"/> for information on the Apache webserver.) Then you will have to configure it appropriately. Section <CrossRef target="Chapter" ref="setting_up_webserver"/> gives a detailed account of the parts of a webserver installation that affect Greenstone, and how they need to be altered. It comes down to including half a dozen or so lines in a configuration file.</Text>
+</Content>
+</Subsection>
+<Subsection id="windows_source">
+<Title>
+<Text id="61">Windows source</Text>
+</Title>
+<Content>
+<Text id="62">The Greenstone source code occupies 50 Mb of disk space, but to compile it you will need about 90 Mb. To compile the source on Windows you need</Text>
+<BulletList>
+<Bullet>
+<Text id="63">The Microsoft Visual C++ compiler. (We are currently sorting out some minor problems in compiling Greenstone with various Windows ports of GNU GCC.)</Text>
+</Bullet>
+</BulletList>
+<Text id="64">(You do not need GDBM, the Gnu database manager, because it is included in the Greenstone source distribution.)</Text>
+<Text id="65">It is unlikely that you will be able to compile Greenstone on a Windows 3.1/3.11 machine.</Text>
+<Text id="66">In the event that you recompile Greenstone and wish to use the recompiled version to create CD-ROMs, you should note that code produced by recent versions of the Visual C++ compiler does not run under Windows 3.1/3.11, although there is no problem with later Windows systems (95, 98, Me, NT, 2000). If you want your CD-ROMs to operate on early Windows machines, you will need a different version of the compiler. Moreover, Greenstone uses STL, the C++ standard template library, and although these compilers sometimes come with STL, the provided version does not always work properly. Hence to recompile Greenstone in such a way that it produces CD-ROMs that work on early versions of Windows, you need</Text>
+<BulletList>
+<Bullet>
+<Text id="67">The Microsoft Visual C++ compiler, Version 4.0 or 4.2.</Text>
+</Bullet>
+<Bullet>
+<Text id="68">An external version of STL, the C++ standard template library. STL is packaged with Greenstone for use with these compiler versions.</Text>
+</Bullet>
+</BulletList>
+<Text id="69">Note that the Windows installation procedure does not attempt to compile Greenstone for you if you choose to install the source code. For platform- and compiler-specific instructions on compiling Greenstone, see the <i>Install.txt</i> document which is placed in the top-level Greenstone directory (<i>C:\Program Files\gsdl</i> by default) during the installation procedure.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="unix">
+<Title>
+<Text id="70">Unix</Text>
+</Title>
+<Content>
+<Text id="71">This section is written for Unix users. (Windows users should skip ahead to Section <CrossRef target="Section" ref="how_to_find_greenstone"/>.) You need to choose whether to install the binary code or the source code. The binary code occupies about 50 Mb of disk space; the source code requires about 160 Mb to compile.</Text>
+<Subsection id="unix_binaries">
+<Title>
+<Text id="72">Unix binaries</Text>
+</Title>
+<Content>
+<Text id="73">The binary code requires an Intel x86-based Linux distribution which includes ELF binary support. Distributions that meet these requirements include:</Text>
+<BulletList>
+<Bullet>
+<Text id="74">RedHat 5.1</Text>
+</Bullet>
+<Bullet>
+<Text id="75">SuSE Linux 6.1</Text>
+</Bullet>
+<Bullet>
+<Text id="76">Debian 2.1</Text>
+</Bullet>
+<Bullet>
+<Text id="77">Slackware 4.0</Text>
+</Bullet>
+</BulletList>
+<Text id="78">More recent versions of these distributions should also work.</Text>
+<Text id="79">You will need a webserver: we recommend Apache. We also strongly recommend you to install your webserver <i>before</i> installing Greenstoneâthis will make it much easier to answer the questions that are asked during the Greenstone installation procedure. If you want to build new digital library collections, you will also need Perl if this is not already on your system. To check, open a terminal window, type <i>perl âv</i>, and see if a message appears specifying, amongst other things, the version number. For most versions of Linux, Perl is installed by default. The Appendix <CrossRef target="Chapter" ref="appendix_associated_software"/> gives information on how to obtain Apache and Perl.</Text>
+</Content>
+</Subsection>
+<Subsection id="unix_source">
+<Title>
+<Text id="80">Unix source</Text>
+</Title>
+<Content>
+<Text id="81">The source code is the same for Unix as for Windows. It has been compiled and tested on Linux, Solaris, and Macintosh OS/X; it should be a fairly routine matter to port it to other flavors of Unix.</Text>
+<Text id="82">To compile the Greenstone source code on Unix, you need</Text>
+<BulletList>
+<Bullet>
+<Text id="83">GCC, the Gnu C++ compiler.</Text>
+</Bullet>
+<Bullet>
+<Text id="84">GDBM, the Gnu database manager.</Text>
+</Bullet>
+</BulletList>
+<Text id="85">To run the Greenstone software, you also need a Web server and Perl, as described above under <i>Unix binaries</i>.</Text>
+</Content>
+</Subsection>
+<Subsection id="unix_installation">
+<Title>
+<Text id="86">Unix installation</Text>
+</Title>
+<Content>
+<Text id="87">To install the Unix version from the CD-ROM, insert the disk into the drive, and type</Text>
+<Table class="hidden" id="table_commands">
+<Title/>
+<TableContent>
+<tr>
+<th width="151">
+<CodeLine>mount /cdrom</CodeLine>
+</th>
+<th width="246">
+<Text id="88">mount the CD-ROM device (this command may differ from one system to another; for example on OS/X you <i>cd</i> to the <i>/Volumes</i> directory and then to the appropriate subdirectory for the CD-ROM)</Text>
+</th>
+</tr>
+<tr>
+<th width="151">
+<CodeLine>cd /cdrom</CodeLine>
+</th>
+<th width="246">
+<Text id="89">change directory to the CD-ROM's top level</Text>
+</th>
+</tr>
+<tr>
+<th width="151">
+<CodeLine>cd Unix</CodeLine>
+</th>
+<th width="246">
+<Text id="90">change directory to where the Unix install script resides</Text>
+</th>
+</tr>
+<tr>
+<th width="151">
+<CodeLine>sh Install.sh</CodeLine>
+</th>
+<th width="246">
+<Text id="91">begin the installation process (an explicit <i>sh</i> is used because many installations forbid you to execute programs directly from CD-ROM)</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="92">The final command begins an interactive dialogue which requests the information that is needed to install Greenstone on your system, and gives detailed feedback on what is happening.</Text>
+<Text id="93">The installation procedure begins by asking you which directory to install Greenstone into. The first file placed there is the âuninstallâ program that cleans up any partial installation, should you encounter problems or terminate the installation prematurely. Next you choose whether you want to install binaries or source code. You are then asked some questions about your webserver setup. You need to have a valid cgi executable directory (normally called âcgi-binâ on Unix systems); you can either create a new one or use your existing one. If you create a new one, you will need to enter this information in your webserver's configuration file. In either case you need to enter the web address of the cgi directory. The installation dialogue will guide you through all these choices. It is important to set the file permissions correctly on certain directories, and you are prompted for the necessary information. Finally, you are prompted for a password for the âadministratorâ user <i>admin</i>.</Text>
+<Text id="94">By default, all Greenstone software is installed in the directory <i>/usr/local/gsdl</i> if it is the root user who is doing the installation, and into the directory ~<i>/gsdl</i> otherwise (where â~â is the user's home directory).</Text>
+<Text id="95">Installing the binaries takes just a few minutes, enough time for you to answer the appropriate questions. If you install the source code, the installation script will compile it, which takes from ten minutes to an hour or so, depending on the speed of your processor.</Text>
+<Text id="96">To uninstall the software, type</Text>
+<CodeLine>cd ~/gsdl</CodeLine>
+<Text id="97">or <i>/usr/local/gsdl</i> if it was the root user who installed Greenstone</Text>
+<CodeLine>sh Uni nstall.sh</CodeLine>
+<Text id="98">During the installation procedure you will be asked whether you want to install any Greenstone collections. The Greenstone Demo collection is installed automatically; other collections on the CD-ROM are described in Section <CrossRef target="Chapter" ref="greenstone_collections"/>.</Text>
+</Content>
+</Subsection>
+<Subsection id="unix_webserver_configuration">
+<Title>
+<Text id="99">Unix webserver configuration</Text>
+</Title>
+<Content>
+<Text id="100">If you already have a webserver, some small changes will have to be made to its configuration to make your Greenstone installation operate. The install script explains what these are. You will probably need help from your system administrator to reconfigure the webserverâhe or she should be able to understand the instructions output by the install script. For your convenience, the output of the install script is written to a file called INSTALL_RECORD in the directory into which you installed Greenstone.</Text>
+<Text id="101">If you do not already have a webserver, you will have to install one. The Appendix <CrossRef target="Chapter" ref="appendix_associated_software"/> gives information on Apache. Then you will have to configure it appropriately. Section <CrossRef target="Chapter" ref="setting_up_webserver"/> gives a detailed account of the parts of an Apache webserver installation that affect Greenstone, and how they need to be altered. It comes down to including half a dozen or so lines in a configuration file.</Text>
+<Text id="102">You do not need to be the Unix ârootâ user to go through the installation procedure above. When it comes to configuring an existing Apache server, however, you may need ârootâ privilegesâit all depends on how Apache is set up. If you install Apache yourself, you can do it as a user without ârootâ privileges. If you need to work your way around an uncooperative system administrator, you can always install a second Apache webserver on your computerâeven if one exists already.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="how_to_find_greenstone">
+<Title>
+<Text id="103">How to find Greenstone</Text>
+</Title>
+<Content>
+<Subsection id="local_library_windows_only">
+<Title>
+<Text id="104">Local library (Windows only)</Text>
+</Title>
+<Content>
+<Text id="105">If you are using the Local Library, simply run the <i>Greenstone</i> program from the <i>Start</i> menu. This automatically opens a dialog box that starts your Internet browser and loads the Greenstone Digital Library home page. The Greenstone Demo collection should be accessible from this page. The dialog box contais a <i>File</i> menu item that allows you to change the default browser used by Greenstone. It doesn't matter whether you use Netscape or Internet Explorer, except that if you are running on Windows 2000, we recommend that you use Internet Explorer.</Text>
+</Content>
+</Subsection>
+<Subsection id="web_library_windows_and_unix">
+<Title>
+<Text id="106">Web library (Windows and Unix)</Text>
+</Title>
+<Content>
+<Text id="107">If you are using the Web Library, once you have installed the software and configured the webserver, use this URL to enter your Greenstone system:</Text>
+<Text id="108"><i>http://localhost/gsdl/cgi-bin/library</i></Text>
+<Text id="109">The Greenstone Demo collection should be accessible from this page.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_collector">
+<Title>
+<Text id="110">The Collector</Text>
+</Title>
+<Content>
+<Text id="111">A link to the Collector is provided on the digital library home page.</Text>
+</Content>
+</Subsection>
+<Subsection id="administration">
+<Title>
+<Text id="112">Administration</Text>
+</Title>
+<Content>
+<Text id="113">A link to the Administration pages is provided on the digital library home page. The âadministratorâ user is called <i>admin</i>, with a password that you specified during the installation process. The administrator is authorized to add new users, and to build collections.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="the_greenstone_librarian_interface_(gli)">
+<Title>
+<Text id="114">The Greenstone Librarian Interface (GLI)</Text>
+</Title>
+<Content>
+<Text id="115">The Greenstone Librarian Interface (GLI) is a tool to assist you with building digital libraries using Greenstone. It gives you access to Greenstone's collection-building functionality from an easy-to-use âpoint and clickâ interface.</Text>
+<Text id="116">GLI is installed automatically with all distributions of Greenstone. It is placed in the subdirectory <i>gli</i> of the top-level Greenstone directory (<i>C:\Program Files\gsdl\gli</i> by default). Note that it runs in conjunction with Greenstone and will not work properly unless it is placed in a subdirectory of your Greenstone installation. If you have downloaded one of the Greenstone distributions, this will be the case.</Text>
+<Text id="117">To use the GLI, your computer needs to have the Java Runtime Environment. If it doesn't, the installer will offer to install a version that is included on the CD-ROM. On Unix, you will also need to ensure that Perl is installed (for Windows, Perl is already included in the Greenstone software). Please report any problems you have running or using the Librarian Interface to <u>greenstone@cs.waikato.ac.nz</u>.</Text>
+<Subsection id="running_under_windows">
+<Title>
+<Text id="118">Running under Windows</Text>
+</Title>
+<Content>
+<Text id="119">To run GLI under Windows, browse to the <i>gli</i> folder in your Greenstone installation (e.g. using Windows Explorer), and double-click on the file called <i>gli.bat</i>. This file checks that Greenstone, the Java Runtime Environment, and Perl are all installed, and starts the Greenstone Librarian Interface.</Text>
+</Content>
+</Subsection>
+<Subsection id="running_under_unix">
+<Title>
+<Text id="120">Running under Unix</Text>
+</Title>
+<Content>
+<Text id="121">To run GLI under Unix, change to the <i>gli</i> directory in your Greenstone installation, then run the <i>gli.sh</i> script. This script checks that Greenstone, the Java Runtime Environment, and Perl are all installed and on your search path, and starts the Greenstone Librarian Interface.</Text>
+</Content>
+</Subsection>
+<Subsection id="getting_help">
+<Title>
+<Text id="122">Getting help</Text>
+</Title>
+<Content>
+<Text id="123">The Greenstone Librarian Interface has extensive on-line help facilities. You get help by clicking the <i>Help</i> button at the top right of the screen. This opens up the text to a section that relates to what you are doingâwhich of the GLI panels you are on. You can click around the help text to learn what you need to know. Use it.</Text>
+</Content>
+</Subsection>
+<Subsection id="compiling_gli">
+<Title>
+<Text id="124">Compiling the Greenstone Librarian Interface</Text>
+</Title>
+<Content>
+<Text id="125">If you have downloaded the Greenstone source distribution, you will have the Java source code of the Librarian Interface. To compile it, your computer needs to have a Java Development Kit. The Appendix <CrossRef target="Chapter" ref="appendix_associated_software"/> gives information on how to obtain this. To compile the source code, run the <i>makegli.bat</i>(Windows) or <i>makegli.sh</i>(Unix) files. Once compiled, you can run GLI as described above.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="testing_and_troubleshooting">
+<Title>
+<Text id="126">Testing and troubleshooting</Text>
+</Title>
+<Content>
+<Text id="127">To test Greenstone, point your Web browser at the Greenstone home page and explore the Demo collection and any other collections that you have installed. Don't worryâyou can't break anything. Click liberally: most images that appear on the screen are clickable. If you hold the mouse stationary over an image, most browsers will soon pop up a message that tells you what will happen if you click. Experiment! Choose common words like âtheâ and âandâ to search forâthat should evoke some responses, and nothing will break.For more information, see the <i>Greenstone Digital Library User's Guide</i>.</Text>
+<Subsection id="troubleshooting">
+<Title>
+<Text id="128">Troubleshooting</Text>
+</Title>
+<Content>
+<Table id="table_troubleshooting">
+<Title/>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="129">Problem</Text>
+</th>
+<th width="246">
+<Text id="130">Try this</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="131">Local Library (Windows only)</Text>
+</th>
+<th width="151">
+<Text id="132">When I start Greenstone my computer asks me to dial up my Internet Service Provider.</Text>
+</th>
+<th width="246">
+<Text id="133">Push the <i>Cancel</i> button in the dialog box. This usually solves the problem.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="134">When I start Greenstone my computer <i>still</i> asks me to dial up my Internet Service Provider.</Text>
+</th>
+<th width="246">
+<Text id="135">Choose the âRestricted versionâ when you run Greenstone. This version only works with Netscape.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="136">When I point my browser at the digital library, it can't find that page.</Text>
+</th>
+<th width="246">
+<Text id="137">Check your Internet Proxy settings and turn proxies off (use <i>Edit preferences</i> on Netscape or <i>Internet options</i> on Explorer).</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="138">The Collector seems to be working very slowly!</Text>
+</th>
+<th width="246">
+<Text id="139">Are you using Netscape under Windows 2000? If so, try using Internet Explorer insteadâon Windows 2000 (only) there seems to be some incompatibility with Netscape.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="142">Web Library (Windows and Unix)</Text>
+</th>
+<th width="151">
+<Text id="143">When I start Apache, it quits immediately.</Text>
+</th>
+<th width="246">
+<Text id="144">Add a <i>ServerName localhost</i> directive to the Apache configuration file (see Section <CrossRef target="Section" ref="apache_web_server"/>).</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="145">When I point my browser at the digital library, it displays garbageâa binary file.</Text>
+</th>
+<th width="246">
+<Text id="146">Check the <i>ScriptAlias</i> directive in the Apache configuration file, making sure it comes before the <i>Alias</i> directive (see Sections 4.2 and 4.3).</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="147">I get the Greenstone home page (Figure <CrossRef target="Figure" ref="your_greenstone_home_page"/>), but the Demo collection icon does not appear.</Text>
+</th>
+<th width="246">
+<Text id="148">Run the program <i>library</i> (in the cgi-bin directory) from the DOS (or shell) prompt to generate debugging information that will help you locate the problem.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="149">Both versions</Text>
+</th>
+<th width="151">
+<Text id="150">When I point my browser at the digital library, it can't find that page.</Text>
+</th>
+<th width="246">
+<Text id="151">Try using 127.0.0.1 in place of <i>localhost</i>. This reserved IP number is defined to be a âloopbackâ to your local computer.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="152">My browser complains that it can't find <i>main.cfg</i>.</Text>
+</th>
+<th width="246">
+<Text id="153">Check that the Greenstone files exist and are world-readable. If you are using the Web library, try running the <i>library</i> program from the command line. If it runs OK, the problem is with file permissions (see Section <CrossRef target="Section" ref="file_permissions"/>). If not, the <i>gsdlhome</i> variable is probably set incorrectly in the <i>gsdlsite.cfg</i> configuration file (see Section <CrossRef target="Section" ref="gsdlsite_configuration_file"/>).</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="154">I'm having trouble using the Collector.</Text>
+</th>
+<th width="246">
+<Text id="155">Read the <i>Greenstone Digital Library User's Guide</i>, Section <CrossRef external="User" lang="en" target="Chapter" ref="making_greenstone_collections"/>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="156">I've added a new user but they can't seem to log in.</Text>
+</th>
+<th width="246">
+<Text id="157">Check that the directory <i>C:\Program Files\gsdl\etc</i> and all its contents are globally writeable (see Section <CrossRef target="Section" ref="file_permissions"/>).</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="learn_more">
+<Title>
+<Text id="158">To learn more</Text>
+</Title>
+<Content>
+<Text id="159">To learn more about the innards of your Greenstone installation, consult the <i>Greenstone Digital Library Developer's Guide</i>. It includes (for example) details of the directory structure that has been created, and information about how to configure your Greenstone site.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="greenstone_collections">
+<Title>
+<Text id="160">Greenstone Collections</Text>
+</Title>
+<Content>
+<Text id="161">Several demonstration Greenstone collections are included on the CD-ROM. If you have Web access, many others can be downloaded, in either pre-built or unbuilt form, from the New Zealand Digital Library Project website (<i>nzdl.org</i>).</Text>
+<Text id="162">The Greenstone Demo collection is a small subset of the Humanity Development Library (HDL), a polished collection. It illustrates that relatively rich browsing capabilities can be provided (so long as suitable metadata is available). It is included automatically when the software is installed.</Text>
+<Text id="163">Greenstone also comes with some well-documented example collections whose âaboutâ page describes how they are constructed. They demonstrate various capabilities of Greenstone. The install dialogue will ask you whether you want to include them in your Greenstone installation; the approximate amount of disk space needed for each collection is shown below.</Text>
+<Table class="hidden" id="table_collections">
+<Title/>
+<TableContent>
+<tr>
+<th width="60">
+<Text id="164"><i>demo</i></Text>
+</th>
+<th width="182">
+<Text id="165">Greenstone Demo<br/>(7 Mb)</Text>
+</th>
+<th width="294">
+<Text id="166">A small subset of the HDL. If you clone this collection, the full facilities will only appear if your new files provide appropriate metadata information.</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="167"><i>dls-e</i></Text>
+</th>
+<th width="182">
+<Text id="168">Development Library Subset collection<br/>(150 Mb)</Text>
+</th>
+<th width="294">
+<Text id="169">Like the Greenstone Demo, this is a subset of the HDLâbut much larger. It contains 250 publicationsâbooks, reports and magazinesâin various areas of human development (the full HDL contains 1,230 publications). It has the same structure as the Greenstone Demo. It's fairly complex, and if you're just starting out you might prefer to look at some other collections first (e.g. <i>MSWord and PDF demonstration</i>, the <i>Greenstone Archives</i>, or the <i>Simple image collection</i>).</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="170"><i>wrdpdf-e</i></Text>
+</th>
+<th width="182">
+<Text id="171">MSWord and PDF demonstration<br/>(4 Mb)</Text>
+</th>
+<th width="294">
+<Text id="172">This contains a few documents in PDF, MSWord, RTF, and Postscript formats, demonstrating the ability to build collections from documents in different formats. The collection configuration file is very simple.</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="173"><i>gsarch-e</i></Text>
+</th>
+<th width="182">
+<Text id="174">Greenstone Archives collection<br/>(5 Mb)</Text>
+</th>
+<th width="294">
+<Text id="175">A collection of email messages from the Greenstone mailing list archives, this uses the Email plugin, which parses files in email formats. The collection configuration file is very simple.</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="176"><i>cltbib-e</i></Text>
+</th>
+<th width="182">
+<Text id="177">Bibliography collection<br/>(7 Mb)</Text>
+</th>
+<th width="294">
+<Text id="178">With about 4,000 bibliography entries, this collection incorporates a form-based search interface that allows fielded searching. It is fairly complex.</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="179"><i>cltext-e</i></Text>
+</th>
+<th width="182">
+<Text id="180">Bibliography supplement<br/>(1 Mb)</Text>
+</th>
+<th width="294">
+<Text id="181">This tiny collection of 10 bibliography entries illustrates the "supercollection" facility which searches several collections together, seamlessly. It operates together with the <i>Bibliography</i> collection, and its configuration file is almost the same.</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="182"><i>MARC-e</i></Text>
+</th>
+<th width="182">
+<Text id="183">MARC example<br/>(1 Mb)</Text>
+</th>
+<th width="294">
+<Text id="184">Based on some MARC records from the Library of Congress, this is a simple collection (and does not allow form-based searching).</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="185"><i>oai-e</i></Text>
+</th>
+<th width="182">
+<Text id="186">OAI demo collection<br/>(18 Mb)</Text>
+</th>
+<th width="294">
+<Text id="187">Using the Open Archive Protocol and the <i>Import-From</i> feature, this retrieves metadata from an archive and builds a collection from the records. In this case they are images, so both the OAI and Image plugins are used.</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="188"><i>image-e</i></Text>
+</th>
+<th width="182">
+<Text id="189">Simple image collection<br/>(1 Mb)</Text>
+</th>
+<th width="294">
+<Text id="190">This very basic image collection contains no text and no explicit metadataâwhich makes it rather unrealistic. The configuration file is about as simple as you can get.</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="191"><i>authen-e</i></Text>
+</th>
+<th width="182">
+<Text id="192">Formatting and authentication demo<br/>(8 Mb)</Text>
+</th>
+<th width="294">
+<Text id="193">With the same material as the original Greenstone demo collection, this shows off two independent features: non-standard document formatting, and controlled access to the documents via user authentication.</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="194"><i>garish</i></Text>
+</th>
+<th width="182">
+<Text id="195">Garish version of demo collection<br/>(8 Mb)</Text>
+</th>
+<th width="294">
+<Text id="196">This collection also contains the same material as the Greenstone demo. Its appearance has been altered to show how the pages generated can be set out differently. It relies on a non-standard macro file that is supplied with Greenstone.</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="197"><i>isis-e</i></Text>
+</th>
+<th width="182">
+<Text id="198">CDS/ISIS example (1 Mb)</Text>
+</th>
+<th width="294">
+<Text id="199">This collection is built from a CDS/ISIS database of about 150 bibliography entries. It uses the ISISPlug plugin, which reads the standard ISIS .mst and .fdt files and converts them to Greenstone metadata.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Chapter>
+<Chapter id="setting_up_webserver">
+<Title>
+<Text id="200">Setting up the Webserver</Text>
+</Title>
+<Content>
+<Text id="201">In this section we describe how to set up your webserver to work with Greenstone. Note that all this is unnecessary when using the Windows Local Library, because this software works âout of the boxâ and does not require a webserver.</Text>
+<Text id="202">We discuss both the Apache webserver, which is freely available for both Windows and Unix (see the Appendix <CrossRef target="Chapter" ref="appendix_associated_software"/> for details) and Microsoft's Personal Web Server (PWS) and Internet Information Services (IIS) webserver. PWS is the standard Microsoft server for Windows 95/98; IIS is the standard webserver for Windows 2000 and the forthcoming Win dows XP ; Windows NT can use either. The Apache description applies equally to the Windows Web Library and Unix versions (though we use Windows-style terminology and pathnames); the PWS/IIS section applies only to the Windows Web Library.</Text>
+<Text id="203">Once you have installed your webserver, the next step is to install Greenstone. We will assume that during the install procedure you have taken the default action for each stage by clicking on the <i>Next</i> button. The result is that the directory <i>C:\Program Files\gsdl</i> is created and the Web Library binary is stored there, along with some supporting files.</Text>
+<Text id="204">All webservers use the special URL âlocalhostâ to denote the computer that the webserver is running on. Thus when you install a webserver, you can get at your html documents by typing the URL <i>http://localhost</i> into a browser. If your computer has a domain name set up, this is used instead of localhost to identify your computer from remote sites. Thus on the New Zealand Digital Library's computer, <i>http://nzdl.org</i> and <i>http://localhost</i> are equivalent. If you type <i>http://nzdl.org</i> on your computer you will get the New Zealand Digital Library webserver, whereas if you type <i>http://localhost</i> you will get your own computer's webserver.</Text>
+<Section id="apache_web_server">
+<Title>
+<Text id="205">The Apache web server</Text>
+</Title>
+<Content>
+<Text id="206">The Apache webserver is usually installed in <i>C:\Program Files\Apache Group\Apache</i> and is configured so that the cgi-bin directory is in the subdirectory <i>\cgi-bin</i> and the document root is the subdirectory <i>\htdocs</i>. It is reconfigured by editing the configuration file <i>C:\Program Files\Apache Group\Apache\conf\httpd.conf</i>. This is a text file: it's quite easy to read it to see how things are set up.</Text>
+<Text id="207">Depending on how your computer's networking software is set up, you may have to add this line to Apache's <i>httpd.conf</i> configuration file:</Text>
+<CodeLine>ServerName localhost</CodeLine>
+<Text id="208">If this line is not included, the system attempts to find your server's name. However, there are bugs in some versions of Windows that cause this to fail. In this case, Apache will exit immediately when you start it up. It does display an error message, but it is immediately erased and you probably can't read it.</Text>
+<Subsection id="setting_up_cgi-bin_directory">
+<Title>
+<Text id="209">Setting up the Greenstone cgi-bin directory</Text>
+</Title>
+<Content>
+<Text id="210">Cgi-bin is a directory from which the webserver treats documents as executable programs. Apache's <i>ScriptAlias</i> directive is used to create a cgi-bin directory. Note that this directive can make any directory a cgi executable directoryâit doesn't have to be called âcgi-binâ! Conversely, a directory called âcgi-binâ isn't special unless <i>ScriptAlias</i> has been applied to it.</Text>
+<Text id="211">When installed, Apache has a cgi-bin directory of <i>C:\Program Files\Apache Group\Apache\cgi-bin</i>. This means that if presented with the URL <i>http://localhost/cgi-bin/hello</i>, the webserver will attempt to execute a file called <i>hello</i> from within the above directory.</Text>
+<Text id="212">There is one Greenstone program, which is called âlibrary.exeâ, that needs to be executed by the webserver; it in turn reads a file called the Greenstone site configuration file, or âgsdlsite.cfgâ, which needs to be located in the same directory.</Text>
+<Text id="213">The best way of arranging this is to use Apache's <i>ScriptAlias</i> directive to create a new cgi-bin directory. Here's the excerpt from Apache's <i>httpd.conf</i> configuration file that adds <i>C:\Program Files\gsdl\cgi-bin</i> as an additional cgi-bin directory:</Text>
+<CodeLine>ScriptAlias /gsdl/cgi-bin/ "C:/Program Files/gsdl/cgi-bin/"</CodeLine>
+<CodeLine>&lt;Directory C:/Program Files/gsdl/cgi-bin&gt;</CodeLine>
+<CodeLine>  Options None</CodeLine>
+<CodeLine>  AllowOverride None</CodeLine>
+<CodeLine>&lt;/Directory&gt;</CodeLine>
+<Text id="214">(It's a curious fact that Apache configuration files use forward slashes in place of standard Windows backslashes.)</Text>
+<Text id="215">This means that any URLs of the form <i>http://localhost/gsdl/cgi-bin</i>... will be sought in the directory <i>C:\Program Files\gsdl\cgi-bin</i>, and executed by the web server. For example, if presented with the URL <i>http://localhost/gsdl/cgi-bin/hello</i>, the web server will attempt to retrieve the file <i>C:\Program Files\gsdl\cgi-bin\hello</i> and execute it. However, the URL <i>http://localhost/cgi-bin/hello</i> looks in Apache's regular <i>cgi-bin</i> directory for the file <i>C:\Program Files\Apache Group\Apache\</i> <i>cgi-bin\hello</i> and executes it, just as it did before.</Text>
+</Content>
+</Subsection>
+<Subsection id="document_root_directory">
+<Title>
+<Text id="216">The document root directory</Text>
+</Title>
+<Content>
+<Text id="217">The document root directory is the root of your webserver's directory structure. When installed, Apache has a document root <i>of C:\Program Files\Apache Group\Apache\htdocs</i>. This means that if presented with the URL <i>http://localhost/hello.html</i>, the webserver will attempt to retrieve a file called <i>hello.html</i> from within the above directory.</Text>
+<Text id="218">Several files within Greenstone need to be read by the webserver. The simplest way to arrange this is to use the <i>Alias</i> directive, which is just like <i>ScriptAlias</i> except that it applies to ordinary web pages, not cgi scripts. Insert these lines into your Apache configuration file, after the <i>ScriptAlias</i> directive, to add <i>C:\Program Files\gsdl</i> as an additional place to look for documents.</Text>
+<CodeLine>Alias /gsdl/ "C:/Program Files/gsdl/"</CodeLine>
+<CodeLine>&lt;Directory C:/Program Files/gsdl&gt;</CodeLine>
+<CodeLine> Options Indexes MultiViews FollowSymLinks</CodeLine>
+<CodeLine> AllowOverride None</CodeLine>
+<CodeLine> Order allow,deny</CodeLine>
+<CodeLine> Allow from all</CodeLine>
+<CodeLine>&lt;/Directory&gt;</CodeLine>
+<Text id="219">This means that any URLs that match the first argument of Alias (gsdl) are sought as files in the place corresponding to the second argument. In other words, URLs of the form <i>http://localhost/gsdl/</i>... will be sought as files in the directory <i>C:\Program Files\gsdl</i>. For example, if presented with the URL <i>http://localhost/gsdl/hello.html</i>, the webserver will attempt to retrieve the file <i>C:\Program Files\gsdl\hello.html</i>. However, the URL <i>http://localhost/hello.html</i> looks in the regular <i>htdocs</i> directory for the file <i>C:\Program Files\Apache Group\Apache\htdocs\hello.html</i>, just as it did before.</Text>
+<Text id="220">Be sure to add the <i>Alias</i> directive after the <i>ScriptAlias</i> directive. Instructing Apache to alias <i>/gsdl</i> before <i>/gsdl/cgi-bin</i> would match the URL <i>/gsdl/cgi-bin/library</i> against the Alias directive rather than the ScriptAlias, and it would be interpreted as a request for a document rather than the result of executing a program. The outcome would be to âdisplayâ the binary program file as a page in the Web browser, instead of executing it.</Text>
+</Content>
+</Subsection>
+<Subsection id="security">
+<Title>
+<Text id="221">Security</Text>
+</Title>
+<Content>
+<Text id="222">You should be aware that if the web library version of Greenstone is set up as instructed above, anyone will be allowed to download any file in the <i>gsdl</i> directory structure. This includes the index files and source documents of any collections you make, the user database, usage logs, etc.</Text>
+<Text id="223">If you are concerned about this, you can easily tighten up your webserver configuration to improve security. For the Apache webserver, put these lines into the configuration file instead of those given in the previous subsection:</Text>
+<CodeLine>Alias /gsdl/ "C:/Program Files/gsdl/"</CodeLine>
+<CodeLine>&lt;Directory "C:/Program Files/gsdl"&gt;</CodeLine>
+<CodeLine>   Order allow,deny</CodeLine>
+<CodeLine>   Deny from all</CodeLine>
+<CodeLine>   &lt;FilesMatch</CodeLine>
+<CodeLine>"\.(gif|jpe?g|png|css|mov|mpeg|ps|pdf|doc|rtf|jar|class)$"&gt;</CodeLine>
+<CodeLine>         Order allow,deny</CodeLine>
+<CodeLine>         Allow from all</CodeLine>
+<CodeLine>   &lt;/FilesMatch&gt;</CodeLine>
+<CodeLine>&lt;/Directory&gt;</CodeLine>
+<Text id="224">This means that only files whose extensions match the regular expression in the <i>FilesMatch</i> line may be downloaded.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="pws_and_iis_webservers">
+<Title>
+<Text id="225">The PWS and IIS webservers</Text>
+</Title>
+<Content>
+<Text id="226">Although neither PWS nor IIS is installed by default on current Windows systems, they can easily be installed using the âAdd/Remove programsâ control panel . If they are not already on your Windows distribution CD-ROM you will have to download them from the Microsoft web site (<i>www.microsoft.com</i>).</Text>
+<Text id="227">The setup procedure for Greenstone is identical for both PWS and IIS. Invoke the Personal Web Manager and perform the following actions.</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="228">Select <i>Advanced</i> to get the <i>Advanced Options</i> screen.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="229">Select <i>Home</i> and click <i>Add</i>Fill out the fields as follows:</Text>
+<Text id="230"><i>Directory</i> field:          <i>C:\Program Files\gsdl</i></Text>
+<Text id="231"><i>Alias</i>field:               <i>gsdl</i></Text>
+<Text id="232">Access permissions:              <i>Read</i></Text>
+<Text id="233">Application permissions:         <i>None</i></Text>
+<Text id="234">Click <i>OK</i></Text>
+<Text id="235">This makes Greenstone files accessible to the webserver.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="236">Back in <i>Advanced Options</i>, select <i>gsdl</i> and click <i>Add</i>Fill out the fields as follows:</Text>
+<Text id="237"><i>Directory</i> field:           <i>C:\Program Files\gsdl\cgi-bin</i></Text>
+<Text id="238"><i>Alias</i> field:               <i>cgi-bin</i></Text>
+<Text id="239">Access permissions:               <i>None</i></Text>
+<Text id="240">Application permissions:          <i>Execute</i></Text>
+<Text id="241">Click <i>OK</i></Text>
+<Text id="242">This allows the Greenstone program <i>library.exe</i> to be executed by the webserver.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="243">Go to the URL <i>http://localhost/gsdl/cgi-bin/library.exe</i></Text>
+<Text id="244">Note: you need to specify the <i>.exe</i> file extension with PWS and IIS.</Text>
+</NumberedItem>
+</NumberedList>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="configuring_your_site">
+<Title>
+<Text id="245">Configuring your Site</Text>
+</Title>
+<Content>
+<Text id="246">For Greenstone to work properly, access permissions for certain files must be set up appropriately. Also, there is a configuration file associated with each Greenstone site. The install procedure creates a generic configuration file based on your installation choices; however its contents can be tailored to cope with different situations. This section explains both of these issues.</Text>
+<Section id="file_permissions">
+<Title>
+<Text id="247">File permissions</Text>
+</Title>
+<Content>
+<Text id="248">This section is irrelevant for Windows 95/98, because these systems don't identify the owners of files.</Text>
+<Text id="249">On Windows NT, 2000 and Unix systems, cgi scripts don't run as normal users, because users can't be identified over the Web. Instead, they run as the user who started up the webserver program (on Windows systems), or as a special user (commonly called <i>nobody</i> on Unix systems). Because of this, all files and directories within <i>C:\Program Files\gsdl</i> need to be globally readable (or at least readable by the cgi-script user, perhaps â<i>nobody</i>â). To test whether file permissions are set up correctly, run the program <i>library.exe</i> from the command line. If the files are in the right places but the permissions are set incorrectly, it will run from the command lineâthat is, when <i>you</i> execute itâbut not from a browserâthat is, when the â<i>nobody</i>â user executes it. Another test is to log in as another user to see if the file permissions are specific to your original user account.</Text>
+<Text id="250">To work through a Web browser, all the Greenstone directories must be globally readable. Also, the <i>C:\Program Files\gsdl\etc</i> directory and all its contents must be globally <i>writable</i>. This is the directory into which the library program writes the usage log, error and initialization logs, and various user databases. If you're reluctant to make this directory globally writable, you can set permissions so that just the files <i>errout.txt</i>, <i>initout.txt</i>, <i>key.db</i>, <i>users.db</i>, <i>history.db</i> and <i>usage.txt</i> are writable by the cgi user.</Text>
+<Text id="251">If file permissions are not set up correctly for <i>C:\Program Files\gsdl\etc</i>, you may find that user authentication and search history do not work, and that no usage log (<i>usage.txt</i>) is generated.</Text>
+</Content>
+</Section>
+<Section id="gsdlsite_configuration_file">
+<Title>
+<Text id="252">The gsdlsite.cfg configuration file</Text>
+</Title>
+<Content>
+<Text id="253">The install procedure creates a generic Greenstone site configuration file based on your installation choices. For our installation this file is <i>C:\Program Files\gsdl\cgi-bin\gsdlsite.cfg</i> and its content is:</Text>
+<CodeLine># Site configuration file for Greenstone.</CodeLine>
+<CodeLine># Lines begining with</CodeLine>
+<CodeLine># are comments.</CodeLine>
+<CodeLine># This file should be placed in the same directory as your library</CodeLine>
+<CodeLine># executable file. it should be edited to suit your site.</CodeLine>
+<CodeLine># points to the GSDLHOME directory</CodeLine>
+<CodeLine>gsdlhome âC:/Program Files/gsdl â</CodeLine>
+<CodeLine># this is the http address of GSDLHOME</CodeLine>
+<CodeLine># if your webservers DocumentRoot is set to $GSDLHOME</CodeLine>
+<CodeLine># then httpprefix can be commented out</CodeLine>
+<CodeLine>httpprefix /gsdl</CodeLine>
+<CodeLine># this is the http address of the directory which</CodeLine>
+<CodeLine># contains the images for the interface.</CodeLine>
+<CodeLine>httpimg /gsdl/images</CodeLine>
+<CodeLine># should contain the http address of this cgi script. This</CodeLine>
+<CodeLine># is not needed if the http server sets the environment variable</CodeLine>
+<CodeLine># SCRIPT_NAME</CodeLine>
+<CodeLine>#gwcgi         /cgi-bin/library</CodeLine>
+<CodeLine># maxrequests is the most requests a fastcgi process</CodeLine>
+<CodeLine># will serve before it exits. This can be set to a</CodeLine>
+<CodeLine># low figure (like 1) while debugging and then set</CodeLine>
+<CodeLine># to a high figure (like 10000) when everything is</CodeLine>
+<CodeLine># working well.</CodeLine>
+<CodeLine>#maxrequests 10000</CodeLine>
+<Text id="254">You can customise your installation by editing this file, although you will probably not need to do so.</Text>
+<Text id="255">The <i>gsdlhome</i> line simply points to the <i>C:\Program Files\gsdl</i> directory.</Text>
+<Text id="256"><i>httpprefix</i> is the web address of the directory that Greenstone is installed in. We explained earlier how to create an alias so that URLs of the form <i>http://localhost/gsdl/</i>... are sought in the <i>C:\Program Files\gsdl</i> directory. Putting a line <i>httpprefix /gsdl</i> into the <i>gsdlsite</i> configuration file establishes the same convention for the Greenstone software.</Text>
+<Text id="257"><i>httpimg</i> is the web address of the <i>C:\Program Files\gsdl\images</i> directory, which contains all the gif images used in the interface. In any standard Greenstone installation this will always be <i>httpprefix/images</i>, and the line in the file above is left untouched.</Text>
+<Text id="258"><i>gwcgi</i> is the web address of the library cgi program. This is not required by most webservers (including Apache), and should remain commented out. Don't uncomment it unless you're sure you need to, because that may introduce problems.</Text>
+<Text id="259"><i>maxrequests</i> is only used by versions of Greenstone that are compiled with the âfast-cgiâ option on. The standard binary distribution does not include this option because not all webservers are configured to support it. Fastcgi speeds up cgi executions by keeping the main executable in memory between invocations of the software, rather than loading it in from disk each time a web page is requested from the Greenstone software. The trade-off is the amount of memory used, which can grow the longer the program remains in memory. Once <i>maxrequests</i> pages have been generated, the cgi program quits, thereby freeing any accumulated memory. To respond to the next request for a Web page, the cgi program is read in from disk again, and a new cycle of page requests is begun. Most installations use the standard cgi protocol, which means that <i>maxrequests</i> can be safely ignored.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="personalizing">
+<Title>
+<Text id="260">Personalizing your Installation</Text>
+</Title>
+<Content>
+<Text id="261">Probably the first thing you will want to do once your Greenstone installation is up and running is personalize the home page. The file that generates the Greenstone home page is called <i>home.dm</i>, and is located in the <i>macros</i> subdirectory of the directory into which you installed Greenstone. (The default for Windows systems is <i>C:\Program Files\gsdl</i>.) This is a plain text file that you will have to edit to create a new home page. Instead of editing it, we recommend creating a new file, say <i>yourhome.dm</i>. This will be like <i>home.dm</i> but will define âpackage homeââwhich is the bit that does the actual workâin a different way.</Text>
+<Text id="262">When you make a different home page, there must be some way of linking in to the digital library pages so that you can search and browse the collections on your system. The solution that Greenstone adopts is to use âmacrosâ. That's why the home-page file is called â.dmâ and not â.htmlââit's a âmacroâ file rather than a regular html file. But don't quail: the macro file basically contains just html, sprinkled with a few mystical incantantations which are explained below. The macro language is a powerful facility, and only a small part of it is described belowâsee the <i>Greenstone Digital Library Developer's Guide</i> for more information.</Text>
+<Section id="example">
+<Title>
+<Text id="263">Example</Text>
+</Title>
+<Content>
+<Figure id="your_own_greenstone_home_page">
+<Title>
+<Text id="264">Your own Greenstone home page</Text>
+</Title>
+<File width="395" height="227" url="images/Install_Fig_3.png"/>
+</Figure>
+<Text id="265">Figure <CrossRef target="Figure" ref="your_own_greenstone_home_page"/> shows an example of a new digital library home page. Each of the âClick hereâ links takes you to the appropriate Greenstone facility. This page was generated by the file called <i>yourhome.dm</i> shown in Figure <CrossRef target="Figure" ref="yourhome_dm"/>.</Text>
+<Figure id="yourhome_dm">
+<Title>
+<Text id="266"><i>yourhome.dm</i> used to create Figure <CrossRef target="Figure" ref="your_own_greenstone_home_page"/></Text>
+</Title>
+<CodeLine>package home</CodeLine>
+<CodeLine>_content_ {</CodeLine>
+<CodeLine>&lt;h2&gt;Your own Greenstone home page&lt;/h2&gt;</CodeLine>
+<CodeLine>&lt;ul&gt;</CodeLine>
+<CodeLine>&lt;table&gt;</CodeLine>
+<CodeLine>&lt;tr valign=top&gt;&lt;td&gt;Search page for the demo collection&lt;br&gt;&lt;/td&gt;</CodeLine>
+<CodeLine>      &lt;td&gt;&lt;a href="_httpquery_&amp;c=demo"&gt;Click here&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;tr&gt;&lt;td&gt;"About" page for the demo collection&lt;/td&gt;</CodeLine>
+<CodeLine>      &lt;td&gt;&lt;a href="_httppageabout_&amp;c=demo"&gt;Click here&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;tr&gt;&lt;td&gt;Preferences page for the demo collection&lt;/td&gt;</CodeLine>
+<CodeLine>      &lt;td&gt;&lt;a href="_httppagepref_&amp;c=demo"&gt;Click here&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;tr&gt;&lt;td&gt;Home page&lt;/td&gt;</CodeLine>
+<CodeLine>      &lt;td&gt;&lt;a href="_httppagehome_"&gt;Click here&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;tr&gt;&lt;td&gt;Help page&lt;/td&gt;</CodeLine>
+<CodeLine>      &lt;td&gt;&lt;a href="_httppagehelp_"&gt;Click here&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;tr&gt;&lt;td&gt;Administration page&lt;/td&gt;</CodeLine>
+<CodeLine>      &lt;td&gt;&lt;a href="_httppagestatus_"&gt;Click here&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;tr&gt;&lt;td&gt;The Collector&lt;/td&gt;</CodeLine>
+<CodeLine>      &lt;td&gt;&lt;a href="_httppagecollector_"&gt;Click here&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;/table&gt;</CodeLine>
+<CodeLine>&lt;/ul&gt;</CodeLine>
+<CodeLine>}</CodeLine>
+<CodeLine># if you hate the squirly green bar down the left-hand side of the</CodeLine>
+<CodeLine># page, uncomment these lines:</CodeLine>
+<CodeLine># _header_ {</CodeLine>
+<CodeLine># }</CodeLine>
+</Figure>
+<Text id="267">You can use Figure <CrossRef target="Figure" ref="yourhome_dm"/> as a template for creating your own specialized Greenstone home page. Basically, it defines a macro called <i>content</i>. Inside the curly braces is ordinary html. You could insert additional text, along with any html formatting commands, to put the content that you want to see on the page. The text is regular html; if you want you can include hyperlinks and use all the other facilities that html provides.</Text>
+<Text id="268">To make your new home page link in with other digital library pages, you need to use an appropriate magic spell. In this macro language, magic spells are words flanked by underscores. You can see these in Figure <CrossRef target="Figure" ref="yourhome_dm"/>. For example, <i>_httppagehome_</i> takes you to the home page, <i>_httppagehelp_</i> to the help page, and so on. In some cases you need to include a collection name. For example, <i>_httpquery_&amp;c=demo</i> specifies the search page for the demo collection; for other collections you should replace <i>demo</i> by the appropriate collection name.</Text>
+<Text id="269">The definition of the macro called <i>_content_</i> is plain html. Any standard html code may be placed within a macro definition. However, the special characters '{', '}', '\', and '_' must be escaped with a backslash to prevent them from being processed by the macro language interpreter.</Text>
+<Text id="270">Note that the <i>_content_</i> macro definition does not contain any html header or footer. If you want to change the header or footer of your home page, you should define <i>_header_</i> and/or <i>_footer_</i> macros, adding them to the <i>yourhome.dm</i> file in the form</Text>
+<CodeLine>_macroname_ {</CodeLine>
+<CodeLine>...</CodeLine>
+<CodeLine>}</CodeLine>
+<Text id="271">For example, the squirly green bar down the left-hand side of Greenstone pages is defined in the <i>_header_</i> macro, and making this macro null will remove it, as indicated at the end of Figure <CrossRef target="Figure" ref="yourhome_dm"/>.</Text>
+</Content>
+</Section>
+<Section id="how_to_make_it_work">
+<Title>
+<Text id="272">How to make it work</Text>
+</Title>
+<Content>
+<Text id="273">You have to tell Greenstone about the new home page <i>yourhome.dm</i>. The system reads in the macro files that are specified in the main configuration file <i>main.cfg</i>, so if you create a new one you must include it there. Name clashes are handled sensibly: the most recent definition takes precedence.</Text>
+<Text id="274">Thus to make the Greenstone digital library software use the home page in Figure <CrossRef target="Figure" ref="your_own_greenstone_home_page"/> instead of the default, first put the <i>yourhome.dm</i> file in Figure <CrossRef target="Figure" ref="yourhome_dm"/> into the <i>macros</i> directory. Then edit the <i>main.cfg</i> configuration file to replace <i>home.dm</i> with <i>yourhome.dm</i> in the list of macro files that are loaded at startup.</Text>
+</Content>
+</Section>
+<Section id="redirecting_a_url_to_greenstone">
+<Title>
+<Text id="275">Redirecting a URL to Greenstone</Text>
+</Title>
+<Content>
+<Text id="276">You may want to redirect a more convenient URL to your Greenstone cgi program. For example, on our system the URL <i>http://nzdl.org</i> (which is shorthand for <i>http://nzdl.org/index.html)</i> is redirected to <i>http://nzdl.org/cgi-bin/library</i>. The Apache webserver accomplishes this with the <i>Redirect</i> directive. Along with other directives, this goes into the <i>C:\Program Files\Apache Group\Apache\conf\httpd.conf</i> configuration file. To redirect the URL <i>http://www.yourserver.com</i> to <i>http://www.yourserver.com/cgi-bin/library</i>, put this line into <i>httpd.conf</i>:</Text>
+<CodeLine>Redirect /index.html http://www.yourserver.com/cgi-bin/library</CodeLine>
+<Text id="277">Then you will reach your digital library system directly from the URL <i>http://www.yourserver.com</i>. Instead, if you wanted a URL like <i>http://www.yourserver.com/greenstone</i> to be redirected to <i>http://www.yourserver.com/cgi-bin/library</i>, include in the <i>httpd.conf</i> file</Text>
+<CodeLine>Redirect /greenstone http://www.yourserver.com/cgi-bin/library</CodeLine>
+<Text id="278">If your computer doesn't have a domain name (like the âwww.yourserver.comâ above), just replace <i>www.yourserver.com</i> by <i>localhost</i> in the lines above. So long as the browser is running on the same machine as the webserverâwhich it surely is if your computer doesn't have a domain nameâthis has the same effect as the above redirections.</Text>
+<Text id="279">Instead of putting redirect directives into the file <i>httpd.conf</i>, you can equally well put them into a file called <i>.htaccess</i> within your server's document root directory. In fact, doing so has two advantages. First, changes to <i>.htaccess</i> take effect immediately, whereas you have to restart the Apache webserver to see the effect of changes to <i>httpd.conf</i>. Second, on Unix systems you usually have to be logged in as the ârootâ user to edit <i>httpd.conf</i>, whereas you don't to edit <i>.htaccess</i>.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="appendix_associated_software">
+<Title>
+<Text id="280">Appendix Associated Software</Text>
+</Title>
+<Content>
+<Text id="281">Here is how to obtain the software packages mentioned above.</Text>
+<Section id="apache_webserver">
+<Title>
+<Text id="282">Apache Webserver</Text>
+</Title>
+<Content>
+<Text id="283">To run any version of Greenstone apart from the Windows Local Library version, you need an external webserver. Many installations, particularly larger ones, will already have a webserver. If you are using Linux, Apache may be on your installation disk but may not have been selected during the installation procedure. The Apache Webserver from <i>www.apache.org</i> is free, and easy to install.</Text>
+</Content>
+</Section>
+<Section id="perl">
+<Title>
+<Text id="284">Perl</Text>
+</Title>
+<Content>
+<Text id="285">Greenstone uses the Perl language when building collections. For Windows, Perl is already included in the Greenstone software. Most Unix systems already have Perl installed, but if not, source code and binaries for a wide range of Unix platforms are freely available at <i>www.perl.com</i>. Perl version 5.0 or higher is needed.</Text>
+</Content>
+</Section>
+<Section id="gcc">
+<Title>
+<Text id="286">GCC</Text>
+</Title>
+<Content>
+<Text id="287">The Unix version of Greenstone compiles under the Gnu C++ compiler, GCC. Greenstone makes extensive use of the C++ standard template library (we've found it to be broken on some older versions of GCC; please tell us if you have STL problems). Note that this version of Greenstone does not compile under GCC 3.0.</Text>
+</Content>
+</Section>
+<Section id="gdbm">
+<Title>
+<Text id="288">GDBM</Text>
+</Title>
+<Content>
+<Text id="289">All versions of Greenstone use the Gnu Database Manager, GDBM. It is supplied with all Windows versions of Greenstone and installed automatically during the installation procedure. Linux systems already have GDBM, so we do not provide it for Linux. Most other Unix systems have it, but if necessary you can download it from <i>www.gnu.org</i>.</Text>
+</Content>
+</Section>
+<Section id="java_runtime_environment">
+<Title>
+<Text id="290">Java runtime environment</Text>
+</Title>
+<Content>
+<Text id="291">To use the Greenstone Librarian Interface, you need a suitable version of the Java Runtime Environment. If you don't already have this, a suitable version is included on the CD-ROM, or you can download the latest version from <u>http://java.sun.com/j2se/downloads.html</u>. Version 1.4.0 or higher is needed.</Text>
+</Content>
+</Section>
+<Section id="java_compiler">
+<Title>
+<Text id="292">Java compiler</Text>
+</Title>
+<Content>
+<Text id="293">To compile the source code of the Greenstone Librarian Interface, you must first install a Java Development Kit. You can download the J2SE Software Development Kit from <u>http://java.sun.com/j2se/downloads.html</u>. Version 1.4.0 or higher is needed.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+</Manual>
Index: /tags/start/gsdl-documentation/manuals/xml-source/en/Paper_en.xml
===================================================================
--- /tags/start/gsdl-documentation/manuals/xml-source/en/Paper_en.xml	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/xml-source/en/Paper_en.xml	(revision 13666)
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Manual>
+<Heading>
+<Text id="1">GREENSTONE DIGITAL LIBRARY</Text>
+</Heading>
+<Title>
+<Text id="2">FROM PAPER TO COLLECTION</Text>
+</Title>
+<Author>
+<Text id="3">Dr Michel Loots, Dan Camarzan and Ian H. Witten</Text>
+</Author>
+<Affiliation>
+<Text id="4">Human Info NGO, Belgium <br/>Simple Words, Romania <br/>University of Waikato, New Zealand</Text>
+</Affiliation>
+<Text id="5">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 New Zealand Digital Library Project at the University of Waikato, and developed 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 G nu General Public License.</Text>
+<Comment>
+<Text id="6">We want to ensure that this software works well for you. Please report any problems to <i>greenstone@cs.waikato.ac.nz</i></Text>
+</Comment>
+<Version>
+<Text id="7">Greenstone gsdl-2.50</Text>
+</Version>
+<Date>
+<Text id="8">March 2004</Text>
+</Date>
+<Section id="about_this_manual">
+<Title>
+<Text id="9">About this manual</Text>
+</Title>
+<Content>
+<Text id="10">This document explains how to create CD-ROM collections from paper documents. It describes in full detail the procedures and economics involved in the scanning and optical character recognition (OCR) processes, so that you end up with text in the right format to apply the Greenstone software. It also describes how to create and edit the material associated with a collection.</Text>
+<Text id="11">We have tried to be as plain as possible in our explanation. Reference to any trade mark or company product is purely for illustrative purposes, and does not imply that we endorse or favor this product over any other.</Text>
+</Content>
+</Section>
+<Section id="companion_documents">
+<Title>
+<Text id="12">Companion documents</Text>
+</Title>
+<Content>
+<Text id="13">The complete set of Greenstone documents include five volumes:</Text>
+<BulletList>
+<Bullet>
+<Text id="14">Greenstone Digital Library Installer's Guide</Text>
+</Bullet>
+<Bullet>
+<Text id="15">Greenstone Digital Library User's Guide</Text>
+</Bullet>
+<Bullet>
+<Text id="16">Greenstone Digital Library Developer's Guide</Text>
+</Bullet>
+<Bullet>
+<Text id="17">Greenstone Digital Library: From Paper to Collection <i>(this document)</i></Text>
+</Bullet>
+<Bullet>
+<Text id="18">Greenstone Digital Library: Using the Organizer</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Section>
+<Section id="acknowledgements">
+<Title>
+<Text id="19">Acknowledgements</Text>
+</Title>
+<Content>
+<Text id="20">The scanning operation and other know-how relating to the creation of collaborative non-profit collections have been developed by Dr Michel Loots, MD, of Human Info NGO and HumanityCD, Dan Camarzan of Simple Words, and their team of collaborators in Brasov, Romania.</Text>
+<Text id="21">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, Hong Chen, Michael Dewsnip, Katherine Don, Elke Duncker, Carl Gutwin, Geoff Holmes, Dana McKay, 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, PERL, WGET, WVWARE and XLHTML.</Text>
+</Content>
+</Section>
+<Chapter id="introduction">
+<Title>
+<Text id="22">Introduction</Text>
+</Title>
+<Content>
+<Text id="23">One goal of the Greenstone Digital Library software is to empower organizations such as universities, United Nations agencies, non-governmental organizations, non-profit organizations and governments to create varied collections of information that can be delivered online or on CD-ROM.</Text>
+<Text id="24">Typical steps that have to be implemented are:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="25">Selecting the documents to be included</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="26">Securing copyrights permissions to use these documents in the digital library</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="27">Scanning and OCR of the hard-copy documents which are not available in to digital form to have a perfect digital format</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="28">Converting all documents to a format (integrating text and images) which can be imported into Greenstone (preferably
+HTML or Microsoft Word, but others are also covered at varying levels of precision by a âpluginâ (see the Greenstone Userâs Manual)</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="29">Tagging the chapters, paragraphs and images of the digital documents</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="30">Organising the collection into a optimally structured digital library</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="31">Building the digital library using the Greenstone software</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="32">Printing and distributing the collection on CD-ROM and/or distributing it over the Internet</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="33">In order to create a digital collection, the publications must be available in digital format. If books, newsletters or other documents are only available on paper, they will need to be scanned and processed into machine-readable form (step iii). Usually this is done using optical character recognition (OCR), but sometimes by manual retyping. This process is covered in Chapters 2-4 of this manual.</Text>
+<Text id="34">Step v. enables the different parts of a document to be independently selected and displayed by readers in the final library, while step vi. involves assigning attributes to the documents such as subject categories, keywords and bibliographic data for ordering and searching the library. These steps are covered in Chapter 5 of this manual.</Text>
+<Text id="35">This manual introduces many issues that affect the editorial process of creating a collection from paper. Before reading on, you should consider these questions:</Text>
+<BulletList>
+<Bullet>
+<Text id="36">What is the goal of your collection?</Text>
+</Bullet>
+<Bullet>
+<Text id="37">What is your target group?</Text>
+</Bullet>
+<Bullet>
+<Text id="38">How big is itâlocal, regional, or global?</Text>
+</Bullet>
+<Bullet>
+<Text id="39">How many documents are you making available?</Text>
+</Bullet>
+<Bullet>
+<Text id="40">How many pages?</Text>
+</Bullet>
+<Bullet>
+<Text id="41">How much graphics content?</Text>
+</Bullet>
+<Bullet>
+<Text id="42">Does the material split into parts that will be consulted by a limited audience and parts that need to be disseminated widely?</Text>
+</Bullet>
+<Bullet>
+<Text id="43">Are the documents already available electronically?</Text>
+</Bullet>
+<Bullet>
+<Text id="44">If so, in which formats? (Note incidentally that PDF files are not automatically equivalent to digital full-text form, as they often contain only page images.)</Text>
+</Bullet>
+<Bullet>
+<Text id="45">What is the copyright status of the documents?</Text>
+</Bullet>
+<Bullet>
+<Text id="46">Who owns the copyright?</Text>
+</Bullet>
+<Bullet>
+<Text id="47">Are there other organizations with the same target audience?</Text>
+</Bullet>
+<Bullet>
+<Text id="48">Are you willing to collaborate with other groups?</Text>
+</Bullet>
+<Bullet>
+<Text id="49">What budget is available for the whole project?</Text>
+</Bullet>
+<Bullet>
+<Text id="50">What human resources are available (in person-months) for co-ordination, editing, scanning and programming?</Text>
+</Bullet>
+<Bullet>
+<Text id="51">How many computers are available for this project?</Text>
+</Bullet>
+<Bullet>
+<Text id="52">How many CD-ROMs do you want to distribute?</Text>
+</Bullet>
+<Bullet>
+<Text id="53">Will they be free, or for sale?</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Chapter>
+<Chapter id="scanners_and_scanning">
+<Title>
+<Text id="54">Scanners and scanning</Text>
+</Title>
+<Content>
+<Text id="55">The first step in converting paper documents into a digital library collection is to obtain images of all pages of all publications in digital format. The next stage is optical character recognition (OCR), and clean, high-quality images are essential for successful OCR. The digitization process requires a scanner capable of working at a resolution of 300 dpi (dots per inch). Most scanning can be done in black-and-white, but if color illustrations are included they must be scanned with a color scanner. In most cases the covers of the book contain colors and will have to be scanned as a color photographic image.</Text>
+<Section id="scanners">
+<Title>
+<Text id="56">Scanners</Text>
+</Title>
+<Content>
+<Text id="57">Scanners are available in all price ranges, and all shapes and sizes. They range from $100 for flat-bed scanners to upwards of $50,000 for large industrial scanners from manufacturers such as Bell &amp; Howell.<FootnoteRef id="1"/>There are many websites that offer a wide range of scanners for sale. To locate them, just search for âscannersâ in search engines like Google, Altavista, or Yahoo.</Text>
+<Text id="58">The output format of a scanned page is a computer file that is usually stored in TIFF or Bitmap format. Compressed TIFF IV is the best format to use. An average page scanned and converted to this format occupies only 50 Kb, compared to perhaps 2 Mb for the equivalent page in uncompressed Bitmap form.</Text>
+<Subsection id="low-cost_flat-bed_scanner">
+<Title>
+<Text id="59">Low-cost flat-bed scanner</Text>
+</Title>
+<Content>
+<Text id="60">Low-cost flat-bed units are the cheapest and most widely available type of scanner. There are many brands: HP, Agfa, Acer, etc. Prices range from $100 to $300. Both black-and-white and color images can be scanned. The low price allows each computer to have its own scanner.</Text>
+<Text id="61">Disadvantages of these scanners include the medium quality of the result, the slow rate of scanning, unreliability in warm environments, and relatively frequent breakdown. Pages must be scanned manually, one by one. Each page must be positioned carefully on the scanning plate to ensure that it is aligned correctly. Productivity of these scanners is low. Despite manufacturers' claims that each page can be scanned in less than a minute, the fact is that rates exceeding twelve pages per hour are rarely achieved. The scanning process monopolizes the computer on which the work is being performed.</Text>
+<Text id="62">Consequently these scanners are useful only for small jobs with limited numbers of pagesâno more than 200 to 400 pages a month on a regular basis, or one-time jobs of up to 1000 or 2000 pages.</Text>
+</Content>
+</Subsection>
+<Subsection id="low-end_scanner_with_sheet_feeder">
+<Title>
+<Text id="63">Low-end scanner with sheet feeder</Text>
+</Title>
+<Content>
+<Text id="64">Low-end scanners with sheet feeders typically cost between $500 and $1200. Ten to fifty pages can be inserted, scanned and processed at once: thus the operator does not have to attend constantly to the machine. This increases capacity up to 150 to 200 pages per day. These scanners are more robust, and have a larger lifespan before repairâusually in the range 30,000 to 50,000 pages.</Text>
+<Text id="65">A disadvantage is that only one side of the page is scanned at a timeâthe stack of pages must be reversed and rescanned in order to obtain an image of both sides. This often creates problems because sheet feeders are never without problems and sometimes pages get blocked.</Text>
+<Text id="66">These scanners are useful for up to 1500 to 3000 pages a month.</Text>
+</Content>
+</Subsection>
+<Subsection id="color_scanners">
+<Title>
+<Text id="67">Color scanners</Text>
+</Title>
+<Content>
+<Text id="68">Any scanning operation invariably involves some color images, so a color scanner will always be required. Generally speaking, less than 5% of any publication contains color images, plus the cover. Thus a low cost flat-bed scanner as described above suffices. It is advisable to select one capable of scanning up to 600 dpi resolution.</Text>
+</Content>
+</Subsection>
+<Subsection id="professional_duplex_scanners">
+<Title>
+<Text id="69">Professional duplex scanners</Text>
+</Title>
+<Content>
+<Text id="70">Professional scanners are reliable, heavy-duty machines capable of processing a large volume of pagesâtypically from 2000 pages to 10,000 pages per day. They have an automatic sheet-feeder tray system that processes batches of about 50 to 200 pages. The best and fastest are duplex machines that scan both sides of the page at once.</Text>
+<Text id="71">Professional duplex scanners require a powerful computer with a hard disk of at least 10 to 20 Gb. Prices range from $5000 to $50,000. For example, the Canon DR-6020 duplex scanner costs $5000 and works with double-sided documents. It has a capacity of about 2000 pages per day and a lifespan of 600,000 to 800,000 pages. Bell &amp; Howell and Fujitsu scanners range from $10,000 to $50,000 and have a lifespan of many millions of pages.</Text>
+<Text id="72">Micro-fiche scanners cost from $15,000 for a semi-manual unit to $80,000 for one that operates fully automatically.</Text>
+</Content>
+</Subsection>
+<Subsection id="scanning_programs">
+<Title>
+<Text id="73">Scanning programs</Text>
+</Title>
+<Content>
+<Text id="74">Every scanner comes with its own software, which means that the program must be installed on the computer that manages the scanner. Some have a computer card that needs to be installed in your computer to speed up the scanning operation.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="preparing_the_documents">
+<Title>
+<Text id="75">Preparing the documents</Text>
+</Title>
+<Content>
+<Text id="76">Before being scanned, documents must be properly prepared. Dusty documents must be cleaned, humid documents dried, clips removed, pages unfolded.</Text>
+<Text id="77">The spine of each book should be removed by cutting it off, straight and precisely. Books provided by libraries must often be rebound, and if so you should be particularly careful when removing spines in order to facilitate smooth rebinding.</Text>
+<Text id="78">If there are just a few documents, cutting can be done manually with a ruler and cutters. Be careful with your hands! For more documents, special manual cutting machines are available.</Text>
+<Text id="79">For high volumesâmore than 20 documentsâwe recommend asking a printer or copy-shop if you can use their professional cutting machine. Do not forget to remove metal clips which could damage the cutting blades.</Text>
+</Content>
+</Section>
+<Section id="the_scanning_process">
+<Title>
+<Text id="80">The scanning process</Text>
+</Title>
+<Content>
+<Text id="81">Using software provided with the scanner, a digital image of each paper page is scanned and transformed into a Bitmap or TIFF image. These images should be stored on hard disk with standard filenames. The OCR process starts once some or all of a batch of documents have been scanned. It can be undertaken by the person who operates the scanner, or by someone else.</Text>
+<Text id="82">Typically a scanning resolution of 300 dpi is needed, although sometimes 200 dpi is acceptable.</Text>
+<Subsection id="quality_control">
+<Title>
+<Text id="83">Quality control</Text>
+</Title>
+<Content>
+<Text id="84">The final goal of scanning is either to OCR the pages to obtain perfect word processor or HTML versions of the publications, or to produce enhanced image files such as PDF image files. In either case the quality of the image is very important. If quality is sub-standard, image files will not look good and will consume more memory. Image quality seriously affects the OCR process: with sub-standard quality, productivity deteriorates by up to 40%. OCR typically represents more than 90% of the total cost, so scanning quality can have a very substantial effect on the final cost.</Text>
+<Text id="85">The quality of the TIFF file can be enhanced by adjusting the scanning process to each type of paper, using settings provided by the scanner software. Relatively transparent kind of paper will require a lighter setting; the contrast must be adjusted depending on the quality of printing, and so on.</Text>
+<Text id="86">First divide the material into batches with similar paper and print qualities. Perform OCR tests on a sample from the first batch to determine the optimal settings. Then scan all material in this batch before proceeding to the next one.</Text>
+</Content>
+</Subsection>
+<Subsection id="filename_conventions">
+<Title>
+<Text id="87">Filename conventions</Text>
+</Title>
+<Content>
+<Text id="88">Give each book or document a job number or unique code, which will become the name of the folder that contains all TIFF images in the document. Depending on the computer system (DOS, Windows, UNIX, LINUX, etc) from 8 characters to 128 characters can be used in a filename. We recommend restricting this unique document identifier to 8 to 16 characters. The first five characters might identify the document, the following letter might contain a language code, and the remaining characters might identify the particular page. For example, the identifier <i>u7548e12.tif</i> might identify the TIFF image of page 12 of a book written in English with code <i>u7548e</i>.</Text>
+<Text id="89">Allocate one directory on the hard disk for scanning jobs, say <i>scanjobs</i>. Then make a subdirectory for each job. Within this make a subdirectory for each publicationâsay <i>u7548e</i> for the above document. Store all the TIFF images of the publication, including color images, in this folder.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="productivity_and_resources">
+<Title>
+<Text id="90">Productivity and resources</Text>
+</Title>
+<Content>
+<Text id="91">You should not underestimate the magnitude of the scanning operationâand particularly the OCR process that follows. It is best to consider scanning and OCR as completely separate activities. The optimal choice from an economic and practical point of view should be madeindividually for each one.</Text>
+<Text id="92">Some points to consider are the investment in scanners and computers that is necessary; the availability of appropriate space and human resources; training the workforce; salary costs; the initial and total number of pages to be scanned; deadlines; and whether documents can be outsourced to third parties.</Text>
+<Subsection id="scanning_costs">
+<Title>
+<Text id="93">Scanning costs</Text>
+</Title>
+<Content>
+<Text id="94">An important decision is whether to invest in scanning equipment and perform all scanning oneself, or outsource it to a scanning company. The main considerations are:</Text>
+<BulletList>
+<Bullet>
+<Text id="95">pressure of time for the scanning job;</Text>
+</Bullet>
+<Bullet>
+<Text id="96">total number of pages;</Text>
+</Bullet>
+<Bullet>
+<Text id="97">salary costs of those who perform the scanning.</Text>
+</Bullet>
+</BulletList>
+<Text id="98">The people who perform the scanning must be highly motivated, technically skilled, and quality-oriented.</Text>
+<Text id="99">The typical cost of scanning by a professional company is $0.06 per page. To this must be added the cost of shipment, which can be up to $0.03 per page for transport from developing countries to developed countries, and $0.015 per page for transport within countries.</Text>
+<Text id="100">Table <CrossRef target="Table" ref="table_scanning_cost"/> estimates the cost of doing it yourself, using various scanner types. Note that all figures are approximate. They are provided as rough guidelines based on the authors' experience. The first three columns concern labor costs. The first is the capacity in pages/month, assuming full-time work. The resources required in person-hours per page is obtained by dividing the number of working hours per month by the pages/month capacity in the second column. It is shown in the second column, which assumes 180 working hours per month.</Text>
+<Table id="table_scanning_cost">
+<Title>
+<Text id="101">Scanning cost</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="90"/>
+<th width="71">
+<Text id="102">Capacity (pages/month)</Text>
+</th>
+<th width="75">
+<Text id="103">Hours/page (180-hour month)</Text>
+</th>
+<th width="83">
+<Text id="104">Cost/page (assuming $4/hour)</Text>
+</th>
+<th width="60">
+<Text id="105">Scanner acquisit- ion</Text>
+</th>
+<th width="66">
+<Text id="106">Scanner lifespan (pages)</Text>
+</th>
+<th width="85">
+<Text id="107">Outsourced pages for scanner cost<br/>(at $.06 each)</Text>
+</th>
+</tr>
+<tr>
+<th width="90">
+<Text id="108">Flat bed scanner</Text>
+</th>
+<th width="71">
+<Text id="109">2,500</Text>
+</th>
+<th width="75">
+<Text id="110">0.072</Text>
+</th>
+<th width="83">
+<Text id="111">$0.288</Text>
+</th>
+<th width="60">
+<Text id="112">$300</Text>
+</th>
+<th width="66">
+<Text id="113">7,000</Text>
+</th>
+<th width="85">
+<Text id="114">5,000</Text>
+</th>
+</tr>
+<tr>
+<th width="90">
+<Text id="115">Scanner with sheet-feeder</Text>
+</th>
+<th width="71">
+<Text id="116">8,000</Text>
+</th>
+<th width="75">
+<Text id="117">0.0225</Text>
+</th>
+<th width="83">
+<Text id="118">$0.09</Text>
+</th>
+<th width="60">
+<Text id="119">$800</Text>
+</th>
+<th width="66">
+<Text id="120">30,000</Text>
+</th>
+<th width="85">
+<Text id="121">13,000</Text>
+</th>
+</tr>
+<tr>
+<th width="90">
+<Text id="122">Professional: low-end duplex</Text>
+</th>
+<th width="71">
+<Text id="123">40,000</Text>
+</th>
+<th width="75">
+<Text id="124">0.0045</Text>
+</th>
+<th width="83">
+<Text id="125">$0.018</Text>
+</th>
+<th width="60">
+<Text id="126">$6,000</Text>
+</th>
+<th width="66">
+<Text id="127">600,000</Text>
+</th>
+<th width="85">
+<Text id="128">100,000</Text>
+</th>
+</tr>
+<tr>
+<th width="90">
+<Text id="129">Professional: high-end duplex</Text>
+</th>
+<th width="71">
+<Text id="130">150,000</Text>
+</th>
+<th width="75">
+<Text id="131">0.0012</Text>
+</th>
+<th width="83">
+<Text id="132">$0.0048</Text>
+</th>
+<th width="60">
+<Text id="133">$50,000</Text>
+</th>
+<th width="66">
+<Text id="134">8,000,000</Text>
+</th>
+<th width="85">
+<Text id="135">833,000</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="136">To determine the price per page, multiply the total hourly salary costs in your situation by the second column of Table <CrossRef target="Table" ref="table_scanning_cost"/>.As an example, the third column gives the price of in-house scanning at a salaryrate of $4/hourânot including investment costs.</Text>
+<Text id="137">These calculations assume that the scanner is used for a sufficient volume to justify the investment. The final three columns of Table <CrossRef target="Table" ref="table_scanning_cost"/> give more information about the cost of the scanner itself. The first of these shows the acquisition cost of the scanner, and the next gives its expected lifetime. The last shows the number of pages that could be scannedcommercially, at a cost of $0.06/page, for the price of the scanner alone.</Text>
+<Text id="138">Of course, many other factors affect the choice of scanner: availability of funds, need to minimize dependence on others, desire to build local capacity, obligations to libraries to scan books locally and not transport them, and so on.</Text>
+<Text id="139">The above figures give some idea of the volume of pages needed to justify different levels of investment. Rarely will an institute or organization need to scan 800,000 pages. At such levels more complex issues ariseâsuch as maintenance and the possibility of recouping costs by offering scanning services to othersâthat we will not discuss here.</Text>
+<Text id="140">It is tempting to regard the development of scanning capacity asa commercial venture, particularly in developing countries. But one shouldalways bear in mind that scanning is not a repetitive business. Oncedocuments have been scanned, clients never place new orders for the same documentsâno matter how good the relationship with the scanning company. From a commercial point of view, intensive marketing efforts are needed. We do not advise NGOs or other non-profit organizations to venture into this realm without thorough initial trials and a carefully-considered business plan.</Text>
+<Text id="141">In conclusion, if 10,000 to 50,000 pages are to be scanned, one should consider outsourcing the job. A low-end professional scanner costing about $6000 can only be justified if more than 100,000 pages have to be scanned. You might consider banding together with a few other institutionsâperhaps NGOs or librariesâto purchase such a scanner.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="ocr">
+<Title>
+<Text id="142">OCR: Optical Character Recognition</Text>
+</Title>
+<Content>
+<Text id="143">An optical character recognition or OCR system transforms a scanned image into text. The input is a digitized image in TIFF or Bitmap formatâpreferably a clean, high-quality image. The output is a word-processor or web file, typically in RTF, Word, or HTML format.</Text>
+<Text id="144">The following steps are involved in converting paper documents to computer form:</Text>
+<BulletList>
+<Bullet>
+<Text id="145">scanning;</Text>
+</Bullet>
+<Bullet>
+<Text id="146">page layout analysis;</Text>
+</Bullet>
+<Bullet>
+<Text id="147">recognition;</Text>
+</Bullet>
+<Bullet>
+<Text id="148">scanning images and tables.</Text>
+</Bullet>
+</BulletList>
+<Text id="149">Following these, you must perform quality checks on the resulting files, and save them in the appropriate format.</Text>
+<Text id="150">On the market are many good OCR programs, with prices ranging from $100 to $400.<FootnoteRef id="2"/>For example, among many others are:</Text>
+<BulletList>
+<Bullet>
+<Text id="151"><i>Read-Iris</i>(http://www.readiris.com/)</Text>
+</Bullet>
+<Bullet>
+<Text id="152"><i>Omnipage</i>(http://www.omnipage.com/)</Text>
+</Bullet>
+<Bullet>
+<Text id="153"><i>Fine-Reader</i>(http://www.finereader.com/)</Text>
+</Bullet>
+</BulletList>
+<Text id="154">All information, including lists of local distributors, can be found on the manufacturers' websites. Among these, in the authors' experience the most user-friendly are Fine-Reader and Omnipage. Fine-Reader is cheapest, costing about $100. It offers a great deal of flexibility, and the widest range of different language options.</Text>
+<Text id="155">A choice must be made between undertaking the scanning and OCR in-house or outsourcing it to a commercial organization. To do it in-house requires a scanner, OCR software program, OCR skill development, and a quality-conscious, highly motivated workforce.</Text>
+<Section id="the_ocr_process">
+<Title>
+<Text id="156">The OCR process</Text>
+</Title>
+<Content>
+<Text id="157">The OCR process differs from one OCR program to another, and each one requires a considerable amount of learning. The program's manual will explain this process in detail. Four points deserve particular attention: quality control, tables, images, and specialized material such as formulas, foreign characters etc.</Text>
+<Subsection id="quality_control_1">
+<Title>
+<Text id="158">Quality control</Text>
+</Title>
+<Content>
+<Text id="159">We cannot place enough emphasis on quality control. Quality checks are best performed by native speakers, or people with an excellent command of the language to check. The best people are at the university or high-school level. We should also note that young people tend to sustain higher concentration than older people for this kind of work.</Text>
+<Text id="160">Normally there are four quality checks.</Text>
+<Text id="161">The first is performed at the same time as OCR. Every OCR program has a built-in spell-checker that highlights every suspect letter. At the same time the image of the word appears too, making it easy to check and correct the error.</Text>
+<Text id="162">The second is a general check of the text once the OCR process is finished. Common errors are to miss a page, a paragraph, chapter titles, and so on. A general overview is necessary to check if pages are missing. It is essential to check titles, chapter headings, paragraphs, and tables.</Text>
+<Text id="163">The third is a spelling check using Microsoft Word. This program has a dictionary that is often more sophisticated than the one embedded in OCR programs. By importing the book into Word and performing a spelling check there, more errors can be found and corrected. Be sure to add to the spell-checker any particularly difficult or error-prone words, or scientific and technical terms common in that type of publication.</Text>
+<Text id="164">Finally, the completed document should be checked by an independent person who samples the complete book and checks for errors, problems with tables and images, tagging, and the general look of the resulting text. Only after this final check can a book be considered ready for digital dissemination.</Text>
+</Content>
+</Subsection>
+<Subsection id="tables">
+<Title>
+<Text id="165">Tables</Text>
+</Title>
+<Content>
+<Text id="166">OCR programs do not cope well with tables. Moreover, tables are hard to check. They contain many digits, sometimes with points and commas, and entries are easily misplaced into the wrong row or column. They require concentrated effort, dedicated work, intensive proof-reading, careful checking, and good quality control. They can be handled in three basically different ways.</Text>
+<Text id="167">First, tables can be treated as images. This involves scanning them as black-and-white images and placing them in this form at the appropriate point in the document. This is the easiest solution. There are no errors, and the only time taken is that involved in creating the image. However, this solution consumes more memory than others. Also, the resolution is not always sufficient when large tables are displayed on a computer screen. If you make the complete table fit, the resolution is too small. If you make the table over-wide, the user must scroll to see all columns and rows, and cannot get an overview of the contents.</Text>
+<Text id="168">Second, tables can be recreated manually by making a table with the same number of rows and columns and filling the entries by typing them in, character by character.</Text>
+<Text id="169">Third, the table can be OCR'd. This saves time compared to the manual process, but has a potential for more errors. Columns sometimes get merged, and commas and points are not recognized.</Text>
+</Content>
+</Subsection>
+<Subsection id="images">
+<Title>
+<Text id="170">Images</Text>
+</Title>
+<Content>
+<Text id="171">Publications contain three different general types of image:</Text>
+<BulletList>
+<Bullet>
+<Text id="172">black and white line art;</Text>
+</Bullet>
+<Bullet>
+<Text id="173">black and white photographs;</Text>
+</Bullet>
+<Bullet>
+<Text id="174">color photographs.</Text>
+</Bullet>
+</BulletList>
+<Text id="175">Black and white line art should be scanned in line art mode and saved as GIF or PNG files. Black and white photographs should be scanned in greyscale mode and saved as GIF or JPEG files. Color photographs should be scanned in color mode and saved as JPEG files. Generally speaking, medium-quality JPEG provides adequate resolution.</Text>
+<Text id="176">For most collections, images consume the bulk of the space required on a hard-disk or CD-ROM. This makes it important to optimize each image for clarity and visibility, while minimizing its size. To save space you might drop some or all of the images if they are not relevant to the text.</Text>
+<Text id="177">Images should be scanned separately, one by one. We recommend giving the image files a name that consists of the first five or six characters used to denote the document followed by the number of the page on which the image was found. An alternative, assuming each document is in its own directory, is to simply use the letter <i>p</i> followed by the page containing the image. If there are several images on a single page, append an additional letter <i>a</i>, <i>b</i>, <i>c</i>âŠ to the filename. For example, if a JPEG image appeared on page 36 of the publication <i>u7548e</i> discussed earlier, it would be placed in a file named <i>u7548e36.jpg</i> or <i>p36.jpg</i>.</Text>
+<Text id="178">Once the images have been scanned, you can put batch-processing programs to work to resize or enhance all the images at once.</Text>
+</Content>
+</Subsection>
+<Subsection id="specialized_material">
+<Title>
+<Text id="179">Specialized material</Text>
+</Title>
+<Content>
+<Text id="180">Many documents contain specialized material such as special characters, formulas, and difficult pages. Special characters generally relate to different languages and diacritical marks. The language option for the OCR program should be set for the specific language being read. Formulas will have to be recreated manually. Sometimes this is not possible in the OCR program, but only in a word processor like MICROSOFT Word. Difficult pages that contain complex material or are damaged so that a clear image cannot be obtained might have to be retyped manually.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="productivity_and_resources_1">
+<Title>
+<Text id="181">Productivity and resources</Text>
+</Title>
+<Content>
+<Text id="182">As mentioned earlier, you should not underestimate the difficulty of OCR. Although the economic and practical options for OCR should be considered separately from scanning, similar points arise: the necessary investment in computers; the availability of human resources and management skills; training the workforce; salary costs; the total number of pages to be processed; and whether documents can be outsourced to third parties.</Text>
+<Text id="183">In this section we share our experience of OCR operations in Belgium, Romania and India. All case studies, calculations and figures assume average situations, documents of standard difficulty (including tables and images) such as are found in most archives or libraries, very high-quality results, and a medium- to long-term operation.</Text>
+<Subsection id="intensive_ocr">
+<Title>
+<Text id="184">Intensive OCR</Text>
+</Title>
+<Content>
+<Text id="185">OCR is difficult. It demands great concentration and much skill. Before attaining peak productivity level and quality, a learning period of about six weeks is needed.</Text>
+<Text id="186">Typically, best results and productivity are achieved during the first hours of each day. After three hours of OCR work, productivity declines very rapidly, perhaps to 50% of the initial level. After six hours most people become very tired.</Text>
+<Text id="187">The same kind of evolution occurs over the initial weeks. In the first few weeks everyone achieves fairly high productivity, but after that up to two-thirds of people become bored and frustrated. These people either quit or perform poorly in terms of quality and productivity. Even those who pass the first three to five critical weeks and become part of the regular work team often leave in search of a better position after 6 to 12 months.</Text>
+<Text id="188">The remarks made in Section <CrossRef target="Section" ref="the_ocr_process"/> about personnel apply particularly to intensive OCR. Quality checks are best undertaken by native speakers or people with a good command of the language being checked. Young people generally sustain higher concentration than older people for OCR work. As a rule-of-the-thumb, people aged between 18 and 23 years tend to be better suited than those over 25.</Text>
+<Text id="189">Finally, OCR can be a boring job, which makes motivation and sustained commitment to quality exceptionally important.</Text>
+<Text id="190">These facts about OCR lead to the following guidelines:</Text>
+<BulletList>
+<Bullet>
+<Text id="191">Young people between 18 and 25 are best suited for this job.</Text>
+</Bullet>
+<Bullet>
+<Text id="192">Because the first hours are always the most productive, the work should either be organized on a part-time basis or only the most motivated and concentrated people should be selected for full-time work.</Text>
+</Bullet>
+<Bullet>
+<Text id="193">Two-thirds of people tend to quit or get bored after about three to five weeks. This translates into poorer quality and low productivity in the last weeks.</Text>
+</Bullet>
+<Bullet>
+<Text id="194">A regular supply of work is needed to justify the necessary training, to maintain concentration, and to keep spirits high.</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Subsection>
+<Subsection id="achievable_productivity">
+<Title>
+<Text id="195">Achievable productivity</Text>
+</Title>
+<Content>
+<Table id="table_ocr_productivity">
+<Title>
+<Text id="196">OCR productivity</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="161"/>
+<th width="142">
+<Text id="197">Working hours/day</Text>
+</th>
+<th width="123">
+<Text id="198">Pages/day</Text>
+</th>
+<th width="104">
+<Text id="199">Pages/month</Text>
+</th>
+</tr>
+<tr>
+<th width="161">
+<Text id="200">Initial training (6 weeks)</Text>
+</th>
+<th width="142">
+<Text id="201">3</Text>
+</th>
+<th width="123">
+<Text id="202">6</Text>
+</th>
+<th width="104">
+<Text id="203">120</Text>
+</th>
+</tr>
+<tr>
+<th width="161">
+<Text id="204">Optimal productivity level</Text>
+</th>
+<th width="142">
+<Text id="205">3</Text>
+</th>
+<th width="123">
+<Text id="206">9</Text>
+</th>
+<th width="104">
+<Text id="207">150 to 200</Text>
+</th>
+</tr>
+<tr>
+<th width="161"/>
+<th width="142">
+<Text id="208">7</Text>
+</th>
+<th width="123">
+<Text id="209">28</Text>
+</th>
+<th width="104">
+<Text id="210">500 to 600</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="211">Table <CrossRef target="Table" ref="table_ocr_productivity"/> gives typical OCR productivity figures. Documents come in all sizes and qualities, and these figures assume that the mix of documents contains an average number of images or tablesâsay one image and one table of five rows by five columns every 8 pages. They also assume that the page images are of medium to high qualityânote that, as discussed above, this depends on the quality of scanningâand that the OCR workers have a good command of the language.</Text>
+<Text id="212">Table <CrossRef target="Table" ref="table_ocr_productivity"/> gives separate figures for people undergoing training and for those who have reached their optimal productivity level. If a member of the administrative staff were to allocate three hours a day to OCR, they could achieve 180 to 200 pages OCR per month. For full-time staff with proper training, high concentration and dedication to quality, 500 to 600 pages a month can be achieved.</Text>
+<Text id="213">However, the rates that are achieved on difficult pages of low quality, with many columns or many tables, are far lowerâperhaps 300 to 400 pages per month for full-time work.</Text>
+<Text id="214">Assume that the salary cost for dedicated and motivated full-time OCR workers is $400 per month, and the overheadâincluding management costs, computers, office space, utilities, etc.âcomes to another $300 to $400 per person per month. Then the cost of OCR comes to about $1.2 to $1.6 per page. Taking into account the training period, total volume, time-span, and layoff costs should the operation close down for lack of work, these figures rise to $1.5 to $2.5 per page.</Text>
+<Text id="215">The cost of in-house OCR should be weighed against the cost of outsourcing the work to a professional OCR company. These typically charge from $1.5 to $4 per page, including images and tables. Human Info NGO/Simple Words has such a unit in Romania, and charges humanitarian non-profit organizations a special price that ranges from $1.2 to $2 per page. Please contact us at scanning@humaninfo.org for further information and advice.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="alternatives_to_ocr">
+<Title>
+<Text id="216">Alternatives to OCR</Text>
+</Title>
+<Content>
+<Text id="217">There are two alternatives to OCR that we discuss here.</Text>
+<Subsection id="manual_retyping">
+<Title>
+<Text id="218">Manual retyping</Text>
+</Title>
+<Content>
+<Text id="219">One, which eliminates most scanning as well, is to retype the documents manually, using a word processor. This still requires the images and front cover to be scanned, but the remaining pages need not be scannedâthus one can dispense with both powerful scanners and OCR software.</Text>
+<Text id="220">The people who do this work do not have to understand the text. They must be accurate typists and re-key exactly what they see. Retyping does introduce errors, and double-keying is often used to find and correct these. This method involves two people who independently re-key the same document, after which both digital versions are compared word for word using a special software program by an operator who has the original document in front of them. The assumption is that if the same word has been typed independently twice in the same way, it is correct. However, this is not always true, and for extremely high precision, triple-keying is performed.</Text>
+<Text id="221">The advantage of rekeying is that cost is saved because an OCR program is not needed and so the computers can be older, lower-range, or second-hand modelsâwhereas powerful computers are needed for OCR. Also, the work can be performed by people with a lower level of skill. The disadvantages are that a training period of at least two months is needed. Single keying usually produces too many errors, and double or triple keying is needed.</Text>
+<Text id="222">The cost depends entirely on salary level. Typically, re-keyers in developing countries are paid on the order of $150/month. Their productivity could be twenty to thirty pages per dayâcorresponding to 400 pages per month, images included. With double-keying, this makes the total salary costs around $300 per month, plus overheads.</Text>
+</Content>
+</Subsection>
+<Subsection id="image_files">
+<Title>
+<Text id="223">Image files</Text>
+</Title>
+<Content>
+<Text id="224">A very low cost alternative to OCR is simply to use a PDF image version of the document pages. The cost is only a fraction of OCR'sâabout $0.1 per page.</Text>
+<Text id="225">Once scanning has been completed and TIFF files are available, an automatic converter (usually Adobe Acrobat or Adobe Photoshop) converts all TIFF files of book pages into PDF files.</Text>
+<Text id="226">The downside is that these files are not searchable. Also, they are quite largeâusually 50 Kb per page, plus or minus 20% depending on the quality of the original TIFF file.</Text>
+<Text id="227">PDF image files are slowâsometimes, in developing countries, impossible or prohibitively expensiveâto download. They rarely fit on a floppy disk, and do not support text manipulation functions such as cut-and-paste.</Text>
+<Text id="228">The PDF image file method should only be used if no OCR budget is available, and for documents that are likely to be used by a small number of people who have high-speed low-cost Internet access.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="combining_scanning_and_ocr">
+<Title>
+<Text id="229">Combining scanning and OCR</Text>
+</Title>
+<Content>
+<Text id="230">If a scanner is connected directly to the computer that runs the OCR software, most OCR programs can scan a page and perform OCR immediately. Page-by-page scanning and OCR is a reasonable strategy for low volumes, but will prove time-consuming for bigger and more continuous jobs.</Text>
+<Text id="231">For up to 100 to 150 pages per month, this solution may suffice. For higher volumes it is faster and more efficient to scan the document first, then perfom OCR on all the pages as a separate step.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="three_examples">
+<Title>
+<Text id="232">Three examples: 1000 to 100,000 pages</Text>
+</Title>
+<Content>
+<Section id="typical_small_collection">
+<Title>
+<Text id="233">Typical small collection: 500 to 1000 pages</Text>
+</Title>
+<Content>
+<Text id="234">Most NGOs have 500 to 1000 pages to scan. This volume can be OCRed in-house if motivated volunteers are available.</Text>
+<Part id="scanning">
+<Title>
+<Text id="235">Scanning</Text>
+</Title>
+<Content>
+<Text id="236">The first step is to scan the publications to generate a high-quality TIFF file of each page, and a separate line-art, grey-scale or color bitmap image for each illustration. Assuming that 1000 pages have to be scanned, this might represent a part-time job of about one monthâjust for scanning. The TIFF files would consume 60 to 80 Mb of hard-disk space, and a good policy is to create a CD-R containing these files. A low-cost flatbed scanner of $100 to $300 will be sufficient for the job. Scanning can be done after working hours or during the weekends by a volunteer in the office or at home.</Text>
+</Content>
+</Part>
+<Part id="ocr">
+<Title>
+<Text id="237">OCR</Text>
+</Title>
+<Content>
+<Text id="238">The second step is OCR by another volunteer, or team of volunteers, skilled in language and correction. The TIFF files can either be shared between computers, or one computer can be used for the entire job. Typically, it will take five or six months of part-time labor (e.g. 20 hours a week) to convert 1000 pages into perfect Word or HTML documents.</Text>
+</Content>
+</Part>
+<Part id="outsourcing">
+<Title>
+<Text id="239">Outsourcing</Text>
+</Title>
+<Content>
+<Text id="240">An alternative is to outsource the scanning and OCR process. It would probably cost $1500 to $2000 to convert everything into perfect Word and HTML files.</Text>
+</Content>
+</Part>
+</Content>
+</Section>
+<Section id="all_publications_from_an_organization">
+<Title>
+<Text id="241">All publications from an organization: 5000 pages</Text>
+</Title>
+<Content>
+<Text id="242">Many larger organizations have archives of around 5000 pages of currrent or out-of print books, journals, newsletters, grey literature, etc.</Text>
+<Part id="scanning_1">
+<Title>
+<Text id="243">Scanning</Text>
+</Title>
+<Content>
+<Text id="244">This is too much for a flat-bed scanner. Scanning should either be outsourced (approximately $400 for 5000 pages) or a sheet-feeder scanner purchased (approximately $900). Alternatively, a more expensive scanner could be bought together with a few other institutions or NGOs ($6000 costs divided by the number of participants). All 5000 pages in TIFF format will take about 300 to 400 Mb of hard-disk space. Again, a good policy is to create a CD-R containing these files.</Text>
+</Content>
+</Part>
+<Part id="ocr_1">
+<Title>
+<Text id="245">OCR</Text>
+</Title>
+<Content>
+<Text id="246">The second step is OCR by another volunteer, or team of volunteers, skilled in OCR and correction. Again, several computers might be used, or one computer for the whole job. It would take 25 to 30 months of half-time labor (assuming 20 hours a week) to convert 5000 pages into perfect Word or HTML. In practice this is too long and too computer-intensive to manage on a volunteer basis. One would have to pay volunteers, monitor them for performance and quality, provide adequate space, etc, in order to have the job finished within reasonable time at a high level of quality.</Text>
+<Text id="247">Alternatively one could create image PDF files, which would take 300 to 400 Mb of space and would be harder to download over the Internet.</Text>
+</Content>
+</Part>
+<Part id="outsourcing_1">
+<Title>
+<Text id="248">Outsourcing</Text>
+</Title>
+<Content>
+<Text id="249">An alternative is to outsource the scanning and OCR processes. It would probably cost $7500 to $10,000 to convert everything into perfect Word and HTML files.</Text>
+</Content>
+</Part>
+</Content>
+</Section>
+<Section id="a_small_library">
+<Title>
+<Text id="250">A small library: 100,000 pages</Text>
+</Title>
+<Content>
+<Text id="251">Larger organizations, universities, governments, and specialized libraries might have a whole library to digitizeâsay 100,000 pages. The first issue to consider is the copyright status of the publications. If they are not in the public domain, explicit permission to digitize them must be obtained from the copyright holders. You should also check whether the files are already available digitally.</Text>
+<Part id="scanning_2">
+<Title>
+<Text id="252">Scanning</Text>
+</Title>
+<Content>
+<Text id="253">The volume is too high for a sheet-feed scanner. Scanning should either be outsourced ($8000 for 100,000 pages), or a more expensive scanner purchased together with a few other institutions or NGOs ($6000 shared between the participants). 100,000 pages in TIFF format will take 6 to 8 Gb of hard-disk space. The best plan is to create a set of CD-R copies containing these files.</Text>
+</Content>
+</Part>
+<Part id="ocr_2">
+<Title>
+<Text id="254">OCR</Text>
+</Title>
+<Content>
+<Text id="255">The second step is OCR (or creation of PDF files for less widely used documents). It would take 500 to 700 months of half-time labor to convert 100,000 pages into perfect Word or HTML. This is impossible to realize with volunteers, and the job must be done on a professional basis.</Text>
+<Text id="256">To save cost, some of the less-frequently-used pagesâsay 80% or 80,000 pagesâcould be transformed into PDF, and the other 20,000 pages into Word and HTML. The PDFs would take 4 to 6 Gb space and be harder to download on the Internet, but would cost only $0.2 per page to create by a professional organization (total of $16,000). If 80,000 PDF files were created from TIFF files by volunteers using PDF conversion programs like Adobe Acrobat, 10 to 20 months of part-time work would be necessary on a powerful computer.</Text>
+</Content>
+</Part>
+<Part id="outsourcing_2">
+<Title>
+<Text id="257">Outsourcing</Text>
+</Title>
+<Content>
+<Text id="258">An alternative is to outsource the work. If the 80% PDF and 20% HTML mix were maintained, the PDF would cost around $16,000 and the HTML $30,000 to $40,000âa total budget of around $50,000. If everything were OCRed, it would cost $150,000 to $200,000 to convert the entire collection into perfect Word and /HTML files.</Text>
+</Content>
+</Part>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="creating_an_electronic_collection">
+<Title>
+<Text id="259">Creating an electronic collection</Text>
+</Title>
+<Content>
+<Text id="260">Three important aspects should be kept in mind when deciding to create digital collections. First, the collection must be organized. The more content there is, the greater the need for indexes and powerful search systems. For collections of 3000 to 5000 pages or more, indexes and search systems are essential. Second, the needs of end-users must prevail. The target groups that will use the collection should be identified, and a process of regular consultation set up. Third, the available budget will determine how much can be done.</Text>
+<Section id="methods_of_collection_building">
+<Title>
+<Text id="261">Methods of collection building</Text>
+</Title>
+<Content>
+<Text id="262">There are many examples of excellent CD-ROMs that are created on the web-page model. HTML, PDF or Word documents are added and linked using hyperlinks. Navigation is made simple and attractive by the use of hyperlinks, frames, keywords, indexes and so on. Such systems work well up to a few thousand pages, but from 3000 to 5000 pages onwards it is important to have a well-structured collection and a powerful search facility. This is where the Greenstone software can help.</Text>
+<Text id="263">The Greenstone Digital Library software creates a structured digital library including a very powerful search and retrieval engine. Up to 150,000 pages can be indexed on a single CD-ROM. Every CD-ROM can become an Internet server. Greenstone is open-source software, and is freely available under the GNU license.</Text>
+<Text id="264">The companion manuals describe how to build Greenstone collections. There are essentially three different ways of building collections:</Text>
+<BulletList>
+<Bullet>
+<Text id="265">The librarian interface</Text>
+</Bullet>
+<Bullet>
+<Text id="266">The Collector</Text>
+</Bullet>
+<Bullet>
+<Text id="267">Building from the command line.</Text>
+</Bullet>
+</BulletList>
+<Text id="268">The first method is the âlibrarianâ interface, described in the <i>Greenstone Digital Library User's Guide</i>(Chapter 3, âMaking Greenstone Collectionsâ). This is a comprehensive interactive facility for collection-building. With it, you can collect sets of documents, import or assign metadata, and build them into a Greenstone collection. The second method is the âCollectorâ subsystem, described in Chapter 4 of the <i>User's Guide</i>. This is an older facility that provides an alternative way of building collections of web pages or other documents. It guides you through a sequence of interactive web pages that request the information needed. However, it does not provide any way of adding metadata to the documents, andâbecause it is a web interfaceâit is not really suitable for collections that take more than a few minutes to build. The third method is to run the programs for collection-building directly from the command line; this is in the <i>Greenstone Digital Library Developer's Guide</i>(Chapter 1). This gives more flexibility in running programs individually and saving intermediate results, which may be desirable for collections that take many hours to build. You will also need to read Chapter 2 of the <i>Developer's Guide</i> in order to harness the full power of Greenstone to build advanced collections.</Text>
+<Text id="269">There is a fourth method for creating and editing the material associated with a collection, a program called the Collection Organizer. However, its functionality has been superseded by the librarian interface mentioned above. It is described in a legacy document entitled <i>Using the Organizer</i>.</Text>
+</Content>
+</Section>
+<Section id="getting_started_in_seven_steps_and_15_minutes">
+<Title>
+<Text id="270">Getting started in seven steps and 15 minutes</Text>
+</Title>
+<Content>
+<Text id="271">The best way of getting the look and feel of the librarian interface is to actually create a small test library. If you have 15 minutes please follow these steps and you will understand this program much better.</Text>
+<Text id="272">Before getting started, first install Greenstone (see the <i>Greenstone Installer's Guide</i>) which includes the Demo collection in DLS format and its source files. <b>Note, if you wish to be able to add to your collection any of the 140 documents in the DLS collection (instead of just the 11 of these documents in the Greenstone Demo collection), you should install DLS as one of the sample Greenstone libraries.</b> The Demo and DLS collections will be installed in <i>C:\Program Files\gsdl\collect</i>, in subdirectories <i>demo</i> and <i>dls</i> respectively. If you previously installed Greenstone without DLS and wish to install it, then you may re-insert your Greenstone CD-ROM and add this collection. It is not necessary to uninstall Greenstone first.</Text>
+<Text id="273">We suggest that you print the instructions below and follow them step by step:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="274">Launch the librarian interface under Windows by selecting <i>Greenstone Digital Library</i> from the <i>Programs</i> section of the <i>Start</i> menu and choosing <i>Librarian Interface</i>If you are using Unix, instead type</Text>
+<CodeLine>cd ~/gsdl</CodeLine>
+<CodeLine>cd gli</CodeLine>
+<CodeLine>./gli.sh</CodeLine>
+<Text id="275">where <i>~/gsdl</i> is the directory containing your Greenstone system.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="276">Select <i>New</i> from the File menu in the horizontal menu bar at the top of the window. Give it a title, for example âMy First Collection,â and fill out your email address and a brief description of the collection. In the âBase this collection onâ menu, choose âgreenstone demoâ or âDevelopment Library Subsetâ (the effect is the same because these two collections have the same structure).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="277">Add some documents from the Demo collection (or the DLS collection if it is installed) to your new collection. To do this, double-click the <i>Greenstone Collections</i> folder in the left-hand panel, then double-click the collection you desire. The documents in it are displayed underneath. Select one of these, drag it, and drop into the right-hand panel. This panel represents the collection you are building. Choose several documents and drag them into it one by one, or using multiple selection in the standard way.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="278">Add some of your own documents that are not in the Demo or DLS collections. Close the <i>Greenstone Collections</i> folder in the left-hand panel and double-click the <i>Local Filespace</i> folder. Navigate to a directory that contains some documents (e.g. small Word or HTML files). Drag a few of these into the right-hand panel to include them in your collection.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="279">Add metadata to the documents in your collection. So far you have been operating under the <i>Gather</i> panel, indicated by the <i>Gather</i> tab underneath the horizontal menu bar at the top of the window. Click the <i>Enrich</i> tab beside it. The documents in your collection now appear in the left-hand panel: click one and examine the metadata associated with it in the â<i>Element âŠ Value</i>â table at the top right. Use the panel underneath to change individual values by selecting the desired <i>Element</i> and either choosing an existing value from the list or typing a new value into the box near the bottom. Add <i>Title</i>, <i>Organization</i>, and <i>Keyword</i> metadata to each of your own documents that you put in the collection. After you type each value you need to click â <i>Appendix</i> to add that value to the metadata.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="280">Click the <i>Create</i> tab to leave the <i>Enrich</i> mode and create your new collection. Click the <i>Build Collection</i> button at the bottom. While the computer is building the collection you will receive some feedback on what it is doing.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="281">When it has finished, click the <i>Preview</i> tab to view the collection from within the librarian interface. Check the <i>titles a-z</i>, <i>organisations</i> and <i>how to</i> lists to ensure that your documents have been included in the collection. You will also find when you visit your Greenstone home page that the collection has been installed as one of the regular collections.</Text>
+</NumberedItem>
+</NumberedList>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<FootnoteList>
+<Footnote id="1">
+<Text id="282">All sums of money mentioned in this document are in US dollars, and were current in 2001.</Text>
+</Footnote>
+<Footnote id="2">
+<Text id="283">Recall that all sums of money are expressed in 2001 US dollars.</Text>
+</Footnote>
+</FootnoteList>
+</Manual>
Index: /tags/start/gsdl-documentation/manuals/xml-source/en/User_en.xml
===================================================================
--- /tags/start/gsdl-documentation/manuals/xml-source/en/User_en.xml	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/xml-source/en/User_en.xml	(revision 13666)
@@ -0,0 +1,2510 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Manual>
+<Heading>
+<Text id="1">GREENSTONE DIGITAL LIBRARY</Text>
+</Heading>
+<Title>
+<Text id="2">USER'S GUIDE</Text>
+</Title>
+<Author>
+<Text id="3">Ian H. Witten, Stefan Boddie and John Thompson</Text>
+</Author>
+<Affiliation>
+<Text id="4">Department of Computer Science <br/>University of Waikato, New Zealand</Text>
+</Affiliation>
+<Text id="5">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 New Zealand Digital Library Project at the University of Waikato, and developed 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.</Text>
+<Comment>
+<Text id="6">We want to ensure that this software works well for you. Please report any problems to <i>greenstone@cs.waikato.ac.nz</i></Text>
+</Comment>
+<Version>
+<Text id="7">Greenstone gsdl-2.70</Text>
+</Version>
+<Date>
+<Text id="8">March 2006</Text>
+</Date>
+<Section id="about_this_manual">
+<Title>
+<Text id="9">About this manual</Text>
+</Title>
+<Content>
+<Text id="10">This manual provides a comprehensive description of how to use the Greenstone software for accessing and building digital library collections.</Text>
+<Text id="11">Section <CrossRef target="Chapter" ref="overview_of_greenstone"/> gives an overview of the capabilities of the software. Section <CrossRef target="Chapter" ref="using_greenstone_collections"/> explains how to use Greenstone collections. The interface is self-explanatoryâthe best way to learn is by doingand this section comprises the on-line help information for a typical collection. Section <CrossRef target="Chapter" ref="making_greenstone_collections"/> explains how to build your own library collections using the Greenstone Librarian Interface. Section <CrossRef target="Chapter" ref="administration"/> introduces the administration facility that allows the system administrator to monitor what is going on and control who can build collections.</Text>
+<Text id="12">Appendices list the features of the Greenstone software, and give a glossary of terms used throughout the Greenstone documentation.</Text>
+</Content>
+</Section>
+<Section id="companion_documents">
+<Title>
+<Text id="13">Companion documents</Text>
+</Title>
+<Content>
+<Text id="14">The complete set of Greenstone documents includes four volumes:</Text>
+<BulletList>
+<Bullet>
+<Text id="15">Greenstone Digital Library Installer's Guide</Text>
+</Bullet>
+<Bullet>
+<Text id="16">Greenstone Digital Library User's Guide <i>(this document)</i></Text>
+</Bullet>
+<Bullet>
+<Text id="17">Greenstone Digital Library Developer's Guide</Text>
+</Bullet>
+<Bullet>
+<Text id="18">Greenstone Digital Library: From Paper to Collection</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Section>
+<Section id="acknowledgements">
+<Title>
+<Text id="19">Acknowledgements</Text>
+</Title>
+<Content>
+<Text id="20">The Greenstone software is a collaborative effort between manypeople. Rodger McNab and Stefan Boddie are the principal architects andimplementors. Contributions have been made by David Bainbridge, GeorgeBuchanan, Hong Chen, Michael Dewsnip, Katherine Don, Elke Duncker, Carl Gutwin, Geoff Holmes, Dana McKay, JohnMcPherson, Craig Nevill-Manning, Dynal Patel, Gordon Paynter, Bernhard Pfahringer, ToddReed, Bill Rogers, John Thompson, and Stuart Yeates. Other members of the New ZealandDigital Library project provided advice and inspiration in the design ofthe system: Mark Apperley, Sally Jo Cunningham, Matt Jones, Steve Jones, Te TakaKeegan, Michel Loots, Malika Mahoui, Gary Marsden, Dave Nichols and Lloyd Smith. We would also like toacknowledge all those who have contributed to the GNU-licensed packagesincluded in this distribution: MG, GDBM, PDFTOHTML, PERL, WGET, WVWARE and XLHTML.</Text>
+</Content>
+</Section>
+<Chapter id="overview_of_greenstone">
+<Title>
+<Text id="21">Overview of Greenstone</Text>
+</Title>
+<Content>
+<Text id="22">Greenstone is a comprehensive system for constructing and presenting collections of thousands or millions of documents, including text, images, audio and video.</Text>
+<Section id="collections">
+<Title>
+<Text id="23">Collections</Text>
+</Title>
+<Content>
+<Text id="24">A typical digital library built with Greenstone will contain many collections, individually organizedâthough they bear a strong family resemblance. Easily maintained, collections can be augmented and rebuilt automatically.</Text>
+<Text id="25">There are several ways to find information in most Greenstone collections. For example, you can <i>search for particular words</i> that appear in the text, or within a section of a document. You can <i>browse documents by title</i>: just click on a book to read it. You can <i>browse documents by subject</i>. Subjects are represented by bookshelves: just click on a bookshelf to look at the books. Where appropriate, documents come complete with a table of contents: you can click on a chapter or subsection to open it, expand the full table of contents, or expand the full document into your browser window (useful for printing). The New Zealand Digital Library website (<i>nzdl.org</i>) provides numerous example collections.</Text>
+<Text id="26">On the front page of each collection is a statement of its purpose and coverage, and an explanation of how the collection is organized. Most collections can be accessed by both <i>searching</i> and <i>browsing</i>. When searching, the Greenstone software looks through the entire text of all documents in the collection (this is called âfull-text searchâ). In most collections the user can choose between indexes built from different parts of the documents. Some collections have an index of full documents, an index of paragraphs, and an index of titles, each of which can be searched for particular words or phrases. Using these you can find all documents that contain a particular set of words (the words may be scattered far and wide throughout the document), or all paragraphs that contain the set of words (which must all appear in the same paragraph), or all documents whose titles contain the words (the words must all appear in the document's title). There might be other indexes, perhaps an index of sections, and an index of section headings. Browsing involves lists that the user can examine: lists of authors, lists of titles, lists of dates, hierarchical classification structures, and so on. Different collections offer different browsing facilities.</Text>
+</Content>
+</Section>
+<Section id="finding_information">
+<Title>
+<Text id="27">Finding information</Text>
+</Title>
+<Content>
+<Text id="28">Greenstone constructs full-text indexes from the document textâthat is, indexes that enable searching on any words in the full text of the document. Indexes can be searched for particular words, combinations of words, or phrases, and results are ordered according to how relevant they are to the query.</Text>
+<Text id="29">In most collections, descriptive data such as author, title, date, keywords, and so on, is associated with each document. This information is called <i>metadata</i>. Many document collections also contain full-text indexes of certain kinds of metadata. For example, many collections have a searchable index of document titles.</Text>
+<Text id="30">Users can browse interactively around lists, and hierarchical structures, that are generated from the metadata that is associated with each document in the collection. Metadata forms the raw material for browsing. It must be provided explicitly or be derivable automatically from the documents themselves. Different collections offer different searching and browsing facilities. Indexes for both searching and browsing are constructed during a âbuildingâ process, according to information in a collection configuration file.</Text>
+<Text id="31">Greenstone creates all index structures automatically from the documents and suppporting files: nothing is done manually. If new documents in the same format become available, they can be merged into the collection automatically. Indeed, for many collections this is done by processes that awake regularly, scout for new material, and rebuild the indexesâall without manual intervention.</Text>
+</Content>
+</Section>
+<Section id="document_formats">
+<Title>
+<Text id="32">Document formats</Text>
+</Title>
+<Content>
+<Text id="33">Source documents come in a variety of formats, and are converted into a standard XML form for indexing by âplugins.â Plugins distributed with Greenstone process plain text, HTML, WORD and PDF documents, and Usenet and E-mail messages. New ones can be written for different document types (to do this you need to study the <i>Greenstone Digital Library Developer's Guide</i>). To build browsing structures from metadata, an analogous scheme of âclassifiersâ is used. These create browsing indexes of various kinds: scrollable lists, alphabetic selectors, dates, and arbitrary hierarchies. Again, Greenstone programmers can create new browsing structures.</Text>
+</Content>
+</Section>
+<Section id="multimedia_and_multilingual_documents">
+<Title>
+<Text id="34">Multimedia and multilingual documents</Text>
+</Title>
+<Content>
+<Text id="35">Collections can contain text, pictures, audio and video. Non-textual material is either linked into the textual documents or accompanied by textual descriptions (such as figure captions) to allow full-text searching and browsing.</Text>
+<Text id="36">Unicode, which is a standard scheme for representing the character sets used in the world's languages, is used throughout Greenstone. This allows any language to be processed and displayed in a consistent manner. Collections have been built containing Arabic, Chinese, English, French, M 0Ã
+Â 1ori and Spanish. Multilingual collections embody automatic language recognition, and the interface is available in all the above languages (and more).</Text>
+</Content>
+</Section>
+<Section id="distributing_greenstone">
+<Title>
+<Text id="37">Distributing Greenstone</Text>
+</Title>
+<Content>
+<Text id="38">Collections are accessed over the Internet or published, in precisely the same form, on a self-installing Windows CD-ROM. Compression is used to compact the text and indexes. A Corba protocol supports distributed collections and graphical query interfaces.</Text>
+<Text id="39">The New Zealand Digital Library (<i>nzdl.org</i>) provides many example collections, including historical documents, humanitarian and development information, technical reports and bibliographies, literary works, and magazines.</Text>
+<Text id="40">Being open source, Greenstone is readily extensible, and benefits from the inclusion of Gnu-licensed modules for full-text retrieval, database management, and text extraction from proprietary document formats. Only through international cooperative efforts will digital library software become sufficiently comprehensive to meet the world's needs with the richness and flexibility that users deserve.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="using_greenstone_collections">
+<Title>
+<Text id="41">Using Greenstone Collections</Text>
+</Title>
+<Content>
+<Text id="42">The Greenstone software is designed to be easy to use. Web-based and CD-ROM collections have interfaces that are identical. Installing the Greenstone software from CD-ROM on any Windows or Linux computer is very easy indeed; a standard installation setup program is used in conjunction with pre-compiled binaries. A collection can be used locally on the computer where it is installed; also, if this computer is connected to a network, the software automatically and transparently allows all other computers on the network to access the same collection.</Text>
+<Text id="43">The next section describes how to install a Greenstone CD-ROM. Then we look at the searching and browsing facilities offered by a typical Greenstone collection, the âDemoâ collection that is supplied with the Greenstone software. Other collections offer similar facilities; if you can use one, you can use them all. The following section explains how to customize the interface for your own requirements using the Preferences page.</Text>
+<Section id="using_a_greenstone_cd-rom">
+<Title>
+<Text id="44">Using a Greenstone CD-ROM</Text>
+</Title>
+<Content>
+<Text id="45">The Greenstone digital library software itself comes on a CD-ROM, and you or your system manager have probably installed it on your system, following the instructions in the <i>Greenstone Digital Library Installer's Guide.</i> If so, Greenstone is already installed on your computer and you should skip the rest of this section.</Text>
+<Text id="46">Some Greenstone collections come on a self-contained Greenstone CD-ROM that includes enough of the software to run just that collection. To use it, simply put it into the CD-ROM drive on any Windows PC. Most likely (if âautorunâ is enabled on your PC), a window will appear inviting you to install the Greenstone software. If not, find the CD-ROM disk drive (on current Windows systems you can get this by clicking on the <i>My Computer</i> icon on the desktop) and double-click it, then the <i>Setup.exe</i> file inside it. The Greenstone <i>Setup</i> program will be entered, which guides you through the setup procedure. Most people respond <i>yes</i> to all the questions.</Text>
+<Text id="47">When the installation procedure has finished, you'll find the library in the <i>Programs</i> submenu of the Windows <i>Start</i> menu, under the name of the collection (for example, âDevelopment Libraryâ or âUnited Nations Universityâ).</Text>
+<Text id="48">Once the software has been installed, the library will be entered automatically every time you re-insert the CD-ROM if autorun is enabled.</Text>
+</Content>
+</Section>
+<Section id="finding_information_1">
+<Title>
+<Text id="49">Finding information</Text>
+</Title>
+<Content>
+<Text id="50">The easiest way to learn how to use a Greenstone collection is to try it out. Don't worryâyou can't break anything. Click liberally: most images that appear on the screen are clickable. If you hold the mouse stationary over an image, most browsers will soon pop up a message that tells you what will happen if you click.</Text>
+<Text id="51">Experiment! Choose common words like âtheâ and âandâ to search forâthat should evoke some responses, and nothing will break.</Text>
+<Text id="52">Greenstone digital library systems usually comprise several separate collectionsâfor example, computer science technical reports, literary works, internet FAQs, magazines. There will be a home page for the digital library system which allows you to access any publicly-accessible collection; in addition, each collection has its own âaboutâ page that gives you information about how the collection is organized and the principles governing what is included in it. To get back to the âaboutâ page at any time, just click on the âcollectionâ icon that appears at the top left side of all searching and browsing pages.</Text>
+<Text id="53">Figure 1 shows a screenshot of the âDemoâ collection supplied with the Greenstone software, which is a very small subset of the Development Library collection; we will use it as an example to describe the different ways of finding information. (If you can't find the Demo collection, use the Development Library instead; it looks just the same.) First, almost all icons are clickable. Several icons appear at the top of almost every page; Table 1 shows you what they mean.</Text>
+<Figure id="using_the_demo_collection">
+<Title>
+<Text id="54">Using the Demo collection</Text>
+</Title>
+<File width="397" height="286" url="images/User_Fig_1.png"/>
+</Figure>
+<Table id="what_the_icons_at_the_top_of_each_page_mean">
+<Title>
+<Text id="55">What the icons at the top of each page mean</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<File width="68" height="32" url="images/User_Icon_1.png"/>
+</th>
+<th width="397">
+<Text id="56">This takes you to the âaboutâ page</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<File width="36" height="16" url="images/User_Icon_2.png"/>
+</th>
+<th width="397">
+<Text id="57">This takes you to the Digital Library's home page, from which you can select another collection</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<File width="29" height="16" url="images/User_Icon_3.png"/>
+</th>
+<th width="397">
+<Text id="58">This provides help text similar to what you are reading now</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<File width="70" height="16" url="images/User_Icon_4.png"/>
+</th>
+<th width="397">
+<Text id="59">This allows you to set some user interface and searching options that will then be used henceforth</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="60">The â<i>search âŠ subjects âŠ titles a-z âŠ organization âŠ how to</i>â bar underneath gives access to the searching and browsing facilities. The leftmost button is for searching, and the ones to the right of itâfour, in this collectionâevoke different browsing facilities. These last four may differ from one collection to another.</Text>
+<Subsection id="how_to_find_information">
+<Title>
+<Text id="61">How to find information</Text>
+</Title>
+<Content>
+<Text id="62">Table 2 shows the five ways to find information in the Demo collection.</Text>
+<Table id="table_icons_on_the_search_browse_bar">
+<Title>
+<Text id="63">What the icons on the search/browse bar mean</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="123">
+<File width="61" height="11" url="images/User_Icon_5.png"/>
+</th>
+<th width="407">
+<Text id="64">Search for particular words</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="58" height="11" url="images/User_Icon_6.png"/>
+</th>
+<th width="407">
+<Text id="65">Access publications by subject</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="58" height="11" url="images/User_Icon_7.png"/>
+</th>
+<th width="407">
+<Text id="66">Access publications by title</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="71" height="11" url="images/User_Icon_8.png"/>
+</th>
+<th width="407">
+<Text id="67">Access publications by organization</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="58" height="11" url="images/User_Icon_9.png"/>
+</th>
+<th width="407">
+<Text id="68">Access publications by âhow toâ listing</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="69">You can <i>search for particular words</i> that appear in the text from the âsearchâ page. (This is just like the âaboutâ page shown in Figure 1, except that it doesn't contain the <i>about this collection</i> text.) The search page can be reached from other pages by pressing the <i>search</i> button. 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 that can be further expanded by clicking on them. You can <i>access publications by title</i> by pressing the <i>titles a-z</i> button. This brings up a list of books in alphabetic order. You can <i>access publications by organization</i> by pressing the <i>organization</i> button. This brings up a list of organizations. 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â hints. All these buttons are visible in Figure 1.</Text>
+</Content>
+</Subsection>
+<Subsection id="how_to_read_the_documents">
+<Title>
+<Text id="70">How to read the documents</Text>
+</Title>
+<Content>
+<Text id="71">In the Demo collection, you can tell when you have arrived at an individual book because there is a photograph of its front cover (Figure 2). Beside the photograph is a table of contents: the entry in bold face marks where you are, in this case <i>Introduction and Summary</i> âSection 1 of the chosen book. This table is expandable: click on the folders to open them or close them. Click on the open book at the top to close it.</Text>
+<Text id="72">Underneath is the text of the current section (âThe international demand for tropical butterflies âŠâ in the example, beginning at the very bottom of the illustration). When you have read through it, there are arrows at the end to take you on to the next section or back to the previous one.</Text>
+<Text id="73">Below the photograph are four buttons. Click on <i>detach</i> to make a new browser window for this book. (This is useful if you want to compare books, or read two at once.) If you have reached this book through a search, the search terms will be highlighted: the <i>no highlighting</i> button turns this off. Click on <i>expand text</i> to expand out the whole text of the current section, or book. Click on <i>expand contents</i> to expand out the whole table of contents so that you can see the titles of all chapters and subsections.</Text>
+<Text id="74">In some collections, the documents do not have this kind of hierarchical structure. In this case, no table of contents is displayed when you get to an individual documentâjust the document text. In some cases, the document is split into pages, and you can read sequentially or jump about from one page to another.</Text>
+<Figure id="a_book_in_the_demo_collection">
+<Title>
+<Text id="75">A book in the Demo collection</Text>
+</Title>
+<File width="397" height="476" url="images/User_Fig_2.png"/>
+</Figure>
+</Content>
+</Subsection>
+<Subsection id="what_the_icons_mean">
+<Title>
+<Text id="76">What the icons mean</Text>
+</Title>
+<Content>
+<Text id="77">When you are browsing around the collection, you will encounter the items shown in Table 3.</Text>
+</Content>
+</Subsection>
+<Subsection id="how_to_search_for_particular_words">
+<Title>
+<Text id="78">How to search for particular words</Text>
+</Title>
+<Content>
+<Text id="79">From the search page, follow these simple steps to make a query:</Text>
+<BulletList>
+<Bullet>
+<Text id="80">Specify what units you want to search: in the Demo collection you can search section titles or the full text of the books.</Text>
+</Bullet>
+<Bullet>
+<Text id="81">Say whether you want to search for all or just some of the words</Text>
+</Bullet>
+<Bullet>
+<Text id="82">Type in the words you want to search for into the query box</Text>
+</Bullet>
+<Bullet>
+<Text id="83">Click the <i>Begin Search</i> button</Text>
+</Bullet>
+</BulletList>
+<Text id="84">When you make a query, the titles of up to twenty matching documents will be shown. There is a button at the end to take you on to the next twenty. From there you will find buttons to take you on to the third twenty or back to the first twenty, and so on. However, for efficiency reasons a maximum of 100 is imposed on the number of documents returned. You can change these numbers by clicking the <i>preferences</i> button at the top of the page.</Text>
+<Table id="table_icons_that_you_will_encounter_when_browsing">
+<Title>
+<Text id="85">Icons that you will encounter when browsing</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="123">
+<File width="19" height="12" url="images/User_Icon_10.png"/>
+</th>
+<th width="407">
+<Text id="86">Click on a book icon to read the corresponding book</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="22" height="17" url="images/User_Icon_11.png"/>
+</th>
+<th width="407">
+<Text id="87">Click on a bookshelf icon to look at books on that subject</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="25" height="16" url="images/User_Icon_12.png"/>
+</th>
+<th width="407">
+<Text id="88">View this document</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="25" height="16" url="images/User_Icon_13.png"/>
+</th>
+<th width="407">
+<Text id="89">Open this folder and view contents</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="29" height="25" url="images/User_Icon_14.png"/>
+</th>
+<th width="407">
+<Text id="90">Click on this icon to close the book</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="25" height="17" url="images/User_Icon_15.png"/>
+</th>
+<th width="407">
+<Text id="91">Click on this icon to close the folder</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="32" height="17" url="images/User_Icon_16.png"/>
+</th>
+<th width="407">
+<Text id="92">Click on the arrow to go on to the next section ...</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="32" height="17" url="images/User_Icon_17.png"/>
+</th>
+<th width="407">
+<Text id="93">... or back to the previous section</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="49" height="31" url="images/User_Icon_18.png"/>
+</th>
+<th width="407">
+<Text id="94">Open this page in a new window</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="61" height="32" url="images/User_Icon_19.png"/>
+</th>
+<th width="407">
+<Text id="95">Expand table of contents</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="48" height="32" url="images/User_Icon_20.png"/>
+</th>
+<th width="407">
+<Text id="96">Display all text</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="55" height="31" url="images/User_Icon_21.png"/>
+</th>
+<th width="407">
+<Text id="97">Highlight search terms</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="98">Click the title of any document, or the little icon beside it, to open it. The icon may show a book, or a folder, or a page: it will be a book icon if you are searching books; otherwise if you are searching sections it will be a folder or page icon depending on whether or not the section found has subsections.</Text>
+<Part id="search_terms">
+<Title>
+<Text id="99"><b><i>Search terms</i></b></Text>
+</Title>
+<Content>
+<Text id="100">Whatever you type into the query box is interpreted as a list of words called âsearch terms.â Each search term contains nothing but alphabetic characters and digits. Terms are separated by white space. If any other characters such as punctuation appear, they serve to separate terms just as though they were spaces. And then they are ignored. You can't search for words that include punctuation.</Text>
+<Text id="101">For example, the query</Text>
+<Text type="code" id="102">Agro-forestry in the Pacific Islands: Systems for Sustainability (1993)</Text>
+<Text id="103">will be treated the same as</Text>
+<Text type="code" id="104">Agro forestry in the Pacific Islands Systems for Sustainability 1993</Text>
+</Content>
+</Part>
+<Part id="query_type">
+<Title>
+<Text id="105"><b><i>Query type</i></b></Text>
+</Title>
+<Content>
+<Text id="106">There are two different kinds of query.</Text>
+<BulletList>
+<Bullet>
+<Text id="107">Queries for all the words. These look for documents (or chapters, or titles) that contain all the words you have specified. Documents that satisfy the query are displayed.</Text>
+</Bullet>
+<Bullet>
+<Text id="108">Queries for some of the words. Just list some terms that are likely to appear in the documents you are looking for. Documents are displayed in order of how closely they match the query. When determining the degree of match,</Text>
+<BulletList>
+<Bullet>
+<Text id="109">the more search terms a document contains, the closer it matches;</Text>
+</Bullet>
+<Bullet>
+<Text id="110">rare terms are more important than common ones;</Text>
+</Bullet>
+<Bullet>
+<Text id="111">short documents match better than long ones.</Text>
+</Bullet>
+</BulletList>
+</Bullet>
+</BulletList>
+</Content>
+</Part>
+<Text id="112">Use as many search terms as you likeâa whole sentence, or even a whole paragraph. If you specify only one term, it doesn't much matter whether you use an <i>all</i> or a <i>some</i> query, except that in the second case the results will be sorted by the search term's frequency of occurrence.</Text>
+</Content>
+</Subsection>
+<Subsection id="scope_of_queries">
+<Title>
+<Text id="113">Scope of queries</Text>
+</Title>
+<Content>
+<Text id="114">In most collections you can choose different indexes to search. For example, there might be author or title indexes. Or there might be chapter or paragraph indexes. Generally, the full matching document is returned regardless of which index you search.</Text>
+<Text id="115">If documents are books, they will be opened at the appropriate place.</Text>
+</Content>
+</Subsection>
+<Subsection id="advanced_search_features">
+<Title>
+<Text id="116">Advanced search features</Text>
+</Title>
+<Content>
+<Text id="117">While the above is enough to meet most searching needs, some more advanced search features are provided. These are activated from the Preferences page, which is reached by clicking the <i>preferences</i> button at the top of the pageâsee Section 2.3 below. After changing your preferences, do not click your browser's <i>Back</i> buttonâthat would undo the changes. Instead, click any of the buttons on the search/browse bar.</Text>
+<Part id="case_sensitivity_and_stemming">
+<Title>
+<Text id="118"><i><b>Case sensitivity and stemming</b></i></Text>
+</Title>
+<Content>
+<Text id="119">When you specify search terms, you can choose whether upper and lower case must match between the query and the document: this is called âcase sensitivity.â You can also choose whether to ignore word endings or not: this is called âstemming.â</Text>
+<Text id="120">Under <i>Search options</i> on the Preferences page you will see a pair of buttons labeled <i>ignore case differences</i> and <i>upper/lower case must match</i>; these control the case sensitivity of your queries. Below is a pair of buttons labeled <i>ignore word endings</i> and <i>whole word must match</i>: these control stemming.</Text>
+<Text id="121">For example, if the buttons <i>ignore case differences</i> and <i>ignore word endings</i> are selected, the query</Text>
+<Text type="code" id="122">African building</Text>
+<Text id="123">will be treated the same as</Text>
+<Text type="code" id="124">africa builds</Text>
+<Text id="125">because the uppercase letter in âAfricanâ will be transformed to lowercase, and the suffixes ânâ and âingâ will be removed from âAfricanâ and âbuildingâ respectively (also, âsâ would be removed from âbuildsâ).</Text>
+<Text id="126">Generally case differences and word endings should be ignored unless you are querying for particular names or acronyms.</Text>
+</Content>
+</Part>
+<Part id="phrase_searching">
+<Title>
+<Text id="127"><b><i>Phrase searching</i></b></Text>
+</Title>
+<Content>
+<Text id="128">If your query includes a phrase in quotation marks, only documents containing that phrase, exactly as typed, will be returned.</Text>
+<Text id="129">If you want to use phrase searching, you need to learn a little about how it works. Phrases are processed by a post-retrieval scan. First the query is issued in the normal wayâall the words in the phrase are included as search termsâand then the documents returned are scanned to eliminate those in which that phrase does not appear.</Text>
+<Text id="130">During the post-retrieval scan, phrases are checked just as they are, including any punctuation. For example, the query</Text>
+<Text type="code" id="131">what's a âpost-retrieval scan?â</Text>
+<Text id="132">will first retrieve all documents that match all of the words</Text>
+<CodeLine>what s a post retrieval scan</CodeLine>
+<Text id="133">and then the documents returned will be checked for the phrase</Text>
+<Text type="code" id="134">post-retrieval scan?</Text>
+<Text id="135">Phrase matches are case-insensitive if <i>ignore case differences</i> is set on the Preferences page.</Text>
+</Content>
+</Part>
+<Part id="advanced_query_mode">
+<Title>
+<Text id="136"><b><i>Advanced query mode</i></b></Text>
+</Title>
+<Content>
+<Text id="137">In <i>advanced query mode</i>, which can be selected on the Preferences page, the queries for <i>all</i> of the words, described above, are actually Boolean queries. They consist of a list of terms joined by logical operators &amp; (and), | (or), and ! (not). Absent operatorsbetween search terms are interpreted as &amp; (and): thus a query without any operators returns documents that match <i>all</i> the terms.</Text>
+<Text id="138">If the words AND, OR, and NOT appear in your query they are treated as ordinary search terms, not operators. For operators you must use &amp;, |, and !. In addition, parentheses can be used for grouping.</Text>
+</Content>
+</Part>
+<Part id="using_search_history">
+<Title>
+<Text id="139"><b><i>Using search history</i></b></Text>
+</Title>
+<Content>
+<Text id="140">When you switch on the âsearch historyâ feature on the Preferences page you will be shown your last few searches, along with a summary of how many results they generated. Click the button beside one of the previous searches to copy the text into the search box. This makes it easy to repeat slightly modified versions of previous queries.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="changing_the_preferences">
+<Title>
+<Text id="141">Changing the preferences</Text>
+</Title>
+<Content>
+<Figure id="the_preferences_page">
+<Title>
+<Text id="142">The Preferences page</Text>
+</Title>
+<File width="394" height="439" url="images/User_Fig_3.png"/>
+</Figure>
+<Text id="143">When you click the <i>preferences</i> button at the top of the page you will be able to change some features of the interface to suit your own requirements. The preferences depend on the collection; an example is shown in Figure 3. When you adjust your search preferences, you should press the <i>set preferences</i> button shown in Figure 3. After setting preferences, do not use your browser's âbackâ buttonâthat would unset them! Instead, click one of the buttons on the access bar near the top of the page.</Text>
+<Subsection id="collection_preferences">
+<Title>
+<Text id="144">Collection preferences</Text>
+</Title>
+<Content>
+<Text id="145">Some collections comprise several subcollections, which can be searched independently or together, as one unit. If so, you can select which subcollections to include in your searches on the Preferences page.</Text>
+</Content>
+</Subsection>
+<Subsection id="language_preferences">
+<Title>
+<Text id="146">Language preferences</Text>
+</Title>
+<Content>
+<Text id="147">Each collection has a default presentation language, but you can switch to a different language if you like. You can also alter the encoding scheme used by Greenstone for output to the browserâthe software chooses sensible defaults, but with some browsers better visual results can be used by switching to a different encoding scheme. All collections allow you to switch from the standard graphical interface format to a textual one. This is particularly useful for visually impaired users who use large screen fonts or speech synthesizers for output.</Text>
+</Content>
+</Subsection>
+<Subsection id="presentation_preferences">
+<Title>
+<Text id="148">Presentation preferences</Text>
+</Title>
+<Content>
+<Text id="149">Depending on the collection, there may be other options you can set that control the presentation. Collections of web pages allow you to suppress the Greenstone navigation bar at the top of each document page, so that once you have done a search you land at the exact web page that matches without any Greenstone header. To do another search you will have to use your browser's âbackâ button. These collections also allow you to suppress Greenstone's warning message when you click a link that takes you out of the digital library collection and on to the web itself. And in some web collections you can control whether the links on the âSearch Resultsâ page take you straight to the actual URL in question, rather than to the digital library's copy of the page.</Text>
+</Content>
+</Subsection>
+<Subsection id="search_preferences">
+<Title>
+<Text id="150">Search preferences</Text>
+</Title>
+<Content>
+<Text id="151">Under <i>Search preferences</i> in Figure 3, the first pair of buttons allows you to get a large query box, so that you can easily do paragraph-sized searching. In Greenstone, it is surprisingly quick to search for large amounts of text. The next two pairs of buttons control the kind of text matching in the searches that you make. The first set (labeled âcase differencesâ) controls whether upper and lower case must match. The second (âword endingsâ) controls whether to ignore word endings or not.</Text>
+<Text id="152">Using the next button pair you can switch to the âadvancedâ query mode described above, which allows you to specify more precise queries by combining terms using AND (&amp;), OR (|), and NOT (!). You can turn the search history feature, described above, on and off. Finally, you can control the number of hits returned, and the number presented on each screenful, through the last entry in Figure 3.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="making_greenstone_collections">
+<Title>
+<Text id="153">Making Greenstone Collections</Text>
+</Title>
+<Content>
+<Text id="154">The simplest way to build new collections is to use Greenstone's âlibrarianâ interface (GLI). This allows you to collect sets of documents, import or assign metadata, and build them into a Greenstone collection. It supports five basic activities, which can be interleaved but are nominally undertaken in this order:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="155">Copy documents from the computer's file space, including existing collections, into the new collection. Any existing metadata remains âattachedâ to these documents. Documents may also be gathered from the web through a built-in mirroring facility.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="156">Enrich the documents by adding further metadata to individual documents or groups of documents.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="157">Design the collection by determining its appearance and the access facilities that it will support.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="158">Build the collection using Greenstone.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="159">Preview the newly created collection, which will have been installed on your Greenstone home page as one of the regular collections.</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="160">The librarian interface allows you to add what people call âexternalâ metadata to documents, metadata that pertains to the document as a whole. But documents often need to be structured into sections and subsections, and âinternalâ metadata might be associated with each part. In Greenstone, source documents can be tagged with this information, and we explain this in Section 3.3.</Text>
+<Text id="161">Finally, an alternative way of building collections is provided by the Collector, which helps you create new collections, modify or add to existing ones, or delete collections. It predates the librarian interface, and for most practical purposes the librarian interface should be used instead of the Collector. It is described in Section 3.4.</Text>
+<Text id="162">To harness the full power of Greenstone to build advanced collections, you will also need to read Chapter 2 of the <i>Developer's Guide</i>.</Text>
+<Section id="the_librarian_interface">
+<Title>
+<Text id="163">The librarian's interface</Text>
+</Title>
+<Content>
+<Text id="164">To convey the operation of Greenstone's librarian interface, we work through a simple example. Figures 4 to 15 are screen snapshots at various points during the interaction. This example uses documents in the Development Library Subset (DLS) collection, which is distributed with Greenstone. For expository purposes, the walkthrough takes the form of a single pass through the steps listed above. A more realistic pattern of use, however, is for users to switch back and forth through the various stages as the task proceeds.</Text>
+<Text id="165">The librarian interface can be run in one of four modes: Librarian Assistant, Librarian, Library Systems Specialist, and Expert. Modes control the level of detail within the interface, and can be changed through 'Preferences' in the 'File' menu. The walkthrough in this section assumes that the librarian interface is operating in the default mode, Librarian.</Text>
+<Subsection id="getting_started">
+<Title>
+<Text id="166">Getting started</Text>
+</Title>
+<Content>
+<Text id="167">Launch the librarian interface under Windows by selecting <i>Greenstone Digital Library</i> from the <i>Programs</i> section of the <i>Start</i> menu and choosing <i>Librarian Interface</i>. If you are using Unix, instead type</Text>
+<CodeLine>cd ~/gsdl</CodeLine>
+<CodeLine>cd gli</CodeLine>
+<CodeLine>./gli.sh</CodeLine>
+<Text id="168">where <i>~/gsdl</i> is the directory containing your Greenstone system. To begin, you must either open an existing collection or start a new one. Figure 4 shows the user in the process of starting a new collection. She has selected <i>New</i> from the file menu and begun to fill out general information about the collectionâits title, the E-mail address of the person responsible for it, and a brief description of the contentâin the popup window. The collection title is a short phrase used throughout the digital library to identify the collection's content: existing collections have names like <i>Food and Nutrition Library</i>, <i>World Environmental Library</i>, and so on. When you type the title, the system assigns a unique mnemonic identifier, the collection ânameâ, for internal use (you can change it if you like). The E-mail address specifies the first point of contact for any problems encountered with the collection.</Text>
+<Text id="169">The brief description is a statement describing the principles that govern what is included in the collection. It appears under the heading <i>About this collection</i> on the collection's initial page.</Text>
+<Figure id="starting_a_new_collection">
+<Title>
+<Text id="170">Starting a new collection</Text>
+</Title>
+<File width="407" height="317" url="images/User_Fig_4.png"/>
+</Figure>
+<Figure id="exploring_the_local_file_space">
+<Title>
+<Text id="171">Exploring the local file space</Text>
+</Title>
+<File width="407" height="318" url="images/User_Fig_5.png"/>
+</Figure>
+<Text id="172">At this point, the user decides whether to base the new collection on the same structure as an existing collection, or to build an entirely new kind of collection. In Figure 4 she has chosen to base it on the <i>Development Library Subset</i> collection. This implies that the âDLSâ metadata set which is used in this collection will be used for the new collection. (In fact, this metadata set has been used to build several Greenstone collections that share a common structure and organization but with different content, including the <i>Development Library Subset</i> and <i>Demo</i> collections delivered as samples with Greenstone.)</Text>
+<Text id="173">The DLS metadata set contains these items:</Text>
+<BulletList>
+<Bullet>
+<Text id="174">Title</Text>
+</Bullet>
+<Bullet>
+<Text id="175">Subject</Text>
+</Bullet>
+<Bullet>
+<Text id="176">Language</Text>
+</Bullet>
+<Bullet>
+<Text id="177">Organization</Text>
+</Bullet>
+<Bullet>
+<Text id="178">Keyword (i.e.âHowtoâ).</Text>
+</Bullet>
+</BulletList>
+<Text id="179">(There is, in addition, a metadata item called <i>AZList</i> which is used to determine which bucket of the alphabetic list contains the document's title, with values like âA-Bâ or âC-D-Eâ. This is used to give precise control over thedivisions in the list. For most other collections it is absent, and Greenstone assigns the buckets itself.)</Text>
+<Text id="180">If, instead, the user had chosen âNew Collectionâ at this point, she would have been asked to select what metadata sets should be used in the new collection. Three standard sets are pre-supplied: Dublin Core, the DLS metadata set mentioned above, and a set that comprises metadata elements extracted automatically by Greenstone from the documents in the collection. The user can also create new metadata sets using a popup panel activated through the âmetadataâ menu.</Text>
+<Text id="181">Several different metadata sets can be associated with the same collection; the system keeps them distinct (so that, for example, documents can have both a Dublin Core <i>Title</i> and a DLS <i>Title</i>). The different sets are clearly distinguished in the interface. Behind the scenes, metadata sets are represented in XML.</Text>
+</Content>
+</Subsection>
+<Subsection id="assembling_the_source_material">
+<Title>
+<Text id="182">Assembling the source material</Text>
+</Title>
+<Content>
+<Text id="183">After clicking the <i>OK</i> button on the ânew collectionâ popup, the remaining parts of the interface, which were grayed out before, become active. The <i>Gather</i> panel, selected by the eponymous tab near the top of Figure 4, is displayed initially. This allows the user to explore the local file space and existing collections, gathering up selected documents for the new collection. The panel is divided into two sections, the left for browsing existing structures and the right for the documents in the collection.</Text>
+<Text id="184">Operations available at this stage include:</Text>
+<BulletList>
+<Bullet>
+<Text id="185">Navigating the existing file structure hierarchy, and the one being created, in the usual way.</Text>
+</Bullet>
+<Bullet>
+<Text id="186">Dragging and dropping files into the new collection.</Text>
+</Bullet>
+<Bullet>
+<Text id="187">Multiple selection of files.</Text>
+</Bullet>
+<Bullet>
+<Text id="188">Dragging and dropping entire sub-hierarchies.</Text>
+</Bullet>
+<Bullet>
+<Text id="189">Deleting documents from the nascent collection.</Text>
+</Bullet>
+<Bullet>
+<Text id="190">Creating new sub-hierarchies within the collection.</Text>
+</Bullet>
+<Bullet>
+<Text id="191">Filtering the files that are visible, in both the local file system and the collection, based on predetermined groups or on standard file matching terms.</Text>
+</Bullet>
+<Bullet>
+<Text id="192">Invoking the appropriate program to display the contents of a selected file, by double-clicking it.</Text>
+</Bullet>
+</BulletList>
+<Text id="193">Care is taken to deal appropriately with name clashes when files of the same name in different parts of the computer's directory structure are copied into the same folder of the collection.</Text>
+<Text id="194">In Figure 5 the user is using the interactive file tree display to explore the local file system. At this stage, the collection on the right is empty; the user populates it by dragging and dropping files of interest from the left to the right panel. Such files are âcopiedâ rather than âmovedâ: so as not to disturb the original file system. The usual techniques for multiple selection, dragging and dropping, structuring the new collection by creating subdirectories (âfoldersâ), and deleting files from it by moving them to a trashcan, are all available.</Text>
+<Text id="195">Existing collections are represented by a subdirectory on the left called âGreenstone Collections,â which can be opened and explored like any other directory. However, the documents therein differ from ordinary files because they already have metadata attached, and this is preserved when they are moved into the new collection. Conflicts may arise because their metadata may have been assigned using a different metadata set from the one in use for the new collection, and the user must resolve these. In Figure 6 the user has selected some documents from an existing collection and dragged them into the new one. The popup window explains that the metadata element <i>Organization</i> cannot be automatically imported, and asks the user to either select a metadata set and press <i>Add</i> to add the metadata element to that set,<FootnoteRef id="1"/>or choose a metadata set, then an element, and press <i>Merge</i> to effectively rename the old metadata element to the new one by merging the two. Metadata in subsequent documents from the same collection will automatically be handled in the same way.</Text>
+<Text id="196">When large file sets are selected, dragged, and dropped into the new collection, the copying operation may take some timeâparticularly if metadata conversion is involved. To indicate progress, the interface shows which file is being copied and what percentage of files has been processed.</Text>
+<Text id="197">Special facilities are provided for dealing with large file sets. For example, the user can choose to filter the file tree to show only certain files, using a dropdown menu of file types displayed underneath the trees. In Figure 7, only the HTM and HTML files are being shown (and only these files will be copied by drag and drop).</Text>
+</Content>
+</Subsection>
+<Subsection id="enriching_the_documents">
+<Title>
+<Text id="198">Enriching the documents</Text>
+</Title>
+<Content>
+<Text id="199">The next phase in collection building is to enrich the documents by adding metadata. The <i>Enrich</i> tab brings up a new panel of information (Figure 8), which shows the document tree representing the collection on the left and on the right allows metadata to be added to individual documents, or groups of documents.</Text>
+<Text id="200">Documents that are copied during the first step come with any applicable metadata attached. If a document is part of a Greenstone collection, previously defined metadata is carried over to the new collection. Of course, this new collection may have a different metadata set, or perhaps just a subset of the defined metadata, and only metadata that pertains to the new collection's set is carried over. Resolution of such conflicts may require user intervention via a supplementary dialog (Figure 6). Any choices made are remembered for subsequent file copies.</Text>
+<Text id="201">The <i>Enrich</i> panel allows metadata values to be assigned to documents in the collection. For example, new values can be added to the set of existing values for an element. If the element's values have a hierarchical structure, the hierarchy can be extended in the same way.</Text>
+<Figure id="importing_existing_metadata">
+<Title>
+<Text id="202">Importing existing metadata</Text>
+</Title>
+<File width="407" height="317" url="images/User_Fig_6.png"/>
+</Figure>
+<Figure id="filtering_the_file_trees">
+<Title>
+<Text id="203">Filtering the file trees</Text>
+</Title>
+<File width="407" height="318" url="images/User_Fig_7.png"/>
+</Figure>
+<Figure id="assigning_metadata_using_enrich_view">
+<Title>
+<Text id="204">Assigning metadata using <i>Enrich</i> view</Text>
+</Title>
+<File width="407" height="318" url="images/User_Fig_8.png"/>
+</Figure>
+<Figure id="viewing_all_metadata_for_selected_files">
+<Title>
+<Text id="205">Viewing all metadata for selected files</Text>
+</Title>
+<File width="407" height="317" url="images/User_Fig_9.png"/>
+</Figure>
+<Text id="206">Metadata values can also be assigned to folders, in just the same way. Documents in these folders for which this metadata is unspecified inherit the metadata values. However, they can subsequently be overridden by supplying different ones for the document itself.</Text>
+<Text id="207">Operations at this stage include:</Text>
+<BulletList>
+<Bullet>
+<Text id="208">Assigning new and existing metadata values to documents.</Text>
+</Bullet>
+<Bullet>
+<Text id="209">Assigning metadata to an individual document.</Text>
+</Bullet>
+<Bullet>
+<Text id="210">Assigning metadata to a folder (this is inherited by all documentsin the folder, including those in nested folders).</Text>
+</Bullet>
+<Bullet>
+<Text id="211">Assigning hierarchical metadata, whose structure can be dynamically updated if required.</Text>
+</Bullet>
+<Bullet>
+<Text id="212">Editing or updating assigned metadata.</Text>
+</Bullet>
+<Bullet>
+<Text id="213">Reviewing the metadata assigned to a selection of files and directories.</Text>
+</Bullet>
+</BulletList>
+<Text id="214">For our walkthrough example, in Figure 8 the user has selected the folder <i>ec121e</i> and assigned âEC Courierâ as its <i>Organization</i> metadata. The buttons for updating and removing metadata become active depending on what selections have been made.</Text>
+<Text id="215">During the enrichment phase, or indeed at any other time, the user can choose to view all the metadata that has been assigned to documents in the collection. This is done by selecting a set of documents and choosing <i>Assigned Metadata</i> from the metadata sets menu, which brings up a popup window like that in Figure 9 that shows the metadata in spreadsheet form. For large collections it is useful to be able to view the metadata associated with certain document types only, and if the user has specified a file filter as mentioned above, only the selected documents are shown in the metadata display.</Text>
+<Text id="216">The panel in Figure 10 allows the user to edit metadata sets. Here, the user is looking at the <i>Subject</i> element of the DLS set. The values of this element form a hierarchy, and the user is examining, and perhaps changing, the list of values assigned to it. The same panel also allows you to change the âprofileâ for mapping elements of one metadata set to another. This profile is created when importing documents from collections that have pre-assigned metadata.</Text>
+<Figure id="editing_the_metadata_set">
+<Title>
+<Text id="217">Editing the metadata set</Text>
+</Title>
+<File width="407" height="317" url="images/User_Fig_10.png"/>
+</Figure>
+<Figure id="designing_the_collection">
+<Title>
+<Text id="218">Designing the collection</Text>
+</Title>
+<File width="407" height="318" url="images/User_Fig_11.png"/>
+</Figure>
+<Figure id="specifying_which_plug-ins_to_use">
+<Title>
+<Text id="219">Specifying which plug-ins to use</Text>
+</Title>
+<File width="407" height="318" url="images/User_Fig_12.png"/>
+</Figure>
+<Figure id="configuring_arguments_to_a_plug-in">
+<Title>
+<Text id="220">Configuring arguments to a plug-in</Text>
+</Title>
+<File width="407" height="317" url="images/User_Fig_13.png"/>
+</Figure>
+</Content>
+</Subsection>
+<Subsection id="designing_the_collection_1">
+<Title>
+<Text id="221">Designing the collection</Text>
+</Title>
+<Content>
+<Text id="222">The <i>Design</i> panel (Figures 11â13) allows one to specify the structure, organization, and presentation of the collection being created. As noted earlier, the result of this process is recorded in a âcollection configuration file,â which is Greenstone's way of expressing the facilities that a collection requires. This step involves a series of separate interaction screens, each dealing with one aspect of the collection design. In effect, it serves as a graphical equivalent to the usual process of editing the configuration file manually.</Text>
+<Text id="223">Operations include:</Text>
+<BulletList>
+<Bullet>
+<Text id="224">Reviewing and editing collection-level metadata such as title, author and public availability of the collection.</Text>
+</Bullet>
+<Bullet>
+<Text id="225">Defining what full-text indexes are to be built.</Text>
+</Bullet>
+<Bullet>
+<Text id="226">Creating sub-collections and having indexes built for them.</Text>
+</Bullet>
+<Bullet>
+<Text id="227">Adding or removing support for predefined interface languages.</Text>
+</Bullet>
+<Bullet>
+<Text id="228">Constructing a list of plug-ins to be used, and their arguments.</Text>
+</Bullet>
+<Bullet>
+<Text id="229">Presenting the list to the user for review and modification.</Text>
+</Bullet>
+<Bullet>
+<Text id="230">Configuring individual plug-ins.</Text>
+</Bullet>
+<Bullet>
+<Text id="231">Constructing a list of âclassifiers,â their arguments, assignment and configuration.</Text>
+</Bullet>
+<Bullet>
+<Text id="232">Assigning formatting strings to various controls within the collection, thus altering its appearance.</Text>
+</Bullet>
+<Bullet>
+<Text id="233">Reviewing the metadata sets, and their elements, used in the collection.</Text>
+</Bullet>
+</BulletList>
+<Text id="234">In Figure 11 the user has clicked the <i>Design</i> tab and is reviewing the general information about the collection, entered when the new collection was created. On the left are listed the various facets that the user can configure: General, Document Plug-ins, Search Types, Search Indexes, Partition Indexes, Cross-Collection Search, Browsing Classifiers, Format Features, Translate Text, Metadata Sets. Appearance and functionality varies between these. For example, clicking the <i>Plug-in</i> button brings up the screen shown in Figure 12, which allows you to add, remove or configure plug-ins, and change the order in which the plug-ins are applied to documents.</Text>
+<Text id="235">Plug-ins and classifiers have many different arguments or âoptionsâ that the user can supply. The dialog box in Figure 13 shows the user specifying arguments to some of the plug-ins. The grayed-out fields become active when the user adds the option by clicking the tick-box beside it. Because Greenstone is a continually growing open-source system, the number of options tends to increase as developers add new facilities. To help cope with this, Greenstone has a âplug-in informationâ utility program that lists the options available for each plug-in, and the librarian interface automatically invokes this to determine what options to show. This allows the interactive user interface to automatically keep pace with developments in the software.</Text>
+<Figure id="getting_ready_to_create_new_collection">
+<Title>
+<Text id="236">Getting ready to create new collection</Text>
+</Title>
+<File width="407" height="318" url="images/User_Fig_14.png"/>
+</Figure>
+<Figure id="previewing_the_newly_built_collection">
+<Title>
+<Text id="237">Previewing the newly built collection</Text>
+</Title>
+<File width="407" height="291" url="images/User_Fig_15.png"/>
+</Figure>
+</Content>
+</Subsection>
+<Subsection id="building_the_collection">
+<Title>
+<Text id="238">Building the collection</Text>
+</Title>
+<Content>
+<Text id="239">The <i>Create</i> panel (Figure 14) is used to construct a collection based on the documents and assigned metadata. The brunt of this work is borne by the Greenstone code itself. The user controls this external process through a series of separate interaction screens, each dealing with the arguments provided to a certain stage of the creation process.</Text>
+<Text id="240">The user observes the building process though a window that shows not only the text output generated by Greenstone's importing and index-building scripts, but also progress bars that indicate the overall degree of completion of each script.</Text>
+<Text id="241">Figure 14 shows the <i>Create</i> view. At the top are shown some options that can be applied during the creation process. The user selects appropriate values for the options. This figure illustrates a popup âtool tipâ that is available throughout the interface to explain the function of each argument.</Text>
+<Text id="242">When satisfied with the arguments, the user clicks <i>Build Collection</i>. Greenstone continually prints text that indicates progress, and this is shown along with a more informative progress bar.</Text>
+</Content>
+</Subsection>
+<Subsection id="previewing">
+<Title>
+<Text id="243">Previewing</Text>
+</Title>
+<Content>
+<Text id="244">The <i>Preview Collection</i> button (Figure 14) is used to view the collection that has been built. Clicking this button launches a web browser showing the home page of the collection (Figure 15). In practice, previewing often shows up deficiencies in the collection design, or in the individual metadata values, and the user frequently returns to earlier stages to correct these. This button becomes active once the collection has been created. The newly created collection will also have been installed on your Greenstone home page as one of the regular collections.</Text>
+</Content>
+</Subsection>
+<Subsection id="help">
+<Title>
+<Text id="245">Help</Text>
+</Title>
+<Content>
+<Text id="246">On-line help is always available, and is invoked using the <i>Help</i> item at the right of the main menu bar at the top of each of the Figures. This opens up a hierarchically structured file of help text, and account is taken of the user's current context to highlight the section that is appropriate to the present stage of the interaction. Furthermore, as noted above, whenever the mouse is held still over any interactive object a small window pops up to give a textual âtool tip,â as illustrated near the bottom of Figure 14.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="librarian_interface_user_guide">
+<Title>
+<Text id="247">Librarian Interface user guide</Text>
+</Title>
+<Content>
+<Subsection id="starting_off">
+<Title>
+<Text id="248">Starting Off</Text>
+</Title>
+<Content>
+<Text id="249">This section covers how to create, load, save and delete collections.</Text>
+<Part id="creating_a_new_collection">
+<Title>
+<Text id="250">Creating a New Collection</Text>
+</Title>
+<Content>
+<Text id="251">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 design view.</Text>
+<Text id="252">"Collection title" is the text displayed at the top of your collection's home page. It can be any length.</Text>
+<Text id="253">"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="254">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".</Text>
+<Text id="255">Click "OK" to create the collection. If you chose "New Collection" you are prompted for the metadata sets to use in it. You can choose more than one, and you can add others later.</Text>
+<Text id="256">Clicking "Cancel" returns you to the main screen immediately.</Text>
+</Content>
+</Part>
+<Part id="saving_the_collection">
+<Title>
+<Text id="257">Saving the Collection</Text>
+</Title>
+<Content>
+<Text id="258">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 Producing Your Collection).</Text>
+<Text id="259">The Librarian Interface protects your work by saving it whenever you exit the program or load another collection.</Text>
+<Text id="260">Saved collections are written to a file named for the collection and with file extension ".col", located in a folder of the same name within your Greenstone installation's "collect" folder.</Text>
+</Content>
+</Part>
+<Part id="opening_an_existing_collection">
+<Title>
+<Text id="261">Opening an Existing Collection</Text>
+</Title>
+<Content>
+<Text id="262">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="263">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. You can tell whether a collection is locked by the colour of its icon: green for a normal collection, red for a locked one. 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. Never steal a collection that someone else is currently working on.</Text>
+<Text id="264">When you open a collection that the Greenstone Librarian Interface did not create, you will be asked to select a metadata set (or sets). If none are selected, any existing metadata will be ignored. Otherwise, metadata will be imported just as it is when you drag in files with existing metadata. The process is described in the Importing Previously Assigned Metadata section.</Text>
+</Content>
+</Part>
+<Part id="deleting_collections">
+<Title>
+<Text id="265">Deleting Collections</Text>
+</Title>
+<Content>
+<Text id="266">To permanently delete collections from your Greenstone installation, choose "Delete..." from the "File" menu. A list of your Greenstone collections appears. Select one to see its description, then tick the box at the bottom of the dialog and click "Delete" to delete the collection. This action is irreversible, so check carefully that you no longer need the collection before proceeding!</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="downloading_files_from_the_internet">
+<Title>
+<Text id="267">Downloading Files From the Internet</Text>
+</Title>
+<Content>
+<Text id="268">The "Download" view helps you download resources from the internet. This section explains the Librarian Interface's mirroring process.</Text>
+<Part id="the_download_view">
+<Title>
+<Text id="269">The Download view</Text>
+</Title>
+<Content>
+<Text id="270">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 downloading jobs.</Text>
+<Text id="271">Files are downloaded into a folder in the workspace called "Downloaded Files" (only present when mirroring is enabled), and can be used in all collections built with the Librarian Interface. Files in this area are named by their full web URL. 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="272">Use the first of the download configuration controls, "Source URL", to enter the URL of a target resource. Use the "Download Depth" control to limit how many hyperlinks to follow when downloading: Set this to 0 to download a single web page; set it to 1 to download a page and all the pages it points to. The depth limit is ignored when downloading media other than html pages. Next, there are several checkbox controls which can be set to turn on the specified feature for a specific download. Once the configuration is set up, click "Download" to start the new download job. There are two other button controls: "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.</Text>
+<Text id="273">The download list has an entry for each web page download. 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 for pausing a currently downloading task. "View Log" opens a window showing the download log file. "Close" terminates the download and removes the task from the list.</Text>
+<Text id="274">The Preferences section describes how to establish an Internet connection via a proxy. If authentication is needed, the proxy server prompts for identification and password. The Librarian Interface does not store passwords between sessions.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="collecting_files_for_your_collection">
+<Title>
+<Text id="275">Collecting Files for Your Collection</Text>
+</Title>
+<Content>
+<Text id="276">Once you have a new collection you need to get some files into it. These may come from your ordinary file space, or from other Greenstone collections. Some may already have attached metadata. This section describes how to import files.</Text>
+<Part id="the_gather_view">
+<Title>
+<Text id="277">The Gather View</Text>
+</Title>
+<Content>
+<Text id="278">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.</Text>
+<Text id="279">The two large areas titled "Workspace" and "Collection" are used to move files into your collection. They contain "file trees", graphical structures that represent files and folders.</Text>
+<Text id="280">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 to open it using its associated application program (see File Associations).</Text>
+<Text id="281">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="282">The Collection file tree represents the contents of the collection so far. Initially, it is empty.</Text>
+<Text id="283">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="284">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="285">Two large buttons occupy the lower right corner of the screen. "New Folder", with a picture of a folder, creates new folders (see Creating folders). "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="286">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>
+<Text id="287">Certain folders -- such as the one containing your own web pages -- sometimes have special significance. The Librarian Interface can map such folders to the first 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>
+</Content>
+</Part>
+<Part id="creating_folders">
+<Title>
+<Text id="288">Creating Folders</Text>
+</Title>
+<Content>
+<Text id="289">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="290">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="291">Folders can also be created by right-clicking over a folder, choosing "New Folder" and proceeding as above.</Text>
+</Content>
+</Part>
+<Part id="adding_files">
+<Title>
+<Text id="292">Adding Files</Text>
+</Title>
+<Content>
+<Text id="293">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="294">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="295">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="296">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 Importing Previously Assigned Metadata 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>
+</Content>
+</Part>
+<Part id="removing_files">
+<Title>
+<Text id="297">Removing Files</Text>
+</Title>
+<Content>
+<Text id="298">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 The Gather View.</Text>
+<Text id="299">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>
+</Content>
+</Part>
+<Part id="filtering_the_tree">
+<Title>
+<Text id="300">Filtering the Tree</Text>
+</Title>
+<Content>
+<Text id="301">"Filtering" the collection tree allows you to narrow down the search for particular files.</Text>
+<Text id="302">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="303">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 "*.*" or "*.doc" ("*" matches any characters).</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="enriching_the_collection_with_metadata">
+<Title>
+<Text id="304">Enriching the Collection with Metadata</Text>
+</Title>
+<Content>
+<Text id="305">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>
+<Part id="the_enrich_view">
+<Title>
+<Text id="306">The Enrich View</Text>
+</Title>
+<Content>
+<Text id="307">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).</Text>
+<Text id="308">On the left of the "Enrich" view is the Collection Tree. 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 are selected, black text indicates that the value is common to all of the selected files, while grey text indicates that it is not. Black values may be updated or removed, while grey ones can be removed from those that have it, or appended to the others.</Text>
+<Text id="309">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="310">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. The 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="311">Metadata values can be organised 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="312">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>
+</Content>
+</Part>
+<Part id="selecting_metadata_sets">
+<Title>
+<Text id="313">Selecting Metadata Sets</Text>
+</Title>
+<Content>
+<Text id="314">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="315">To control the metadata sets used in a collection, use the "Metadata Sets" entry on the Design view.</Text>
+</Content>
+</Part>
+<Part id="appending_new_metadata">
+<Title>
+<Text id="316">Appending New Metadata</Text>
+</Title>
+<Content>
+<Text id="317">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="318">Next select the metadata element you want to add by clicking its row in the table.</Text>
+<Text id="319">Type the value into the value field. Use the "|" character to add structure, as described in The Enrich View. 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="320">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>
+</Content>
+</Part>
+<Part id="adding_previously_defined_metadata">
+<Title>
+<Text id="321">Adding Previously Defined Metadata</Text>
+</Title>
+<Content>
+<Text id="322">To add metadata that has an existing value, first select the file, then select the required value from the value tree, expanding hierarchy folders as necessary. The value of the selected entry automatically appears in the Value field (alternatively, use the value tree's auto-select and auto-complete features).</Text>
+<Text id="323">The process of adding metadata with already-existing values to folders or multiple files is just the same.</Text>
+</Content>
+</Part>
+<Part id="editing_or_removing_metadata">
+<Title>
+<Text id="324">Editing or Removing Metadata</Text>
+</Title>
+<Content>
+<Text id="325">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="326">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="327">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 the values which are no longer assigned.</Text>
+</Content>
+</Part>
+<Part id="reviewing_assigned_metadata">
+<Title>
+<Text id="328">Reviewing Assigned Metadata</Text>
+</Title>
+<Content>
+<Text id="329">Sometimes you need to see the metadata assigned to many or all 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="330">Select the files 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="331">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="332">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="333">The 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="334">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>
+</Content>
+</Part>
+<Part id="importing_previously_assigned_metadata">
+<Title>
+<Text id="335">Importing Previously Assigned Metadata</Text>
+</Title>
+<Content>
+<Text id="336">This section describes how to import previously assigned metadata: metadata assigned to documents before they were added to the collection.</Text>
+<Text id="337">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="338">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="339">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="340">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>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="designing_your_collection_appearance">
+<Title>
+<Text id="341">Designing Your Collection's Appearance</Text>
+</Title>
+<Content>
+<Text id="342">Once your files are marked up with metadata, you next decide how it should appear to users as a Greenstone collection. What kind of information is searchable? What ways are provided to browse through the documents? What languages are supported? Where do the buttons appear on the page? These things can be customized; this section describes how to do it.</Text>
+<Part id="the_design_view">
+<Title>
+<Text id="343">The Design View</Text>
+</Title>
+<Content>
+<Text id="344">This section introduces you to the design view and explains how to navigate between the various views within this pane.</Text>
+<Text id="345">With the Librarian Interface, you can configure how the collection appears to the user. The configuration options are divided into different sections, each associated with a particular stage of navigating or presenting information.</Text>
+<Text id="346">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="347">To understand the stages and terms involved in designing a collection, first read Chapters 1 and 2 of the Greenstone Developer's Guide.</Text>
+</Content>
+</Part>
+<Part id="general">
+<Title>
+<Text id="348">General</Text>
+</Title>
+<Content>
+<Text id="349">This section explains how to review and alter the general settings associated with your collection. First, under "Design Sections", click "General".</Text>
+<Text id="350">Here the values provided during collection creation can be modified.</Text>
+<Text id="351">First are the contact emails 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 edited. The next one specifies (in the form of a URL) the icon to show at the top left of the collection's "About" page, and the next is the icon used in the Greenstone library page to link to the collection. Then, a checkbox controls whether the collection should be publicly accessible. Finally comes the "Collection Description" text area as described in Creating A New Collection.</Text>
+</Content>
+</Part>
+<Part id="document_plugins">
+<Title>
+<Text id="352">Document Plugins</Text>
+</Title>
+<Content>
+<Text id="353">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 "Design Sections", click "Document Plugins".</Text>
+<Text id="354">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 "Currently Assigned Plugins" list. Note that, except for UnknownPlug, each plugin may only occur once in the list.</Text>
+<Text id="355">To remove a plugin, select it in the list and click "Remove Plugin".</Text>
+<Text id="356">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="357">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="358">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="359">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 Preferences).</Text>
+</Content>
+</Part>
+<Part id="search_types">
+<Title>
+<Text id="360">Search Types</Text>
+</Title>
+<Content>
+<Text id="361">This section explains how to modify a new design feature in Greenstone, Search Types, which allow fielded searching. The search types specify what kind of search interface should be provided: form, for fielded searching, and/or plain for regular searching. Under "Design Sections", click "Search Types".</Text>
+<Text id="362">When you enter the Search Types view, first check "Enable Advanced Searches", which activates the other controls. This changes the collection to use an indexing mechanism that allows fielded searching. Index specification is slightly different in this mode. (When switching between standard and advanced searching, the GLI does its best to convert the index specification, but may not get it completely right.)</Text>
+<Text id="363">To add a search type, select it from the "Search Types" list and click "Add Search Type". Each type can only appear in the list once. The first search type will be the default, and will appear on the search page of the built collection. Any others will be selectable from the preferences page.</Text>
+<Text id="364">To remove a search type, select it from the "Currently Assigned Search Types" list and click "Remove Search Type". The list must contain at least one search type.</Text>
+</Content>
+</Part>
+<Part id="search_indexes">
+<Title>
+<Text id="365">Search Indexes</Text>
+</Title>
+<Content>
+<Text id="366">Indexes specify what parts of the collection are searchable. This section explains how to add and remove indexes, and set a default index. Under "Design Sections", click "Search Indexes".</Text>
+<Text id="367">To add an index, type a name for it into the "Index Name" field. Select which of the possible information sources to index by clicking the checkboxes beside them. The list shows all the assigned metadata elements, as well the full text. Having selected the data sources, choose the granularity of the index, using the "At the level" menu. Once these details are complete, "Add Index" becomes active (unless there is an existing index with the same settings). Click it to add the new index.</Text>
+<Text id="368">To edit an index, select it and change the index details, then click "Replace Index".</Text>
+<Text id="369">To remove an index, select it from the list of assigned indexes and click "Remove Index".</Text>
+<Text id="370">To create an index covering text and all metadata, click "Add All".</Text>
+<Text id="371">The default index, the one used on the collection's search page, is tagged with "[Default Index]" in the "Assigned Indexes" list. To set it, select an index from the list and click "Set Default".</Text>
+<Text id="372">If advanced searching is enabled (via the Search Types view), the index controls are different. There is a new pseudo-data source "allfields" which provides searching across all specified indexes at once. Levels are not assigned to a specific index, but apply across all indexes: thus indexes and levels are added separately. "Add All" creates a separate index for each metadata field in this mode.</Text>
+<Text id="373">The name of each index will default to the source name. To change the name, select an index, change its details, and click "Replace Index".</Text>
+</Content>
+</Part>
+<Part id="partition_indexes">
+<Title>
+<Text id="374">Partition Indexes</Text>
+</Title>
+<Content>
+<Text id="375">Indexes are built on particular text or metadata sources. The search space can be further controlled by partitioning the index, either by language or by a predetermined filter. This section describes how to do this. Under "Design Sections", click "Partition Indexes".</Text>
+<Text id="376">The "Partition Indexes" view has three tabs; "Define Filters", "Assign Partitions" and "Assign Languages". To learn more about partitions read about subcollections and subindexes in Chapter 2 of the Greenstone Developer's Guide.</Text>
+<Text id="377">The Partition Indexes screen is only enables in Library Systems Specialist and Expert modes (see Preferences). Note that the total number of partitions generated is a combination of all indexes, subcollection filters and languages chosen. Two indexes with two subcollection filters in two languages would yield eight index partitions.</Text>
+</Content>
+</Part>
+<Part id="define_filters">
+<Title>
+<Text id="378">Define Filters</Text>
+</Title>
+<Content>
+<Text id="379">Filters allow you to group together into a subcollection all documents in an index for which a metadata value matches a given pattern.</Text>
+<Text id="380">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="381">To remove a filter, select it from the list and click "Remove Filter".</Text>
+<Text id="382">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>
+</Content>
+</Part>
+<Part id="assign_partitions">
+<Title>
+<Text id="383">Assign Partitions</Text>
+</Title>
+<Content>
+<Text id="384">Having defined a subcollection filter, 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, enter a name for your partition in the "Partition Name" field, and click "Add Partition".</Text>
+<Text id="385">To remove a partition, select it from the list and click "Remove Partition".</Text>
+<Text id="386">To make a partition the default one, select it from the list and click "Set Default".</Text>
+</Content>
+</Part>
+<Part id="assign_languages">
+<Title>
+<Text id="387">Assign Languages</Text>
+</Title>
+<Content>
+<Text id="388">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="389">To add a new language to partition by, use the "Assign Languages" tab to build an index for it. Select the desired language from the "Language to add" pull-down list and click "Add Language".</Text>
+<Text id="390">To remove a language, select it from the "Language Selection" list and click "Remove Language".</Text>
+<Text id="391">To set the default language, select it from the list and click "Set Default".</Text>
+</Content>
+</Part>
+<Part id="cross-collection_search">
+<Title>
+<Text id="392">Cross-Collection Search</Text>
+</Title>
+<Content>
+<Text id="393">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 "Design Sections", click "Cross-Collection Search".</Text>
+<Text id="394">The Cross-Collection Search view shows a checklist of available collections. The current collection is ticked and cannot be deselected. 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="395">If the individual collections do not have the same indexes (including subcollection 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="396">For further details, see Chapter 1 of the Greenstone Developer's Guide.</Text>
+</Content>
+</Part>
+<Part id="browsing_classifiers">
+<Title>
+<Text id="397">Browsing Classifiers</Text>
+</Title>
+<Content>
+<Text id="398">This section explains how to assign "classifiers", which are used for browsing, to the collection. Under "Design Sections", click "Browsing Classifiers".</Text>
+<Text id="399">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 Document Plugins). Once you have configured the new classifier, it is added to the end of the "Currently Assigned Classifiers" list.</Text>
+<Text id="400">To remove a classifier, select it from the list and click "Remove Classifier".</Text>
+<Text id="401">To change the arguments a classifier, select it from the list and click "Configure Classifier" (or double-click on the classifier in the list).</Text>
+<Text id="402">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="403">For further information on classifiers read Chapter 2, Greenstone Developer's Guide -- Getting the most out of your documents.</Text>
+</Content>
+</Part>
+<Part id="format_features">
+<Title>
+<Text id="404">Format Features</Text>
+</Title>
+<Content>
+<Text id="405">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 where 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 "Design Sections", click "Format Features".</Text>
+<Text id="406">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 the current position in the format string, select it from the pull-down list and click "Insert".</Text>
+<Text id="407">You can specify a default format for a particular component by selecting the blank feature. This format is then applied to all applicable features unless otherwise specified.</Text>
+<Text id="408">To add a new format command, fill out the information as explained above and click "Add Format". The new format command appears in the list of "Currently Assigned Format Commands". Only one format command can be assigned to each feature/component combination.</Text>
+<Text id="409">To remove a format command, select it from the list and click "Remove Format".</Text>
+<Text id="410">To change a format command, select it from the list, modify the settings, and click "Replace Format".</Text>
+<Text id="411">For more information about variables and the feature components, read Chapter 2 of the Greenstone Developer's Guide.</Text>
+<Text id="412">If the "Allow Extended Options" checkbox is ticked, some advanced formatting options are enabled. The list of features that can be formatted is changed slightly, and more variables are available to be used in the format command, providing greater control over the page layout.</Text>
+</Content>
+</Part>
+<Part id="translate_text">
+<Title>
+<Text id="413">Translate Text</Text>
+</Title>
+<Content>
+<Text id="414">This section describes the translation view, where you can define language-specific text fragments for parts of the collection's interface. Under "Design Sections", click "Translate Text".</Text>
+<Text id="415">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="416">To remove an existing translation, select it in the "Assigned Translations" table and click "Remove Translation".</Text>
+<Text id="417">To edit a translation, select it, edit it in the "Translated Text" text area, and click "Replace Translation".</Text>
+</Content>
+</Part>
+<Part id="metadata_sets">
+<Title>
+<Text id="418">Metadata Sets</Text>
+</Title>
+<Content>
+<Text id="419">This section explains the metadata set review panel. Under "Design Sections", click "Metadata Sets".</Text>
+<Text id="420">This view is used to review the metadata sets that the collection uses, and the elements that are available within each set. Choose from the list of "Available Metadata Sets" in order to see details of their elements.</Text>
+<Text id="421">To use another metadata set with the loaded collection, click "Add Metadata Set" and select the metadata set file (.mds) for the new metadata set.</Text>
+<Text id="422">Editing metadata sets is done with the Greenstone Editor for Metadata Sets (GEMS). Clicking the "Edit Metadata Set" button provides information on how to run the GEMS.</Text>
+<Text id="423">If you no longer need a metadata set, select it and press "Remove Metadata Set" to remove it. If you have assigned any metadata to elements in the removed set you will be asked how to deal with this metadata when you next open the collection.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="producing_your_collection">
+<Title>
+<Text id="424">Producing Your Collection</Text>
+</Title>
+<Content>
+<Text id="425">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>
+<Part id="the_create_view">
+<Title>
+<Text id="426">The Create View</Text>
+</Title>
+<Content>
+<Text id="427">The Create view is used to create the collection by running Greenstone collection-building scripts on the information you have provided. 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".</Text>
+<Text id="428">Once the collection has successfully built, clicking "Preview Collection" will launch a web browser showing the home page of the collection.</Text>
+<Text id="429">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>
+</Content>
+</Part>
+<Part id="import_and_build_settings">
+<Title>
+<Text id="430">Import and Build Settings</Text>
+</Title>
+<Content>
+<Text id="431">This section explains how to access the various import and build settings. For more information of importing and building read Chapter 1 of the Greenstone Developer's Guide -- Understanding the collection-building process.</Text>
+<Text id="432">Controlling the various settings is done in a similar way to the "Configuring Arguments" window described in the Document Plugins section. Some fields require numeric arguments, and you can either type these in or use the up and down 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>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="miscellaneous">
+<Title>
+<Text id="433">Miscellaneous</Text>
+</Title>
+<Content>
+<Text id="434">This section describes features of the Librarian Interface that are not associated with any particular view.</Text>
+<Part id="preferences">
+<Title>
+<Text id="435">Preferences</Text>
+</Title>
+<Content>
+<Text id="436">This section explains the preferences dialog, accessed by opening "File" -&gt; "Preferences".</Text>
+<Text id="437">The first "General" option is a text field for entering your e-mail address. This will be used for the "creator" and "maintainer" collection metadata items. 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, you must restart the Librarian Interface in order to load the new language strings from the dictionary.</Text>
+<Text id="438">If "View Extracted Metadata" is checked, the various controls dealing with metadata always show all metadata that has been extracted automatically from documents. Deselecting 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="439">The "Mode" panel 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 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="440">The Librarian Interface can support different workflows by determining which of the various view tabs are visible. Use the "Workflow" tab to customise what views are available by checking the boxes next to the views that you want to be available. Alternatively, use the pull-down list at the bottom to select predetermined configurations. Closing the preferences dialog establishes these workflow settings. These settings are stored with the collection, not in the Librarian Interface configuration file.</Text>
+<Text id="441">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 Downloading Files From the Internet 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="442">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 box next to warning messages you want to see again.</Text>
+</Content>
+</Part>
+<Part id="file_associations">
+<Title>
+<Text id="443">File Associations</Text>
+</Title>
+<Content>
+<Text id="444">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="445">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 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="446">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="447">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="448">File associations are stored in the Librarian Interface's main folder, in a file called "associations.xml".</Text>
+</Content>
+</Part>
+<Part id="exporting_collections_to_cddvd">
+<Title>
+<Text id="449">Exporting Collections to CD/DVD</Text>
+</Title>
+<Content>
+<Text id="450">Greenstone can export one or more collections to a self-installing CD/DVD for Windows. To do so, Greenstone's "Export to CD-ROM" package must be installed. This is not included by default, so you may need to modify your installation to include it.</Text>
+<Text id="451">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 box: this is what will appear in the Start menu when the CD/DVD has been installed. Then click "Export". The process involves copying many files and may take a few minutes.</Text>
+<Text id="452">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>
+</Content>
+</Part>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="tagging_document_files">
+<Title>
+<Text id="453">Tagging document files</Text>
+</Title>
+<Content>
+<Text id="454">Source documents often need to be structured into sections and subsections, and this information needs to be communicated to Greenstone so that it can preserve the hierarchical structure. Also, metadata - typically the title - might be associated with each section and subsection.</Text>
+<Text id="455">The source documents from an OCR process are typically a set of word processor files, including images. If these are represented as MicrosoftWord files, they can be input into Greenstone using the Word plugin. Alternatively, they can be converted to HTML and input using the HTML plugin.</Text>
+<Text id="456">In either case, the hierarchical structure of a document may be indicated by inserting tags in the text as follows:</Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>&lt;Description&gt;</CodeLine>
+<Text type="code" id="457">&lt;Metadata name="Title"&gt;Realizing human rights for poor people: Strategies for achieving the international development targets&lt;/Metadata&gt;</Text>
+<CodeLine>&lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="458"><i>(text of section goes here)</i></Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="459">The &lt;!-- ... --&gt; markers are used because they indicate comments in HTML; thus these section tags will not affect document formatting. You must include these markers around your section tags, even if the document you are working with is not HTML (e.g. if it's a Microsoft Word file).</Text>
+<Text id="460">In the Description part (between the &lt;Description&gt; and &lt;/Description&gt; tags) other kinds of metadata can be specified, but this is not done for the style of collections we are describing here.</Text>
+<Text id="461">It is important to remember that you are creating a hierarchical table of contents when you insert section tags into your document. This means that sections can be nested within other sections. In fact, all sections must be nested within a single enclosing section that encompasses the entire document.</Text>
+<Text id="462">The following example demonstrates a document with two chapters, the second of which contains two subsections. For real examples of sourcedocuments tagged in this way, look at the source documents for the Demo or DLS collections.</Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>&lt;Description&gt;</CodeLine>
+<CodeLine>&lt;Metadata name="Title"&gt;My Document&lt;/Metadata&gt;</CodeLine>
+<CodeLine>&lt;/Description&gt;</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>&lt;Description&gt;</CodeLine>
+<CodeLine>&lt;Metadata name="Title"&gt;Chapter 1&lt;/Metadata&gt;</CodeLine>
+<CodeLine>&lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text type="code" id="463">(text of chapter 1 goes here)</Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>&lt;Description&gt;</CodeLine>
+<CodeLine>&lt;Metadata name="Title"&gt;Chapter 2&lt;/Metadata&gt;</CodeLine>
+<CodeLine>&lt;/Description&gt;</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>&lt;Description&gt;</CodeLine>
+<CodeLine>&lt;Metadata name="Title"&gt;Subsection 1&lt;/Metadata&gt;</CodeLine>
+<CodeLine>&lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text type="code" id="464">(text of sub-section 1 goes here)</Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>&lt;Description&gt;</CodeLine>
+<CodeLine>&lt;Metadata name="Title"&gt;Subsection 2&lt;/Metadata&gt;</CodeLine>
+<CodeLine>&lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text type="code" id="465">(text of sub-section 2 goes here)</Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="466">Note that metadata assigned from within a section tag in a source document takes precedence over that assigned to the document as a whole. This means that you should not explicitly specify Title metadata for the top-level section within a source document unless you want it to override the title you gave it when specifying metadata. In the above example, unless you want to override the document's existing title you should omit the line that reads:</Text>
+<CodeLine>&lt;Metadata name="Title"&gt;My Document&lt;/Metadata&gt;</CodeLine>
+</Content>
+</Section>
+<Section id="the_collector">
+<Title>
+<Text id="467">The Collector</Text>
+</Title>
+<Content>
+<Text id="468">The Collector is a facility that helps you create new collections, modify or add to existing ones, or delete collections. To do this you will be guided through a sequence of web pages which request the information that is needed. The sequence is self-explanatory: this section takes you through it. As an alternative to using the Collector, you can also build collections from the command lineâthe first few pages of the Developer's Guide give a detailed walk-through of how to do this. The Collector predates the librarian interface described in Section 3.1, and for most practical purposes the librarian interface should be used instead of the Collector.</Text>
+<Text id="469">Building and distributing information collections carries responsibilities that you should reflect on before you begin. There are legal issues of copyright: being able to access documents doesn't mean you can necessarily give them to others. There are social issues: collections should respect the customs of the community out of which the documents arise. And there are ethical issues: some things simply should not be made available to others. The pen is mightier than the sword!âbe sensitive to the power of information and use it wisely.</Text>
+<Text id="470">To access the Collector, click the appropriate link on the digital library home page.</Text>
+<Text id="471">In Greenstone, the structure of a particular collection is determined when the collection is set up. This includes such things as the format of the source documents, how they should be displayed on the screen, the source of metadata, what browsing facilities should be provided, what full-text search indexes should be provided, and how the search results should be displayed. Once the collection is in place, it is easy to add new documents to itâso long as they have the same format as the existing documents, and the same type of metadata is provided, in exactly the same way.</Text>
+<Text id="472">The Collector has the following basic functions:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="473">create a new collection with the same structure as an existing one;</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="474">create a new collection with a different structure from existing ones;</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="475">add new material to an existing collection;</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="476">modify the structure of an existing collection;</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="477">delete a collection; and</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="478">write an existing collection to a self-contained, self-installing cd-rom.</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="479">Figure 16 shows the Collector being used to create a new collection, in this case from a set of html files stored locally. You must first decide whether to work with an existing collection or build a new one. The former case covers options 1 and 2 above; the latter covers options 3â6. In Figure 16a, the user opts to create a new collection.</Text>
+<Figure id="using_the_collector_to_build_a_new_collection">
+<Title>
+<Text id="480">Using the Collector to build a new collection (continued on next pages)</Text>
+<SubTitle>
+<Text id="481">(a)</Text>
+</SubTitle>
+</Title>
+<File width="369" height="440" url="images/User_Fig_16a.png"/>
+</Figure>
+<Subsection id="logging_in">
+<Title>
+<Text id="482">Logging in</Text>
+</Title>
+<Content>
+<Text id="483">Either way it is necessary to log in before proceeding. Note that in general, people use their web browser to access the collection-building facility on a remote computer, and build the collection on that server. Of course, we cannot allow arbitrary people to build collections (for reasons of propriety if nothing else), so Greenstone contains a security system which forces people who want to build collections to log in first. This allows a central system to offer a service to those wishing to build information collections and use that server to make them available to others. Alternatively, if you are running Greenstone on your own computer you can build collections locally, but it is still necessary to log in because other people who use the Greenstone system on your computer should not be allowed to build collections without prior permission.</Text>
+</Content>
+</Subsection>
+<Subsection id="dialog_structure">
+<Title>
+<Text id="484">Dialog structure</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_1">
+<Title>
+<Text id="485">Using the Collector to build a new collection (Continued)</Text>
+<SubTitle>
+<Text id="486">(b)</Text>
+</SubTitle>
+</Title>
+<File width="369" height="435" url="images/User_Fig_16b.png"/>
+</Figure>
+<Text id="487">Upon completion of login, the page in Figure 16b appears. This shows the sequence of steps that are involved in collection building. They are:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="488">Collection information</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="489">Source data</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="490">Configuring the collection</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="491">Building the collection</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="492">Viewing the collection.</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="493">The first step is to specify the collection's name and associated information. The second is to say where the source data is to come from. The third is to adjust the configuration options, a step that becomes more useful as you gain experience with Greenstone. The fourth step is where all the (computer's) work is done. During the âbuildingâ process the system makes all the indexes and gathers together any other information that is required to make the collection operate. The fifth step is to view the collection that has been created.</Text>
+<Text id="494">These five steps are displayed as a linear sequence of gray buttons at the bottom of the screen in Figure 16b, and at the bottom of all other pages generated by the Collector. This display helps users keep track of where they are in the process. The button that should be clicked to continue the sequence is shown in green (<i>collection information</i> in Figure 16b). The gray buttons (all the others, in Figure 16b) are inactive. The buttons change to yellow as you proceed through the sequence, and the user can return to an earlier step by clicking the corresponding yellow button in the diagram. This display is modeled after the âwizardsâ that are widely used in commercial software to guide users through the steps involved in installing new software.</Text>
+</Content>
+</Subsection>
+<Subsection id="collection_information">
+<Title>
+<Text id="495">Collection information</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_2">
+<Title>
+<Text id="496">Using the Collector to build a new collection (Continued)</Text>
+<SubTitle>
+<Text id="497">(c)</Text>
+</SubTitle>
+</Title>
+<File width="369" height="504" url="images/User_Fig_16c.png"/>
+</Figure>
+<Text id="498">The next step in the sequence, collection information, is shown in Figure 16c. When creating a new collection, it is necessary to enter some information about it:</Text>
+<BulletList>
+<Bullet>
+<Text id="499">title,</Text>
+</Bullet>
+<Bullet>
+<Text id="500">contact E-mail address, and</Text>
+</Bullet>
+<Bullet>
+<Text id="501">brief description.</Text>
+</Bullet>
+</BulletList>
+<Text id="502">The collection title is a short phrase used through the digital library to identify the content of the collection. Example titles include <i>Food and Nutrition Library</i>, <i>World Environmental Library</i>, <i>Development Library</i>, and so on. The E-mail address specifies the first point of contact for any problems encountered with the collection. If the Greenstone software detects a problem, a diagnostic report may be sent to this address. Finally, the brief description is a statement describing the principles that govern what is included in the collection. It appears under the heading <i>About this collection</i> on the first page when the collection is presented.</Text>
+<Text id="503">The user's current position in the collection-building sequence is indicated by an arrow that appears in the display at the bottom of each screenâin this case, as Figure 16c shows, the collection information stage. The user proceeds to Figure 16d by clicking the green source data button.</Text>
+</Content>
+</Subsection>
+<Subsection id="source_data">
+<Title>
+<Text id="504">Source data</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_3">
+<Title>
+<Text id="505">Using the Collector to build a new collection (Continued)</Text>
+<SubTitle>
+<Text id="506">(d)</Text>
+</SubTitle>
+</Title>
+<File width="368" height="532" url="images/User_Fig_16d.png"/>
+</Figure>
+<Text id="507">Figure 16d is the point where the user specifies the source text that comprises the collection. You may either base your collection on a default structure that is provided, or on the structure of an existing collection.</Text>
+<Text id="508">If you opt for the default structure, the new collection may contain html documents (files ending in <i>.htm, .html</i>), or plain text documents (files ending in <i>.txt, .text</i>), Microsoft Word documents (files ending in <i>.doc</i>), PDF documents (files ending in <i>.pdf</i>) or E-mail documents (files ending in <i>.email</i>). More information about the different document formats that can be accommodated is given in the section on âDocument formatsâ below.</Text>
+<Text id="509">If you base your new collection on an existing one, the files in the new collection must be exactly the same type as those used to build the existing one. Note that some collections use non-standard input file formats, while others use metadata specified in auxiliary files. If your new input lacks this information, some browsing facilities may not work properly. For example, if you clone the Demo collection you may find that the <i>subjects</i>, <i>organization</i>, and <i>how to</i> buttons don't work.</Text>
+<Text id="510">Boxes are provided to indicate where the source documents are located: up to three separate input sources can be specified in Figure 16d. If you need more, just click the button marked âmore sources.â</Text>
+<Text id="511">There are three kinds of specification:</Text>
+<BulletList>
+<Bullet>
+<Text id="512">a directory name on the Greenstone server system (beginning with âfile://â)</Text>
+</Bullet>
+<Bullet>
+<Text id="513">an address beginning with âhttp://â for files to be downloaded from the web</Text>
+</Bullet>
+<Bullet>
+<Text id="514">an address beginning with âftp://â for files to be downloaded using anonymous FTP.</Text>
+</Bullet>
+</BulletList>
+<Text id="515">If you use <i>file://</i> or <i>ftp://</i> to specify a file, that file will be downloaded.</Text>
+<Text id="516">If you use <i>http://</i> it depends on whether the URL gives you a normal web page in your browser, or a list of files. If a page, that page will be downloadedâand so will all pages it links to, and all pages they link to, etc.âprovided they reside on the same site, below the URL.</Text>
+<Text id="517">If you use <i>file://</i> or <i>ftp://</i> to specify a folder or directory, or give a <i>http://</i> URL that leads to a list of files, everything in the folder and all its subfolders will be included in the collection.</Text>
+<Text id="518">You can specify sources of more than one type.</Text>
+<Text id="519">In this case (Figure 16d) the new collection will contain documents taken from a local file system as well as a remote web site, which will be mirrored during the building process.</Text>
+<Text id="520">When you click the <i>configure collection</i> button to proceed to the next stage of building, the Collector checks that all the sources of input you specified can be reached. This might take a few seconds, or even a few minutes if you have specified several sources. If one or more of the input sources you specified is unavailable, you will be presented with a page like that in Figure 16e, where the unavailable sources are marked (both of them in this case).</Text>
+<Figure id="using_the_collector_to_build_a_new_collection_4">
+<Title>
+<Text id="521">Using the Collector to build a new collection (Continued)</Text>
+<SubTitle>
+<Text id="522">(e)</Text>
+</SubTitle>
+</Title>
+<File width="368" height="531" url="images/User_Fig_16e.png"/>
+</Figure>
+<Text id="523">Sources might be unavailable because</Text>
+<BulletList>
+<Bullet>
+<Text id="524">the file, FTP site or URL does not exist;</Text>
+</Bullet>
+<Bullet>
+<Text id="525">you need to dial up your ISP first;</Text>
+</Bullet>
+<Bullet>
+<Text id="526">you are trying to access a URL from behind a firewall.</Text>
+</Bullet>
+</BulletList>
+<Text id="527">The last case is potentially the most mysterious. It occurs if you normally have to present a username and password to access the Internet Sometimes it happens that you can see the page from your Web browser if you enter the URL, but the Collector claims that it is unavailable. The explanation is that the page in your browser may be coming from a locally cached copy. Unfortunately, locally cached copies are invisible to the Collector. In this case we recommend that you download the pages using your browser first.</Text>
+</Content>
+</Subsection>
+<Subsection id="configuring_the_collection">
+<Title>
+<Text id="528">Configuring the collection</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_5">
+<Title>
+<Text id="529">Using the Collector to build a new collection (Continued)</Text>
+<SubTitle>
+<Text id="530">(f)</Text>
+</SubTitle>
+</Title>
+<File width="369" height="467" url="images/User_Fig_16f.png"/>
+</Figure>
+<Text id="531">Figure 16f shows the next stage. The construction and presentation of all collections is controlled by specifications in a special collection configuration file (see below). Advanced users may use this page to alter the configuration settings. Most, however, will proceed directly to the final stage. Indeed, in Figure 16d both the <i>configure collection</i> and the <i>build collection</i> buttons are displayed in green, signifying that step 3 can be bypassed completely.</Text>
+<Text id="532">In our example the user has made a small modification to the default configuration file by including the <i>file_is_url</i> flag with the html plugin. This flag causes URL metadata to be inserted in each document, based on the filename convention that is adopted by the mirroring package. This metadata is used in the collection to allow readers to refer to the original source material, rather than to a local copy.</Text>
+</Content>
+</Subsection>
+<Subsection id="building_the_collection_1">
+<Title>
+<Text id="533">Building the collection</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_6">
+<Title>
+<Text id="534">Using the Collector to build a new collection (Continued)</Text>
+<SubTitle>
+<Text id="535">(g)</Text>
+</SubTitle>
+</Title>
+<File width="369" height="304" url="images/User_Fig_16g.png"/>
+</Figure>
+<Text id="536">Figure 16g shows the âbuildingâ stage. Up until now, the responses to the dialog have merely been recorded in a temporary file. The building stage is where the action takes place.</Text>
+<Text id="537">During building, indexes for both browsing and searching are constructed according to instructions in the collection configuration file. The building process takes some time: minutes to hours, depending on the size of the collection and the speed of your computer. Some very large collections take a day or more to build.</Text>
+<Text id="538">When you reach this stage in the interaction, a status line at the bottom of the web page gives feedback on how the operation is progressing, updated every five seconds. The message visible in Figure 16f indicates that when the snapshot was taken, Title metadata was being extracted from an input file.</Text>
+<Text id="539">Warnings are written if input files or URLs are requested that do not exist, or exist but there is no plugin that can process them, or the plugin cannot find an associated file, such as an image file embedded in a html document. The intention is that you will monitor progress by keeping this window open in your browser. If any errors cause the process to terminate, they are recorded in this status area.</Text>
+<Text id="540">You can stop the building process at any time by clicking on the <i>stop building</i> button in Figure 16g. If you leave the web page (and have not cancelled the building process with the <i>stop building</i> button), the building operation will continue, and the new collection will be installed when the operation completes.</Text>
+</Content>
+</Subsection>
+<Subsection id="viewing_the_collection">
+<Title>
+<Text id="541">Viewing the collection</Text>
+</Title>
+<Content>
+<Text id="542">When the collection is built and installed, the sequence of buttons visible at the bottom of Figures 16bâf appears at the bottom of Figure 16g, with the View collection button active. This takes the user directly to the newly built collection.</Text>
+<Text id="543">Finally, there is a facility for E-mail to be sent to the collection's contact E-mail address, and to the system's administrator, whenever a collection is created (or modified.) This allows those responsible to check when changes occur, and monitor what is happening on the system. The facility is disabled by default but can be enabled by editing the <i>main.cfg</i> configuration file (see the <i>Greenstone Digital Library Developer's Guide</i>, Section <CrossRef target="Chapter" external="Develop" lang="en" ref="configuring_your_greenstone_site"/>).</Text>
+</Content>
+</Subsection>
+<Subsection id="working_with_existing_collections">
+<Title>
+<Text id="544">Working with existing collections</Text>
+</Title>
+<Content>
+<Text id="545">When you enter the Collector you have to specify whether you want to create an entirely new collection or work with an existing one, adding data to it or deleting it. By creating all searching and browsing structures automatically from the documents themselves Greenstone makes it easy to add new information to existing collections. Because no links are inserted by hand, when new documents in the same format become available they can be merged into the collection automatically.</Text>
+<Text id="546">To work with an existing collection, you first select the collection from a list that is provided. Some collections are âwrite protectedâ and cannot be altered: these ones don't appear in the selection list. With the collection, you can</Text>
+<BulletList>
+<Bullet>
+<Text id="547">Add more data and rebuild the collection</Text>
+</Bullet>
+<Bullet>
+<Text id="548">Edit the collection configuration file</Text>
+</Bullet>
+<Bullet>
+<Text id="549">Delete the collection entirely</Text>
+</Bullet>
+<Bullet>
+<Text id="550">Export the collection to CD-ROM.</Text>
+</Bullet>
+</BulletList>
+<Part id="add_new_data">
+<Title>
+<Text id="551">Add new data</Text>
+</Title>
+<Content>
+<Text id="552">The files that you specify will be added to the collection. Make sure that you do not re-specify files that are already in the collectionâotherwise two copies will be included. Files are identified by their full pathname, web pages by their absolute web address. You specify directories and files just as you do when building a new collection.</Text>
+<Text id="553">If you add data to a collection and for some reason the building process fails, the old version of the collection remains unchanged.</Text>
+</Content>
+</Part>
+<Part id="edit_configuration_file">
+<Title>
+<Text id="554">Edit configuration file</Text>
+</Title>
+<Content>
+<Text id="555">Advanced users can edit the collection configuration file, just as they can when a new collection is built.</Text>
+</Content>
+</Part>
+<Part id="delete_the_collection">
+<Title>
+<Text id="556">Delete the collection</Text>
+</Title>
+<Content>
+<Text id="557">You will be asked to confirm whether you really want to delete the collection. Once deleted, Greenstone can not bring the collection back!</Text>
+</Content>
+</Part>
+<Part id="export_the_collection">
+<Title>
+<Text id="558">Export the collection</Text>
+</Title>
+<Content>
+<Text id="559">You can export the collection in a form that allows it to be written to a self-contained, self-installing Greenstone CD-ROM for Windows. Because commercial software that creates self-installing CD-ROMs is expensive, this facility includes a homegrown installer module.</Text>
+<Text id="560">When you export the collection, the dialogue informs you of the directory name in which the result has been placed. The entire contents of the directory should be written on to CD-ROM using a standard CD-writing utility.</Text>
+<Text id="561">The immense variety of different possible Windows configurations has made it difficult for us to test and debug the Greenstone installer under all possible conditions. Although the installer produces CD-ROMs that operate on most Windows systems, it is still under development. If you experience problems and you possess a commercial installation package (e.g. InstallShield), you can use it to create CD-ROMs from the information that Greenstone provides. The above-mentioned export directory contains four files that relate to the installation process, and three subdirectories that contain the complete collection and software. Remove the four files and use InstallShield to make a CD-ROM image that installs these directories and creates a shortcut to the program <i>gsdl\server.exe</i>.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="document_formats_1">
+<Title>
+<Text id="562">Document formats</Text>
+</Title>
+<Content>
+<Text id="563">When building collections, Greenstone processes each different format of source document by seeking a âpluginâ that can deal with that particular format. Plugins are specified in the collection configuration file. Greenstone generally uses the filename to determine document formatsâfor example, <i>foo.txt</i> is processed as a text file, <i>foo.html</i> as html, and <i>foo.doc</i> as a Word file.</Text>
+<Text id="564">Here is a summary of the plugins that are available for widely-used document formats. More detail about these plugins, and additional plugins for less commonly-used formats, can be found in the <i>Greenstone Digital Library Developer's Guide</i>.</Text>
+<Part id="textplug">
+<Title>
+<Text id="565">TEXTPlug (*.txt, *.text)</Text>
+</Title>
+<Content>
+<Text id="566">TEXTPlug interprets a plain text file as a simple document. It adds <i>title</i> metadata based on the first line of the file.</Text>
+</Content>
+</Part>
+<Part id="htmlplug">
+<Title>
+<Text id="567">HTMLPlug (*.htm, *.html; also .shtml, .shm, .asp, .php, .cgi)</Text>
+</Title>
+<Content>
+<Text id="568">HTMLPlug processes html files. It extracts <i>title</i> metadata based on the &lt;title&gt; tag; other metadata expressed using html's metatag syntax can be extracted too. There are many options available with this plugin, documented in the <i>Greenstone Digital Library Developer's Guide</i>.</Text>
+</Content>
+</Part>
+<Part id="wordplug">
+<Title>
+<Text id="569">WORDPlug (*.doc)</Text>
+</Title>
+<Content>
+<Text id="570">WORDPlug imports Microsoft Word documents. There are many different variants on the Word formatâand even Microsoft programs frequently make conversion errors. Greenstone uses independent programs to convert Word files to html. For some older Word formats the system resorts to a simple extraction algorithm that finds all text strings in the input file.</Text>
+</Content>
+</Part>
+<Part id="pdfplug">
+<Title>
+<Text id="571">PDFPlug (*.pdf)</Text>
+</Title>
+<Content>
+<Text id="572">PDFPlug imports documents in PDF Adobe's Portable Document Format. Like WORDPlug, it uses an independent program, in this case <i>pdftohtml</i>, to convert PDF files to html.</Text>
+<Text id="573">As with WORDPlug, by default collections will display the html equivalent of the file when the user clicks the <i>document</i> icon; however, the format strings in the collection configuration file can be adjusted to give the user access to the original PDF file instead, and we recommend that you do this. Again, just replace the <i>&lt;link&gt; âŠ &lt;/link&gt;</i> tags by <i>&lt;srclink&gt; âŠ &lt;/srclink&gt;</i> ones.</Text>
+<Text id="574">The <i>pdftohtml</i> program fails on some PDF files. What happens is that the conversion process takes an exceptionally long time, and often an error message relating to the conversion process appears on the screen. If this occurs, the only solution that we can offer is to remove the offending document from the collection. Also, PDFPlug cannot handle encrypted PDF files.</Text>
+</Content>
+</Part>
+<Part id="psplug">
+<Title>
+<Text id="575">PSPlug (*.ps)</Text>
+</Title>
+<Content>
+<Text id="576">PSPlug imports documents in PostScript. It works best if a standard Linux program, called <i>ps2ascii</i>, is already installed on your computer. This is available on most Linux installations, but not on Windows. If this program is not available, PSPlug resorts to a simple text extraction algorithm.</Text>
+</Content>
+</Part>
+<Part id="emailplug">
+<Title>
+<Text id="577">EMAILPlug (*.email)</Text>
+</Title>
+<Content>
+<Text id="578">EMAILPlug imports files containing E-mail, and deals with common E-mail formats such as are used by the Netscape, Eudora, and Unix mail readers. Each source document is examined to see if it contains an E-mail, or several E-mails joined together in one file, and if so its contents are processed. The plugin extracts <i>Subject</i>, <i>To</i>, <i>From</i>, and <i>Date</i> metadata. However, this plugin does not yet handle MIME-encoded E-mails properlyâalthough legible, they often look rather strange.</Text>
+</Content>
+</Part>
+<Part id="zipplug">
+<Title>
+<Text id="579">ZIPPlug (.gz, .z, .tgz, .taz, .bz, .zip, .tar)</Text>
+</Title>
+<Content>
+<Text id="580">ZIPPlug plugin handles the following compressed and/or archived input formats : gzip (.<i>gz</i>, .<i>z</i>, .<i>tgz</i>, .<i>taz</i>) , bzip (.<i>bz</i>) , zip (.<i>zip</i>, .<i>jar</i>) , and tar (.<i>tar</i>). It relies on the programs <i>gunzip</i>, <i>bunzip</i>, <i>unzip</i>, and <i>tar</i>, which are standard Linux utilities. ZIPPlug is disabled on Windows computers.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="administration">
+<Title>
+<Text id="581">Administration</Text>
+</Title>
+<Content>
+<Text id="582">An âadministrativeâ facility is included with every Greenstone installation.To access this facility, click the appropriate link on the front page.</Text>
+<Text id="583">The entry page, shown in Figure 17, gives information about each of the collections offered by the system. Note that <i>all</i> collections are includedâfor there may be âprivateâ ones that do not appear on the Greenstone home page. With each is given its short name, full name, whether it is publicly displayed, and whether or not it is running. Clicking a particular collection's abbreviation (the first column of links in Figure 17) brings up information about that collection, gathered from its collection configuration file and from other internal structures created for that collection. If the collection is both public and running, clicking the collection's full name (the second link) takes you to the collection itself.</Text>
+<Text id="584">A collection named <i>wohiex</i>, for <i>Women's History Excerpt</i>, is visible near the bottom of Figure 17. Figure 18 shows the information that is displayed when this link is clicked. The first section gives some information from the configuration file, and the size of the collection (about 1000 documents, about a million words, over 6 Mb). The next sections contain internal information related to the communication protocol through which collections are accessed. For example, the filter options for âQueryFilterâ show the options and possible values that can be used when querying the collection.</Text>
+<Text id="585">The administrative facility also presents configuration information about the installation and allows it to be modified. It facilitates examination of the error logs that record internal errors, and the user logs that record usage. It enables a specified user (or users) to authorize others to build collections and add new material to existing ones. All these facilities are accessed interactively from the menu items at the left-hand side of Figure 17.</Text>
+<Figure id="greenstone_administration_facility">
+<Title>
+<Text id="586">Greenstone Administration facility</Text>
+</Title>
+<File width="335" height="699" url="images/User_Fig_17.png"/>
+</Figure>
+<Figure id="information_about_the_womens_history_excerpt_collection">
+<Title>
+<Text id="587">Information about the <i>Women's History Excerpt</i> collection</Text>
+</Title>
+<File width="331" height="699" url="images/User_Fig_18.png"/>
+</Figure>
+<Section id="configuration_files">
+<Title>
+<Text id="588">Configuration files</Text>
+</Title>
+<Content>
+<Text id="589">There are two configuration files that control Greenstone's operation, the site configuration file <i>gsdlsite.cfg</i> and the main configuration file <i>main.cfg</i>.</Text>
+<Text id="590">The <i>gsdlsite.cfg</i> file is used to configure the Greenstone software for the site where it is installed. It is designed for keeping configuration options that are particular to a given site. Examples include the name of the directory where the Greenstone software is kept, the http address of the Greenstone system, and whether the <i>fastcgi</i> facility is being used.The entries in this file are described in the <i>Greenstone Digital Library Installation Guide</i>.</Text>
+<Text id="591">The <i>main.cfg</i> file contains information that is common to the interface of all collections served by a Greenstone site. It includes the E-mail address of the system maintainer, whether the status and collector pages are enabled, whether logs of user activity are kept, and whether Internet âcookiesâ are used to identify users.</Text>
+</Content>
+</Section>
+<Section id="logs">
+<Title>
+<Text id="592">Logs</Text>
+</Title>
+<Content>
+<Text id="593">Three kinds of logs can be examined: usage logs, error logs and initialization logs. The last two are only really of interest to people maintaining the software.</Text>
+<Text id="594">All user activityâevery page that each user visitsâcan be recorded by the Greenstone software, though no personal names are included in the logs. Logging, disabled by default, is enabled by including the lines</Text>
+<CodeLine>logcgiargs true</CodeLine>
+<CodeLine>usecookies true</CodeLine>
+<Text id="595">in the main system configuration file. Both options are false by default, so that no logging is done unless they are set. It is the <i>logcgiargs</i> line that actually turns logging on and off. By activating <i>usecookies</i> a unique identification code is assigned to each user, which enables individual user's interactions to be traced through the log file.</Text>
+<Text id="596">Each line in the user log records a page visitedâeven the pages generated to inspect the log files! It contains (a) the IP address of the user's computer, (b) a timestamp in square brackets, (c) the CGI arguments in parentheses, and (d) the name of the user's browser (Netscape is called âMozillaâ). Here is a sample line, split and annotated for ease of reading:</Text>
+<CodeLine>/fast-cgi-bin/niupepalibrary</CodeLine>
+<CodeLine>(a) its-www1.massey.ac.nz</CodeLine>
+<CodeLine>(b) [ Thu Dec07 23:47:00 NZDT2000]</CodeLine>
+<CodeLine>(c) (a=p, b=0, bcp=, beu=, c=niupepa, cc=, ccp=0, ccs=0, cl=, cm=, cq2=, d=, e=, er=, f=0, fc=1, gc=0, gg=text, gt=0, h=, h2=, hl=1, hp=, il=l, j=, j2=, k=1, ky=, l=en, m=50, n=, n2=, o=20, p=home, pw=, q=, q2=, r=1, s=0, sp=frameset, t=1, ua=, uan=, ug=, uma=listusers, umc=, umnpw1=, umnpw2=, umpw=, umug=, umun=, umus=, un=, us=invalid, v=0, w=w, x=0, z=130.123.128.4-950647871)</CodeLine>
+<CodeLine>(d) âMozilla/4.08 [en] (Win95; I ;Nav)â</CodeLine>
+<Text id="597">The last CGI argument, âzâ, is an identification code or âcookieâ generated by the user's browser: it comprises the user's IP number followed by the timestamp when they first accessed the digital library.</Text>
+<Text id="598">The log file <i>usage.txt</i> is placed in the <i>etc</i> directoryin the Greenstone file structure (see the <i>Greenstone Digital Library Developer's Guide</i>).When logging is enabled, every action by every user is logged. However, only the last 100 entries in the log file are displayed by the <i>usage log</i> link in Figure 17.</Text>
+</Content>
+</Section>
+<Section id="user_management">
+<Title>
+<Text id="599">User management</Text>
+</Title>
+<Content>
+<Text id="600">Greenstone incorporates an authentication scheme which can be used to control access to certain facilities. At the moment this is only used to restrict the people who are allowed to enter the Collectorand certain administration functions. If, for a particular collection, it were necessary to authenticate users before returning information to them, this is possible tooâfor example, documents could be protected on an individual basis so that they can only be accessed by registered users on presentation of a password. However, no current collections use this facility). Authentication is done by requesting a user name and password, as illustrated in Figure 16a.</Text>
+<Text id="601">From the administration page users can be listed, new ones added, and old ones deleted. The ability to do this is of course also protected: only users who have administrative privileges can add new users. It is also possible for each user to belong to different âgroupsâ. At present, the only extant groups are âadministratorâ and âcolbuilderâ. Members of the first group can add and remove users, and change their groups. Members of the second can access the facilities described above to build new collections and alter (and delete) existing ones.</Text>
+<Text id="602">When Greenstone is installed, there is one user called <i>admin</i> who belongs to both groups. The password for this user is set during the installation process. This user can create new names and passwords for users who belong just to the <i>colbuilder</i> group, which is the recommended way of giving other users the ability to build collections. User information is recorded in two databases that are placed in the Greenstone file structure (see the <i>Greenstone Digital Library Developer's Guide</i>).</Text>
+</Content>
+</Section>
+<Section id="technical_information">
+<Title>
+<Text id="603">Technical information</Text>
+</Title>
+<Content>
+<Text id="604">The links under the <i>Technical information</i> heading show further information on the installation.The <i>general</i> link gives access to technical information, including the directories where things are stored.The <i>protocols</i> menu item gives, for each possible protocol type, information about each of the collections supported by that protocol.</Text>
+<Text id="605">Finally, user interface code (called the âreceptionistâ) uses <i>actions</i> to communicate the wishes of the user. These actions correspond to the CGI argument labeled <i>a</i>. For example, if <i>a=status</i> the receptionist invokes the <i>status</i> action (which displays the status page). A menu item gives access to lists of all actions supported by the system, and another leads to the arguments that these actions take.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="appendix_a_software_features">
+<Title>
+<Text id="606">Appendix A Software features</Text>
+</Title>
+<Content>
+<Table class="hidden" id="table_appendixa">
+<Title/>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="607"><i>Accessible via web browser</i></Text>
+</th>
+<th width="397">
+<Text id="608">Collections are accessed through a standard web browser (Netscape or Internet Explorer) and combine easy-to-use browsing with powerful search facilities.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="609"><i>Full-text and fielded search</i></Text>
+</th>
+<th width="397">
+<Text id="610">The user can search the full text of the documents, or choose between indexes built from different parts of the documents. For example, some collections have an index of full documents, an index of sections, an index of titles, and an index of authors, each of which can be searched for particular words or phrases. Results can be ranked by relevance or sorted by a metadata element.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="611"><i>Flexible browsing facilities</i></Text>
+</th>
+<th width="397">
+<Text id="612">The user can browse lists of authors, lists of titles, lists of dates, classification structures, and so on. Different collections may offer different browsing facilities and even within a collection, a broad variety of browsing interfaces are available. Browsing and searching interfaces are constructed during the building process, according to collection configuration information.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="613"><i>Creates access structures automatically</i></Text>
+</th>
+<th width="397">
+<Text id="614">The Greenstone software creates information collections that are very easy to maintain. All searching and browsing structures are built directly from the documents themselves. No links are inserted by hand, but existing links in originals are maintained. This means that if new documents in the same format become available, they can be merged into the collection automatically. Indeed, for some collections this is done by processes that wake up regularly, scout for new material, and rebuild the indexesâall without manual intervention.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="615"><i>Makes use of available metadata</i></Text>
+</th>
+<th width="397">
+<Text id="616">Metadata, which is descriptive information such as author, title, date, keywords, and so on, may be associated with each document, or with individual sections within documents. Metadata is used as the raw material for browsing indexes. It must be either provided explicitly or derivable automatically from the source documents. The Dublin Core metadata scheme is used for most electronic documents, however, provision is made for other schemes.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="617"><i>Plugins extend the system's capabilities</i></Text>
+</th>
+<th width="397">
+<Text id="618">In order to accommodate different kinds of source documents, the software is organized in such a way that âpluginsâ can be written for new document types. Plugins currently exist for plain text, html, Word, PDF, PostScript, E-mail, some proprietary formats, and for recursively traversing directory structures and compressed archives containing such documents. A collection may have source documents in different forms. In order to build browsing indexes from metadata, an analogous scheme of âclassifiersâ is used: classifiers create browsing indexes of various kinds based on metadata.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="619"><i>Designed for multi-gigabyte collections</i></Text>
+</th>
+<th width="397">
+<Text id="620">Collections can contain millions of documents, making the Greenstone system suitable for collections up to several gigabytes.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="621"><i>Documents can be in any language</i></Text>
+</th>
+<th width="397">
+<Text id="622">Unicode is used throughout the software, allowing any language to be processed in a consistent manner. To date, collections have been built containing French, Spanish, Maori, Chinese, Arabic and English. On-the-fly conversion is used to convert from Unicode to an alphabet supported by the user's web browser.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="623"><i>User interface available in multiple languages</i></Text>
+</th>
+<th width="397">
+<Text id="624">The interface can be presented in multiple languages. Currently, the interface is available in Arabic, Chinese, Dutch, English, French, German, Maori, Portuguese, and Spanish. New languages can be added easily.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="625"><i>Collections can contain text, pictures, audio, and video</i></Text>
+</th>
+<th width="397">
+<Text id="626">Greenstone collections can contain text, pictures, audio and video clips. Most non-textual material is either linked in to the textual documents or accompanied by textual descriptions (such as figure captions) to allow full-text searching and browsing. However, the architecture permits implementation of plugins and classifiers even for non-textual data.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="627"><i>Uses advanced compression techniques</i></Text>
+</th>
+<th width="397">
+<Text id="628">Compression techniques are used to reduce the size of the indexes and text. Reducing the size of the indexes via compression has the added advantage of increasing the speed of text retrieval.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="629"><i>Administrative function provided</i></Text>
+</th>
+<th width="397">
+<Text id="630">An âadministrativeâ function enables specified users to authorize new users to build collections, protect documents so that they can only be accessed by registered users on presentation of a password, examine the composition of all collections, and so on. Logs of user activity can record all queries made to every Greenstone collection.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="631"><i>New collections appear dynamically</i></Text>
+</th>
+<th width="397">
+<Text id="632">Collections can be updated and new ones brought on-line at any time, without bringing the system down; the process responsible for the user interface will notice (through periodic polling) when new collections appear and add them to the list presented to the user.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="633"><i>Collections can be published on the Internet or on CD-ROM</i></Text>
+</th>
+<th width="397">
+<Text id="634">The software can be used to serve collections over the World-Wide Web. Greenstone collections can be made available, in precisely the same form, on CD-ROM. The user interface is through a standard web browser (Netscape is provided on each disk), and the interaction is identical to accessing the collection on the webâexcept that response times are more predictable. The CD-ROMs run under all versions of the Windows operating system.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="635"><i>Collections can be distributed amongst different computers</i></Text>
+</th>
+<th width="397">
+<Text id="636">A flexible process structure allows different collections to be served by different computers, yet be presented to the user in the same way, on the same web page, as part of the same digital library.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="637"><i>Operates on both Windows and Unix</i></Text>
+</th>
+<th width="397">
+<Text id="638">Greenstone runs under both Windows (3.1/3.11, 95/98/Me, NT/2000) and Unix (Linux and SunOS). Any of these systems can be used as a webserver. Collections cannot be built on low-end Windows systems (3.1/3.11), but pre-built collections can be transferred to them.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="639"><i>What you get with Greenstone</i></Text>
+</th>
+<th width="397">
+<Text id="640">The Greenstone Digital Library is open-source software, available from the New Zealand Digital Library (<i>nzdl.org</i>) under the terms of the Gnu General Public License. The software includes everything described above: web serving, CD-ROM creation, collection building, multi-lingual capability, plugins and classifiers for a variety of different source document types. It includes an autoinstall feature to allow easy installation on both Windows and Unix. In the spirit of open-source software, users are encouraged to contribute modifications and enhancements.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Chapter>
+<Chapter id="appendix_b_glossary_of_terms">
+<Title>
+<Text id="641">Appendix B Glossary of terms</Text>
+</Title>
+<Content>
+<Table id="appendixb" class="hidden">
+<Title/>
+<TableContent>
+<tr>
+<th width="123">
+<Text id="642"><b>Term</b></Text>
+</th>
+<th width="406">
+<Text id="643"><b>Meaning</b></Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="644"><i>autoconf</i></Text>
+</th>
+<th width="406">
+<Text id="645">Unix program used to configure the Greenstone software installation package to suit your system</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="646"><i>Autorun</i></Text>
+</th>
+<th width="406">
+<Text id="647">Windows feature that starts a program automatically whenever a CD-ROM is inserted</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="648">Boolean query</Text>
+</th>
+<th width="406">
+<Text id="649">Query to an information retrieval system that may contain AND, OR, NOT</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="650">Browsing</Text>
+</th>
+<th width="406">
+<Text id="651">Accessing a collection by scanning an organized list of metadata values associated with the documents (such as author, title, date, keywords)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="652"><i>buildcol.pl</i></Text>
+</th>
+<th width="406">
+<Text id="653">Greenstone program used to build collections</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="654">Building</Text>
+</th>
+<th width="406">
+<Text id="655">Process of creating the indexing and browsing structures that are used to access a collection</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="656">C++</Text>
+</th>
+<th width="406">
+<Text id="657">Programming language in which the majority of the Greenstone software is written</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="658">Casefolding</Text>
+</th>
+<th width="406">
+<Text id="659">Making uppercase and lowercase words look the same, for searching purposes</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="660">CGI</Text>
+</th>
+<th width="406">
+<Text id="661">Common Gateway Interface, a scheme that allows users to activate programs on the host computer by clicking on web pages</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="662">CGI script</Text>
+</th>
+<th width="406">
+<Text id="663">Code associated with a button, menu, or link on a web page that specifies what the host computer is to do when it is clicked</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="664"><i>cgi-bin</i></Text>
+</th>
+<th width="406">
+<Text id="665">Directory in which CGI scripts are stored</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="666">Classifier</Text>
+</th>
+<th width="406">
+<Text id="667">Greenstone code module that examines document metadata to form an index for browsing</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="668">Collection</Text>
+</th>
+<th width="406">
+<Text id="669">Set of documents that are brought together under a uniform searching and browsing interface</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="670">Collection configuration file</Text>
+</th>
+<th width="406">
+<Text id="671">File that specifies how a collection is to be imported and built, what indexes and language interfaces are to be provided, etc.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="672">Collection server</Text>
+</th>
+<th width="406">
+<Text id="673">Program responsible for providing access to a collection when it is being used</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="674">Configuration file</Text>
+</th>
+<th width="406">
+<Text id="675">See collection configuration file, main configuration file, site configuration file</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="676">CVS</Text>
+</th>
+<th width="406">
+<Text id="677">Concurrent Versioning System, a scheme for maintaining source code used throughout Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="678"><i>db2txt</i></Text>
+</th>
+<th width="406">
+<Text id="679">Greenstone tool for viewing a GDBM database as text (see GDBM)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="680">Demo collection</Text>
+</th>
+<th width="406">
+<Text id="681">A subset of the Humanities Development Library, distributed with the Greenstone software and used for illustration in this tutorial</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="682">Digital library</Text>
+</th>
+<th width="406">
+<Text id="683">Collection of digital objects (text, audio, video), along with methods for access and retrieval, and for selection, organization, and maintenance</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="684">DL</Text>
+</th>
+<th width="406">
+<Text id="685">Development Library, A Greenstone collection of humanitarian information for developing countries</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="686">Document</Text>
+</th>
+<th width="406">
+<Text id="687">Basic unit from which digital library collections are constructed; it may include text, graphics, sound, video, etc.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="688">Dublin core</Text>
+</th>
+<th width="406">
+<Text id="689">A standard way of describing metadata</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="690">Fast CGI</Text>
+</th>
+<th width="406">
+<Text id="691">Facility that allows CGI scripts to remain continuously active so that they do not have to be restarted from scratch every time they are invoked</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="692">Filter program</Text>
+</th>
+<th width="406">
+<Text id="693">That part of a Greenstone collection server that implements querying and browsing operations</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="694">Format string</Text>
+</th>
+<th width="406">
+<Text id="695">A string that specifies how documents and other listings are to be displayed in Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="696">GB-encoding</Text>
+</th>
+<th width="406">
+<Text id="697">Standard way of encoding the Chinese language</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="698">GDBM</Text>
+</th>
+<th width="406">
+<Text id="699">Gnu DataBase Manager, a program used within the Greenstone software to store metadata for each document</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="700">GIMP</Text>
+</th>
+<th width="406">
+<Text id="701">Gnu Image-Manipulation Program used (on Unix) to create icons in Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="702">GML</Text>
+</th>
+<th width="406">
+<Text id="703">Greenstone Markup Language, an XML-compliant format used for storing documents internally</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="704">Gnu license</Text>
+</th>
+<th width="406">
+<Text id="705">Software license that permits users to copy and distribute computer programs freely, and modify themâso long as all modifications are made publicly available</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="706">Greenstone</Text>
+</th>
+<th width="406">
+<Text id="707">The name of this digital library software</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="708">GSDL</Text>
+</th>
+<th width="406">
+<Text id="709">Abbreviation for Greenstone Digital Library</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="710"><i>%GSDLHOME%</i></Text>
+</th>
+<th width="406">
+<Text id="711">Operating system variable that represents the top-level directory in which all Greenstone programs and collections are stored (<i>$GSDLHOME</i> on Unix systems)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="712"><i>%GSDLOS%</i></Text>
+</th>
+<th width="406">
+<Text id="713">Operating system variable that represents the operating system currently being used (<i>$GSDLOS</i> on Unix systems)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="714"><i>hashfile</i></Text>
+</th>
+<th width="406">
+<Text id="715">Greenstone program used at import or build time to generate the OID of each document</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="716">HTML</Text>
+</th>
+<th width="406">
+<Text id="717">HyperText Markup Language, the language in which web documents are written</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="718"><i>import.pl</i></Text>
+</th>
+<th width="406">
+<Text id="719">Greenstone program used to import documents</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="720">Importing</Text>
+</th>
+<th width="406">
+<Text id="721">Process of bringing collections of documents into the Greenstone system</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="722">Index</Text>
+</th>
+<th width="406">
+<Text id="723">Information structure that is used for searching or browsing a collection</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="724">InstallShield</Text>
+</th>
+<th width="406">
+<Text id="725">Windows program, used by Greenstone CD-ROMs, that allows a system to be installed from a CD-ROM</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="726">Main configuration file</Text>
+</th>
+<th width="406">
+<Text id="727">File that contains specifications common to all collections served by this site</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="728">Metadata</Text>
+</th>
+<th width="406">
+<Text id="729">Descriptive data such as author, title, date, keywords, and so on, that is associated with a document (or document collection)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="730">MG</Text>
+</th>
+<th width="406">
+<Text id="731">Managing Gigabytes, a program used by the Greenstone system for full-text indexing, that incorporates compression techniques (see Witten, I.H., Moffat, A. and Bell, T. <i>Managing Gigabytes: compressing and indexing documents and images</i>, Morgan Kaufmann, second edition, 1999)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="732"><i>mgbuild</i></Text>
+</th>
+<th width="406">
+<Text id="733">MG program for building a compressed full-text index</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="734"><i>mgquery</i></Text>
+</th>
+<th width="406">
+<Text id="735">MG program for querying a compressed full-text index</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="736"><i>mkcol.pl</i></Text>
+</th>
+<th width="406">
+<Text id="737">Greenstone program that creates and initializes the directory structure for a new collection</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="738">New ZealandÂ <br/>Digital Library Project</Text>
+</th>
+<th width="406">
+<Text id="739">Research project in the Computer Science Department at the University of Waikato, New Zealand, that created the Greenstone software (<i>nzdl.org</i>)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="740">OID</Text>
+</th>
+<th width="406">
+<Text id="741">Object Identifier, a unique identification code associated with a document</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="742">Perl</Text>
+</th>
+<th width="406">
+<Text id="743">Programming language used for many of the text-processing operations that occur during the building process</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="744">Ping</Text>
+</th>
+<th width="406">
+<Text id="745">Message sent to a system to determine whether it is running or not</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="746">Plugin</Text>
+</th>
+<th width="406">
+<Text id="747">Code module for handling documents of different formats, used during the importing and building processes</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="748">Protocol</Text>
+</th>
+<th width="406">
+<Text id="749">Set of conventions by which a Greenstone receptionist communicates with a collection server</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="750">Ranked query</Text>
+</th>
+<th width="406">
+<Text id="751">Natural-language query to an information retrieval system, for which the documents that match the query are sorted in order of relevance</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="752">Receptionist</Text>
+</th>
+<th width="406">
+<Text id="753">Program that organizes the Greenstone user interface</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="754">RTF</Text>
+</th>
+<th width="406">
+<Text id="755">Rich Text Format, a standard format for interchange of text documents</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="756">Searching</Text>
+</th>
+<th width="406">
+<Text id="757">Accessing a collection through a full-text search of its contents (or parts of contents, such as section titles)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="758">Server</Text>
+</th>
+<th width="406">
+<Text id="759">See Collection server and Web server</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="760"><i>setup.bat, setup.sh, setup.csh</i></Text>
+</th>
+<th width="406">
+<Text id="761">Script used to set up your environment to recognize the Greenstone software</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="762">Site configuration file</Text>
+</th>
+<th width="406">
+<Text id="763">File that contains specifications used to configure the Greenstone software for the site on which it is installed</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="764">Stemming</Text>
+</th>
+<th width="406">
+<Text id="765">Stripping endings off a query term to make it more general</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="766">STL</Text>
+</th>
+<th width="406">
+<Text id="767">Standard template library, a widely-available library of C++ code developed by Silicon Graphics</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="768">txt2db</Text>
+</th>
+<th width="406">
+<Text id="769">Greenstone program used at build time to create the GDBM database</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="770">Unicode</Text>
+</th>
+<th width="406">
+<Text id="771">Standard scheme for representing the character sets used in the world's languages</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="772">UNU</Text>
+</th>
+<th width="406">
+<Text id="773">The United Nations University; also used to refer to a Greenstone collection created for that organization</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="774">Web server</Text>
+</th>
+<th width="406">
+<Text id="775">Standard program that computers use to make information accessible over the World Wide Web</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="776">XML</Text>
+</th>
+<th width="406">
+<Text id="777">A standard format for structured documents and data on the web (the Greenstone Markup Language is an XML-compliant format)</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Chapter>
+<FootnoteList>
+<Footnote id="1">
+<Text id="778">This option is disabled if an element of the same name already exists.</Text>
+</Footnote>
+</FootnoteList>
+</Manual>
Index: /tags/start/gsdl-documentation/manuals/xml-source/es/Develop_es.xml
===================================================================
--- /tags/start/gsdl-documentation/manuals/xml-source/es/Develop_es.xml	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/xml-source/es/Develop_es.xml	(revision 13666)
@@ -0,0 +1,5252 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Manual>
+<Heading>
+<Text id="1">BIBLIOTECA DIGITAL GREENSTONE</Text>
+</Heading>
+<Title>
+<Text id="2">GUÃA DEL PROGRAMADOR</Text>
+</Title>
+<Author>
+<Text id="3">David Bainbridge, Dana McKay e Ian H. Witten</Text>
+</Author>
+<Affiliation>
+<Text id="4">Departamento de InformÃ¡tica<br/>Universidad de Waikato, Nueva Zelandia</Text>
+</Affiliation>
+<Text id="5">Greenstone es un conjunto de programas informÃ¡ticos destinado a la creaciÃ³n y difusiÃ³n de colecciones documentales digitales que ofrece un nuevo procedimiento para organizar la informaciÃ³n y publicarla en Internet o en forma de CD-ROM. Elaborado dentro del proyecto de Biblioteca Digital de Nueva Zelandia de la Universidad de Waikato, este producto se distribuye en colaboraciÃ³n con la UNESCO y el Proyecto de Bibliotecas sobre Aspectos Humanitarios y de Desarrollo. Es un programa informÃ¡tico de cÃ³digo fuente abierto (<i>open-source software</i>), que puede descargarse en la direcciÃ³n <i>http://greenstone.org</i> segÃºn las condiciones estipuladas en la Licencia PÃºblica General de GNU</Text>
+<Comment>
+<Text id="6">Nuestro deseo es garantizar el correcto funcionamiento de este programa, por lo que alentamos a sus usuarios a notificar cualquier problema que detecten a:Â <i>greenstone@cs.waikato.ac.nz</i></Text>
+</Comment>
+<Version>
+<Text id="7">Greenstone gsdl-2.50</Text>
+</Version>
+<Date>
+<Text id="8">Marzo de 2004</Text>
+</Date>
+<Section id="about_this_manual">
+<Title>
+<Text id="9">Acerca de este manual</Text>
+</Title>
+<Content>
+<Text id="10">En este manual se explica cÃ³mo funciona Greenstone. Se dirige a aquellos que desean personalizar las colecciones y desarrollar y mantener al dÃ­a el programa.</Text>
+<Text id="11">En la SecciÃ³n <CrossRef target="Chapter" ref="understanding_the_collection-building_process"/> se da una idea general del proceso de creaciÃ³n de colecciones, que comprende la estructura de los directorios, el formato de documento interno y el archivo de configuraciÃ³n por el que se rige la estructura de cada colecciÃ³n. En la SecciÃ³n <CrossRef target="Chapter" ref="getting_the_most_out_of_your_documents"/> se describen las partes de Greenstone que tratan los documentos de origen (y los metadatos) y se muestra cÃ³mo se accede a la informaciÃ³n mediante la interfaz de usuario. Se definen asimismo los componentes âexternosâ del programa distribuidos con Greenstone. En la SecciÃ³n <CrossRef target="Chapter" ref="the_greenstone_runtime_system"/> se explica la estructura del sistema de ejecuciÃ³n de Greenstone y se proporciona informaciÃ³n sobre el programa que permite comprender su funcionamiento y el modo de modificar el sistema para adaptarlo a las distintas necesidades. En la SecciÃ³n <CrossRef target="Chapter" ref="configuring_your_greenstone_site"/> se exponen los archivos de configuraciÃ³n, y en el ApÃ©ndice se presenta la biblioteca estÃ¡ndar de plantillas C++ (Â <i>SLT</i>).</Text>
+<Text id="12">Es posible que cuando utilice el programa Greenstone aparezcan referencias a caracterÃ­sticas que no figuran en este manual, ya que Greenstone se encuentra en constante evoluciÃ³n. Para estar al tanto de las modificaciones, inscrÃ­base a la lista de correo electrÃ³nico de Greenstone (siga las instrucciones enÂ <i>greenstone.org</i>).</Text>
+</Content>
+</Section>
+<Section id="companion_documents">
+<Title>
+<Text id="13">Conjunto de documentos</Text>
+</Title>
+<Content>
+<Text id="14">La serie completa de documentos Greenstone comprende cinco volÃºmenes:</Text>
+<BulletList>
+<Bullet>
+<Text id="15">La GuÃ­a del Instalador de la Biblioteca Digital Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="16">La GuÃ­a del Usuario de la Biblioteca Digital Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="17">La GuÃ­a del Programador de la Biblioteca Digital Greenstone (el presente documento)</Text>
+</Bullet>
+<Bullet>
+<Text id="18">La Biblioteca Digital Greenstone: del Papel a la ColecciÃ³n</Text>
+</Bullet>
+<Bullet>
+<Text id="19">La Biblioteca Digital Greenstone: uso del Organizador</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Section>
+<Section id="acknowledgements">
+<Title>
+<Text id="20">Agradecimientos</Text>
+</Title>
+<Content>
+<Text id="21">El programa Greenstone es fruto de la colaboraciÃ³n de muchas personas. Rodger McNab y Stefan Boddie son los principales arquitectos y programadores. TambiÃ©n han contribuido David Bainbridge, George Buchanan, Hong Chen, Michael Dewsnip, Katherine Don, Elke Duncker, Carl Gutwin, Geoff Holmes, Dana McKay, John McPherson, Craig Nevill-Manning, Dynal Patel, Gordon Paynter, Bernhard Pfahringer, Todd Reed, Bill Rogers, John Thompson y Stuart Yeates. Otros miembros del proyecto Biblioteca Digital de Nueva Zelanda que proporcionaron asesorÃ­a y valiosas ideas para la concepciÃ³n del sistema son: Mark Apperley, Sally Jo Cunningham, Matt Jones, Steve Jones, Te Taka Keegan, Michel Loots, Malika Mahoui, Gary Marsden, Dave Nichols y Lloyd Smith. TambiÃ©n queremos dar las gracias a todos aquellos que contribuyeron a los paquetes de programas con licencias GNU incluidos en esta distribuciÃ³n: MG, GDBM, PDFTOHTML, PERL, WGET, WVWARE y XLHTML.</Text>
+</Content>
+</Section>
+<Chapter id="understanding_the_collection-building_process">
+<Title>
+<Text id="22">FUNCIONAMIENTO DEL PROCESO DE CREACIÃN DE UNA COLECCIÃN</Text>
+</Title>
+<Content>
+<Text id="23">Los usuarios de Greenstone pueden crear colecciones utilizando el Colector, cuyo funcionamiento se explica en laÂ <i>GuÃ­a del Usuario de la Biblioteca Digital Greenstone</i>Â (SecciÃ³n 3). Este procedimiento permite crear colecciones muy fÃ¡cilmente basÃ¡ndose en los modelos ya existentes pero con un contenido nuevo. Sin embargo, el Colector no permite realmente crear colecciones con estructuras completamente nuevas. Le invita a modificar el archivo de configuraciÃ³n de la colecciÃ³n por el que se rige la estructura de la colecciÃ³n, pero usted necesita tener sÃ³lidos conocimientos de Greenstone para efectuar cambios radicales pero efectivos. En esta secciÃ³n se le indica lo que necesita saber para hacerlo. TambiÃ©n se explica la estructura de directorios de Greenstone y el formato en el que se almacenan internamente los documentos.</Text>
+<Text id="24">En este manual suponemos que usted ha instalado Greenstone en su computadora, bien con Windows o bien con Unix. Si aÃºn no lo ha hecho, deberÃ­a consultar laÂ <i>GuÃ­a de InstalaciÃ³n de la Biblioteca Digital Greenstone.</i>Â Utilizamos el nombreÂ <i>GSDLHOME</i>Â a lo largo de este manual para referirnos al directorio principal de Greenstone, que se denominaÂ <i>%GSDLHOME%</i>Â en los sistemas Windows yÂ <i>$GSDLHOME</i>Â en los sistemas Unix. Este directorio se estableciÃ³ durante el procedimiento de instalaciÃ³n.</Text>
+<Section id="building_collections_from_the_command_line">
+<Title>
+<Text id="25">CreaciÃ³n de colecciones desde la lÃ­nea de comandos</Text>
+</Title>
+<Content>
+<Text id="26">A fin de comprender mejor este proceso, empecemos por recorrer las operaciones necesarias para crear una colecciÃ³n a partir de la lÃ­nea de comandos. Por supuesto, el mÃ©todo mÃ¡s fÃ¡cil es utilizar el Colector. La colecciÃ³n que tomamos como ejemplo es la que se incluye en el CD-ROM de distribuciÃ³n del programa Greenstone, que contiene las pÃ¡ginas Web de muchas de las personas que han colaborado en el proyecto de Biblioteca Digital de Nueva Zelandia y el programa Greenstone.</Text>
+<Text id="27">En las siguientes subsecciones se explica la creaciÃ³n de una colecciÃ³n con Windows y con Unix. De hecho, las dos subsecciones son casi idÃ©nticas, sÃ³lo tiene que leer la que corresponda a su sistema. Algunas de las instrucciones le podrÃ¡n parecer misteriosas e indescifrables, pero sÃ­galas atentamente, su significado se explicarÃ¡ mÃ¡s adelante. Tras las instrucciones se resumen las diferencias entre la creaciÃ³n de una colecciÃ³n con cada uno de los sistemas.</Text>
+<Subsection id="collection_building_under_windows">
+<Title>
+<Text id="28">CreaciÃ³n de colecciones bajo Windows</Text>
+</Title>
+<Content>
+<Text id="29">El primer desafÃ­o para crear una colecciÃ³n de Greenstone a partir de la lÃ­nea de comandos en el sistema Windows es llegar al âindicador de comandosâ, el lugar en el que se teclean los comandos. Trate de buscar en el menÃºÂ <i>Inicio</i>, o en el submenÃºÂ <i>Programas</i>, una entrada comoÂ <i>indicador MS-DOS</i>,Â <i>indicador DOS</i>Â oÂ <i>indicador de comandos</i>. Si no logra encontrarla, abra la funciÃ³nÂ <i>Ejecutar</i>Â y tecleeÂ <i>command (</i>Â oÂ <i>cmd)</i>Â en la ventana de diÃ¡logo. Si todo esto falla, pida ayuda a algÃºn entendido, como su administrador de sistema.</Text>
+<Text id="30">Vaya al directorio en el que estÃ¡ instalado Greenstone. Si Greenstone estÃ¡ instalado en su ubicaciÃ³n por defecto, puede acceder tecleando:</Text>
+<CodeLine>cd âC:\Program Files\gsdlâ</CodeLine>
+<Text id="31">(Son necesarias las comillas debido a los espacios existentes enÂ <i>Program Files</i>.) A continuaciÃ³n, teclee en el indicador:</Text>
+<CodeLine>setup.bat</CodeLine>
+<Text id="32">Este archivo de ejecuciÃ³n por lotes (que puede usted leer si lo desea) indica al sistema dÃ³nde encontrar los programas Greenstone<FootnoteRef id="1"/>. Si, mÃ¡s adelante durante su sesiÃ³n interactiva en el indicador de DOS, desea volver al directorio principal de Greenstone, puede hacerlo tecleandoÂ <i>cd â%GSDLHOME%â</i>Â (una vez mÃ¡s, son necesarias las comillas debido a los espacios existentes en el nombre de archivo). Si cierra su ventana DOS y abre otra, tendrÃ¡ que volver a teclearÂ <i>setup.bat</i>.</Text>
+<Text id="33">Ahora estÃ¡ en condiciones de constituir, crear y recrear colecciones. El primer programa que examinaremos es el programa PerlÂ <i>mkcol.pl</i>, cuyo nombre corresponde a âÂ <i>make a collection</i>Â â (constituir una colecciÃ³n). En primer lugar, active el programa tecleandoÂ <i>perl -S mkcol.pl</i>Â para obtener en pantalla una descripciÃ³n de la sintaxis y una lista de argumentos. Si su entorno Windows estÃ¡ programado para asociar la aplicaciÃ³n Perl con archivos terminados enÂ <i>.pl</i>, puede expresarlo de manera mÃ¡s concisa tecleandoÂ <i>mkcol.pl</i>. Como puede comprobarlo en el mensaje que aparece, el Ãºnico argumento necesario esÂ <i>creator</i>, que se utiliza para especificar quiÃ©n ha creado la colecciÃ³n.</Text>
+<Text id="34">Utilicemos ahora este comando para crear los archivos y subdirectorios iniciales necesarios para nuestra colecciÃ³n de las pÃ¡ginas personales de los miembros del proyecto de Biblioteca Digital Greenstone. Para asignar a la colecciÃ³n el nombreÂ <i>dlpeople</i>Â (abreviaciÃ³n en inglÃ©s de âpersonas de la biblioteca digitalâ), esto fue lo que escribÃ­:</Text>
+<CodeLine>perl âS mkcol.pl âcreator me@cs.waikato.ac.nz dlpeople</CodeLine>
+<Text id="35">(oÂ <i>mkcol.pl âcreator me@cs.waikato.ac.nz dlpeople</i>, si Perl estÃ¡ asociado con la extensiÃ³n de archivosÂ <i>.pl</i>). Â¡No olvide sustituir mi direcciÃ³n de correo electrÃ³nico por la suya!</Text>
+<Text id="36">Para poder visualizar los archivos reciÃ©n creados, vaya al directorio reciÃ©n creado de la colecciÃ³n tecleando:</Text>
+<CodeLine>cd â%GSDLHOME%\collect\dlpeopleâ</CodeLine>
+<Figure id="figure_archivo_de_configuraciÃ³n_de_la_colecciÃ³n_creado_porÂ mkcol.pl">
+<Title>
+<Text id="37">Archivo de configuraciÃ³n de la colecciÃ³n creado porÂ <i>mkcol.pl</i></Text>
+</Title>
+<CodeLine>creatorÂ Â Â Â Â Â  me@cs.waikato.ac.nz</CodeLine>
+<CodeLine>maintainerÂ Â Â  me@cs.waikato.ac.nz</CodeLine>
+<CodeLine>publicÂ Â Â Â Â Â Â  true</CodeLine>
+<CodeLine>betaÂ Â Â Â Â Â Â Â Â  true</CodeLine>
+<CodeLine>indexesÂ Â Â Â Â Â Â  document:text</CodeLine>
+<CodeLine>defaultindexÂ Â  document:text </CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â  ZIPPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â  GAPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â  TEXTPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â  Â Â HTMLPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â  EMAILPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â  ArcPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â  RecPlug</CodeLine>
+<CodeLine>classifyÂ Â Â Â Â Â  AZList -metadata "Title"</CodeLine>
+<CodeLine>collectionmeta collectionnameÂ Â Â  "dlpeople"</CodeLine>
+<CodeLine>collectionmeta iconcollectionÂ Â Â  ""</CodeLine>
+<CodeLine>collectionmeta collectionextraÂ Â  ""</CodeLine>
+<CodeLine>collectionmeta .document:textÂ Â Â  "documents"</CodeLine>
+</Figure>
+<Text id="38">Puede acceder al contenido de este directorio tecleandoÂ <i>dir</i>. DeberÃ­a haber siete subdirectorios:Â <i>archives, building, etc, images, import, index</i>Â yÂ <i>perllib</i>.</Text>
+<Text id="39">Ahora debemos introducir documentos de muestra en la colecciÃ³n. Los documentos de origen para la colecciÃ³nÂ <i>dlpeople</i>Â pueden encontrarse en el directorioÂ <i>collect\dlpeople</i>Â del CD-ROM de distribuciÃ³n Greenstone. En primer lugar, inserte el CD-ROM en el lector (por ejemplo en la unidadÂ <i>D:\</i>). A continuaciÃ³n, copie el contenido del directorioÂ <i>D:\collect\dlpeople</i>Â en el directorioÂ <i>import</i>Â de la colecciÃ³nÂ <i>dlpeople</i>. Para ello, proceda de la manera siguiente:</Text>
+<Indented>
+<Text id="40">seleccione el contenido del directorioÂ <i>dlpeople</i> y arrÃ¡strelo al directorioÂ <i>import</i>Â de la colecciÃ³nÂ <i>dlpeople</i>.</Text>
+</Indented>
+<Text id="41">Como alternativa, puede teclear el comando</Text>
+<CodeLine>xcopyÂ  /sÂ  d:\collect\dlpeople\* import</CodeLine>
+<Text id="42">En el directorioÂ <i>etc</i>Â de la colecciÃ³n hay un archivo denominadoÂ <i>collect.cfg</i>. Ãbralo con el editor de texto que prefiera; uno bÃ¡sico pero que es fÃ¡cil de conseguir se llamaÂ <i>edit</i>. El resultado deberÃ­a parecerse a la Figura <CrossRef target="Figure" ref="collection_configuration_file_created_by_mkcol"/>, que muestra el archivo de configuraciÃ³n de la colecciÃ³n creado mediante el comandoÂ <i>perlÂ  âS mkcol.pl âcreatorme@cs.waikato.ac.nz dlpeople</i>.</Text>
+<Text id="43">Ahora puede âimportarâ la colecciÃ³n. Se trata del proceso por el que se traen los documentos al sistema Greenstone, normalizando el formato de los documentos, el modo en que se especifican los metadatos y la estructura de los archivos en que se almacenan los documentos. TecleeÂ <i>perl âS import.pl</i>Â en el indicador para obtener una lista de todas las opciones del programa de importaciÃ³n. Para simplificar, limÃ­tese al comando bÃ¡sico</Text>
+<CodeLine>perl âS import.pl dlpeople</CodeLine>
+<Text id="44">No se preocupe por el texto que desfila rÃ¡pidamente en la pantalla: es sÃ³lo un informe de la progresiÃ³n de la importaciÃ³n. Tenga en cuenta que importar esta colecciÃ³n lleva unos cinco minutos en una computadora de 1 GHz y, por consiguiente, mÃ¡s tiempo en mÃ¡quinas mÃ¡s lentas. ObsÃ©rvese que no es necesario encontrarse en los directoriosÂ <i>collect</i>Â oÂ <i>dlpeople</i>Â cuando se selecciona este comando, porque ya se ha introducido la variable GSDLHOME y el programa Greenstone puede encontrar todos los archivos necesarios.</Text>
+<Text id="45">Ahora vamos a introducir algunas modificaciones en el archivo de configuraciÃ³n de la colecciÃ³n para personalizar su apariencia. En primer lugar, demos un nombre a la colecciÃ³n. SerÃ¡ el que utilicen los navegadores Web como tÃ­tulo de pÃ¡gina de la portada de la colecciÃ³n, y servirÃ¡ como icono de la colecciÃ³n si no se proporciona ninguna otra imagen. Sustituya la lÃ­nea que diceÂ <i>collectionmeta collectionname âdlpeopleâ</i>Â por algo comoÂ <i>collectionmeta collectionname âLos miembros del proyecto NZDLâ.</i></Text>
+<Text id="46">AÃ±ada una descripciÃ³n de su colecciÃ³n entre las comillas de la lÃ­neaÂ <i>collectionmeta collectionextra</i>Â ââ, la cual servirÃ¡ como texto delÂ <i>Acerca de esta colecciÃ³n</i>Â en la pÃ¡gina principal de la colecciÃ³n. Yo escribÃ­ âEsta colecciÃ³n comprende las pÃ¡ginas personales de algunas de las personas que han colaborado en el proyecto NZDLâ. Es importante escribir este texto en el editor en una sola lÃ­nea: si el cursor llega al margen derecho de la ventana del editor no pulse la tecla âIntroâ aunque tenga que aÃ±adir mÃ¡s texto; siga escribiendo de continuo, de lo contrario el archivo de configuraciÃ³n no podrÃ¡ ser analizado correctamente. Si desea que su colecciÃ³n pueda utilizarse con diferentes interfaces de lenguas, existe una opciÃ³n para que este texto aparezca de manera diferente segÃºn la interfaz lingÃŒÃ­stica elegida, que se describe mÃ¡s adelante en la SecciÃ³n <CrossRef target="Section" ref="import_and_build_processes"/>.</Text>
+<Text id="47">Puede utilizar cualquier imagen que pueda visualizarse en un navegador como icono de la colecciÃ³n; la imagen que yo creÃ© se muestra en la Figura <CrossRef target="Figure" ref="collection_icon"/>. Escriba la ubicaciÃ³n de la imagen entre las comillas de la lÃ­neaÂ <i>collectionmeta iconcollection ââ</i>Â en el archivo de configuraciÃ³n. Como abreviaciÃ³n, y para contribuir a la portabilidad, puede utilizarse <i>_httpprefix_</i>Â como inicio de una direcciÃ³n URL que remite a una imagen situada en la zona de archivos de Greenstone. Por ejemplo, puede usted escribir: _Â <i>httpprefix_/collect/dlpeople/images/icon.gif</i>Â si ha introducido una imagen adecuada en el directorioÂ <i>images</i>Â de la colecciÃ³n (Â <i>collect\dlpeople\images</i>Â en nuestro ejemplo).</Text>
+<Text id="48">Guarde el archivo de configuraciÃ³n de la colecciÃ³n y ciÃ©rrelo; no lo necesitarÃ¡ de nuevo en este manual de instrucciones.</Text>
+<Text id="49">La siguiente fase consiste en âcrearâ la colecciÃ³n, es decir, elaborar todos los Ã­ndices y archivos que permiten su funcionamiento. TecleeÂ <i>perl âS buildcol.pl</i>Â en el indicador de comandos para acceder a una lista de opciones de creaciÃ³n de colecciÃ³n, que se explican mÃ¡s detalladamente en la SecciÃ³n <CrossRef target="Section" ref="import_and_build_processes"/>. Por ahora, cÃ­Ã±ase a los valores por defecto y teclee:</Text>
+<CodeLine>perl âS buildcol.pl dlpeople</CodeLine>
+<Text id="50">Una vez mÃ¡s, no se preocupe por los textos de âinforme de progresiÃ³nâ que desfilan por la pantalla.</Text>
+<Text id="51">Active la colecciÃ³n como sigue: </Text>
+<Text id="52">seleccione el contenido del directorioÂ <i>building</i>Â de la colecciÃ³nÂ <i>dlpeople</i> y arrÃ¡strelo hasta el directorioÂ <i>index</i>.</Text>
+<Text id="53">Como alternativa, puede suprimir el directorioÂ <i>index</i>Â (y todo su contenido) con el comando:</Text>
+<CodeLine>rd /s indexÂ Â Â Â Â Â Â Â  # con Windows NT/2000</CodeLine>
+<CodeLine>deltree /Y indexÂ Â Â  # con Windows 95/98</CodeLine>
+<Text id="54">y luego cambiar el nombre del directorioÂ <i>building</i>Â por el deÂ <i>index</i>Â tecleando:</Text>
+<CodeLine>ren building index</CodeLine>
+<Text id="55">Por Ãºltimo, teclee:</Text>
+<CodeLine>mkdir building </CodeLine>
+<Text id="56">en preparaciÃ³n para cualquier recreaciÃ³n futura. Es importante que estos comandos se efectÃºen en el directorio correcto (a diferencia de los comandosÂ <i>mkcol.pl</i>,Â <i>import.pl</i>Â yÂ <i>buildcol.pl</i>Â de Greenstone). Si el directorio que se encuentra en uso no esÂ <i>dlpeople</i>, tecleeÂ <i>cd â%GSDLHOME%\collect\dlpeopleâ</i>Â antes de proceder a la secuencia de operacionesÂ <i>rd</i>,Â <i>ren</i>Â yÂ <i>mkdir</i>Â antes expuestas.</Text>
+<Text id="57">DeberÃ­a poder acceder a la colecciÃ³n reciÃ©n creada desde la pÃ¡gina principal de Greenstone. TendrÃ¡ que volver a cargar la pÃ¡gina si ya la habÃ­a abierto en su navegador, o tal vez incluso tenga que cerrar el navegador y arrancarlo de nuevo (para evitar problemas de âÂ <i>cache</i>Â â). En cambio, si estÃ¡ utilizando la versiÃ³n âBiblioteca Localâ de Greenstone tendrÃ¡ que volver a arrancar el programaÂ <i>library</i>. Para visualizar la nueva colecciÃ³n, haga clic en la imagen. El resultado deberÃ­a parecerse a la Figura <CrossRef target="Figure" ref="about_page_for_the_new_collection"/>.</Text>
+<Figure id="collection_icon">
+<Title>
+<Text id="58">Icono de la colecciÃ³n</Text>
+</Title>
+<File width="150" height="80" url="images/Dev_Fig_2.png"/>
+</Figure>
+<Text id="59">En resumen, los comandos que se han de teclear para general la colecciÃ³nÂ <i>dlpeople</i>Â son los siguientes:</Text>
+<CodeLine>cd âC:\Program Files\gsdlâ # se supone la ubicaciÃ³n por defecto</CodeLine>
+<CodeLine>setup.bat</CodeLine>
+<CodeLine>perl âS mkcol.pl âcreator me@cs.waikato.ac.nz dlpeople</CodeLine>
+<CodeLine>cd â%GSDLHOME%\collect\dlpeopleâ</CodeLine>
+<CodeLine>xcopy /s d:\collect\dlpeople\* import # se supone la unidad D</CodeLine>
+<CodeLine>perl âS import.pl dlpeople</CodeLine>
+<CodeLine>perl âS buildcol.pl dlpeople</CodeLine>
+<CodeLine>rdÂ  /s indexÂ Â Â Â Â Â Â Â Â Â Â Â Â Â  # con Windows NT/2000</CodeLine>
+<CodeLine>deltreeÂ  /Y index Â Â Â Â Â Â Â Â  # con Windows 95/98</CodeLine>
+<CodeLine>ren building index</CodeLine>
+<CodeLine>mkdir building</CodeLine>
+</Content>
+</Subsection>
+<Subsection id="collection_building_under_unix">
+<Title>
+<Text id="60">CreaciÃ³n de colecciones bajo Unix</Text>
+</Title>
+<Content>
+<Text id="61">En primer lugar vaya al directorio donde estÃ¡ instalado Greenstone. Por ejemplo, si Greenstone estÃ¡ instalado en vuestro directorio de inicio de sesiÃ³n, con su nombre por defecto, puede dirigirse allÃ­ tecleando</Text>
+<CodeLine>cd ~/gsdl</CodeLine>
+<Text id="62">Luego en el indicador, teclee</Text>
+<CodeLine>source setup.bashÂ Â  # si estÃ¡ utilizando el shell BASH</CodeLine>
+<CodeLine>source setup.cshÂ Â Â  # si estÃ¡ utilizando el shell C</CodeLine>
+<Text id="63">Estos archivos de ejecuciÃ³n por lotes (que puede usted leer si lo desea) indican al sistema dÃ³nde buscar los programas Greenstone. Si mÃ¡s adelante, durante su sesiÃ³n de introducciÃ³n de lÃ­neas de comando en Greenstone, desea volver al directorio principal de Greenstone, puede hacerlo escribiendoÂ <i>cd $GSDLHOME</i>.</Text>
+<Text id="64">Si no estÃ¡ seguro del tipo de intÃ©rprete de comandos (<i>shell</i>) que estÃ¡ utilizando, tecleeÂ <i>echo $0</i>Â en su indicador de lÃ­nea de comandos y obtendrÃ¡ la informaciÃ³n buscada. Si utiliza un intÃ©rprete de comandos diferente, contacte a su administrador de sistema para que le asesore.</Text>
+<Text id="65">Una vez localizado el archivo de instalaciÃ³n adecuado, estamos en condiciones de constituir, crear y recrear colecciones. El primer programa que examinaremos es el programa PerlÂ <i>mkcol.pl</i>, cuyo nombre corresponde a âmake a collectionâ (constituir una colecciÃ³n). En primer lugar, active el programa escribiendo sÃ³loÂ <i>mkcol.pl</i>Â para obtener en pantalla una descripciÃ³n de la sintaxis y una lista de argumentos. Como puede comprobarlo en el mensaje que aparece, el Ãºnico argumento necesario esÂ <i>creator</i>, que se utiliza para especificar quiÃ©n ha creado la colecciÃ³n.</Text>
+<Figure id="about_page_for_the_new_collection">
+<Title>
+<Text id="66">PÃ¡gina âAcerca deâ de la nueva colecciÃ³n</Text>
+</Title>
+<File width="604" height="415" url="images/Dev_Fig_3.png"/>
+</Figure>
+<Text id="67">Utilicemos ahora este comando para crear los archivos y subdirectorios iniciales necesarios para nuestra colecciÃ³n de las pÃ¡ginas personales de los miembros del proyecto de Biblioteca Digital Greenstone. Para asignar a la colecciÃ³n el nombreÂ <i>dlpeople</i>, esto fue lo que escribÃ­:</Text>
+<CodeLine>mkcol.pl âcreatorme@cs.waikato.ac.nzdlpeople</CodeLine>
+<Text id="68">Â¡No olvide sustituir mi direcciÃ³n de correo electrÃ³nico por la suya!</Text>
+<Text id="69">Para poder visualizar los archivos reciÃ©n creados, vaya al directorio reciÃ©n creado de la colecciÃ³n tecleando:</Text>
+<CodeLine>cd $GSDLHOME/collect/dlpeople</CodeLine>
+<Text id="70">Puede acceder al contenido de este directorio tecleandoÂ <i>ls</i>. DeberÃ­a haber siete subdirectorios:Â <i>archives, building, etc, images, import, index</i>Â yÂ <i>perllib</i>.</Text>
+<Text id="71">Ahora debemos introducir documentos de muestra en la colecciÃ³n. Los documentos de origen para la colecciÃ³nÂ <i>dlpeople</i>Â pueden encontrarse en el directorioÂ <i>collect\dlpeople</i>Â del CD-ROM de distribuciÃ³n Greenstone. Para leer la informaciÃ³n de un CD-ROM con Linux, inserte el disco en el lector y teclee:</Text>
+<CodeLine>mount /cdrom</CodeLine>
+<Text id="72">en el indicador (este comando puede cambiar de un sistema a otro). Una vez montado, el CD-ROM puede usarse como cualquier otro directorio, por consiguiente puede teclearÂ <i>ls /cdrom/collect</i>. Esto deberÃ­a darle acceso a un directorio denominadoÂ <i>dlpeople</i>Â en el CD-ROM.</Text>
+<Text id="73">A continuaciÃ³n, copie el contenido del directorioÂ <i>/cdrom/collect/dlpeople</i>Â en el directorioÂ <i>GSDLHOME/collect/dlpeople/import</i>. Para ello, teclee el comando:</Text>
+<CodeLine>cp âr /cdrom/collect/dlpeople/*Â  import/</CodeLine>
+<Text id="74">Luego teclee:</Text>
+<CodeLine>umount /cdrom</CodeLine>
+<Text id="75">para cerrar la unidad del CD-ROM.</Text>
+<Text id="76">En el directorioÂ <i>etc</i>Â de la colecciÃ³n hay un archivo denominadoÂ <i>collect.cfg</i>. Ãbralo con el editor de texto que prefiera;Â <i>emacs</i>Â es un editor muy utilizado en Linux. El resultado deberÃ­a parecerse a la Figura <CrossRef target="Figure" ref="collection_configuration_file_created_by_mkcol"/>, que muestra el archivo de configuraciÃ³n de la colecciÃ³n creado mediante el comandoÂ <i>mkcol.pl âcreatorme@cs.waikato.ac.nz dlpeople</i>.</Text>
+<Text id="77">Ahora puede âimportarâ la colecciÃ³n. Se trata del proceso por el que se traen los documentos al sistema Greenstone, normalizando el formato de los documentos, el modo en que se especifican los metadatos y la estructura de los archivos en que se almacenan los documentos. TecleeÂ <i>import.pl</i>Â en el indicador para obtener una lista de todas las opciones del programa de importaciÃ³n. Para simplificar, limÃ­tese al comando bÃ¡sico</Text>
+<CodeLine>import.pl dlpeople</CodeLine>
+<Text id="78">No se preocupe por el texto que desfila rÃ¡pidamente en la pantalla: es sÃ³lo un informe de la progresiÃ³n de la importaciÃ³n. Tenga en cuenta que importar esta colecciÃ³n lleva unos cinco minutos en una computadora de 1 GHz y, por consiguiente, mÃ¡s tiempo en mÃ¡quinas mÃ¡s lentas. ObsÃ©rvese que no es necesario encontrarse en los directoriosÂ <i>collect</i>Â oÂ <i>dlpeople</i>Â cuando se selecciona este comando, porque ya se ha introducido la variable GSDLHOME y el programa Greenstone puede encontrar todos los archivos necesarios.</Text>
+<Text id="79">Ahora vamos a introducir algunas modificaciones en el archivo de configuraciÃ³n de la colecciÃ³n para personalizar su apariencia. En primer lugar, demos un nombre a la colecciÃ³n. SerÃ¡ el que utilicen los navegadores Web como tÃ­tulo de pÃ¡gina de la portada de la colecciÃ³n, y servirÃ¡ como icono de la colecciÃ³n si no se proporciona ninguna otra imagen. Sustituya la lÃ­nea que diceÂ <i>collectionmeta collectionname âdlpeopleâ</i>Â por algo comoÂ <i>collectionmeta collectionname âLos miembro+s del proyecto NZDLâ.</i></Text>
+<Text id="80">AÃ±ada una descripciÃ³n de su colecciÃ³n entre las comillas de la lÃ­neaÂ <i>collectionmeta collectionextra</i>Â ââ, la cual servirÃ¡ como texto delÂ <i>Acerca de esta colecciÃ³n</i>Â en la pÃ¡gina principal de la colecciÃ³n. Yo escribÃ­ âEsta colecciÃ³n comprende las pÃ¡ginas personales de algunas de las personas que han colaborado en el proyecto NZDLâ. Es importante escribir este texto en el editor en una sola lÃ­nea: si el cursor llega al margen derecho de la ventana del editor no pulse la tecla âIntroâ aunque tenga que aÃ±adir mÃ¡s texto; siga escribiendo de continuo, de lo contrario el archivo de configuraciÃ³n no podrÃ¡ ser analizado correctamente. Si desea que su colecciÃ³n pueda utilizarse con diferentes interfaces de lenguas, existe una opciÃ³n para que este texto aparezca de manera diferente segÃºn la interfaz lingÃŒÃ­stica elegida, que se describe mÃ¡s adelante en la SecciÃ³n <CrossRef target="Section" ref="import_and_build_processes"/>.</Text>
+<Text id="81">Puede utilizar cualquier imagen que pueda visualizarse en un navegador como icono de la colecciÃ³n; la imagen que yo creÃ© se muestra en la Figura <CrossRef target="Figure" ref="collection_icon"/>. Escriba la ubicaciÃ³n de la imagen entre las comillas de la lÃ­neaÂ <i>collectionmeta iconcollection ââ</i>Â en el archivo de configuraciÃ³n. Como abreviaciÃ³n, y para contribuir a la portabilidad, puede utilizarse _Â <i>httpprefix_</i>Â como inicio de una direcciÃ³n URL que remite a una imagen situada en la zona de archivos de Greenstone. Por ejemplo, puede usted escribir: _Â <i>httpprefix_/collect/dlpeople/images/icon.gif</i>Â si ha introducido una imagen adecuada en el directorioÂ <i>images</i>Â de la colecciÃ³n (Â <i>collect\dlpeople\images</i>Â en nuestro ejemplo).</Text>
+<Text id="82">Guarde el archivo de configuraciÃ³n de la colecciÃ³n y ciÃ©rrelo; no lo necesitarÃ¡ de nuevo en este manual de instrucciones.</Text>
+<Text id="83">La siguiente fase consiste en âcrearâ la colecciÃ³n, es decir, elaborar todos los Ã­ndices y archivos que permiten su funcionamiento. TecleeÂ <i>buildcol.pl</i>Â en el indicador de comandos para acceder a una lista de opciones de creaciÃ³n de colecciÃ³n, que se explican mÃ¡s detalladamente en la SecciÃ³n <CrossRef target="Section" ref="import_and_build_processes"/>. Por ahora, cÃ­Ã±ase a los valores por defecto por defecto y teclee:</Text>
+<CodeLine>buildcol.pl dlpeople</CodeLine>
+<Text id="84">Una vez mÃ¡s, no se preocupe por los textos de âinforme de progresiÃ³nâ que desfilan por la pantalla.</Text>
+<Text id="85">Active la colecciÃ³n trasladando al directorioÂ <i>index</i>Â todos los datos que acaba de introducir en el directorioÂ <i>building</i>Â de la colecciÃ³n. Si ya ha creado esta colecciÃ³n anteriormente, en primer lugar suprima el antiguo Ã­ndice tecleando:</Text>
+<CodeLine>rm âr index/*</CodeLine>
+<Text id="86">(suponiendo que se encuentre en el directorioÂ <i>dlpeople</i>) en el indicador. A continuaciÃ³n teclee:</Text>
+<CodeLine>mv building/*Â  index/</CodeLine>
+<Table id="collection-building_differences_between_windows_and_linux">
+<Title>
+<Text id="87">Diferencias entre Windows y Linux para la creaciÃ³n de colecciones</Text>
+</Title>
+<TableContent>
+<tr>
+<th>
+<Text id="88"><b>Windows</b></Text>
+</th>
+<th>
+<Text id="89"><b>Linux</b></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="90">EjecutarÂ <i>setup.bat</i>Â para poder acceder a los programas Greenstone</Text>
+</th>
+<th>
+<Text id="91">CargarÂ <i>setup.bash</i>Â oÂ <i>setup.csh</i>Â para poder acceder a los programas</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="92">Copiar los archivos del CD-ROM utilizando el administrador grÃ¡fico de archivos o los comandos de Windows</Text>
+</th>
+<th>
+<Text id="93">Copiar los archivos del CD-ROM utilizandoÂ <i>mount</i>Â y los comandos de Unix</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="94">El directorioÂ <i>index</i>Â de la antigua colecciÃ³n se sustituye tecleandoÂ <i>rd /s index</i>, luegoÂ <i>ren building index</i>Â seguido deÂ <i>mkdir building</i>, o utilizando el administrador de archivos grÃ¡ficos.</Text>
+</th>
+<th>Â </th>
+<th>
+<Text id="95">El directorioÂ <i>index</i>Â de la antigua colecciÃ³n se sustituye tecleandoÂ <i>rm âr index/</i>Â * luegoÂ <i>mv building/* index</i></Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="96">DeberÃ­a poder acceder a la colecciÃ³n reciÃ©n creada desde la pÃ¡gina principal de Greenstone. TendrÃ¡ que volver a cargar la pÃ¡gina si ya la habÃ­a abierto en su navegador, o tal vez incluso tenga que cerrar el navegador y arrancarlo de nuevo (para evitar problemas de âÂ <i>cache</i>Â â). Para visualizar la nueva colecciÃ³n, haga clic en la imagen. El resultado deberÃ­a parecerse a la Figura <CrossRef target="Figure" ref="about_page_for_the_new_collection"/>.</Text>
+<Text id="97">En resumen, los comandos que se han de teclear para generar la colecciÃ³nÂ <i>dlpeople</i>Â son los siguientes:</Text>
+<CodeLine>cd ~/gsdlÂ Â Â Â Â Â Â Â Â Â  # suponiendo que Greenstone estÃ¡ por defecto</CodeLine>
+<CodeLine># en vuestro directorio de inicio de sesiÃ³n</CodeLine>
+<CodeLine>source setup.bashÂ Â  # si estÃ¡ utilizando el shell BASH</CodeLine>
+<CodeLine>source setup.cshÂ Â Â  # si estÃ¡ utilizando el shell C</CodeLine>
+<CodeLine>mkcol.pl âcreatorme@cs.waikato.ac.nzdlpeople</CodeLine>
+<CodeLine>cd $GSDLHOME/collect/dlpeople</CodeLine>
+<CodeLine>mount /cdromÂ Â Â Â Â Â Â  # suponiendo que el CD-ROM se asigna ahÃ­</CodeLine>
+<CodeLine>cp âr /cdrom/collect/dlpeople/ * import/</CodeLine>
+<CodeLine>umount /cdrom</CodeLine>
+<CodeLine>import.pl dlpeople</CodeLine>
+<CodeLine>buildcol.pl dlpeople</CodeLine>
+<CodeLine>rm âr index/*</CodeLine>
+<CodeLine>mv building/* index</CodeLine>
+</Content>
+</Subsection>
+<Subsection id="differences_between_windows_and_unix">
+<Title>
+<Text id="98">Diferencias entre Windows y Unix</Text>
+</Title>
+<Content>
+<Text id="99">El proceso de creaciÃ³n de una colecciÃ³n con Unix es muy parecido al de Windows, pero hay algunas pequeÃ±as diferencias que se resumen en el Cuadro <CrossRef target="Table" ref="collection-building_differences_between_windows_and_linux"/>.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="greenstone_directories">
+<Title>
+<Text id="100">Directorios de Greenstone</Text>
+</Title>
+<Content>
+<Text id="101">En la Figura <CrossRef target="Figure" ref="structure_of_the_gsdlhome_directory"/> se muestra la estructura del directorioÂ <i>GSDLHOME</i>. En el Cuadro <CrossRef target="Table" ref="where_to_find_information_about_directories"/> se presenta una breve descripciÃ³n del contenido de cada uno de los directorios que aparecen en el diagrama. En una secciÃ³n ulterior del manual se detallan mÃ¡s algunos directorios; utilice la guÃ­a de secciones del Cuadro <CrossRef target="Table" ref="where_to_find_information_about_directories"/> para saber dÃ³nde hallar mÃ¡s informaciÃ³n.</Text>
+<Figure id="structure_of_the_gsdlhome_directory">
+<Title>
+<Text id="102">Estructura del directorio GSDLHOME</Text>
+</Title>
+<File width="603" height="197" url="images/Dev_Fig_4.png"/>
+</Figure>
+<Table id="where_to_find_information_about_directories">
+<Title>
+<Text id="103">DÃ³nde encontrar informaciÃ³n sobre los directorios</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="@width"/>
+<th>
+<Text id="104"><b>Contenido</b></Text>
+</th>
+<th>
+<Text id="105"><b>SecciÃ³n</b></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="106"><i>bin</i></Text>
+</th>
+<th>
+<Text id="107">CÃ³digo ejecutable, que incluye binarios en el directorio que lleva el nombre de su sistema operativo.</Text>
+</th>
+<th>
+<Text id="108">-</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="109"><i>bin/script</i></Text>
+</th>
+<th>
+<Text id="110">Guiones Perl utilizados para crear y constituir colecciones (por ejemplo,Â <i>import.pl</i>Â yÂ <i>buildcol.pl</i>). Para obtener una descripciÃ³n de cualquiera de estos programas, teclee su nombre en el indicador de comandos.</Text>
+</th>
+<th>
+<Text id="111">1.3</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="112"><i>perllib</i></Text>
+</th>
+<th>
+<Text id="113">MÃ³dulos Perl utilizados durante la importaciÃ³n y la creaciÃ³n (conectores, por ejemplo).</Text>
+</th>
+<th>
+<Text id="114">2.1</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="115"><i>perllib/plugins</i></Text>
+</th>
+<th>
+<Text id="116">CÃ³digo Perl para los conectores de tratamiento de documentos.</Text>
+</th>
+<th>
+<Text id="117">2.1</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="118"><i>perllib/classify</i></Text>
+</th>
+<th>
+<Text id="119">CÃ³digo Perl para clasificadores (por ejemplo, el cÃ³digo AZList que elabora una lista de documentos basada en el orden alfabÃ©tico de un atributo).</Text>
+</th>
+<th>
+<Text id="120">2.2</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="121"><i>cgi-bin</i></Text>
+</th>
+<th>
+<Text id="122">Todos los guiones CGI de Greenstone que se trasladan al directorioÂ <i>cgi-bin</i>Â del sistema.</Text>
+</th>
+<th>
+<Text id="123">-</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="124"><i>tmp</i></Text>
+</th>
+<th>
+<Text id="125">Directorio utilizado por Greenstone para almacenar archivos temporales.</Text>
+</th>
+<th>
+<Text id="126">-</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="127"><i>etc</i></Text>
+</th>
+<th>
+<Text id="128">Archivos de configuraciÃ³n, registros de inicializaciÃ³n y de errores, bases de datos de autorizaciÃ³n de usuarios.</Text>
+</th>
+<th>
+<Text id="129">-</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="130"><i>src</i></Text>
+</th>
+<th>
+<Text id="131">CÃ³digo C++ utilizado para suministrar colecciones a travÃ©s de un servidor Web.</Text>
+</th>
+<th>
+<Text id="132">3</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="133"><i>src/colservr</i></Text>
+</th>
+<th>
+<Text id="134">CÃ³digo C++ para suministrar colecciones, responder a consultas y demÃ¡s.</Text>
+</th>
+<th>
+<Text id="135"><CrossRef target="Section" ref="protocol"/></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="136"><i>src/recpt</i></Text>
+</th>
+<th>
+<Text id="137">CÃ³digo C++ para obtener consultas desde la interfaz de usuario y formatear las respuestas para esta interfaz.</Text>
+</th>
+<th>
+<Text id="138">3.8</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="139"><i>packages</i></Text>
+</th>
+<th>
+<Text id="140">CÃ³digos fuente para paquetes de programas informÃ¡ticos ajenos a Greenstone pero utilizados por Ã©ste.</Text>
+</th>
+<th>
+<Text id="141">2.5</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="142"><i>packages/mg</i></Text>
+</th>
+<th>
+<Text id="143">El cÃ³digo fuente de MG, programa de compresiÃ³n e indizaciÃ³n utilizado por Greenstone.</Text>
+</th>
+<th>
+<Text id="144">2.5</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="145"><i>mappings</i></Text>
+</th>
+<th>
+<Text id="146">Cuadros de correspondencia Unicode (por ejemplo para los caracteres chinos GB).</Text>
+</th>
+<th>
+<Text id="147">-</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="148"><i>macros</i></Text>
+</th>
+<th>
+<Text id="149">Los archivos de macros utilizados para la interfaz de usuario.</Text>
+</th>
+<th>
+<Text id="150">2.4</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="151"><i>collect</i></Text>
+</th>
+<th>
+<Text id="152">Colecciones que se suministran a partir de este ejemplar de Greenstone.</Text>
+</th>
+<th>
+<Text id="153">1.1 </Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="154"><i>lib</i></Text>
+</th>
+<th>
+<Text id="155">CÃ³digo fuente C++ utilizado por el servidor de colecciÃ³n y por el recepcionista. </Text>
+</th>
+<th>
+<Text id="156">3.1</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="157"><i>images</i></Text>
+</th>
+<th>
+<Text id="158">ImÃ¡genes utilizadas en la interfaz de usuario.</Text>
+</th>
+<th>
+<Text id="159">-</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="160"><i>docs</i></Text>
+</th>
+<th>
+<Text id="161">DocumentaciÃ³n.</Text>
+</th>
+<th>
+<Text id="162">-</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Section>
+<Section id="import_and_build_processes">
+<Title>
+<Text id="163">Procesos de importaciÃ³n y de creaciÃ³n</Text>
+</Title>
+<Content>
+<Text id="164">En el proceso de creaciÃ³n de la colecciÃ³n explicado en la SecciÃ³n <CrossRef target="Section" ref="building_collections_from_the_command_line"/> se utiliza un comando,Â <i>import.pl</i>, para importar los documentos y otro,Â <i>buildcol.pl</i>, para crear la colecciÃ³n. En esta secciÃ³n ampliamos la informaciÃ³n sobre las funciones y opciones de estos programas. Empleamos la variableÂ <i>nombre_col</i>Â para referirnos a la colecciÃ³n en proceso de creaciÃ³n o importaciÃ³n.</Text>
+<Text id="165">Los procesos de importaciÃ³n y creaciÃ³n guardan muchas semejanzas y, por consiguiente, muchas de sus opciones, expuestas en el Cuadro <CrossRef target="Table" ref="options_for_the_import_and_build_processes"/>, son iguales. (Recuerde que para ver las opciones de cualquier guiÃ³n de Greenstone sÃ³lo tiene que escribir su nombre sin opciones en el indicador de comandos).</Text>
+<Table id="options_for_the_import_and_build_processes">
+<Title>
+<Text id="166">Opciones de los procesos de importaciÃ³n y de creaciÃ³n</Text>
+</Title>
+<TableContent>
+<tr>
+<th>Â </th>
+<th>
+<Text id="167"><b>Argumento</b></Text>
+</th>
+<th>
+<Text id="168"><b>FunciÃ³n</b></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="169"><i>-verbosity</i></Text>
+</th>
+<th>
+<Text id="170">NÃºmero 0-3</Text>
+</th>
+<th>
+<Text id="171">Controla la cantidad de informaciÃ³n sobre el proceso que se visualiza como error estÃ¡ndar: 0 significa un poco, 3 mucho.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="172"><i>-archivedir</i></Text>
+</th>
+<th>
+<Text id="173">Nombre de directorio</Text>
+</th>
+<th>
+<Text id="174">Especifica dÃ³nde estÃ¡n almacenados los archivos en el Format de Archivo Greenstone (<i>Greenstone Archive Files</i>), esto es, dÃ³nde los guardaÂ <i>import.pl</i>Â y donde los encuentraÂ <i>buildcol.pl</i>. El valor por defecto esÂ <i>GSDLHOME/collect/nombre_col/archives.</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="175"><i>-maxdocs</i></Text>
+</th>
+<th>
+<Text id="176">NÃºmero &gt;0</Text>
+</th>
+<th>
+<Text id="177">Indica el nÃºmero mÃ¡ximo de documentos que se pueden importar o crear. Esta opciÃ³n es Ãºtil cuando se prueba el archivo de configuraciÃ³n de una nueva colecciÃ³n o se ensayan nuevos conectores.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="178"><i>-collectdir</i></Text>
+</th>
+<th>
+<Text id="179">Nombre de directorio</Text>
+</th>
+<th>
+<Text id="180">Especifica dÃ³nde se puede encontrar la colecciÃ³n. El valor por defecto esÂ <i>GSDLHOME/collect</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="181"><i>-out</i></Text>
+</th>
+<th>
+<Text id="182">Nombre de archivo</Text>
+</th>
+<th>
+<Text id="183">Especifica un archivo en el que se escriben todos los mensajes producidos, que por defecto se visualizan como error estÃ¡ndar (esto es, en la pantalla). OpciÃ³n Ãºtil cuando se trabaja con niveles de depuraciÃ³n.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="184"><i>-keepold</i></Text>
+</th>
+<th>
+<Text id="185">Ninguno</Text>
+</th>
+<th>
+<Text id="186">No suprime el resultado de la operaciÃ³n de importaciÃ³n o creaciÃ³n anterior. En caso de importaciÃ³n, no suprime el contenido del directorioÂ <i>archives</i>Â ; en caso de creaciÃ³n, no suprime el contenido del directorioÂ <i>building</i>.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="187"><i>-debug</i></Text>
+</th>
+<th>
+<Text id="188">Ninguno</Text>
+</th>
+<th>
+<Text id="189">Muestra la salida del conector en la salida estÃ¡ndar.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Subsection id="subsection_el_proceso_de_importaciÃ³n">
+<Title>
+<Text id="190">El proceso de importaciÃ³n</Text>
+</Title>
+<Content>
+<Text id="191">La principal funciÃ³n del proceso de importaciÃ³n es pasar los documentos de su formato original al Formato de Archivo Greenstone (<i>Greenstone Archive Format</i>), asÃ­ como crear un archivo de resumen (denominadoÂ <i>archives.inf</i>) que se utilizarÃ¡ para crear la colecciÃ³n.Â <i>import.pl</i>Â necesita saber quÃ© conectores se han de utilizar y dÃ³nde encontrar los archivos de los documentos originales. En el Cuadro <CrossRef target="Table" ref="options_for_the_import_and_build_processes"/> se muestran las opciones comunes de los procesos de importaciÃ³n y de creaciÃ³n; en el Cuadro <CrossRef target="Table" ref="additional_options_for_the_import_process"/> se presentan las opciones adicionales aplicables sÃ³lo al proceso de importaciÃ³n. La opciÃ³nÂ <i>OIDtype</i>Â requiere ciertas explicaciones. Cada documento tiene un identificador de objeto asociado (Â <i>Object Identifier</i>) u OID. La mejor manera de calcularlo es que el programa desmenuce el contenido del documento (Â <i>hash</i>). Sin embargo, este procedimiento es lento, por ello se propone una alternativa mÃ¡s sencilla (Â <i>incremental</i>) que simplemente numera los documentos secuencialmente en el orden de importaciÃ³n (mÃ©todo por incremento gradual). Puede usted utilizar el mÃ©todoÂ <i>incremental</i>Â para ir mÃ¡s rÃ¡pido, pero debe emplearÂ <i>hash</i>Â si quiere aÃ±adir documentos a su colecciÃ³n en una fecha ulterior (sin volver a importar).</Text>
+<Table id="additional_options_for_the_import_process">
+<Title>
+<Text id="192">Opciones adicionales del proceso de importaciÃ³n</Text>
+</Title>
+<TableContent>
+<tr>
+<th>Â </th>
+<th>
+<Text id="193"><b>Argumento</b></Text>
+</th>
+<th>
+<Text id="194"><b>FunciÃ³n</b></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="195"><i>-importdir</i></Text>
+</th>
+<th>
+<Text id="196">Nombre de directorio</Text>
+</th>
+<th>
+<Text id="197">Indica dÃ³nde se puede encontrar el material que se ha de importar. El valor por defecto esÂ <i>GSDLHOME/collect/nombre_col/archives.</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="198"><i>-removeold</i></Text>
+</th>
+<th>
+<Text id="199">Ninguno</Text>
+</th>
+<th>
+<Text id="200">Suprime el contenido del directorioÂ <i>archives</i>Â antes de importar.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="201"><i>-gzip</i></Text>
+</th>
+<th>
+<Text id="202">Ninguno</Text>
+</th>
+<th>
+<Text id="203">Comprime los documentos de archivos de Greenstone producidos porÂ <i>import</i>Â (ZIPPlug debe formar parte de la lista de conectores yÂ <i>gzip</i>Â ha de estar instalado en su computadora).</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="204"><i>-groupsize</i></Text>
+</th>
+<th>
+<Text id="205">NÃºmero &gt;0</Text>
+</th>
+<th>
+<Text id="206">NÃºmero de documentos que se pueden reunir en un archivo en el Format de Archivo de Greenstone. El valor por defecto es 1 (esto es, un documento por archivo).</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="207"><i>-sortmeta</i></Text>
+</th>
+<th>
+<Text id="208">Nombre de etiqueta de metadatos</Text>
+</th>
+<th>
+<Text id="209">Clasifica alfabÃ©ticamente los documentos segÃºn el contenido de la etiqueta de metadatos. Sin embargo, esta funciÃ³n queda invalidada si la colecciÃ³n tiene mÃ¡s de un grupo en la colecciÃ³n (por ejemplo,Â <i>groupsize</i>Â &gt;1).</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="210"><i>-OIDtype</i></Text>
+</th>
+<th>
+<Text id="211">hasho incremental</Text>
+</th>
+<th>
+<Text id="212">MÃ©todo de creaciÃ³n de las OID para los documentos:Â <i>hash</i>Â desmenuza el contenido pero es lento;Â <i>incremental</i>Â simplemente asigna nÃºmeros de manera secuencial a los documentos y es mÃ¡s rÃ¡pido.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Figure id="steps_in_the_import_process">
+<Title>
+<Text id="213">Etapas del proceso de importaciÃ³n</Text>
+</Title>
+<File width="604" height="384" url="images/Dev_Fig_5.png"/>
+</Figure>
+<Text id="214">La Figura <CrossRef target="Figure" ref="steps_in_the_import_process"/> representa el proceso de importaciÃ³n efectuado por el programaÂ <i>import.pl</i>. Cada Ã³valo representa un mÃ³dulo utilizado para llevar a cabo tareas relacionadas con una parte especÃ­fica del sistema Greenstone. Todos estos mÃ³dulos pueden encontrarse en el directorioÂ <i>GSDLHOME/perllib</i>.</Text>
+<Text id="215">En la etapa 3, nÃ³tese que las variables de importaciÃ³n comoÂ <i>importdir</i>Â yÂ <i>archivedir</i>Â pueden definirse en el archivo de configuraciÃ³n de la colecciÃ³n o desde la lÃ­nea de comandos. Si se definen desde la lÃ­nea de comandos, se ignorarÃ¡n todos los valores especificados en el archivo de configuraciÃ³n.</Text>
+<Text id="216">En la etapa 6 se crea el archivo de informaciÃ³n de los archivos (<i>archives.inf</i>).</Text>
+<Text id="217">En la etapa 7 se crea un objeto que sabrÃ¡ dÃ³nde guardar los documentos y obedecerÃ¡ a todas las instrucciones especiales de memorizaciÃ³n (tales comoÂ <i>sortmeta</i>, que clasifica los documentos segÃºn una etiqueta de metadatos especificada).</Text>
+<Text id="218">De hecho, la mayorÃ­a de las tareas del proceso de importaciÃ³n corren a cargo de conectores, que se activan mediante el mÃ³duloÂ <i>plugin</i>. Dicho mÃ³dulo establece una secuencia de los conectores especificados en el archivo de configuraciÃ³n de la colecciÃ³n y maneja asimismo la escritura de los documentos en el Formato de Archivo Greenstone (utilizando un objetoÂ <i>document</i>).</Text>
+</Content>
+</Subsection>
+<Subsection id="the_build_process">
+<Title>
+<Text id="219">El proceso de creaciÃ³n</Text>
+</Title>
+<Content>
+<Text id="220">Durante el proceso de creaciÃ³n de la colecciÃ³n se comprime el texto y se crean los Ã­ndices de texto completo especificados en el archivo de configuraciÃ³n de la colecciÃ³n. AdemÃ¡s, se calculan con antelaciÃ³n y se incorporan a la colecciÃ³n los datos relativos a la apariencia de la colecciÃ³n en Internet, por ejemplo las informaciones sobre los iconos y los tÃ­tulos, asÃ­ como la informaciÃ³n producida por los clasificadores.Â <i>buildcol.pl</i>Â comparte numerosas opciones conÂ <i>import.pl</i>, como se muestra en el Cuadro <CrossRef target="Table" ref="options_for_the_import_and_build_processes"/>. En el Cuadro <CrossRef target="Table" ref="additional_options_for_the_build_process"/> se muestran otras que le son propias.</Text>
+<Table id="additional_options_for_the_build_process">
+<Title>
+<Text id="221">Opciones adicionales del proceso de creaciÃ³n</Text>
+</Title>
+<TableContent>
+<tr>
+<th>Â </th>
+<th>
+<Text id="222"><b>Argumento</b></Text>
+</th>
+<th>
+<Text id="223"><b>FunciÃ³n</b></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="224"><i>-builddir</i></Text>
+</th>
+<th>
+<Text id="225">Nombre de directorio</Text>
+</th>
+<th>
+<Text id="226">Especifica dÃ³nde se ha de almacenar el resultado de la creaciÃ³n. (El valor por defecto esÂ <i>GSDLHOME/collect/nombre_col/building).</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="227"><i>-index</i></Text>
+</th>
+<th>
+<Text id="228">Nombre del Ã­ndice (por ejemplo,Â <i>section:Title</i>)</Text>
+</th>
+<th>
+<Text id="229">Especifica quÃ© Ã­ndices crear. El valor por defecto es la totalidad de los Ã­ndices indicados en el archivo de configuraciÃ³n de la colecciÃ³n.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="230"><i>-allclassifications</i></Text>
+</th>
+<th>
+<Text id="231">Ninguno</Text>
+</th>
+<th>
+<Text id="232">Evita que el proceso de creaciÃ³n elimine las clasificaciones que no contienen documentos (por ejemplo, la clasificaciÃ³n âXâ en los tÃ­tulos, si no hay documentos cuyo tÃ­tulo empiece por la letra X).</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="233"><i>-create_images</i></Text>
+</th>
+<th>
+<Text id="234">Ninguno</Text>
+</th>
+<th>
+<Text id="235">Crea automÃ¡ticamente los iconos de colecciÃ³n (para ello es necesario haber instalado GIMP y el mÃ³dulo Gimp Perl).</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="236"><i>-mode</i></Text>
+</th>
+<th>
+<Text id="237">all, compress_text, infodb, o build_index</Text>
+</th>
+<th>
+<Text id="238">Determina lo que debe hacer el proceso de creaciÃ³n. (El valor por defecto esÂ <i>all</i>).Â <i>all</i>Â lleva a cabo una creaciÃ³n completa,Â <i>compress_text</i>Â sÃ³lo comprime el texto del documento,Â <i>infodb</i>Â crea una base de datos de informaciones sobre la colecciÃ³n (nombres, archivos, archivos asociados, informaciÃ³n sobre la clasificaciÃ³n y otros) yÂ <i>build_index</i>Â crea los Ã­ndices especificados en el archivo de configuraciÃ³n de la colecciÃ³n o en la lÃ­nea de comandos.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="239"><i>-no_text</i></Text>
+</th>
+<th>Â </th>
+<th>
+<Text id="240">No almacena texto comprimido. Esta opciÃ³n es Ãºtil para minimizar el tamaÃ±o de los Ã­ndices creados si desea visualizar siempre los documentos originales en el momento de la ejecuciÃ³n.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Figure id="steps_in_the_build_process">
+<Title>
+<Text id="241">Etapas del proceso de creaciÃ³n</Text>
+</Title>
+<File width="605" height="306" url="images/Dev_Fig_6.png"/>
+</Figure>
+<Text id="242">El diagrama de la Figura <CrossRef target="Figure" ref="steps_in_the_build_process"/> representa la ejecuciÃ³n del programaÂ <i>buildcol.pl</i>. Muchas de las etapas son iguales a las del proceso de importaciÃ³n. La primera que no coincide es la etapa 4 (a la izquierda), que sÃ³lo se ejecuta si se ha activado la opciÃ³nÂ <i>create_images</i>. A continuaciÃ³n, las imÃ¡genes se crean y se registran en el archivo de configuraciÃ³n de la colecciÃ³n mediante una funciÃ³n del guiÃ³nÂ <i>buildcol.pl</i>. Para que todo esto funcione adecuadamente, deben haberse instalado y configurado apropiadamente GIMP (Â <i>GNU Image Manipulation Program</i>, o Programa de manipulaciÃ³n de imÃ¡genes de GNU) y el mÃ³dulo Gimp Perl. Debe existir asimismo un permiso de escritura (asÃ­ como de lectura) al archivo de configuraciÃ³n de la colecciÃ³n.</Text>
+<Text id="243">En la etapa 5 se comprueba primero si existe un proceso de creaciÃ³n especÃ­fico de la colecciÃ³n. Algunas colecciones requieren un tratamiento especial durante la creaciÃ³n, en cuyo caso se debe escribir un creador especÃ­fico de la colecciÃ³n y colocarlo en su directorioÂ <i>perllib</i>, que lleva el nombre de la colecciÃ³n seguido de âÂ <i>builder</i>Â â (creador). Los creadores especÃ­ficos de colecciÃ³n provienen deÂ <i>mgbuilder</i>. En la etapa 5, se inicializa el creador (ya sea el instalado por defecto o uno especÃ­fico de la colecciÃ³n) con informaciÃ³n sobre el nÃºmero de documentos que se va a incluir, el mantenimiento o no de la antigua versiÃ³n de la colecciÃ³n y la ubicaciÃ³n de los directoriosÂ <i>building</i>Â yÂ <i>archive</i>.</Text>
+<Text id="244">La etapa 6 es la de la creaciÃ³n. El texto de los documentos se comprime y se indiza, los tÃ­tulos y los iconos se almacenan en una base de datos de informaciones de la colecciÃ³n y se crean las estructuras de datos para apoyar los clasificadores activados por los conectores de la colecciÃ³n. El archivoÂ <i>mgbuilder</i>Â (o el creador especÃ­fico de la colecciÃ³n) maneja todas esas etapas y utiliza el programa MG (âÂ <i>Managing Gigabytes</i>Â â, o gestiÃ³n de gigabytes; vÃ©ase WittenÂ <i>et al.</i>, 1999) para comprimir e indizar.</Text>
+<Text id="245">La opciÃ³nÂ <i>mode</i>Â permite especificar las partes de la colecciÃ³n que se crean, pero por defecto se crea todo: el texto comprimido, los Ã­ndices y las bases de datos de informaciones de colecciÃ³n.</Text>
+<Text id="246">Una vez concluido el proceso de creaciÃ³n, si desea que la colecciÃ³n pueda consultarse en Internet, es preciso trasladarla del directorioÂ <i>building</i>Â de la colecciÃ³n al directorioÂ <i>index</i>. Las colecciones no se crean directamente en el directorioÂ <i>index</i>Â porque la creaciÃ³n de las colecciones voluminosas puede tardar horas o dÃ­as. Es importante que el proceso de creaciÃ³n no afecte una copia existente de la colecciÃ³n hasta que la operaciÃ³n no haya concluido.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="greenstone_archive_documents">
+<Title>
+<Text id="247">Documentos en el Formato de Archivo Greenstone</Text>
+</Title>
+<Content>
+<Text id="248">Todos los documentos de origen se importan al sistema Greenstone despuÃ©s de su conversiÃ³n en el Formato de Archivo Greenstone, que es un estilo XML que divide los documentos en secciones y puede contener metadatos para cada documento o secciÃ³n. No tendrÃ¡ que crear manualmente los archivos en el Format de Archivo Greenstone, ya que los conectores que tratan los documentos cumplen esta funciÃ³n, tal como se explica en el capÃ­tulo siguiente. Sin embargo, puede resultar Ãºtil comprender el formato de los archivos Greenstone, que describimos a continuaciÃ³n.</Text>
+<Text id="249">En XML, las etiquetas van entre corchetes angulares para el marcado. El Formato de Archivo Greenstone codifica los documentos que ya estÃ¡n en HTML, y todos los signos &lt;, &gt; o â incluidos en el texto original se eluden mediante la convenciÃ³n estÃ¡ndar &amp;lt;, &amp;gt; y &amp;quot;.</Text>
+<Figure id="greenstone_archive_format">
+<Title>
+<Text id="250">Formato de Archivo Greenstone:</Text>
+<SubTitle>
+<Text id="251">(a)Â DefiniciÃ³n de tipo de documento (DTD);</Text>
+</SubTitle>
+</Title>
+<CodeLine>&lt;!DOCTYPE GreenstoneArchive [</CodeLine>
+<CodeLine>Â  &lt;!ELEMENT Section (Description,Content,Section*)&gt;</CodeLine>
+<CodeLine>Â  &lt;!ELEMENT Description (Metadata*)&gt;</CodeLine>
+<CodeLine>Â  &lt;!ELEMENT Content (#PCDATA)&gt;</CodeLine>
+<CodeLine>Â  &lt;!ELEMENT Metadata (#PCDATA)&gt;</CodeLine>
+<CodeLine>Â  &lt;ATTLIST Metadata name CDATA #REQUIRED&gt;</CodeLine>
+<CodeLine>]&gt;</CodeLine>
+</Figure>
+<Figure id="greenstone_archive_format_1">
+<Title>
+<Text id="252"/>
+<SubTitle>
+<Text id="253">(b) Documento de ejemplo.</Text>
+</SubTitle>
+</Title>
+<CodeLine>&lt;?xml version="1.0" ?&gt;</CodeLine>
+<CodeLine>&lt;!DOCTYPE GreenstoneArchive SYSTEM</CodeLine>
+<CodeLine>"http://greenstone.org/dtd/GreenstoneArchive/1.0/GreenstoneArchive.dtd"&gt;</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>Â  &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;Metadata name="gsdlsourcefilename"&gt;ec158e.txt&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;Metadata name="Title"&gt;Freshwater Resources in Arid Lands&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;Metadata name="Identifier"&gt;HASH0158f56086efffe592636058&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;Metadata name="gsdlassocfile"&gt;cover.jpg:image/jpeg:&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;Metadata name="gsdlassocfile"&gt;p07a.png:image/png:&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â  &lt;/Description&gt;</CodeLine>
+<CodeLine>Â  &lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â  &lt;Metadata name="Title"&gt;PrÃ³logo&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;Content&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â  Eso es el texto del prÃ³logo</CodeLine>
+<CodeLine>Â Â Â  &lt;/Content&gt;</CodeLine>
+<CodeLine>Â  &lt;/Section&gt;</CodeLine>
+<CodeLine>Â  &lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â  &lt;Metadata name="Title"&gt;Primer y Ãºnico capÃ­tulo&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;Section&gt; </CodeLine>
+<CodeLine>Â Â Â Â Â  &lt;Description&gt; </CodeLine>
+<CodeLine>Â Â Â Â Â Â Â  &lt;Metadata name="Title"&gt;Parte 1&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â  &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â  &lt;Content&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â  Eso es la primera parte del primer y Ãºnico capÃ­tulo</CodeLine>
+<CodeLine>Â Â Â Â Â  &lt;/Content&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;/Section&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â Â  Â &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â  &lt;Metadata name="Title"&gt;Parte 2&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â  &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â  &lt;Content&gt; </CodeLine>
+<CodeLine>Â Â Â Â Â Â Â  Eso es la segunda parte del primer y Ãºnico capÃ­tulo</CodeLine>
+<CodeLine>Â Â Â Â Â  &lt;/Content&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;/Section&gt; </CodeLine>
+<CodeLine>Â  &lt;/Section&gt;</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+</Figure>
+<Text id="254">En la Figura <CrossRef target="Figure" ref="greenstone_archive_format"/> se muestra la definiciÃ³n de tipo de documento (DTD) XML para el Formato de Archivo Greenstone. BÃ¡sicamente, un documento se divide enÂ <i>Sections</i>Â (Secciones), que pueden a su vez subdividirse. CadaÂ <i>Section</i>Â tiene unaÂ <i>Description</i>Â (descripciÃ³n) que comprende cero o varios elementosÂ <i>Metadata</i>Â (metadatos) y una parteÂ <i>Content</i>Â (contenido) (que puede estar vacÃ­a), donde se guardan los datos propiamente dichos del documento. Cada elementoÂ <i>Metadata</i>Â va asociado con un atributo de nombre (puede ser cualquier nombre) y algunos datos textuales. En XML,Â <i>PCDATA</i>Â corresponde a âÂ <i>parsed character data</i>Â â (datos de caracteres analizados), es decir, bÃ¡sicamente texto.</Text>
+<Text id="255">En la Figura <CrossRef target="Figure" ref="greenstone_archive_format_1"/> se muestra un documento simple escrito en este formato, que es un pequeÃ±o libro con dos imÃ¡genes asociadas. El libro tiene dos secciones denominadasÂ <i>PrÃ³logo</i>Â yÂ <i>Primer y Ãºnico capÃ­tulo</i>,Â <i/>Â respectivamente; la segunda secciÃ³n se divide en dos subsecciones. ObsÃ©rvese que no existe nociÃ³n de âcapÃ­tuloâ como tal: se lo representa simplemente como una secciÃ³n de nivel superior.</Text>
+<Table id="greenstone_archive_format_values">
+<Title>
+<Text id="256">Formato de Archivo Greenstone: Valores del atributoÂ <i>name</i>Â de la etiquetaÂ <i>Metadata</i>.</Text>
+</Title>
+<TableContent>
+<tr>
+<th>
+<Text id="257"><i>gsdlsourcefilename</i></Text>
+</th>
+<th>
+<Text id="258">Archivo original a partir del cual se generÃ³ el archivo de archivo de Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="259"><i>gsdlassocfile</i></Text>
+</th>
+<th>
+<Text id="260">Archivo asociado con el documento (un archivo grÃ¡fico, por ejemplo) </Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="261">La etiqueta &lt;Section&gt; indica el principio de cada secciÃ³n del documento y la correspondiente etiqueta de cierre &lt;/Section&gt; seÃ±ala el final de dicha secciÃ³n. Tras cada etiqueta &lt;Section&gt; hay una secciÃ³n &lt;Description&gt; que incluye una serie cualquiera de elementos &lt;Metadata&gt;. De este modo, se pueden asociar diferentes metadatos con las distintas secciones de un documento. En su mayorÃ­a son tipos particulares de metadatos, como âTitleâ (tÃ­tulo), por ejemplo. Los dos valores del atributoÂ <i>name</i>Â (nombre) que se muestran en el Cuadro <CrossRef target="Table" ref="greenstone_archive_format_values"/> reciben un tratamiento especial por parte de Greenstone; todos los demÃ¡s se consideran metadatos vinculados a esa secciÃ³n.</Text>
+<Text id="262">En algunas colecciones, los documentos estÃ¡n divididos en pÃ¡ginas que se tratan como secciones. Por ejemplo, un libro puede contener secciones de primer nivel que corresponden a los capÃ­tulos, en los que se definen una serie de âseccionesâ que, en realidad, corresponden a las diferentes pÃ¡ginas del capÃ­tulo.</Text>
+<Subsection id="document_metadata">
+<Title>
+<Text id="263">Metadatos del documento</Text>
+</Title>
+<Content>
+<Text id="264">Los metadatos son informaciÃ³n descriptiva asociada a un documento, como por ejemplo, autor, tÃ­tulo, fecha, palabras clave, etc. Ya se ha mencionado que los metadatos se almacenan con los documentos. En la Figura <CrossRef target="Figure" ref="greenstone_archive_format"/> se puede ver que las etiquetas &lt;Metadata&gt; especifican el nombre del tipo de metadatos y les asignan un valor. Un ejemplo es la lÃ­nea &lt;Â <i>Metadata name=âTitleâ</i>Â &gt;Â <i>Primer y Ãºnico capÃ­tulo&lt;/Metadata</i>Â &gt; de la Figura <CrossRef target="Figure" ref="greenstone_archive_format_1"/>: el tÃ­tulo de un documento es un elemento de metadato asociado a Ã©l. Se utiliza la norma de metadatos Dublin Core para definir los tipos de metadatos (Dublin Core, 2001; Weibel, 1999; Thiele, 1997)</Text>
+<Text id="265">En el Cuadro <CrossRef target="Table" ref="dublin_core_metadata_standard"/> se muestran los tipos de metadatos disponibles en la norma; los que van seÃ±alados con un asterisco se utilizan en las colecciones que se pueden consultar actualmente en el sitio Web de la Biblioteca Digital de Nueva Zelandia. Si ninguno de estos tipos corresponde exactamente a una clase determinada de metadatos, se pueden utilizar tambiÃ©n otros tipos de metadatos que no figuran en la norma Dublin Core. Por ejemplo, la colecciÃ³n de demostraciÃ³n contiene los metadatosÂ <i>how to</i>Â (CÃ³mo...) yÂ <i>Magazine</i>Â (Revista).</Text>
+<Table id="dublin_core_metadata_standard">
+<Title>
+<Text id="266">Norma de metadatos Dublin Core</Text>
+</Title>
+<TableContent>
+<tr>
+<th>
+<Text id="267"><b>Nombre</b></Text>
+</th>
+<th>
+<Text id="268"><b>Subetiqueta de metadato</b></Text>
+</th>
+<th>
+<Text id="269"><b>DefiniciÃ³n</b></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="270">*TÃ­tulo</Text>
+</th>
+<th>
+<Text id="271"><i>Title</i></Text>
+</th>
+<th>
+<Text id="272">Nombre que se da al recurso</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="273">*Creador</Text>
+</th>
+<th>
+<Text id="274"><i>Creator</i></Text>
+</th>
+<th>
+<Text id="275">Entidad encargada principalmente de crear el contenido del recurso</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="276">*Tema y palabras clave</Text>
+</th>
+<th>
+<Text id="277"><i>Subject</i></Text>
+</th>
+<th>
+<Text id="278">Tema del contenido del recurso</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="279">*DescripciÃ³n</Text>
+</th>
+<th>
+<Text id="280"><i>Description</i></Text>
+</th>
+<th>
+<Text id="281">ExplicaciÃ³n del contenido del recurso</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="282">*Editor</Text>
+</th>
+<th>
+<Text id="283"><i>Publisher</i></Text>
+</th>
+<th>
+<Text id="284">Entidad encargada de publicar el recurso</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="285">Contribuidor</Text>
+</th>
+<th>
+<Text id="286"><i>Contributor</i></Text>
+</th>
+<th>
+<Text id="287">Entidad encargada de aportar contribuciones al contenido del recurso</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="288">*Fecha</Text>
+</th>
+<th>
+<Text id="289"><i>Date</i></Text>
+</th>
+<th>
+<Text id="290">Fecha en que se publicÃ³ el recurso o cualquier otra fecha importante asociada con el recurso.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="291">Tipo de recurso</Text>
+</th>
+<th>
+<Text id="292"><i>Type</i></Text>
+</th>
+<th>
+<Text id="293">Ãndole o tipo del contenido del recurso</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="294">Formato</Text>
+</th>
+<th>
+<Text id="295"><i>Format</i></Text>
+</th>
+<th>
+<Text id="296">RepresentaciÃ³n fÃ­sica o digital del recurso</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="297">*Identificador de recurso</Text>
+</th>
+<th>
+<Text id="298"><i>Identifier</i></Text>
+</th>
+<th>
+<Text id="299">Referencia inequÃ­voca al recurso en un contexto determinado: se trata del identificador de objeto u OID</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="300">*Fuente</Text>
+</th>
+<th>
+<Text id="301"><i>Source</i></Text>
+</th>
+<th>
+<Text id="302">Referencia a un recurso del que deriva el presente recurso</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="303">*Lengua</Text>
+</th>
+<th>
+<Text id="304"><i>Language</i></Text>
+</th>
+<th>
+<Text id="305">Lengua del contenido intelectual del recurso</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="306">RelaciÃ³n</Text>
+</th>
+<th>
+<Text id="307"><i>Relation</i></Text>
+</th>
+<th>
+<Text id="308">Referencia a un recurso conexo</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="309">*Cobertura</Text>
+</th>
+<th>
+<Text id="310"><i>Coverage</i></Text>
+</th>
+<th>
+<Text id="311">ExtensiÃ³n o alcance del contenido del recurso</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="312">GestiÃ³n de los derechos</Text>
+</th>
+<th>
+<Text id="313"><i>Rights</i></Text>
+</th>
+<th>
+<Text id="314">InformaciÃ³n sobre los derechos relacionados con el recurso o atinentes a Ã©ste</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+<Subsection id="inside_greenstone_archive_documents">
+<Title>
+<Text id="315">Los documentos en el Format de Archivo de Greenstone vistos por dentro</Text>
+</Title>
+<Content>
+<Text id="316">El Formato de Archivo de Greenstone impone poca estructura a los documentos individuales. Los documentos se dividen en pÃ¡rrafos. Pueden subdividirse jerÃ¡rquicamente en secciones y subsecciones que pueden a su vez subdividirse indefinidamente. Cada documento va asociado con un identificador de objeto u OID que tambiÃ©n sirve para identificar las secciones y subsecciones mediante nÃºmeros separados por puntos en los OID de los documentos. Por ejemplo, el OID HASHa7.2.3 se referirÃ¡ a la subsecciÃ³n 3 de la secciÃ³n 2 del documento HASHa7.</Text>
+<Text id="317">Cuando se lee un libro en una colecciÃ³n de Greenstone, la jerarquÃ­a de las secciones figura en el Ã­ndice del libro. Por ejemplo, los libros de la colecciÃ³n de demostraciÃ³n disponen de un Ã­ndice jerÃ¡rquico compuesto de capÃ­tulos, secciones y subsecciones como se muestra en la Figura <CrossRef target="Figure" ref="hierarchical_structure_in_the_demo_collection"/>. Los documentos de la colecciÃ³nÂ <i>Computer Science Technical Reports</i>Â no presentan una estructura jerÃ¡rquica en subsecciones, pero cada documento estÃ¡ dividido en pÃ¡ginas y se puede navegar por las pÃ¡ginas de un documento recuperado. Los capÃ­tulos, las secciones, las subsecciones y las pÃ¡ginas se consideran simplemente âseccionesâ del documento.</Text>
+<Figure id="hierarchical_structure_in_the_demo_collection">
+<Title>
+<SubTitle>
+<Text id="318a">(a)</Text>
+</SubTitle>
+<Text id="318">Estructura jerÃ¡rquica de la colecciÃ³n de demostraciÃ³n</Text>
+</Title>
+<File width="605" height="296" url="images/Dev_Fig_8a.png"/>
+</Figure>
+<Figure id="hierarchical_structure_in_the_demo_collection_1">
+<Title>
+<Text id="318b">Estructura jerÃ¡rquica de la colecciÃ³n de demostraciÃ³n</Text>
+<SubTitle>
+<Text id="318c">(b)</Text>
+</SubTitle>
+</Title>
+<File width="605" height="296" url="images/Dev_Fig_8b.png"/>
+</Figure>
+<Text id="319">La estructura del documento sirve tambiÃ©n para los Ã­ndices de bÃºsqueda. Existen tres niveles posibles de Ã­ndices:Â <i>documento</i>,Â <i>secciÃ³n</i>Â yÂ <i>pÃ¡rrafo</i>, aunque la mayorÃ­a de las colecciones no utilizan los tres niveles. Un Ã­ndice deÂ <i>documento</i>Â contiene el documento completo; se lo utiliza para encontrar todos los documentos en los que figura un conjunto determinado de palabras (los tÃ©rminos pueden estar repartidos por todo el documento, lejos unos de otros). Cuando se crea un Ã­ndice deÂ <i>secciÃ³n</i>, cada porciÃ³n de texto que se indiza se extiende desde una etiqueta &lt;Section&gt; hasta la siguiente etiqueta &lt;Section&gt;; por consiguiente, un capÃ­tulo que empieza directamente con una nueva secciÃ³n producirÃ¡ un documento vacÃ­o en el Ã­ndice. Las secciones y subsecciones se tratan de la misma manera: la estructura jerÃ¡rquica del documento se allana con objeto de crear Ã­ndices de bÃºsqueda. Para los Ã­ndices de pÃ¡rrafos, Ãºtiles para bÃºsquedas mÃ¡s especÃ­ficas, cada pÃ¡rrafo se considera un documento aparte.</Text>
+<Text id="320">En el menÃº desplegable de la Figura <CrossRef target="Figure" ref="hierarchical_structure_in_the_demo_collection_1"/> se muestran los Ã­ndices de bÃºsqueda de la colecciÃ³n de demostraciÃ³n. Los âcapÃ­tulosâ y los âtÃ­tulos de las seccionesâ son Ã­ndices de nivel de la secciÃ³n, mientras que los âlibros enterosâ son Ã­ndices de nivel del documento. Al igual que los Ã­ndices de texto, se pueden crear Ã­ndices de cualquier tipo de metadatos. Por ejemplo, algunas colecciones proponen Ã­ndices de bÃºsqueda de tÃ­tulos de secciÃ³n, como se muestra en la Figura <CrossRef target="Figure" ref="hierarchical_structure_in_the_demo_collection_1"/>.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="configuration_file">
+<Title>
+<Text id="321">Archivo de configuraciÃ³n de la colecciÃ³n</Text>
+</Title>
+<Content>
+<Text id="322">El archivo de configuraciÃ³n de la colecciÃ³n rige la estructura de una colecciÃ³n tal como la ve el usuario, lo que permite personalizar su aspecto y estilo, asÃ­ como el modo en que se tratan y presentan los documentos. Cuando usted ejecutaÂ <i>mkcol.pl</i>, se crea un simple archivo de configuraciÃ³n de colecciÃ³n en el que queda registrada su direcciÃ³n electrÃ³nica como creador y responsable de la actualizaciÃ³n. RecuÃ©rdese que el argumentoÂ <i>creator</i>Â es obligatorio, y a menos que se especifique por separado, se registra la misma informaciÃ³n para el elementoÂ <i>maintainer</i>Â (actualizador).</Text>
+<Table id="items_in_the_collection_configuration_file">
+<Title>
+<Text id="323">Elementos del archivo de configuraciÃ³n de la colecciÃ³n</Text>
+</Title>
+<TableContent>
+<tr>
+<th>
+<CodeLine>creator</CodeLine>
+</th>
+<th>
+<Text id="324">DirecciÃ³n electrÃ³nica del creador de la colecciÃ³n</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>maintainer</i></CodeLine>
+</th>
+<th>
+<Text id="325">DirecciÃ³n electrÃ³nica del actualizador de la colecciÃ³n</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>public</i></CodeLine>
+</th>
+<th>
+<Text id="326">Determina si la colecciÃ³n va a ponerse a disposiciÃ³n del pÃºblico o no</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>beta</i></CodeLine>
+</th>
+<th>
+<Text id="327">Determina si la colecciÃ³n es una versiÃ³n beta o no</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>indexes</i></CodeLine>
+</th>
+<th>
+<Text id="328">Lista de Ã­ndices por crear</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>defaultindex</i></CodeLine>
+</th>
+<th>
+<Text id="329">Ãndice por defecto</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>subcollection</i></CodeLine>
+</th>
+<th>
+<Text id="330">Define una subcolecciÃ³n basada en metadatos</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>indexsubcollections</i></CodeLine>
+</th>
+<th>
+<Text id="331">Especifica quÃ© subcolecciones indizar</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>defaultsubcollection</i></CodeLine>
+</th>
+<th>
+<Text id="332">Ãndice de subcolecciÃ³n por defecto</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>languages</i></CodeLine>
+</th>
+<th>
+<Text id="333">Lista de lenguas en las que hay que crear los Ã­ndices</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>defaultlanguage</i></CodeLine>
+</th>
+<th>
+<Text id="334">Ãndice de lengua por defecto</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>collectionmeta</i></CodeLine>
+</th>
+<th>
+<Text id="335">Define los metadatos al nivel de la colecciÃ³n</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>plugin</i></CodeLine>
+</th>
+<th>
+<Text id="336">Especifica un conector que habrÃ¡ de utilizarse durante la creaciÃ³n</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>format</i></CodeLine>
+</th>
+<th>
+<Text id="337">Cadena de formato (se explica mÃ¡s adelante)</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>classify</i></CodeLine>
+</th>
+<th>
+<Text id="338">Especifica un clasificador que habrÃ¡ de utilizarse durante la creaciÃ³n</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="339">Cada lÃ­nea del archivo de configuraciÃ³n de colecciÃ³n es bÃ¡sicamente un par âatributo, valorâ. Cada atributo aporta una parte de informaciÃ³n sobre la colecciÃ³n que determina su apariencia y el modo en que se van a tratar los documentos. En el Cuadro <CrossRef target="Table" ref="items_in_the_collection_configuration_file"/> se muestran los elementos que se pueden incluir en un archivo de configuraciÃ³n de colecciÃ³n y su utilizaciÃ³n. AdemÃ¡s, se pueden especificar todas las opciones de lÃ­nea de comandos de los programasÂ <i>import.pl</i>Â yÂ <i>buildcol.pl</i>Â en un archivo de configuraciÃ³n de colecciÃ³n; por ejemplo, una lÃ­nea que digaÂ <i>no_text true</i>Â propondrÃ¡ la opciÃ³nÂ <i>no_text</i>Â deÂ <i>buildcol.pl</i>.</Text>
+<Text id="340">El archivo de configuraciÃ³n de la colecciÃ³n creado por la secuencia de comandosÂ <i>mkcol.pl</i>, que se muestra en el Cuadro <CrossRef target="Table" ref="collection_configuration_file_created_by_mkcd"/>, es muy simple y no contiene sino la informaciÃ³n estrictamente necesaria. Las lÃ­neas 1 y 2, que proceden del valorÂ <i>creator</i>Â suministrado al programaÂ <i>mkcol.pl</i>, contienen las direcciones electrÃ³nicas de la persona encargada de la creaciÃ³n de la colecciÃ³n y de la persona encargada de actualizarla (no es necesariamente la misma).</Text>
+<Table id="collection_configuration_file_created_by_mkcd">
+<Title>
+<Text id="341">Archivo de configuraciÃ³n de colecciÃ³n creado medianteÂ <i>mkcol.pl</i></Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="342"><b>Atributo</b></Text>
+</th>
+<th width="265">
+<Text id="343"><b>Valor</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>1</CodeLine>
+</th>
+<th width="132">
+<CodeLine>creator</CodeLine>
+</th>
+<th width="265">
+<Text id="344">nombre_del_usuario@email.com</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>2</CodeLine>
+</th>
+<th width="132">
+<CodeLine>maintainer</CodeLine>
+</th>
+<th width="265">
+<Text id="345">nombre_del_usuario@email.com</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>3</CodeLine>
+</th>
+<th width="132">
+<CodeLine>public</CodeLine>
+</th>
+<th width="265">
+<Text id="346">True</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>4</CodeLine>
+</th>
+<th width="132">
+<CodeLine>beta</CodeLine>
+</th>
+<th width="265">
+<Text id="347">True</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>5</CodeLine>
+</th>
+<th width="132">
+<CodeLine>indexes</CodeLine>
+</th>
+<th width="265">
+<Text id="348">document:text</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>6</CodeLine>
+</th>
+<th width="132">
+<CodeLine>defaultindex</CodeLine>
+</th>
+<th width="265">
+<Text id="349">document:text</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>7</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="350">ZIPPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>8</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="351">GAPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>9</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="352">TextPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>10</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="353">HTMLPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>11</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="354">EMAILPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>12</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="355">ArcPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>13</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="356">RecPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>14</CodeLine>
+</th>
+<th width="132">
+<CodeLine>classify</CodeLine>
+</th>
+<th width="265">
+<Text id="357">AZList metadata Title</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>15</CodeLine>
+</th>
+<th width="132">
+<CodeLine>collectionmeta</CodeLine>
+</th>
+<th width="265">
+<Text id="358">collectioname âcolecciÃ³n de muestrasâ</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>16</CodeLine>
+</th>
+<th width="132">
+<CodeLine>collectionmeta</CodeLine>
+</th>
+<th width="265">
+<Text id="359">iconcollection       ""</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>17</CodeLine>
+</th>
+<th width="132">
+<CodeLine>collectionmeta</CodeLine>
+</th>
+<th width="265">
+<Text id="360">collectionextra     ""</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>18</CodeLine>
+</th>
+<th width="132">
+<CodeLine>collectionmeta</CodeLine>
+</th>
+<th width="265">
+<Text id="361">.document:text     "documents"</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="362">La lÃ­nea 3 indica si la colecciÃ³n se pondrÃ¡ a disposiciÃ³n del pÃºblico una vez creada, mediante los valoresÂ <i>true</i>Â (el parÃ¡metro por defecto, que significa que la colecciÃ³n se podrÃ¡ consultar pÃºblicamente) oÂ <i>false</i>Â (que significa lo contrario). Esta Ãºltima opciÃ³n es Ãºtil cuando se crean colecciones para probar programas o para uso personal. La lÃ­nea 4 indica si la colecciÃ³n es beta o no (el valor por defecto tambiÃ©n esÂ <i>true</i>Â (verdadero), lo que significa que la colecciÃ³n es una versiÃ³n beta).</Text>
+<Text id="363">La lÃ­nea 5 determina los Ã­ndices de colecciÃ³n que han de constituirse en el momento de la creaciÃ³n: en este ejemplo sÃ³lo se indizarÃ¡ el texto del documento. Existen tres niveles posibles de Ã­ndices:Â <i>document (</i>Â documentoÂ <i>)</i>,Â <i>section (</i>Â secciÃ³nÂ <i>)</i>Â yÂ <i>paragraph (</i>Â pÃ¡rrafoÂ <i>)</i>. Pueden contener datos en formatoÂ <i>text</i>Â (texto) o en cualquier tipo de metadatos, por lo generalÂ <i>Title</i>Â (tÃ­tulo). La forma que se utiliza para especificar el tipo de Ã­ndice esÂ <i>nivel:datos</i>. Por ejemplo, para incluir tambiÃ©n un Ã­ndice de tÃ­tulos de secciÃ³n, habrÃ­a que sustituir la lÃ­nea 5 porÂ <i>indexes document:text section:Title</i>. Se puede incluir mÃ¡s de un tipo de datos en el mismo Ã­ndice separando los tipos de datos por comas. Por ejemplo, para crear un Ã­ndice en el nivel de secciÃ³n que incluya tÃ­tulos, texto y datos, la lÃ­nea deberÃ­a rezarÂ <i>indexes section:text,Title,Date</i>. El Ã­ndice por defecto que se define en la lÃ­nea 6 es el valor por defecto que se utiliza en la pÃ¡gina de bÃºsqueda de la colecciÃ³n.</Text>
+<Text id="364">Las lÃ­neas 7-13 especifican los conectores que se han de utilizar para convertir los documentos en el Formato de Archivo Greenstone y para crear colecciones a partir de archivos en el Formato de Archivo Greenstone. En la SecciÃ³n <CrossRef target="Section" ref="plugins"/> se proporciona informaciÃ³n sobre los conectores disponibles. Los conectores se prueban en cada documento siguiendo el orden de su enumeraciÃ³n y cuando se encuentra un conector capaz de tratar un documento, no se prueba ninguno mÃ¡s.</Text>
+<Text id="365">La lÃ­nea 14 especifica que se va a crear una lista alfabÃ©tica de tÃ­tulos para facilitar la consulta. Las estructuras de consulta estÃ¡n compuestas por âclasificadoresâ. En la SecciÃ³n <CrossRef target="Section" ref="classifiers"/> se proporciona informaciÃ³n sobre los clasificadores y sus funciones.</Text>
+<Text id="366">Las lÃ­neas 15-18 sirven para especificar los metadatos de nivel de colecciÃ³n. Se utiliza la forma larga delÂ <i>collectionname</i>Â como âtÃ­tuloâ de la colecciÃ³n para el navegador de Internet. El atributoÂ <i>collectionicon</i>Â proporciona la URL del icono de la colecciÃ³n. Si se especifica un Ã­ndice (como en la lÃ­nea 18), la cadena siguiente aparece en la pÃ¡gina de bÃºsqueda de la colecciÃ³n como el nombre de ese Ã­ndice. Un metadato de nivel de colecciÃ³n particularmente importante esÂ <i>collectionextra</i>, que suministra un texto entrecomillado en que se describe la colecciÃ³n. Este atributo aparecerÃ¡ como texto en âAcerca de esta colecciÃ³nâ. Se pueden introducir distintas versiones deÂ <i>collectionextra</i>Â para las diferentes interfaces lingÃŒÃ­sticas aÃ±adiendo la especificaciÃ³n de la lengua entre corchetes. Por ejemplo:</Text>
+<Indented>
+<Text id="367">collectionmeta collectionextra âdescripciÃ³n de la coleciÃ³nâ</Text>
+</Indented>
+<Indented>
+<Text id="368">collectionmeta collectionextra [l=fr] âdescripciÃ³n en francÃ©sâ</Text>
+</Indented>
+<Indented>
+<Text id="369">collectionmeta collectionextra [l=mi] âdescripciÃ³n en maorÃ­â</Text>
+</Indented>
+<Text id="370">Si se introduce âfrâ o âmiâ como idioma de la interfaz, aparecerÃ¡ en pantalla la correspondiente versiÃ³n lingÃŒÃ­stica de la descripciÃ³n. Para otras lenguas aparecerÃ¡ la versiÃ³n por defecto.</Text>
+<Text id="371">Este archivo simple de configuraciÃ³n de colecciÃ³n no incluye ningÃºn ejemplo de cadenas de formato, ni de las posibilidades de subcolecciÃ³n o de idiomas que ofrece el archivo de configuraciÃ³n. Las cadenas de formato se examinan mÃ¡s en detalle en la SecciÃ³n <CrossRef target="Section" ref="formatting_greenstone_output"/>, pero las subcolecciones y las posibilidades lingÃŒÃ­sticas se abordarÃ¡n en este capÃ­tulo.</Text>
+<Subsection id="subcollections">
+<Title>
+<Text id="372">Las subcolecciones</Text>
+</Title>
+<Content>
+<Text id="373">Greenstone le permite definir subcolecciones y crear Ã­ndices separados para cada una. Por ejemplo, en una colecciÃ³n hay un amplio subconjunto de documentos denominadoÂ <i>Food and Nutrition Bulletin</i>Â (boletÃ­n de los alimentos y la nutriciÃ³n). Utilizaremos esta colecciÃ³n como ejemplo.</Text>
+<Text id="374">Esta colecciÃ³n posee tres Ã­ndices, todos de nivel de secciÃ³n: el primero para toda la colecciÃ³n, el segundo para elÂ <i>Food and Nutrition Bulletin</i>Â y el tercero para el resto de los documentos. A continuaciÃ³n se presentan las correspondientes lÃ­neas del archivo de configuraciÃ³n de la colecciÃ³n:</Text>
+<CodeLine>indexesÂ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  section:text</CodeLine>
+<CodeLine>subcollectionÂ Â Â Â Â Â  fn âTitle/^Food and Nutrition Bulletin/iâ</CodeLine>
+<CodeLine>subcollectionÂ Â Â Â Â Â  other â!Title/^Food and Nutrition Bulletin/iâ</CodeLine>
+<CodeLine>indexsubcollections Â Â Â Â Â Â  fn Â Â Â  otherÂ  fn,other</CodeLine>
+<Text id="375">La segunda y la tercera lÃ­neas definen las subcolecciones denominadasÂ <i>fn</i>, que contendrÃ¡ los documentos deÂ <i>Food and Nutrition Bulletin</i>, yÂ <i>other</i>, que contendrÃ¡ el resto de los documentos. El tercer campo de estas definiciones es una expresiÃ³n regular en Perl que identifica estos subconjuntos mediante el metadatoÂ <i>Title</i>Â : en el primer caso, buscamos tÃ­tulos que empiecen porÂ <i>Food and Nutrition Bulletin</i>Â y, en el segundo, otros tÃ­tulos que no empiezan asÃ­ (obsÃ©rvese el â!â). LaÂ <i>i</i>Â final permite que la bÃºsqueda se haga sin distinciÃ³n entre mayÃºsculas y minÃºsculas. El campo de metadatos, en este casoÂ <i>Title</i>, puede ser cualquier campo vÃ¡lido, oÂ <i>Filename</i>Â (nombre de archivo) que coincida con el nombre de archivo original del documento. La cuarta lÃ­nea,Â <i>indexsubcollections</i>, especifica tres Ã­ndices: uno para la subcolecciÃ³nÂ <i>fn</i>, otro para la subcolecciÃ³nÂ <i>other</i>, y el tercero para ambas subcolecciones (esto es, para todos los documentos). ObsÃ©rvese que si se hubiesen especificado dos entradas en la lÃ­neaÂ <i>indexes</i>, el nÃºmero total de Ã­ndices generado hubiese sido seis en lugar de tres.</Text>
+<Text id="376">Si una colecciÃ³n contiene documentos en distintas lenguas, se pueden crear Ã­ndices separados para cada lengua. La lengua es una instrucciÃ³n de metadato; los valores se especifican a travÃ©s de la norma ISO 639 que consta de un cÃ³digo de dos letras para representar los idiomas, por ejemplo,Â <i>en</i>Â para inglÃ©s,Â <i>zh</i>Â para chino yÂ <i>mi</i>Â para maorÃ­. Puesto que los valores de los metadatos pueden especificarse en el nivel de la secciÃ³n, las diferentes partes de un documento pueden estar en distintos idiomas.</Text>
+<Text id="377">Por ejemplo, si el archivo de configuraciÃ³n incluyese:</Text>
+<CodeLine>indexes section:text section:Title document:text paragraph:text</CodeLine>
+<CodeLine>languages en zh mi</CodeLine>
+<Text id="378">los Ã­ndices correspondientes al texto de la secciÃ³n, al tÃ­tulo de la secciÃ³n, al texto del documento y al texto de los pÃ¡rrafos se crearÃ­an en inglÃ©s, chino y maorÃ­: doce Ã­ndices en total. Si se aÃ±aden un par de subcolecciones se multiplica de nuevo el nÃºmero de Ã­ndices. Es preciso tener cuidado a fin de evitar recargar el Ã­ndice.</Text>
+<Text id="379">(Esta especificaciÃ³n del Ã­ndice podrÃ­a definirse mediante la funciÃ³nÂ <i>subcollection</i>Â en vez de la funciÃ³nÂ <i>languages</i>. Sin embargo, como la sintaxis impide crear subcolecciones de subcolecciones, serÃ­a imposible indizar cada lengua por separado en las subcolecciones.)</Text>
+</Content>
+</Subsection>
+<Subsection id="cross-collection_searching">
+<Title>
+<Text id="380">BÃºsqueda transversal en las colecciones</Text>
+</Title>
+<Content>
+<Text id="381">Greenstone tiene una funciÃ³n de âbÃºsqueda transversal en las coleccionesâ que permite buscar en varias colecciones a la vez y combinar los resultados âentre bastidoresâ como si se estuviera buscando en una sola colecciÃ³n unificada. Se puede buscar en cualquier subconjunto de colecciones: la pÃ¡gina deÂ <i>Preferencias</i>Â le permite elegir las colecciones que se han de incluir en las bÃºsquedas.</Text>
+<Text id="382">La bÃºsqueda transversal en las colecciones se activa mediante la lÃ­nea siguiente:</Text>
+<CodeLine>supercollection col_1 col_2 ...</CodeLine>
+<Text id="383">en que las colecciones en cuestiÃ³n se denominanÂ <i>col_1</i>,Â <i>col_2</i>, ... La misma lÃ­nea debe figurar en el archivo de configuraciÃ³n de cada una de las colecciones en cuestiÃ³n.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="getting_the_most_out_of_your_documents">
+<Title>
+<Text id="384">EXPLOTACIÃN ÃPTIMA DE SUS DOCUMENTOS</Text>
+</Title>
+<Content>
+<Text id="385">Las colecciones pueden personalizarse para que la informaciÃ³n que contienen sea accesible de distintas maneras. En este capÃ­tulo se explica la manera en que Greenstone extrae la informaciÃ³n de los documentos y la presenta al usuario: el tratamiento de los documentos (SecciÃ³n <CrossRef target="Section" ref="plugins"/>), las estructuras de clasificaciÃ³n (SecciÃ³n <CrossRef target="Section" ref="classifiers"/>) y las herramientas de la interfaz de usuario (Secciones <CrossRef target="Section" ref="formatting_greenstone_output"/> y <CrossRef target="Section" ref="controlling_the_greenstone_user_interface"/>).</Text>
+<Section id="plugins">
+<Title>
+<Text id="386">Conectores (<i>plugins</i>)</Text>
+</Title>
+<Content>
+<Text id="387">Los conectores analizan los documentos importados y extraen los metadatos. El conector HTML, por ejemplo, convierte las pÃ¡ginas HTML en el Formato de Archivo Greenstone y extrae los metadatos que estÃ¡n explÃ­citos en el formato del documento, como los tÃ­tulos entre etiquetas &lt;title&gt; &lt;/title&gt;.</Text>
+<Text id="388">Los conectores se escriben en lenguaje Perl. Todos proceden de un conector bÃ¡sico denominadoÂ <i>BasPlug</i>, que realiza todas las operaciones necesarias como crear un nuevo documento en el Formato de Archivo Greenstone con que trabajar, asignar un identificador de objeto (OID) y manejar las secciones de un documento. Los conectores se guardan en el directorioÂ <i>perllib/plugins</i>.</Text>
+<Text id="389">Para saber mÃ¡s sobre un conector cualquiera, escribaÂ <i>pluginfo.pl nombre-de-conector</i>Â en la lÃ­nea de comandos. (Es preciso que active primero el guiÃ³n de configuraciÃ³n âÂ <i>setup</i>Â --adecuado, si aÃºn no lo ha hecho, y en Windows ha de teclearÂ <i>perlÂ  âS pluginfo.pl nombre de conector</i>Â si su sistema no estÃ¡ configurado para reconocer los archivos que terminan enÂ <i>.pl</i>Â como ejecutables de Perl). Aparece entonces en la pantalla la informaciÃ³n sobre el conector: quÃ© opciones especÃ­ficas admite y quÃ© opciones generales se autorizan.</Text>
+<Text id="390">Puede usted escribir fÃ¡cilmente nuevos conectores para tratar formatos de documentos que los conectores existentes no manejan, formatear documentos de determinada manera o extraer un nuevo tipo de metadatos.</Text>
+<Subsection id="general_options">
+<Title>
+<Text id="391">Opciones generales</Text>
+</Title>
+<Content>
+<Text id="392">En el Cuadro <CrossRef target="Table" ref="options_applicable_to_all_plugins"/> se muestran las opciones que admite cualquier conector derivado de BasPlug.</Text>
+<Table id="options_applicable_to_all_plugins">
+<Title>
+<Text id="393">Opciones vÃ¡lidas para todos los conectores</Text>
+</Title>
+<TableContent>
+<tr>
+<th>
+<CodeLine><i>input_encoding</i></CodeLine>
+</th>
+<th>
+<Text id="394">CodificaciÃ³n de los caracteres utilizados en los documentos de origen. Por defecto Greenstone averigua automÃ¡ticamente la codificaciÃ³n de cada documento. Sin embargo, algunas veces conviene definir este valor. Por ejemplo, si se sabe con certeza que todos los documentos estÃ¡n en ASCII, el hecho de establecer la codificaciÃ³n de los datos de entrada enÂ <i>ascii</i>Â incrementa considerablemente la velocidad de importaciÃ³n y creaciÃ³n de la colecciÃ³n. Hay muchos valores posibles: tecleeÂ <i>pluginfo.pl BasPlug</i>Â para obtener una lista completa.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>default_encoding</i></CodeLine>
+</th>
+<th>
+<Text id="395">CodificaciÃ³n utilizada siÂ <i>input_encoding</i>Â estÃ¡ enÂ <i>auto</i>Â y falla la detecciÃ³n automÃ¡tica de la codificaciÃ³n.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>process_exp</i></CodeLine>
+</th>
+<th>
+<Text id="396">ExpresiÃ³n regular en Perl para detectar los nombres de archivo (por ejemplo, para localizar un tipo determinado de extensiÃ³n de archivo). Esto determina quÃ© archivos debe tratar un conector. Todo conector tiene una extensiÃ³n por defecto (el valor por defecto deÂ <i>HTMLPlug</i>Â esÂ <i>(?i).html?</i>, o sea, cualquier archivo con la extensiÃ³nÂ <i>.htm</i>Â oÂ <i>.html</i>).</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>block_exp</i></CodeLine>
+</th>
+<th>
+<Text id="397">Una expresiÃ³n regular para detectar los nombres de archivo que no van a pasarse a otros conectores. Esta operaciÃ³n puede evitar la apariciÃ³n de mensajes de error molestos sobre archivos que no interesan. Algunos conectores tienen expresiones de bloqueo por defecto, por ejemplo,Â <i>HTMLPlug</i>Â bloquea los archivos con extensionesÂ <i>.gif</i>,Â <i>.jpg</i>,Â <i>.jpeg</i>,Â <i>.png</i>,Â <i>.rtf</i>Â yÂ <i>.css</i>.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>cover_image</i></CodeLine>
+</th>
+<th>
+<Text id="398">Busca un archivoÂ <i>.jpg</i>Â (con el mismo nombre que el archivo en curso de tratamiento) y lo asocia con el documento como imagen de portada.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>extract_acronyms</i></CodeLine>
+</th>
+<th>
+<Text id="399">Extrae siglas de los documentos y las aÃ±ade como metadatos a los correspondientes documentos en el Formato de Archivo Greenstone.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>markup_acronyms</i></CodeLine>
+</th>
+<th>
+<Text id="400">AÃ±ade informaciÃ³n sobre las siglas al texto del documento.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>extract_language</i></CodeLine>
+</th>
+<th>
+<Text id="401">Identifica la lengua de cada documento y la asocia como metadato. ObsÃ©rvese que esto se hace de forma automÃ¡tica si la opciÃ³nÂ <i>input_encoding</i>Â estÃ¡ en posiciÃ³nÂ <i>auto</i>.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>default_language</i></CodeLine>
+</th>
+<th>
+<Text id="402">Si falla la extracciÃ³n automÃ¡tica de la lengua, el metadato de lengua adopta este valor.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>first</i></CodeLine>
+</th>
+<th>
+<Text id="403">Extrae una lista separada por comas de la primera porciÃ³n de texto y la incorpora como metadatoÂ <i>FirstNNN</i>Â (se utiliza a menudo como sustituto delÂ <i>Title</i>).</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>extract_email</i></CodeLine>
+</th>
+<th>
+<Text id="404">Extrae las direcciones electrÃ³nicas y las aÃ±ade como metadatos del documento.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<CodeLine><i>extract_date</i></CodeLine>
+</th>
+<th>
+<Text id="405">Extrae las fechas relacionadas con el contenido de documentos histÃ³ricos y los incluye como metadatos de tipoÂ <i>Coverage</i>.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+<Subsection id="subsection_conectores_de_tratamiento_de_documentos">
+<Title>
+<Text id="406">Conectores de tratamiento de documentos</Text>
+</Title>
+<Content>
+<Table id="table_conectores_de_greenstone">
+<Title>
+<Text id="407">Conectores de Greenstone</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="@width"/>
+<th width="@width"/>
+<th>
+<Text id="408"><b>Objetivo</b></Text>
+</th>
+<th>
+<Text id="409"><b>Tipos de archivo</b></Text>
+</th>
+<th>
+<Text id="410"><b>Ignora archivos</b></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="411"><b>Generales</b></Text>
+</th>
+<th>
+<Text id="412">ArcPlug</Text>
+</th>
+<th>
+<Text id="413">Trata los archivos mencionados en el archivoÂ <i>archives.inf</i>, que se utiliza como vector de comunicaciÃ³n entre los procesos de importaciÃ³n y de creaciÃ³n. Debe incluirse (a menos que no se vaya a utilizarÂ <i>import.pl</i>)</Text>
+</th>
+<th>
+<Text id="414"><i>-</i></Text>
+</th>
+<th>
+<Text id="415"><i>-</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="416"><i>RecPlug</i></Text>
+</th>
+<th>
+<Text id="417">Explora recursivamente una estructura de directorios para comprobar si un nombre de archivo corresponde a un directorio y, de ser asÃ­, insertar todos los archivos del directorio en la secuencia de los conectores. Asigna metadatos si la opciÃ³nÂ <i>âuse_metadata_files</i>Â estÃ¡ activada y los archivosÂ <i>metadata.xml</i>Â estÃ¡n presentes.</Text>
+</th>
+<th>
+<Text id="418"><i>-</i></Text>
+</th>
+<th>
+<Text id="419"><i>-</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="420"><i>GAPlug</i></Text>
+</th>
+<th>
+<Text id="421">Trata los archivos en el Formato de Archivo Greenstone generados porÂ <i>import.pl</i>. Debe incluirse (a menos que no se vaya a utilizarÂ <i>import.pl</i>).</Text>
+</th>
+<th>
+<Text id="422"><i>.xml</i></Text>
+</th>
+<th>
+<Text id="423"><i>-</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="424"><i>TEXTPlug</i></Text>
+</th>
+<th>
+<Text id="425">Trata texto sin formato colocÃ¡ndolo entre etiquetas &lt;pre&gt; &lt;/pre&gt; (tratÃ¡ndolo como si estuviera previamente formateado).</Text>
+</th>
+<th>
+<Text id="426"><i>.txt, .text</i></Text>
+</th>
+<th>
+<Text id="427"><i>-</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="428"><i>HTMLPlug</i></Text>
+</th>
+<th>
+<Text id="429">Trata el HTML, sustituyendo adecuadamente los hipervÃ­nculos. Si el documento al que apunta el hipervÃ­nculo no se encuentra en la colecciÃ³n, se inserta una pÃ¡gina intermedia que avisa al usuario de que estÃ¡ saliendo de la colecciÃ³n. Extrae los metadatos ya disponibles, comoÂ <i>Title</i>.</Text>
+</th>
+<th>
+<Text id="430"><i>.htm, .html, .cgi, .php, .asp, .shm, .shtml</i></Text>
+</th>
+<th>
+<Text id="431"><i>.gif, .jpeg, .jpg, .png, .css, .rtf</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="432"><i>WordPlug</i></Text>
+</th>
+<th>
+<Text id="433">Trata los documentos en formato Word de Microsoft, extrae el autor y el tÃ­tulo cuando estÃ¡n disponibles y mantiene los diagramas e imÃ¡genes en sus lugares adecuados. Las aplicaciones de conversiÃ³n utilizadas por este conector generan algunas veces HTML mal formateados y, por consiguiente, le recomendamos que proporcione los documentos originales para su visualizaciÃ³n cuando cree colecciones de archivos WORD. Sin embargo, el texto que se extrae de los documentos es apropiado a efectos de bÃºsqueda e indizaciÃ³n.</Text>
+</th>
+<th>
+<Text id="434"><i>.doc</i></Text>
+</th>
+<th>
+<Text id="435"><i>.gif, .jpeg, .jpg, .png, .css, .rtf</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="436"><i>PDFPlug</i></Text>
+</th>
+<th>
+<Text id="437">Trata documentos PDF y extrae la primera lÃ­nea del texto como tÃ­tulo. El programaÂ <i>pdftohtml</i>Â no logra tratar algunos archivos PDF. Lo que ocurre es que el proceso de conversiÃ³n lleva un tiempo excesivo y a menudo aparece en pantalla un mensaje de error al respecto. Si esto ocurre, la Ãºnica soluciÃ³n que podemos proponerle es suprimir de la colecciÃ³n el documento problemÃ¡tico y volverla a importar.</Text>
+</th>
+<th>
+<Text id="438"><i>.pdf</i></Text>
+</th>
+<th>
+<Text id="439"><i>.gif, .jpeg, .jpg, .png, .css, .rtf</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="440"><i>PSPlug</i></Text>
+</th>
+<th>
+<Text id="441">Trata documentos PostScript y opcionalmente extrae los metadatos de fecha, tÃ­tulo y nÃºmero de pÃ¡gina.</Text>
+</th>
+<th>
+<Text id="442"><i>.ps</i></Text>
+</th>
+<th>
+<Text id="443"><i>.eps</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="444"><i>EMAILPlug</i></Text>
+</th>
+<th>
+<Text id="445">Trata los mensajes de correo electrÃ³nico y reconoce el autor, el asunto, la fecha, etc. Este conector aÃºn no maneja adecuadamente los correos electrÃ³nicos codificados con MIME; aunque son legibles, suelen tener un aspecto bastante extraÃ±o.</Text>
+</th>
+<th>
+<Text id="446">Debe terminar por dÃ­gitos o por dÃ­gitos seguidos de .Email</Text>
+</th>
+<th>
+<Text id="447"><i>-</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="448"><i>BibTexPlug</i></Text>
+</th>
+<th>
+<Text id="449">Trata los archivos bibliogrÃ¡ficos en formatoÂ <i>BibTeX</i></Text>
+</th>
+<th>
+<Text id="450"><i>.bib</i></Text>
+</th>
+<th>
+<Text id="451"><i>-</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="452"><i>ReferPlug</i></Text>
+</th>
+<th>
+<Text id="453">Trata los archivos bibliogrÃ¡ficos en formatoÂ <i>refer</i></Text>
+</th>
+<th>
+<Text id="454"><i>.bib</i></Text>
+</th>
+<th>
+<Text id="455"><i>-</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="456"><i>SRCPlug</i></Text>
+</th>
+<th>
+<Text id="457">Trata los archivos de cÃ³digo fuente</Text>
+</th>
+<th>
+<Text id="458"><i>Makefile, Readme, .c, .cc, .cpp, .h, .hpp, .pl, .pm, .sh</i></Text>
+</th>
+<th>
+<Text id="459"><i>.o, .obj, .a, .so, .dll</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="460"><i>ImagePlug</i></Text>
+</th>
+<th>
+<Text id="461">Trata los archivos de imÃ¡genes para crear una biblioteca de imÃ¡genes. SÃ³lo funciona con UNIX.</Text>
+</th>
+<th>
+<Text id="462"><i>.jpeg, .jpg, .gif, .png, .bmp, .xbm, .tif, .tiff</i></Text>
+</th>
+<th>
+<Text id="463"><i>-</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="464"><i>SplitPlug</i></Text>
+</th>
+<th>
+<Text id="465">Como BasPlug y ConvertToPlug, este conector no debe activarse directamente; en cambio, puede ser heredado por conectores que necesiten tratar archivos que contengan varios documentos</Text>
+</th>
+<th>
+<Text id="466"><i>-</i></Text>
+</th>
+<th>
+<Text id="467"><i>-</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="468"><i>FOXPlug</i></Text>
+</th>
+<th>
+<Text id="469">Trata los archivos dbt de FoxBASE</Text>
+</th>
+<th>
+<Text id="470"><i>.dbt, .dbf,</i></Text>
+</th>
+<th>
+<Text id="471"><i>-</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="472"><i>ZIPPlug</i></Text>
+</th>
+<th>
+<Text id="473">Descomprime archivosÂ <i>gzip</i>,Â <i>bzip</i>,Â <i>zip</i>Â yÂ <i>tar</i>Â siempre que se disponga de las herramientas GNU adecuadas</Text>
+</th>
+<th>
+<Text id="474"><i>.gzip, .bzip, .zip, .tar, .gz, .bz, .tgz, .taz</i></Text>
+</th>
+<th>
+<Text id="475"><i>-</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="476"><b>EspecÃ­ficos de una colecciÃ³n</b></Text>
+</th>
+<th>
+<Text id="477"><i>PrePlug</i></Text>
+</th>
+<th>
+<Text id="478">Trata la salida HTML utilizando PRESCRIPT y divide los documentos en pÃ¡ginas para la colecciÃ³nÂ <i>Computer Science Tecnical Reports</i></Text>
+</th>
+<th>
+<Text id="479"><i>.html, .html.gz</i></Text>
+</th>
+<th>
+<Text id="480"><i>-</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="481"><i>GBPlug</i></Text>
+</th>
+<th>
+<Text id="482">Trata el texto electrÃ³nico del Proyecto Gutenberg, que incluye informaciÃ³n sobre tÃ­tulos introducida manualmente.</Text>
+</th>
+<th>
+<Text id="483"><i>.txt.gz, .html, .htm</i></Text>
+</th>
+<th>
+<Text id="484"><i>-</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="485"><i>TCCPlug</i></Text>
+</th>
+<th>
+<Text id="486">Trata los documentos de correo electrÃ³nico procedentes deÂ <i>ComputistsÂŽ Weekly</i>Â (el semanario de los informÃ¡ticos)</Text>
+</th>
+<th>
+<Text id="487">Debe empezar por <i>tcc o cw</i></Text>
+</th>
+<th>
+<Text id="488"><i>-</i></Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="489">Los programas de creaciÃ³n de colecciÃ³n utilizan conectores de tratamiento de documentos para analizar los documentos de origen en funciÃ³n de su formato. En el archivo de configuraciÃ³n de colecciÃ³n se enumeran todos los conectores utilizados durante el proceso de creaciÃ³n. Durante la operaciÃ³n de importaciÃ³n, cada archivo o directorio pasa uno a uno por todos los conectores, siguiendo el orden establecido, hasta que encuentra uno que puede tratarlo; asÃ­ pues, los primeros conectores de la lista tienen prioridad sobre los Ãºltimos. Si ningÃºn conector puede tratar el archivo, aparece un aviso (en error estÃ¡ndar) y el tratamiento pasa al archivo siguiente. (En este caso la opciÃ³nÂ <i>block_exp</i>Â puede resultar Ãºtil a fin de evitar estos mensajes de error para los archivos que pueden estar presentes pero no necesitan tratamiento.) Durante la etapa de creaciÃ³n de la colecciÃ³n se aplica el mismo procedimiento, pero se trata el directorioÂ <i>archives</i>Â en lugar del directorioÂ <i>import</i>.</Text>
+<Text id="490">Los conectores estÃ¡ndar de Greenstone se enumeran en el Cuadro <CrossRef target="Table" ref="greenstone_plugins"/>. Es preciso utilizar un procedimiento recursivo para recorrer transversalmente jerarquÃ­as de directorios. Aunque los programas de importaciÃ³n y creaciÃ³n no efectÃºan una recursiÃ³n explÃ­cita, algunos conectores provocan una recursiÃ³n indirecta al introducir nombres de archivos o de directorios en la secuencia de los conectores. Por ejemplo, el modo estÃ¡ndar de recursiÃ³n a travÃ©s de una jerarquÃ­a de directorio consiste en especificarÂ <i>RecPlug</i>, que realiza exactamente esta operaciÃ³n. Si estÃ¡ presente, deberÃ­a ser el Ãºltimo elemento en la secuencia. SÃ³lo los dos primeros conectores del Cuadro <CrossRef target="Table" ref="greenstone_plugins"/> provocan una recursiÃ³n indirecta.</Text>
+<Text id="491">Algunos conectores estÃ¡n escritos para colecciones especÃ­ficas que tienen un formato de documento que no se encuentra en ninguna otra parte, como el texto electrÃ³nico utilizado en la colecciÃ³n Gutenberg. Estos conectores especÃ­ficos de una colecciÃ³n se encuentran en el directorioÂ <i>perllib/plugins</i>Â de la colecciÃ³n. Los conectores especÃ­ficos de colecciÃ³n pueden utilizarse para invalidar los conectores generales que llevan el mismo nombre.</Text>
+<Text id="492">Algunos conectores de tratamiento de documentos utilizan programas externos que analizan determinados formatos patentados, como por ejemplo Word de Microsoft, y los transforman en texto normal o en HTML. Un conector general denominadoÂ <i>ConvertToPlug</i>Â activa el programa de conversiÃ³n correspondiente y pasa el resultado aÂ <i>TEXTPlug</i>Â o aÂ <i>HTMLPlug</i>. MÃ¡s adelante se explicarÃ¡ mÃ¡s detalladamente esta operaciÃ³n.</Text>
+<Text id="493">Algunos conectores disponen de opciones especÃ­ficas que permiten controlar sus operaciones de manera mÃ¡s precisa que las opciones generales. VÃ©ase al respecto el Cuadro <CrossRef target="Table" ref="plugin-specific_options"/>.</Text>
+<Table id="plugin-specific_options">
+<Title>
+<Text id="494">Opciones especÃ­ficas de los conectores</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="@width"/>
+<th>
+<Text id="495"><b>OpciÃ³n</b></Text>
+</th>
+<th>
+<Text id="496"><b>Objetivo</b></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="497">HTMLPlug</Text>
+</th>
+<th>
+<Text id="498"><i>nolinks</i></Text>
+</th>
+<th>
+<Text id="499">No guarda enlaces dentro de la colecciÃ³n. Esto acelera el proceso de importaciÃ³n/creaciÃ³n, pero se pierden todos los enlaces de la colecciÃ³n.</Text>
+</th>
+</tr>
+<tr>
+<th>Â </th>
+<th>
+<Text id="500"><i>description_tags</i></Text>
+</th>
+<th>
+<Text id="501">Interpreta los archivos de documentos etiquetados como se explica en la subsecciÃ³n siguiente.</Text>
+</th>
+</tr>
+<tr>
+<th>Â </th>
+<th>
+<Text id="502"><i>keep_head</i></Text>
+</th>
+<th>
+<Text id="503">No quita los encabezados HTML.</Text>
+</th>
+</tr>
+<tr>
+<th>Â </th>
+<th>
+<Text id="504"><i>no_metadata</i></Text>
+</th>
+<th>
+<Text id="505">No busca ningÃºn metadato (esto puede acelerar el proceso de importaciÃ³n/creaciÃ³n).</Text>
+</th>
+</tr>
+<tr>
+<th>Â </th>
+<th>
+<Text id="506"><i>metadata_fields</i></Text>
+</th>
+<th>
+<Text id="507">Toma una lista separada por comas de tipos de metadatos (cuyo valor por defecto esÂ <i>Title</i>) que se han de extraer. Para cambiar el nombre de los metadatos en el archivo en el Formato de Archivo Greenstone, utiliceÂ <i>tag&lt;nuevo_nombre&gt;</i>, en queÂ <i>tag</i>Â es la etiqueta HTML buscada yÂ <i>nuevo_nombre</i>Â su nuevo nombre.</Text>
+</th>
+</tr>
+<tr>
+<th>Â </th>
+<th>
+<Text id="508"><i>hunt_creator_metadata</i></Text>
+</th>
+<th>
+<Text id="509">Encuentra el mayor nÃºmero posible de metadatos sobre la autorÃ­a del documento y los consigna en el documento en el Formato de Archivo Greenstone como metadatosÂ <i>Creator</i>. Se debe incluir tambiÃ©nÂ <i>Creator</i>Â mediante la opciÃ³nÂ <i>metadata_fields</i>.</Text>
+</th>
+</tr>
+<tr>
+<th>Â </th>
+<th>
+<Text id="510"><i>file_is_url</i></Text>
+</th>
+<th>
+<Text id="511">Utilice esta opciÃ³n si se ha usado un programa de duplicaciÃ³n o espejo Web para crear la estructura de los documentos por importar.</Text>
+</th>
+</tr>
+<tr>
+<th>Â </th>
+<th>
+<Text id="512"><i>assoc_files</i></Text>
+</th>
+<th>
+<Text id="513">Asigna una expresiÃ³n regular de Perl que define los tipos de archivos que se han de tratar como archivos asociados. Los tipos por defecto son:Â <i>.jpg</i>,Â <i>.jpeg</i>,Â <i>.gif</i>,Â <i>.png</i>,Â <i>.css.</i></Text>
+</th>
+</tr>
+<tr>
+<th>Â </th>
+<th>
+<Text id="514"><i>rename_assoc_files</i></Text>
+</th>
+<th>
+<Text id="515">Cambia el nombre de los archivos asociados con los documentos. Durante este proceso, la estructura de directorio de todo archivo asociado reducirÃ¡ mucho su volumen (opciÃ³n Ãºtil si se ha de almacenar la colecciÃ³n en un espacio limitado).</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="516"><i>HTMLPlug</i> y <br/><i>TEXTPlug</i></Text>
+</th>
+<th>
+<Text id="517"><i>title_sub</i></Text>
+</th>
+<th>
+<Text id="518">ExpresiÃ³n de sustituciÃ³n Perl para modificar los tÃ­tulos.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="519"><i>PSPlug</i></Text>
+</th>
+<th>
+<Text id="520"><i>extract_date</i></Text>
+</th>
+<th>
+<Text id="521">Extrae la fecha de creaciÃ³n del encabezado PostScript y la almacena como metadato.</Text>
+</th>
+</tr>
+<tr>
+<th>Â </th>
+<th>
+<Text id="522"><i>extract_title</i></Text>
+</th>
+<th>
+<Text id="523">Extrae el tÃ­tulo del documento del encabezado PostScript y lo almacena como metadato de tÃ­tulo.</Text>
+</th>
+</tr>
+<tr>
+<th>Â </th>
+<th>
+<Text id="524"><i>extract_pages</i></Text>
+</th>
+<th>
+<Text id="525">Extrae los nÃºmeros de pÃ¡gina del documento PostScript y los incluye en las secciones adecuadas como metadatos con la etiquetaÂ <i>Pages</i>.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="526"><i>RecPlug</i></Text>
+</th>
+<th>
+<Text id="527"><i>use_metadata_files</i></Text>
+</th>
+<th>
+<Text id="528">Asigna metadatos desde un archivo, como se explica en la subsecciÃ³n siguiente.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="529"><i>ImagePlug</i></Text>
+</th>
+<th>
+<Text id="530">Diversas opciones</Text>
+</th>
+<th>
+<Text id="531">VÃ©aseÂ <i>ImagePlug.pm</i>. </Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="532"><i>SRCPlug</i></Text>
+</th>
+<th>
+<Text id="533"><i>remove_prefix</i></Text>
+</th>
+<th>
+<Text id="534">Especifica en forma de expresiÃ³n regular de Perl,Â un patrÃ³n inicial que debe eliminarse del nombre del archivo. El comportamiento por defecto es suprimir toda la ruta.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+<Subsection id="plugins_to_import_proprietary_formats">
+<Title>
+<Text id="535">Conectores de importaciÃ³n de formatos patentados</Text>
+</Title>
+<Content>
+<Text id="536">Los formatos patentados plantean serias dificultades para cualquier sistema de biblioteca digital. Aunque se disponga de documentaciÃ³n sobre su funcionamiento, pueden ser modificados sin aviso y resulta difÃ­cil mantenerse al tanto de los cambios. Greenstone ha optado por utilizar las aplicaciones de conversiÃ³n publicadas segÃºn los tÃ©rminos de la GPL (Licencia PÃºblica General de GNU) y elaboradas por personas dedicadas a esta tarea. Los instrumentos para convertir formatos Word y PDF se encuentran en el directorioÂ <i>packages</i>. Estos convierten los documentos en texto normal o en HTML. Se utilizan posteriormenteÂ <i>HTMLPlug</i>Â yÂ <i>TEXTPlug</i>Â para convertirlos en el Formato de Archivo Greenstone.Â <i>ConvertToPlug</i>Â sirve para incluir los instrumentos de conversiÃ³n y, al igual queÂ <i>BasPlug</i>, nunca se activa directamente, sino que los conectores de tratamiento de formatos especÃ­ficos derivan o heredan de Ã©l, como se ilustra en la Figura <CrossRef target="Figure" ref="plugin_inheritance_hierarchy"/>.Â <i>ConvertToPlug</i>Â emplea el sistema de herencia dinÃ¡mico de Perl para heredar deÂ <i>TEXTPlug</i>Â o deÂ <i>HTMLPlug</i>, segÃºn el formato en el que se ha convertido el documento de origen.</Text>
+<Figure id="plugin_inheritance_hierarchy">
+<Title>
+<Text id="537">JerarquÃ­a de herencia de los conectores</Text>
+</Title>
+<File width="206" height="229" url="images/Dev_Fig_9.png"/>
+</Figure>
+<Text id="538">CuandoÂ <i>ConvertToPlug</i>Â recibe un documento, acude aÂ <i>gsConvert.pl</i>Â (que se encuentra enÂ <i>GSDLHOME/bin/script</i>) para activar el instrumento de conversiÃ³n adecuado. Una vez convertido, el documento es devuelto aÂ <i>ConvertToPlug</i>, que aplica el conector texto o HTML, segÃºn convenga. Todo conector derivado deÂ <i>ConvertToPlug</i>Â dispone de una opciÃ³nÂ <i>convert_to</i>Â (convertir en), cuyo argumento esÂ <i>text</i>Â oÂ <i>html</i>, para especificar el formato intermedio que se prefiere. El formato texto es mÃ¡s rÃ¡pido, pero HTML suele tener una mejor presentaciÃ³n e incluye imÃ¡genes.</Text>
+<Text id="539">Existen a veces varios instrumentos de conversiÃ³n para un formato particular yÂ <i>gsConvert</i>Â puede probar varios de ellos en un documento. Por ejemplo, el instrumento de conversiÃ³n mÃ¡s comÃºn de Word,Â <i>wvWare</i>, sÃ³lo funciona con Word 6, y para convertir los documentos Word 5 se utiliza un programa denominadoÂ <i>AnyToHTML</i>, cuya principal funciÃ³n es extraer todas las cadenas de texto que puede encontrar.</Text>
+<Text id="540">Las etapas necesarias para agregar un nuevo programa de conversiÃ³n de documentos externos son las siguientes:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="541">Instale el nuevo programa de conversiÃ³n para que sea accesible por Greenstone (colÃ³quelo en el directorioÂ <i>packages</i>).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="542">ModifiqueÂ <i>gsConvert.pl</i>Â para utilizar el nuevo programa de conversiÃ³n. Esto implica aÃ±adir una nueva clÃ¡usula a la instrucciÃ³nÂ <i>if</i>Â de la funciÃ³nÂ <i>main</i>, y agregar una funciÃ³n que active el programa de conversiÃ³n.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="543">Escriba un conector de nivel superior que herede deÂ <i>ConvertToPlug</i>Â para interceptar el formato y luego dejarlo âpasar adelanteâ.</Text>
+</NumberedItem>
+</NumberedList>
+</Content>
+</Subsection>
+<Subsection id="assigning_metadata_from_a_file">
+<Title>
+<Text id="544">Asignar metadatos desde un archivo</Text>
+</Title>
+<Content>
+<Text id="545">El conector estÃ¡ndarÂ <i>RecPlug</i>Â incorpora asimismo la posibilidad de asignar metadatos a los documentos a partir de archivos XML creados manual o automÃ¡ticamente. Vamos a explicar detalladamente el proceso para que pueda usted crear archivos de metadatos en el formato adecuado. Si se especifica la opciÃ³nÂ <i>use_metadata_files</i>,Â <i>RecPlug</i>Â utiliza un archivo de metadatos auxiliar llamadoÂ <i>metadata.xml</i>. En la Figura <CrossRef target="Figure" ref="xml_format"/> se muestra la DefiniciÃ³n de Tipo de Documento (DTD) XML para el formato de archivo de metadatos, mientras que la figura <CrossRef target="Figure" ref="xml_format_1"/> muestra un ejemplo de archivoÂ <i>metadata.xml</i>.</Text>
+<Figure id="xml_format">
+<Title>
+<Text id="546">Formato XML:</Text>
+<SubTitle>
+<Text id="547">a) DefiniciÃ³n de Tipo de Documento (DTD);</Text>
+</SubTitle>
+</Title>
+<CodeLine>&lt;!DOCTYPE GreenstoneDirectoryMetadataÂ Â  [</CodeLine>
+<CodeLine>&lt;!ELEMENT DirectoryMetadata (FileSet*)&gt;</CodeLine>
+<CodeLine>&lt;!ELEMENT FileSet (FileName+,Description)&gt;</CodeLine>
+<CodeLine>&lt;!ELEMENT FileName (#PCDATA)&gt;</CodeLine>
+<CodeLine>&lt;!ELEMENT Description (Metadata*)&gt;</CodeLine>
+<CodeLine>&lt;!ELEMENT Metadata (#PCDATA)&gt;</CodeLine>
+<CodeLine>&lt;ATTLIST Metadata name CDATA #REQUIRED&gt;</CodeLine>
+<CodeLine>&lt;ATTLIST Metadata mode (accumulate | override) âoverrideâ&gt;</CodeLine>
+<CodeLine>]&gt;</CodeLine>
+</Figure>
+<Figure id="xml_format_1">
+<Title>
+<Text id="548"/>
+<SubTitle>
+<Text id="549">b) Ejemplo de archivo de metadatos</Text>
+</SubTitle>
+</Title>
+<CodeLine>&lt;?xml version="1.0"Â ?&gt;</CodeLine>
+<CodeLine>&lt;!DOCTYPE GreenstoneDirectoryMetadata SYSTEM</CodeLine>
+<CodeLine>"http://greenstone.org/dtd/GreenstoneDirectoryMetadata/1.0/GreenstoneDirectoryMetadata.dtdâ&gt;</CodeLine>
+<CodeLine>&lt;DirectoryMetadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â  &lt;FileSet&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  &lt;FileName&gt;nugget.*&lt;/FileName&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  &lt;Metadata name=âTitleâ&gt;Nugget Point Lighthouse&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  &lt;Metadata name=âPlaceâ mode=âaccumulateâ&gt;Nugget Point&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â  &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â  &lt;/FileSet&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â  &lt;FileSet&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  &lt;FileName&gt;nugget-point-1.jpg&lt;/FileName&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  Â Â Â Â Â Â  &lt;Metadata name=âTitleâ&gt;Nugget Point Lighthouse, The Catlins&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  Â Â Â Â Â Â  &lt;Metadata name=âSubjectâ&gt;Lighthouse&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â  &lt;FileSet&gt;</CodeLine>
+<CodeLine>&lt;/DirectoryMetadata&gt;</CodeLine>
+</Figure>
+<Text id="550">El archivo de ejemplo contiene dos estructuras de metadatos. En cada una de ellas, el elementoÂ <i>filename</i>Â describe los archivos a los que se aplican los metadatos en forma de expresiÃ³n regular. AsÃ­ pues, &lt;FileName&gt;nugget.*&lt;/FileName&gt;Â <i/>Â indica que el primer registro de metadatos se aplica a todos los archivos cuyo nombre empieza por âÂ <i>nugget</i>Â â<FootnoteRef id="2"/>. Para estos archivos, el metadatoÂ <i>Title</i>Â se aplica a âNugget Point Lighthouseâ.</Text>
+<Text id="551">Los elementos de metadatos se tratan en el orden en que aparecen. La segunda estructura establece que el metadatoÂ <i>Title</i>Â para el archivoÂ <i>nugget-point-1.jpg</i>Â se aplica a âNugget Point Lighthouse, The Catlinsâ e invalida la especificaciÃ³n anterior. AÃ±ade asimismo un campo de metadatosÂ <i>Subject</i>.</Text>
+<Text id="552">Algunas veces los metadatos poseen varios valores y los nuevos valores deben acumularse en vez de invalidar los anteriores. El atributoÂ <i>mode=accumulate</i>Â activa esta opciÃ³n. Se aplica al metadatoÂ <i>Place</i>Â en la primera especificaciÃ³n que, por consiguiente, podrÃ¡ adoptar mÃºltiples valores. Para volver a un metadato simple, teclee &lt;Metadata name=âPlaceâ mode=âoverrideâ&gt;New Zealand&lt;/Metadata&gt;Â <i>.</i>Â De hecho, se podrÃ­a omitir esta especificaciÃ³n de modo porque todo elemento invalida el anterior, salvo si se indica lo contrario. Para acumular metadatos en un campo particular, se debe especificarÂ <i>mode=accumulate</i>Â en cada apariciÃ³n.</Text>
+<Text id="553">Cuando se activa la opciÃ³nÂ <i>use_metadata_files</i>,Â <i>RecPlug</i>Â comprueba en cada directorio de entrada la presencia de un archivo XML denominadoÂ <i>metadata.xml</i>Â y aplica su contenido a todos los archivos y subdirectorios del directorio.</Text>
+<Text id="554">El mecanismoÂ <i>metadata.xml</i>Â incorporado aÂ <i>RecPlug</i>Â es sÃ³lo un modo de especificar los metadatos para los documentos. Es fÃ¡cil escribir diferentes conectores que aceptan especificaciones de metadatos con formatos completamente diferentes.</Text>
+</Content>
+</Subsection>
+<Subsection id="tagging_document_files">
+<Title>
+<Text id="555">Etiquetado de los archivos de documentos</Text>
+</Title>
+<Content>
+<Text id="556">Los documentos de origen necesitan a menudo estructurarse en secciones y subsecciones, y es preciso comunicar esta informaciÃ³n a Greenstone a fin de que pueda mantener la estructura jerÃ¡rquica. Asimismo, se pueden asociar metadatos âen particular el tÃ­tuloâ con cada secciÃ³n y subsecciÃ³n.</Text>
+<Text id="557">La manera mÃ¡s sencilla de efectuar esta operaciÃ³n suele ser modificando los archivos de origen. El conector HTML dispone de una opciÃ³nÂ <i>description_tags</i>Â que trata las etiquetas en el texto como sigue:</Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>&lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â  &lt;Metadata name=âTitleâ&gt; Realizing human rights for poor people: Strategies for achieving the international development targets &lt;/Metadata&gt;</CodeLine>
+<CodeLine>&lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="558"><i>(el texto de la secciÃ³n va aquÃ­)</i></Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="559">Se utilizan los marcadores &lt;!-- ... --&gt; porque indican comentarios en formato HTML; en consecuencia, estas etiquetas de secciÃ³n no afectarÃ¡n al formateo del documento. En la parteÂ <i>Description</i>Â se pueden especificar otros tipos de metadatos, pero esto no ocurre para el estilo de colecciÃ³n que mencionamos aquÃ­. Asimismo, las etiquetas pueden subdividirse, de tal modo que la lÃ­nea anterior seÃ±alada por marcadoresÂ <i>el texto de la secciÃ³n va aquÃ­</i>Â pueda incluir a su vez otras subsecciones, como por ejemplo:</Text>
+<Text id="560"><i>(el texto de la primera parte de la secciÃ³n va aquÃ­)</i></Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>&lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â  &lt;Metadata name=âTitleâ&gt; The international development targets &lt;/Metadata&gt;</CodeLine>
+<CodeLine>&lt;Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="561"><i>(el texto de la subsecciÃ³n va aquÃ­)</i></Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="562"><i>(el texto de la Ãºltima parte de la secciÃ³n va aquÃ­)</i></Text>
+<Text id="563">Cualquier conector que utilice HTMLPlug hereda esta funciÃ³n. El conector Word, en particular, convierte en formato HTML los datos que recibe y por ello se pueden especificar los metadatos exactamente de la misma manera en los archivos Word (y RTF). (Esto supone un poco de trabajo âentre bastidoresâ, porque cuando los documentos Word se convierten en HTML, el programa por lo general procura neutralizar la interpretaciÃ³n especial que suele hacer HTML de los signos sueltos â&lt;â y â&gt;â; nos las hemos arreglado para invalidar esto en el caso de las especificaciones antes mencionadas.) ObsÃ©rvese que se utiliza exactamente el mismo formato que antes, incluso en los archivos Word, asÃ­ como los signos de comentarios â&lt;!--â y â--&gt;â. El tipo de letra y el espaciado no se tienen en cuenta.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="classifiers">
+<Title>
+<Text id="564">Clasificadores</Text>
+</Title>
+<Content>
+<Text id="565">Los clasificadores sirven para crear los Ã­ndices de consulta de la colecciÃ³n. Valgan como ejemplos el Ã­ndiceÂ <i>tÃ­tulos A-Z</i>Â de la colecciÃ³nÂ <i>dlpeople</i>, asÃ­ como los Ã­ndicesÂ <i>tema</i>,Â <i>cÃ³mo...</i>,Â <i>organizaciones</i>Â yÂ <i>tÃ­tulos A-Z</i>Â de la Biblioteca sobre Aspectos Humanitarios y de Desarrollo, de la que la colecciÃ³n de demostraciÃ³n es un subconjunto. La barra de desplazamiento que aparece en la parte superior de la pantalla en las Figuras 3 y 8a incluye la funciÃ³nÂ <i>bÃºsqueda</i>, que siempre estÃ¡ disponible, seguida de botones correspondientes a todos los clasificadores que se han definido. La informaciÃ³n utilizada para facilitar la consulta se encuentra en la base de datos de informaciones de la colecciÃ³n, donde es colocada por los clasificadores activados durante la fase final del programaÂ <i>buildcol.pl</i>.</Text>
+<Figure id="azlist_classifier">
+<Title>
+<Text id="566">ClasificadorÂ <i>AZList</i></Text>
+</Title>
+<File width="604" height="245" url="images/Dev_Fig_11.png"/>
+</Figure>
+<Text id="567">Los clasificadores, al igual que los conectores, se especifican en el archivo de configuraciÃ³n de la colecciÃ³n. Todos tienen una lÃ­nea que empieza por la palabra claveÂ <i>classify</i>Â seguida del nombre del clasificador y las opciones que admite. El archivo bÃ¡sico de configuraciÃ³n de la colecciÃ³n mencionado en la SecciÃ³n <CrossRef target="Section" ref="import_and_build_processes"/> comprende la lÃ­neaÂ <i>classify AZList âmetadata Title</i>, que crea una lista alfabÃ©tica de tÃ­tulos reuniendo todos aquÃ©llos que estÃ¡n provistos del campo de metadatosÂ <i>Title</i>, y los clasifica y divide por orden alfabÃ©tico. En la Figura <CrossRef target="Figure" ref="azlist_classifier"/> se muestra un ejemplo.</Text>
+<Figure id="list_classifier">
+<Title>
+<Text id="568">ClasificadorÂ <i>List</i></Text>
+</Title>
+<File width="605" height="280" url="images/Dev_Fig_12.png"/>
+</Figure>
+<Text id="569">Un clasificador mÃ¡s simple, llamadoÂ <i>List</i>, que se muestra en la Figura <CrossRef target="Figure" ref="list_classifier"/>, crea una lista clasificada de un elemento de metadato determinado y lo presenta sin ninguna subsecciÃ³n alfabÃ©tica. Un ejemplo es el metadatoÂ <i>cÃ³mo</i>Â de la colecciÃ³n de demostraciÃ³n, que es generado por la lÃ­neaÂ <i>classify List âmetadata Howto</i>Â en el archivo de configuraciÃ³n de la colecciÃ³n. Otro clasificador general esÂ <i>DateList</i>, ilustrado en la Figura <CrossRef target="Figure" ref="datelist_classifier"/>, que genera una lista de selecciÃ³n de intervalos de fechas. (El clasificadorÂ <i>DateList</i>Â se utiliza tambiÃ©n en la colecciÃ³n âArchivos de Greenstoneâ.)</Text>
+<Figure id="datelist_classifier">
+<Title>
+<Text id="570">ClasificadorÂ <i>DateList</i></Text>
+</Title>
+<File width="604" height="304" url="images/Dev_Fig_13.png"/>
+</Figure>
+<Text id="571">Otros clasificadores generan estructuras de consulta que son explÃ­citamente jerÃ¡rquicas. Las clasificaciones jerÃ¡rquicas son Ãºtiles para las clasificaciones y subclasificaciones temÃ¡ticas, asÃ­ como para las jerarquÃ­as relativas a organizaciones. El archivo de configuraciÃ³n de la colecciÃ³n de demostraciÃ³n incluye la lÃ­neaÂ <i>classify Hierarchy âhfile sub.txt âmetadata Subject âsort Title</i>, y en la Figura <CrossRef target="Figure" ref="hierarchy_classifier"/> se muestra la jerarquÃ­a de temas que esta lÃ­nea produce. El estante que lleva un tÃ­tulo en negrita es el que se estÃ¡ examinando en este momento; encima de Ã©l se puede ver la clasificaciÃ³n temÃ¡tica a la que pertenece. En este ejemplo la jerarquÃ­a de clasificaciÃ³n se guarda en un formato de texto sencillo que lleva el nombre deÂ <i>sub.txt</i>.</Text>
+<Figure id="hierarchy_classifier">
+<Title>
+<Text id="572">ClasificadorÂ <i>Hierarchy</i></Text>
+</Title>
+<File width="605" height="321" url="images/Dev_Fig_14.png"/>
+</Figure>
+<Text id="573">Todos los clasificadores generan una estructura jerÃ¡rquica que se utiliza para mostrar un Ã­ndice de consulta. Normalmente, los niveles inferiores de la jerarquÃ­a (esto es, las hojas) son los documentos, pero en algunos clasificadores son las secciones. Los nodos internos de la jerarquÃ­a sonÂ <i>Vlist</i>,Â <i>Hlist</i>Â oÂ <i>Datelist</i>. UnaÂ <i>Vlist</i>Â es una lista de elementos dispuestos verticalmente en la pÃ¡gina, como el Ã­ndice âÂ <i>cÃ³mo...</i>Â â de la colecciÃ³n de demostraciÃ³n (vÃ©ase la Figura <CrossRef target="Figure" ref="list_classifier"/>). UnaÂ <i>Hlist</i>Â tiene una presentaciÃ³n horizontal. Por ejemplo, laÂ <i>AZList</i>Â de la Figura <CrossRef target="Figure" ref="azlist_classifier"/> es una jerarquÃ­a de nodos internos de dos niveles compuesta por unaÂ <i>Hlist</i>Â (que da el selector A-Z) cuyos elementos secundarios son nodosÂ <i>Vlists</i>Â ; los documentos son a su vez elementos secundarios de esta Ãºltima lista. Un nodoÂ <i>Datelist</i>Â (Figura <CrossRef target="Figure" ref="datelist_classifier"/>) es un tipo especial del nodoÂ <i>Vlist</i>Â que permite efectuar selecciones por aÃ±o y por mes.</Text>
+<Text id="574">Las lÃ­neas que se utilizan para especificar los clasificadores en los archivos de configuraciÃ³n de colecciÃ³n contienen un argumentoÂ <i>metadata</i>Â que identifica los metadatos mediante los cuales se clasifican y seleccionan los documentos. El clasificador omitirÃ¡ todo documento de la colecciÃ³n para el que no se haya definido este metadato (pero se lo indizarÃ¡ y, por consiguiente, la funciÃ³n bÃºsqueda lo tendrÃ¡ en cuenta). Si no se especifica un argumentoÂ <i>metadata</i>, todos los documentos se incluyen en el clasificador, en el orden en que aparecieron durante el proceso de creaciÃ³n. Esto es Ãºtil si desea obtener una lista de todos los documentos de su colecciÃ³n.</Text>
+<Table id="greenstone_classifiers">
+<Title>
+<Text id="575">Clasificadores de Greenstone</Text>
+</Title>
+<TableContent>
+<tr>
+<th>
+<Text id="576"><b>Argumento</b></Text>
+</th>
+<th>
+<Text id="577"><b>Finalidad</b></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="578"><i>Hierarchy</i></Text>
+</th>
+<th>
+<Text id="579">ClasificaciÃ³n jerÃ¡rquica</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="580"><i>hfile</i></Text>
+</th>
+<th>
+<Text id="581">Archivo de clasificaciÃ³n</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="582"><i>metadata</i></Text>
+</th>
+<th>
+<Text id="583">Elemento de metadato para cotejar con el identificadorÂ <i>hfile</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="584"><i>sort</i></Text>
+</th>
+<th>
+<Text id="585">Elemento de metadato utilizado para clasificar los documentos en las hojas (el valor por defecto esÂ <i>Title</i>)</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="586"><i>buttonname</i></Text>
+</th>
+<th>
+<Text id="587">Nombre del botÃ³n utilizado para acceder a este clasificador (el valor por defecto es el valor del argumentoÂ <i>metadata</i>)</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="588">List</Text>
+</th>
+<th>
+<Text id="589">Lista alfabÃ©tica de los documentos</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="590"><i>metadata</i></Text>
+</th>
+<th>
+<Text id="591">Incluye los documentos que contienen este elemento de metadato</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="592"><i>buttonname</i></Text>
+</th>
+<th>
+<Text id="593">Nombre del botÃ³n utilizado para acceder a este clasificador (el valor por defecto es el valor del argumentoÂ <i>metadata</i>)</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="594"><i>SectionList</i></Text>
+</th>
+<th>
+<Text id="595">Lista de las secciones en los documentos</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="596"><i>AZList</i></Text>
+</th>
+<th>
+<Text id="597">Lista de documentos dividida por intervalos alfabÃ©ticos</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="598"><i>metadata</i></Text>
+</th>
+<th>
+<Text id="599">Incluye todos los documentos que contienen este elemento de metadato</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="600"><i>buttonname</i></Text>
+</th>
+<th>
+<Text id="601">Nombre del botÃ³n utilizado para acceder a este clasificador (el valor por defecto es el valor del argumentoÂ <i>metadata</i>)</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="602"><i>AZSectionList</i></Text>
+</th>
+<th>
+<Text id="603">ComoÂ <i>AZList</i>Â pero incluye cada secciÃ³n del documento</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="604"><i>DateList</i></Text>
+</th>
+<th>
+<Text id="605">Similar aÂ <i>AZList</i>Â pero ordenada por fechas</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="606">La lista de los clasificadores actualmente disponibles aparece en el Cuadro <CrossRef target="Table" ref="greenstone_classifiers"/>. Al igual que se puede utilizar el programaÂ <i>pluginfo.pl</i>Â para obtener informaciÃ³n sobre cualquier conector, el programaÂ <i>classinfo.pl</i>Â le facilita informaciÃ³n sobre cualquier clasificador y las opciones que ofrece.</Text>
+<Text id="607">Todos los clasificadores aceptan el argumentoÂ <i>buttonname</i>, que define el contenido del botÃ³n de consulta de Greenstone que activa el clasificador (el valor por defecto es el nombre del argumentoÂ <i>metadata</i>). Existen botones para cada tipo de metadato del sistema Dublin Core y para algunos otros tipos de metadatos.</Text>
+<Text id="608">Cada clasificador recibe un nombre implÃ­cito con arreglo a su posiciÃ³n en el archivo de configuraciÃ³n. Por ejemplo, el tercer clasificador especificado en el archivo se denomina CL3. Esos nombres se emplean para nombrar los campos de la base de datos de informaciones de la colecciÃ³n que definen la jerarquÃ­a de los clasificadores.</Text>
+<Text id="609">Se pueden escribir clasificadores especÃ­ficos para una colecciÃ³n, que se almacenan en el directorioÂ <i>perllib/classify</i>Â de la colecciÃ³n. La Biblioteca sobre Aspectos Humanitarios y de Desarrollo tiene un clasificador especÃ­fico de colecciÃ³n que se llamaÂ <i>HDLList</i>, que es una variante menor deÂ <i>AZList</i>.</Text>
+<Subsection id="list_classifiers">
+<Title>
+<Text id="610">Clasificadores de listas</Text>
+</Title>
+<Content>
+<Text id="611">A continuaciÃ³n figuran los diversos tipos de clasificadores de listas:</Text>
+<BulletList>
+<Bullet>
+<Text id="612"><i>SectionList</i>Â : es comoÂ <i>List</i>Â pero las hojas son secciones y no documentos. Se incluyen todas las secciones del documento excepto las del nivel superior. Este clasificador sirve para crear listas de secciones (o de artÃ­culos, capÃ­tulos, etc.), como en la colecciÃ³nÂ <i>Computistsâ Weekly</i>Â (el semanario de los informÃ¡ticos, disponible en el sitio WebÂ <i>nzdl.org</i>), en la que cada nÃºmero es un solo documento que comprende varios artÃ­culos independientes, cada uno en su propia secciÃ³n.</Text>
+</Bullet>
+<Bullet>
+<Text id="613"><i>AZList</i>Â : genera una jerarquÃ­a de dos niveles que comprende un nodoÂ <i>Hlist</i>Â cuyos elementos secundarios son nodosÂ <i>Vlists</i>, cuyos elementos secundarios, a su vez, son documentos. El nodoÂ <i>Hlist</i>Â es un selector A-Z que divide los documentos en intervalos alfabÃ©ticos.</Text>
+</Bullet>
+<Bullet>
+<Text id="614"><i>AZSectionList</i>Â : es como AZList pero las hojas son secciones y no documentos.</Text>
+</Bullet>
+<Bullet>
+<Text id="615"><i>DateList</i>Â : es comoÂ <i>AZList</i>Â excepto que el nodoÂ <i>Hlist</i>Â de nivel superior permite seleccionar por aÃ±o y sus elementos secundarios son nodos de tipoÂ <i>DateList</i>Â y no de tipoÂ <i>Vlist</i>. El valor por defecto del argumentoÂ <i>metadata</i>Â esÂ <i>Date</i>.</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Subsection>
+<Subsection id="the_hierarchy_classifier">
+<Title>
+<Text id="616">El clasificadorÂ <i>hierarchy</i></Text>
+</Title>
+<Content>
+<Text id="617">Todos los clasificadores son jerÃ¡rquicos. Sin embargo, los clasificadores de listas antes mencionados disponen de un nÃºmero fijo de niveles, mientras que los clasificadores âÂ <i>hierarchy</i>Â â (jerÃ¡rquicos) tratados en esta secciÃ³n pueden crear una serie arbitraria de niveles y son mÃ¡s complejos de especificar que los clasificadores de listas.</Text>
+<Figure id="part_of_the_file_sub">
+<Title>
+<Text id="618">Parte del archivoÂ <i>sub.txt</i></Text>
+</Title>
+<CodeLine>1Â Â Â Â Â  1Â Â Â Â Â  "General reference"</CodeLine>
+<CodeLine>1.2Â Â Â  1.2Â Â Â  "Dictionaries, glossaries, language courses, terminology</CodeLine>
+<CodeLine>2Â Â Â Â Â  2Â Â Â Â Â  "Sustainable Development, International cooperation, Pro</CodeLine>
+<CodeLine>2.1Â Â Â  2.1Â Â Â  "Development policy and theory, international cooperatio</CodeLine>
+<CodeLine>2.2Â Â Â  2.2Â Â Â  "Development, national planning, national plans"</CodeLine>
+<CodeLine>2.3Â Â Â  2.3Â Â Â  "Project planning and evaluation (incl. project managem</CodeLine>
+<CodeLine>2.4Â Â Â  2.4Â Â Â  "Regional development and planning incl. regional profil</CodeLine>
+<CodeLine>2.5Â Â Â  2.5Â Â Â  "Nongovernmental organisations (NGOs) in general, self-</CodeLine>
+<CodeLine>2.6Â Â Â  2.6Â Â Â  "Organisations, institutions, United Nations (general, d</CodeLine>
+<CodeLine>2.6.1Â  2.6.1Â  "United Nations"</CodeLine>
+<CodeLine>2.6.2Â  2.6.2Â  "International organisations"</CodeLine>
+<CodeLine>2.6.3Â  2.6.3Â  "Regional organisations"</CodeLine>
+<CodeLine>2.6.5Â  2.6.5Â  "European Community - European Union"</CodeLine>
+<CodeLine>2.7Â Â Â  2.7Â Â Â  "Sustainable Development, Development models and example</CodeLine>
+<CodeLine>2.8Â Â Â  2.8Â Â Â  "Basic Human Needs"</CodeLine>
+<CodeLine>2.9Â Â Â  2.9Â Â Â  "Hunger and Poverty Alleviation"</CodeLine>
+</Figure>
+<Text id="619">El argumentoÂ <i>hfile</i>Â da el nombre de un archivo, como el de la Figura <CrossRef target="Figure" ref="part_of_the_file_sub"/>, que define la jerarquÃ­a de metadatos. Cada lÃ­nea describe una clasificaciÃ³n y las descripciones constan de tres partes:</Text>
+<BulletList>
+<Bullet>
+<Text id="620">Un identificador, que hace corresponder el valor del metadato (proporcionado por el argumentoÂ <i>metadata</i>) con la clasificaciÃ³n.</Text>
+</Bullet>
+<Bullet>
+<Text id="621">Un marcador de posiciÃ³n en la jerarquÃ­a, con forma numÃ©rica en varias partes, por ejemplo, 2, 2.12, 2.12.6.</Text>
+</Bullet>
+<Bullet>
+<Text id="622">El nombre de la clasificaciÃ³n. (Si contiene espacios, deberÃ¡ ponerse entre comillas)</Text>
+</Bullet>
+</BulletList>
+<Text id="623">La Figura <CrossRef target="Figure" ref="part_of_the_file_sub"/> forma parte del archivoÂ <i>sub.txt</i>Â utilizado para crear la jerarquÃ­a temÃ¡tica en la Biblioteca sobre Aspectos Humanitarios y de Desarrollo (y en la colecciÃ³n de demostraciÃ³n). Este ejemplo es un poco confuso porque el nÃºmero que representa la jerarquÃ­a aparece dos veces en cada lÃ­nea. El tipo de metadatoÂ <i>Hierarchy</i>Â se representa en los documentos con valores que adoptan una forma numÃ©rica jerÃ¡rquica, lo que corresponde a su primera apariciÃ³n. La segunda apariciÃ³n se utiliza para determinar la jerarquÃ­a que se aplica en el navegador.</Text>
+<Text id="624">El clasificadorÂ <i>hierarchy</i>Â tiene un argumento opcional,Â <i>sort</i>, que determina el modo en que se ordenan los documentos en las hojas. Se puede especificar cualquier metadato como criterio de ordenaciÃ³n. La lista se crea por defecto siguiendo el orden en que se encuentran los documentos durante el proceso de creaciÃ³n. El orden de los nodos internos viene determinado por el orden en que se especifican los elementos en el argumentoÂ <i>hfile</i>.</Text>
+</Content>
+</Subsection>
+<Subsection id="how_classifiers_work">
+<Title>
+<Text id="625">Funcionamiento de los clasificadores</Text>
+</Title>
+<Content>
+<Text id="626">Los clasificadores son objetos Perl, derivados deÂ <i>BasClas.pm</i>, y se almacenan en el directorioÂ <i>perllib/classify</i>. Se utilizan durante la creaciÃ³n de la colecciÃ³n. Su ejecuciÃ³n se hace en cuatro etapas:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="627">El mÃ©todoÂ <i>new</i>Â crea el objeto Clasificador.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="628">El mÃ©todoÂ <i>init</i>Â inicializa el objeto con parÃ¡metros como el tipo de metadato, el nombre del botÃ³n y el criterio de clasificaciÃ³n.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="629">El mÃ©todoÂ <i>classify</i>Â interviene una vez para cada documento, y guarda la informaciÃ³n sobre la clasificaciÃ³n efectuada dentro del objeto de clasificador.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="630">El mÃ©todoÂ <i>get_classify_info</i>Â transmite la informaciÃ³n de la clasificaciÃ³n localmente almacenada hacia el proceso de creaciÃ³n, que entonces la incluye en la base de datos de informaciones de la colecciÃ³n para su uso cuando la colecciÃ³n se visualiza en el momento de la ejecuciÃ³n.</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="631">El mÃ©todoÂ <i>classify</i>Â recupera el OID de cada documento, el valor de metadato con el que se va a clasificar el documento y, si es necesario, el valor de metadato con el que se van a ordenar los documentos. El mÃ©todoÂ <i>get_classify_info</i>Â efectÃºa todas las funciones de ordenaciÃ³n y clasificaciÃ³n especÃ­ficas del clasificador. Por ejemplo, en el caso del clasificadorÂ <i>AZList</i>Â divide la lista en intervalos alfabÃ©ticos.</Text>
+<Text id="632">El proceso de creaciÃ³n de la colecciÃ³n activa los clasificadores en cuanto se crea el objetoÂ <i>builder</i>. Las clasificaciones se realizan durante la fase de creaciÃ³n, cuando se crea la base de datos de informaciones medianteÂ <i>classify.pm</i>, que se encuentra en el directorioÂ <i>perllib</i>Â de Greenstone.</Text>
+<Table id="items_appearing_in_format_strings">
+<Title>
+<Text id="633">Elementos que aparecen en las cadenas de formato</Text>
+</Title>
+<TableContent>
+<tr>
+<th>
+<Text id="634"><i>[Text]</i></Text>
+</th>
+<th>
+<Text id="635">El texto del documento</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="636"><i>[link]...[/link]</i></Text>
+</th>
+<th>
+<Text id="637">El HTML que debe enlazarse al propio documento</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="638"><i>[icon]</i></Text>
+</th>
+<th>
+<Text id="639">Un icono apropiado (por ejemplo, el pequeÃ±o icono de texto en una cadenaÂ <i>Resultados de la bÃºsqueda</i>)</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="640"><i>[num]</i></Text>
+</th>
+<th>
+<Text id="641">El nÃºmero del documento (Ãºtil para depurar)</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="642"><i>[metadata-name]</i></Text>
+</th>
+<th>
+<Text id="643">El valor de este elemento de metadato para el documento, por ejemplo,Â <i>[Title]</i></Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="formatting_greenstone_output">
+<Title>
+<Text id="644">Formateo de la salida de Greenstone</Text>
+</Title>
+<Content>
+<Text id="645">Las pÃ¡ginas Web que usted ve cuando utiliza Greenstone no han sido almacenadas previamente sino que son generadas âal instanteâ a medida que se las necesita. La apariencia de numerosos aspectos de las pÃ¡ginas se controla a travÃ©s de las âcadenas de formatoâ. Las cadenas de formato se encuentran en el archivo de configuraciÃ³n de la colecciÃ³n y se introducen con la palabra claveÂ <i>format</i>Â seguida del nombre del elemento al que se aplica el formato. Las cadenas de formato controlan dos tipos diferentes de elementos de pÃ¡gina. El primero comprende los elementos de la pÃ¡gina que muestran documentos o partes de documentos. El segundo incluye las listas generadas por los clasificadores y las bÃºsquedas. Todas las cadenas de formato se interpretan en el momento en que se visualizan las pÃ¡ginas. Es rÃ¡pido y sencillo experimentar con las cadenas de formato ya que surten efecto en cuanto se guarda cualquier modificaciÃ³n en el archivoÂ <i>collect.cfg</i>.</Text>
+<Text id="646">En el Cuadro <CrossRef target="Table" ref="items_appearing_in_format_strings"/> se muestran las instrucciones de formato que afectan la apariencia de los documentos. La opciÃ³nÂ <i>DocumentButtons</i>Â controla los botones que aparecen en una pÃ¡gina de documento. En este caso,Â <i>cadena</i>Â es una lista de botones (separados por |) y sus valores posibles sonÂ <i>Detach</i>Â (separar),Â <i>Highlight</i>Â (resaltar),Â <i>Expand Text</i>Â (texto completo) yÂ <i>Expand contents</i>Â (expandir Ã­ndice). La modificaciÃ³n del orden de la lista modifica en consecuencia el orden de los botones.</Text>
+<Table id="the_format_options">
+<Title>
+<Text id="647">Las opciones de la palabra claveÂ <i>format</i></Text>
+</Title>
+<TableContent>
+<tr>
+<th>
+<Text id="648"><i>format DocumentImages true/false</i></Text>
+</th>
+<th>
+<Text id="649">Si el valor esÂ <i>true</i>, muestra una imagen de portada en la parte superior izquierda de la pÃ¡gina del documento (el valor por defecto esÂ <i>false</i>).</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="650"><i>format DocumentHeading cadena_de_formato</i></Text>
+</th>
+<th>
+<Text id="651">Si el valor deÂ <i>DocumentImages</i>Â esÂ <i>false</i>, la cadena de formato controla la apariencia del encabezado del documento que aparece en la parte superior izquierda de la pÃ¡gina del documento (el valor por defecto esÂ <i>[Title]</i>).</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="652"><i>format DocumentContents true/false</i></Text>
+</th>
+<th>
+<Text id="653">Muestra el Ã­ndice (si el documento tiene una estructura jerÃ¡rquica), o flechas para ir a la secciÃ³n siguiente/anterior y el texto âpÃ¡gina k de nâ (en caso contrario).</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="654"><i>format DocumentButtons cadena</i></Text>
+</th>
+<th>
+<Text id="655">Controla los botones que figuran en una pÃ¡gina de documento (el valor por defecto esÂ <i>Separar/Resaltar</i>).</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="656"><i>format DocumentText cadena_de_formato</i></Text>
+</th>
+<th>
+<Text id="657">Formato de texto que se muestra en una pÃ¡gina de documento. El valor por defecto es:</Text>
+<CodeLine><i>&lt;center&gt;&lt;table width=537&gt;</i>
+</CodeLine>
+<CodeLine><i>&lt;tr&gt;&lt;td&gt;[Text]&lt;/td&gt;&lt;/tr&gt;</i>
+</CodeLine>
+<CodeLine><i>&lt;/table&gt;&lt;/center&gt;</i>
+</CodeLine>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="658"><i>format DocumentArrowsBottom true/false</i></Text>
+</th>
+<th>
+<Text id="659">Muestra las flechas para ir a la secciÃ³n siguiente/anterior en la parte inferior de la pÃ¡gina del documento (el valor por defecto esÂ <i>true</i>).</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="660"><i>format DocumentUseHTML true/false</i></Text>
+</th>
+<th>
+<Text id="661">Si el valor esÂ <i>true</i>, cada documento aparece en un marco separado. La pÃ¡gina deÂ <i>Preferencias</i>Â cambia tambiÃ©n ligeramente, ya que propone opciones aplicables a una colecciÃ³n de documentos HTML, como la posibilidad de acudir directamente al documento original (en cualquier sitio de la Web) en lugar de ir a la copia efectuada por Greenstone.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Subsection id="formatting_greenstone_lists">
+<Title>
+<Text id="662">Formateo de las listas de Greenstone</Text>
+</Title>
+<Content>
+<Text id="663">Las cadenas de formato que controlan la apariencia de las listas pueden aplicarse a distintos niveles de la estructura de presentaciÃ³n. Pueden modificar todas las listas de determinado tipo dentro de una colecciÃ³n (por ejemplo,Â <i>DateList</i>) o todas las partes de una lista (por ejemplo, todas las entradas de la listaÂ <i>Search</i>Â (bÃºsqueda)) o determinadas partes de una lista particular (por ejemplo, la porciÃ³n vertical de la lista de un clasificadorÂ <i>AZList</i>Â aplicado a tÃ­tulos).</Text>
+<Text id="664">DespuÃ©s de la palabra claveÂ <i>format</i>Â hay otra palabra clave en dos partes, de las que sÃ³lo una es obligatoria. La primera parte identifica la lista a la que se aplica el formato. La lista que se obtiene mediante una bÃºsqueda se llamaÂ <i>Search</i>Â (bÃºsqueda), mientras que las listas generadas por clasificadores se denominanÂ <i>CL1, CL2, CL3</i>, etc., para el primer, segundo, tercer, etc., clasificador especificado en el archivoÂ <i>collect.cfg</i>. La segunda parte de la palabra clave se refiere a la porciÃ³n de la lista a la que se aplica el formateo, esto es,Â <i>Hlist</i>Â (para una lista horizontal, como el selector A-Z en un nodoÂ <i>AZList</i>),Â <i>Vlist</i>Â (para una lista vertical, como la lista de tÃ­tulos en un nodoÂ <i>AZList</i>) oÂ <i>DateList</i>. Por ejemplo:</Text>
+<Indented>
+<Text id="665"><i>format CL4Vlist ...</i>Â Â Â Â Â Â Â Â Â Â Â Â Â Â  se aplica a todos los VLists de CL4</Text>
+</Indented>
+<Indented>
+<Text id="666"><i>format CL2Hlist ...</i>Â Â Â Â Â Â Â Â Â Â Â Â Â Â  se aplica a todos los HListsde CL2</Text>
+</Indented>
+<Indented>
+<Text id="667"><i>format CL1DateList ...</i>Â Â Â Â Â Â Â  se aplica a todos los DateListsde CL1</Text>
+</Indented>
+<Indented>
+<Text id="668"><i>format SearchVList ...</i>Â Â Â Â Â Â Â Â  se aplica a la lista de resultados de bÃºsqueda</Text>
+</Indented>
+<Indented>
+<Text id="669"><i>format CL3 ...</i>Â Â Â Â Â Â Â  Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  se aplica a todos los nodos de CL3, a menos que se especifique lo contrario</Text>
+</Indented>
+<Indented>
+<Text id="670"><i>format Vlist ...</i>Â Â Â Â Â Â  Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  se aplica a todos los Vlistsde todos los clasificadores, a menos que se especifique lo contrario</Text>
+</Indented>
+<Text id="671">En los ejemplos de la figura 16, las comillas (â...â) representan las especificaciones de formato HTML que controlan la informaciÃ³n y su presentaciÃ³n, tal como aparecen en las pÃ¡ginas Web que muestran el clasificador. Al igual que las especificaciones HTML, cualquier metadato puede aparecer entre corchetes: su valor se interpola en el lugar indicado. Asimismo, cualquiera de los elementos del Cuadro <CrossRef target="Table" ref="the_format_options"/> puede aparecer en las cadenas de formato. La sintaxis de las cadenas incluye tambiÃ©n una instrucciÃ³n condicional que se ilustra en un ejemplo mÃ¡s adelante.</Text>
+<Text id="672">Recuerde que todos los clasificadores producen jerarquÃ­as. Cada nivel de la jerarquÃ­a se visualiza en una de cuatro formas posibles. Ya hemos vistoÂ <i>Hlist</i>,Â <i>Vlist</i>Â yÂ <i>DateList</i>. Existe ademÃ¡sÂ <i>Invisible</i>, que es el modo en que se visualizan los niveles superiores de las jerarquÃ­as: en efecto, el nombre del clasificador aparece ya separadamente en la barra de desplazamiento de Greenstone.</Text>
+</Content>
+</Subsection>
+<Subsection id="examples_of_classifiers_and_format_strings">
+<Title>
+<Text id="673">Ejemplos de clasificadores y cadenas de formato</Text>
+</Title>
+<Content>
+<Figure id="excerpt_from_the_demo_collection_collect" class="withLineNumber">
+<Title>
+<Text id="674">Extracto del archivoÂ <i>collect.cfg</i>Â de la colecciÃ³n de demostraciÃ³n</Text>
+</Title>
+<CodeLine>classify Hierarchy Â Â Â Â Â  âhfile sub.txt âmetadata Subject âsort Title</CodeLine>
+<CodeLine>classify AZList -metadata Title</CodeLine>
+<CodeLine>classify HierarchyÂ Â Â Â Â Â  -hfile org.txt âmetadata Organisation âsort Title</CodeLine>
+<CodeLine>classify ListÂ Â Â Â Â Â Â Â Â Â Â  -metadata Howto</CodeLine>
+<CodeLine>format SearchVList Â Â Â Â Â  â&lt;td valign=top&gt;Â Â Â Â  [link][icon][/link]&lt;/td&gt;&lt;td&gt;{If}</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  {[parent (Allâ: â):Title], [parent (Allâ:â):Title]:}</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  [link][Title][/link]&lt;/td&gt;â</CodeLine>
+<CodeLine>format CL4Vlist â&lt;br&gt;[link][Howto][/link]â</CodeLine>
+<CodeLine>format DocumentImagesÂ Â Â  Â Â  true</CodeLine>
+<CodeLine>format DocumentTextÂ Â Â Â Â  Â Â  â&lt;h3&gt; [Title] &lt;/h3&gt;\\n\\n&lt;p&gt;[Text]â</CodeLine>
+<CodeLine>format DocumentButtonsÂ Â  Â Â  âExpand Text|Expand contents|Detach|Highlightâ</CodeLine>
+</Figure>
+<Text id="675">En la Figura <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/> se muestra una parte del archivo de configuraciÃ³n de la colecciÃ³n de demostraciÃ³n. La utilizamos como ejemplo porque comprende varios clasificadores con un formato muy elaborado. ObsÃ©rvese que las instrucciones de los archivos de configuraciÃ³n no deben contener caracteres de nueva lÃ­nea; en el Cuadro, hemos cortado las lÃ­neas mÃ¡s largas para facilitar su legibilidad.</Text>
+<Text id="676">La lÃ­nea 4 especifica el clasificadorÂ <i>How To</i>Â (cÃ³mo...) de la colecciÃ³n de demostraciÃ³n. Es la cuarta en el archivo de configuraciÃ³n de la colecciÃ³n y, por consiguiente, se denomina CL4. La instrucciÃ³n de formato correspondiente es la lÃ­nea 7 de la Figura <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/>. La informaciÃ³n âcÃ³moâ se genera a partir del clasificadorÂ <i>List</i>Â y su estructura es la lista completa de tÃ­tulos que aparecen en la Figura <CrossRef target="Figure" ref="list_classifier"/>. Los tÃ­tulos tienen un enlace con los propios documentos: cuando se hace clic en un tÃ­tulo se abre el documento correspondiente. Los elementos secundarios del primer nivel de la jerarquÃ­a se visualizan comoÂ <i>Vlist</i>Â (lista vertical), es decir, las secciones se muestran verticalmente. Como indica la instrucciÃ³nÂ <i>format</i>Â asociada, cada elemento de la lista estÃ¡ en una nueva lÃ­nea (â&lt;br&gt;â) y contiene el texto del metadatoÂ <i>Howto</i>, vinculado por hipervÃ­nculo al documento en cuestiÃ³n.</Text>
+<Text id="677">La lÃ­nea 1 especifica la clasificaciÃ³nÂ <i>Subject</i>Â (tema) de la colecciÃ³n de demostraciÃ³n, denominada CL1 (la primera en el archivo de configuraciÃ³n); la lÃ­nea 3 especifica la clasificaciÃ³nÂ <i>Organisation</i>Â y se denomina CL3. Ambas son generadas por el clasificadorÂ <i>Hierarchy</i>Â y, por consiguiente, comprenden una estructura jerÃ¡rquica de objetosÂ <i>VList</i>.</Text>
+<Text id="678">La lÃ­nea 2 especifica el resto de la clasificaciÃ³n de la colecciÃ³n de demostraciÃ³n,Â <i>TÃ­tulos A-Z</i>Â (CL2). ObsÃ©rvese que no existen cadenas de formato asociadas a los clasificadores CL1 a CL3. Greenstone dispone de valores por defecto para cada tipo de cadena de formato y por lo tanto no es necesario configurar una cadena de formato a menos que se desee invalidar el valor por defecto.</Text>
+<Figure id="formatting_the_document">
+<Title>
+<Text id="679">Formateo del documento</Text>
+</Title>
+<File width="604" height="329" url="images/Dev_Fig_17.png"/>
+</Figure>
+<Text id="680">Estas explicaciones corresponden a las cuatro lÃ­neasÂ <i>classify</i>Â de la Figura <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/>. Hay tambiÃ©n cuatro lÃ­neasÂ <i>format</i>. Ya hemos explicado la lÃ­neaÂ <i>CL4Vlist</i>. Las otras tres pertenecen al primer tipo de cadena de formato, ilustrado en el Cuadro <CrossRef target="Table" ref="items_appearing_in_format_strings"/>. La lÃ­nea 8, por ejemplo, coloca la imagen de portada en la parte superior izquierda de cada pÃ¡gina del documento. La lÃ­nea 9 formatea el texto del documento propiamente dicho, y coloca el tÃ­tulo del capÃ­tulo o secciÃ³n correspondiente justo ante del texto. Todos estos efectos se ilustran en la Figura <CrossRef target="Figure" ref="formatting_the_document"/>.</Text>
+<Figure id="formatting_the_search_results">
+<Title>
+<Text id="681">Formateo de los resultados de la bÃºsqueda</Text>
+</Title>
+<File width="604" height="291" url="images/Dev_Fig_18.png"/>
+</Figure>
+<Text id="682">La lÃ­nea 5 de la Figura <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/> es una especificaciÃ³n algo complicada que formatea la lista de resultados generada por una bÃºsqueda, cuyas porciones se muestran en la Figura <CrossRef target="Figure" ref="formatting_the_search_results"/>. Presentamos a continuaciÃ³n, una versiÃ³n simplificada de la cadena de formato:</Text>
+<CodeLine>&lt;td valign=top&gt;[link][icon][/link]&lt;/td&gt;</CodeLine>
+<CodeLine>&lt;td&gt;[link][Title][/link]&lt;/td&gt;</CodeLine>
+<Text id="683">EstÃ¡ diseÃ±ada para aparecer como una lÃ­nea en un cuadro, que es como se formatea la lista de resultados de una consulta. Va acompaÃ±ada, como de costumbre, por un pequeÃ±o icono vinculado al texto, y por el tÃ­tulo del documento que establece un hipervÃ­nculo con el documento en cuestiÃ³n. </Text>
+<Text id="684">En esta colecciÃ³n, los documentos son jerÃ¡rquicos. De hecho, el hipervÃ­nculo anterior remite al tÃ­tulo de la secciÃ³n obtenido por la consulta. Sin embargo, serÃ­a preferible que incluyese tambiÃ©n el tÃ­tulo de la secciÃ³n que la contiene, del capÃ­tulo que contiene esta Ãºltima y del libro en el que se encuentra. Existe un elemento de metadato especial,Â <i>parent</i>, que no se guarda en los documentos pero que estÃ¡ implÃ­cito en cualquier documento jerÃ¡rquico y que genera este tipo de lista. Ãste remite al documento principal, o si se utiliza con el calificadorÂ <i>All</i>, remite a la lista de documentos principales emparentados jerÃ¡rquicamente, separada por una cadena de caracteres que se pueden precisar tras el calificadorÂ <i>All</i>. AsÃ­ pues,</Text>
+<CodeLine>&lt;td valign=top&gt;[link][icon][/link]&lt;/td&gt;</CodeLine>
+<CodeLine>&lt;td&gt;{[parent(AllÂŽ: ÂŽ):Title]: }[link][Title][/link]&lt;/td&gt;</CodeLine>
+<Text id="685">produce una lista que contiene el tÃ­tulo del libro, el tÃ­tulo del capÃ­tulo, etc. que encierra la secciÃ³n buscada, separados por dos puntos, y mÃ¡s adelante por otro carÃ¡cter de dos puntos seguido de un hipervÃ­nculo con el tÃ­tulo de la secciÃ³n buscada.</Text>
+<Text id="686">Lamentablemente, si el objetivo buscado es un libro, no hay documento emparentado y, por lo tanto, aparecerÃ¡ una cadena vacÃ­a seguida de dos puntos. Para evitar tales problemas puede usted utilizar en una cadena de formato las instrucciones condicionalesÂ <i>if</i>Â yÂ <i>or</i>Â ...Â <i>else</i>Â :</Text>
+<CodeLine>{If} {[metadato],acciÃ³n-si-no-vacio, acciÃ³n-si-vacio}</CodeLine>
+<CodeLine>{Or} {acciÃ³n,else otra-acciÃ³n, else otra-acciÃ³n, etc}</CodeLine>
+<Text id="687">En cualquiera de los casos, se utilizan las llaves para seÃ±alar que las instrucciones deben interpretarse y no sÃ³lo considerarse como texto. La instrucciÃ³nÂ <i>if</i>Â comprueba si el metadato estÃ¡ vacÃ­o y elige la primera opciÃ³n si no es asÃ­; de lo contrario pasa a la segunda (si es que existe). Se puede utilizar cualquier elemento de metadato, incluso el metadato especialÂ <i>parent</i>. La instrucciÃ³nÂ <i>Or</i>Â evalÃºa todas las acciones por turno hasta que encuentra una que no estÃ© vacÃ­a. La envÃ­a entonces a la lista de resultados e ignora el resto de la lÃ­nea.</Text>
+<Text id="688">Volviendo a la lÃ­nea 5 de la Figura <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/>, la cadena de formato completa es:</Text>
+<CodeLine>&lt;td valign=top&gt;[link][icon][/link]&lt;/td&gt;</CodeLine>
+<CodeLine>&lt;td&gt;{If}{[parent (AllÂŽ: ÂŽ):Title],</CodeLine>
+<CodeLine>Â Â Â  Â Â Â Â Â [parent (AllÂŽ: ÂŽ):Title]:}</CodeLine>
+<CodeLine>Â Â Â  [link][Title][/link]&lt;/td&gt;</CodeLine>
+<Text id="689">De este modo la especificaciÃ³nÂ <i>parent</i>Â va precedida de un condicional que comprueba si el resultado estÃ¡ vacÃ­o y sÃ³lo muestra la cadena completa (Â <i>parent</i>) cuando estÃ¡ presente. Algunas veces,Â <i>parent</i>Â puede ser calificado porÂ <i>Top</i>Â en vez deÂ <i>All</i>, lo cual da el nombre del documento de nivel superior que encierra una secciÃ³n: en este caso, el nombre del libro. ConÂ <i>Top</i>Â no es necesaria una cadena de separaciÃ³n.</Text>
+<Text id="690">Para concluir, presentamos algunos ejemplos que ilustran otras funciones. En la Figura <CrossRef target="Figure" ref="datelist_classifier"/>,Â <i>DateList</i>Â se utiliza en la clasificaciÃ³nÂ <i>Fechas</i>Â de la colecciÃ³nÂ <i>Computistsâ Weekly</i>Â (el semanario de los informÃ¡ticos) y resulta ser el segundo clasificador, esto es, CL2. El clasificador y las especificaciones de formato se muestran mÃ¡s adelante. El clasificadorÂ <i>DateList</i>Â difiere deÂ <i>AZList</i>Â en que siempre clasifica por metadatosÂ <i>Date</i>Â y en que las ramas inferiores de la jerarquÃ­a de consulta utilizanÂ <i>DateList</i>Â en vez deÂ <i>Vlist</i>, con lo que se agrega el aÃ±o y el mes a la izquierda de las listas de documentos.</Text>
+<CodeLine>classify AZSectionList metadata=Creator</CodeLine>
+<CodeLine>format CL2Vlist â&lt;td&gt;[link][icon][/link]&lt;/td&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  &lt;td&gt;[Creator]&lt;/td&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  &lt;td&gt;&amp;nbsp;&amp;nbsp;[Title]&lt;/td&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  &lt;td&gt;[parent(Top):Date]&lt;/td&gt;â</CodeLine>
+<Text id="691">La especificaciÃ³n de formato muestra esosÂ <i>Vlists</i>Â de manera apropiada.</Text>
+<Text id="692">El mecanismo de cadena de formato es flexible pero difÃ­cil de aprender. La mejor manera de proceder es estudiando los archivos de configuraciÃ³n de colecciones existentes.</Text>
+</Content>
+</Subsection>
+<Subsection id="linking_to_different_document_versions">
+<Title>
+<Text id="693">Enlaces con diferentes versiones de documentos</Text>
+</Title>
+<Content>
+<Text id="694">El mecanismoÂ <i>[link] ... [/link]</i>Â en una cadena de formato, se crea un enlace con el formato HTML del documento, donde el hipervÃ­nculo es el tÃ­tulo del documento: cuando se hace clic en el enlace se abre la versiÃ³n HTML del documento. En algunas colecciones es Ãºtil poder visualizar otras versiones del documento. En una colecciÃ³n de documentos con formato Word de Microsoft, por ejemplo, es bueno poder abrir una versiÃ³n Word de cada documento en lugar de la HTML que se ha extraÃ­do de ella; lo mismo ocurre con los documentos PDF.</Text>
+<Text id="695">Para poder mostrar diferentes versiones de un documento, la soluciÃ³n es incorporar la informaciÃ³n necesaria (es decir, dÃ³nde se encuentran las demÃ¡s versiones) al formato de archivo de Greenstone del documento. Esta informaciÃ³n se representa en forma de metadatos. Recuerde que al colocar:</Text>
+<CodeLine>[link][Title][/link]</CodeLine>
+<Text id="696">en una cadena de formato, se crea un enlace con el formato HTML del documento, donde elÂ  hipervÃ­nculo es el tÃ­tulo del documento. Tanto los conectores de Word como los de PDF generan metadatosÂ <i>srclink</i>, de modo que si se introduce:</Text>
+<CodeLine>[srclink][Title][/srclink]</CodeLine>
+<Text id="697">en una cadena de formato, se crea un enlace con la versiÃ³n Word o PDF del documento, donde el hipervÃ­nculo es tambiÃ©n en este caso el tÃ­tulo del documento. A fin de que aparezcan los iconos correspondientes a los documentos Word y PDF, estos conectores generan tambiÃ©n metadatosÂ <i>srcicon</i>Â de tal forma que:</Text>
+<CodeLine>[srclink][srcicon][/srclink]</CodeLine>
+<Text id="698">crea un enlace etiquetado por el icono estÃ¡ndar de Word o PDF (segÃºn el caso) y no por el tÃ­tulo del documento.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="controlling_the_greenstone_user_interface">
+<Title>
+<Text id="699">Control de la interfaz de usuario de Greenstone</Text>
+</Title>
+<Content>
+<Text id="700">El conjunto de la interfaz de usuario de Greenstone se controla mediante macros que se encuentran listados en el directorioÂ <i>GSDLHOME/macrosÂ </i>. Estas macros estÃ¡n escritas en un lenguaje especialmente concebido para Greenstone y se utilizan en el momento de la ejecuciÃ³n para generar pÃ¡ginas Web. La traducciÃ³n del lenguaje macro al formato HTML es la Ãºltima etapa para mostrar una pÃ¡gina. AsÃ­ pues, las modificaciones de un archivo de macros afectan inmediatamente la presentaciÃ³n en pantalla y permiten experimentar rÃ¡pida y fÃ¡cilmente. Todos los archivos de macros que utiliza Greenstone se encuentran enÂ <i>GSDLHOME/etc/main.cfg</i>Â y se cargan cada vez que se arranca el programa. La Ãºnica excepciÃ³n es cuando se utiliza la Biblioteca Local de Windows: en este caso es necesario reiniciar el proceso.</Text>
+<Text id="701">Las pÃ¡ginas Web se generan al instante por numerosas razones y el sistema de macros le permite a Greenstone funcionar con la flexibilidad necesaria. Las pÃ¡ginas pueden presentarse en diversos idiomas y existe un archivo de macros diferente para almacenar todo el texto de la interfaz en cada lengua. Cuando Greenstone presenta una pÃ¡gina, el intÃ©rprete de macros comprueba la variable de idioma y carga la pÃ¡gina en la lengua apropiada (aunque no llega a traducir el contenido del documento). AdemÃ¡s, los valores de determinadas variables de visualizaciÃ³n, como el nÃºmero de documentos encontrados en una bÃºsqueda, no se conocen de antemano, sino que se interpolan en el texto de la pÃ¡gina mediante macros.</Text>
+<Subsection id="the_macro_file_format">
+<Title>
+<Text id="702">El formato de los archivos de macros</Text>
+</Title>
+<Content>
+<Text id="703">Los archivos de macros tienen la extensiÃ³nÂ <i>.dm</i>. Cada archivo define uno o mÃ¡sÂ <i>paquetes</i>Â (Â <i>packages</i>), cada uno de los cuales contiene una serie de macros utilizadas con un fin preciso y Ãºnico. Al igual que los clasificadores y los conectores, hay una base a partir de la cual se elaboran las macros, que se llamaÂ <i>base.dm</i>Â ; este archivo define el contenido bÃ¡sico de una pÃ¡gina.</Text>
+<Text id="704">Los nombres de las macros empiezan y terminan con una rayita de subrayado y su contenido se define mediante llaves. El contenido puede ser texto llano, HTML (incluidos los enlaces con pequeÃ±os programas (Â <i>applets</i>) de Java y JavaScript), nombres de macros o cualquier combinaciÃ³n de estos elementos. La siguiente macro procedente deÂ <i>base.dm</i>Â define el contenido de una pÃ¡gina en ausencia de cualquier otra macro que la invalide:</Text>
+<CodeLine>_content_ {&lt;p&gt;&lt;h2&gt;Oops&lt;/h2&gt;_textdefaultcontent_}</CodeLine>
+<Text id="705">En la parte superior de la pÃ¡gina aparecerÃ¡ el mensaje âOopsâ, seguido de la macro _textdefaultcontent_, que en inglÃ©s equivale aÂ  The requested page could not be found. Please use your browsers âbackâ button or the above home button to return to the Greenstone Digital Library, y en otros idiomas aparecerÃ¡ la correspondiente traducciÃ³n de esta frase. En espaÃ±ol, por ejemplo, se podrÃ¡ leer: No se pudo encontrar la pÃ¡gina solicitada. Pulse el botÃ³n âAtrÃ¡sâ o el botÃ³n de âPÃ¡gina principalâ para volver a la Biblioteca Digital Greenstone.</Text>
+<Text id="706">Las macros <i>_textdefaultcontent_</i>Â (contenido del texto por defecto) y <i>_content_</i>Â (contenido) se encuentran en el paqueteÂ <i>global</i>Â porque son necesarias para todas las partes de la interfaz de usuario. Las macros pueden utilizar como contenido macros de otros paquetes, mas para ello deben anteponer sus nombres y el de su paquete. Por ejemplo, la macro:</Text>
+<CodeLine>_collectionextra_ {Esta colecciÃ³n contiene_about:numdocs_documentos. Se constituyÃ³ por Ãºltima vez hace _about:builddate_ dÃ­as.}</CodeLine>
+<Text id="707">procede del archivoÂ <i>english.dm</i>Â y se utiliza como descripciÃ³n por defecto de una colecciÃ³n. Forma parte del paqueteÂ <i>global</i>, peroÂ <i>_numdocs_</i>Â y _Â <i>builddate</i>Â _ pertenecen ambas al paqueteÂ <i>about</i>, por elloÂ <i>about:</i>Â precede sus nombres.</Text>
+<Text id="708">Las macros suelen contener instrucciones condicionales que se parecen a las cadenas de formato condicionales antes mencionadas, aunque su apariencia difiere un poco. El formato bÃ¡sico es _Â <i>If</i>Â _Â <i>(x,y,z)</i>, en queÂ <i>x</i>Â es una condiciÃ³n,Â <i>y</i>Â es el contenido de la macro que se debe utilizar si esta condiciÃ³n se cumple, yÂ <i>z</i>Â el contenido que se debe utilizar en caso contrario. Los operadores de comparaciÃ³n son los mismos que los operadores simples utilizados en Perl (menor que, mayor que, igual a, diferente de). El siguiente ejemplo procedente del archivoÂ <i>base.dm</i>Â se utiliza para determinar cÃ³mo visualizar la parte superior de la pÃ¡ginaÂ <i>acerca de</i>Â de una colecciÃ³n:</Text>
+<CodeLine>_imagecollection_ {</CodeLine>
+<CodeLine>Â Â  _If_("_iconcollection_" ne "",</CodeLine>
+<CodeLine>Â Â Â Â Â Â  &lt;a href = "_httppageabout_"&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â  &lt;img src = "_iconcollection_" border = 0&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â  &lt;/a&gt;,</CodeLine>
+<CodeLine>Â Â Â Â Â Â  _imagecollectionv_)</CodeLine>
+<CodeLine>}</CodeLine>
+<Text id="709">Esto puede parecer un poco crÃ­ptico. La macroÂ <i>_iconcollection</i>Â _ desemboca en la cadena vacÃ­a si la colecciÃ³n carece de icono, o en el nombre del archivo de una imagen. Haciendo la parÃ¡frasis del cÃ³digo antes mencionado: si existe una imagen de colecciÃ³n, presentar el encabezado de pÃ¡ginaÂ <i>acerca de esta colecciÃ³n</i>Â (al que se remite mediante <i>_httppageabout_</i>) y luego esa imagen; de otro modo, utilizar la presentaciÃ³n alternativa <i>_imagecollectionv_</i>.</Text>
+<Text id="710">Las macros pueden incluir argumentos. Hay aquÃ­ una segunda definiciÃ³n de la macro <i>_imagecollection_</i> que sigue inmediatamente la definiciÃ³n antes indicada en el archivoÂ <i>base.dm</i>:</Text>
+<CodeLine>_imagecollection_[v=1]{_imagecollectionv_}</CodeLine>
+<Text id="711">El argumentoÂ <i>[v=1]</i>Â especifica que la segunda definiciÃ³n se utiliza cuando Greenstone se ejecuta en modo âsÃ³lo textoâ. Las macros de idiomas funcionan de la misma manera: todas especifican su lengua como argumento, salvoÂ <i>english.dm</i>Â porque es el idioma por defecto. Por ejemplo:</Text>
+<CodeLine>_textimagehome_ {Home Page}</CodeLine>
+<Text id="712">aparece en el archivo de macro de lengua inglesa, mientras que la versiÃ³n alemana es:</Text>
+<CodeLine>_textimagehome_ [l=de] {Hauptaseite}</CodeLine>
+<Text id="713">Las versiones inglesa y alemana se encuentran en el mismo paquete, aunque en archivos diferentes (las definiciones de paquetes pueden ocupar mÃ¡s de un archivo). Greenstone utiliza su argumentoÂ <i>l</i>Â en el momento de la ejecuciÃ³n para determinar quÃ© idioma se debe visualizar.</Text>
+<Figure id="part_of_the_aboutdm_macro_file">
+<Title>
+<Text id="714">Parte del archivo de macrosÂ <i>about.dm</i></Text>
+</Title>
+<CodeLine>package about</CodeLine>
+<CodeLine>############################################</CodeLine>
+<CodeLine># about page content</CodeLine>
+<CodeLine>############################################</CodeLine>
+<CodeLine>_pagetitle_ {_collectionname_}</CodeLine>
+<CodeLine>_content_ {</CodeLine>
+<CodeLine>&lt;center&gt;</CodeLine>
+<CodeLine>_navigationbar_</CodeLine>
+<CodeLine>&lt;/center&gt;</CodeLine>
+<CodeLine>_query:queryform_ </CodeLine>
+<CodeLine>&lt;p&gt;_iconblankbar_</CodeLine>
+<CodeLine>&lt;p&gt;_textabout_</CodeLine>
+<CodeLine>_textsubcollections_</CodeLine>
+<CodeLine>&lt;h3&gt;_help:textsimplehelpheading_&lt;/h3&gt;</CodeLine>
+<CodeLine>_help:simplehelp_</CodeLine>
+<CodeLine>}</CodeLine>
+<CodeLine>_textabout_ {</CodeLine>
+<CodeLine>&lt;h3&gt;_textabcol_&lt;/h3&gt;</CodeLine>
+<CodeLine>_Global:collectionextra_</CodeLine>
+<CodeLine>}</CodeLine>
+</Figure>
+<Text id="715">Por Ãºltimo, en la Figura <CrossRef target="Figure" ref="part_of_the_aboutdm_macro_file"/> se muestra un extracto del archivo de macrosÂ <i>about.dm</i>Â que se utiliza para configurar la pÃ¡ginaÂ <i>acerca de</i>Â de cada colecciÃ³n. Este ejemplo muestra la definiciÃ³n de tres macros: <i>_pagetitle_</i>, <i>_content_</i>Â y <i>_textabout_</i>.</Text>
+</Content>
+</Subsection>
+<Subsection id="using_macros">
+<Title>
+<Text id="716">UtilizaciÃ³n de las macros</Text>
+</Title>
+<Content>
+<Text id="717">Las macros son instrumentos de alta potencia que pueden parecer un poco complicados y crÃ­pticos. Sin embargo, con unos buenos conocimientos de HTML y un poco de prÃ¡ctica pueden convertirse en una manera rÃ¡pida y fÃ¡cil de personalizar su sitio Greenstone.</Text>
+<Text id="718">Supongamos, por ejemplo, que usted querÃ­a crear una pÃ¡gina estÃ¡tica parecida a su sitio Greenstone actual. Puede usted crear un nuevo paquete, que se llamarÃ¡Â <i>static</i>Â por ejemplo, en un nuevo archivo, e invalidar la macro _Â <i>content_</i>. Agregue el nuevo nombre de archivo a la lista de macros situadas enÂ <i>GSDLHOME/etc/main.cfg</i>Â que Greenstone carga cada vez que arranca. Por Ãºltimo, acceda a la nueva pÃ¡gina utilizando su URL Greenstone normal y aÃ±ada los argumentosÂ <i>?a=p&amp;p=static</i>Â (por ejemplo:Â <i>http://servidor/cgi-bin/library?a=p&amp;p=static</i>).</Text>
+<Text id="719">Para cambiar el âaspecto y estiloâ de Greenstone puede modificar los paquetesÂ <i>base</i>Â yÂ <i>style (estilo)</i>. Para cambiar la pÃ¡gina principal de Greenstone, modifique el paqueteÂ <i>home</i>Â (como se explica en laÂ <i>GuÃ­a de InstalaciÃ³n de la Biblioteca Digital Greenstone</i>). Para cambiar la pÃ¡gina de bÃºsqueda, modifiqueÂ <i>query.dm</i>.</Text>
+<Text id="720">Experimente sin miedo con las macros. Las modificaciones aparecen instantÃ¡neamente porque las macros se interpretan a medida que se visualizan las pÃ¡ginas. El lenguaje de macros es un instrumento Ãºtil que puede servirle para personalizar a su gusto el sitio Greenstone.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="the_packages_directory">
+<Title>
+<Text id="721">El directorioÂ <i>packages</i></Text>
+</Title>
+<Content>
+<Table id="the_packages_directory_1">
+<Title>
+<Text id="722">El directorioÂ <i>packages</i>Â (paquetes)</Text>
+</Title>
+<TableContent>
+<tr>
+<th>Â </th>
+<th>
+<Text id="723"><b>Paquete</b></Text>
+</th>
+<th>
+<Text id="724"><b>URL</b></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="725">mg</Text>
+</th>
+<th>
+<Text id="726">MG, abreviaciÃ³n inglesa de âManaging Gigabytesâ (gestiÃ³n de gigabytes). Programa de compresiÃ³n, indizaciÃ³n y bÃºsqueda que se utiliza para administrar la informaciÃ³n textual en las colecciones Greenstone.</Text>
+</th>
+<th>
+<Text id="727"><i>www.citri.edu.au/mg</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="728"><i>wget</i></Text>
+</th>
+<th>
+<Text id="729">Programa de duplicaciÃ³n de Web (espejo) utilizado por Greenstone. Escrito en C++.</Text>
+</th>
+<th>
+<Text id="730"><i>www.tuwien.ac.at/~prikryl/wget.html</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="731"><i>w3mir</i></Text>
+</th>
+<th>
+<Text id="732">Programa de duplicaciÃ³n de Web escrito en Perl. Este no es el programa de duplicaciÃ³n preferido por Greenstone porque se basa en una versiÃ³n obsoleta de un mÃ³dulo Perl (que se distribuye en el directorioÂ <i>w3mir</i>).</Text>
+</th>
+<th>
+<Text id="733"><i>www.math.uio.no/~janl/w3mir</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="734"><i>windows</i></Text>
+</th>
+<th>
+<Text id="735">Paquetes que se utilizan cuando se funciona con Windows.</Text>
+</th>
+<th>
+<Text id="736"><i>-</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="737"><i>windows/gdbm</i></Text>
+</th>
+<th>
+<Text id="738">VersiÃ³n del administrador de base de datos de GNU creada para Windows. GDBM viene con las versiones estÃ¡ndar de Linux.</Text>
+</th>
+<th>
+<Text id="739"><i>-</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="740"><i>windows/crypt</i></Text>
+</th>
+<th>
+<Text id="741">Programa de codificaciÃ³n utilizado para las contraseÃ±as en las funciones administrativas de Greenstone.</Text>
+</th>
+<th>
+<Text id="742"><i>-</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="743"><i>windows/stlport</i></Text>
+</th>
+<th>
+<Text id="744">Biblioteca EstÃ¡ndar de Plantillas que se utiliza para compilar Greenstone con determinados compiladores de Windows.</Text>
+</th>
+<th>
+<Text id="745"><i>-</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="746"><i>wv</i></Text>
+</th>
+<th>
+<Text id="747">Convertidor del formato Word de Microsoft (para crear colecciones a partir de documentos Word), aligerado para Greenstone.</Text>
+</th>
+<th>
+<Text id="748"><i>sourceforge.net/projects/wvware</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="749"><i>pdftohtml</i></Text>
+</th>
+<th>
+<Text id="750">Convertidor del formato PDF que se utiliza para crear colecciones a partir de documentos PDF.</Text>
+</th>
+<th>
+<Text id="751"><i>www.ra.informatik.uni-stuttgart.de/~gosho/pdftohtml</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="752"><i>yaz</i></Text>
+</th>
+<th>
+<Text id="753">Programa cliente Z39.50 que se utiliza para lograr la compatibilidad de Greenstone con el protocolo Z39.50. El archivoÂ <i>README.gsdl</i>. informa de los progresos al respecto.</Text>
+</th>
+<th>
+<Text id="754"><i>www.indexdata.dk</i></Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="755">El directorioÂ <i>packages</i>Â (paquetes), cuyo contenido se muestra en el Cuadro <CrossRef target="Table" ref="the_packages_directory_1"/>, es donde se guardan todos los cÃ³digos utilizados por Greenstone pero elaborados por otros equipos de investigadores. Todos los programas informÃ¡ticos distribuidos con Greenstone cumplen los requisitos de la Licencia PÃºblica General de GNU. Los ejecutables producidos por esos paquetes se colocan en el directorioÂ <i>bin</i>Â de Greenstone. Cada paquete se guarda en su propio directorio. Sus funciones varÃ­an considerablemente, desde indizar y comprimir hasta convertir documentos de Word de Microsoft en el formato HTML. Cada paquete tiene un archivo README (LÃAME) que proporciona informaciones complementarias sobre el mismo.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="the_greenstone_runtime_system">
+<Title>
+<Text id="756">EL SISTEMA DE EJECUCIÃN DE GREENSTONE</Text>
+</Title>
+<Content>
+<Text id="757">En este capÃ­tulo se explica el sistema de ejecuciÃ³n de Greenstone a fin de que usted pueda comprender, aumentar y ampliar sus posibilidades. El programa estÃ¡ escrito en C++ y hace un uso importante de la âherencia virtualâ. Si no conoce bien este lenguaje, es preferible que lo aprenda antes de seguir adelante. Deitel y Deitel (1994) propone un manual de introducciÃ³n general, pero Stroustroup (1997) es la referencia de mayor autoridad.</Text>
+<Text id="758">Empezaremos explicando la filosofÃ­a conceptual que sustenta el sistema de ejecuciÃ³n, ya que influye considerablemente en su implementaciÃ³n. Luego pasaremos a examinarÂ  detalladamente la implementaciÃ³n, que constituye la parte principal de este capÃ­tulo. La versiÃ³n de Greenstone que se expone aquÃ­ es la versiÃ³n CGI (Biblioteca Web para los usuarios de Windows). La versiÃ³n Biblioteca Local de Windows utiliza el mismo cÃ³digo fuente pero tiene un servidor Web incorporado como interfaz de usuario. AdemÃ¡s, la Biblioteca Local es un proceso de tipo persistente.</Text>
+<Section id="process_structure">
+<Title>
+<Text id="759">Estructura de los procesos</Text>
+</Title>
+<Content>
+<Figure id="overview_of_a_general_greenstone_system">
+<Title>
+<Text id="760">Resumen grÃ¡fico de un sistema Greenstone general</Text>
+</Title>
+<File width="483" height="468" url="images/Dev_Fig_20.png"/>
+</Figure>
+<Text id="761">En la Figura <CrossRef target="Figure" ref="overview_of_a_general_greenstone_system"/> aparecen varios usuarios, representados por computadoras en la parte superior del diagrama, que acceden a tres colecciones de Greenstone. Antes de ser puestas en lÃ­nea, estas colecciones pasan por los procesos de importaciÃ³n y creaciÃ³n expuestos en los capÃ­tulos anteriores. En primer lugar, los documentos, que aparecen en la parte inferior de la figura, se importan en el Formato de ArchivoÂ  Greenstone, que es un formato XML. A continuaciÃ³n, los archivos en el Formato de Archivo Greenstone se incorporan a varios Ã­ndices de bÃºsqueda y a una base de datos de informaciones de la colecciÃ³n que incluye las estructuras jerÃ¡rquicas necesarias para las operaciones de consulta. Una vez hecho esto, la colecciÃ³n estÃ¡ lista para ser puesta en lÃ­nea y responder a las solicitudes de informaciÃ³n.</Text>
+<Text id="762">Los dos componentes fundamentales en la concepciÃ³n del sistema de ejecuciÃ³n son los ârecepcionistasâ y los âservidores de colecciÃ³nâ. Desde el punto de vista del usuario, un recepcionista es el punto de contacto con la biblioteca digital. Recibe los datos proporcionados por los usuarios mediante el teclado y los clics del ratÃ³n, los analiza y luego transmite una solicitud al correspondiente servidor (o servidores) de la colecciÃ³n. Este Ãºltimo localiza la informaciÃ³n solicitada y la envÃ­a al recepcionista para que la presente al usuario. Los servidores de colecciÃ³n actÃºan como un mecanismo abstracto que administra el contenido de la colecciÃ³n, mientras que los recepcionistas se encargan de la interfaz de usuario.</Text>
+<Figure id="greenstone_system_using_the_null_protocol">
+<Title>
+<Text id="763">Resumen grÃ¡fico de un sistema Greenstone general</Text>
+</Title>
+<File width="483" height="468" url="images/Dev_Fig_21.png"/>
+</Figure>
+<Text id="764">Como se muestra en la Figura <CrossRef target="Figure" ref="overview_of_a_general_greenstone_system"/>, los recepcionistas se comunican con los servidores de colecciÃ³n mediante un protocolo definido. La implementaciÃ³n de este protocolo depende de la configuraciÃ³n de la computadora en la que se ejecuta el sistema de biblioteca digital. El caso mÃ¡s comÃºn, y el mÃ¡s sencillo, es cuando hay un recepcionista y un servidor de colecciÃ³n y ambos operan en la misma computadora. Eso es lo que se obtiene con la instalaciÃ³n por defecto de Greenstone. En este caso, los dos procesos se combinan para formar un solo ejecutable (denominadoÂ <i>library</i>) y, por consiguiente, la utilizaciÃ³n del protocolo se reduce a llamadas de funciÃ³n. A esto lo llamamosÂ <i>null protocol</i>Â (protocolo nulo) y es la base del sistema estÃ¡ndar de biblioteca digital Greenstone en su estado original. Esta configuraciÃ³n simplificada aparece en la Figura <CrossRef target="Figure" ref="greenstone_system_using_the_null_protocol"/>, en la que el recepcionista, el protocolo y el servidor de colecciÃ³n estÃ¡n unidos en una sola entidad, el programaÂ <i>library</i>Â (biblioteca). La finalidad de este capÃ­tulo es explicar cÃ³mo funciona.</Text>
+<Text id="765">Normalmente, un âservidorâ es un proceso persistente que, una vez iniciado, funciona indefinidamente y responde a cualquier solicitud que le llegue. No obstante, a pesar de su nombre, el servidor de colecciÃ³n en la configuraciÃ³n de protocolo nulo no es un servidor en el sentido estricto. De hecho, cada vez que se solicita una pÃ¡gina Web de Greenstone, se arranca el programaÂ <i>library</i>Â (mediante el mecanismo CGI), Ã©ste responde a la solicitud y luego se cierra. Lo llamamos âservidorâ porque tambiÃ©n estÃ¡ diseÃ±ado para funcionar con una configuraciÃ³n mÃ¡s general como la de la Figura <CrossRef target="Figure" ref="overview_of_a_general_greenstone_system"/>.</Text>
+<Text id="766">Por mÃ¡s sorprendente que parezca, este ciclo de arranque, tratamiento y cierre no es tan lento como se podrÃ­a imaginar y el resultado es un servicio perfectamente utilizable. Sin embargo, el sistema es poco eficiente. Existe un mecanismo llamado Fast-CGI (<i>www.fastcgi.com</i>) que ofrece una buena soluciÃ³n de compromiso. Gracias a su utilizaciÃ³n, el programaÂ <i>library</i>Â puede permanecer en memoria despuÃ©s de la primera ejecuciÃ³n y recibir las subsiguientes series de argumentos CGI, con lo que se evita repetir la inicializaciÃ³n y su funciÃ³n se asemeja mÃ¡s a la de un servidor convencional. La utilizaciÃ³n de Fast-CGI es una opciÃ³n de Greenstone y se activa volviendo a compilar el cÃ³digo fuente con las bibliotecas adecuadas.</Text>
+<Text id="767">Como alternativa al protocolo nulo, hemos elaborado tambiÃ©n el protocolo Greenstone utilizando el famoso sistema CORBA (SlamaÂ <i>et al.</i>, 1999), que utiliza un paradigma unificado orientado a objetos, para permitir a distintos procesos ejecutÃ¡ndose en distintas plataformas informÃ¡ticas e implementados en diferentes lenguajes de programaciÃ³n, acceder a la misma serie de objetos distribuidos por Internet (o cualquier otra red). AsÃ­ pues, una situaciÃ³n como la de la Figura <CrossRef target="Figure" ref="overview_of_a_general_greenstone_system"/>, en la que todos los recepcionistas y los servidores de colecciÃ³n operan en diferentes computadoras, es perfectamente viable.</Text>
+<Figure id="graphical_query_interface_to_greenstone">
+<Title>
+<Text id="768">Interfaz grÃ¡fica de consultas de Greenstone</Text>
+</Title>
+<File width="397" height="347" url="images/Dev_Fig_22.png"/>
+</Figure>
+<Text id="769">Ello permite la instalaciÃ³n de interfaces mucho mÃ¡s complejas para distribuir exactamente las mismas colecciones de biblioteca digital. A modo de ejemplo, en la Figura <CrossRef target="Figure" ref="graphical_query_interface_to_greenstone"/> se muestra una interfaz grÃ¡fica de consultas, basada en los diagramas de Venn, que permite a los usuarios manipular directamente las consultas booleanas. Escrita en Java, la interfaz funciona localmente en la computadora del usuario. Con el sistema CORBA, se puede acceder a un servidor remoto de colecciÃ³n de Greenstone, escrito en C++.</Text>
+<Text id="770">No nos extenderemos mÃ¡s sobre este tema en el presente manual, ya que el protocolo distribuido sigue siendo objeto de perfeccionamiento y mejoras para su utilizaciÃ³n (para obtener mÃ¡s informaciÃ³n, vÃ©ase BainbridgeÂ <i>et al</i>., 2001).</Text>
+</Content>
+</Section>
+<Section id="conceptual_framework">
+<Title>
+<Text id="771">Marco conceptual</Text>
+</Title>
+<Content>
+<Figure id="generating_the_about_this_collection_page">
+<Title>
+<Text id="772">GeneraciÃ³n de la pÃ¡gina âAcerca de esta colecciÃ³nâ</Text>
+</Title>
+<File width="604" height="457" url="images/Dev_Fig_23.png"/>
+</Figure>
+<Text id="773">En la Figura <CrossRef target="Figure" ref="generating_the_about_this_collection_page"/> se muestra la pÃ¡gina âAcerca de esta colecciÃ³nâ de una colecciÃ³n Greenstone particular (la colecciÃ³n del Proyecto Gutenberg). FÃ­jese en la direcciÃ³n URL que aparece en la parte superior: esta pÃ¡gina se obtiene activando el programa CGIÂ <i>library</i>, que es el ejecutable anteriormente mencionado en que el recepcionista y el servidor de colecciÃ³n estÃ¡n conectados mediante el protocolo nulo. Los argumentos del programaÂ <i>library</i>Â sonÂ <i>c=gberg</i>,Â <i>a=p</i>,Â <i>p=about</i>Â yÂ <i>l=es</i>. Pueden interpretarse del modo siguiente:</Text>
+<Indented>
+<Text id="774">Para acceder a la colecciÃ³n del Proyecto Gutenberg (c=gberg), la acciÃ³n consiste en crear una pÃ¡gina (a=p) y la pÃ¡gina que hay que generar se llama âaboutâ (p=about), en espaÃ±ol (l=es).</Text>
+</Indented>
+<Figure id="greenstone_runtime_system">
+<Title>
+<Text id="775">Sistema de ejecuciÃ³n de Greenstone</Text>
+</Title>
+<File width="287" height="467" url="images/Dev_Fig_24.png"/>
+</Figure>
+<Text id="776">La Figura <CrossRef target="Figure" ref="greenstone_runtime_system"/> ilustra las principales partes del sistema de ejecuciÃ³n de Greenstone. En la parte superior, el recepcionista inicializa primero sus componentes, luego analiza los argumentos CGI para decidir quÃ© acciÃ³n activar. Al ejecutar la acciÃ³n (que incluye nuevos tratamientos de los argumentos CGI), el programa utiliza el protocolo para acceder al contenido de la colecciÃ³n. Se utiliza la respuesta para generar una pÃ¡gina Web, con la asistencia del componente de formato y del lenguaje de macros.</Text>
+<Text id="777">El lenguaje de macros, que ya examinamos en la SecciÃ³n <CrossRef target="Section" ref="controlling_the_greenstone_user_interface"/>, se utiliza para conferir al sistema de Biblioteca Digital Greenstone un estilo coherente y crear interfaces en diferentes lenguas. La interacciÃ³n con la biblioteca genera la estructura bÃ¡sica de las pÃ¡ginas Web y las macros del directorioÂ <i>GSDLHOME/macros</i>Â aportan el contenido.</Text>
+<Text id="778">El objeto Lenguaje de macros representado en la Figura <CrossRef target="Figure" ref="greenstone_runtime_system"/> se encarga de leer estos archivos y de memorizar el resultado del anÃ¡lisis. Cualquier acciÃ³n puede utilizar este objeto para ampliar una macro. Puede incluso crear nuevas definiciones de macro e invalidar las anteriores, aportando asÃ­ una dimensiÃ³n dinÃ¡mica al uso de las macros.</Text>
+<Text id="779">La representaciÃ³n de la pÃ¡gina âAcerca de esta colecciÃ³nâ (Figura <CrossRef target="Figure" ref="generating_the_about_this_collection_page"/>) se conoce antes de la ejecuciÃ³n y estÃ¡ codificada en el archivo de macrosÂ <i>about.dm</i>. Los encabezados, los pies de pÃ¡gina y la imagen de fondo ni siquiera se mencionan porque se encuentran en el paquete de macrosÂ <i>Global</i>. Sin embargo, el texto especÃ­fico de âacerca deâ correspondiente a una colecciÃ³n particular no se conoce de antemano, sino que se guarda en la base de datos de informaciones de la colecciÃ³n durante el proceso de creaciÃ³n. Esta informaciÃ³n se recupera mediante el protocolo y se guarda como macro _Â <i>collectionextra_</i>Â en el paquete de macrosÂ <i>Global</i>. ObsÃ©rvese que este nombre de macro es prÃ¡cticamente el mismo que se empleÃ³ para expresar esta informaciÃ³n en el archivo de configuraciÃ³n de colecciÃ³n mencionado en la SecciÃ³n <CrossRef target="Section" ref="import_and_build_processes"/>. Para generar el contenido de la pÃ¡gina, se amplÃ­a la macro _Â <i>content</i>Â _ en el paqueteÂ <i>about</i>Â (que se muestra en la Figura <CrossRef target="Figure" ref="part_of_the_aboutdm_macro_file"/>). Esta operaciÃ³n amplÃ­a a su vez _Â <i>textabout</i>Â _, que accede a la macro _Â <i>collectionextra</i>Â _ que acababa de colocarse allÃ­ de manera dinÃ¡mica.</Text>
+<Text id="780">Otro componente importante es el objeto Formato. Las instrucciones de formato en el archivo de configuraciÃ³n de colecciÃ³n inciden en la presentaciÃ³n de determinados elementos de informaciÃ³n, como se explica en la SecciÃ³n <CrossRef target="Section" ref="formatting_greenstone_output"/>. Su gestiÃ³n corre a cargo del objeto Formato representado en la Figura <CrossRef target="Figure" ref="greenstone_runtime_system"/>. La principal tarea de este objeto es analizar y evaluar instrucciones como las cadenas de formato de la Figura <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/>. Tal como vimos en la SecciÃ³n <CrossRef target="Section" ref="formatting_greenstone_output"/>, Ã©stas pueden comprender referencias a metadatos entre corchetes (por ejemplo,Â <i>[Title]</i>), que han de recuperarse del servidor de colecciÃ³n. Se producen interacciones entre el objeto Formato y el objeto Lenguaje de macros, ya que las instrucciones de formato pueden incluir macros, que cuando se amplÃ­an incluyen metadatos, y cuando Ã©stos se amplÃ­an a su vez incluyen macros, y asÃ­ sucesivamente.</Text>
+<Text id="781">El servidor de colecciÃ³n, visible en la parte inferior de la Figura <CrossRef target="Figure" ref="greenstone_runtime_system"/>, experimenta tambiÃ©n un proceso de inicializaciÃ³n, en el que establece objetos Filtro y de fuente para responder a las solicitudes que recibe del protocolo, y un objeto BÃºsqueda para prestar asistencia en esta tarea. En Ãºltima instancia, los objetos acceden a los Ã­ndices y las bases de datos de informaciones de colecciÃ³n, ambos elaborados durante la creaciÃ³n de la colecciÃ³n.</Text>
+<Text id="782">Sin contar las lÃ­neas en blanco, el recepcionista contiene 15.000 lÃ­neas de cÃ³digo. El servidor de colecciÃ³n sÃ³lo contiene 5.000 lÃ­neas, el 75% de las cuales estÃ¡n ocupadas por archivos de encabezado. El servidor de colecciÃ³n es mÃ¡s compacto porque la recuperaciÃ³n de los datos se lleva a cabo mediante dos programas precompilados. Se utiliza MG, un sistema de recuperaciÃ³n de texto completo, para las bÃºsquedas y GDBM, un sistema de gestiÃ³n de bases de datos, para la gestiÃ³n de la base de datos de informaciones de colecciÃ³n.</Text>
+<Text id="783">Para facilitar la extensibilidad y la flexibilidad, Greenstone utiliza considerablemente el mÃ©todo de herencia, en particular, en los objetos AcciÃ³n, Filtro, Fuente y BÃºsqueda. Esto significa que, para manejar una simple biblioteca digital que sÃ³lo contenga colecciones de textos, usted tiene que aprender un poco mÃ¡s para programar el sistema. No obstante, esto tambiÃ©n significa que MG y GDBM podrÃ­an sustituirse fÃ¡cilmente si ello fuera necesario. AdemÃ¡s, la arquitectura del programa es lo suficientemente rica para admitir todas las posibilidades multimedia, como el control de la interfaz por medio de sistemas de reconocimiento de voz oÂ  consultas en forma de grÃ¡fica.</Text>
+</Content>
+</Section>
+<Section id="how_the_conceptual_framework_fits_together">
+<Title>
+<Text id="784">Ajuste del marco conceptual</Text>
+</Title>
+<Content>
+<Text id="785">En las Secciones <CrossRef target="Section" ref="collection_server"/> y <CrossRef target="Section" ref="receptionist"/> se explica mÃ¡s detalladamente el funcionamiento del servidor de colecciÃ³n y del recepcionista, se amplÃ­a la informaciÃ³n sobre los mÃ³dulos de la Figura <CrossRef target="Figure" ref="greenstone_runtime_system"/> y se explica su implementaciÃ³n. Es conveniente, en primer lugar, ilustrar con ejemplos la interacciÃ³n de un usuario con el programa Greenstone y luego explicar lo que sucede âentre bastidoresâ. De momento, supondremos que todos los objetos estÃ¡n inicializados correctamente. La inicializaciÃ³n es un procedimiento bastante complejo que reexaminaremos en la SecciÃ³n <CrossRef target="Section" ref="initialisation"/>.</Text>
+<Subsection id="performing_a_search">
+<Title>
+<Text id="786">Efectuar una bÃºsqueda</Text>
+</Title>
+<Content>
+<Figure id="searching_gutenberg_for_darcy">
+<Title>
+<Text id="787">BÃºsqueda deÂ <i>Darcy</i>Â en el Proyecto Gutenberg</Text>
+</Title>
+<File width="604" height="375" url="images/Dev_Fig_25.png"/>
+</Figure>
+<Text id="788">Cuando un usuario introduce una consulta y pulsaÂ <i>Iniciar la bÃºsqueda</i>Â en la pÃ¡gina de bÃºsqueda, se activa una acciÃ³n Greenstone que culmina generando una nueva pÃ¡gina HTML mediante el lenguaje de macros. En la Figura <CrossRef target="Figure" ref="searching_gutenberg_for_darcy"/> se muestra el resultado de la bÃºsqueda del nombreÂ <i>Darcy</i>Â en la colecciÃ³n del Proyecto Gutenberg. La instrucciÃ³nÂ <i>a=q</i>Â se encuentra oculta en el HTML de la pÃ¡gina original de bÃºsqueda. Cuando se pulsa el botÃ³n de bÃºsqueda se activa esta instrucciÃ³n y se ejecuta la nueva acciÃ³nÂ <i>queryaction</i>. La ejecuciÃ³n deÂ <i>queryaction</i>Â consiste en una llamada al objeto Filtro de la colecciÃ³n designada (Â <i>c=gberg</i>) a travÃ©s del protocolo.</Text>
+<Text id="789">Los filtros desempeÃ±an una funciÃ³n bÃ¡sica importante en los servidores de colecciÃ³n. Adaptados a las actividades de bÃºsqueda y consulta, los filtros permiten seleccionar un subconjunto de informaciÃ³n en una colecciÃ³n. En este caso,Â <i>queryaction</i>Â inicia una solicitud de filtro:</Text>
+<BulletList>
+<Bullet>
+<Text id="790">estableciendo que el tipo de solicitud de filtro esÂ <i>QueryFilter</i>Â (los distintos tipos de filtro se explican en la SecciÃ³n <CrossRef target="Section" ref="collection_server"/>);</Text>
+</Bullet>
+<Bullet>
+<Text id="791">memorizando las preferencias de bÃºsqueda del usuario â reconocimiento de mayÃºsculas y minÃºsculas, truncamiento, etc.â en la solicitud de filtro;</Text>
+</Bullet>
+<Bullet>
+<Text id="792">activando la funciÃ³nÂ <i>filter( )</i>Â mediante el protocolo nulo.</Text>
+</Bullet>
+</BulletList>
+<Text id="793">Las llamadas al protocolo son sÃ­ncronicas. El recepcionista queda efectivamente bloqueado hasta que el servidor de colecciÃ³n trata la solicitud de filtro y se envÃ­an los datos generados.</Text>
+<Text id="794">Cuando se hace una llamada de protocolo de tipoÂ <i>QueryFilter</i>, el objeto de filtro (vÃ©ase la Figura <CrossRef target="Figure" ref="greenstone_runtime_system"/>) descodifica las opciones y llama al objeto BÃºsqueda, que utiliza MG para efectuar la bÃºsqueda propiamente dicha. La funciÃ³n del objeto BÃºsqueda es proporcionar una interfaz abstracta de programa que permita la bÃºsqueda, independientemente de la herramienta de bÃºsqueda subyacente que se utilice. El formato utilizado para enviar los resultados recurre tambiÃ©n a la abstracciÃ³n, lo cual obliga el objeto BÃºsqueda a traducir los datos generados por la herramienta de bÃºsqueda a una forma normalizada.</Text>
+<Text id="795">Una vez enviados los resultados de bÃºsqueda al recepcionista, se procede a formatearlos para su presentaciÃ³n utilizando los objetos Formato y Lenguaje de macros. Como se muestra en la Figura <CrossRef target="Figure" ref="searching_gutenberg_for_darcy"/>, esta operaciÃ³n supone: la creaciÃ³n del encabezado, el pie de pÃ¡gina, la barra de desplazamiento y la imagen de fondo normalizados de Greenstone; la repeticiÃ³n de la parte principal de la pÃ¡gina de consulta justo debajo de la barra de desplazamiento; y la presentaciÃ³n de un icono de libro, asÃ­ como el tÃ­tulo y el autor para cada uno de los resultados de la bÃºsqueda. El formato de esta Ãºltima parte depende de la instrucciÃ³nÂ <i>format SearchVList</i>Â que se encuentra en el archivo de configuraciÃ³n de la colecciÃ³n. Para poder mostrar los metadatos de tÃ­tulo y autor, Ã©stos han de recuperarse antes del servidor de colecciÃ³n, lo que requiere nuevas llamadas al protocolo, pero esta vez utilizandoÂ <i>BrowseFilter</i>Â (filtro de consulta).</Text>
+</Content>
+</Subsection>
+<Subsection id="retrieving_a_document">
+<Title>
+<Text id="796">RecuperaciÃ³n de un documento</Text>
+</Title>
+<Content>
+<Text id="797">Siguiendo con la bÃºsqueda anterior deÂ <i>Darcy</i>, obsÃ©rvese lo que sucede cuando visualiza un documento. En la Figura <CrossRef target="Figure" ref="the_golf_course_mystery"/> se muestra el resultado de pulsar el icono que se encuentra junto aÂ <i>The Golf Course Mystery</i>Â en la Figura <CrossRef target="Figure" ref="searching_gutenberg_for_darcy"/>.</Text>
+<Figure id="the_golf_course_mystery">
+<Title>
+<Text id="798"><i>The Golf Course Mystery</i></Text>
+</Title>
+<File width="465" height="461" url="images/Dev_Fig_26.png"/>
+</Figure>
+<Text id="799">El texto de origen de la colecciÃ³n Gutenberg consiste en un extenso archivo por cada libro. Durante la creaciÃ³n de la colecciÃ³n, dichos archivos se dividen en pÃ¡ginas separadas cada 200 lÃ­neas aproximadamente, y las informaciones importantes de cada pÃ¡gina se guardan en los Ã­ndices y en la base de datos de informaciones de la colecciÃ³n. En la parte superior de la Figura <CrossRef target="Figure" ref="the_golf_course_mystery"/> se indica que este libro tiene 104 pÃ¡ginas electrÃ³nicas, y justo debajo aparece el principio de la primera pÃ¡gina: el nombre de la persona que introdujo el texto, el tÃ­tulo, el autor y el principio de un Ã­ndice (dicho Ã­ndice forma parte del texto de origen del Proyecto Gutenberg y no ha sido generado por Greenstone). En la parte superior izquierda se ven los botones que controlan la presentaciÃ³n del documento: una sola pÃ¡gina o la totalidad del documento, si se resalta o no el tÃ©rmino de la consulta, y si se muestra o no el libro en su propia ventana, separado de la actividad principal de bÃºsqueda y consulta. En la parte superior derecha hay un asistente de consulta que proporciona acceso directo a cualquier pÃ¡gina del libro: basta con escribir el nÃºmero de la pÃ¡gina y pulsar el botÃ³n âir a la pÃ¡ginaâ. Asimismo, se pueden consultar las pÃ¡ginas anteriores y posteriores haciendo clic en los iconos de flecha situados de cada lado del dispositivo de selecciÃ³n de pÃ¡gina.</Text>
+<Text id="800">La operaciÃ³n de recuperaciÃ³n de documentos,Â <i>documentaction</i>, se especifica mediante la configuraciÃ³nÂ <i>a=d</i>Â y requiere varios argumentos suplementarios. Lo mÃ¡s importante es el documento por recuperar: Ã©ste se define mediante la variableÂ <i>d</i>. En la Figura <CrossRef target="Figure" ref="the_golf_course_mystery"/> su valor esÂ <i>d=HASH51e598821ed6cbbdf0942b.1</i>Â para recuperar la primera pÃ¡gina del documento cuyo identificador esÂ <i>HASH51e598821ed6cbbdf0942b</i>, y que en tÃ©rminos mÃ¡s convencionales se conoce comoÂ <i>The Golf Course Mystery</i>. Hay otras variables mediante las cuales se determina si el tÃ©rmino de bÃºsqueda ha de resaltarse o no (Â <i>hl</i>) y quÃ© pÃ¡gina del libro se debe mostrar (Â <i>gt</i>). Estas variables complementan las opciones propuestas por los botones de la pÃ¡gina Web representados en la Figura <CrossRef target="Figure" ref="the_golf_course_mystery"/> y antes mencionados. Se utilizan los valores por defecto cuando se omite cualquiera de estas variables.</Text>
+<Text id="801">Esta acciÃ³n sigue un procedimiento similar aÂ <i>queryaction</i>Â : examen de los argumentos CGI, acceso al servidor de colecciÃ³n mediante el protocolo y utilizaciÃ³n del resultado para generar una pÃ¡gina Web. Las opciones relativas al documento se descodifican a partir de los argumentos CGI y se guardan en el objeto para operaciones ulteriores. Para recuperar el documento desde el servidor de colecciÃ³n, sÃ³lo se necesita el identificador de documento para efectuar la llamada de protocoloÂ <i>get_document( )</i>. Una vez enviado el documento, queda por hacer un trabajo considerable de formateo. Para ello, el cÃ³digo deÂ <i>documentaction</i>Â accede a los argumentos almacenados y utiliza los objetos Formato y Lenguaje de macros.</Text>
+</Content>
+</Subsection>
+<Subsection id="browsing_a_hierarchical_classifier">
+<Title>
+<Text id="802">Consulta de un clasificador jerÃ¡rquico</Text>
+</Title>
+<Content>
+<Text id="803">En la Figura <CrossRef target="Figure" ref="browsing_titles_in_the_gutenberg_collection"/> se muestra un ejemplo de consulta, en que el usuario ha elegidoÂ <i>tÃ­tulos a-z</i>Â y ha accedido al hipervÃ­nculo de la letraÂ <i>K</i>. Esta operaciÃ³n se basa tambiÃ©n enÂ <i>documentaction,</i>Â funciÃ³n proporcionada por la especificaciÃ³n del argumento CGIÂ <i>a=d</i>, como en el caso anterior. Sin embargo, la diferencia es que antes se incluyÃ³ la variableÂ <i>d</i>Â y esta vez no. En su lugar, el nodo de la jerarquÃ­a de clasificaciÃ³n por visualizar se especifica con la variableÂ <i>cl</i>, que en este caso representa los tÃ­tulos agrupados bajo la letraÂ <i>K</i>. Esta lista se constituyÃ³ durante el proceso de creaciÃ³n y estÃ¡ guardada en la base de datos de informaciones de la colecciÃ³n.</Text>
+<Figure id="browsing_titles_in_the_gutenberg_collection">
+<Title>
+<Text id="804">Consulta de los tÃ­tulos de la colecciÃ³n Gutenberg</Text>
+</Title>
+<File width="605" height="519" url="images/Dev_Fig_27.png"/>
+</Figure>
+<Text id="805">Los registros que representan nodos de clasificador en la base de datos utilizan el prefijoÂ <i>CL</i>, seguido de nÃºmeros separados por puntos (.) para indicar dÃ³nde se encuentran dentro de la estructura de subdivisiones. Si se ignora el botÃ³n de bÃºsqueda (visible en el extremo izquierdo de la barra de desplazamiento), los clasificadores se numeran secuencialmente por orden ascendente, de izquierda a derecha, empezando por 1. AsÃ­ pues, el nodo de clasificador de primer nivel para los tÃ­tulos en nuestro ejemplo esÂ <i>CL1</i>, y la pÃ¡gina buscada se obtiene indicandoÂ <i>cl=CL1.11</i>, como puede verse en la direcciÃ³n URL que aparece en la parte superior de la Figura <CrossRef target="Figure" ref="browsing_titles_in_the_gutenberg_collection"/>.</Text>
+<Text id="806">Para tratar una solicitud de documento de tipoÂ <i>cl</i>, se utiliza el objeto Filtro para recuperar el nodo a travÃ©s del protocolo. SegÃºn los datos enviados, se efectÃºan ulteriores llamadas de protocolo para recuperar los metadatos de los documentos. En este caso, se obtienen los tÃ­tulos de los libros. Sin embargo, si se tratara de un nodo interno cuyos elementos secundarios fueran a su vez nodos, se recuperarÃ­an tambiÃ©n los tÃ­tulos de los nodos secundarios. Desde el punto de vista de la codificaciÃ³n es lo mismo y de ello se encarga el mismo mecanismo.</Text>
+<Text id="807">Por Ãºltimo, toda la informaciÃ³n recuperada se interconecta mediante el lenguaje de macros a fin de crear la pÃ¡gina Web que se muestra en la Figura <CrossRef target="Figure" ref="browsing_titles_in_the_gutenberg_collection"/>.</Text>
+</Content>
+</Subsection>
+<Subsection id="generating_the_home_page">
+<Title>
+<Text id="808">GeneraciÃ³n de la pÃ¡gina principal</Text>
+</Title>
+<Content>
+<Figure id="greenstone_home_page">
+<Title>
+<Text id="809">PÃ¡gina principal de Greenstone</Text>
+</Title>
+<File width="604" height="571" url="images/Dev_Fig_28.png"/>
+</Figure>
+<Text id="810">Como Ãºltimo ejemplo, examinaremos el caso de la generaciÃ³n de la pÃ¡gina principal de Greenstone. En la Figura <CrossRef target="Figure" ref="greenstone_home_page"/> se muestra âen el caso de la instalaciÃ³n por defecto de Greenstoneâ su pÃ¡gina principal tras la instalaciÃ³n de algunas colecciones de prueba. La direcciÃ³n URL, que puede verse en la parte superior de la pantalla, incluye los argumentosÂ <i>a=p</i>Â yÂ <i>p=home</i>. AsÃ­ pues, al igual que en el caso de la pÃ¡gina âAcerca de esta colecciÃ³nâ, Ã©sta se genera mediante unaÂ <i>pageaction</i>Â (a=p), pero esta vez la pÃ¡gina creada esÂ <i>home</i>Â (Â <i>p=home</i>). Por consiguiente, el lenguaje de macros accede al contenido del archivoÂ <i>home.dm</i>. En este caso no es necesario especificar una colecciÃ³n (mediante la variableÂ <i>c</i>).</Text>
+<Text id="811">La finalidad de la pÃ¡gina principal es mostrar las colecciones disponibles. Cuando el usuario hace clic en un icono, aparece la pÃ¡gina âAcerca de esta colecciÃ³nâ de la colecciÃ³n correspondiente. Cada vez que se carga la pÃ¡gina, se genera dinÃ¡micamente el menÃº de las colecciones basÃ¡ndose en las colecciones que se encuentran en el sistema de archivos en ese momento. Cuando una nueva colecciÃ³n se pone en lÃ­nea, aparece automÃ¡ticamente en la pÃ¡gina principal cuando Ã©sta se vuelve a cargar, siempre que se haya especificado que la colecciÃ³n es âpÃºblicaâ.</Text>
+<Text id="812">Para ello, el recepcionista utiliza, desde luego, el protocolo. Como parte de su funciÃ³n de evaluaciÃ³n de los argumentos CGI, la acciÃ³nÂ <i>pageaction</i>Â estÃ¡ programada para detectar el caso particularÂ <i>p=home</i>. A continuaciÃ³n, la acciÃ³n utiliza la llamada de protocoloÂ <i>get_collection_list()</i>Â para establecer el conjunto de colecciones que se encuentran en lÃ­nea y activaÂ <i>get_collectinfo()</i>Â a fin de obtener informaciÃ³n sobre cada una de ellas. Dicha informaciÃ³n indica si la colecciÃ³n puede consultarse pÃºblicamente, cuÃ¡l es la direcciÃ³n URL del icono de la colecciÃ³n (si es que existe) y el nombre completo de la colecciÃ³n. Estos datos se utilizan para generar una entrada apropiada de la colecciÃ³n en la pÃ¡gina principal.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="source_code">
+<Title>
+<Text id="813">El cÃ³digo fuente</Text>
+</Title>
+<Content>
+<Table id="standalone_programs_included_in_greenstone">
+<Title>
+<Text id="814">Programas autÃ³nomos incluidos en Greenstone</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="815"><i>setpasswd/</i></Text>
+</th>
+<th width="397">
+<Text id="816">Ayuda para las contraseÃ±as bajo Windows.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="817"><i>getpw/</i></Text>
+</th>
+<th width="397">
+<Text id="818">Ayuda para las contraseÃ±as bajo Unix.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="819"><i>txt2db/</i></Text>
+</th>
+<th width="397">
+<Text id="820">Convierte un formato de texto ASCII de tipo XML en formato de base de datos de GNU.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="821"><i>db2txt/</i></Text>
+</th>
+<th width="397">
+<Text id="822">Convierte el formato de base de datos de GNU en formato de texto ASCII de tipo XML. </Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="823"><i>phind/</i></Text>
+</th>
+<th width="397">Â Â Â Â Â Â Â Â Â Â Â Â  
+<Text id="824">Herramienta de consulta jerÃ¡rquica en los grupos de palabras.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="825"><i>hashfile/</i></Text>
+</th>
+<th width="397">Â Â Â Â Â Â Â Â  
+<Text id="826">Calcula un identificador de documento Ãºnico, basÃ¡ndose en el contenido del archivo.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="827"><i>mgpp/</i></Text>
+</th>
+<th width="397">Â Â Â Â Â Â Â Â Â Â Â Â Â  
+<Text id="828">VersiÃ³n reescrita y actualizada del paqueteÂ <i>Managing Gigabytes</i>Â en C++</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="829"><i>w32server/</i></Text>
+</th>
+<th width="397">Â Â Â Â  
+<Text id="830">Servidor de Biblioteca Local para Windows.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="831"><i>checkis/</i></Text>
+</th>
+<th width="397">Â Â Â Â Â Â Â Â Â  
+<Text id="832">Ayuda especÃ­fica para la instalaciÃ³n de Greenstone bajo Windows.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="833">El cÃ³digo fuente del sistema de ejecuciÃ³n se encuentra enÂ <i>GSDLHOME/src</i>. Ocupa dos subdirectorios,Â <i>recpt</i>Â para el cÃ³digo del recepcionista yÂ <i>colservr</i>Â para el del servidor de colecciÃ³n. Greenstone funciona bajo Windows a partir de la versiÃ³n Windows 3.1, lo cual impone desafortunadamente un mÃ¡ximo de ocho caracteres en los nombres de archivos y directorios. Esto explica la utilizaciÃ³n de abreviaciones crÃ­pticas comoÂ <i>recpt</i>Â yÂ <i>colservr</i>. Los demÃ¡s subdirectorios incluyen programas independientes que se utilizan principalmente para reforzar el proceso de creaciÃ³n (vÃ©ase el Cuadro <CrossRef target="Table" ref="standalone_programs_included_in_greenstone"/>).</Text>
+<Text id="834">Otro directorio,Â <i>GSDLHOME/lib</i>, incluye objetos de nivel inferior que el recepcionista y el servidor de colecciÃ³n utilizan. En la SecciÃ³n <CrossRef target="Section" ref="common_greenstone_types"/> se explica este cÃ³digo.</Text>
+<Text id="835">Greenstone utiliza considerablemente la Biblioteca EstÃ¡ndar de Plantillas (STL), una biblioteca C++ de amplia difusiÃ³n concebida por Silicon Graphics (Â <i>www.sgi.com</i>), y que es el resultado de numerosos aÃ±os de investigaciÃ³n y desarrollo. Como todas las bibliotecas de programaciÃ³n requiere un tiempo de aprendizaje. En el ApÃ©ndice A se presenta un breve resumen de las principales porciones que se utilizan en el cÃ³digo de Greenstone. Para una descripciÃ³n mÃ¡s completa, consulte el manual oficial de referencia de STL disponible en la direcciÃ³n InternetÂ <i>www.sgi.com</i>, o alguno de los numerosos manuales sobre STL, como por ejemplo el de Josuttis (1999).</Text>
+</Content>
+</Section>
+<Section id="common_greenstone_types">
+<Title>
+<Text id="836">Tipos bÃ¡sicos de Greenstone</Text>
+</Title>
+<Content>
+<Text id="837">Los elementos definidos en el directorioÂ <i>GSDLHOME/lib</i>Â son objetos Greenstone de nivel inferior, creados por encima de STL, y que se utilizan en todo el cÃ³digo fuente. En primer lugar, describimos con detallesÂ <i>text_t</i>, un objeto utilizado para representar texto Unicode y luego resumimos la finalidad de cada uno de los archivos de biblioteca.</Text>
+<Subsection id="the_text_t_object">
+<Title>
+<Text id="838">El objetoÂ <i>text_t</i></Text>
+</Title>
+<Content>
+<Text id="839">Greenstone funciona con mÃºltiples idiomas, tanto en lo que se refiere al contenido de una colecciÃ³n como a la interfaz de usuario. Para ello, se utiliza Unicode a todo lo largo del cÃ³digo fuente. El objeto subyacente que realiza una cadena Unicode esÂ <i>text_t</i>.</Text>
+<Figure id="the_text_t_api" class="withLineNumber">
+<Title>
+<Text id="840">La API deÂ <i>text_t</i>Â (abreviada)</Text>
+</Title>
+<CodeLine>typedef vector&lt;unsigned short&gt; usvector;</CodeLine>
+<CodeLine/>
+<CodeLine>class text_t {</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>usvector text;</CodeLine>
+<CodeLine>unsigned short encoding; // 0 = unicode, 1 = other</CodeLine>
+<CodeLine/>
+<CodeLine>public:</CodeLine>
+<CodeLine>Â  // constructors</CodeLine>
+<CodeLine>Â  text_t ();</CodeLine>
+<CodeLine>Â  text_t (int i);</CodeLine>
+<CodeLine>Â  text_t (char *s); // assumed to be a normal c string</CodeLine>
+<CodeLine/>
+<CodeLine>Â  void setencoding (unsigned short theencoding);</CodeLine>
+<CodeLine>Â  unsigned short getencoding ();</CodeLine>
+<CodeLine/>
+<CodeLine>Â  // STL container support</CodeLine>
+<CodeLine>Â  iterator begin ();</CodeLine>
+<CodeLine>Â  iterator end (); </CodeLine>
+<CodeLine/>
+<CodeLine>Â  void erase(iterator pos);</CodeLine>
+<CodeLine>Â  void push_back(unsigned short c);</CodeLine>
+<CodeLine>Â  void pop_back();</CodeLine>
+<CodeLine/>
+<CodeLine>Â  void reserve (size_type n);</CodeLine>
+<CodeLine/>
+<CodeLine>Â  bool empty () const {return text.empty();}</CodeLine>
+<CodeLine>Â  size_type size() const {return text.size();}</CodeLine>
+<CodeLine/>
+<CodeLine>Â  // added functionality</CodeLine>
+<CodeLine>Â  void clear ();</CodeLine>
+<CodeLine>Â  void append (const text_t &amp;t);</CodeLine>
+<CodeLine/>
+<CodeLine>Â  // support for integers</CodeLine>
+<CodeLine>Â  void appendint (int i);</CodeLine>
+<CodeLine>Â  void setint (int i);</CodeLine>
+<CodeLine>Â  int getint () const;</CodeLine>
+<CodeLine/>
+<CodeLine>Â  // support for arrays of chars</CodeLine>
+<CodeLine>Â  void appendcarr (char *s, size_type len);</CodeLine>
+<CodeLine>Â  void setcarr (char *s, size_type len);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="841">Unicode necesita dos bytes para almacenar cada carÃ¡cter. En la Figura <CrossRef target="Figure" ref="the_text_t_api"/> se muestran las caracterÃ­sticas principales de la interfaz para programas de aplicaciÃ³n (API, esto es,Â <i>Application Program Interface</i>) deÂ <i>text_t</i>. El requisito de los dos bytes se cumple utilizando el tipo estÃ¡ndar C++Â <i>short</i>, que se define como un nÃºmero entero de dos bytes. El principal tipo de datos del objetoÂ <i>text_t</i>Â es una matriz dinÃ¡mica deÂ <i>unsigned</i><i>shorts</i>Â elaborada mediante la declaraciÃ³n STLÂ <i>vector&lt;unsigned short&gt;</i>Â y que recibe el nombre abreviado deÂ <i>usvector</i>.</Text>
+<Text id="842">Las funciones de creaciÃ³n (lÃ­neas 10-12) admiten explÃ­citamente tres formas de inicializaciÃ³n: creaciÃ³n sin parÃ¡metros, que genera una cadena Unicode vacÃ­a; creaciÃ³n con un parÃ¡metro entero, que genera una versiÃ³n de texto Unicode con el valor numÃ©rico proporcionado; y creaciÃ³n con un parÃ¡metroÂ <i>char*</i>, que trata el argumento como una cadena C++ terminada en cero y genera una versiÃ³n Unicode del mismo.</Text>
+<Text id="843">A continuaciÃ³n, la mayor parte del cÃ³digo (lÃ­neas 17-28) se ocupa de mantener un contenedor de tipo vector STL:Â <i>begin( )</i>,Â <i>end( )</i>,Â <i>push_back( )</i>,Â <i>empty( )</i>, etc. Permite asimismo borrar y concatenar cadenas, asÃ­ como convertir un nÃºmero entero en una cadena de texto Unicode y remitir el correspondiente valor entero a un texto que representa un nÃºmero.</Text>
+<Figure id="overloaded_operators_to_text_t" class="withLineNumber">
+<Title>
+<Text id="844">Operadores sobrecargados paraÂ <i>text_t</i></Text>
+</Title>
+<CodeLine>class text_t{</CodeLine>
+<CodeLine>Â Â Â Â Â  // ...</CodeLine>
+<CodeLine>Â Â Â Â Â  public:</CodeLine>
+<CodeLine>Â Â Â Â Â  text_t &amp;operator=(const text_t &amp;x);</CodeLine>
+<CodeLine>Â Â Â Â Â  text_t &amp;operator+=(const text_t &amp;t);</CodeLine>
+<CodeLine>Â Â Â Â Â  reference operator[](size_type n);</CodeLine>
+<CodeLine/>
+<CodeLine>Â Â Â Â Â  text_t &amp;operator=(int i);</CodeLine>
+<CodeLine>Â Â Â Â Â  text_t &amp;operator+= (int i);</CodeLine>
+<CodeLine>Â Â Â Â Â  text_t &amp;operator= (char *s);</CodeLine>
+<CodeLine>Â Â Â Â Â  text_t &amp;operator+= (char *s);</CodeLine>
+<CodeLine/>
+<CodeLine>Â Â Â Â Â  friend inline bool operator!=(const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>Â Â Â Â Â  friend inline bool operator==(const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>Â Â Â Â Â  friend inline bool operator&lt; (const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>Â Â Â Â Â  friend inline bool operator&gt; (const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>Â Â Â Â Â  friend inline bool operator&gt;=(const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>Â Â Â Â Â  friend inline bool operator&lt;=(const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>Â Â Â Â Â  // ...</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="845">Existen numerosos operadores sobrecargados que no aparecen en la Figura <CrossRef target="Figure" ref="the_text_t_api"/>. La Figura <CrossRef target="Figure" ref="overloaded_operators_to_text_t"/> nos da una idea general de las operaciones posibles. La lÃ­nea 4 permite asignar un objetoÂ <i>text_t</i>Â a otro, y la lÃ­nea 5 sobrecarga el operador += para poder concatenar de modo mÃ¡s natural un objetoÂ <i>text_t</i>Â al final de otro. La lÃ­nea 6 permite asimismo tener acceso a un carÃ¡cter Unicode particular (representado como unÂ <i>short</i>) utilizando subÃ­ndices de matriz [ ]. Se proporcionan asimismo operadores de asignaciÃ³n y concatenaciÃ³n para los nÃºmeros enteros y las cadenas C++. Las lÃ­neas 12-18 suministran operadores booleanos para comparar dos objetosÂ <i>text_t</i>Â : igual a, diferente de, precede alfabÃ©ticamente, etc.</Text>
+<Text id="846">Existen asimismo funciones miembro que toman argumentos de tipoÂ <i>const</i>Â en lugar de argumentos noÂ <i>-const</i>, pero no se muestran aquÃ­. Dicha repeticiÃ³n es habitual en los objetos C++: aumenta el volumen de la API pero sin incrementarla conceptualmente. En realidad, muchas de estas funciones se implementan como instrucciones individuales de una sola lÃ­nea. Para mayor informaciÃ³n, consulte el archivo fuenteÂ <i>GSDLHOME/lib/text_t.h</i>.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_greenstone_library_code">
+<Title>
+<Text id="847">El cÃ³digo de biblioteca Greenstone</Text>
+</Title>
+<Content>
+<Text id="848">Los archivos de encabezados situados en el directorioÂ <i>GSDLHOME/lib</i>Â comprenden una mezcla de funciones y objetos que contribuyen Ãºtilmente al sistema de ejecuciÃ³n de Greenstone. Cuando lo importante es la eficiencia, las funciones y las funciones miembro se especificanÂ <i>inline</i>. En la mayorÃ­a de los casos, los detalles de implementaciÃ³n se incluyen en el archivoÂ <i>.cpp</i>Â correspondiente al archivo de encabezados.</Text>
+<Table class="hidden">
+<Title/>
+<TableContent>
+<tr>
+<th width="100">
+<Text id="849"><b>cfgread.h</b></Text>
+</th>
+<th width="450">
+<Text id="850">Funciones de lectura y escritura de archivos de configuraciÃ³n. Por ejemplo, la funciÃ³nÂ <i>read_cfg_line( )</i>Â (leer archivo de configuraciÃ³n) toma como argumentos el flujo de entrada y la matrizÂ <i>text_tarray</i>Â (abreviaciÃ³n deÂ <i>vector&lt;text_t&gt;</i>) para rellenar con los datos leÃ­dos.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="851"><b>display.h</b></Text>
+</th>
+<th width="450">
+<Text id="852">Objeto complejo utilizado por el recepcionista para definir, almacenar y ampliar macros, y para manejar tipos. En la SecciÃ³n <CrossRef target="Section" ref="receptionist"/> se proporciona mayor informaciÃ³n al respecto.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="853"><b>fileutil.h</b></Text>
+</th>
+<th width="450">
+<Text id="854">Auxiliar para funciones de gestiÃ³n de archivos independientes del sistema operativo. Por ejemplo,Â <i>filename_cat( )</i>Â admite hasta seis argumentosÂ <i>text_t</i>Â y devuelve unÂ <i>text_t</i>Â que es el resultado de concatenar los elementos utilizando el separador de directorio adecuado para el sistema operativo en cuestiÃ³n.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="855"><b>gsdlconf.h</b></Text>
+</th>
+<th width="450">
+<Text id="856">Funciones especÃ­ficas del sistema que contestan a preguntas como: Â¿el sistema operativo que se estÃ¡ utilizando para la compilaciÃ³n necesita acceder al archivoÂ Â <i>strings.h</i>Â asÃ­ como al archivoÂ <i>string.h</i>Â ? Â¿Se han definido correctamente todos los valores apropiados para el bloqueo de archivos?</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="857"><b>gsdltimes.h</b></Text>
+</th>
+<th width="450">
+<Text id="858">FunciÃ³n de apoyo para fechas y horas. Por ejemplo,Â <i>time2text( )</i>Â toma la hora de la computadora, expresada como el nÃºmero de segundos transcurridos desde el 1Âº de enero de 1970, y la convierte en el formato AAAA/MM/DD hh:mm:ss, que devuelve como tipoÂ <i>text_t</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="859"><b>gsdltools.h</b></Text>
+</th>
+<th width="450">
+<Text id="860">Apoyo variado al sistema de ejecuciÃ³n de Greenstone: determina si se trata deÂ <i>littleEndian</i>Â oÂ <i>bigEndian</i>Â ; comprueba si Perl estÃ¡ disponible; ejecuta un comando del sistema (con âcampaneos y silbidosâ, esto es, con ciertas cualidades avanzadas y exageradas del programa); y elude los caracteres especiales de macro en una cadenaÂ <i>text_t</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="861"><b>gsdlunicode.h</b></Text>
+</th>
+<th width="450">
+<Text id="862">Serie de objetos heredados que admiten tratar las cadenasÂ <i>text_t</i>Â de Unicode a travÃ©s de flujos de entrada y salida, como las conversiones de Unicode en UTF-8 y viceversa; y la supresiÃ³n de los espacios de ancho cero. Administra asimismo los archivos de correspondencia mediante el objetoÂ <i>mapconvert</i>, y carga los cuadros de correspondencia en el directorioÂ <i>GSDLHOME/mappings</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="863"><b>text_t.h</b></Text>
+</th>
+<th width="450">
+<Text id="864">Principalmente el objeto de texto de Unicode antes expuesto. Proporciona asimismo dos clases de conversiÃ³n de flujos:Â <i>inconvertclass</i>Â yÂ <i>outconvertclass</i>. Son las clases de base utilizadas en el archivoÂ <i>gsdlunicode.h</i>.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="collection_server">
+<Title>
+<Text id="865">El servidor de colecciones</Text>
+</Title>
+<Content>
+<Text id="866">Ahora pasaremos a explicar sistemÃ¡ticamente todos los objetos del marco conceptual de la Figura <CrossRef target="Figure" ref="greenstone_runtime_system"/>. Empezaremos por la parte inferior del diagrama, que constituye ademÃ¡s la base del sistema, con los objetos BÃºsqueda (<i>Search</i>), Fuente (Â <i>Source</i>) y Filtro (Â <i>Filter</i>), y recorreremos las capas del protocolo hasta llegar a los componentes centrales del Recepcionista, Acciones, Formato y Lenguaje de macros. Luego nos centraremos en la inicializaciÃ³n de los objetos, ya que es mÃ¡s fÃ¡cil entender este proceso una vez que se conoce la funciÃ³n de los distintos objetos.</Text>
+<Text id="867">La mayorÃ­a de las clases fundamentales del marco conceptual se expresan mediante la herencia virtual para facilitar la extensibilidad. Mediante la herencia virtual, los objetos heredados se pueden transferir como su clase base, pero cuando se activa una funciÃ³n miembro, la versiÃ³n definida en el objeto heredado es la que se ejecuta. Como el cÃ³digo fuente de Greenstone utiliza la clase base en todas partes, excepto donde se crean los objetos, esto significa que se pueden insertar fÃ¡cilmente diferentes implementaciones, utilizando tal vez tecnologÃ­as subyacentes radicalmente diferentes.</Text>
+<Text id="868">Por ejemplo, supongamos que una clase de base denominadaÂ <i>BaseCalc</i>Â se encarga de la aritmÃ©tica elemental: suma, resta, multiplicaciÃ³n y divisiÃ³n. Si todas sus funciones se declaran virtuales, y todos los argumentos y tipos devueltos se declaran como cadenas, podemos implementar fÃ¡cilmente las versiones heredadas del objeto. Una de ellas, llamadaÂ <i>FixedPrecisionCalc</i>, podrÃ­a utilizar las funciones de la biblioteca C para las conversiones entre cadenas y nÃºmeros enteros e implementar los cÃ¡lculos con los operadores aritmÃ©ticos habituales: +, -, *,Â  y /. La otra, llamadaÂ <i>InfinitePrecisionCalc</i>, podrÃ­a acceder a los argumentos de cadena carÃ¡cter por carÃ¡cter, efectuando operaciones aritmÃ©ticas que en principio son de una precisiÃ³n infinita. Escribiendo un programa principal que utilizaÂ <i>BaseCalc</i>Â por doquier, la implementaciÃ³n puede pasar de la precisiÃ³n finita a la precisiÃ³n infinita modificando una sola lÃ­nea: el lugar donde se crea el objeto de cÃ¡lculo.</Text>
+<Subsection id="the_search_object">
+<Title>
+<Text id="869">El objeto BÃºsqueda (<i>Search</i>)</Text>
+</Title>
+<Content>
+<Figure id="search_base_class_api">
+<Title>
+<Text id="870">API de la clase base BÃºsqueda (<i>Search</i>)</Text>
+</Title>
+<CodeLine>class searchclass {</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>Â  searchclass ();</CodeLine>
+<CodeLine>Â  virtual ~searchclass ();</CodeLine>
+<CodeLine>Â  // the index directory must be set before any searching</CodeLine>
+<CodeLine>Â  // is done </CodeLine>
+<CodeLine>Â  virtual void setcollectdir (const text_t &amp;thecollectdir);</CodeLine>
+<CodeLine>Â  // the search results are returned in queryresults</CodeLine>
+<CodeLine>Â  // search returns âtrueâ if it was able to do a search</CodeLine>
+<CodeLine>Â  virtual bool search(const queryparamclass &amp;queryparams,</CodeLine>
+<CodeLine>Â  Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  queryresultsclass &amp;queryresults)=0;</CodeLine>
+<CodeLine>Â  // the document text for âdocnumâ is placed in âoutputâ</CodeLine>
+<CodeLine>Â  // docTargetDocument returns âtrueâ if it was able to</CodeLine>
+<CodeLine>Â  // try to get a document</CodeLine>
+<CodeLine>Â  // collection is needed to see if an index from the</CodeLine>
+<CodeLine>Â  // collection is loaded. If no index has been loaded</CodeLine>
+<CodeLine>Â  // defaultindex is needed to load one</CodeLine>
+<CodeLine>Â  virtual bool docTargetDocument(const text_t &amp;defaultindex,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  const text_t &amp;defaultsubcollection,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  const text_t &amp;defaultlanguage,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  const text_t &amp;collection,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  int docnum,</CodeLine>
+<CodeLine>Â Â  Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â text_t &amp;output)=0;</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>Â  querycache *cache;</CodeLine>
+<CodeLine>Â  text_t collectdir; // the collection directory</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="871">En la Figura <CrossRef target="Figure" ref="search_base_class_api"/> se muestra el API de la clase de base para el objeto de bÃºsqueda de la Figura <CrossRef target="Figure" ref="greenstone_runtime_system"/>. Define dos funciones miembro virtuales:Â <i>search( )</i>Â yÂ <i>docTargetDocument( )</i>. Tal como indica elÂ <i>=0</i>Â que sigue la declaraciÃ³n de argumento, se trata de funciones puras, lo que significa que una clase que hereda este objeto debe implementar ambas funciones (de otro modo el compilador se quejarÃ¡).</Text>
+<Text id="872">La clase incluye asimismo dos campos de datos protegidos:Â <i>collectdir</i>Â yÂ <i>cache</i>. Cuando se instancia un objeto de bÃºsqueda para una colecciÃ³n particular, se utiliza el campoÂ <i>collectdir</i>Â para determinar dÃ³nde estÃ¡ guardada esa colecciÃ³n (y, lo que es mÃ¡s importante, sus archivos de Ã­ndice) en el sistema de archivos. El campoÂ <i>cache</i>Â retiene el resultado de una consulta. Se utiliza para acelerar el tratamiento de consultas ulteriores que repiten la primera (y sus parÃ¡metros). Puede parecer improbable que se efectÃºen consultas idÃ©nticas, pero de hecho esto ocurre con bastante frecuencia. El protocolo de Greenstone es sin estado. A fin de generar una pÃ¡gina de resultados como la de la Figura <CrossRef target="Figure" ref="searching_gutenberg_for_darcy"/>, pero con los resultados 11-20 de la misma consulta, se transmite de nuevo la bÃºsqueda especificando, en este caso, que se presente la serie de documentos 11-20. El campoÂ <i>cache</i>Â acelera esta operaciÃ³n, puesto que se comprueba que la bÃºsqueda ya ha sido ejecutada y los resultados se sacan directamente de este campo.</Text>
+<Text id="873">Ambos campos de datos son aplicables a todos los objetos heredados que implementan un mecanismo de bÃºsqueda. Por ello aparecen en la clase de base y se declaran dentro de una secciÃ³n protegida de la clase, a fin de que las clases heredadas puedan acceder directamente a ellos.</Text>
+</Content>
+</Subsection>
+<Subsection id="search_and_retrieval_with_mg">
+<Title>
+<Text id="874">BÃºsqueda y recuperaciÃ³n con MG</Text>
+</Title>
+<Content>
+<Text id="875">Greenstone utiliza MG (abreviaciÃ³n deÂ <i>Managing Gigabytes</i>Â ; vÃ©ase WittenÂ <i>et al</i>., 1999) para indizar y recuperar documentos, y su cÃ³digo fuente se incluye en el directorioÂ <i>GSDLHOME/packages</i>. MG emplea tÃ©cnicas de compresiÃ³n para optimizar la utilizaciÃ³n del espacio de disco sin alterar la rapidez de ejecuciÃ³n. En el caso de una colecciÃ³n de documentos en inglÃ©s, el texto comprimido y los Ã­ndices suelen ocupar un tercio del espacio que necesitarÃ­a el texto original sin comprimir. La bÃºsqueda y recuperaciÃ³n suelen ser mÃ¡s rÃ¡pidas que las operaciones equivalentes en la versiÃ³n sin comprimir porque requieren menos operaciones en el disco duro.</Text>
+<Figure id="api_for_direct_access_to_mg">
+<Title>
+<Text id="876">API para acceder directamente a MG (abreviada)</Text>
+</Title>
+<CodeLine>enum result_kinds {</CodeLine>
+<CodeLine>Â  result_docs,Â Â Â Â Â  // Return the documents found in last search</CodeLine>
+<CodeLine>Â  result_docnums,Â Â  // Return document id numbers and weights</CodeLine>
+<CodeLine>Â  result_termfreqs, // Return terms and frequencies</CodeLine>
+<CodeLine>Â  result_termsÂ Â Â Â Â  // Return matching query terms</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine>int mgq_ask(char *line);</CodeLine>
+<CodeLine>int mgq_results(enum result_kinds kind, int skip, int howmany,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  int (*sender)(char *, int, int, float, void *),</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â  Â Â Â Â Â Â Â void *ptr);</CodeLine>
+<CodeLine>int mgq_numdocs(void);</CodeLine>
+<CodeLine>int mgq_numterms(void);</CodeLine>
+<CodeLine>int mgq_equivterms</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â  (unsigned char *wordstem,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â  Â int (*sender)(char *, int, int, float, void *),</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â  Â void *ptr);</CodeLine>
+<CodeLine>int mgq_docsretrieved (int *total_retrieved, int *is_approx);</CodeLine>
+<CodeLine>int mgq_getmaxstemlen ();</CodeLine>
+<CodeLine>void mgq_stemword (unsigned char *word);</CodeLine>
+</Figure>
+<Text id="877">MG se utiliza por lo general de manera interactiva tecleando las instrucciones desde la lÃ­nea de comandos, y un modo de implementarÂ <i>mgsearchclass</i>Â serÃ­a activando la llamadaÂ <i>system( )</i>Â de la biblioteca C dentro del objeto para ejecutar los comandos MG apropiados. Sin embargo, un mÃ©todo mÃ¡s eficaz consiste en intervenir directamente en el cÃ³digo de MG utilizando las llamadas de funciÃ³n. Aunque esto requiere un mayor conocimiento del cÃ³digo de MG, una gran parte de la complejidad puede ocultarse tras una nueva API que pasarÃ¡ a ser el punto de contacto para el objetoÂ <i>mgsearchclass</i>. Ãsta es la funciÃ³n del archivoÂ <i>colserver/mgq.c</i>, cuya API se muestra en la Figura <CrossRef target="Figure" ref="api_for_direct_access_to_mg"/>.</Text>
+<Text id="878">Para proporcionar parÃ¡metros a MG, se usaÂ <i>mgq_ask( )</i>, que admite opciones de texto en un formato idÃ©ntico al que se usa en la lÃ­nea de comandos, como por ejemplo:</Text>
+<CodeLine>mgq_ask(â.set casefold offâ);</CodeLine>
+<Text id="879">Se utiliza asimismo para activar una consulta. Se accede a los resultados mediante la funciÃ³nÂ <i>mgq_results</i>, que adopta como cuarto parÃ¡metro un puntero dirigido hacia una funciÃ³n. Ello proporciona un modo flexible de convertir la informaciÃ³n devuelta en estructuras de datos de MG en el formato que requiereÂ <i>mgsearchclass</i>. Las operaciones comoÂ <i>mgq_numdocs( )</i>,Â <i>mgq_numterms( )</i>Â yÂ <i>mgq_docsretrieved( )</i>Â tambiÃ©n devuelven informaciÃ³n, pero prescritas de manera mÃ¡s precisa. Las dos Ãºltimas contribuyen a la funciÃ³n de truncamiento.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_source_object">
+<Title>
+<Text id="880">El objeto Fuente (<i>Source</i>)</Text>
+</Title>
+<Content>
+<Figure id="source_base_class_api">
+<Title>
+<Text id="881">API de la clase base Fuente (<i>Source</i>)</Text>
+</Title>
+<CodeLine>class sourceclass {</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>Â  sourceclass ();</CodeLine>
+<CodeLine>Â  virtual ~sourceclass ();</CodeLine>
+<CodeLine>Â  // configure should be called once for each configuration line</CodeLine>
+<CodeLine>Â  virtual void configure (const text_t &amp;key, </CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  const text_tarray &amp;cfgline);</CodeLine>
+<CodeLine>Â  // init should be called after all the configuration is done but</CodeLine>
+<CodeLine>Â  // before any other methods are called</CodeLine>
+<CodeLine>Â  virtual bool init (ostream &amp;logout);</CodeLine>
+<CodeLine>Â  // translate_OID translates OIDs using ".pr", ."fc" etc.</CodeLine>
+<CodeLine>Â  virtual bool translate_OID (const text_t &amp;OIDin, text_t &amp;OIDout,</CodeLine>
+<CodeLine>Â  Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>Â  // get_metadata fills out the metadata if possible, if it is not</CodeLine>
+<CodeLine>Â  // responsible for the given OID then it returns false.</CodeLine>
+<CodeLine>Â  virtual bool get_metadata (const text_t &amp;requestParams, </CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  Â Â const text_t &amp;refParams,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  Â Â bool getParents,</CodeLine>
+<CodeLine>Â Â Â Â Â  Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â const text_tset &amp;fields,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  Â Â const text_t &amp;OID,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  Â Â MetadataInfo_tmap &amp;metadata,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  Â Â comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>Â  virtual bool get_document (const text_t &amp;OID, text_t &amp;doc,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  Â Â comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>}; </CodeLine>
+</Figure>
+<Text id="882">La funciÃ³n del objeto Fuente (<i>Source</i>) de la Figura <CrossRef target="Figure" ref="greenstone_runtime_system"/> es acceder a los metadatos y al texto del documento; la API de su clase de base se muestra en la Figura <CrossRef target="Figure" ref="source_base_class_api"/>. Una funciÃ³n miembro se asigna a cada tarea: las funcionesÂ <i>get_metadata( )</i>Â yÂ <i>get_document( )</i>, respectivamente. Ambas se declaranÂ <i>virtual</i>, por lo que la versiÃ³n suministrada por una implementaciÃ³n particular de la clase de base se activa durante la ejecuciÃ³n. Una versiÃ³n heredada de este objeto utiliza GDBM para implementarÂ <i>get_metadata( )</i>Â y MG para implementarÂ <i>get_document( )</i>Â : a continuaciÃ³n explicaremos en detalle esta versiÃ³n.</Text>
+<Text id="883">Las otras funciones miembro que aparecen en la Figura <CrossRef target="Figure" ref="source_base_class_api"/> sonÂ <i>configure( )</i>,Â <i>init( )</i>Â yÂ <i>translate_OID( )</i>. Las dos primeras se relacionan con el proceso de inicializaciÃ³n que se explica en la SecciÃ³n <CrossRef target="Section" ref="initialisation"/>.</Text>
+<Text id="884">La otra,Â <i>translate_OID( )</i>, maneja la sintaxis para expresar los identificadores de documento. En la Figura <CrossRef target="Figure" ref="the_golf_course_mystery"/> vimos que el nÃºmero de una pÃ¡gina podÃ­a anexarse a un identificador de documento para recuperar Ãºnicamente esa pÃ¡gina. Esto era posible porque, al crearse la colecciÃ³n, las pÃ¡ginas se almacenaban como âseccionesâ. Si se agrega â.1â a un OID, se recupera la primera secciÃ³n del documento correspondiente. Las secciones pueden subdividirse y para acceder a ellas es preciso concatenar nÃºmeros de secciones separados por puntos.</Text>
+<Text id="885">AdemÃ¡s de los nÃºmeros jerÃ¡rquicos de secciones, la sintaxis del identificador de documento admite una forma de acceso relativo. En el caso de la secciÃ³n en uso de un documento, se puede acceder alÂ <i>primer hijo</i>Â anexandoÂ <i>.fc (first child)</i>, alÂ <i>Ãºltimo niÃ±o</i>Â anexandoÂ <i>.lc (last child)</i>, alÂ <i>padre</i>Â anexandoÂ <i>.pr (parent)</i>, alÂ <i>hermano</i><i>siguiente</i>Â anexandoÂ <i>.ns</i><i>(next sibling)</i>Â y alÂ <i>hermano anterior</i>Â anexandoÂ <i>.ps (previous sibling)</i>.</Text>
+<Text id="886">La funciÃ³nÂ <i>translate_OID</i>Â utiliza los parÃ¡metrosÂ <i>OIDin</i>Â yÂ <i>OIDout</i>Â para retener la fuente y el resultado de la conversiÃ³n. Incluye otros dos parÃ¡metros:Â <i>err</i>Â yÂ <i>logout</i>. Ãstos comunican cualquier estado de error que se pueda producir durante la operaciÃ³n de traducciÃ³n, y determina dÃ³nde enviar la informaciÃ³n de registro (Â <i>logging information</i>). Como veremos en la SecciÃ³n <CrossRef target="Section" ref="protocol"/>, estos parÃ¡metros dependen estrechamente del protocolo.</Text>
+<Part id="database_retrieval_with_gdbm">
+<Title>
+<Text id="887">RecuperaciÃ³n de base de datos con gdbm</Text>
+</Title>
+<Content>
+<Text id="888">GDBM es el programa de gestiÃ³n de base de datos de GNU (<i>www.gnu.org</i>). Establece una estructura de registros planos de pares clave/datos, y es compatible con versiones anteriores de DBM y NDBM. Las operaciones incluyen el almacenamiento, la recuperaciÃ³n y la supresiÃ³n de registros por clave, y un recorrido no ordenado de todas las claves.</Text>
+<Figure id="gdbm_database_for_the_gutenberg_collection">
+<Title>
+<Text id="889">La base de datos GDBM para la colecciÃ³n Gutenberg (extracto)</Text>
+</Title>
+<CodeLine>[HASH01d7b30d4827b51282919e9b]</CodeLine>
+<CodeLine>&lt;doctype&gt; doc</CodeLine>
+<CodeLine>&lt;hastxt&gt;Â Â Â Â Â Â Â Â Â Â  0</CodeLine>
+<CodeLine>&lt;Title&gt;Â Â Â Â Â Â Â Â Â Â Â  The Winterâs Tale</CodeLine>
+<CodeLine>&lt;Creator&gt; William Shakespeare</CodeLine>
+<CodeLine>&lt;archivedir&gt;Â Â Â Â Â Â  HASH01d7/b30d4827.dir</CodeLine>
+<CodeLine>&lt;thistype&gt; Â Â Â Â Â Â Â  Invisible</CodeLine>
+<CodeLine>&lt;childtype&gt; Â Â Â Â Â Â  Paged</CodeLine>
+<CodeLine>&lt;contains&gt; Â Â Â Â Â Â Â  ".1;".2;".3;".4;".5;".6;".7;".8;".9;".10;".11;".12; \</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  ".13;".14;".15;".16;".17;".18;".19;".20;".21;".22; \</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  ".23;".24;".25;".26;".27;".28;".29;".30;".31;".32; \</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  ".33;".34;".35</CodeLine>
+<CodeLine>&lt;docnum&gt;Â Â Â Â Â Â Â Â Â Â  168483</CodeLine>
+<CodeLine>------------------------</CodeLine>
+<CodeLine>[CL1]</CodeLine>
+<CodeLine>&lt;doctype&gt; classify</CodeLine>
+<CodeLine>&lt;hastxt&gt;Â Â Â Â Â Â Â Â Â Â  0</CodeLine>
+<CodeLine>&lt;childtype&gt;Â Â Â Â Â Â Â  HList</CodeLine>
+<CodeLine>&lt;Title&gt;Â Â Â Â Â Â Â Â Â Â Â  Title</CodeLine>
+<CodeLine>&lt;numleafdocs&gt;Â Â Â Â Â  1818</CodeLine>
+<CodeLine>&lt;thistype&gt;Â Â Â Â Â Â Â Â  Invisible</CodeLine>
+<CodeLine>&lt;contains&gt;Â Â Â Â Â Â Â Â  ".1;".2;".3;".4;".5;".6;".7;".8;".9;".10;".11;".12; \</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  ".13;".14;".15;".16;".17;".18;".19;".20;".21;".22; \</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  ".23;".24</CodeLine>
+<CodeLine>------------------------</CodeLine>
+<CodeLine>[CL1.1]</CodeLine>
+<CodeLine>&lt;doctype&gt; classify</CodeLine>
+<CodeLine>&lt;hastxt&gt;Â Â Â Â Â Â Â Â Â Â  0</CodeLine>
+<CodeLine>&lt;childtype&gt;Â Â Â Â Â Â Â  VList</CodeLine>
+<CodeLine>&lt;Title&gt;Â Â Â Â Â Â Â Â Â Â Â  A</CodeLine>
+<CodeLine>&lt;numleafdocs&gt;Â Â Â Â Â  118</CodeLine>
+<CodeLine>&lt;contains&gt;Â Â Â Â Â Â Â Â  HASH0130bc5f9f90089b3723431f;HASH9cba43bacdab5263c98545;\</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â  Â Â Â Â Â Â Â Â Â HASH12c88a01da6e8379df86a7;HASH9c86579a83e1a2e4cf9736;Â  \</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  HASHdc2951a7ada1f36a6c3aca;HASHea4dda6bbc7cdeb4abfdee;Â  \</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  HASHce55006513c47235ac38ba;HASH012a33acaa077c0e612b9351;\</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  HASH010dd1e923a123826ae30e4b;HASHaf674616785679fed4b7ee;\</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  HASH0147eef4b9d1cb135e096619;HASHe69b9dbaa83ffb045d963b;\</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  HASH01abc61c646c8e7a8ce88b10;HASH5f9cd13678e21820e32f3a;\</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  HASHe8cbba1594c72c98f9aa1b;HASH01292a2b7b6b60dec96298bc;\</CodeLine>
+<CodeLine>...</CodeLine>
+</Figure>
+<Text id="890">En la Figura <CrossRef target="Figure" ref="gdbm_database_for_the_gutenberg_collection"/> se muestra un extracto de la base de datos de informaciones de la colecciÃ³n elaborada durante la creaciÃ³n de la colecciÃ³n Gutenberg. El extracto se obtuvo utilizando la aplicaciÃ³nÂ <i>db2txt</i>Â de Greenstone que convierte el formato binario de base de datos GDBM en forma textual. La Figura <CrossRef target="Figure" ref="gdbm_database_for_the_gutenberg_collection"/> contiene tres registros separados por lÃ­neas horizontales. El primero es una entrada de documento, los otros dos forman parte de la jerarquÃ­a creada por el clasificadorÂ <i>AZList</i>Â para los tÃ­tulos de la colecciÃ³n. La primera lÃ­nea de cada registro es su clave.</Text>
+<Text id="891">El registro del documento guarda el tÃ­tulo del libro, el autor y cualquier otro metadato proporcionado (o extraÃ­do) durante la creaciÃ³n de la colecciÃ³n. Contiene asimismo valores para uso interno: dÃ³nde se encuentran los archivos asociados con ese documento (&lt;Â <i>archivedir</i>Â &gt;) y el nÃºmero de documento utilizado internamente por MG (&lt;Â <i>docnum</i>Â &gt;).</Text>
+<Text id="892">En el campo &lt;Â <i>contains</i>Â &gt; se almacena una lista de elementos, separados por caracteres de punto y coma, que remiten a registros conexos en la base de datos. Para un registro de documento, el campo &lt;Â <i>contains</i>Â &gt; sirve para seÃ±alar las secciones subdivididas. Las subsiguientes claves de registro se forman concatenando la clave en curso con uno de los elementos secundarios (separado por un punto).</Text>
+<Text id="893">El segundo registro de la Figura <CrossRef target="Figure" ref="gdbm_database_for_the_gutenberg_collection"/> es el nodo principal de la jerarquÃ­a de clasificaciÃ³n de tÂ <i>Ã­tulos a-z</i>. Sus elementos secundarios, a los que se accede a travÃ©s del campo &lt;Â <i>contains</i>Â &gt;, incluyenÂ <i>CL1.1</i>,Â <i>CL1.2</i>,Â <i>CL1.3</i>Â y asÃ­ sucesivamente, y corresponden a las distintas pÃ¡ginas para las letrasÂ <i>A</i>,Â <i>B</i>,Â <i>C</i>, etc. Hay Ãºnicamente 24 elementos secundarios: el clasificadorÂ <i>AZList</i>Â fusionÃ³ las letrasÂ <i>Q-R</i>Â eÂ <i>Y-Z</i>Â porque sÃ³lo incluÃ­an unos cuantos tÃ­tulos.</Text>
+<Text id="894">Los elementos secundarios en el campo &lt;Â <i>contains</i>Â &gt; del tercer registro,Â <i>CL1.1</i>, son los documentos propiamente dichos. Es posible establecer estructuras mÃ¡s complicadas: el campo &lt;Â <i>contains</i>Â &gt; puede incluir una combinaciÃ³n de documentos y otros nodosÂ <i>CL</i>. Las claves relacionadas con la clave en curso se distinguen de las claves absolutas porque llevan comillas (â) antepuestas.</Text>
+</Content>
+</Part>
+<Part id="using_mg_and_gdbm_to_implement_a_source_object">
+<Title>
+<Text id="895">El uso de MG y GDBM para implementar un objeto Fuente (Source)</Text>
+</Title>
+<Content>
+<Figure id="api_for_mg_and_gdbm_based_version_of_sourceclass">
+<Title>
+<Text id="896">API de la versiÃ³n deÂ <i>sourceclass</i>Â basada en MG y GDBM (abreviada)</Text>
+</Title>
+<CodeLine>class mggdbmsourceclass : public sourceclass {</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>Â  // Omitted, data fields that store:</CodeLine>
+<CodeLine>Â  // Â Â collection specific file information</CodeLine>
+<CodeLine>Â  // Â Â index substructure</CodeLine>
+<CodeLine>Â  // Â Â information about parent</CodeLine>
+<CodeLine>Â  // Â Â pointers to gdbm and mgsearch objects</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>Â  mggdbmsourceclass ();</CodeLine>
+<CodeLine>Â  virtual ~mggdbmsourceclass ();</CodeLine>
+<CodeLine>Â  void set_gdbmptr (gdbmclass *thegdbmptr);</CodeLine>
+<CodeLine>Â  void set_mgsearchptr (searchclass *themgsearchptr);</CodeLine>
+<CodeLine>Â  void configure (const text_t &amp;key, const text_tarray &amp;cfgline);</CodeLine>
+<CodeLine>Â  bool init (ostream &amp;logout);</CodeLine>
+<CodeLine>Â  bool translate_OID (const text_t &amp;OIDin, text_t &amp;OIDout,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>Â  bool get_metadata (const text_t &amp;requestParams,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  const text_t &amp;refParams,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  bool getParents, const text_tset &amp;fields,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  const text_t &amp;OID, MetadataInfo_tmap &amp;metadata,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>Â  bool get_document (const text_t &amp;OID, text_t &amp;doc,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="897">El objeto que reÃºne MG y GDBM para efectuar una implementaciÃ³n deÂ <i>sourceclass</i>Â se denominaÂ <i>mggdbmsourceclass</i>. En la Figura <CrossRef target="Figure" ref="api_for_mg_and_gdbm_based_version_of_sourceclass"/> se presenta su API. Las dos nuevas funciones miembroÂ <i>set_gdbmptr( )</i>Â yÂ <i>set_mgsearchptr( )</i>Â almacenan punteros dirigidos hacia sus respectivos objetos, de modo que las implementaciones deÂ <i>get_metadata( )</i>Â yÂ <i>get_document( )</i>Â puedan acceder a las herramientas apropiadas para llevar a cabo su tarea.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="the_filter_object">
+<Title>
+<Text id="898">El objeto Filtro (<i>Filter</i>)</Text>
+</Title>
+<Content>
+<Figure id="api_for_the_filter_base_class">
+<Title>
+<Text id="899">API de la clase base de Filtro</Text>
+</Title>
+<CodeLine>class filterclass {</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>Â  text_t gsdlhome;</CodeLine>
+<CodeLine>Â  text_t collection;</CodeLine>
+<CodeLine>Â  text_t collectdir;</CodeLine>
+<CodeLine>Â  FilterOption_tmap filterOptions;</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>Â  filterclass ();</CodeLine>
+<CodeLine>Â  virtual ~filterclass ();</CodeLine>
+<CodeLine>Â  virtual void configure (const text_t &amp;key,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  const text_tarray &amp;cfgline);</CodeLine>
+<CodeLine>Â  virtual bool init (ostream &amp;logout);</CodeLine>
+<CodeLine>Â  // returns the name of this filter</CodeLine>
+<CodeLine>Â  virtual text_t get_filter_name ();</CodeLine>
+<CodeLine>Â  // returns the current filter options</CodeLine>
+<CodeLine>Â  virtual void get_filteroptions</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  (InfoFilterOptionsResponse_t &amp;response, </CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>Â  virtual void filter (const FilterRequest_t &amp;request,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  FilterResponse_t &amp;response,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="900">La API de la clase de base para el objeto Filtro de la Figura <CrossRef target="Figure" ref="greenstone_runtime_system"/> se presenta en la Figura <CrossRef target="Figure" ref="api_for_the_filter_base_class"/>. Empieza con los campos de datos protegidosÂ <i>gsdlhome</i>,Â <i>collection</i>Â yÂ <i>collectdir</i>. Estos suelen emplearse en las clases que necesitan acceder a archivos de colecciones especÃ­ficas:</Text>
+<BulletList>
+<Bullet>
+<Text id="901"><i>gsdlhome</i>Â es lo mismo queÂ <i>GSDLHOME</i>, de modo que el objeto pueda localizar los archivos de Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="902"><i>collection</i>Â es el nombre del directorio que corresponde a la colecciÃ³n</Text>
+</Bullet>
+<Bullet>
+<Text id="903"><i>collectdir</i>Â es el nombre de ruta completo del directorio de la colecciÃ³n (es necesario porque una colecciÃ³n no tiene por quÃ© encontrarse necesariamente en la zonaÂ <i>GSDLHOME</i>).</Text>
+</Bullet>
+</BulletList>
+<Text id="904"><i>mggdbsourceclass</i>Â es otra clase que incluye estos tres campos de datos.</Text>
+<Text id="905">El proceso de inicializaciÃ³n utiliza las funciones miembroÂ <i>configure( )</i>Â eÂ <i>init( )</i>Â (que ya vimos en la funciÃ³nÂ <i>sourceclass</i>). El propio objeto se alinea estrechamente con la porciÃ³n de filtro que le corresponde en el protocolo; las funcionesÂ <i>get_filteroptions( )</i>Â yÂ <i>filter( )</i>, en particular, coinciden exactamente.</Text>
+<Figure id="how_a_filter_option_is_stored">
+<Title>
+<Text id="906">Manera en que se almacena una opciÃ³n de filtro</Text>
+</Title>
+<CodeLine>struct FilterOption_t {</CodeLine>
+<CodeLine>Â  void clear (); \ void check_defaultValue ();</CodeLine>
+<CodeLine>Â  FilterOption_t () {clear();}</CodeLine>
+<CodeLine>Â  text_t name;</CodeLine>
+<CodeLine>Â  enum type_t {booleant=0, integert=1, enumeratedt=2, stringt=3};</CodeLine>
+<CodeLine>Â  type_t type;</CodeLine>
+<CodeLine>Â  enum repeatable_t {onePerQuery=0, onePerTerm=1, nPerTerm=2};</CodeLine>
+<CodeLine>Â  repeatable_t repeatable;</CodeLine>
+<CodeLine>Â  text_t defaultValue; </CodeLine>
+<CodeLine>Â  text_tarray validValues;</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine>struct OptionValue_t {</CodeLine>
+<CodeLine>Â  void clear ();</CodeLine>
+<CodeLine>Â  text_t name;</CodeLine>
+<CodeLine>Â  text_t value;</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="907">Las dos clases que se muestran en la Figura <CrossRef target="Figure" ref="how_a_filter_option_is_stored"/> son fundamentales para las opciones de filtro.Â <i>FilterOption_t</i>Â almacena elÂ <i>nombre (name)</i>Â de la opciÃ³n, suÂ <i>tipo (type)</i>, y si se puede repetir o no (Â <i>repeatable)</i>. La interpretaciÃ³n deÂ <i>validValues</i>Â depende del tipo de opciÃ³n. Para un tipo booleano, el primer valor esÂ <i>false</i>Â y el segundoÂ <i>true</i>. Para un tipo entero, el primer valor es el nÃºmero mÃ­nimo y el segundo el mÃ¡ximo. Para un tipo enumerado todos los valores estÃ¡n en la lista. Para un tipo de cadena se ignora el valor. Para las situaciones mÃ¡s simples, se empleaÂ <i>OptionValue_t</i>Â que registra elÂ <i>nombre</i>Â de la opciÃ³n y suÂ <i>valor</i>Â comoÂ <i>text_t</i>.</Text>
+<Text id="908">Los objetos de bÃºsqueda y de respuesta transmitidos como parÃ¡metros aÂ <i>filterclass</i>Â se crean a partir de estas dos clases, utilizando matrices asociativas para almacenar un conjunto de opciones como las que se requieren paraÂ <i>InfoFilterOptionsResponse_t</i>. Para obtener mÃ¡s detalles vÃ©aseÂ <i>GSDLHOME/src/recpt/comtypes.h</i>.</Text>
+</Content>
+</Subsection>
+<Subsection id="inherited_filter_objects">
+<Title>
+<Text id="909">Objetos Filtro heredados (<i>Inherited Filter</i>)</Text>
+</Title>
+<Content>
+<Figure id="inheritance_hierarchy_for_filter">
+<Title>
+<Text id="910">JerarquÃ­a de herencia para el objeto de filtro</Text>
+</Title>
+<File width="342" height="332" url="images/Dev_Fig_38.png"/>
+</Figure>
+<Text id="911">Tal como se muestra en la Figura <CrossRef target="Figure" ref="inheritance_hierarchy_for_filter"/>, los filtros utilizan dos niveles de herencia. En primer lugar, se establece una distinciÃ³n entre filtros de bÃºsqueda y consulta, y luego para los primeros se procede a una implementaciÃ³n especÃ­fica basada en MG. Para que funcione correctamente,Â <i>mgqueryfilterclass</i>Â necesita acceder a MG a travÃ©s deÂ <i>mgsearchclass</i>Â y a GDBM a travÃ©s deÂ <i>gdbmclass</i>.Â <i>browsefilterclass</i>Â sÃ³lo necesita tener acceso a GDBM. Los punteros de estos objetos se guardan como campos de datos protegidos dentro de las respectivas clases.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_collection_server_code">
+<Title>
+<Text id="912">El cÃ³digo del servidor de colecciÃ³n</Text>
+</Title>
+<Content>
+<Text id="913">A continuaciÃ³n presentamos los archivos de encabezado del directorioÂ <i>GSDLHOME/src/colservr</i>. El nombre del archivo coincide por lo general con el nombre del objeto que define. </Text>
+<Table class="hidden">
+<Title/>
+<TableContent>
+<tr>
+<th width="120">
+<Text id="914"><b>browsefilter.h</b></Text>
+</th>
+<th width="420">
+<Text id="915">Heredado deÂ <i>filterclass</i>, este objeto proporciona acceso a GDBM (se explica mÃ¡s arriba).</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="916"><b>collectserver.h</b></Text>
+</th>
+<th width="420">
+<Text id="917">Este objeto enlaza los objetos Filtro y de Fuente de una colecciÃ³n a fin de formar el objeto ColecciÃ³n representado en la Figura <CrossRef target="Figure" ref="greenstone_runtime_system"/>.</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="918"><b>colservrconfig.h</b></Text>
+</th>
+<th width="420">
+<Text id="919">FunciÃ³n de apoyo para la lectura de los archivos especÃ­ficos de una colecciÃ³nÂ <i>etc/collect.cfg</i>Â eÂ <i>index/build.cfg</i>. El primero es el archivo de configuraciÃ³n de la colecciÃ³n y el segundo es un archivo generado por el proceso de creaciÃ³n que registra la hora de la Ãºltima creaciÃ³n llevada satisfactoriamente a cabo, una lista de las correspondencias de Ã­ndice, el nÃºmero de documentos indizados y su tamaÃ±o en bytes (sin comprimir).</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="920"><b>filter.h</b></Text>
+</th>
+<th width="420">
+<Text id="921">La clase de base del objeto de filtroÂ <i>filterclass</i>Â antes mencionado.</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="922"><b>maptools.h</b></Text>
+</th>
+<th width="420">
+<Text id="923">Define una clase llamadaÂ <i>stringmap</i>Â que proporciona una correspondencia que recuerda el orden original de una correspondenciaÂ <i>text_t</i>, pero cuya consulta es rÃ¡pida. Se utiliza enÂ <i>mggdbmsourceclass</i>Â yÂ <i>queryfilterclass</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="924"><b>mggdbmsource.h</b></Text>
+</th>
+<th width="420">
+<Text id="925">Heredado deÂ <i>sourceclass</i>, este objeto proporciona acceso a MG y GDBM (se explica mÃ¡s arriba).</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="926"><b>mgppqueryfilter.h</b></Text>
+</th>
+<th width="420">
+<Text id="927">Heredado deÂ <i>queryfilterclass</i>, este objeto proporciona una implementaciÃ³n deÂ <i>QueryFilter</i>Â basada en MG++, una versiÃ³n mejorada de MG escrita en C++. ObsÃ©rvese que Greenstone estÃ¡ configurado para utilizar MG por defecto, ya que MG++ se encuentra todavÃ­a en fase de desarollo.</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="928"><b>mgppsearch.h</b></Text>
+</th>
+<th width="420">
+<Text id="929">Heredado deÂ <i>searchclass</i>, este objeto proporciona une implementaciÃ³n del objeto BÃºsqueda utilizando MG++. ComoÂ <i>mgppqueryfilterclass</i>, tampoco se utiliza por defecto.</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="930"><b>mgq.h</b></Text>
+</th>
+<th width="420">
+<Text id="931">Interfaz funcional para el paquete MG. Sus principales funciones sonÂ <i>mg_ask( )</i>Â yÂ <i>mg_results( )</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="932"><b>mgqueryfilter.h</b></Text>
+</th>
+<th width="420">
+<Text id="933">Heredado deÂ <i>queryfilterclass</i>, este objeto proporciona una implementaciÃ³n deÂ <i>QueryFilter</i>Â basada en MG.</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="934"><b>mgsearch.h</b></Text>
+</th>
+<th width="420">
+<Text id="935">Heredado deÂ <i>searchclass</i>, este objeto proporciona una implementaciÃ³n de SearchÂ <i/>Â (bÃºsqueda) utilizando MG (se explica mÃ¡s arriba).</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="936"><b>phrasequeryfilter.h</b></Text>
+</th>
+<th width="420">
+<Text id="937">Heredado deÂ <i>mgqueryclass</i>, este objeto proporciona una clase de consulta basada en frases. No se utiliza en la instalaciÃ³n por defecto. En su lugarÂ <i>mgqueryfilterclass</i>Â ofrece esta posibilidad a travÃ©s del apoyo funcional deÂ <i>phrasesearch.h</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="938"><b>phrasesearch.h</b></Text>
+</th>
+<th width="420">
+<Text id="939">FunciÃ³n de apoyo para efectuar una bÃºsqueda de grupos de palabras como operaciÃ³n posterior al tratamiento.</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="940"><b>querycache.h</b></Text>
+</th>
+<th width="420">
+<Text id="941">Utilizado porÂ <i>searchclass</i>Â y sus clases heredadas para almacenar en el campo cachÃ© los resultados de una consulta, a fin de que la generaciÃ³n de las pÃ¡ginas resultantes de bÃºsquedas posteriores resulte mÃ¡s eficaz (se explica mÃ¡s arriba).</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="942"><b>queryfilter.h</b></Text>
+</th>
+<th width="420">
+<Text id="943">Heredado de la clase base de filtroÂ <i>filterclass</i>, este objeto establece una clase base para los objetos Filtro y BÃºsqueda (se explica mÃ¡s arriba).</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="944"><b>queryinfo.h</b></Text>
+</th>
+<th width="420">
+<Text id="945">Ayuda para la bÃºsqueda: estructuras de datos y objetos para guardar los parÃ¡metros de consulta, los resultados de documentos y las frecuencias de tÃ©rminos.</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="946"><b>search.h</b></Text>
+</th>
+<th width="420">
+<Text id="947">La clase de base del objeto BÃºsquedaÂ <i>searchclass</i>Â (se explica mÃ¡s arriba).</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="948"><b>source.h</b></Text>
+</th>
+<th width="420">
+<Text id="949">La clase de base del objeto FuenteÂ <i>sourceclass</i>Â (se explica mÃ¡s arriba).</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="protocol">
+<Title>
+<Text id="950">Protocolo</Text>
+</Title>
+<Content>
+<Table id="list_of_protocol_calls">
+<Title>
+<Text id="951">Lista de llamadas del protocolo</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="952"><i>get_protocol_name( )</i></Text>
+</th>
+<th width="397">
+<Text id="953">Devuelve el nombre de este protocolo. Las opciones incluyenÂ <i>nullproto</i>,Â <i>corbaproto</i>Â yÂ <i>z3950proto</i>. Utilizado por las partes del sistema de ejecuciÃ³n que dependen del protocolo para decidir quÃ© cÃ³digo ejecutar.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="954"><i>get_collection_list( )</i></Text>
+</th>
+<th width="397">
+<Text id="955">Devuelve la lista de colecciones que este protocolo conoce.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="956"><i>has_collection( )</i></Text>
+</th>
+<th width="397">
+<Text id="957">Devuelve el valorÂ <i>true</i>Â (Â <i>verdadero)</i>Â si el protocolo puede comunicar con la colecciÃ³n nombrada, es decir, si se encuentra en su lista de colecciones.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="958"><i>ping( )</i></Text>
+</th>
+<th width="397">
+<Text id="959">ReenvÃ­a el valorÂ <i>true (verdadero)</i>Â si se ha logrado establecer una conexiÃ³n con la colecciÃ³n nombrada. En el caso del protocolo nulo, la implementaciÃ³n es idÃ©ntica a la deÂ <i>has_collection( )</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="960"><i>get_collectinfo( )</i></Text>
+</th>
+<th width="397">
+<Text id="961">Obtiene informaciÃ³n general sobre la colecciÃ³n nombrada: fecha de la Ãºltima creaciÃ³n, nÃºmero de documentos que contiene, etc. Incluye tambiÃ©n metadatos del archivo de configuraciÃ³n de la colecciÃ³n: texto de âAcerca de esta colecciÃ³nâ, el icono de la colecciÃ³n que ha de utilizarse, etc.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="962"><i>get_filterinfo( )</i></Text>
+</th>
+<th width="397">
+<Text id="963">Obtiene una lista de todos los objetos Filtro para la colecciÃ³n nombrada.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="964"><i>get_filteroptions( )</i></Text>
+</th>
+<th width="397">
+<Text id="965">Obtiene todas las opciones para un objeto Filtro particular en la colecciÃ³n nombrada.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="966"><i>filter( )</i></Text>
+</th>
+<th width="397">
+<Text id="967">Permite la bÃºsqueda y la consulta. Para un tipo de filtro determinado y unas configuraciones de opciones, accede al contenido de las colecciones nombradas para producir un conjunto de resultados que es filtrado segÃºn las configuraciones de opciones. Los campos de datos devueltos dependen tambiÃ©n de las configuraciones de opciones, por ejemplo: la frecuencia de los tÃ©rminos de consulta y los metadatos de documento.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="968"><i>get_document( )</i></Text>
+</th>
+<th width="397">
+<Text id="969">Obtiene un documento o secciÃ³n de un documento.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="970">En el Cuadro <CrossRef target="Table" ref="list_of_protocol_calls"/> se presenta una lista de las llamadas de funciÃ³n al protocolo, y un resumen de cada una de ellas. Los ejemplos de la SecciÃ³n <CrossRef target="Section" ref="how_the_conceptual_framework_fits_together"/> ilustran la mayorÃ­a de esas llamadas. Las funciones no mencionadas anteriormente sonÂ <i>has_collection( )</i>,Â <i>ping( )</i>,Â <i>get_protocol_name( )</i>Â yÂ <i>get_filteroptions( )</i>. Las dos primeras responden afirmativa o negativamente a las preguntas âÂ¿existe la colecciÃ³n en este servidor?â y âÂ¿se encuentra en funcionamiento?â, respectivamente. La finalidad de las otras dos es admitir protocolos mÃºltiples en una arquitectura repartida en diferentes computadoras, y no sÃ³lo el ejecutable individual basado en el protocolo nulo que se menciona aquÃ­. Una de ellas detecta quÃ© protocolo se encuentra en uso. La otra permite que un recepcionista consulte al servidor de una colecciÃ³n para averiguar quÃ© opciones admite, a fin de configurarse dinÃ¡micamente y sacar el mÃ¡ximo provecho de los servicios ofrecidos por un servidor particular.</Text>
+<Figure id="null_protocol_api">
+<Title>
+<Text id="971">API del protocolo nulo (abreviado)</Text>
+</Title>
+<CodeLine>class nullproto : public recptproto {</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>Â  virtual text_t get_protocol_name ();</CodeLine>
+<CodeLine>Â  virtual void get_collection_list (text_tarray &amp;collist,</CodeLine>
+<CodeLine>Â Â  Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>Â  virtual void has_collection (const text_t &amp;collection,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  bool &amp;hascollection,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>Â  virtual void ping (const text_t &amp;collection,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  bool &amp;wassuccess,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>Â  virtual void get_collectinfo (const text_t &amp;collection,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  ColInfoResponse_t &amp;collectinfo, </CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>virtual void get_filterinfo (const text_t &amp;collection,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  InfoFiltersResponse_t &amp;response,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>virtual void get_filteroptions (const text_t &amp;collection,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  const InfoFilterOptionsRequest_t &amp;request,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  InfoFilterOptionsResponse_t &amp;response,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>Â  virtual void filter (const text_t &amp;collection,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â  Â Â Â Â Â Â Â Â Â Â FilterRequest_t &amp;request,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  FilterResponse_t &amp;response,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>Â Â virtual void get_document (const text_t &amp;collection,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  const DocumentRequest_t &amp;request,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  DocumentResponse_t &amp;response,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="972">En la Figura <CrossRef target="Figure" ref="null_protocol_api"/> se muestra la API para el protocolo nulo. Se han omitido los comentarios y determinados detalles de nivel inferior (vÃ©ase el archivo fuenteÂ <i>recpt/nullproto.h</i>Â para obtener mÃ¡s informaciÃ³n al respecto).</Text>
+<Text id="973">Este protocolo hereda de la clase de baseÂ <i>recptproto</i>. Se utiliza la herencia virtual a fin de poder admitir fÃ¡cilmente mÃ¡s de un tipo de protocolo âincluso protocolos aÃºn no concebidosâ en el resto del cÃ³digo fuente. Ello es posible porque el objeto de clase de baseÂ <i>recptproto</i>Â se utiliza a lo largo de todo el cÃ³digo fuente, excepto en el punto de creaciÃ³n, donde especificamos la variedad concreta de protocolo que deseamos utilizar que, en este caso, es el protocolo nulo.</Text>
+<Text id="974">Con la excepciÃ³n deÂ <i>get_protocol_name( )</i>, que no toma parÃ¡metros y devuelve el nombre del protocolo como una cadena de texto codificada en Unicode, todas las funciones de protocolo incluyen un parÃ¡metro de error y un flujo de salida como argumentos finales. El parÃ¡metro de error registra cualquier error que se produce durante la ejecuciÃ³n de la llamada de protocolo y la secuencia de salida se utiliza a efectos de registro (Â <i>logging</i>). Las funciones son del tipoÂ <i>void</i>, esto es, no reenvÃ­an explÃ­citamente la informaciÃ³n en su instrucciÃ³n final, sino que reenvÃ­an datos a travÃ©s de parÃ¡metros designados como el parÃ¡metro de error antes mencionado. En algunos lenguajes de programaciÃ³n, estos subprogramas se definirÃ­an como âprocedimientosâ en vez de âfuncionesâ, pero C++ no establece ninguna distinciÃ³n sintÃ¡ctica.</Text>
+<Text id="975">La mayorÃ­a de las funciones toman el nombre de la colecciÃ³n como argumento. Tres de las funciones miembro,Â <i>get_filteroptions( )</i>,Â <i>filter( )</i>Â yÂ <i>get_document( )</i>Â siguen el esquema de proporcionar un parÃ¡metro de consulta y de recibir los resultados en un parÃ¡metro de respuesta Response.</Text>
+</Content>
+</Section>
+<Section id="receptionist">
+<Title>
+<Text id="976">El recepcionista</Text>
+</Title>
+<Content>
+<Text id="977">La capa final del modelo conceptual es el recepcionista. Una vez analizados los argumentos CGI, la actividad principal es la ejecuciÃ³n de una acciÃ³n con la asistencia de los objetos Formato y Lenguaje de macros, que se explican mÃ¡s adelante. Aunque se representen como objetos en el marco conceptual, los objetos Formato y Lenguaje de macros no son estrictamente objetos en el sentido de C++. En realidad, el objeto de formato es una colecciÃ³n de estructuras de datos con un conjunto de funciones que operan en aquÃ©llas, y el objeto de lenguaje de macros se crea en torno aÂ <i>displayclass</i>, definido enÂ <i>lib/display.h</i>Â con un apoyo de conversiÃ³n de flujo procedente deÂ <i>lib/gsdlunicode.h</i>.</Text>
+<Subsection id="actions">
+<Title>
+<Text id="978">Acciones</Text>
+</Title>
+<Content>
+<Table id="actions_in_greenstone">
+<Title>
+<Text id="979">Las acciones en Greenstone</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="980"><i>action</i></Text>
+</th>
+<th width="397">
+<Text id="981">Clase base para la herencia virtual.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="982"><i>authenaction</i></Text>
+</th>
+<th width="397">
+<Text id="983">Presta ayuda a la autenticaciÃ³n del usuario: pide al usuario una contraseÃ±a si no se ha introducido ninguna, comprueba su validez y obliga al usuario a introducir la contraseÃ±a de nuevo si transcurre demasiado tiempo entre dos accesos.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="984"><i>collectoraction</i></Text>
+</th>
+<th width="397">
+<Text id="985">Genera las pÃ¡ginas para el Colector.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="986"><i>documentaction</i></Text>
+</th>
+<th width="397">
+<Text id="987">Recupera documentos, secciones de documentos, porciones de la jerarquÃ­a de clasificaciÃ³n o informaciÃ³n sobre formatos.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="988"><i>extlinkaction</i></Text>
+</th>
+<th width="397">
+<Text id="989">Lleva un usuario directamente a una direcciÃ³n URL que es externa a la colecciÃ³n, generando eventualmente antes una pÃ¡gina de alerta (segÃºn lasÂ <i>preferencias</i>).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="990"><i>pageaction</i></Text>
+</th>
+<th width="397">
+<Text id="991">Genera una pÃ¡gina en conjunciÃ³n con el lenguaje de macros.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="992"><i>pingaction</i></Text>
+</th>
+<th width="397">
+<Text id="993">Comprueba si una colecciÃ³n estÃ¡ en lÃ­nea.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="994"><i>queryaction</i></Text>
+</th>
+<th width="397">
+<Text id="995">EfectÃºa una bÃºsqueda.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="996"><i>statusaction</i></Text>
+</th>
+<th width="397">
+<Text id="997">Genera las pÃ¡ginas de administraciÃ³n.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="998"><i>tipaction</i></Text>
+</th>
+<th width="397">
+<Text id="999">Facilita de forma aleatoria una sugerencia al usuario.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1000"><i>usersaction</i></Text>
+</th>
+<th width="397">
+<Text id="1001">Administra la adiciÃ³n, la supresiÃ³n y la gestiÃ³n de los accesos de usuario.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="1002">Greenstone admite las once acciones que se resumen en el Cuadro <CrossRef target="Table" ref="actions_in_greenstone"/>.</Text>
+<Figure id="using_the_cgiargsinfoclass_from_pageactioncpp" class="withLineNumber">
+<Title>
+<Text id="1003">UtilizaciÃ³n deÂ <i>cgiargsinfoclass</i>Â desdeÂ <i>pageaction.cpp</i></Text>
+</Title>
+<CodeLine>cgiarginfo arg_ainfo;</CodeLine>
+<CodeLine>arg_ainfo.shortname = "a";</CodeLine>
+<CodeLine>arg_ainfo.longname = "action";</CodeLine>
+<CodeLine>arg_ainfo.multiplechar = true;</CodeLine>
+<CodeLine>arg_ainfo.argdefault = "p";</CodeLine>
+<CodeLine>arg_ainfo.defaultstatus = cgiarginfo::weak;</CodeLine>
+<CodeLine>arg_ainfo.savedarginfo = cgiarginfo::must;</CodeLine>
+<CodeLine>argsinfo.addarginfo (NULL, arg_ainfo);</CodeLine>
+<CodeLine/>
+<CodeLine>arg_ainfo.shortname = "p";</CodeLine>
+<CodeLine>arg_ainfo.longname = "page";</CodeLine>
+<CodeLine>arg_ainfo.multiplechar = true;</CodeLine>
+<CodeLine>arg_ainfo.argdefault = "home";</CodeLine>
+<CodeLine>arg_ainfo.defaultstatus = cgiarginfo::weak;</CodeLine>
+<CodeLine>arg_ainfo.savedarginfo = cgiarginfo::must;</CodeLine>
+<CodeLine>argsinfo.addarginfo (NULL, arg_ainfo);</CodeLine>
+</Figure>
+<Text id="1004">Los argumentos CGI necesarios para una acciÃ³n se declaran formalmente en la funciÃ³n constructora utilizandoÂ <i>cgiarginfo</i>Â (definida enÂ <i>recpt/cgiargs.h</i>). En la Figura <CrossRef target="Figure" ref="using_the_cgiargsinfoclass_from_pageactioncpp"/> se muestra un extracto de la funciÃ³n constructoraÂ <i>pageaction</i>, que define el tamaÃ±o y las propiedades de los argumentos CGIÂ <i>a</i>Â yÂ <i>p</i>.</Text>
+<Text id="1005">Para cada argumento CGI, el constructor debe especificar su nombre corto (lÃ­neas 2 y 10), que es el nombre de la variable CGI propiamente dicha; un nombre largo (lÃ­neas 3 y 11) que se utiliza para proporcionar una descripciÃ³n mÃ¡s elocuente de la acciÃ³n; si representa un valor de carÃ¡cter simple o mÃºltiple (lÃ­neas 4 y 12); un posible valor por defecto (lÃ­neas 5 y 13); lo que ocurre cuando se proporcionan varios valores por defecto (lÃ­neas 6 y 14) (ya que pueden introducirse valores por defecto en los archivos de configuraciÃ³n); y si es preciso preservar o no el valor al final de esta acciÃ³n (lÃ­neas 7 y 15).</Text>
+<Text id="1006">Puesto que estÃ¡ integrada en el cÃ³digo, se pueden generar automÃ¡ticamente pÃ¡ginas Web que detallan esta informaciÃ³n. La acciÃ³nÂ <i>statusaction</i>Â produce esta informaciÃ³n, que puede visualizarse introduciendo la direcciÃ³n URL de la pÃ¡gina de administraciÃ³n de Greenstone.</Text>
+<Text id="1007">Las doce acciones heredadas se construyen enÂ <i>main( )</i>, la funciÃ³n de alto nivel del ejecutableÂ <i>library</i>, cuya definiciÃ³n figura en el archivoÂ <i>recpt/librarymain.cpp</i>. Es aquÃ­ tambiÃ©n donde se forma el objeto Recepcionista (definido enÂ <i>recpt/receptionist.cpp</i>). La responsabilidad de todas las acciones recae en el objeto de recepcionista, que las trata manteniendo, como un campo de datos, una matriz asociativa de la clase base AcciÃ³n, indizada por nombres de acciÃ³n.</Text>
+<Figure id="action_base_class_api">
+<Title>
+<Text id="1008">API de la clase base AcciÃ³n</Text>
+</Title>
+<CodeLine>class action {</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>Â  cgiargsinfoclass argsinfo;</CodeLine>
+<CodeLine>Â  text_t gsdlhome;</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>Â  action ();</CodeLine>
+<CodeLine>Â  virtual ~action ();</CodeLine>
+<CodeLine>Â  virtual void configure (const text_t &amp;key,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  const text_tarray &amp;cfgline);</CodeLine>
+<CodeLine>Â  virtual bool init (ostream &amp;logout);</CodeLine>
+<CodeLine>Â  virtual text_t get_action_name ();</CodeLine>
+<CodeLine>Â  cgiargsinfoclass getargsinfo ();</CodeLine>
+<CodeLine>Â  virtual bool check_cgiargs (cgiargsinfoclass &amp;argsinfo,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  cgiargsclass &amp;args,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  ostream &amp;logout);</CodeLine>
+<CodeLine>virtual bool check_external_cgiargs (cgiargsinfoclass &amp;argsinfo,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  cgiargsclass &amp;args,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  outconvertclass &amp;outconvert,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  const text_t &amp;saveconf,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  ostream &amp;logout); </CodeLine>
+<CodeLine>virtual void get_cgihead_info (cgiargsclass &amp;args,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  recptprotolistclass *protos,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  response_t &amp;response,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  text_t &amp;response_data,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  ostream &amp;logout);</CodeLine>
+<CodeLine>virtual bool uses_display (cgiargsclass &amp;args);</CodeLine>
+<CodeLine>virtual void define_internal_macros (displayclass &amp;disp,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  cgiargsclass &amp;args,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  recptprotolistclass *protos,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  ostream &amp;logout);</CodeLine>
+<CodeLine>virtual void define_external_macros (displayclass &amp;disp,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  cgiargsclass &amp;args,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  recptprotolistclass *protos,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  ostream &amp;logout);</CodeLine>
+<CodeLine>virtual bool do_action (cgiargsclass &amp;args,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  recptprotolistclass *protos,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  browsermapclass *browsers,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  displayclass &amp;disp,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  outconvertclass &amp;outconvert,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  ostream &amp;textout,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  ostream &amp;logout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="1009">En la Figura <CrossRef target="Figure" ref="action_base_class_api"/> se muestra la API de la clase base AcciÃ³n. Cuando se ejecuta una acciÃ³n, el objeto Recepcionista activa diversas funciones, empezando porÂ <i>check_cgiarsgs( )</i>. La mayorÃ­a de estas funciones contribuyen a verificar, configurar y definir valores y macros, mientras queÂ <i>do_action( )</i>Â genera efectivamente la pÃ¡gina resultante. Si un objeto heredado particular no dispone de una definiciÃ³n para una funciÃ³n miembro determinada, pasa a la definiciÃ³n de la clase base que implementa un comportamiento por defecto apropiado.</Text>
+<Text id="1010">La explicaciÃ³n de las funciones miembro es la siguiente:</Text>
+<BulletList>
+<Bullet>
+<Text id="1011"><i>get_action_name( )</i>Â devuelve el valor del argumento CGIÂ <i>a</i>Â que especifica esta acciÃ³n. El nombre deberÃ­a ser corto pero puede incluir mÃ¡s de un carÃ¡cter.</Text>
+</Bullet>
+<Bullet>
+<Text id="1012"><i>check_cgiargs( )</i>Â es llamada antes queÂ <i>get_cgihead_info( )</i>,Â <i>define_external_macros( )</i>Â yÂ <i>do_action( )</i>. En caso de error aparece un mensaje escrito enÂ <i>logout</i>Â ; si el error es importante, la funciÃ³n devuelve el valorÂ <i>false</i>Â (falso) y no genera ningÃºn contenido de pÃ¡gina.</Text>
+</Bullet>
+<Bullet>
+<Text id="1013"><i>check_external_cgiargs( )</i>Â se activa despuÃ©s deÂ <i>check_cgiargs( )</i>Â para todas las acciones. Su uso se limita a invalidar otros comportamientos por defecto, como por ejemplo, mostrar una pÃ¡gina de conexiÃ³n cuando la pÃ¡gina solicitada requiere una autenticaciÃ³n.</Text>
+</Bullet>
+<Bullet>
+<Text id="1014"><i>get_cgihead_info( )</i>Â establece la informaciÃ³n del encabezado CGI. SiÂ <i>response</i>Â tiene el valor deÂ <i>location</i>, entoncesÂ <i>response_data</i>Â contiene la direcciÃ³n de redirecciÃ³n. SiÂ <i>response</i>Â equivale aÂ <i>content</i>, entoncesÂ <i>response_data</i>Â contiene el tipo de contenido.</Text>
+</Bullet>
+<Bullet>
+<Text id="1015"><i>uses_display( )</i>Â devuelveÂ <i>true</i>Â (Â <i>verdadero)</i>Â si se necesitaÂ <i>displayclass</i>Â para mostrar el contenido de la pÃ¡gina (comportamiento por defecto).</Text>
+</Bullet>
+<Bullet>
+<Text id="1016"><i>define_internal_macros( )</i>Â define todas las macros relacionadas con las pÃ¡ginas generadas por esta acciÃ³n.</Text>
+</Bullet>
+<Bullet>
+<Text id="1017"><i>define_external_macros( )</i>Â define todas las macros que podrÃ­an ser utilizadas por otras acciones para producir pÃ¡ginas.</Text>
+</Bullet>
+<Bullet>
+<Text id="1018"><i>do_action( )</i>Â genera la pÃ¡gina resultante, normalmente en un flujo a travÃ©s del objeto Lenguaje de macrosÂ <i>display</i>Â y el objeto de conversiÃ³n de salidaÂ <i>textout</i>. ReenvÃ­a el valorÂ <i>false</i>Â si un error ha impedido que la acciÃ³n produzca un resultado.</Text>
+</Bullet>
+</BulletList>
+<Text id="1019">Situado en el principio de la definiciÃ³n de clase,Â <i>argsinfo</i>Â es el campo de datos protegidos (utilizado en el extracto de cÃ³digo que se muestra en la Figura <CrossRef target="Figure" ref="using_the_cgiargsinfoclass_from_pageactioncpp"/>) que almacena la informaciÃ³n de argumento CGI especificada en una funciÃ³n constructora de acciÃ³n heredada. El otro campo de datos,Â <i>gsdlhome</i>, registraÂ <i>GSDLHOME</i>Â para facilitar el acceso<FootnoteRef id="3"/>. El objeto incluye asimismo las funcionesÂ <i>configure( )</i>Â eÂ <i>init( )</i>Â a efectos de inicializaciÃ³n.</Text>
+</Content>
+</Subsection>
+<Subsection id="formatting">
+<Title>
+<Text id="1020">Formateo</Text>
+</Title>
+<Content>
+<Figure id="core_data_structures_in_format">
+<Title>
+<Text id="1021">Estructuras de datos centrales de la clase Formato</Text>
+</Title>
+<CodeLine>enum command_t {comIf, comOr, comMeta, comText, comLink, comEndLink,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  comNum, comIcon, comDoc,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  comHighlight, comEndHighlight};</CodeLine>
+<CodeLine>enum pcommand_t {pNone, pImmediate, pTop, pAll};</CodeLine>
+<CodeLine>enum dcommand_t {dMeta, dText};</CodeLine>
+<CodeLine>enum mcommand_t {mNone, mCgiSafe};</CodeLine>
+<CodeLine>struct metadata_t {</CodeLine>
+<CodeLine>Â  void clear();</CodeLine>
+<CodeLine>Â  metadata_t () {clear();}</CodeLine>
+<CodeLine>Â  text_t metaname;</CodeLine>
+<CodeLine>Â  mcommand_t metacommand;</CodeLine>
+<CodeLine>Â  pcommand_t parentcommand;</CodeLine>
+<CodeLine>Â  text_t parentoptions;</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine>// The decision component of an {If}{decision,true-text,false-text}</CodeLine>
+<CodeLine>// formatstring. The decision can be based on metadata or on text;</CodeLine>
+<CodeLine>// normally that text would be a macro like</CodeLine>
+<CodeLine>// _cgiargmode_.</CodeLine>
+<CodeLine>struct decision_t {</CodeLine>
+<CodeLine>Â  void clear();</CodeLine>
+<CodeLine>Â  decision_t () {clear();}</CodeLine>
+<CodeLine>Â  dcommand_t command;</CodeLine>
+<CodeLine>Â  metadata_t meta;</CodeLine>
+<CodeLine>Â  text_t text;</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine>struct format_t {</CodeLine>
+<CodeLine>Â  void clear();</CodeLine>
+<CodeLine>Â  format_t () {clear();}</CodeLine>
+<CodeLine>Â  command_t command;</CodeLine>
+<CodeLine>Â  decision_t decision;</CodeLine>
+<CodeLine>Â  text_t text;</CodeLine>
+<CodeLine>Â  metadata_t meta;</CodeLine>
+<CodeLine>Â  format_t *nextptr;</CodeLine>
+<CodeLine>Â  format_t *ifptr;</CodeLine>
+<CodeLine>Â  format_t *elseptr;</CodeLine>
+<CodeLine>Â  format_t *orptr;</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="1022">Aunque en la Figura <CrossRef target="Figure" ref="greenstone_runtime_system"/> el formateo se representa como una entidad Ãºnica, en realidad estÃ¡ constituida por un conjunto de estructuras de datos y funciones, que se encuentran en el archivo de encabezadoÂ <i>recpt/formattools.h</i>. Las estructuras de datos centrales aparecen en la Figura <CrossRef target="Figure" ref="core_data_structures_in_format"/>.</Text>
+<Figure id="data_structures_built_for_sample_format_statement">
+<Title>
+<Text id="1023">Estructuras de datos creadas para el ejemplo de instrucciÃ³n de formato</Text>
+</Title>
+<File width="605" height="187" url="images/Dev_Fig_43.png"/>
+</Figure>
+<Text id="1024">Es mÃ¡s fÃ¡cil explicar la implementaciÃ³n con un ejemplo. Cuando la instrucciÃ³n de formato:</Text>
+<CodeLine>Â Â Â Â Â Â  Format CL1Vlist</CodeLine>
+<Text id="1025" type="code">â[link][Title]{If}{[Creator], por [Creator]}[/link]}â</Text>
+<Text id="1026">es leÃ­da desde un archivo de configuraciÃ³n de colecciÃ³n, las funciones deÂ <i>formattools.cpp</i>Â la analizan y se forma la estructura de datos interconectados que se muestra en la Figura <CrossRef target="Figure" ref="data_structures_built_for_sample_format_statement"/>. Cuando es necesario que una acciÃ³n evalÃºe la instrucciÃ³n de formato, se recorre la estructura de datos. La ruta que se toma a nivel de los nodosÂ <i>comIf</i>Â yÂ <i>comOr</i>Â depende de los metadatos devueltos por una llamada al protocolo.</Text>
+<Text id="1027">Al recuperar los metadatos, puede ocurrir que el resultado contenga otras macros y sintaxis de formato. Esto se resuelve avanzando y retrocediendo entre el anÃ¡lisis y la evaluaciÃ³n, segÃºn convenga.</Text>
+</Content>
+</Subsection>
+<Subsection id="macro_language">
+<Title>
+<Text id="1028">El lenguaje de macros</Text>
+</Title>
+<Content>
+<Text id="1029">La entidad de Lenguaje de macros de la Figura <CrossRef target="Figure" ref="greenstone_runtime_system"/>, al igual que la de Formato, no corresponde a una Ãºnica clase C++. En este caso existe una clase principal, pero la implementaciÃ³n del lenguaje de macros depende tambiÃ©n de funciones y clases de apoyo.</Text>
+<Text id="1030">La mejor manera de explicarlo es, una vez mÃ¡s, mediante un ejemplo. En primer lugar presentaremos unos ejemplos de definiciones de macros que ilustran las prioridades de las macros, luego, mediante un diagrama, describiremos las estructuras de datos principales creadas para apoyar esta actividad. Por Ãºltimo, presentaremos y explicaremos las funciones miembro pÃºblicas deÂ <i>displayclass</i>, el objeto de macro de primer nivel.</Text>
+<Figure id="illustration_of_macro_precedence">
+<Title>
+<Text id="1031">IlustraciÃ³n de la prioridad entre las macros</Text>
+</Title>
+<CodeLine>package query</CodeLine>
+<CodeLine>_header_ [] Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  {_querytitle_}</CodeLine>
+<CodeLine>_header_ [l=en] Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  {Search page}</CodeLine>
+<CodeLine>_header_ [c=demo] Â Â Â Â Â Â Â Â Â  {&lt;table</CodeLine>
+<CodeLine>bgcolor=green&gt;&lt;tr&gt;&lt;td&gt;_querytitle_&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;}</CodeLine>
+<CodeLine>_header_ [v=1] Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  {_textquery_}</CodeLine>
+<CodeLine>_header_ [l=fr,v=1,c=hdl] Â  {HDL Page de recherche}</CodeLine>
+</Figure>
+<Text id="1032">En una colecciÃ³n Greenstone clÃ¡sica, la prioridad entre las macros es normalmente:Â <i>c</i>Â (para la colecciÃ³n) tiene prioridad sobreÂ <i>v</i>Â (para la interfaz grÃ¡fica o textual), que tiene prioridad sobreÂ <i>l</i>Â (para el idioma). Esto se establece con la lÃ­nea:</Text>
+<CodeLine>macroprecedence c, v, l</CodeLine>
+<Text id="1033">en el archivo de configuraciÃ³n principalÂ <i>main.cfg</i>. Las instrucciones de macros de la Figura <CrossRef target="Figure" ref="illustration_of_macro_precedence"/> definen ejemplos de macros para _Â <i>header</i>Â _ en el paqueteÂ <i>query</i>Â para distintos valores deÂ <i>c</i>,Â <i>v</i>Â yÂ <i>l</i>. Si los argumentos CGI proporcionados cuando se solicita una acciÃ³n incluyenÂ <i>c=hdl</i>,Â <i>v=1</i>Â yÂ <i>l=en</i>, se seleccionarÃ­a entonces la presentaciÃ³n de la macro _Â <i>header</i>Â _Â <i>[v=1]</i>. Se seleccionarÃ­a antes que _Â <i>content</i>Â _Â <i>[l=en]</i>Â porqueÂ <i>v</i>Â tiene prioridad sobreÂ <i>l</i>. La macro _Â <i>content</i>Â _Â <i>[l=fr, v=1, c=hdl]</i>Â no serÃ­a seleccionada porque el parÃ¡metro de pÃ¡gina paraÂ <i>l</i>Â es diferente.</Text>
+<Figure id="data_structures_representing_the_default_macros">
+<Title>
+<Text id="1034">Estructuras de datos que representan las macros por defecto</Text>
+</Title>
+<File width="605" height="224" url="images/Dev_Fig_45.png"/>
+</Figure>
+<Text id="1035">En la Figura <CrossRef target="Figure" ref="data_structures_representing_the_default_macros"/> se muestra la estructura de datos principales creada por la lectura de los archivos de macros especificados enÂ <i>etc/main.cfg</i>. Se trata esencialmente de una matriz asociativa de matrices asociativas de matrices asociativas. El nivel superior (que aparece a la izquierda) indiza el paquete del que procede la macro, y el segundo nivel indiza el nombre de la macro. El Ãºltimo nivel indiza todos los parÃ¡metros especificados, guardando cada uno de ellos como tipoÂ <i>mvalue</i>Â que registra el valor de la macro y el archivo del que procede. Por ejemplo, podemos ver el texto definido para _Â <i>header</i>Â _Â <i>[l=en]</i>Â de la Figura <CrossRef target="Figure" ref="illustration_of_macro_precedence"/> almacenado en el mÃ¡s bajo de los dos registrosÂ <i>mvalue</i>Â de la Figura <CrossRef target="Figure" ref="data_structures_representing_the_default_macros"/>.</Text>
+<Figure id="displayclass_api">
+<Title>
+<Text id="1036">API de la claseÂ <i>displayclass</i>Â (abreviada)</Text>
+</Title>
+<CodeLine>class displayclass</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>Â  displayclass ();</CodeLine>
+<CodeLine>Â  ~displayclass ();</CodeLine>
+<CodeLine>Â  int isdefaultmacro (text_t package, const text_t &amp;macroname);</CodeLine>
+<CodeLine>Â  int setdefaultmacro (text_t package, const text_t &amp;macroname,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  text_t params, const text_t &amp;macrovalue); </CodeLine>
+<CodeLine>Â  int loaddefaultmacros (text_t thisfilename);</CodeLine>
+<CodeLine>Â  void openpage (const text_t &amp;thispageparams,</CodeLine>
+<CodeLine>Â  const text_t &amp;thisprecedence);</CodeLine>
+<CodeLine>Â  void setpageparams (text_t thispageparams,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  text_t thisprecedence);</CodeLine>
+<CodeLine>Â  int setmacro (const text_t &amp;macroname,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  text_t package,</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  const text_t &amp;macrovalue);</CodeLine>
+<CodeLine>Â  void expandstring (const text_t &amp;inputtext, text_t &amp;outputtext);</CodeLine>
+<CodeLine>Â  void expandstring (text_t package, const text_t &amp;inputtext,</CodeLine>
+<CodeLine>Â  Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â text_t &amp;outputtext, int recursiondepth = 0);</CodeLine>
+<CodeLine>Â  void setconvertclass (outconvertclass *theoutc) {outc = theoutc;}</CodeLine>
+<CodeLine>Â  Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â outconvertclass *getconvertclass () {return outc;}</CodeLine>
+<CodeLine>Â Â Â  Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ostream *setlogout (ostream *thelogout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="1037">El objeto principal de apoyo al lenguaje de macros esÂ <i>displayclass</i>, definido enÂ <i>lib/display.h</i>. Sus funciones miembro pÃºblicas aparecen en la Figura <CrossRef target="Figure" ref="displayclass_api"/>. La clase lee los archivos de macros especificados utilizandoÂ <i>loaddefaultmacros( )</i>Â y guarda en una secciÃ³n protegida de la clase (que no se muestra) el tipo de la estructura de datos que se muestra en la Figura <CrossRef target="Figure" ref="data_structures_representing_the_default_macros"/>. Es posible asimismo que el sistema de ejecuciÃ³n cree macros utilizandoÂ <i>setmacro( )</i>Â (en el Ãºltimo ejemplo de la SecciÃ³n <CrossRef target="Section" ref="how_the_conceptual_framework_fits_together"/>,Â <i>pageaction</i>Â establece que _Â <i>homeextra</i>Â _ sea el cuadro generado dinÃ¡micamente para las colecciones disponibles que utilizan esta funciÃ³n). Todo ello con la ayuda de un conjunto de matrices asociativas semejantes a las que se utilizan para representar los archivos de macros (no es idÃ©ntico porque el primero no requiere la capa âparÃ¡metroâ). EnÂ <i>displayclass</i>, las macros que se leen desde el archivo se denominanÂ <i>macros por defecto</i>. Las macros locales que se especifican a travÃ©s deÂ <i>setmacro( )</i>Â se denominanÂ <i>macros en curso</i>, y son borradas de la memoria tras generarse la pÃ¡gina.</Text>
+<Text id="1038">Cuando se va a generar una pÃ¡gina, se llama primeroÂ <i>openpage( )</i>Â para comunicar las configuraciones en curso de los parÃ¡metros de la pÃ¡gina en cuestiÃ³n (Â <i>l=en</i>, etc.). A continuaciÃ³n, el texto y las macros fluyen a travÃ©s de la clase â normalmente desde unaÂ <i>actionclass</i>Â â utilizando el cÃ³digo:</Text>
+<CodeLine>cout &lt;&lt; text_t2ascii &lt;&lt; display &lt;&lt; â_unamacro_â</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  &lt;&lt; â_otramacro_â;</CodeLine>
+<Text id="1039">El resultado es que las macros se amplÃ­an siguiendo las configuraciones de los parÃ¡metros de la pÃ¡gina. En caso necesario, estas configuraciones pueden modificarse durante el proceso mediante una acciÃ³n que utilizaÂ <i>setpageparams( )</i>. Las demÃ¡s funciones miembro pÃºblicas proporcionan el apoyo de nivel inferior.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_receptionist_code">
+<Title>
+<Text id="1040">El cÃ³digo del recepcionista</Text>
+</Title>
+<Content>
+<Text id="1041">Hemos explicado ya los objetos principales del recepcionista. A continuaciÃ³n, detallaremos las clases de apoyo que se encuentran en el directorioÂ <i>GSDLHOME/src/recpt</i>. Excepto cuando la eficiencia es prioritaria, en cuyo caso las definiciones estÃ¡nÂ <i>inline</i>Â (en lÃ­nea), los detalles de la implementaciÃ³n se encuentran en el archivoÂ <i>.cpp</i>Â correspondiente al archivo de encabezados. Los archivos de apoyo suelen incluir la palabraÂ <i>tool</i>Â como parte del nombre del archivo, como enÂ <i>OIDtools.h</i>Â yÂ <i>formattools.h</i>.</Text>
+<Text id="1042">Un segundo conjunto de archivos de alcance lÃ©xico comprenden el prefijoÂ <i>z3950</i>. Los archivos proporcionan acceso remoto a las bases de datos y los catÃ¡logos en lÃ­nea pÃºblicamente accesibles mediante el protocolo Z39.50.</Text>
+<Text id="1043">Otro amplio grupo de archivos de apoyo comprende el tÃ©rminoÂ <i>browserclass</i>. Estos archivos estÃ¡n relacionados mediante una jerarquÃ­a de herencia virtual. Como grupo apoyan la nociÃ³n abstracta de consulta: generaciÃ³n de pÃ¡ginas en serie que comportan contenidos de documentos compartimentados o metadatos. Las posibilidades de consulta incluyen el examen de documentos ordenados alfabÃ©ticamente por tÃ­tulo o cronolÃ³gicamente por fecha, la consulta de los resultados de una bÃºsqueda por grupos de diez, y el acceso a las pÃ¡ginas individuales de un libro utilizando el mecanismo âir a la pÃ¡ginaâ. Todas las actividades de consulta heredan la clase de baseÂ <i>browserclass</i>Â :</Text>
+<BulletList>
+<Bullet>
+<Text id="1044"><i>datelistbrowserclass</i>Â para apoyo para las listas cronolÃ³gicas;</Text>
+</Bullet>
+<Bullet>
+<Text id="1045"><i>hlistbrowserclass</i>Â para apoyo para las listas horizontales;</Text>
+</Bullet>
+<Bullet>
+<Text id="1046"><i>htmlbrowserclass</i>Â para apoyo para las pÃ¡ginas HTML;</Text>
+</Bullet>
+<Bullet>
+<Text id="1047"><i>invbrowserclass</i>Â para apoyo para las listas invisibles;</Text>
+</Bullet>
+<Bullet>
+<Text id="1048"><i>pagedbrowserclass</i>Â para apoyo para ir a una pÃ¡gina particular;</Text>
+</Bullet>
+<Bullet>
+<Text id="1049"><i>vlistbrowserclass</i>Â para apoyo para las listas verticales.</Text>
+</Bullet>
+</BulletList>
+<Text id="1050">Las acciones acceden a los objetosÂ <i>browserclass</i>Â a travÃ©s del archivoÂ <i>browsetools.h</i>.</Text>
+<Table class="hidden">
+<Title/>
+<TableContent>
+<tr>
+<th width="140">
+<Text id="1051"><b>OIDtools.h</b></Text>
+</th>
+<th width="390">
+<Text id="1052">FunciÃ³n de apoyo para la evaluaciÃ³n de los identificadores de documento en el protocolo.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1053"><b>action.h</b></Text>
+</th>
+<th width="390">
+<Text id="1054">Clase de base para la entidad AcciÃ³n expuesta en la Figura <CrossRef target="Figure" ref="greenstone_runtime_system"/>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1055"><b>authenaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1056">AcciÃ³n heredada para la gestiÃ³n de la autenticaciÃ³n de un usuario.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1057"><b>browserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1058">Clase de base para las actividades de consulta abstractas.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1059"><b>browsetools.h</b></Text>
+</th>
+<th width="390">
+<Text id="1060">FunciÃ³n de apoyo para el acceso a la jerarquÃ­aÂ <i>browserclass</i>. Las funciones incluyen la ampliaciÃ³n y contracciÃ³n de contenidos, la creaciÃ³n de un Ã­ndice y la generaciÃ³n de controles como el mecanismo âir a la pÃ¡ginaâ.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1061"><b>cgiargs.h</b></Text>
+</th>
+<th width="390">
+<Text id="1062">DefineÂ <i>cgiarginfo</i>, utilizado en la Figura <CrossRef target="Figure" ref="using_the_cgiargsinfoclass_from_pageactioncpp"/>, asÃ­ como el apoyo de otras estructuras de datos para los argumentos CGI.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1063"><b>cgiutils.h</b></Text>
+</th>
+<th width="390">
+<Text id="1064">FunciÃ³n de apoyo para los argumentos CGI que utilizan las estructuras de datos definidas enÂ <i>cgiargs.h</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1065"><b>cgiwrapper.h</b></Text>
+</th>
+<th width="390">
+<Text id="1066">FunciÃ³n de apoyo que hace todo lo necesario para generar una pÃ¡gina utilizando el protocolo CGI. El acceso se hace mediante la funciÃ³n:</Text>
+<CodeLine>void cgiwrapper (receptionist &amp;recpt,</CodeLine>
+<CodeLine>Â  text_t collection);</CodeLine>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1067">que es la Ãºnica funciÃ³n declarada en el archivo de encabezados. Todo el resto del archivoÂ <i>.cpp</i>Â tiene un alcance lÃ©xico de carÃ¡cter local en el archivo (utilizando la palabra clave C++Â <i>static</i>). Si se utiliza la funciÃ³n para una colecciÃ³n particular, entonces se debe introducirÂ <i>collection</i>, o si no la cadena vacÃ­a ââ. El cÃ³digo incluye apoyo para Fast-CGI.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1068"><b>collectoraction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1069">AcciÃ³n heredada que facilita la creaciÃ³n de colecciones por parte del usuario final mediante el Colector. La pÃ¡gina generada procede deÂ <i>collect.dm</i>Â y es controlada por el argumento CGIÂ <i>p=page</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1070"><b>comtypes.h</b></Text>
+</th>
+<th width="390">
+<Text id="1071">Tipos centrales delÂ <i>protocolo</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1072"><b>converter.h</b></Text>
+</th>
+<th width="390">
+<Text id="1073">Objeto de apoyo para los convertidores de flujo.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1074"><b>datelistbrowserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1075">Heredado deÂ <i>browserclass</i>, este objeto presta apoyo para la consulta de las listas cronolÃ³gicas, como las que se ven en la colecciÃ³nÂ <i>Archivos Greenstone</i>Â en âÂ <i>dates</i>Â â (fechas) de la barra de desplazamiento.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1076"><b>documentaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1077">AcciÃ³n heredada que se utiliza para recuperar un documento o porciÃ³n de una jerarquÃ­a de clasificaciÃ³n.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1078"><b>extlinkaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1079">AcciÃ³n heredada que controla si un usuario va directamente a un enlace externo o si debe pasar por una pÃ¡gina de aviso que le informa de que se dispone a salir del sistema de biblioteca digital.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1080"><b>formattools.h</b></Text>
+</th>
+<th width="390">
+<Text id="1081">FunciÃ³n de apoyo para analizar y evaluar las instruccionesÂ <i>format</i>Â de configuraciÃ³n de colecciÃ³n. Se explica con mÃ¡s detalles en la SecciÃ³n <CrossRef target="Subsection" ref="formatting"/>Â <i>supra</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1082"><b>historydb.h</b></Text>
+</th>
+<th width="390">
+<Text id="1083">Estructuras de datos y funciÃ³n de apoyo para la gestiÃ³n de una base de datos de bÃºsquedas anteriores, de modo que un usuario pueda iniciar una nueva bÃºsqueda que incluya tÃ©rminos de bÃºsquedas anteriores.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1084"><b>hlistbrowserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1085">Heredado deÂ <i>browserclass</i>, este objeto presta apoyo para la consulta de las listas horizontales.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1086"><b>htmlbrowserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1087">Heredado deÂ <i>browserclass</i>, este objeto presta apoyo para la consulta de las pÃ¡ginas HTML.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1088"><b>htmlgen.h</b></Text>
+</th>
+<th width="390">
+<Text id="1089">FunciÃ³n de apoyo para resaltar los tÃ©rminos de bÃºsqueda en una cadenaÂ <i>text_t</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1090"><b>htmlutils.h</b></Text>
+</th>
+<th width="390">
+<Text id="1091">FunciÃ³n de apoyo que convierte una cadenaÂ <i>text_t</i>Â en el HTML equivalente. Los sÃ­mbolos â, &amp;, &lt; y &gt; se convierten respectivamente enÂ <i>&amp;quot;</i>,Â <i>&amp;amp;</i>,Â <i>&amp;lt;</i>Â yÂ <i>&amp;gt;</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1092"><b>infodbclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1093">Define dos clases:Â <i>gdbmclass</i>Â eÂ <i>infodbclass</i>. La primera proporciona la API de Greenstone para GDBM; la segunda es la clase de objeto utilizada para guardar una entrada de registro leÃ­da en una base de datos GDBM, y es esencialmente una matriz asociativa formada por matrices de cadenasÂ <i>text_t</i>Â indizadas por nÃºmeros enteros.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1094"><b>invbrowserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1095">Heredado deÂ <i>browserclass</i>, este objeto presta apoyo para la consulta de listas que no se presentarÃ¡n en pantalla (invisibles).</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1096"><b>nullproto.h</b></Text>
+</th>
+<th width="390">
+<Text id="1097">Heredada deÂ <i>recptproto</i>, este clase realiza el protocolo nulo a travÃ©s de las llamadas de funciones del recepcionista al servidor de colecciÃ³n.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1098"><b>pageaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1099">AcciÃ³n heredada que, en combinaciÃ³n con el archivo de macros indicado enÂ <i>p=page</i>, genera una pÃ¡gina Web.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1100"><b>pagedbrowserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1101">Heredado deÂ <i>browserclass</i>, este objeto presta apoyo para el mecanismo âir a la pÃ¡ginaâ, como vimos por ejemplo en la colecciÃ³n Gutenberg.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1102"><b>pingaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1103">AcciÃ³n heredada que comprueba si una colecciÃ³n particular responde.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1104"><b>queryaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1105">AcciÃ³n heredada que toma la bÃºsqueda formulada, las configuraciones y las preferencias, efectÃºa la bÃºsqueda y genera como resultado el subconjunto de documentos correspondientesÂ <i>o=num</i>Â empezando en la posiciÃ³nÂ <i>r=num</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1106"><b>querytools.h</b></Text>
+</th>
+<th width="390">
+<Text id="1107">FunciÃ³n de apoyo para las bÃºsquedas.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1108"><b>receptionist.h</b></Text>
+</th>
+<th width="390">
+<Text id="1109">Objeto de alto nivel del recepcionista. Mantiene un registro de las informaciones de argumentos CGI, las instancias de cada acciÃ³n heredada, las instancias de cada objeto de consulta heredado, el objeto central de lenguaje de macrosÂ <i>displayclass</i>, asÃ­ como todos los convertidores posibles.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1110"><b>recptconfig.h</b></Text>
+</th>
+<th width="390">
+<Text id="1111">FunciÃ³n de apoyo para la lectura de los principales archivos de configuraciÃ³n y de sitio.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1112"><b>recptproto.h</b></Text>
+</th>
+<th width="390">
+<Text id="1113">Clase de base para el protocolo.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1114"><b>statusaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1115">AcciÃ³n heredada que genera, conjuntamente conÂ <i>status.dm</i>, las diversas pÃ¡ginas de administraciÃ³n.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1116"><b>tipaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1117">AcciÃ³n heredada que genera, conjuntamente conÂ <i>tip.dm</i>, una pÃ¡gina Web que contiene una sugerencia elegida de forma aleatoria a partir de una lista de sugerencias que se encuentra enÂ <i>tip.dm</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1118"><b>userdb.h</b></Text>
+</th>
+<th width="390">
+<Text id="1119">Estructura de datos y funciÃ³n de apoyo para mantener una base de datos GDBM de usuarios: su contraseÃ±a, sus grupos, etc.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1120"><b>usersaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1121">Una acciÃ³n de administraciÃ³n heredada de la clase de base que permite aÃ±adir y suprimir usuarios, asÃ­ como modificar los grupos a los que pertenecen.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1122"><b>vlistbrowserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1123">Heredado deÂ <i>browserclass</i>, este objeto presta apoyo para la consulta de las listas verticales, que constituyen la base de los clasificadores. Por ejemplo, los elementos secundarios del nodo de tÃ­tulos que empiezan con la letraÂ <i>N</i>Â forman unaÂ <i>Vlist</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1124"><b>z3950cfg.h</b></Text>
+</th>
+<th width="390">
+<Text id="1125">Apoyo de estructura de datos para el protocolo Z39.50. Utilizado porÂ <i>z3950proto.cpp</i>, que define la clase de protocolo principal (heredada de la clase de baseÂ <i>recptproto</i>) y el analizador del archivo de configuraciÃ³nÂ <i>zparse.y</i>Â (escrito en YACC).</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1126"><b>z3950proto.h</b></Text>
+</th>
+<th width="390">
+<Text id="1127">Heredado deÂ <i>recptproto</i>, esta clase implementa el protocolo Z39.50 de tal modo que el recepcionista de Greenstone pueda acceder a los sitios de bibliotecas remotas que funcionan con servidores Z39.50.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1128"><b>z3950server.h</b></Text>
+</th>
+<th width="390">
+<Text id="1129">Apoyo complementario para el protocolo Z39.50.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="initialisation">
+<Title>
+<Text id="1130">InicializaciÃ³n</Text>
+</Title>
+<Content>
+<Text id="1131">En Greenstone, la inicializaciÃ³n es una operaciÃ³n compleja que trata archivos de configuraciÃ³n y asigna valores por defecto a los campos de datos. AdemÃ¡s de las funciones de herencia y de creaciÃ³n, los objetos centrales definen las funcionesÂ <i>init( )</i>Â yÂ <i>configure( )</i>Â para contribuir a normalizar la tarea. Aun asÃ­, el orden de ejecuciÃ³n puede ser difÃ­cil de seguir. En esta secciÃ³n se explica lo que sucede.</Text>
+<Text id="1132">Greenstone utiliza varios archivos de configuraciÃ³n con diferentes fines, pero todos respetan la misma sintaxis. A menos que una lÃ­nea empiece por el sÃ­mbolo â#â o sÃ³lo contenga espacios en blanco, la primera palabra define un tÃ©rmino clave y las demÃ¡s representan una configuraciÃ³n particular de dicho tÃ©rmino clave.</Text>
+<Text id="1133">Las lÃ­neas de los archivos de configuraciÃ³n se transmiten de una en una a la funciÃ³nÂ <i>configure( )</i>Â y contienen dos argumentos: el tÃ©rmino clave y una matriz de las palabras restantes. BasÃ¡ndose en el tÃ©rmino clave, una versiÃ³n particular deÂ <i>configure( )</i>Â determina si la informaciÃ³n es de interÃ©s, y si es asÃ­ la guarda. Por ejemplo,Â <i>collectserver</i>Â (que corresponde al objeto ColecciÃ³n de la Figura <CrossRef target="Figure" ref="greenstone_runtime_system"/>) trata las instrucciones de formato del archivo de configuraciÃ³n de una colecciÃ³n. Cuando la funciÃ³nÂ <i>configure( )</i>Â recibe el tÃ©rmino claveÂ <i>format</i>, se activa una instrucciÃ³nÂ <i>if</i>Â que guarda en el objeto una copia del segundo argumento de la funciÃ³n.</Text>
+<Text id="1134">Tras tratar el tÃ©rmino clave y antes de que concluya la funciÃ³n, algunas versiones deÂ <i>configure( )</i>Â transmiten los datos a las funcionesÂ <i>configure( )</i>Â de otros objetos. El objeto Recepcionista activa la funciÃ³nÂ <i>configure( )</i>Â de los objetos Acciones, Protocolos y Consulta. El objeto Protocolo nulo activa la funciÃ³nÂ <i>configure( )</i>Â de cada objeto ColecciÃ³n; el objeto ColecciÃ³n activa los objetos Filtro y Fuente.</Text>
+<Text id="1135">En C++, los campos de datos se inicializan normalmente mediante la funciÃ³n de creaciÃ³n del objeto. Sin embargo, en Greenstone algunas inicializaciones dependen de los valores leÃ­dos en los archivos de configuraciÃ³n, por ello es preciso proceder a una segunda tanda de inicializaciones. Esta es la finalidad de las funciones miembroÂ <i>init( )</i>, y en algunos casos requiere posteriores llamadas de la funciÃ³nÂ <i>configure( )</i>.</Text>
+<Figure id="initialising_greenstone_using_the_null_protocol">
+<Title>
+<Text id="1136">InicializaciÃ³n de Greenstone utilizando el protocolo nulo</Text>
+</Title>
+<CodeLine>============</CodeLine>
+<CodeLine>Main program</CodeLine>
+<CodeLine>============</CodeLine>
+<CodeLine>Statically construct Receptionist</CodeLine>
+<CodeLine>Statically construct NullProtocol</CodeLine>
+<CodeLine>Establish the value for âgsdlhomeâ by reading gsdlsite.cfg</CodeLine>
+<CodeLine>Foreach directory in GSDLHOME/collect that isnât "modelcol":</CodeLine>
+<CodeLine>Â  Add directory name (now treated as collection name) to NullProtocol:</CodeLine>
+<CodeLine>Â Â Â  Dynamically construct Collection</CodeLine>
+<CodeLine>Â Â Â  Dynamically construct Gdbm class</CodeLine>
+<CodeLine>Â Â Â  Dynamically construct the Null Filter</CodeLine>
+<CodeLine>Â Â Â  Dynamically construct the Browse Filter</CodeLine>
+<CodeLine>Â Â Â  Dynamically construct MgSearch</CodeLine>
+<CodeLine>Â Â Â  Dynamically construct the QueryFilter</CodeLine>
+<CodeLine>Â Â Â  Dynamically construct the MgGdbmSource</CodeLine>
+<CodeLine>Â Â Â  Configure Collection with âcollectionâ</CodeLine>
+<CodeLine>Â Â Â Â Â  Passing âcollectionâ value on to Filters and Sources:</CodeLine>
+<CodeLine>Configure Receptionist with âcollectinfoâ:</CodeLine>
+<CodeLine>Â Â Â Â Â  Passing âcollectinfoâ value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>Add NullProtocol to Receptionist</CodeLine>
+<CodeLine>Add in UTF-8 converter</CodeLine>
+<CodeLine>Add in GB converter</CodeLine>
+<CodeLine>Add in Arabic converter</CodeLine>
+<CodeLine>Foreach Action:</CodeLine>
+<CodeLine>Â  Statically construct Action</CodeLine>
+<CodeLine>Â  Add Action to Receptionist</CodeLine>
+<CodeLine>Foreach Browsers:</CodeLine>
+<CodeLine>Â  Statically construct Browser</CodeLine>
+<CodeLine>Â  Add Browser to Receptionist</CodeLine>
+<CodeLine>Call function cgiwrapper:</CodeLine>
+<CodeLine>Â  =================</CodeLine>
+<CodeLine>Â  Configure objects</CodeLine>
+<CodeLine>Â  =================</CodeLine>
+<CodeLine>Â  Configure Receptionist with âcollectionâ</CodeLine>
+<CodeLine>Â Â Â  Passing âcollectionâ value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>Â Â Â  NullProtocol not interested in âcollectionâ</CodeLine>
+<CodeLine>Â  Configure Receptionist with âhttpimgâ</CodeLine>
+<CodeLine>Â Â Â  Passing âhttpimgâ value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>Â Â Â  NullProtocol passing âhttpimgâ on to Collection</CodeLine>
+<CodeLine>Â Â Â  Passing âhttpimgâ value on to Filters and Sources:</CodeLine>
+<CodeLine>Â  Configure Receptionist with âgwcgiâ</CodeLine>
+<CodeLine>Â Â Â  Passing âgwcgiâ value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>Â Â Â  NullProtocol passing âgwcgiâ on to Collection</CodeLine>
+<CodeLine>Â Â Â  Passing âgwcgiâ value on to Filters and Sources:</CodeLine>
+<CodeLine>Â  Reading in site configuration file gsdlsite.cfg</CodeLine>
+<CodeLine>Â Â Â  Configure Recptionist with âgsdlhomeâ</CodeLine>
+<CodeLine>Â Â Â Â Â  Passing âgsdlhomeâ value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>Â Â Â Â Â  NullProtocol passing âgsdlhomeâ on to Collection</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â  Passing âgsdlhomeâ value on to Filters and Sources:</CodeLine>
+<CodeLine>Â Â Â  Configure Recptionist with ...</CodeLine>
+<CodeLine>Â Â Â  ... and so on for all entries in gsdlsite.cfg </CodeLine>
+<CodeLine>Â  Reading in main configuration file main.cfg</CodeLine>
+<CodeLine>Â Â Â  Configure Recptionist with ...</CodeLine>
+<CodeLine>Â Â Â  ... and so on for all entries in main.cfg</CodeLine>
+<CodeLine>Â  ====================</CodeLine>
+<CodeLine>Â  Initialising objects</CodeLine>
+<CodeLine>Â  ====================</CodeLine>
+<CodeLine>Â  Initialise the Receptionist</CodeLine>
+<CodeLine>Â Â Â  Configure Receptionist with âcollectdirâ</CodeLine>
+<CodeLine>Â Â Â Â Â  Passing âcollectdirâ value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>Â Â Â Â Â  NullProtocol not interested in âcollectdirâ</CodeLine>
+<CodeLine>Â Â Â  Read in Macro files</CodeLine>
+<CodeLine>Â Â Â  Foreach Actions</CodeLine>
+<CodeLine>Â Â Â Â Â  Initialise Action</CodeLine>
+<CodeLine>Â Â Â  Foreach Protocol</CodeLine>
+<CodeLine>Â Â Â Â Â  Initialise Protocol</CodeLine>
+<CodeLine>Â Â Â Â Â  When Protocol==NullProtocol:</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â  Foreach Collection</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â  Reading Collectionâs build.cfg</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â  Reading Collectionâs collect.cfg</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â  Configure Collection with âcreatorâ</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â  Â Â Â Passing âcreatorâ value on to Filters and Sources:</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â  Configure Collection with âmaintainerâ</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â  Passing âmaintainerâ value on to Filters and Sources:</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â  ... and so on for all entries in collect.cfg</CodeLine>
+<CodeLine>Â Â Â  Foreach Browsers</CodeLine>
+<CodeLine>Â Â Â  Â Â Initialise Browser</CodeLine>
+<CodeLine>Â  =============</CodeLine>
+<CodeLine>Â  Generate page</CodeLine>
+<CodeLine>Â  =============</CodeLine>
+<CodeLine>Â  Parse CGI arguments</CodeLine>
+<CodeLine>Â  Execute designated Action to produce page</CodeLine>
+<CodeLine>End.</CodeLine>
+</Figure>
+<Text id="1137">En la Figura <CrossRef target="Figure" ref="initialising_greenstone_using_the_null_protocol"/> se presentan los mensajes de diagnÃ³stico generados por una versiÃ³n de Greenstone configurada para resaltar el proceso de inicializaciÃ³n. El programa arranca con la funciÃ³nÂ <i>main( )</i>Â del archivoÂ <i>recpt/librarymain.cpp</i>. Crea un objeto Recepcionista y un objeto Protocolo nulo, luego recorre el archivoÂ <i>gsdlsite.cfg</i>Â (ubicado en el mismo directorio que el ejecutableÂ <i>library</i>) enÂ  busca deÂ <i>gsdlhome</i>Â y guarda su valor en una variable. Para cada colecciÃ³n en lÃ­nea âlista establecida leyendo los directorios deÂ <i>GSDLHOME/collect</i>Â â el programa crea un objeto de colecciÃ³n mediante el objeto Protocolo nulo, que contiene objetos Filtro, BÃºsqueda y Fuente, asÃ­ como algunas llamadas cableadas aÂ <i>configure( )</i>.</Text>
+<Text id="1138">A continuaciÃ³n, la funciÃ³nÂ <i>main( )</i>Â agrega el objeto Protocolo nulo al recepcionista, que mantiene una matriz de clase de base de protocolos en un campo de datos protegidos, y luego activa varios convertidores. La funciÃ³nÂ <i>main( )</i>Â crea todos los objetos AcciÃ³n y Consulta que se utilizan en el ejecutable y los incorpora al recepcionista. La funciÃ³n concluye al activar la funciÃ³nÂ <i>cgiwrapper( )</i>Â ubicada enÂ <i>cgiwrapper.cpp</i>, que efectÃºa a su vez un nÃºmero importante de inicializaciones de objetos.</Text>
+<Text id="1139">La funciÃ³nÂ <i>cgiwrapper( )</i>Â comprende tres partes: configuraciÃ³n, inicializaciÃ³n y generaciÃ³n de pÃ¡gina. En primer lugar, se efectÃºan algunas llamadas cableadas a la funciÃ³nÂ <i>configure( )</i>, luego se lee el archivoÂ <i>gsdlsite.cfg</i>Â y se aplicaÂ <i>configure</i>Â a cada lÃ­nea. Lo mismo ocurre con el archivoÂ <i>etc/main.cfg</i>.</Text>
+<Text id="1140">La segunda fase deÂ <i>cgiwrapper( )</i>Â activaÂ <i>init( )</i>. El objeto Recepcionista sÃ³lo hace una llamada a su funciÃ³nÂ <i>init( )</i>, pero esta acciÃ³n invoca las funcionesÂ <i>init( )</i>Â de los diferentes objetos que contiene. Primero una llamada cableada aÂ <i>configure( )</i>Â para instalarÂ <i>collectdir</i>, y luego se leen los archivos de macros. Se activa la funciÃ³nÂ <i>init( )</i>Â de cada acciÃ³n. Lo mismo ocurre con cada protocolo almacenado en el recepcionista, pero en el sistema que se describe aquÃ­ sÃ³lo se almacena el protocolo nulo. La activaciÃ³n de la funciÃ³nÂ <i>init( )</i>Â de este objeto suscita otras configuraciones: en cada colecciÃ³n del protocolo nulo se leen y se tratan los archivos especÃ­ficos de la colecciÃ³nÂ <i>build.cfg</i>Â yÂ <i>collect.cfg</i>, y cada lÃ­nea activa la funciÃ³nÂ <i>configure( )</i>.</Text>
+<Text id="1141">La fase final deÂ <i>cgiwrapper( )</i>Â consiste en analizar los argumentos CGI y luego activar la acciÃ³n adecuada. Ambas acciones se efectÃºan con la asistencia del objeto Recepcionista.</Text>
+<Text id="1142">Los cÃ³digos de configuraciÃ³n, inicializaciÃ³n y generaciÃ³n de pÃ¡ginas estÃ¡n separados porque Greenstone estÃ¡ concebido para funcionar como servidor (con Fast-CGI, el protocolo CORBA, o la versiÃ³n Biblioteca Local de Windows). En ese modo de funcionamiento, el cÃ³digo de configuraciÃ³n y de inicializaciÃ³n sÃ³lo se ejecuta una vez, y luego el programa permanece en memoria y genera numerosas pÃ¡ginas Web en respuesta a las consultas de los usuarios sin necesidad de volverse a inicializar.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="configuring_your_greenstone_site">
+<Title>
+<Text id="1143">CONFIGURACIÃN DEL SITIO GREENSTONE</Text>
+</Title>
+<Content>
+<Text id="1144">En Greenstone, se utilizan dos archivos de configuraciÃ³n para configurar las diversas caracterÃ­sticas del sitio Greenstone: el archivo de configuraciÃ³n âprincipalâÂ <i>main.cfg</i>, que se encuentra en el directorioÂ <i>GSDLHOME/etc</i>, y el archivo de configuraciÃ³n âde sitioâÂ <i>gsdlsite.cfg</i>, que se encuentra en el directorioÂ <i>GSDLHOME/cgi-bin</i>. Ambos archivos controlan aspectos especÃ­ficos de la configuraciÃ³n del sitio y pueden visualizarse desde la pÃ¡gina de administraciÃ³n de Greenstone.</Text>
+<Section id="main_configuration_file">
+<Title>
+<Text id="1145">Archivo de configuraciÃ³n principal</Text>
+</Title>
+<Content>
+<Text id="1146">El archivo de configuraciÃ³n principalÂ <i>main.cfg</i>Â sirve para configurar el recepcionista, esto es, la parte de Greenstone que procesa las consultas y muestra las pÃ¡ginas. Se puede controlar todo, desde las lenguas que la interfaz puede utilizar hasta los registros que se llevarÃ¡n.</Text>
+<Subsection id="site_maintenance_and_logging">
+<Title>
+<Text id="1147">Mantenimiento del sitio y registro de utilizaciÃ³n (<i>logging</i>)</Text>
+</Title>
+<Content>
+<Text id="1148">Las lÃ­neas del archivo de configuraciÃ³n establecen la manera en que su sitio Greenstone se mantendrÃ¡, quÃ© funciones ofrecerÃ¡, quÃ© eventos se registrarÃ¡n y quÃ© notificaciones se harÃ¡n al responsable del mantenimiento. En el Cuadro <CrossRef target="Table" ref="configuration_options_for_site_maintenance_and_logging"/> se muestran algunas de las opciones disponibles; las restantes se exponen en las secciones siguientes.</Text>
+<Table id="configuration_options_for_site_maintenance_and_logging">
+<Title>
+<Text id="1149">Opciones de configuraciÃ³n para el mantenimiento del sitio y el registro de utilizaciÃ³n (<i>logging</i>)</Text>
+</Title>
+<TableContent>
+<tr>
+<th>Â </th>
+<th>
+<Text id="1150"><b>Valor</b></Text>
+</th>
+<th>
+<Text id="1151"><b>Finalidad</b></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="1152">maintainer</Text>
+</th>
+<th>
+<Text id="1153">NULL o una direcciÃ³n de correo electrÃ³nico</Text>
+</th>
+<th>
+<Text id="1154">DirecciÃ³n de correo electrÃ³nico del encargado del mantenimiento del sitio que se utiliza para algunas notificaciones. Si es NULL se desactivan los eventos de correo electrÃ³nico.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="1155">MailServer </Text>
+</th>
+<th>
+<Text id="1156">NULL o un nombre de servidor</Text>
+</th>
+<th>
+<Text id="1157">Servidor de correo electrÃ³nico de salida para el sitio. Si es NULL, se utilizaÂ <i>mail.dominio_del_encargado_del_mantenimiento</i>Â (por ejemplo, si el encargado del mantenimiento esÂ <i>ayuda@ejemplo.com</i>Â el valor por defecto serÃ¡Â <i>mail.ejemplo.com</i>.) Si ello no lleva a un servidor SMTP vÃ¡lido, los eventos de correo electrÃ³nico no funcionarÃ¡n.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="1158"><i>status</i></Text>
+</th>
+<th>
+<Text id="1159"><i>enabled</i>Â (activado) oÂ <i>disabled</i>Â (desactivado)</Text>
+</th>
+<th>
+<Text id="1160">Determina si la pÃ¡gina de âMantenimiento y administraciÃ³nâ debe estar disponible.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="1161"><i>collector</i></Text>
+</th>
+<th>
+<Text id="1162"><i>enabled</i>Â (activado) oÂ <i>disabled</i>Â (desactivado)</Text>
+</th>
+<th>
+<Text id="1163">Determina si la aplicaciÃ³n âColectorâ de creaciÃ³n de colecciÃ³n para el usuario final debe estar disponible.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="1164"><i>logcgiargs</i></Text>
+</th>
+<th>
+<Text id="1165"><i>true</i>Â (verdadero) oÂ <i>false</i>Â (falso)</Text>
+</th>
+<th>
+<Text id="1166">Si el valor esÂ <i>true</i>Â (verdadero), se conserva un registro de utilizaciÃ³n enÂ <i>usage.txt</i>.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="1167"><i>usecookies</i></Text>
+</th>
+<th>
+<Text id="1168"><i>true</i>Â (verdadero) oÂ <i>false</i>Â (falso)</Text>
+</th>
+<th>
+<Text id="1169">Si el valor esÂ <i>true</i>Â (verdadero), se acopia informaciÃ³n relativa a los usuarios del sitio (mediante registros de identificaciÃ³n oÂ <i>cookies</i>) que se guarda enÂ <i>usage.txt</i>Â (sÃ³lo funciona si la opciÃ³nÂ <i>logcgiargs</i>Â tiene el valorÂ <i>true</i>).</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="1170"><i>LogDateFormat</i></Text>
+</th>
+<th>
+<Text id="1171"><i>LocalTime</i>Â (hora local) oÂ <i>UTCTime</i>Â (hora universal) oÂ <i>Absolute</i>Â (hora absoluta)</Text>
+</th>
+<th>
+<Text id="1172">Formato en el que se consignan las fechas y las horas en los registros.Â <i>LocalTime</i>Â genera el formato âThu Dec 07 12:34 NZDT 2000â,Â <i>UTCTime</i>Â es el mismo formato pero en tiempo universal (o GMT), yÂ <i>absolute</i>Â es un nÃºmero entero que representa el nÃºmero de segundos transcurridos desde â00:00:00 01/01/1970 GMTâ</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="1173"><i>LogEvents</i></Text>
+</th>
+<th>
+<Text id="1174"><i>AllEvents</i>Â (todos los eventos) oÂ <i>CollectorEvents</i>Â (eventos del Colector) oÂ <i>disabled</i>Â (desactivado)</Text>
+</th>
+<th>
+<Text id="1175">Registra determinados eventos enÂ <i>events.txt.</i><i>AllEvents</i>Â consigna todos los eventos de Greenstone,Â <i>CollectorEvents</i>Â sÃ³lo registra los eventos relacionados con el Colector, yÂ <i>disabled</i>Â no registra ningÃºn evento.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="1176"><i>EmailEvents</i></Text>
+</th>
+<th>
+<Text id="1177"><i>enabled</i>Â (activado) oÂ <i>disabled</i>Â (desactivado)</Text>
+</th>
+<th>
+<Text id="1178">EnvÃ­a un mensaje por correo electrÃ³nico al encargado del mantenimiento (en caso de haberlo - vÃ©ase la opciÃ³nÂ <i>mantainer</i>) cada vez que se produce un evento.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="1179"><i>EmailUserEvents</i></Text>
+</th>
+<th>
+<Text id="1180"><i>enabled</i>Â (activado) oÂ <i>disabled</i>Â (desactivado)</Text>
+</th>
+<th>
+<Text id="1181">EnvÃ­a un mensaje por correo electrÃ³nico al usuario sobre determinados eventos (por ejemplo, cuando el Colector finaliza la creaciÃ³n de una colecciÃ³n). </Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="1182"><i>macrofiles</i></Text>
+</th>
+<th>
+<Text id="1183">lista de nombres de archivos de macros</Text>
+</th>
+<th>
+<Text id="1184">Determina quÃ© macros se encuentran a disposiciÃ³n del programa de interfaz de usuario de Greenstone</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+<Subsection id="language_support">
+<Title>
+<Text id="1185">SelecciÃ³n de lenguas</Text>
+</Title>
+<Content>
+<Text id="1186">El archivo de configuraciÃ³nÂ <i>main.cfg</i>Â contiene dos tipos de entradas que inciden en la gestiÃ³n de las diferentes lenguas. Ãstas determinan quÃ© idiomas y quÃ© cÃ³digos estarÃ¡n disponibles en la pÃ¡gina de preferencias. Las lÃ­neasÂ <i>encoding</i>Â (codificaciÃ³n) especifican los diferentes tipos de codificaciÃ³n de caracteres que pueden seleccionarse. Las lÃ­neasÂ <i>language</i>Â (lengua) especifican quÃ© idiomas se podrÃ¡n seleccionar para la interfaz de usuario (por supuesto, es preciso que exista una macro de lengua para cada lengua posible).</Text>
+<Text id="1187">La lÃ­neaÂ <i>encoding</i>Â (codificaciÃ³n) puede contener cuatro valores posibles:Â <i>shortname</i>Â (nombre corto),Â <i>longname</i>Â (nombre largo),Â <i>map</i>Â (correspondencia) yÂ <i>multibyte</i>. El valorÂ <i>shortname</i>Â es la etiqueta del juego de caracteres estÃ¡ndar y debe especificarse en todas las codificaciones. El valorÂ <i>longname</i>Â da el nombre de codificaciÃ³n que se especifica en la pÃ¡gina deÂ <i>preferencias</i>. En su ausencia, el valor por defecto es el deÂ <i>shortname</i>. El valorÂ <i>map</i>Â es obligatorio para todas las codificaciones, excepto para UTF-8, que se maneja internamente (y que deberÃ­a siempre estar activado). El valorÂ <i>multibyte</i>Â deberÃ­a aplicarse a todos los juegos de caracteres que necesitan mÃ¡s de un byte por carÃ¡cter. El archivoÂ <i>main.cfg</i>Â especifica numerosas codificaciones, la mayorÃ­a de las cuales estÃ¡ desactivada, pues estÃ¡n comentadas de manera que la programaciÃ³n nos las toma en consideraciÃ³n. Para activar una codificaciÃ³n, suprima el carÃ¡cter de comentario â#â.</Text>
+<Text id="1188">Cada lÃ­neaÂ <i>language</i>Â (idioma) puede contener tres valores posibles:Â <i>shortname</i>Â (nombre corto),Â <i>longname</i>Â (nombre largo) yÂ <i>default_encoding</i>Â (codificaciÃ³n por defecto). El valorÂ <i>shortname</i>Â es el sÃ­mbolo de idioma de dos letras ISO 639 y es obligatorio. El valorÂ <i>longname</i>Â da el nombre de la lengua especificada en la pÃ¡gina deÂ <i>preferencias</i>. En su ausencia, el valor por defecto es el deÂ <i>shortname</i>. La opciÃ³nÂ <i>default_encoding</i>Â sirve para especificar la codificaciÃ³n preferida para esa lengua.</Text>
+</Content>
+</Subsection>
+<Subsection id="page_parameters_and_cgi_arguments">
+<Title>
+<Text id="1189">ParÃ¡metros de pÃ¡gina y argumentos CGI</Text>
+</Title>
+<Content>
+<Text id="1190">Se pueden definir parÃ¡metros de pÃ¡gina y argumentos CGI en el archivo de configuraciÃ³nÂ <i>main.cfg</i>. Recuerde que en la Figura <CrossRef target="Figure" ref="using_the_cgiargsinfoclass_from_pageactioncpp"/> la mayorÃ­a de los argumentos CGI se definen en el seno mismo del cÃ³digo C++ de la biblioteca. Sin embargo, a veces resulta Ãºtil definir nuevos argumentos o modificar los argumentos existentes en los archivos de configuraciÃ³n, lo cual evita recompilar la biblioteca.</Text>
+<Text id="1191">Para ello, utilice la opciÃ³n de configuraciÃ³nÂ <i>cgiarg</i>, que puede contener hasta seis argumentos:Â <i>shortname</i>Â (nombre corto),Â <i>longname</i>Â (nombre largo),Â <i>multiplechar</i>Â (caracteres mÃºltiples),Â <i>argdefault</i>Â (argumento por defecto),Â <i>defaultstatus</i>Â (estado por defecto) yÂ <i>savedarginfo</i>Â (informaciÃ³n de Resguardo (Â <i>backup</i>) de argumentos). Estos argumentos corresponden a opciones de argumentos CGI descritos en la SecciÃ³n <CrossRef target="Section" ref="receptionist"/>. Por ejemplo, en el archivoÂ <i>main.cfg</i>Â por defecto, la opciÃ³n de configuraciÃ³nÂ <i>cgiarg</i>Â sirve para establecer los valores por defecto de los argumentos CGI existentesÂ <i>a</i>Â yÂ <i>p</i>Â con los valoresÂ <i>p</i>Â yÂ <i>home</i>Â respectivamente.</Text>
+<Text id="1192">Los parÃ¡metros de pÃ¡gina son un caso particular de argumentos CGI que corresponden a los parÃ¡metros de los archivos de macros de Greenstone. Por ejemplo, el argumento CGIÂ <i>l</i>Â corresponde directamente al parÃ¡metroÂ <i>l=</i>Â en los archivos de macros. Se utiliza la opciÃ³n de configuraciÃ³nÂ <i>pageparam</i>Â para definir un argumento CGI tambiÃ©n como parÃ¡metro de pÃ¡gina.</Text>
+<Text id="1193">El mejor modo de aprender las diferentes opciones de configuraciÃ³n posibles en el archivo de configuraciÃ³nÂ <i>main.cfg</i>Â es experimentar con Ã©ste. Recuerde que si estÃ¡ utilizando la versiÃ³n Biblioteca Local de Greenstone con Windows, es preciso volver a arrancar el servidor para que toda modificaciÃ³n de los archivos de configuraciÃ³n surta efecto.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="site_configuration_file">
+<Title>
+<Text id="1194">Archivo de configuraciÃ³n de sitio</Text>
+</Title>
+<Content>
+<Table id="lines_in_gsdlsitecfg">
+<Title>
+<Text id="1195">LÃ­neas del archivoÂ <i>gsdlsite.cfg</i></Text>
+</Title>
+<TableContent>
+<tr>
+<th>
+<Text id="1196"><b>LÃ­nea</b></Text>
+</th>
+<th>
+<Text id="1197"><b>FunciÃ³n</b></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="1198">gsdlhome</Text>
+</th>
+<th>
+<Text id="1199">Una ruta hacia el directorioÂ <i>GSDLHOME</i>.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="1200"><i>httpprefix</i></Text>
+</th>
+<th>
+<Text id="1201">La direcciÃ³n Web deÂ <i>GSDLHOME</i>. Si la raÃ­z de documentos de su servidor Web contiene el valorÂ <i>GSDLHOME</i>, no necesita esta lÃ­nea.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="1202"><i>httpimage</i></Text>
+</th>
+<th>
+<Text id="1203">La direcciÃ³n Web del directorio que contiene las imÃ¡genes de la interfaz de usuario. Si la raÃ­z de documentos de su servidor Web contiene el valorÂ <i>GSDLHOME</i>, Ã©ste serÃ¡Â <i>/images</i>.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="1204"><i>gwcgi</i></Text>
+</th>
+<th>
+<Text id="1205">La direcciÃ³n Web del presente guiÃ³n CGI (acaba generalmente porÂ <i>library</i>). No se necesita si su servidor Web contiene la variable de entornoÂ <i>SCRIPT_NAME</i>Â (nombre de guiÃ³n).</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="1206"><i>maxrequests</i></Text>
+</th>
+<th>
+<Text id="1207">(SÃ³lo se aplica si se utiliza Fast-CGI). NÃºmero de consultas que Fast-CGI debe tratar antes de terminar. Durante la depuraciÃ³n de la biblioteca, deberÃ¡ fijarse un valor bajo a esta funciÃ³n, y en el caso contrario, esto es, en producciÃ³n, un valor elevado.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="1208">El archivo de configuraciÃ³n del sitioÂ <i>gsdlsite.cfg</i>, que se encuentra en el mismo directorio que el programaÂ <i>library</i>, establece variables utilizadas por el programa de biblioteca y el servidor Web durante la ejecuciÃ³n. En el Cuadro <CrossRef target="Table" ref="lines_in_gsdlsitecfg"/> se enumeran las lÃ­neas de este archivo cuya explicaciÃ³n aparece en la SecciÃ³n 5 de laÂ <i>GuÃ­a de InstalaciÃ³n de la Biblioteca Digital Greenstone</i>.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="appendix_a_stl">
+<Title>
+<Text id="1209">APÃNDICE A: LA BIBLIOTECA ESTÃNDAR DE PLANTILLAS C++ (<i>STL</i>)</Text>
+</Title>
+<Content>
+<Text id="1210">La Biblioteca EstÃ¡ndar de Plantillas (<i>Standard Template Library - STL</i>) es una biblioteca de cÃ³digo C++ de amplia difusiÃ³n concebida por Silicon Graphics (Â <i>www.sgi.com</i>). En el presente ApÃ©ndice se presenta un breve resumen de sus principales funciones, que se utilizan a todo lo largo del cÃ³digo Greenstone. Para una explicaciÃ³n mÃ¡s completa, consulte el manual oficial de referencia STL disponible en la siguiente direcciÃ³n Internet:Â <i>www.sgi.com</i>, o alguno de los numerosos libros sobre STL, como el de Josuttis (1999).</Text>
+<Text id="1211">Tal como lo sugiere el tÃ©rmino âplantillaâ, STL no es sÃ³lo una biblioteca de objetos lista para usar. Unida al mecanismo de plantillas de C++, proporciona a los programadores una soluciÃ³n para desarrollar de manera concisa sus propios objetos, recurriendo a las funciones algorÃ­tmicas de STL. Esto aÃ±ade un grado mÃ¡s de complejidad pero vale la pena.</Text>
+<Text id="1212">A fin de ayudar a comprender los extractos del cÃ³digo de Greenstone que figuran en el presente manual, citaremos algunos ejemplos didÃ¡cticos de utilizaciÃ³n de la STL.</Text>
+<Section id="lists">
+<Title>
+<Text id="1213">Listas (<i>Lists</i>)</Text>
+</Title>
+<Content>
+<Figure id="programming_a_list_of_integers" class="withLineNumber">
+<Title>
+<Text id="1214">ProgramaciÃ³n de una lista de nÃºmeros enteros</Text>
+</Title>
+<CodeLine>#include &lt;iostream.h&gt;</CodeLine>
+<CodeLine/>
+<CodeLine>#define nil 0</CodeLine>
+<CodeLine/>
+<CodeLine>struct intlist {</CodeLine>
+<CodeLine>Â  int val; </CodeLine>
+<CodeLine>Â  struct intlist* next;</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine/>
+<CodeLine>int total_int_list(intlist* head)</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>Â  int total = 0;</CodeLine>
+<CodeLine>Â  intlist* curr = head;</CodeLine>
+<CodeLine>Â  while (curr!=nil)</CodeLine>
+<CodeLine>Â  {</CodeLine>
+<CodeLine>Â Â Â  total += curr-&gt;val;</CodeLine>
+<CodeLine>Â Â Â  curr = curr-&gt;next;</CodeLine>
+<CodeLine>Â  }</CodeLine>
+<CodeLine/>
+<CodeLine>Â  return total;</CodeLine>
+<CodeLine>}</CodeLine>
+<CodeLine/>
+<CodeLine>void main()</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>Â  intlist node1 = { 5, nil };</CodeLine>
+<CodeLine>Â  intlist node2 = { 4, nil };</CodeLine>
+<CodeLine>Â  node2.next = &amp;node1;</CodeLine>
+<CodeLine/>
+<CodeLine>Â  int total = total_int_list(&amp;node2);</CodeLine>
+<CodeLine>Â  cout &lt;&lt; "Total de los objetos: " &lt;&lt; total &lt;&lt; endl;</CodeLine>
+<CodeLine>}</CodeLine>
+</Figure>
+<Text id="1215">En primer lugar, estudiaremos dos programas que implementan una lista de nÃºmeros enteros. Uno de ellos utiliza tipos C++ bÃ¡sicas (la âmanera tradicional de procederâ), mientras que el otro utiliza STL. En la Figura <CrossRef target="Figure" ref="programming_a_list_of_integers"/> se muestra la implementaciÃ³n del cÃ³digo fuente queÂ <i>no</i>Â utiliza STL. Las lÃ­neas 5-8 definen la estructura de datos bÃ¡sica que vamos a utilizar: en el campoÂ <i>val</i>Â se almacena el valor del nÃºmero entero, yÂ <i>next</i>Â indica el siguiente elemento de la lista. Como puede advertirse se trata, en suma, de una implementaciÃ³n clÃ¡sica de una lista enlazada.</Text>
+<Text id="1216">Para ilustrar la utilizaciÃ³n de la estructura de datos, el programa principal (lÃ­neas 23-32) inicializa una lista de nÃºmeros enteros con los elementos [5, 4]. Luego activa la funciÃ³nÂ <i>total_int_list</i>Â (definida en las lÃ­neas 10-21), que tiene como Ãºnico parÃ¡metro un puntero dirigido hacia el principio de una lista y que suma los valores que Ã©sta contiene. El valor que devuelve (9 en nuestro ejemplo) aparece en la pantalla.</Text>
+<Text id="1217">Las lÃ­neas 12-18 llevan a cabo las tareas principales. Se comienza por un poco de inicializaciÃ³n: la variable localÂ <i>total</i>Â se fija en cero, yÂ <i>curr</i>Â apunta hacia el principio de la lista. A continuaciÃ³n, un bucleÂ <i>while</i>Â agrega el elemento de nÃºmero entero actual al subtotal vigente (total += curr-&gt;val;) antes de pasar al siguiente elemento (curr = curr-&gt;next;). El bucleÂ <i>while</i>Â termina cuandoÂ <i>curr</i>Â equivale aÂ <i>nil</i>Â (nada), lo que significa que no queda ningÃºn elemento por tratar.</Text>
+<Figure id="programming_a_list_of_integers_using_stl">
+<Title>
+<Text id="1218">ProgramaciÃ³n de una lista de nÃºmeros enteros mediante la STL</Text>
+</Title>
+<CodeLine>#include &lt;iostream.h&gt;</CodeLine>
+<CodeLine>#include &lt;list&gt;</CodeLine>
+<CodeLine/>
+<CodeLine>int total_int_list(list&lt;int&gt;* head)</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>Â  int total = 0;</CodeLine>
+<CodeLine>Â  list&lt;int&gt;::iterator curr = head-&gt;begin();</CodeLine>
+<CodeLine>Â  while (curr!=head-&gt;end())</CodeLine>
+<CodeLine>Â  {</CodeLine>
+<CodeLine>Â Â Â  total += *curr;</CodeLine>
+<CodeLine>Â Â Â  curr++;</CodeLine>
+<CodeLine>Â  }</CodeLine>
+<CodeLine/>
+<CodeLine>Â  return total;</CodeLine>
+<CodeLine>}</CodeLine>
+<CodeLine/>
+<CodeLine>void main()</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>Â  list&lt;int&gt; vals;</CodeLine>
+<CodeLine>Â  vals.push_back(5);</CodeLine>
+<CodeLine>Â  vals.push_back(4);</CodeLine>
+<CodeLine/>
+<CodeLine>Â  int total = total_int_list(&amp;vals);</CodeLine>
+<CodeLine>Â  cout &lt;&lt; "Total de los objetos: " &lt;&lt; total &lt;&lt; endl;</CodeLine>
+<CodeLine>}</CodeLine>
+</Figure>
+<Text id="1219">En la Figura <CrossRef target="Figure" ref="programming_a_list_of_integers_using_stl"/> se muestra un programa equivalente que utiliza STL. Ya no es necesario definir una estructura de datos adecuada en el cÃ³digo, sino que basta con la directiva #include &lt;list&gt; de la lÃ­nea 2 que contiene la plantilla para la lista definida en STL. El objeto se denomina âclase Contenedorâ ya que cuando se declara una variable de este tipo se especifica tambiÃ©n el tipo que se desea que almacene. En la lÃ­nea 19 se elabora una lista de nÃºmeros enteros con la instrucciÃ³n list&lt;int&gt; vals;. Se pueden agregar elementos al objeto mediante la funciÃ³n miembroÂ <i>push_back ( )</i>, como se hace en las lÃ­neas 20-21.</Text>
+<Text id="1220">Las lÃ­neas 6-12 efectÃºan el trabajo principal. Sigue habiendo dos inicializaciones y un bucleÂ <i>while</i>, pero por lo demÃ¡s la nueva sintaxis tiene poco en comÃºn con la antigua. En esta nueva forma de tratamiento es fundamental una variable de tipoÂ <i>iterator</i>Â (lÃ­nea 7). Numerosas clases STL incluyen tiposÂ <i>iterator</i>Â para ofrecer una manera uniforme de recorrer una secuencia de objetos de contenedor. El primer elemento se devuelve conÂ <i>begin( )</i>Â y el elemento que sigue al Ãºltimo elemento se devuelve conÂ <i>end( )</i>. Se pasa al elemento siguiente mediante la operaciÃ³n de incremento ++, que es sobrecargada por la claseÂ <i>iterator</i>Â para implementar esta tarea, y se accede al valor almacenado mediante una operaciÃ³n de derreferenciaciÃ³n (Â <i>*curr</i>Â en la lÃ­nea 10) tambiÃ©n sobrecargada.</Text>
+<Text id="1221">La implementaciÃ³n STL de este programa es un poco mÃ¡s concisa que el cÃ³digo convencional (25 lÃ­neas, en lugar de 31). Las ventajas son mÃ¡s importantes en proyectos mÃ¡s voluminosos, ya que el objetoÂ <i>list</i>Â de STL tiene un potencial mayor de lo que muestra el ejemplo. Este objeto incluye, por ejemplo, una lista doblemente enlazada que admite diversas formas de inserciÃ³n y supresiÃ³n. Se requerirÃ­an tareas de programaciÃ³n suplementarias para integrar estas funciones en la versiÃ³n de lista de nÃºmeros enteros bÃ¡sica.</Text>
+<Text id="1222">ObsÃ©rvese que el parÃ¡metroÂ <i>total_int_list</i>Â de la Figura <CrossRef target="Figure" ref="programming_a_list_of_integers_using_stl"/> se ha implementado como puntero para que corresponda con el puntero utilizado enÂ <i>total_int_list</i>Â de la Figura <CrossRef target="Figure" ref="programming_a_list_of_integers"/>. En STL, suele ser mÃ¡s natural (y preferible) utilizar referencias en lugar de punteros. AsÃ­ pues, el parÃ¡metro se convierte enÂ <i>list&lt;int&gt;&amp; head</i>, y sus funciones miembro se activan con la sintaxisÂ <i>head.begin( );</i>Â y asÃ­ sucesivamente.</Text>
+</Content>
+</Section>
+<Section id="section_correspondencias_(maps)">
+<Title>
+<Text id="1223">Correspondencias (<i>Maps</i>)</Text>
+</Title>
+<Content>
+<Text id="1224">Cuando se implementa un sistema de biblioteca digital, es Ãºtil poder almacenar elementos en una matriz indizada por secuencias de texto en lugar de nÃºmeros. En Greenstone, por ejemplo, esto simplifica considerablemente el almacenamiento de los archivos de macros despuÃ©s de su lectura; lo mismo ocurre con los diversos archivos de configuraciÃ³n. El tipo de datos que permite esta clase de acceso se denominaÂ <i>matriz asociativa</i>Â y suele encontrarse en los lenguajes de programaciÃ³n modernos de alto nivel. Se lo conoce tambiÃ©n con el nombre de âÂ <i>hash array</i>Â â (matriz de desmenuzamiento, sobre todo en Perl) ya que la tÃ©cnica habitual utilizada para implementar los Ã­ndices de texto es el desmenuzamiento (eso es, calcular una suma de control).</Text>
+<Figure id="using_associative_arrays_in_stl" class="withLineNumber">
+<Title>
+<Text id="1225">UtilizaciÃ³n de matrices asociativas en STL</Text>
+</Title>
+<CodeLine>#include &lt;iostream.h&gt;</CodeLine>
+<CodeLine>#include &lt;map&gt;</CodeLine>
+<CodeLine/>
+<CodeLine>int total_int_table(map&lt;char*, int&gt;&amp; table)</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>Â  int total = 0;</CodeLine>
+<CodeLine>Â  map&lt;char*, int&gt;::iterator curr = table.begin();</CodeLine>
+<CodeLine> Â while (curr!=table.end())</CodeLine>
+<CodeLine>Â  {</CodeLine>
+<CodeLine>Â Â Â  total += (curr-&gt;second);</CodeLine>
+<CodeLine>Â Â Â  curr++;</CodeLine>
+<CodeLine>Â  }</CodeLine>
+<CodeLine/>
+<CodeLine>  return total;</CodeLine>
+<CodeLine>}</CodeLine>
+<CodeLine/>
+<CodeLine>int main()</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>Â  map&lt;char*, int&gt; table;</CodeLine>
+<CodeLine>Â  table["Alicia"] = 31;</CodeLine>
+<CodeLine>Â  table["Pedro"] = 24;</CodeLine>
+<CodeLine>Â  table["Maria"] = 47;</CodeLine>
+<CodeLine/>
+<CodeLine>Â  int total = total_int_table(table);</CodeLine>
+<CodeLine>Â  cout &lt;&lt; "Edad total: " &lt;&lt; total &lt;&lt; endl;</CodeLine>
+<CodeLine>}</CodeLine>
+</Figure>
+<Text id="1226">En STL, las matrices asociativas se constituyen mediante el objetoÂ <i>map</i>Â (correspondencia). En la Figura <CrossRef target="Figure" ref="using_associative_arrays_in_stl"/> se presenta un ejemplo un tanto artificial que almacena la edad de tres personas (Alicia, Pedro y Maria) en una matriz asociativa indizada con sus nombres (lÃ­neas 19-22). El problema es escribir una funciÃ³n que calcule la edad total de todas las personas presentes, sin saber ni cuÃ¡ntas ni quiÃ©nes son. Por supuesto, se podrÃ­a resolver este problema con una matriz clÃ¡sica de nÃºmeros enteros indizados numÃ©ricamente. Este ejemplo estÃ¡ concebido para ilustrar las funciones del objetoÂ <i>map</i>Â y poner de manifiesto las semejanzas de tratamiento con el objetoÂ <i>list</i>Â acompaÃ±ado de unÂ <i>iterator</i>.</Text>
+<Text id="1227">Al igual queÂ <i>list</i>,Â <i>map</i>Â es una clase de contenedor. Sin embargo, cuando se declara una variable de este tipo, es preciso especificar dos cosas: el tipo de Ã­ndice y el tipo de elemento<FootnoteRef id="4"/>. Como se puede apreciar en la lÃ­nea 19, se obtiene una matriz asociativa que almacena nÃºmeros enteros indizados por cadenas utilizandoÂ <i>char*</i>Â (que es la manera de declarar una cadena en C++) como tipo de Ã­ndice, seguido deÂ <i>int</i>Â como tipo de elemento.</Text>
+<Text id="1228">Existen diversas maneras de almacenar elementos en la matriz asociativa. En las lÃ­neas 20-22 del ejemplo se utiliza el Ã­ndice de la matriz sobrecargada [ ] para inicializar el cuadro con la edad de las tres personas. La semejanza entreÂ <i>total_int_table</i>, que efectÃºa el cÃ¡lculo principal en el programa, yÂ <i>total_int_list</i>Â en la Figura <CrossRef target="Figure" ref="programming_a_list_of_integers"/> es notable. De hecho, estos dos objetos son casi idÃ©nticos y no es una coincidencia. STL recurre en gran medida a la herencia, de tal modo que objetos diferentes utilizan las mismas operaciones fundamentales. AsÃ­ ocurre sobre todo con losÂ <i>iterators</i>. Las pequeÃ±as diferencias entre las dos funciones consisten en que elÂ <i>iterator</i>Â procede aquÃ­ deÂ <i>map&lt;char*, int&gt;</i>, y que el acceso a sus elementos se hace con la instrucciÃ³n curr-&gt;second(); en efecto, la derreferenciaciÃ³n de la variableÂ <i>(*curr)</i>Â estÃ¡ definida para devolver un objeto de tipoÂ <i>pair</i>. Esta operaciÃ³n registra el nombre del Ã­ndice (Â <i>first</i>) y el valor del elemento (Â <i>second</i>), pero sÃ³lo nos interesa este Ãºltimo. Por lo demÃ¡s, el cÃ³digo permanece igual. La Ãºnica diferencia que persiste âel cambio del Ãºnico argumento de la funciÃ³n de puntero a referenciaâ esÂ  superficial.</Text>
+<Text id="1229">El cÃ³digo de Greenstone utiliza ampliamente otros dos tipos STL:Â <i>vector</i>Â (vector) yÂ <i>set</i>Â (conjunto). El primero facilita las matrices dinÃ¡micas y el segundo admite las operaciones matemÃ¡ticas de conjunto como la uniÃ³n, la intersecciÃ³n y la diferencia.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="bibliography">
+<Title>
+<Text id="1230">BIBLIOGRAFÃA</Text>
+</Title>
+<Content>
+<Text id="1231">Aulds, C. (2000),Â <i>Linux Apache Web Server Administration</i>, Sybex.</Text>
+<Text id="1232">Bainbridge, D., Buchanan, G., McPherson, J., Jones, S., Mahoui, A. y Witten, I.H. (2001) âGreenstone: A platform for distributed digital library developmentâ. Informe de investigaciÃ³n, Departamento de informÃ¡tica, Universidad de Waikato, Nueva Zelandia.</Text>
+<Text id="1233">Christiansen, T. Torkington, N. and Wall, L. (1998),Â <i>Perl Cookbook</i>, OÂŽReilly and Associates.</Text>
+<Text id="1234">Coar, K.A.L. (1998),Â <i>Apache Server For Dummies</i>, IDG Books.</Text>
+<Text id="1235">Deitel, H.M. y Deitel, P.J. (1994),Â <i>C++: How to Program</i>, Prentice Hall, Englewood Cliffs, Nueva Jersey.</Text>
+<Text id="1236">Dublin Core (2001) âThe Dublin Core Metadata Initiativeâ enÂ <i>http://purl.org/dc/</i>, consultado el 16 de enero de 2001. </Text>
+<Text id="1237">Josuttis, N.M. (1999)Â <i>The C++ standard library: a tutorial and reference</i>, Addison-Wesley, 1999.</Text>
+<Text id="1238">Keller, M. y Holden, G. (1999),Â <i>Apache Server for Windows Little Black Book</i>, Grupo Coriolis.</Text>
+<Text id="1239">Schwartz, R.L. y Christiansen, T. (1997),Â <i>Learning Perl</i>Â (2Âª ediciÃ³n), OÂŽReilly and Associates.</Text>
+<Text id="1240">Slama, D., Garbis, J. y Russell, P. (1999),Â <i>Enterprise CORBA</i>, Prentice Hall, Englewood Cliffs, Nueva Jersey.</Text>
+<Text id="1241">Stroustroup, B. (1997),Â <i>The C++ Programming Language</i>, Addison-Wesley.</Text>
+<Text id="1242">Thiele, H. (1997) âThe Dublin Core and Warwick Framework: A Review of the Literature, March 1995-September 1997.âÂ <i>D-Lib Magazine</i>, enero, &lt;Â <i>http://www.dlib.org/dlib/january98/01thiele.html</i>Â &gt;</Text>
+<Text id="1243">Wall, L., Christiansen, T. y Orwant, J. (2000),Â <i>Programming Perl</i>Â (3Âª ediciÃ³n), OÂŽReilly and Associates.</Text>
+<Text id="1244">Weibel, S. (1999), âThe State of the Dublin Core Metadata Initiativeâ,Â <i>D-Lib Magazine</i>, Volumen 5 NÂº 4, abril, &lt;http://www.dlib.org/dlib/april99/04weibel.html&gt;.</Text>
+<Text id="1245">Witten, I.H., Moffat, A. y Bell, T.C. (1999),Â <i>Managing gigabytes: compressing and indexing documents and images</i>, Morgan Kaufmann, San Francisco.</Text>
+</Content>
+</Chapter>
+<FootnoteList>
+<Footnote id="1">
+<Text id="1246">Es posible que al ejecutarÂ <i>setup.bat</i>Â en los sistemas Windows 95/98, aparezca el mensaje de errorÂ <i>âSin espacio en entornoâ</i>. Si ello sucede, deberÃ¡ modificar su archivo de sistemaÂ <i>config.sys</i>Â (que normalmente se encuentra enÂ <i>C:\config.sys</i>) y aÃ±adir la lÃ­neaÂ <i>shell=C:\command.com /e:4096 /p</i>Â (dondeÂ <i>C:</i>Â es la letra correspondiente a la unidad de sistema) para ampliar el tamaÃ±o de su cuadro de entorno. SerÃ¡ necesario volver a arrancar la computadora para que esta modificaciÃ³n surta efecto, y luego repetir los pasos anteriores para Greenstone.</Text>
+</Footnote>
+<Footnote id="2">
+<Text id="1247">ObsÃ©rvese que en Greenstone, las expresiones usuales se interpretan en lenguaje Perl, que difiere levemente de otras convenciones. Por ejemplo, â*â corresponde a cero o mÃ¡s apariciones del carÃ¡cter anterior, mientras que â.â corresponde a cualquier carÃ¡cter, por lo tantoÂ <i>nugget.*</i>Â corresponde a toda cadena que comienza por el prefijo ânuggetâ, seguido o no por un punto. Para insistir en la presencia de un punto serÃ­a necesario aÃ±adir un caracter de escape y escribir en su lugarÂ <i>nugget\...*</i>.</Text>
+</Footnote>
+<Footnote id="3">
+<Text id="1248"/>
+</Footnote>
+<Footnote id="4">
+<Text id="1249">El valor deÂ <i>gsdlhome</i>Â procede del archivoÂ <i>gsdlsite.cfg</i>Â ubicado en el mismo directorio que el ejecutable CGIÂ <i>library</i>, mientras queÂ <i>GSDLHOME</i>Â se activa ejecutando el guiÃ³nÂ <i>setup</i>Â que da acceso a un archivo diferente; asÃ­ pues, es posible tÃ©cnicamente que los dos valores sean diferentes, pero no es deseable. El texto que figura mÃ¡s arriba estÃ¡ escrito partiendo de la hipÃ³tesis de que ambos valores son iguales.</Text>
+</Footnote>
+<Footnote id="5">
+<Text id="1250">TÃ©cnicamente son cuatro tipos, pero los dos Ãºltimos son opcionales. Puesto que nos limitamos a una introducciÃ³n bÃ¡sica de esta clase STL, omitiremos los detalles sobre estos dos Ãºltimos tipos.</Text>
+</Footnote>
+</FootnoteList>
+</Manual>
Index: /tags/start/gsdl-documentation/manuals/xml-source/es/Install_es.xml
===================================================================
--- /tags/start/gsdl-documentation/manuals/xml-source/es/Install_es.xml	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/xml-source/es/Install_es.xml	(revision 13666)
@@ -0,0 +1,1002 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Manual>
+<Heading>
+<Text id="1">BIBLIOTECA DIGITAL GREENSTONE</Text>
+</Heading>
+<Title>
+<Text id="2">GUÃA DE INSTALACIÃN</Text>
+</Title>
+<Author>
+<Text id="3">Ian H. Witten y Stefan Boddie</Text>
+</Author>
+<Affiliation>
+<Text id="4">Departamento de InformÃ¡tica <br/>Universidad de Waikato, Nueva Zelanda</Text>
+</Affiliation>
+<Text id="5">Greenstone es un conjunto de programas y aplicaciones de software especialmente diseÃ±ados para la creaciÃ³n y difusiÃ³n de colecciones documentales digitales, el cual le ofrece una nueva forma de organizar la informaciÃ³n y publicarla en Internet o CD-ROM. Greenstone ha sido elaborado como parte del proyecto de Biblioteca Digital de Nueva Zelanda de la Universidad de Waikato y actualmente es desarrollado y distribuido en colaboraciÃ³n con la UNESCO y la ONG Human Info. Es un software de cÃ³digo abierto disponible enÂ <i>http://greenstone.org</i>Â bajo los tÃ©rminos y condiciones de la Licencia PÃºblica General de GNU .</Text>
+<Comment>
+<Text id="6">Queremos estar seguros que este software trabaje bien para usted.Â Por favor comunÃ­quenos cualquier problema que tenga con Ã©l a la siguiente direcciÃ³n:greenstone@cs.waikato.ac.nz</Text>
+</Comment>
+<Version>
+<Text id="7">Greenstone gsdl-2.50</Text>
+</Version>
+<Date>
+<Text id="8">Marzo de 2004</Text>
+</Date>
+<Section id="about_this_manual">
+<Title>
+<Text id="9">Acerca de este manual</Text>
+</Title>
+<Content>
+<Text id="10">En este documento se explica cÃ³mo instalar Greenstone para que usted pueda utilizarlo en su propia computadora. Se indica tambiÃ©n cÃ³mo obtener otros programas asociados disponibles gratuitamente: el servidor Web Apache y Perl. Hemos procurado que el procedimiento de instalaciÃ³n sea lo mÃ¡s sencillo posible.</Text>
+<Text id="11">El programa funciona en diferentes plataformas y con distintas configuraciones. Por consiguiente, son muchos los factores que inciden (o pueden incidir) en el procedimiento de instalaciÃ³n. En la SecciÃ³n <CrossRef target="Chapter" ref="versions_of_greenstone"/> se mencionan algunos puntos que tendrÃ¡ usted que examinar antes de instalar Greenstone. En la <CrossRef target="Chapter" ref="installation_procedure"/> se detalla el procedimiento de instalaciÃ³n para todas las distintas versiones; sÃ³lo es necesario que lea usted la parte correspondiente a su sistema operativo. La SecciÃ³n <CrossRef target="Chapter" ref="greenstone_collections"/> trata de las colecciones de demostraciÃ³n de la biblioteca digital que estÃ¡n incluidas en la distribuciÃ³n. En la SecciÃ³n <CrossRef target="Chapter" ref="setting_up_webserver"/> se explica cÃ³mo instalar servidores Web comunes, Apache y PWS/IIS de Microsoft, para que funcionen con Greenstone. En la SecciÃ³n <CrossRef target="Chapter" ref="configuring_your_site"/> se mencionan varias opciones de configuraciÃ³n de Greenstone y en la SecciÃ³n <CrossRef target="Chapter" ref="personalizing"/> se muestra cÃ³mo crear una pÃ¡gina principal personalizada para la instalaciÃ³n de su biblioteca digital. Por Ãºltimo, en el ApÃ©ndice <CrossRef target="Chapter" ref="appendix_associated_software"/> se enumeran los programas asociados y se indica cÃ³mo obtenerlos.</Text>
+</Content>
+</Section>
+<Section id="companion_documents">
+<Title>
+<Text id="12">Conjunto de documentos</Text>
+</Title>
+<Content>
+<Text id="13">La serie completa de documentos comprende cinco volÃºmenes:</Text>
+<BulletList>
+<Bullet>
+<Text id="14">La GuÃ­a de InstalaciÃ³n de la Biblioteca Digital Greenstone (<i>el presente documento</i>)</Text>
+</Bullet>
+<Bullet>
+<Text id="15">La GuÃ­a del Usuario de la Biblioteca Digital Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="16">La GuÃ­a del Programador de la Biblioteca Digital Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="17">La Biblioteca Digital Greenstone: del Papel a la ColecciÃ³n</Text>
+</Bullet>
+<Bullet>
+<Text id="18">La Biblioteca Digital Greenstone: uso del Organizador</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Section>
+<Section id="acknowledgements">
+<Title>
+<Text id="19">Agradecimientos</Text>
+</Title>
+<Content>
+<Text id="20">El programa Greenstone es fruto de la colaboraciÃ³n de muchas personas. Rodger McNab y Stefan Boddie son los principales arquitectos y programadores. TambiÃ©n han contribuido David Bainbridge, George Buchanan, Hong Chen, Michael Dewsnip, Katherine Don, Elke Duncker, Carl Gutwin, Geoff Holmes, Dana McKay, John McPherson, Craig Nevill-Manning, Dynal Patel, Gordon Paynter, Bernhard Pfahringer, Todd Reed, Bill Rogers, John Thompson y Stuart Yeates. Otros miembros del proyecto Biblioteca Digital de Nueva Zelanda que proporcionaron asesorÃ­a y valiosas ideas para la concepciÃ³n del sistema son: Mark Apperley, Sally Jo Cunningham, Matt Jones, Steve Jones, Te Taka Keegan, Michel Loots, Malika Mahoui, Gary Marsden, Dave Nichols y Lloyd Smith. TambiÃ©n queremos dar las gracias a todos aquellos que contribuyeron a los paquetes de programas con licencias GNU incluidos en esta distribuciÃ³n: MG, GDBM, PDFTOHTML, PERL, WGET, WVWARE y XLHTML.</Text>
+</Content>
+</Section>
+<Chapter id="versions_of_greenstone">
+<Title>
+<Text id="21">VERSIONES DE GREENSTONE</Text>
+</Title>
+<Content>
+<Text id="22">El programa Greenstone funciona en diferentes plataformas y con distintas configuraciones, como se resume en la Figura <CrossRef target="Figure" ref="different_options"/>.</Text>
+<Figure id="different_options">
+<Title>
+<Text id="23">Las distintas opciones para las versiones Windows y Unix de Greenstone</Text>
+</Title>
+<File width="642" height="295" url="images/Install_Fig_1.png"/>
+</Figure>
+<Text id="24">Hay muchos factores que inciden (o pueden incidir) en el procedimiento de instalaciÃ³n. Antes de proseguir la lectura, detÃ©ngase en los siguientes puntos:</Text>
+<BulletList>
+<Bullet>
+<Text id="25">Â¿EstÃ¡ usted utilizando Windows o Unix?</Text>
+</Bullet>
+<Bullet>
+<Text id="26">Si es Windows, Â¿estÃ¡ usted utilizando Windows 3.1/3.11 o una versiÃ³n mÃ¡s reciente? Aunque se pueden visualizar las colecciones en las mÃ¡quinas que funcionan con las versiones 3.1 Ã³ 3.11, y dar servicio a otras computadoras en la misma red, no puede usted crear nuevas colecciones. El programa Greenstone completo funciona con 95/98/Me y NT/2000.</Text>
+</Bullet>
+<Bullet>
+<Text id="27">Si es Unix, Â¿estÃ¡ usted utilizando Linux u otra versiÃ³n de Unix? Para Linux, se proporciona una versiÃ³n binaria del sistema completo que es fÃ¡cil de instalar. Para otros tipos de Unix tendrÃ¡ usted que instalar el cÃ³digo fuente y compilarlo. Para ello, puede ser preciso instalar en su computadora programas suplementarios.</Text>
+</Bullet>
+<Bullet>
+<Text id="28">Si es Windows NT/2000 o Unix, Â¿puede usted iniciar la sesiÃ³n como âadministradorâ del sistema oÂ <i>root</i>Â ? Esto puede ser necesario para configurar adecuadamente un servidor Web para Greenstone.</Text>
+</Bullet>
+<Bullet>
+<Text id="29">Â¿Quiere usted el cÃ³digo fuente? Si estÃ¡ usted utilizando Windows o Linux, puede usted instalar solamente los binarios. Pero es posible que quiera usted tambiÃ©n el cÃ³digo fuente: Ã©ste viene en la distribuciÃ³n de Greenstone.</Text>
+</Bullet>
+<Bullet>
+<Text id="30">Â¿Quiere usted crear nuevas colecciones de biblioteca digital? En tal caso, es necesario que tenga Perl, disponible gratuitamente para Windows y Unix.</Text>
+</Bullet>
+<Bullet>
+<Text id="31">Â¿Su computadora maneja un servidor Web? Greenstone viene con un servidor Web Windows. No obstante, si ya estÃ¡ usted utilizando un servidor Web, es muy posible que quiera conservarlo. Para Unix, es necesario utilizar un servidor Web.</Text>
+</Bullet>
+<Bullet>
+<Text id="32">Â¿Sabe usted como volver a configurar su servidor Web? Si usted no utiliza el servidor Web de Greenstone, tendrÃ¡ que modificar ligeramente la configuraciÃ³n del suyo para que reconozca el programa Greenstone.</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Chapter>
+<Chapter id="installation_procedure">
+<Title>
+<Text id="33">EL PROCEDIMIENTO DE INSTALACIÃN</Text>
+</Title>
+<Content>
+<Text id="34">Existen sendas versiones de Greenstone disponibles para Windows y Unix, como binarios y en forma de cÃ³digo fuente. La interfaz de usuario de Greenstone utiliza cualquiera de los dos navegadores Web siguientes: Netscape Navigator o Internet Explorer (versiÃ³n 4.0 o superior en ambos casos). En caso de que no tenga usted todavÃ­a un navegador Web, puede usted instalar una de las versiones Windows de Netscape que vienen en el CD-ROM.</Text>
+<Section id="windows">
+<Title>
+<Text id="35">Windows</Text>
+</Title>
+<Content>
+<Text id="36">Si es usted un usuario de Unix, pase directamente a la SecciÃ³n 2.2. Para los usuarios de Windows, si sÃ³lo desea una instalaciÃ³n sencilla siga el siguiente procedimiento de âinstalaciÃ³n simpleâ. El sistema Greenstone ocupa unos 40 Mb de espacio de memoria en el disco duro.</Text>
+<Text id="37">Si no escoge usted la instalaciÃ³n por defecto, tendrÃ¡ que decidir si quiere instalar el cÃ³digo binario o el cÃ³digo fuente. En caso de duda, escoja el cÃ³digo binario. El procedimiento de instalaciÃ³n es el mismo para ambos. En las secciones siguientes encontrarÃ¡ usted mÃ¡s informaciÃ³n sobre las opciones ofrecidas.</Text>
+<Text id="38">Una vez terminada la instalaciÃ³n, pase directamente a la SecciÃ³n 2.3.</Text>
+<Subsection id="simple_installation">
+<Title>
+<Text id="39">InstalaciÃ³n simple</Text>
+</Title>
+<Content>
+<Text id="40">Para instalar la versiÃ³n Windows a partir del CD-ROM, inserte el disco en el lector (por ejemplo,Â <i>D:</i>). Si al cabo de unos 20 segundos el procedimiento de instalaciÃ³n no comienza automÃ¡ticamente, pulse en el menÃºÂ <i>Inicio</i>, seleccioneÂ <i>Ejecutar</i>Â y tecleeÂ <i>D:\Windows\Setup.exe</i>, donde âÂ <i>D</i>Â â es la letra que designa su lector de CD-ROM. Para Windows 3.1, seleccioneÂ <i>Ejecutar</i>Â en el âAdministrador de archivosâ y tecleeÂ <i>D:\Windows\Setup.exe</i>.</Text>
+<Text id="41">Para proceder a la instalaciÃ³n mÃ¡s simple, basta con aceptar el parÃ¡metro por defecto en cada etapa, pulsando el botÃ³nÂ <i>Next</i>Â (siguiente). Â¡Eso es todo! Greenstone queda instalado en el directorioÂ <i>C:\Program Files\gsdl</i>.</Text>
+<Text id="42">Una vez concluida la instalaciÃ³n, para arrancar su sistema Greenstone pulse el botÃ³nÂ <i>Inicio</i>, abra el menÃºÂ <i>Programas</i>Â y seleccioneÂ <i>Biblioteca Digital Greenstone (Greenstone Digital Library)</i>. Esto hace aparecer un cuadro de diÃ¡logo: haga clic enÂ <i>Entrar en la biblioteca (Enter Library)</i>. Esto activa automÃ¡ticamente el navegador Internet y carga la pÃ¡gina principal de la Biblioteca Digital Greenstone, cuyo aspecto debe ser parecido al del ejemplo de la Figura <CrossRef target="Figure" ref="your_greenstone_home_page"/>. Se entra en la colecciÃ³n de demostraciÃ³n de Greenstone pulsando en su icono.</Text>
+<Figure id="your_greenstone_home_page">
+<Title>
+<Text id="43">Su pÃ¡gina principal Greenstone</Text>
+</Title>
+<File width="642" height="527" url="images/Install_Fig_2.png"/>
+</Figure>
+</Content>
+</Subsection>
+<Subsection id="windows_binaries">
+<Title>
+<Text id="44">Binarios Windows</Text>
+</Title>
+<Content>
+<Text id="45">En el CD-ROM hay dos programas binarios Windows distintos: laÂ <i>Biblioteca Local</i>Â y laÂ <i>Biblioteca Web</i>. La instalaciÃ³n por defecto mencionada mÃ¡s arriba selecciona la versiÃ³nÂ <i>Biblioteca Local</i>. Le recomendamos encarecidamente que utilice esta versiÃ³n. La Biblioteca Web, que es mucho mÃ¡s difÃ­cil de instalar, sÃ³lo es necesaria si usted utiliza ya un servidor Web y experimenta conflictos de asignaciÃ³n de puerto al usar la Biblioteca Local. A pesar de su modesto nombre, la Biblioteca Local ofrece una capacidad completa y autÃ³noma de servidor Web.</Text>
+<Text id="46"><b>La Biblioteca Local.</b>Â Este programa permite, a cualquier computadora equipada con Windows,Â  distribuir colecciones Greenstone previamente creadas. La colecciÃ³n de demostraciÃ³n de Greenstone se instalarÃ¡ automÃ¡ticamente; se pueden instalar tambiÃ©n las demÃ¡s colecciones que figuran en el CD-ROM (vÃ©ase la SecciÃ³n <CrossRef target="Chapter" ref="greenstone_collections"/>). El programa de Biblioteca Local es el mismo utilizado en los CD-ROM producidos por el sistema Greenstone.</Text>
+<Text id="47">La Biblioteca Local estÃ¡ destinada a utilizarse en computadoras autÃ³nomas o en computadoras que aÃºn no estÃ¡n equipadas con un servidor Web. Contiene un pequeÃ±o servidor Web incorporado para que otras computadoras en la misma red puedan tambiÃ©n acceder a la biblioteca. (Sin embargo, este servidor Web tiene una capacidad de configuraciÃ³n limitada.)</Text>
+<Text id="48">El programa de Biblioteca Local detecta automÃ¡ticamente si su computadora tiene un programa de red instalado o si estÃ¡ conectada a una red. Funciona correctamente en cualquier combinaciÃ³n de estas condiciones. No obstante, pueden plantearse eventualmente dos problemas. Greenstone puede:</Text>
+<BulletList>
+<Bullet>
+<Text id="49">provocar una operaciÃ³n no deseada de marcado telefÃ³nico;</Text>
+</Bullet>
+<Bullet>
+<Text id="50">no funcionar debido a la presencia de un programa de red instalado incorrectamente.</Text>
+</Bullet>
+</BulletList>
+<Text id="51">Se suministra una versiÃ³n limitada de la Biblioteca Local que se puede utilizar en tales situaciones. La versiÃ³n limitada sÃ³lo funciona con Netscape (pero no con Internet Explorer). Cuando se activa la versiÃ³n de la Biblioteca Local de Greenstone, en el cuadro de diÃ¡logo aparece un botÃ³n que permite seleccionar la versiÃ³n limitada. Se deberÃ¡ siempre utilizar la versiÃ³n estÃ¡ndar, a menos que se planteen los problemas antes mencionados.</Text>
+<Text id="52"><b>Biblioteca Web.</b>Â Este programa permite que cualquier computadora con un servidor Web existente distribuya colecciones Greenstone previamente creadas. Como en el caso de la Biblioteca Local, la colecciÃ³n de demostraciÃ³n de Greenstone se instalarÃ¡ automÃ¡ticamente. Se pueden instalar tambiÃ©n las demÃ¡s colecciones que figuran en el CD-ROM (vÃ©ase la SecciÃ³n <CrossRef target="Chapter" ref="greenstone_collections"/>).</Text>
+<Text id="53">La Biblioteca Web difiere de la Biblioteca Local porque estÃ¡ destinada a computadoras que ya disponen de un programa de servidor Web.</Text>
+<Text id="54">Para activar la Biblioteca Web, se requiere tambiÃ©n</Text>
+<BulletList>
+<Bullet>
+<Text id="55">Un programa de servidor Web, como por ejemplo Apache (vÃ©ase el ApÃ©ndice <CrossRef target="Chapter" ref="appendix_associated_software"/>).</Text>
+</Bullet>
+</BulletList>
+<Text id="56"><b>El Colector.</b>Â Este componente, que viene tanto en la Biblioteca Local como en la Biblioteca Web, permite crear colecciones que contengan el material elegido por usted. Para activarlo, se requiere tambiÃ©n Perl. Recomendamos ActivePerl (vÃ©ase el ApÃ©ndice). (No se podrÃ¡ utilizar el Colector con un sistema Windows 3.1 Ã³ 3.11.)</Text>
+</Content>
+</Subsection>
+<Subsection id="windows_webserver_configuration">
+<Title>
+<Text id="57">ConfiguraciÃ³n del servidor Web de Windows (en las versiones de Biblioteca Web Ãºnicamente)</Text>
+</Title>
+<Content>
+<Text id="58">Una ventaja de la versiÃ³n de la Biblioteca Local de Greenstone es que estÃ¡ lista para funcionar y no requiere ninguna configuraciÃ³n especial. Para la versiÃ³n Biblioteca Web, en cambio, tendrÃ¡ usted que hacer algunos ajustes a su instalaciÃ³n del servidor Web.</Text>
+<Text id="59">Si ya dispone usted de un servidor Web, habrÃ¡ que hacer algunos pequeÃ±os cambios en su configuraciÃ³n para que la instalaciÃ³n de Greenstone funcione correctamente. El guiÃ³n (<i>script</i>) de instalaciÃ³n explica cuÃ¡les son esos cambios para el servidor Web Apache (vÃ©ase la SecciÃ³n <CrossRef target="Section" ref="pws_and_iis_webservers"/> para las instrucciones relativas a la configuraciÃ³n de los servidores Web PWS e IIS). Es posible que necesite la ayuda de un administrador de sistema para volver a configurar un servidor Web ya instalado. Esta persona entenderÃ¡ seguramente las instrucciones del guiÃ³n de instalaciÃ³n, que pueden imprimirse.</Text>
+<Text id="60">Si no dispone usted todavÃ­a de un servidor Web, tendrÃ¡ que instalar uno (vÃ©ase el ApÃ©ndice <CrossRef target="Chapter" ref="appendix_associated_software"/> para la informaciÃ³n relativa al servidor Web Apache) y luego tendrÃ¡ que configurarlo adecuadamente. En la SecciÃ³n <CrossRef target="Chapter" ref="setting_up_webserver"/> se explica detalladamente quÃ© partes de la instalaciÃ³n de un servidor Web afectan a Greenstone y cÃ³mo deben modificarse. Esto supone incluir una media docena de lÃ­neas en un archivo de configuraciÃ³n.</Text>
+</Content>
+</Subsection>
+<Subsection id="windows_source">
+<Title>
+<Text id="61">Fuente Windows</Text>
+</Title>
+<Content>
+<Text id="62">El cÃ³digo fuente de Greenstone ocupa 50 Mb en el disco, aunque para compilarlo se necesitarÃ¡n unos 90 Mb. Para compilar la fuente en Windows se necesita</Text>
+<BulletList>
+<Bullet>
+<Text id="63">El compilador Microsoft Visual C++. (Estamos resolviendo actualmente algunos problemas menores en la compilaciÃ³n de Greenstone con varios puertos Windows de GNU GCC.)</Text>
+</Bullet>
+</BulletList>
+<Text id="64">(No se necesita el GDBM, el administrador de la base de datos de GNU, porque viene incluido en la distribuciÃ³n de Greenstone.)</Text>
+<Text id="65">Es poco probable que logre usted compilar Greenstone en una computadora que funcione con un sistema Windows 3.1 Ã³ 3.11.</Text>
+<Text id="66">En caso de que usted vuelva a compilar Greenstone y desee utilizar la versiÃ³n nuevamente compilada para crear discos CD-ROM, debe tomar nota de que el cÃ³digo producido por las versiones recientes del compilador Visual C++ no funciona con Windows 3.1 Ã³ 3.11, no habiendo en cambio problema alguno con sistemas Windows ulteriores (95, 98, Me, NT, 2000). Si desea que sus CD-ROM puedan leerse en mÃ¡quinas con sistemas Windows antiguos, se necesitarÃ¡ otra versiÃ³n del compilador. AdemÃ¡s, Greenstone utiliza STL (<i>Standard Template Library</i>), la biblioteca estÃ¡ndar de plantillas para C++, y aunque esos compiladores vienen a veces con STL, la versiÃ³n proporcionada no siempre funciona correctamente. Por consiguiente, para volver a compilar Greenstone de tal modo que produzca discos CD-ROM que funcionen con versiones antiguas de Windows, se necesita:</Text>
+<BulletList>
+<Bullet>
+<Text id="67">el compilador Microsoft Visual C++, versiÃ³n 4.0 Ã³ 4.2.</Text>
+</Bullet>
+<Bullet>
+<Text id="68">una versiÃ³n externa de STL, la biblioteca estÃ¡ndar de plantillas para C++. STL viene incluida en el sistema Greenstone para poder utilizarla con esas versiones del compilador.</Text>
+</Bullet>
+</BulletList>
+<Text id="69">Cabe seÃ±alar que el procedimiento de instalaciÃ³n de Windows no propone compilar Greenstone si se escoge instalar el cÃ³digo fuente. Para obtener instrucciones sobre la compilaciÃ³n de Greenstone relativas a su plataforma y su compilador, vÃ©ase el documentoÂ <i>Install</i>Â que aparece en el directorio principal de Greenstone (<i>C:\Program Files\gsdl</i>Â por defecto) durante el procedimiento de instalaciÃ³n.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="unix">
+<Title>
+<Text id="70">Unix</Text>
+</Title>
+<Content>
+<Text id="71">Esta secciÃ³n estÃ¡ destinada a los usuarios de Unix. (Los usuarios de Windows pueden pasar directamente a la SecciÃ³n <CrossRef target="Section" ref="how_to_find_greenstone"/>.) Tiene usted que escoger entre instalar el cÃ³digo binario o el cÃ³digo fuente. El cÃ³digo binario ocupa unos 50 Mb en el disco duro; el cÃ³digo fuente necesita unos 160 Mb para compilar.</Text>
+<Subsection id="unix_binaries">
+<Title>
+<Text id="72">Binarios Unix</Text>
+</Title>
+<Content>
+<Text id="73">El cÃ³digo binario requiere una distribuciÃ³n Linux basada en Intel x86 que incluye un soporte binario ELF. Las distribuciones que cumplen estos requisitos son:</Text>
+<BulletList>
+<Bullet>
+<Text id="74">RedHat 5.1</Text>
+</Bullet>
+<Bullet>
+<Text id="75">SuSE Linux 6.1</Text>
+</Bullet>
+<Bullet>
+<Text id="76">Debian 2.1</Text>
+</Bullet>
+<Bullet>
+<Text id="77">Slackware 4.0</Text>
+</Bullet>
+</BulletList>
+<Text id="78">Deben funcionar tambiÃ©n las versiones mÃ¡s recientes de estos productos.</Text>
+<Text id="79">Se necesitarÃ¡ un servidor Web: recomendamos Apache. Le recomendamos tambiÃ©n encarecidamente que instale su servidor WebÂ <i>antes</i>Â de instalar Greenstone, esto facilitarÃ¡ considerablemente la respuesta a las preguntas que se formulan durante el procedimiento de instalaciÃ³n de Greenstone. Si desea crear nuevas colecciones de biblioteca digital, necesitarÃ¡ tambiÃ©n Perl si Ã©ste no se encuentra ya en su sistema. Para comprobarlo, abra una ventana de terminal, tecleeÂ <i>perl -v</i>, y vea si aparece un mensaje en que se especifica, entre otras cosas, el nÃºmero de la versiÃ³n. En la mayorÃ­a de las versiones de Linux, Perl viene instalado por defecto. En el ApÃ©ndice <CrossRef target="Chapter" ref="appendix_associated_software"/> se proporciona informaciÃ³n sobre cÃ³mo obtener Apache y Perl.</Text>
+</Content>
+</Subsection>
+<Subsection id="unix_source">
+<Title>
+<Text id="80">Fuente Unix</Text>
+</Title>
+<Content>
+<Text id="81">El cÃ³digo fuente para Unix es el mismo que para Windows. Se ha compilado y probado en Linux, Solaris y Macintosh OS/X; deberÃ­a resultar sencillo adaptarlo a otras variantes de Unix.</Text>
+<Text id="82">Para compilar el cÃ³digo fuente de Greenstone en Unix, se necesita</Text>
+<BulletList>
+<Bullet>
+<Text id="83">el compilador de GNU C++, GCC</Text>
+</Bullet>
+<Bullet>
+<Text id="84">el administrador de la base de datos GNU, GDBM.</Text>
+</Bullet>
+</BulletList>
+<Text id="85">Para activar el programa Greenstone, se necesita tambiÃ©n un servidor Web y el programa Perl, como se indica mÃ¡s arriba enÂ <i>Binarios Unix</i>.</Text>
+</Content>
+</Subsection>
+<Subsection id="unix_installation">
+<Title>
+<Text id="86">InstalaciÃ³n en Unix</Text>
+</Title>
+<Content>
+<Text id="87">Para instalar la versiÃ³n destinada a Unix a partir del CD-ROM, inserte el disco en el lector y teclee</Text>
+<Table class="hidden">
+<Title/>
+<TableContent>
+<tr>
+<th width="151">
+<CodeLine>mount /cdrom</CodeLine>
+</th>
+<th width="246">
+<Text id="88">monta el dispositivo de CD-ROM (este comando puede diferir de un sistema a otro; por ejemplo, en OS/X se tecleaÂ <i>cd</i>Â en el directorioÂ <i>/Volumes</i>Â y luego se pasa al subdirectorio correspondiente al CD-ROM)</Text>
+</th>
+</tr>
+<tr>
+<th width="151">
+<CodeLine>cd /cdrom</CodeLine>
+</th>
+<th width="246">
+<Text id="89">cambia de directorio y pasa al directorio principal del CD-ROM</Text>
+</th>
+</tr>
+<tr>
+<th width="151">
+<CodeLine>cd Unix</CodeLine>
+</th>
+<th width="246">
+<Text id="90">cambia de directorio y pasa adonde se encuentra el guiÃ³n de instalaciÃ³n para Unix</Text>
+</th>
+</tr>
+<tr>
+<th width="151">
+<CodeLine>sh Install.sh</CodeLine>
+</th>
+<th width="246">
+<Text id="91">inicia el proceso de instalaciÃ³n (se utiliza unÂ <i>sh</i>Â explÃ­cito porque muchas instalaciones prohiben la ejecuciÃ³n de programas directamente a partir del CD-ROM)</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="92">Este Ãºltimo comando inicia un diÃ¡logo interactivo en que se le pregunta a usted la informaciÃ³n necesaria para instalar Greenstone en su sistema, proporcionando datos precisos sobre las operaciones efectuadas.</Text>
+<Text id="93">El procedimiento de instalaciÃ³n comienza preguntÃ¡ndole en quÃ© directorio quiere usted instalar Greenstone. El primer archivo que se instala allÃ­ es el programa de âdesinstalaciÃ³nâ que despeja toda instalaciÃ³n parcial, en caso de que se topara usted con problemas o terminara la instalaciÃ³n prematuramente. A continuaciÃ³n, usted escoge si quiere instalar los binarios o el cÃ³digo fuente. Luego se formulan algunas preguntas sobre la instalaciÃ³n de su servidor Web. Es necesario tener un directorio de CGI ejecutable vÃ¡lido (que en los sistemas Unix suele llamarse â<i>cgi-bin</i>Â â); puede usted crear uno o utilizar el existente. En caso de crear uno nuevo, serÃ¡ necesario que introduzca esta informaciÃ³n en el archivo de configuraciÃ³n de su servidor Web. En cualquier caso, es necesario introducir la direcciÃ³n Web del directorio CGI. El diÃ¡logo de instalaciÃ³n lo guiarÃ¡ a travÃ©s de todas estas opciones. Es importante establecer correctamente los permisos de archivo en determinados directorios, y se le invita a proporcionar la informaciÃ³n necesaria. Por Ãºltimo, se le invita a escoger una clave de acceso para el usuario âadministradorâÂ <i>admin</i>.</Text>
+<Text id="94">Todo el programa Greenstone se instala por defecto en el directorioÂ <i>/usr/local/gsdl</i>Â si es el usuarioÂ <i>root</i>Â quien efectÃºa la instalaciÃ³n, y de otro modo en el directorioÂ <i>~/gsdl</i>Â (en que â~â es el directorio principal del usuario).</Text>
+<Text id="95">La instalaciÃ³n de los binarios tarda apenas unos minutos, tiempo suficiente para que usted responda a las preguntas correspondientes. Si usted instala el cÃ³digo fuente, el guiÃ³n de instalaciÃ³n lo compilarÃ¡, lo cual lleva entre diez minutos y una hora, segÃºn la velocidad de su procesador.</Text>
+<Text id="96">Para desinstalar el programa, teclee</Text>
+<CodeLine>cd ~/gsdl</CodeLine>
+<Text id="97">o bien /usr/local/gsdl si quien instalÃ³ Greenstone fue el usuarioÂ <i>root</i></Text>
+<CodeLine>sh Uni nstall.sh</CodeLine>
+<Text id="98">Durante el procedimiento de instalaciÃ³n se le preguntarÃ¡ si quiere usted instalar alguna colecciÃ³n Greenstone. La colecciÃ³n de demostraciÃ³n Greenstone se instala automÃ¡ticamente; las demÃ¡s colecciones que figuran en el CD-ROM se describen en la SecciÃ³n <CrossRef target="Chapter" ref="greenstone_collections"/>.</Text>
+</Content>
+</Subsection>
+<Subsection id="unix_webserver_configuration">
+<Title>
+<Text id="99">ConfiguraciÃ³n del servidor Web para Unix</Text>
+</Title>
+<Content>
+<Text id="100">Si ya dispone usted de un servidor Web, tendrÃ¡ que hacerle algunos pequeÃ±os cambios en su configuraciÃ³n para poder instalar Greenstone. El guiÃ³n de instalaciÃ³n explica en quÃ© consisten. Es probable que necesite la ayuda del administrador del sistema para volver a configurar el servidor Web; esta persona comprenderÃ¡ seguramente las instrucciones que figuran en el guiÃ³n de instalaciÃ³n y que pueden imprimirse. Para su conveniencia, la informaciÃ³n imprimible del guiÃ³n de instalaciÃ³n estÃ¡ escrita en un archivo llamadoÂ <i>INSTALL_RECORD</i>Â situado en el directorio en que usted instalÃ³ Greenstone.</Text>
+<Text id="101">Si no dispone usted todavÃ­a de un servidor Web, tendrÃ¡ que instalar uno. En el ApÃ©ndice <CrossRef target="Chapter" ref="appendix_associated_software"/> se proporciona informaciÃ³n sobre Apache. DespuÃ©s tendrÃ¡ que configurarlo adecuadamente. En la SecciÃ³n <CrossRef target="Chapter" ref="setting_up_webserver"/> se explica detalladamente quÃ© partes de la instalaciÃ³n de un servidor Web Apache afectan a Greenstone y cÃ³mo hay que modificarlas. Ello supone incluir una media docena de lÃ­neas en un archivo de configuraciÃ³n.</Text>
+<Text id="102">No es necesario que sea usted el usuario â<i>root</i>Â â de Unix para ejecutar el procedimiento de instalaciÃ³n antes expuesto. Sin embargo, tratÃ¡ndose de la configuraciÃ³n de un servidor Apache, serÃ¡ preciso disponer de privilegios de â<i>root</i>Â â, todo depende de cÃ³mo se instale Apache. Si instala Apache usted mismo, puede hacerlo como un usuario carente de privilegios de â<i>root</i>Â â. Si resulta necesario eludir un administrador de sistema poco dispuesto a cooperar, es posible instalar en su computadora un segundo servidor Web Apache, aun si ya existe uno.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="how_to_find_greenstone">
+<Title>
+<Text id="103">CÃ³mo encontrar Greenstone</Text>
+</Title>
+<Content>
+<Subsection id="local_library_windows_only">
+<Title>
+<Text id="104">Biblioteca Local (sÃ³lo con Windows)</Text>
+</Title>
+<Content>
+<Text id="105">Si estÃ¡ utilizando la Biblioteca Local, ejecute simplemente el programa Greenstone a partir del menÃº deÂ <i>Inicio</i>. Esto activa automÃ¡ticamente su navegador Internet y carga la pÃ¡gina principal de la Biblioteca Digital Greenstone. A partir de esta pÃ¡gina se podrÃ¡ tener acceso a la colecciÃ³n de demostraciÃ³n de Greenstone. </Text>
+</Content>
+</Subsection>
+<Subsection id="web_library_windows_and_unix">
+<Title>
+<Text id="106">Biblioteca Web (Windows y Unix)</Text>
+</Title>
+<Content>
+<Text id="107">Si estÃ¡ utilizando la Biblioteca Web, una vez instalado el programa y configurado el servidor Web, utilice esta URL para entrar en su sistema Greenstone:</Text>
+<Text id="108"><i>http://localhost/gsdl/cgi-bin/library</i></Text>
+<Text id="109">A partir de esta pÃ¡gina se podrÃ¡ tener acceso a la colecciÃ³n de demostraciÃ³n de Greenstone.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_collector">
+<Title>
+<Text id="110">El Colector</Text>
+</Title>
+<Content>
+<Text id="111">En la pÃ¡gina principal de la biblioteca digital figura un enlace hacia el Colector.</Text>
+</Content>
+</Subsection>
+<Subsection id="administration">
+<Title>
+<Text id="112">AdministraciÃ³n</Text>
+</Title>
+<Content>
+<Text id="113">En la pÃ¡gina principal de la biblioteca digital figura un enlace hacia las pÃ¡ginas de AdministraciÃ³n. El usuario âadministradorâ se llamaÂ <i>admin</i>, con una clave de acceso que usted escogiÃ³ durante el proceso de instalaciÃ³n. El administrador estÃ¡ autorizado a aÃ±adir nuevos usuarios y a crear colecciones.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="section_la_interfaz_de_bibliotecario_de_greenstone_(gli)">
+<Title>
+<Text id="114">La Interfaz de Bibliotecario de Greenstone (GLI)</Text>
+</Title>
+<Content>
+<Text id="115">La Interfaz de Bibliotecario de Greenstone (GLI por sus siglas en inglÃ©s) es una herramienta grÃ¡fica que le ayuda a construir bibliotecas digitales dÃ¡ndole acceso a todas las funciones de Greenstone por medio de una interfaz fÃ¡cil de usar con la que sÃ³lo tiene que apuntar y hacer click.</Text>
+<Text id="116">GLI se instala automÃ¡ticamente con todas las versiones de Greenstone en el subdirectorioÂ <i>gli</i>Â del directorio principal de la biblioteca digital (<i>C:\Program Files\gsdl\gli</i>Â por omisiÃ³n). Recuerde que la interfaz corre en conjunto con los programas de Greenstone y no funcionarÃ¡ adecuadamente a menos que se encuentre en un subdirectorio de Greenstone. Si usted ya bajÃ³ alguna de las versiones de Greenstone, entonces Ã©ste serÃ¡ el caso.</Text>
+<Text id="117">Para poder usar la GLI su computadora deberÃ¡ contar con el Ambiente de EjecuciÃ³n Java. Si todavÃ­a no lo tiene, el programa de instalaciÃ³n se ofrecerÃ¡ a instalar la versiÃ³n que estÃ© incluida en el CD-ROM. En el caso de UNIX tambiÃ©n deberÃ¡ asegurarse de que Perl estÃ© instalado (en el caso de Windows Perl ya viene incluido en el software Greenstone). Por favor infÃ³rmenos sobre cualquier problema que tenga al correr o usar la Interfaz de Bibliotecario a la siguiente direcciÃ³n:Â <u>greenstone@cs.waikato.ac.nz</u>.</Text>
+<Subsection id="running_under_windows">
+<Title>
+<Text id="118">EjecuciÃ³n bajo Windows</Text>
+</Title>
+<Content>
+<Text id="119">Para correr la GLI bajo Windows explore la carpetaÂ <i>gli</i>Â que se encuentra en su instalaciÃ³n de Greenstone (por ejemplo usando el Explorador de Windows) y haga doble click en el archivoÂ <i>gli.bat</i>. Este archivo verificarÃ¡ que Greenstone, el Ambiente de EjecuciÃ³n Java y Perl estÃ¡n instalados e iniciarÃ¡ la Interfaz de Bibliotecario.</Text>
+</Content>
+</Subsection>
+<Subsection id="running_under_unix">
+<Title>
+<Text id="120">EjecuciÃ³n bajo UNIX</Text>
+</Title>
+<Content>
+<Text id="121">Para correr la GLI bajo UNIX cambie al directorioÂ <i>gli</i>Â que se encuentra en su instalaciÃ³n de Greenstone y ejecute el guiÃ³nÂ <i>gli.sh</i>. Este guiÃ³n verificarÃ¡ que Greenstone, el Ambiente de EjecuciÃ³n Java y Perl estÃ©n instalados y en su ruta de bÃºsqueda e iniciarÃ¡ la Interfaz de Bibliotecario.</Text>
+</Content>
+</Subsection>
+<Subsection id="getting_help">
+<Title>
+<Text id="122">CÃ³mo obtener ayuda</Text>
+</Title>
+<Content>
+<Text id="123">La Interfaz de Bibliotecario de Greenstone cuenta con una extensa variedad de opciones de ayuda en lÃ­nea. Usted puede obtenerla haciendo click en el botÃ³nÂ <i>Ayuda</i>Â que se encuentra en la parte superior derecha de la pantalla. Esto abrirÃ¡ una secciÃ³n relacionada con lo que usted estÃ© haciendo, es decir, con el panel GLI en el que usted se encuentre en ese momento. Una vez abierta haga click en la parte del texto de ayuda sobre la que usted quiera saber mÃ¡s. Ãsela. Â¡Se la recomendamos!</Text>
+</Content>
+</Subsection>
+<Subsection id="compiling_gli">
+<Title>
+<Text id="124">Compilando la Interfaz de Bibliotecario de Greenstone</Text>
+</Title>
+<Content>
+<Text id="125">Si usted bajÃ³ la versiÃ³n con el cÃ³digo fuente de Greenstone, entonces tendrÃ¡ con usted el cÃ³digo fuente Java de la Interfaz de Bibliotecario. Para compilarlo su computadora necesitarÃ¡ contar con una versiÃ³n adecuada del Kit de Desarrollo de Software Java. En el ApÃ©ndice <CrossRef target="Chapter" ref="appendix_associated_software"/> usted encontrarÃ¡ mayor informaciÃ³n sobre la forma de obtenerla. Para compilar el cÃ³digo fuente ejecute los archivosÂ <i>makegli.bat</i>Â (Windows) oÂ <i>makegli.sh</i>Â (UNIX). Una vez que haya hecho esto usted podrÃ¡ correr la GLI tal como se describe arriba.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="testing_and_troubleshooting">
+<Title>
+<Text id="126">Pruebas y soluciÃ³n de problemas</Text>
+</Title>
+<Content>
+<Text id="127">Para probar Greenstone, dirija su navegador Web hacia la pÃ¡gina principal de Greenstone y explore la colecciÃ³n de demostraciÃ³n y cualquier otra colecciÃ³n que haya usted instalado. No se preocupe, no va a romper nada. Pulse libremente: se puede hacer clic en la mayorÃ­a de las imÃ¡genes que aparecen en la pantalla. Si se mantiene el cursor quieto sobre una imagen, en la mayorÃ­a de los navegadores aparece un mensaje en que se explica lo que sucederÃ¡ si se hace clic. Â¡Experimente y verÃ¡! Elija palabras comunes como â<i>the</i>Â â (el) y â<i>and</i>Â â (y) para ejercitarse en la bÃºsqueda y no tema, que nada se va a romper. Para mÃ¡s informaciÃ³n, vÃ©ase laÂ <i>GuÃ­a del Usuario de la Biblioteca Digital Greenstone</i>.</Text>
+<Subsection id="troubleshooting">
+<Title>
+<Text id="128">SoluciÃ³n de problemas</Text>
+</Title>
+<Content>
+<Table id="table_troubleshooting">
+<Title/>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="129">Problema</Text>
+</th>
+<th width="246">
+<Text id="130">SoluciÃ³n posible</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="131">Biblioteca local (sÃ³lo con Windows)</Text>
+</th>
+<th width="151">
+<Text id="132">Cuando arranco el programa Greenstone mi computadora me invita a conectarme a mi proveedor de servicio Internet. </Text>
+</th>
+<th width="246">
+<Text id="133">Pulse el botÃ³nÂ <i>Cancelar</i>Â en el cuadro de diÃ¡logo. Esto suele resolver el problema.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="134">Cuando arranco el programa Greenstone mi computadora meÂ <i>sigue invitando</i>Â a conectarme a mi proveedor de servicio Internet.</Text>
+</th>
+<th width="246">
+<Text id="135">Escoja la âversiÃ³n limitadaâ cuando active Greenstone. Esta versiÃ³n sÃ³lo funciona con Netscape.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="136">Cuando dirijo mi navegador hacia la Biblioteca Digital, no puede encontrar esa pÃ¡gina.</Text>
+</th>
+<th width="246">
+<Text id="137">Verifique su configuraciÃ³n de Internet Proxy y desconecte los proxies (utiliceÂ <i>Edit preferences</i>Â en Netscape oÂ <i>Internet options</i>Â en Explorer).</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="138">Â¡El Colector parece estar funcionando muy lentamente!</Text>
+</th>
+<th width="246">
+<Text id="139">Â¿EstÃ¡ usted utilizando Netscape con Windows 2000? En ese caso, intente utilizar mÃ¡s bien Internet Explorer. Parece haber cierta incompatibilidad entre Netscape y Windows 2000.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="142">Biblioteca Web (Windows y Unix)</Text>
+</th>
+<th width="151">
+<Text id="143">Cuando arranco Apache, se cierra de inmediato.</Text>
+</th>
+<th width="246">
+<Text id="144">AÃ±ada en el archivo de configuraciÃ³n de Apache una directivaÂ <i>ServerName localhost</i>Â (vÃ©ase SecciÃ³n <CrossRef target="Section" ref="apache_web_server"/>).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">Â </th>
+<th width="151">
+<Text id="145">Cuando dirijo mi navegador a la biblioteca digital, aparece un archivo binario.</Text>
+</th>
+<th width="246">
+<Text id="146">Verifique la directivaÂ <i>ScriptAlias</i>Â en el archivo de configuraciÃ³n de Apache y cerciÃ³rese de que aparece antes de la directivaÂ <i>Alias</i>Â (vÃ©ase Secciones 4.2 y 4.3).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">Â </th>
+<th width="151">
+<Text id="147">Logro llegar a la pÃ¡gina principal de Greenstone (Figura <CrossRef target="Figure" ref="your_greenstone_home_page"/>), pero el icono de la colecciÃ³n de demostraciÃ³n no aparece.</Text>
+</th>
+<th width="246">
+<Text id="148">Abra el programaÂ <i>library</i>Â (en el directorioÂ <i>cgi-bin</i>) a partir del indicador de DOS (o del âshellâ) para obtener informaciÃ³n sobre depuraciÃ³n que le ayudarÃ¡ a localizar el problema.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="149">Ambas versiones</Text>
+</th>
+<th>
+<Text id="150">Cuando dirijo mi navegador hacia la Biblioteca Digital, no puede encontrar esa pÃ¡gina.</Text>
+</th>
+<th>
+<Text id="151">Intente utilizar 127.0.0.1 en lugar deÂ <i>localhost</i>. Este nÃºmero IP reservado se define como un âbucle de retrocesoâ hacia su computadora local.</Text>
+</th>
+</tr>
+<tr>
+<th>Â </th>
+<th>
+<Text id="152">Mi navegador se queja de que no puede encontrarÂ <i>main.cfg</i>.</Text>
+</th>
+<th>
+<Text id="153">Verifique que los archivos de Greenstone existen y que son legibles por todos. Si estÃ¡ usando la biblioteca Web, intente activar el programaÂ <i>library</i>Â a partir de la lÃ­nea de comandos. Si funciona bien, el problema es con los permisos de archivo (vÃ©ase la SecciÃ³n <CrossRef target="Section" ref="file_permissions"/>). En caso contrario, es probable que la variableÂ <i>gsdlhome</i>Â estÃ© configurada incorrectamente en el archivo de configuraciÃ³nÂ <i>gsdlsite.cfg</i>Â (vÃ©ase la SecciÃ³n <CrossRef target="Section" ref="gsdlsite_configuration_file"/>).</Text>
+</th>
+</tr>
+<tr>
+<th>Â </th>
+<th>
+<Text id="154">Tengo problemas con la utilizaciÃ³n del Colector.</Text>
+</th>
+<th>
+<Text id="155">Lea la GuÃ­a del Usuario de la Biblioteca Digital Greenstone, SecciÃ³n <CrossRef external="User" lang="es" target="Chapter" ref="making_greenstone_collections"/>.</Text>
+</th>
+</tr>
+<tr>
+<th>Â </th>
+<th>
+<Text id="156">He aÃ±adido un nuevo usuario, pero no parece poder iniciar la sesiÃ³n.</Text>
+</th>
+<th>
+<Text id="157">Verifique que el directorioÂ <i>C:\Program Files\gsdl\etc</i>Â y todo su contenido son modificables (vÃ©ase SecciÃ³n <CrossRef target="Section" ref="file_permissions"/>).</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="learn_more">
+<Title>
+<Text id="158">Para obtener mÃ¡s informaciÃ³n</Text>
+</Title>
+<Content>
+<Text id="159">Para obtener mÃ¡s informaciÃ³n sobre los entresijos de su instalaciÃ³n Greenstone, consulte laÂ <i>GuÃ­a del Programador de la Biblioteca Digital Greenstone</i>, que comprende, entre otras cosas, los detalles sobre la estructura de los directorios que se ha creado e informaciÃ³n sobre cÃ³mo configurar su sitio Greenstone.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="greenstone_collections">
+<Title>
+<Text id="160">COLECCIONES GREENSTONE</Text>
+</Title>
+<Content>
+<Text id="161">El CD-ROM incluye varias colecciones Greenstone de muestra. Si usted tiene acceso a Internet tambiÃ©n podrÃ¡ bajar muchas otras desde el sitio Web del Proyecto de Biblioteca Digital de Nueva Zelanda (<i>nzdl.org</i>), ya sea armadas previamente o sin armar.</Text>
+<Text id="162">La colecciÃ³n de muestra Greenstone es un pequeÃ±o subconjunto de la Biblioteca para el Desarrollo Humano (HDL por sus siglas en inglÃ©s), una colecciÃ³n perfectamente acabada que muestra la forma en que se puede lograr una amplia capacidad de exploraciÃ³n y bÃºsqueda (siempre que se cuente con los metadatos adecuados). Esta colecciÃ³n se incluye automÃ¡ticamente al momento de instalar el software.</Text>
+<Text id="163">Greenstone tambiÃ©n incluye otros ejemplos de colecciones documentadas cuyas pÃ¡ginas informativas describen la forma en que estÃ¡n construidas, demostrando las diferentes capacidades de Greenstone. Un cuadro de diÃ¡logo le preguntarÃ¡ si quiere incluirlas junto con su instalaciÃ³n. La cantidad aproximada de espacio de disco que se necesita para cada una se muestra a continuaciÃ³n.</Text>
+<Table class="hidden" id="table_collections">
+<Title/>
+<TableContent>
+<tr>
+<th>
+<Text id="164"><i>demo</i></Text>
+</th>
+<th>
+<Text id="165">ColecciÃ³n de muestra GreenstoneÂ <br/>(7Â Mb)</Text>
+</th>
+<th>
+<Text id="166">Un pequeÃ±o subconjunto de la Biblioteca para el Desarrollo Humano (HDL por sus siglas en inglÃ©s). Si se clona esta colecciÃ³n las funciones completas sÃ³lo estarÃ¡n disponibles si sus nuevos archivos proporcionan la informaciÃ³n de metadatos apropiada.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="167"><i>dls-e</i></Text>
+</th>
+<th>
+<Text id="168">Subconjunto de la Biblioteca para el DesarrolloÂ <br/>(150 Mb)</Text>
+</th>
+<th>
+<Text id="169">Al igual que la ColecciÃ³n de muestra Greenstone, Ã©sta es un subconjunto de la Biblioteca para el Desarrollo Humano, sÃ³lo que mucho mayor. Contiene 250 publicaciones entre libros, informes y revistas relacionadas con diferentes Ã¡reas del saber humano (la HDL contiene un total de 1,230 publicaciones). Tiene la misma estructura que la ColecciÃ³n de muestra Greenstone y es bastante compleja, por lo que si apenas estÃ¡ empezando a familiarizarse con su uso quizÃ¡ sea mejor que se fije primero en alguna otra (p. ej. laÂ <i>demostraciÃ³n en MSWord y PDF</i>, losÂ <i>Archivos Greenstone</i>Â o laÂ <i>colecciÃ³n de ImÃ¡genes Sencillas</i>).</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="170"><i>wrdpdf-e</i></Text>
+</th>
+<th>
+<Text id="171">DemostraciÃ³n en MSWord y PDFÂ <br/>(4 Mb)</Text>
+</th>
+<th>
+<Text id="172">Esta colecciÃ³n contiene unos cuantos documentos en formatos PDF, MSWord, RTF y PostScript, y muestra la capacidad de construir colecciones a partir de diferentes tipos de documentos. El archivo de configuraciÃ³n de la colecciÃ³n es sumamente sencillo.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="173"><i>gsarch-e</i></Text>
+</th>
+<th>
+<Text id="174">ColecciÃ³n de Archivos GreenstoneÂ <br/>(5 Mb)</Text>
+</th>
+<th>
+<Text id="175">Una colecciÃ³n de mensajes de correo electrÃ³nico hecha a partir de los archivos de las listas de correo de Greenstone. Utiliza el pluginÂ <i>Email</i>Â que descompone y analiza los archivos en formatos de correo electrÃ³nico. El archivo de configuraciÃ³n de la colecciÃ³n es sumamente sencillo.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="176"><i>cltbib-e</i></Text>
+</th>
+<th>
+<Text id="177">ColecciÃ³n bibliogrÃ¡ficaÂ <br/>(7 Mb)</Text>
+</th>
+<th>
+<Text id="178">Con aproximadamente 4,000 entradas bibliogrÃ¡ficas, esta colecciÃ³n incorpora una interfase de bÃºsqueda basada en formas que permite la bÃºsqueda por campos. Es bastante compleja.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="179"><i>cltext-e</i></Text>
+</th>
+<th>
+<Text id="180">Suplemento bibliogrÃ¡ficoÂ <br/>(1 Mb)</Text>
+</th>
+<th>
+<Text id="181">Esta pequeÃ±a colecciÃ³n de 10 entradas bibliogrÃ¡ficas ilustra el programa âsupercolecciÃ³nâ de Greenstone, el cual busca en varias colecciones al mismo tiempo. Opera junto con la colecciÃ³nÂ <i>BibliogrÃ¡fica</i>Â y su archivo de configuraciÃ³n es casi idÃ©ntico.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="182"><i>MARC-e</i></Text>
+</th>
+<th>
+<Text id="183">ColecciÃ³n de muestra MARCÂ <br/>(1 Mb)</Text>
+</th>
+<th>
+<Text id="184">Basada en algunos registros MARC de la Biblioteca del Congreso, Ã©sta es una colecciÃ³n sencilla, aunque no permite la bÃºsqueda basada en formas.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="185"><i>oai-e</i></Text>
+</th>
+<th>
+<Text id="186">ColecciÃ³n de muestra OAIÂ <br/>(18 Mb)</Text>
+</th>
+<th>
+<Text id="187">Por medio del Protocolo de Archivo Abierto y la funciÃ³nÂ <i>Import-From</i>, Ã©sta recupera metadatos de un archivo y construye una colecciÃ³n a partir de los registros. En este caso se trata de imÃ¡genes, por lo que se utilizan tanto el plugin OAI como el pluginÂ <i>ImagePlug</i>.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="188"><i>image-e</i></Text>
+</th>
+<th>
+<Text id="189">ColecciÃ³n de imÃ¡genes sencillasÂ <br/>(1 Mb)</Text>
+</th>
+<th>
+<Text id="190">Esta colecciÃ³n de imÃ¡genes es sumamente bÃ¡sica y no contiene texto ni metadatos explÃ­citos, lo que mÃ¡s bien la hace poco prÃ¡ctica. El archivo de configuraciÃ³n es lo mÃ¡s simple que se puede encontrar.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="191"><i>authen-e</i></Text>
+</th>
+<th>
+<Text id="192">DemostraciÃ³n de formateo y autenticaciÃ³nÂ <br/>(8 Mb)</Text>
+</th>
+<th>
+<Text id="193">Con el mismo material que la colecciÃ³n de muestra Greenstone original, Ã©sta muestra dos funciones independientes: el formateo de documentos que no sean estÃ¡ndar y el acceso controlado a los documentos por medio de la autenticaciÃ³n de los usuarios.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="194"><i>garish</i></Text>
+</th>
+<th>
+<Text id="195">VersiÃ³n Garish de la colecciÃ³n de muestraÂ <br/>(8 Mb)</Text>
+</th>
+<th>
+<Text id="196">Esta colecciÃ³n tambiÃ©n contiene el mismo material que la colecciÃ³n de muestra Greenstone, sÃ³lo que su apariencia ha sido alterada para mostrar la forma en que las pÃ¡ginas generadas pueden configurarse de manera diferente. Se basa en un archivo de macros no estÃ¡ndar que se proporciona junto con Greenstone.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="197"><i>Isis-e</i></Text>
+</th>
+<th>
+<Text id="198">ColecciÃ³n de muestra CDS/ISIS (1 Mb)</Text>
+</th>
+<th>
+<Text id="199">Esta colecciÃ³n estÃ¡ construida a partir de una base de datos CDS/ISIS de cerca de 150 referencias bibliogrÃ¡ficas. Usa el plugin ISISPlug, el cual lee archivos estÃ¡ndar ISIS (.mst y .fdt) y los convierte a metadatos de Greenstone.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Chapter>
+<Chapter id="setting_up_webserver">
+<Title>
+<Text id="200">InstalaciÃ³n del servidor Web</Text>
+</Title>
+<Content>
+<Text id="201">En esta secciÃ³n explicaremos cÃ³mo instalar su servidor Web para que funcione con Greenstone. Cabe seÃ±alar que estas explicaciones son innecesarias cuando se utiliza la Biblioteca Local Windows, ya que este programa estÃ¡ concebido para funcionar de entrada sin servidor Web.</Text>
+<Text id="202">Nos referiremos al servidor Web Apache, que se puede conseguir libremente para Windows y Unix (vÃ©ase el ApÃ©ndice <CrossRef target="Chapter" ref="appendix_associated_software"/> para mÃ¡s detalles), el Personal Web Server (PWS) y el servidor Web Internet Information Services (IIS) de Microsoft. El PWS es el servidor Microsoft estÃ¡ndar para Windows 95/98; el IIS es el de las versiones 2000 y XP de Windows; Windows NT puede utilizar cualquiera de los dos. Las explicaciones relativas a Apache se aplican igualmente a la biblioteca Web Windows y a las versiones de Unix (aunque utilizamos la terminologÃ­a y los nombres de las rutas de acceso propios de Windows); la secciÃ³n relativa a PWS/IIS sÃ³lo se aplica a la biblioteca Web Windows.</Text>
+<Text id="203">Una vez instalado el servidor Web, el siguiente paso es instalar Greenstone. Supondremos que durante el procedimiento de instalaciÃ³n usted ha escogido la opciÃ³n por defecto en cada fase pulsando el botÃ³nÂ <i>Next</i>Â (siguiente). El resultado es la creaciÃ³n del directorioÂ <i>C:\Program Files\gsdl</i>, donde se instala el binario de la biblioteca Web, junto con algunos archivos auxiliares.</Text>
+<Text id="204">Todos los servidores Web utilizan la URL especial âlocalhostâ que representa la computadora en que estÃ¡ funcionando el servidor Web. AsÃ­, cuando se instala un servidor Web, se puede acceder a los documentos HTML tecleando la URLÂ <i>http://localhost</i>Â en un navegador. Si su computadora tiene instalado un nombre de dominio, Ã©ste se utiliza en lugar delÂ <i>localhost</i>Â para poder identificar su computadora desde sitios remotos. En la computadora de la Biblioteca Digital de Nueva Zelanda, por ejemplo, las URLÂ <i>http://nzdl.org</i>Â yÂ <i>http://localhost</i>Â son equivalentes. Si usted tecleaÂ <i>http://nzdl.org</i>Â en su computadora obtendrÃ¡ el servidor Web de la Biblioteca Digital de Nueva Zelanda, mientras que si tecleaÂ <i>http://localhost</i>Â obtendrÃ¡ el servidor Web de su propia computadora.</Text>
+<Section id="apache_web_server">
+<Title>
+<Text id="205">El servidor Web Apache</Text>
+</Title>
+<Content>
+<Text id="206">El servidor Web Apache suele instalarse enÂ <i>C:\Program Files\Apache Group\Apache</i>Â y se configura de tal modo que el directorioÂ <i>cgi-bin</i>Â estÃ© en el subdirectorioÂ <i>\cgi-bin</i>Â y la raÃ­z de documentos es el subdirectorioÂ <i>\htdocs</i>. Se vuelve a configurar modificando el archivo de configuraciÃ³n enÂ <i>C:\Program Files\Apache Group\Apache\conf\httpd.conf</i>. Se trata de un archivo de texto: es muy fÃ¡cil leerlo para ver cÃ³mo se ha efectuado la configuraciÃ³n.</Text>
+<Text id="207">SegÃºn cÃ³mo estÃ© configurado el programa de conexiÃ³n en red de su computadora, podrÃ¡ ser necesario aÃ±adir la siguiente lÃ­nea en su archivo de configuraciÃ³nÂ <i>httpd.conf</i>Â de Apache:</Text>
+<CodeLine>ServerNameÂ  localhost</CodeLine>
+<Text id="208">Si esta lÃ­nea no figura, el sistema intenta encontrar el nombre de su servidor. Sin embargo, en algunas versiones de Windows hay algunos errores que impiden esta operaciÃ³n. En tal caso, Apache se cierra inmediatamente despuÃ©s de arrancarlo. Aparece un mensaje de error, pero Ã©ste se borra de inmediato y es muy probable que usted no lo alcance a leer.</Text>
+<Subsection id="setting_up_cgi-bin_directory">
+<Title>
+<Text id="209">InstalaciÃ³n del directorioÂ <i>cgi-bin</i>Â de Greenstone</Text>
+</Title>
+<Content>
+<Text id="210"><i>cgi-bin</i>Â es un directorio desde el cual el servidor Web trata documentos como programas ejecutables. La directivaÂ <i>ScriptAlias</i>Â de Apache se utiliza para crear un directorioÂ <i>cgi-bin</i>. Cabe seÃ±alar que esta directiva puede hacer de cualquier directorio un directorio CGI ejecutable, Â¡sin que se llame forzosamente âcgi-binâ! A la inversa, un directorio llamado âcgi-binâ no tiene nada especial si no se le ha aplicado la directivaÂ <i>ScriptAlias</i>.</Text>
+<Text id="211">Una vez instalado, Apache tiene un directorio cgi-bin en C:\Program Files\Apache Group\Apache\cgi-bin. Esto significa que si se le presenta la URL <i>http://localhost/cgi-bin/hello</i>, el servidor Web intentarÃ¡ ejecutar un archivo llamado hello en el directorio antes mencionado.</Text>
+<Text id="212">Hay un programa Greenstone, llamado â<i>library.exe</i>Â â, que tiene que ser ejecutado por el servidor Web y que a su vez lee un archivo llamado el archivo de configuraciÃ³n de sitio de Greenstone, o â<i>gsdlsite.cfg</i>Â â, que debe estar situado en el mismo directorio.</Text>
+<Text id="213">La mejor manera de obtener este resultado es utilizar la directivaÂ <i>ScriptAlias</i>Â de Apache para crear un nuevo directorioÂ <i>cgi-bin</i>. Este es el pasaje del archivo de configuraciÃ³nÂ <i>httpd.conf</i>Â de Apache que aÃ±adeÂ <i>C:\Program Files\gsdl\cgi-bin</i>Â como un directorioÂ <i>cgi-bin</i>Â suplementario:</Text>
+<CodeLine>ScriptAlias /gsdl/cgi-bin/ âC:/Program Files/gsdl/cgi-binâ</CodeLine>
+<CodeLine>&lt;Directory C:/Program Files/gsdl/cgi-bin&gt;</CodeLine>
+<CodeLine>Â  Options None</CodeLine>
+<CodeLine>Â  AllowOverride None</CodeLine>
+<CodeLine>&lt;/Directory&gt;</CodeLine>
+<Text id="214">(Curiosamente, los archivos de configuraciÃ³n de Apache utilizan barras oblicuas hacia adelante en lugar de las barras oblicuas hacia atrÃ¡s que se suelen utilizar en Windows.)</Text>
+<Text id="215">Esto significa que el servidor Web buscarÃ¡ en el directorioÂ <i>C:\Program Files\gsdl\cgi-bin</i>Â cualquier URL que tenga la formaÂ <i>http://localhost/gsdl/cgi-bin</i>... y la ejecutarÃ¡. Por ejemplo, si se le presenta la URLÂ <i>http://localhost/gsdl/cgi-bin/hello</i>, el servidor Web intentarÃ¡ recuperar el archivoÂ <i>C:\Program Files\gsdl\cgi-bin\hello</i>Â y ejecutarlo. Sin embargo, la URLÂ <i>http://localhost/cgi-bin/hello</i>Â busca en el directorioÂ <i>cgi-bin</i>Â normal de Apache el archivoÂ <i>C:\Program Files\Apache Group\Apache\cgi-bin\hello</i>Â y lo ejecuta, tal como lo hizo antes.</Text>
+</Content>
+</Subsection>
+<Subsection id="document_root_directory">
+<Title>
+<Text id="216">El directorio raÃ­z de los documentos</Text>
+</Title>
+<Content>
+<Text id="217">El directorio raÃ­z de los documentos es la raÃ­z de la estructura de directorios de su servidor Web. Una vez instalado, Apache dispone como raÃ­z de documentos deÂ <i>C:\Program Files\Apache Group\Apache\htdocs</i>. Esto significa que si se le presenta la URLÂ <i>http://localhost/hello.html</i>, el servidor Web intentarÃ¡ recuperar un archivo llamadoÂ <i>hello.html</i>Â desde dentro del directorio antes mencionado.</Text>
+<Text id="218">Greenstone contiene varios archivos que el servidor Web tiene que leer. La manera mÃ¡s sencilla de proceder es utilizando la directivaÂ <i>Alias</i>, que es comoÂ <i>ScriptAlias</i>Â salvo que se aplica a las pÃ¡ginas Web ordinarias, no a los guiones CGI. Inserte las siguientes lÃ­neas en su archivo de configuraciÃ³n Apache, despuÃ©s de la directivaÂ <i>ScriptAlias</i>, a fin de aÃ±adirÂ <i>C:\Program Files\gsdl</i>Â como lugar suplementario donde buscar documentos.</Text>
+<CodeLine>Alias /gsdl/Â  âC:/Program Files/gsdl/â</CodeLine>
+<CodeLine>&lt;Directory C:/Program Files/gsdl&gt;</CodeLine>
+<CodeLine>Â  Options Indexes MultiViews FollowSymLinks</CodeLine>
+<CodeLine>Â  AllowOverride None</CodeLine>
+<CodeLine>Â  Order allow, deny</CodeLine>
+<CodeLine>Â  Allow from all</CodeLine>
+<CodeLine>&lt;/Directory&gt;</CodeLine>
+<Text id="219">Esto significa que cualquier URL que se ajuste al primer argumento de la directivaÂ <i>Alias</i>Â (gsdl) se busca como archivo en el lugar correspondiente al segundo argumento. Dicho de otro modo, las URL con la formaÂ <i>http://localhost/gsdl/...</i>Â se buscarÃ¡n como archivos en el directorioÂ <i>C:\Program Files\gsdl</i>. Por ejemplo, si se le presenta la URLÂ <i>http://localhost/gsdl/hello.html</i>, el servidor Web intentarÃ¡ recuperar el archivoÂ <i>C:\Program Files\gsdl\hello.html</i>. Sin embargo, la URLÂ <i>http://localhost/hello.html</i>Â busca el archivoÂ <i>C:\Program Files\Apache Group\Apache\htdocs\hello.html</i>Â en el directorioÂ <i>htdocs</i>Â normal, tal como lo hizo antes.</Text>
+<Text id="220">AsegÃºrese de aÃ±adir la directivaÂ <i>Alias</i>Â despuÃ©s de la directivaÂ <i>ScriptAlias</i>. Si se le da la instrucciÃ³n a Apache de aÃ±adir el aliasÂ <i>/gsdl</i>Â antes deÂ <i>/gsdl/cgi-bin</i>Â se harÃ­a corresponder la URLÂ <i>/gsdl/cgi-bin/library</i>Â con la directivaÂ <i>Alias</i>Â y no con la directivaÂ <i>ScriptAlias</i>, lo cual se interpretarÃ­a como una solicitud de un documento y no como el resultado de la ejecuciÃ³n de un programa. La consecuencia serÃ­a que se âvisualizarÃ­aâ el archivo del programa binario como una pÃ¡gina en el servidor Web, en vez de ejecutarlo.</Text>
+</Content>
+</Subsection>
+<Subsection id="security">
+<Title>
+<Text id="221">Seguridad</Text>
+</Title>
+<Content>
+<Text id="222">Debe usted saber que si la versiÃ³n de biblioteca Web de Greenstone se instala como se indica mÃ¡s arriba, cualquier persona podrÃ¡ descargar cualquier archivo en la estructura de directoriosÂ <i>gsdl</i>. Esto comprende los archivos de Ã­ndice y los documentos fuente de cualquiera de las colecciones que haya usted creado, la base de datos del usuario, los registros de utilizaciÃ³n, etc.</Text>
+<Text id="223">Para evitar esto, puede usted reforzar fÃ¡cilmente las medidas de seguridad modificando la configuraciÃ³n de su servidor Web. En el caso del servidor Web Apache, sustituya las lÃ­neas en el archivo de configuraciÃ³n indicadas en el apartado anterior por las siguientes:</Text>
+<CodeLine>Alias /gsdl/Â  âC:/Program Files/gsdl/â</CodeLine>
+<CodeLine>&lt;Directory C:/Program Files/gsdl&gt;</CodeLine>
+<CodeLine>Â  Order allow, deny</CodeLine>
+<CodeLine>Â  Deny from all</CodeLine>
+<CodeLine>Â  &lt;FilesMatch â\.(gif|jpe?g|png|css|mov|mpeg|ps|pdf|doc|rtf|jar|class)$â&gt;</CodeLine>
+<CodeLine>Â Â Â Â  Order allow, deny</CodeLine>
+<CodeLine>Â Â Â Â  Allow from all</CodeLine>
+<CodeLine>Â  &lt;/FilesMatch&gt;</CodeLine>
+<CodeLine>&lt;/Directory&gt;</CodeLine>
+<Text id="224">Esto significa que sÃ³lo se podrÃ¡n descargar los archivos cuyas extensiones se ajustan a la expresiÃ³n regular indicada en la lÃ­neaÂ <i>FilesMatch</i>.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="pws_and_iis_webservers">
+<Title>
+<Text id="225">Los servidores Web PWS e IIS</Text>
+</Title>
+<Content>
+<Text id="226">Aunque ni el PWS ni el IIS estÃ¡n instalados por defecto en los actuales sistemas Windows, Ã©stos se pueden instalar fÃ¡cilmente usando el icono âAgregar o quitar programasâ del panel de control. Si no estÃ¡n ya en su CD-ROM de Windows, tendrÃ¡ que descargarlos del sitio Web de Microsoft (<i>www.microsoft.com</i>).</Text>
+<Text id="227">El procedimiento de instalaciÃ³n de Greenstone es idÃ©ntico para el PWS y el IIS. Abra el Administrador Personal de Web y sigas las instrucciones siguientes:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="228">SeleccioneÂ <i>Avanzadas</i>Â para llegar a la pantallaÂ <i>Opciones avanzadas</i></Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="229">SeleccioneÂ <i>Inicio</i>Â y pulseÂ <i>AÃ±adir</i>Rellene los campos del modo siguiente:</Text>
+<Text id="230">CampoÂ <i>Directorio</i>Â :Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <i>C:\Program Files\gsdl</i></Text>
+<Text id="231">CampoÂ <i>Alias</i>Â :Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <i>gsdl</i></Text>
+<Text id="232">Permisos de acceso:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <i>Read</i></Text>
+<Text id="233">Permisos de aplicaciones:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <i>None</i></Text>
+<Text id="234">PulseÂ <i>OK</i></Text>
+<Text id="235">Esto hace que los archivos Greenstone sean accesibles para el servidor Web.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="236">Regrese aÂ <i>Opciones avanzadas</i>, seleccioneÂ <i>gsdl</i>Â y pulseÂ <i>AÃ±adir</i>Rellene los campos del modo siguiente:</Text>
+<Text id="237">Campo Directorio:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  C:\Program Files\gsdl\cgi-bin</Text>
+<Text id="238">Campo Alias:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  cgi-bin</Text>
+<Text id="239">Permisos de acceso:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  None</Text>
+<Text id="240">Permisos de aplicaciones:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  Execute</Text>
+<Text id="241">Pulse OK</Text>
+<Text id="242">Esto permite que el servidor Web ejecute el programa de GreenstoneÂ <i>library.exe</i></Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="243">Vaya a la URL http://localhost/cgi-bin/library.exe.</Text>
+<Text id="244">Nota: con el PWS y el IIS se debe especificar la extensiÃ³n de archivoÂ <i>.exe</i></Text>
+</NumberedItem>
+</NumberedList>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="configuring_your_site">
+<Title>
+<Text id="245">CONFIGURACIÃN DE SU SITIO</Text>
+</Title>
+<Content>
+<Text id="246">Para que Greenstone funcione correctamente, se deben instalar adecuadamente los permisos de acceso para determinados archivos. Asimismo, cada sitio Greenstone tiene un archivo de configuraciÃ³n asociado. El procedimiento de instalaciÃ³n crea una configuraciÃ³n genÃ©rica basada en las opciones de instalaciÃ³n escogidas por usted; no obstante, su contenido puede personalizarse para hacer frente a distintas situaciones. En esta secciÃ³n se explican ambas cosas.</Text>
+<Section id="file_permissions">
+<Title>
+<Text id="247">Permisos de archivo</Text>
+</Title>
+<Content>
+<Text id="248">Esta secciÃ³n no ataÃ±e a los usuarios de Windows 95/98, ya que esos sistemas no identifican a los propietarios de los archivos.</Text>
+<Text id="249">En Windows NT, 2000 y en los sistemas Unix, los guiones CGI no funcionan como usuarios normales, ya que no se puede identificar a los usuarios en la Web. En cambio, se ejecutan en nombre del usuario que arrancÃ³ el programa del servidor Web (en los sistemas Windows), o de un usuario especial (que en los sistemas Unix suele llamarseÂ <i>nobody</i>). Debido a esto, todos los archivos y directorios dentro deÂ <i>C:\Program Files\gsdl</i>Â deben ser legibles por todos (o al menos legibles por el usuario de guiones CGI, que puede ser âÂ <i>nobody</i>Â â). Para comprobar si los permisos de archivo estÃ¡n configurados correctamente, ejecute el programaÂ <i>library.exe</i>Â a partir de la lÃ­nea de comando. Si los archivos estÃ¡n en los lugares correctos pero los permisos estÃ¡n mal configurados, el programa arrancarÃ¡ desde la lÃ­nea de comando âesto es, cuandoÂ <i>usted</i>Â la ejecuta- pero no desde un navegador âesto es, cuando el usuario âÂ <i>nobody</i>Â â la ejecuta. Otra prueba es iniciar la sesiÃ³n como otro usuario para ver si los permisos de archivo corresponden especÃ­ficamente a su cuenta de usuario original.</Text>
+<Text id="250">Para funcionar desde un navegador Web, todos los directorios de Greenstone deben ser legibles por todos. Asimismo, el directorioÂ <i>C:\Program Files\gsdl\etc</i>Â y todo su contenido deben serÂ <i>modificables</i>Â por cualquier persona. Ãste es el directorio en el que el programa de biblioteca escribe el registro de uso, los registros de error y de inicializaciÃ³n y varias bases de datos del usuario. Si no desea usted que cualquier persona pueda modificar este directorio, puede establecer permisos para que el usuario de CGI sÃ³lo pueda modificar los archivosÂ <i>errout.txt, initout.txt, key.db, users.db, history.db</i>Â yÂ <i>usage.txt</i>.</Text>
+<Text id="251">Si los permisos de archivo no estÃ¡n configurados correctamente paraÂ <i>C:\Program Files\gsdl\etc</i>, es posible que no funcione la autenticaciÃ³n de usuario y el historial de bÃºsqueda, y que no se genere un registro de uso (Â <i>usage.txt</i>).</Text>
+</Content>
+</Section>
+<Section id="gsdlsite_configuration_file">
+<Title>
+<Text id="252">El archivo de configuraciÃ³nÂ <i>gsdlsite.cfg</i></Text>
+</Title>
+<Content>
+<Text id="253">El procedimiento de instalaciÃ³n crea un archivo de configuraciÃ³n de sitio genÃ©rico de Greenstone basado en las opciones de instalaciÃ³n que usted ha escogido. Para nuestra instalaciÃ³n este archivo esÂ <i>C:\Program Files\gsdl\cgi-bin\gsdlsite.cfg</i>Â y su contenido es el siguiente:</Text>
+<CodeLine># Site configuration file por Greenstone.</CodeLine>
+<CodeLine># Lines begining with</CodeLine>
+<CodeLine># are comments.</CodeLine>
+<CodeLine># This file should be placed in the same directory as your library</CodeLine>
+<CodeLine># executable file. It should be edited to suit your site.</CodeLine>
+<CodeLine># points to the GSDLHOME directory</CodeLine>
+<CodeLine>gsdlhomeÂ Â Â Â Â  âC:/Program Files/gsdlâ</CodeLine>
+<CodeLine># this is the http address of GSDLHOME</CodeLine>
+<CodeLine># if your webservers DocumentRoot is set to $GSDLHOME</CodeLine>
+<CodeLine># then httpprefix can be commented out</CodeLine>
+<CodeLine>httpprefixÂ Â Â  /gsdl</CodeLine>
+<CodeLine># this is the http address of the directory which</CodeLine>
+<CodeLine># contains the image for the interface.</CodeLine>
+<CodeLine>httpimgÂ Â Â Â Â Â  /gsdl/images</CodeLine>
+<CodeLine># should contain the http address of this cgi script. This</CodeLine>
+<CodeLine># is not needed if the http server sets the environment variable</CodeLine>
+<CodeLine># SCRIPT_NAME</CodeLine>
+<CodeLine>#gwcgiÂ Â Â Â Â Â Â  /cgi-bin/library</CodeLine>
+<CodeLine># maxrequests is the most requests a fastcgi process</CodeLine>
+<CodeLine># will serve before it exits. This can be set to a</CodeLine>
+<CodeLine># low figure (like 1) while debugging and then set</CodeLine>
+<CodeLine># to a high figure (like 10000) when everything is</CodeLine>
+<CodeLine># working well.</CodeLine>
+<CodeLine>#maxrequests 10000</CodeLine>
+<Text id="254">Puede usted personalizar su instalaciÃ³n modificando este archivo, aunque es muy probable que no tenga que hacerlo.</Text>
+<Text id="255">La lÃ­neaÂ <i>gsdlhome</i>Â seÃ±ala simplemente hacia el directorioÂ <i>C:\Program Files\gsdl</i>.</Text>
+<Text id="256"><i>httpprefix</i>Â es la direcciÃ³n Web del directorio en que Greenstone estÃ¡ instalado. Explicamos antes cÃ³mo crear un alias de tal modo que las URL con la formaÂ <i>http://localhost/gsdl/...</i>Â se busquen en el directorioÂ <i>C:\Program Files\gsdl</i>. AÃ±adiendo una lÃ­neaÂ <i>httpprefix /gsdl</i>Â en el archivo de configuraciÃ³nÂ <i>gsdlsite.cfg</i>Â se establece la misma convenciÃ³n para el programa Greenstone.</Text>
+<Text id="257"><i>httpimg</i>Â es la direcciÃ³n Web del directorioÂ <i>C:\Program Files\gsdl|images</i>, que contiene todas las imÃ¡genes en formato GIF utilizadas en la interfaz. En cualquier instalaciÃ³n estÃ¡ndar de Greenstone Ã©ste serÃ¡ siempreÂ <i>httpprefix/images</i>, y no se toca la lÃ­nea correspondiente en el archivo antes indicado.</Text>
+<Text id="258"><i>gwcgi</i>Â es la direcciÃ³n Web del programa CGI de la biblioteca. La mayorÃ­a de los servidores Web (incluido Apache) no la necesitan y debe permanecer marcado como comentario, por lo tanto inactiva. No se debe quitar la marca de comentario a menos de estar seguro de que es necesario, pues eso puede traer problemas.</Text>
+<Text id="259"><i>maxrequests</i>Â sÃ³lo es utilizado por las versiones de Greenstone que se compilaron con la opciÃ³n âfast-cgiâ. La distribuciÃ³n binaria estÃ¡ndar no comprende esta opciÃ³n porque no todos los servidores Web estÃ¡n configurados para admitirla. La opciÃ³n âfast-cgiâ acelera las ejecuciones de los guiones CGI manteniendo en memoria el ejecutable principal entre dos utilizaciones del programa, en vez de cargarlo a partir del disco cada vez que el programa Greenstone solicita una pÃ¡gina Web. Se debe conseguir un equilibrio con la cantidad de memoria utilizada, que puede aumentar mientras mÃ¡s tiempo permanezca el programa en memoria. Una vez generadas las pÃ¡ginasÂ <i>maxrequests</i>, el programa CGI se cierra, liberando asÃ­ el espacio de memoria ocupado. Para responder a la siguiente solicitud de pÃ¡gina Web, el programa CGI se lee de nuevo a partir del disco duro y se inicia un nuevo ciclo de solicitudes de pÃ¡gina. La mayorÃ­a de las instalaciones utilizan el protocolo CGI estÃ¡ndar, lo que significa que el parÃ¡metroÂ <i>maxrequests</i>Â puede ser ignorado sin problema.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="personalizing">
+<Title>
+<Text id="260">PERSONALIZACIÃN DE SU INSTALACIÃN</Text>
+</Title>
+<Content>
+<Text id="261">Es probable que lo primero que usted quiera hacer una vez que Greenstone estÃ© instalado y en funcionamiento es personalizar la pÃ¡gina principal. El archivo que genera la pÃ¡gina principal de Greenstone se llamaÂ Â <i>home.dm</i>Â y estÃ¡ situado en el subdirectorio deÂ <i>macros</i>Â del directorio en el que usted instalÃ³ Greenstone. (El directorio por defecto para los sistemas Windows esÂ <i>C:\Program Files\gsdl</i>.) Se trata de un archivo de texto sin formato que tendrÃ¡ usted que modificar para crear una nueva pÃ¡gina principal. En vez de modificarla, le recomendamos que cree un nuevo archivo, por ejemploÂ <i>yourhome.dm</i>. Ãste serÃ¡ semejante aÂ <i>home.dm</i>,Â <i/>Â pero definirÃ¡ el âÂ <i>package home</i>Â â âque es la parte que efectÃºa el trabajo efectivo- de un modo distinto.</Text>
+<Text id="262">Al crear una pÃ¡gina principal diferente, hay que poder vincularla a las pÃ¡ginas de la biblioteca digital para que usted pueda efectuar bÃºsquedas y consultar las colecciones en su sistema. La soluciÃ³n adoptada por Greenstone es utilizar âmacrosâ. Por esa razÃ³n, el archivo de la pÃ¡gina principal tiene por sufijo âÂ <i>.dm</i>Â â y no âÂ <i>.html</i>Â â: es un archivo âmacroâ y no un archivo HTML ordinario. Pero no se preocupe: el archivo macro sÃ³lo contiene bÃ¡sicamente el HTML, acompaÃ±ado de unos cuantos ensalmos mÃ¡gicos que se explican mÃ¡s abajo. El lenguaje macro es una funciÃ³n potente y sÃ³lo se describe una pequeÃ±a parte de ella mÃ¡s abajo. VÃ©ase laÂ <i>GuÃ­a del Programador de la Biblioteca Digital Greenstone</i>Â para obtener mÃ¡s informaciÃ³n al respecto.</Text>
+<Section id="example">
+<Title>
+<Text id="263">Ejemplo</Text>
+</Title>
+<Content>
+<Figure id="your_own_greenstone_home_page">
+<Title>
+<Text id="264">Su propia pÃ¡gina principal Greenstone</Text>
+</Title>
+<File width="630" height="412" url="images/Install_Fig_3.png"/>
+</Figure>
+<Text id="265">En la Figura <CrossRef target="Figure" ref="your_own_greenstone_home_page"/> se muestra un ejemplo de una nueva pÃ¡gina principal de la biblioteca digital. Cada uno de los enlaces âÂ <i>Presione aquÃ­</i>Â â lo lleva a la funciÃ³n de Greenstone apropiada. Esta pÃ¡gina se produjo mediante un archivo llamadoÂ <i>yourhome.dm</i>Â que se muestra en la Figura <CrossRef target="Figure" ref="yourhome_dm"/>.</Text>
+<Figure id="yourhome_dm">
+<Title>
+<Text id="266"><i>yourhome.dm</i>Â utilizado para crear la Figura <CrossRef target="Figure" ref="your_own_greenstone_home_page"/></Text>
+</Title>
+<CodeLine>package home</CodeLine>
+<CodeLine>_content_ {</CodeLine>
+<CodeLine>&lt;h2&gt;Su propia pÃ¡gina principal para Greenstone&lt;/h2&gt;</CodeLine>
+<CodeLine>&lt;ul&gt;</CodeLine>
+<CodeLine>&lt;table&gt;</CodeLine>
+<CodeLine>&lt;tr valign=top&gt;&lt;td&gt;PÃ¡gina de bÃºsqueda para la colecciÃ³n demo&lt;br&gt;&lt;/td&gt;</CodeLine>
+<CodeLine>Â Â  Â &lt;td&gt;&lt;a href="_httpquery_&amp;c=demo"&gt;Presione aquÃ­&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;tr&gt;&lt;td&gt;PÃ¡gina Â«sobreÂ» para la colecciÃ³n demo&lt;/td&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;td&gt;&lt;a href="_httppageabout_&amp;c=demo"&gt;Presione aquÃ­&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;tr&gt;&lt;td&gt;PÃ¡gina de preferencias para la colecciÃ³n demo&lt;/td&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;td&gt;&lt;a href="_httppagepref_&amp;c=demo"&gt;Presione aquÃ­&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;tr&gt;&lt;td&gt;PÃ¡gina principal&lt;/td&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;td&gt;&lt;a href="_httppagehome_"&gt;Presione aquÃ­&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;tr&gt;&lt;td&gt;PÃ¡gina de ayuda&lt;/td&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;td&gt;&lt;a href="_httppagehelp_"&gt;Presione aquÃ­&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;tr&gt;&lt;td&gt;PÃ¡gina de administraciÃ³n&lt;/td&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;td&gt;&lt;a href="_httppagestatus_"&gt;Presione aquÃ­&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;tr&gt;&lt;td&gt;El Colector&lt;/td&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;td&gt;&lt;a href="_httppagecollector_"&gt;Presione aquÃ­&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;/table&gt;</CodeLine>
+<CodeLine>&lt;/ul&gt;</CodeLine>
+<CodeLine>}</CodeLine>
+<CodeLine># if you hate the squirly green bar down the left-hand side of the page,</CodeLine>
+<CodeLine># uncomment these lines:</CodeLine>
+<CodeLine># _header_ {</CodeLine>
+<CodeLine># }</CodeLine>
+</Figure>
+<Text id="267">Puede usted utilizar la Figura <CrossRef target="Figure" ref="yourhome_dm"/> como plantilla para crear su propia pÃ¡gina principal de Greenstone personalizada. BÃ¡sicamente, define una macro llamadoÂ <i>content</i>. Entre llaves hay un HTML ordinario. Puede usted insertar texto suplementario, asÃ­ como cualquiera de los comandos de formato HTML, para introducir el contenido que usted quiera ver en la pÃ¡gina. El texto es HTML normal; si lo desea, puede incluir hypervÃ­nculos y utilizar todas las demÃ¡s funciones que ofrece HTML.</Text>
+<Text id="268">Para vincular su nueva pÃ¡gina principal con otras pÃ¡ginas de la biblioteca digital, debe usted hacer uso de un conjuro mÃ¡gico adecuado. En este lenguaje macro, los conjuros mÃ¡gicos son palabras flanqueadas por signos de subrayado, como se puede ver en la Figura <CrossRef target="Figure" ref="yourhome_dm"/>. Por ejemplo,Â <i>_httppagehome_</i>Â lo lleva a la pÃ¡gina principal,Â <i>_httppagehelp_</i>Â a la pÃ¡gina de ayuda, y asÃ­ sucesivamente. En algunos casos es necesario incluir un nombre de colecciÃ³n. Por ejemplo,Â <i>_httpquery_&amp;c=demo</i>Â especifica la pÃ¡gina de bÃºsqueda de la colecciÃ³n de demostraciÃ³n; para otras colecciones se debe reemplazarÂ <i>demo</i>Â por el nombre de la colecciÃ³n correspondiente.</Text>
+<Text id="269">La definiciÃ³n de la macro llamadaÂ <i>_content_</i>Â es HTML simple. Cualquier cÃ³digo HTML estÃ¡ndar puede colocarse dentro de una definiciÃ³n de macro. Sin embargo, los caracteres especiales â{â, â}â, â\â y â_â deben ser precedidos de una barra inversa para evitar que sean procesados por el intÃ©rprete del lenguaje macro.</Text>
+<Text id="270">ObsÃ©rvese que la definiciÃ³n de la macroÂ <i>_content_</i>Â no contiene ningÃºn encabezado o pie de pÃ¡gina HTML. Si desea usted cambiar el encabezado o el pie de su pÃ¡gina principal, debe definir macrosÂ <i>_header_</i>Â y/oÂ <i>_footer_</i>, aÃ±adiÃ©ndolas a su archivoÂ <i>yourhome.dm</i>Â de la siguiente forma:</Text>
+<CodeLine>_macroname_ {</CodeLine>
+<CodeLine>...</CodeLine>
+<CodeLine>}</CodeLine>
+<Text id="271">Por ejemplo, la barra verde ondulada que aparece en el lado izquierdo de las pÃ¡ginas de Greenstone estÃ¡ definida en la macroÂ <i>_header_</i>Â y al anular esta macro se la harÃ¡ desaparecer, como se indica al final de la Figura <CrossRef target="Figure" ref="yourhome_dm"/>.</Text>
+</Content>
+</Section>
+<Section id="how_to_make_it_work">
+<Title>
+<Text id="272">CÃ³mo hacer que funcione</Text>
+</Title>
+<Content>
+<Text id="273">Hay que indicar a Greenstone que se ha creado una nueva pÃ¡gina principalÂ <i>yourhome.dm</i>. El sistema lee en los archivos macro especificados en el archivo de configuraciÃ³n principalÂ <i>main.cfg</i>Â y, por lo tanto, si usted crea uno nuevo debe incluirlo allÃ­. Los conflictos de nombres se manejan con el siguiente criterio: la definiciÃ³n mÃ¡s reciente tiene prioridad sobre las demÃ¡s.</Text>
+<Text id="274">Por consiguiente, para que el programa Greenstone de biblioteca digital utilice la pÃ¡gina principal de la Figura <CrossRef target="Figure" ref="your_own_greenstone_home_page"/> en vez de la instalada por defecto, primero ponga el archivoÂ <i>yourhome.dm</i>Â de la Figura <CrossRef target="Figure" ref="yourhome_dm"/> en el directorio deÂ <i>macros</i>. Luego modifique el archivo de configuraciÃ³nÂ <i>main.cfg</i>Â para reemplazarÂ <i>home.dm</i>Â porÂ <i>yourhome.dm</i>Â en la lista de archivos macro que se cargan al inicio.</Text>
+</Content>
+</Section>
+<Section id="redirecting_a_url_to_greenstone">
+<Title>
+<Text id="275">Reenviar una URL a Greenstone</Text>
+</Title>
+<Content>
+<Text id="276">Es posible que desee usted reenviar una URL mÃ¡s apropiada a su programa CGI de Greenstone. Por ejemplo, en nuestro sistema la URLÂ <i>http://nzdl.org</i>Â (que es la abreviatura deÂ <i>http://nzdl.org/index.html</i>) se reenvÃ­a aÂ <i>http://nzdl.org/cgi-bin/library</i>. El servidor Web Apache efectÃºa esto mediante la directivaÂ <i>Redirect</i>. Como las demÃ¡s directivas, Ã©sta va al archivo de configuraciÃ³nÂ <i>C:\Program Files\Apache Group\Apache\conf\httpd.conf</i>. Para reenviar la URLhttp://www.servidor.comahttp://www.servidor.com/cgi-bin/library, aÃ±ada la lÃ­nea siguiente enÂ <i>httpd.conf</i>Â :</Text>
+<CodeLine>Redirect /index.html http://www.servidor.com/cgi-bin/library</CodeLine>
+<Text id="277">AsÃ­ llegarÃ¡ usted a su sistema de biblioteca digital directamente desde la URLÂ <i>http://www.servidor.com</i>. En cambio, si usted deseara reenviar una URL comoÂ <i>http://www.servidor.com/greenstone</i>Â aÂ <i>http://www.servidor.com/cgi-bin/library,</i>Â introduzca en el archivoÂ <i>httpd.conf</i>Â la lÃ­nea siguiente:</Text>
+<CodeLine>Redirect /greenstone http://www.servidor.com/cgi-bin/library</CodeLine>
+<Text id="278">Si su computadora carece de nombre de dominio (como el âwww.servidor.comâ mencionado mÃ¡s arriba), basta con reemplazarÂ <i>www.servidor.com</i>Â porÂ <i>localhost</i>Â en las lÃ­neas que figuran mÃ¡s arriba. Mientras el navegador estÃ© funcionando en la misma mÃ¡quina que el servidor Web âlo cual es seguramente el caso si su computadora no tiene un nombre de dominio- esto tiene el mismo efecto que los reenvÃ­os antes mencionados.</Text>
+<Text id="279">En lugar de introducir las directivas de reenvÃ­o en el archivoÂ <i>httpd.conf</i>,Â  puede usted ponerlas en un archivo llamadoÂ <i>.htaccess</i>Â dentro del directorio raÃ­z de los documentos de su servidor. De hecho, esta soluciÃ³n tiene dos ventajas. En primer lugar, las modificaciones efectuadas en el archivoÂ <i>.htaccess</i>Â surten efecto de inmediato, mientras que es necesario volver a arrancar el servidor Web Apache para ver los efectos de los cambios en el archivoÂ <i>httpd.conf</i>. En segundo lugar, en los sistemas Unix suele ser necesario iniciar la sesiÃ³n como el usuario âÂ <i>root</i>Â â para poder modificar el archivoÂ <i>httpd.conf</i>, mientras que no lo es para modificar el archivoÂ <i>.htaccess</i>.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="appendix_associated_software">
+<Title>
+<Text id="280">APÃNDICE: PROGRAMAS ASOCIADOS</Text>
+</Title>
+<Content>
+<Text id="281">A continuaciÃ³n se explica cÃ³mo conseguir los paquetes de programas mencionados en este documento.</Text>
+<Section id="apache_webserver">
+<Title>
+<Text id="282">Servidor Web Apache</Text>
+</Title>
+<Content>
+<Text id="283">Para hacer funcionar cualquier versiÃ³n de Greenstone aparte de la versiÃ³n de Biblioteca Local de Windows, se necesita un servidor Web externo. Muchas instalaciones, en particular las mÃ¡s voluminosas, tendrÃ¡n ya un servidor Web. Si usted utiliza Linux, Apache puede encontrarse en su disco de instalaciÃ³n pero puede no haber sido seleccionado durante el procedimiento de instalaciÃ³n. El servidor Web Apache deÂ <i>www.apache.org</i>Â es libre y fÃ¡cil de instalar.</Text>
+</Content>
+</Section>
+<Section id="perl">
+<Title>
+<Text id="284">Perl</Text>
+</Title>
+<Content>
+<Text id="285">Para crear colecciones con Greenstone se necesita el lenguaje Perl, versiÃ³n 5 o superior. Para Windows, recomendamos ActivePerl deÂ <i>www.activestate.com</i>. La mayorÃ­a de los sistemas Unix ya tienen Perl instalado, pero si no es el caso, los cÃ³digos fuente y los binarios de una amplia gama de plataformas Unix pueden descargarse libremente enÂ <i>www.perl.com</i>.</Text>
+</Content>
+</Section>
+<Section id="gcc">
+<Title>
+<Text id="286">GCC</Text>
+</Title>
+<Content>
+<Text id="287">La versiÃ³n Unix de Greenstone se compila con el compilador C++ de GNU, GCC. Greenstone hace un amplio uso de la biblioteca estÃ¡ndar de plantillas C++ (hemos observado que estÃ¡ rota en algunas antiguas versiones de GCC, sÃ­rvase avisarnos si tiene usted problemas con STL). Cabe seÃ±alar que esta versiÃ³n de Greenstone no compila con la versiÃ³n 3.0 de GCC.</Text>
+</Content>
+</Section>
+<Section id="gdbm">
+<Title>
+<Text id="288">GDBM</Text>
+</Title>
+<Content>
+<Text id="289">Todas las versiones de Greenstone utilizan el Administrador de Base de Datos GNU, GDBM (GNU Database Manager). Viene con todas las versiones Windows de Greenstone y se instala automÃ¡ticamente durante el procedimiento de instalaciÃ³n. Los sistemas Linux ya tienen GDBM, por lo que no lo proporcionamos para Linux. La mayorÃ­a de los demÃ¡s sistemas Unix lo tienen, pero si es necesario puede usted descargarlo en la URLÂ <i>www.gnu.org</i>.</Text>
+</Content>
+</Section>
+<Section id="java_runtime_environment">
+<Title>
+<Text id="290">Ambiente de EjecuciÃ³n Java</Text>
+</Title>
+<Content>
+<Text id="291">Para poder usar la Interfaz de Bibliotecario de Greenstone es necesario contar con una versiÃ³n adecuada del Ambiente de EjecuciÃ³n Java (JRE por sus siglas en inglÃ©s). Si todavÃ­a no lo tiene, el CD-ROM incluye una versiÃ³n apropiada, o tambiÃ©n puede bajar la versiÃ³n mÃ¡s reciente desdeÂ <u>http://java.sun.com/j2se/downloads.html</u>. Se requiere la versiÃ³n 1.4.0 o superior.</Text>
+</Content>
+</Section>
+<Section id="java_compiler">
+<Title>
+<Text id="292">Compilador Java</Text>
+</Title>
+<Content>
+<Text id="293">Para compilar el cÃ³digo fuente de la Interfaz de Bibliotecario de Greenstone primero deberÃ¡ instalar un Kit de Desarrollo de Software Java (SDK por sus siglas en inglÃ©s). Usted puede bajar el Kit de Desarrollo de Software J2SE desdeÂ <u>http://java.sun.com/j2se/downloads.html</u>. Se requiere la versiÃ³n 1.4.0 o superior.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+</Manual>
Index: /tags/start/gsdl-documentation/manuals/xml-source/es/Paper_es.xml
===================================================================
--- /tags/start/gsdl-documentation/manuals/xml-source/es/Paper_es.xml	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/xml-source/es/Paper_es.xml	(revision 13666)
@@ -0,0 +1,853 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Manual>
+<Heading>
+<Text id="1">BIBLIOTECA DIGITAL GREENSTONE</Text>
+</Heading>
+<Title>
+<Text id="2">DEL PAPEL A LA COLECCIÃN</Text>
+</Title>
+<Author>
+<Text id="3">Dr. Michel Loots, Dan Camarzan e Ian H. Witten</Text>
+</Author>
+<Affiliation>
+<Text id="4">Human Info (BÃ©lgica) <br/>Simple Words (Rumania)<br/>Universidad de Waikato (Nueva Zelanda)</Text>
+</Affiliation>
+<Text id="5">Greenstone es un conjunto de programas y aplicaciones de software especialmente diseÃ±ados para la creaciÃ³n y difusiÃ³n de colecciones documentales digitales, el cual le ofrece una nueva forma de organizar la informaciÃ³n y publicarla en Internet o CD-ROM. Greenstone ha sido elaborado como parte del proyecto de Biblioteca Digital de Nueva Zelanda de la Universidad de Waikato y actualmente es desarrollado y distribuido en colaboraciÃ³n con la UNESCO y la ONG Human Info. Es un software de cÃ³digo abierto disponible en <i>http://greenstone.org</i> bajo los tÃ©rminos y condiciones de la Licencia PÃºblica General de GNU.</Text>
+<Comment>
+<Text id="6">Queremos estar seguros que este software trabaje bien para usted. Por favor comunÃ­quenos cualquier problema que tenga con Ã©l a la siguiente direcciÃ³n: <i>greenstone@cs.waikato.ac.nz</i>
+</Text>
+</Comment>
+<Version>
+<Text id="7">Greenstone gsdl-2.50</Text>
+</Version>
+<Date>
+<Text id="8">Marzo de 2004</Text>
+</Date>
+<Section id="about_this_manual">
+<Title>
+<Text id="9">Acerca de este manual</Text>
+</Title>
+<Content>
+<Text id="10">El presente documento explica la forma de crear colecciones en CD-ROM a partir de documentos impresos y expone con detalle los procedimientos y costos de los procesos de escaneado y reconocimiento Ã³ptico de caracteres (OCR por sus siglas en inglÃ©s) para obtener al final un texto con el formato adecuado para los programas Greenstone. TambiÃ©n se describe la forma de crear y editar el material asociado a una colecciÃ³n.</Text>
+<Text id="11">Hemos procurado formular nuestras explicaciones de la manera mÃ¡s sencilla posible. Cualquier referencia a productos o empresas responde a un propÃ³sito meramente ilustrativo, y no presupone por nuestra parte valoraciÃ³n o preferencia alguna por tales productos en perjuicio de cualquier otro.</Text>
+</Content>
+</Section>
+<Section id="companion_documents">
+<Title>
+<Text id="12">Conjunto de documentos</Text>
+</Title>
+<Content>
+<Text id="13">La serie completa de documentos comprende cinco volÃºmenes:</Text>
+<BulletList>
+<Bullet>
+<Text id="14">La GuÃ­a de InstalaciÃ³n de la Biblioteca Digital Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="15">La GuÃ­a del Usuario de la Biblioteca Digital Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="16">La GuÃ­a del Programador de la Biblioteca Digital Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="17">La Biblioteca Digital Greenstone: del Papel a la ColecciÃ³n (<i>el presente documento</i>)</Text>
+</Bullet>
+<Bullet>
+<Text id="18">La Biblioteca Digital Greenstone: uso del Organizador</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Section>
+<Section id="acknowledgements">
+<Title>
+<Text id="19">Agradecimientos</Text>
+</Title>
+<Content>
+<Text id="20">Los capÃ­tulos dedicados al escaneado, el Organizador y demÃ¡s informaciÃ³n relativa a la creaciÃ³n de colecciones documentales colectivas sin fines de lucro son obra del Dr. Michel Loots , Gerente de la ONG Human Info y de HumanityCD , Dan Camarzan de Simple Words y el equipo que colabora con ambos desde Brasov (Rumania).</Text>
+<Text id="21">El programa Greenstone es fruto de la colaboraciÃ³n de muchas personas. Rodger McNab y Stefan Boddie son los principales arquitectos y programadores. TambiÃ©n han contribuido David Bainbridge, George Buchanan, Hong Chen, Michael Dewsnip, Katherine Don, Elke Duncker, Carl Gutwin, Geoff Holmes, Dana McKay, John McPherson, Craig Nevill-Manning, Dynal Patel, Gordon Paynter, Bernhard Pfahringer, Todd Reed, Bill Rogers, John Thompson y Stuart Yeates. Otros miembros del proyecto Biblioteca Digital de Nueva Zelanda que proporcionaron asesorÃ­a y valiosas ideas para la concepciÃ³n del sistema son: Mark Apperley, Sally Jo Cunningham, Matt Jones, Steve Jones, Te Taka Keegan, Michel Loots, Malika Mahoui, Gary Marsden, Dave Nichols y Lloyd Smith. TambiÃ©n queremos dar las gracias a todos aquellos que contribuyeron a los paquetes de programas con licencias GNU incluidos en esta distribuciÃ³n: MG, GDBM, PDFTOHTML, PERL, WGET, WVWARE y XLHTML.</Text>
+</Content>
+</Section>
+<Chapter id="introduction">
+<Title>
+<Text id="22">IntroducciÃ³n</Text>
+</Title>
+<Content>
+<Text id="23">Uno de los objetivos de la Biblioteca Digital Greenstone es hacer posible que instituciones como las universidades, organismos del sistema de las Naciones Unidas, organizaciones no gubernamentales, gobiernos y organizaciones no lucrativas puedan crear diversas colecciones de informaciÃ³n y difundirlas por Internet o en forma de CD-ROM.</Text>
+<Text id="24">El proceso suele comprender los siguientes pasos:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="25">Determinar los documentos que han de figurar en la colecciÃ³n.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="26">Obtener la autorizaciÃ³n de los titulares de los derechos de autor para incluir esos documentos en la biblioteca digital.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="27">Escanear y reconocer por medio de OCR los documentos impresos que no estÃ©n disponibles en formato digital.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="28">Convertir todos los documentos en un formato que integre texto e imÃ¡genes y se pueda importar a Greenstone, de preferencia en formato HTML o Word de Microsoft, aunque tambiÃ©n se cuenta con plugins que reconocen otros formatos con un nivel variable de precisiÃ³n (vÃ©ase laÂ <i>GuÃ­a del Usuario de la Biblioteca Digital Greenstone</i>).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="29">Etiquetar los capÃ­tulos, pÃ¡rrafos e imÃ¡genes de los documentos electrÃ³nicos.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="30">Dotar a la colecciÃ³n de la estructura idÃ³nea para que funcione como biblioteca digital.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="31">Crear la biblioteca digital utilizando los programas Greenstone.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="32">Editar y distribuir la colecciÃ³n en CD-ROM y/o distribuirla por Internet.</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="33">Para crear una colecciÃ³n digital es preciso que las publicaciones existan antes en formato digital. Los libros, revistas u otros documentos que sÃ³lo existan en forma impresa deberÃ¡n ser escaneados, procesados y convertidos en un formato que la computadora reconozca (paso iii). El procedimiento mÃ¡s usual para ello es el reconocimiento Ã³ptico de caracteres (OCR por sus siglas en inglÃ©s), aunque a veces se opta por capturar Ã­ntegramente el texto. De este proceso tratan los capÃ­tulos 2 a 4 del presente manual.</Text>
+<Text id="34">El paso v) sirve para que, una vez finalizada la biblioteca, el usuario pueda seleccionar y ver en pantalla por separado las distintas partes de un documento. El paso vi) consiste en asignar atributos a cada documento, como por ejemplo categorÃ­as temÃ¡ticas, palabras clave y datos bibliogrÃ¡ficos con arreglo a los cuales se pueda ordenar y consultar la biblioteca. Estos pasos se explican en el CapÃ­tulo 5 del presente manual.</Text>
+<Text id="35">Asimismo, en el presente manual se tratan numerosas cuestiones relativas al procedimiento editorial y a la creaciÃ³n de una colecciÃ³n digital a partir de documentos impresos. Antes de seguir adelante, el lector debe plantearse las siguientes preguntas:</Text>
+<BulletList>
+<Bullet>
+<Text id="36">Â¿CuÃ¡l es el objetivo de mi colecciÃ³n?</Text>
+</Bullet>
+<Bullet>
+<Text id="37">Â¿A quÃ© grupo de usuarios se dirige?</Text>
+</Bullet>
+<Bullet>
+<Text id="38">Â¿CuÃ¡n grande es dicho grupo? Â¿Tiene dimensiÃ³n local, regional o mundial?</Text>
+</Bullet>
+<Bullet>
+<Text id="39">Â¿CuÃ¡ntos documentos tengo pensado incluir en la colecciÃ³n?</Text>
+</Bullet>
+<Bullet>
+<Text id="40">Â¿CuÃ¡ntas pÃ¡ginas?</Text>
+</Bullet>
+<Bullet>
+<Text id="41">Â¿CuÃ¡nta informaciÃ³n grÃ¡fica contienen?</Text>
+</Bullet>
+<Bullet>
+<Text id="42">Â¿Cabe subdividir la documentaciÃ³n en partes que sean de interÃ©s para un pÃºblico reducido y otras que requieran una difusiÃ³n mÃ¡s amplia?</Text>
+</Bullet>
+<Bullet>
+<Text id="43">Â¿Existen ya en forma electrÃ³nica los documentos?</Text>
+</Bullet>
+<Bullet>
+<Text id="44">De ser asÃ­, Â¿en quÃ© formato? (SeÃ±alemos de paso que un archivo PDF no equivale automÃ¡ticamente al texto completo en formato electrÃ³nico, pues a menudo contiene sÃ³lo la imagen de las pÃ¡ginas.)</Text>
+</Bullet>
+<Bullet>
+<Text id="45">Â¿A quÃ© derechos de autor estÃ¡n sujetos los documentos?</Text>
+</Bullet>
+<Bullet>
+<Text id="46">Â¿QuiÃ©n es el titular de los derechos de autor?</Text>
+</Bullet>
+<Bullet>
+<Text id="47">Â¿Hay otras organizaciones que se dirijan al mismo pÃºblico? </Text>
+</Bullet>
+<Bullet>
+<Text id="48">Â¿Tengo deseos de colaborar con otros grupos?</Text>
+</Bullet>
+<Bullet>
+<Text id="49">Â¿De quÃ© presupuesto dispongo para el conjunto del proyecto?</Text>
+</Bullet>
+<Bullet>
+<Text id="50">Â¿De quÃ© recursos humanos (en personas-mes) dispongo para las labores de coordinaciÃ³n, ediciÃ³n, escaneado y programaciÃ³n?</Text>
+</Bullet>
+<Bullet>
+<Text id="51">Â¿De cuÃ¡ntas computadoras dispongo para el proyecto?</Text>
+</Bullet>
+<Bullet>
+<Text id="52">Â¿CuÃ¡ntos CD-ROM tengo pensado distribuir?</Text>
+</Bullet>
+<Bullet>
+<Text id="53">Â¿Voy a distribuirlos gratuitamente o a venderlos?</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Chapter>
+<Chapter id="scanners_and_scanning">
+<Title>
+<Text id="54">EscÃ¡neres y escaneado</Text>
+</Title>
+<Content>
+<Text id="55">En el proceso de conversiÃ³n de documentos impresos en una colecciÃ³n de biblioteca digital, el primer paso consiste en obtener imÃ¡genes digitales de todas las pÃ¡ginas de todas las publicaciones. La siguiente etapa es la del reconocimiento Ã³ptico de caracteres (OCR), proceso que requiere, para un resultado Ã³ptimo, imÃ¡genes de partida limpias y de buena calidad. Para el proceso de digitalizaciÃ³n se necesita un escÃ¡ner que pueda trabajar a una resoluciÃ³n de 300 ppp (puntos por pulgada). Gran parte del trabajo puede hacerse en blanco y negro, aunque deberÃ¡ utilizarse un escÃ¡ner capaz de obtener imÃ¡genes en color cuando el documento las contenga. La mayorÃ­a de las cubiertas de libro son en color, por lo que hay que escanearlas en forma de imagen fotogrÃ¡fica en color.</Text>
+<Section id="scanners">
+<Title>
+<Text id="56">EscÃ¡neres</Text>
+</Title>
+<Content>
+<Text id="57">Existen escÃ¡neres de todos los precios, formas y tamaÃ±os, que pueden costar desde 100 dÃ³lares (un escÃ¡ner plano) hasta mÃ¡s de 50.000 dÃ³lares (los grandes escÃ¡neres industriales de fabricantes como Bell &amp; Howell<FootnoteRef id="1"/>). Hay muchos sitios Web en los que se ofrece a la venta un amplio surtido de escÃ¡neres. Para encontrarlos basta con introducir la palabra âscannerâ (escÃ¡ner) en buscadores como Google, Altavista o Yahoo.</Text>
+<Text id="58">El formato de salida de una pÃ¡gina escaneada es un archivo informÃ¡tico, por lo general en formato TIFF o Bitmap. El mejor formato es el TIFF IV comprimido. Una pÃ¡gina normal, escaneada y convertida en este formato, ocupa sÃ³lo 50 Kb de memoria, mientras que una pÃ¡gina equivalente en formato Bitmap no comprimido puede llegar a los 2 Mb.</Text>
+<Subsection id="low-cost_flat-bed_scanner">
+<Title>
+<Text id="59">EscÃ¡neres planos (o de sobremesa) de gama baja</Text>
+</Title>
+<Content>
+<Text id="60">Los escÃ¡neres de este tipo son los mÃ¡s econÃ³micos y difundidos. Existen muchas marcas: HP, Agfa, Acer, etc., con precios que van de los 100 a los 300 dÃ³lares. Con ellos pueden obtenerse imÃ¡genes tanto en blanco y negro como en color.Â <b/>Â El bajo precio de estas mÃ¡quinas permite conectar cada computadora a su propio escÃ¡ner.</Text>
+<Text id="61">Entre sus inconvenientes cabe citar la mediocre calidad del resultado, la lentitud con que trabajan, su escasa fiabilidad a temperaturas altas y la relativa frecuencia con que se averÃ­an. Es preciso escanear las pÃ¡ginas manualmente, una por una, colocÃ¡ndolas cuidadosamente en la placa de escaneado para que queden correctamente alineadas. De ahÃ­ que su productividad resulte baja. Aunque los fabricantes aseguran que se puede escanear una pÃ¡gina en menos de un minuto, en la prÃ¡ctica rara vez se consiguen resultados superiores a las doce pÃ¡ginas por hora. AdemÃ¡s, el proceso de escaneado monopoliza la computadora con la que se estÃ¡ realizando el trabajo.</Text>
+<Text id="62">Por todo lo dicho, estos escÃ¡neres sÃ³lo son Ãºtiles para realizar trabajos de escasa envergadura y pocas pÃ¡ginas: no mÃ¡s de 200 a 400 pÃ¡ginas al mes cuando se trate de un trabajo sistemÃ¡tico, y de 1.000 a 2.000 pÃ¡ginas para operaciones de carÃ¡cter esporÃ¡dico.</Text>
+</Content>
+</Subsection>
+<Subsection id="low-end_scanner_with_sheet_feeder">
+<Title>
+<Text id="63">EscÃ¡neres de gama baja con alimentador de papel</Text>
+</Title>
+<Content>
+<Text id="64">Los escÃ¡neres de este tipo suelen costar entre 500 y 1.200 dÃ³lares. Ofrecen la posibilidad de escanear y procesar de 10 a 50 pÃ¡ginas de una vez, lo que evita que el operador tenga que estar continuamente pendiente de la mÃ¡quina y aumenta la productividad hasta unas 150 a 200 pÃ¡ginas diarias. Estos escÃ¡neres son mÃ¡s robustos y gozan de una vida Ãºtil mÃ¡s larga antes de necesitar reparaciones (lo que suele ocurrir al cabo de 30.000 a 50.000 pÃ¡ginas).</Text>
+<Text id="65">Una de sus desventajas es que sÃ³lo pueden escanear una cara a la vez, lo que obliga a invertir el paquete de pÃ¡ginas y escanearlas de nuevo para obtener imÃ¡genes por ambas caras. Ello da lugar a frecuentes problemas, pues los alimentadores nunca funcionan a la perfecciÃ³n y a veces las pÃ¡ginas se atascan.</Text>
+<Text id="66">Estos escÃ¡neres son Ãºtiles para trabajos de 1.500 a 3.000 pÃ¡ginas mensuales.</Text>
+</Content>
+</Subsection>
+<Subsection id="color_scanners">
+<Title>
+<Text id="67">EscÃ¡neres en color</Text>
+</Title>
+<Content>
+<Text id="68">Toda operaciÃ³n de escaneado conlleva siempre imÃ¡genes en color, lo que hace imprescindible un escÃ¡ner capaz de procesarlas. Por regla general, menos del 5% de una publicaciÃ³n contiene imÃ¡genes en color, sin contar la cubierta. En consecuencia, serÃ¡ suficiente un escÃ¡ner plano de gama baja como los mencionados mÃ¡s arriba. Es aconsejable elegir una mÃ¡quina que pueda trabajar a una resoluciÃ³n de hasta 600 ppp.</Text>
+</Content>
+</Subsection>
+<Subsection id="professional_duplex_scanners">
+<Title>
+<Text id="69">EscÃ¡neres dÃºplex profesionales</Text>
+</Title>
+<Content>
+<Text id="70">Los escÃ¡neres profesionales son mÃ¡quinas fiables y resistentes, capaces de tratar un gran nÃºmero de pÃ¡ginas (normalmente entre 2.000 y 10.000 pÃ¡ginas diarias). EstÃ¡n provistos de una bandeja de alimentaciÃ³n automÃ¡tica con capacidad para 50 a 200 pÃ¡ginas. Los mejores y mÃ¡s rÃ¡pidos son los dÃºplex, es decir, capaces de escanear simultÃ¡neamente las dos caras de una hoja.</Text>
+<Text id="71">Para utilizar un escÃ¡ner dÃºplex profesional se requiere una computadora potente, dotada de un disco duro de 10 a 20 Gb de capacidad como mÃ­nimo. El precio de estos escÃ¡neres oscila entre los 5.000 y los 50.000 dÃ³lares. El escÃ¡ner dÃºplex Canon DR-6020, por ejemplo, cuesta 5.000 dÃ³lares y puede trabajar con documentos impresos por ambas caras. Ofrece un rendimiento de unas 2.000 pÃ¡ginas diarias y un periodo de vida Ãºtil de 600.000 a 800.000 pÃ¡ginas. Los escÃ¡neres Bell &amp; Howell y Fujitsu cuestan entre 10.000 y 50.000 dÃ³lares y gozan de un periodo de vida Ãºtil de muchos millones de pÃ¡ginas.</Text>
+<Text id="72">Los escÃ¡neres para microfichas cuestan entre 15.000 (por una unidad semimanual) y 80.000 dÃ³lares (por un escÃ¡ner completamente automÃ¡tico).</Text>
+</Content>
+</Subsection>
+<Subsection id="scanning_programs">
+<Title>
+<Text id="73">Programas de escaneado</Text>
+</Title>
+<Content>
+<Text id="74">Cada escÃ¡ner viene acompaÃ±ado de su propio programa informÃ¡tico, que es necesario instalar en la computadora desde la que vaya a controlarse el escaneado. Algunos traen consigo una tarjeta controladora que se instala en la computadora para acelerar la digitalizaciÃ³n.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="preparing_the_documents">
+<Title>
+<Text id="75">PreparaciÃ³n de los documentos</Text>
+</Title>
+<Content>
+<Text id="76">Antes de escanear los documentos hay que prepararlos adecuadamente, eliminando posibles motas de polvo, secÃ¡ndolos si estÃ¡n hÃºmedos, extrayendo clips y grapas y alisando las pÃ¡ginas dobladas o arrugadas.</Text>
+<Text id="77">Es preciso desmontar el lomo de los libros, cortÃ¡ndolo en lÃ­nea recta y desprendiÃ©ndolo con precisiÃ³n. A menudo habrÃ¡n de encuadernarse de nuevo los libros procedentes de bibliotecas, en cuyo caso conviene extremar las precauciones al desmontar el lomo para facilitar la posterior encuadernaciÃ³n.</Text>
+<Text id="78">Cuando se trabaje con pocos documentos se puede retirar el lomo manualmente, con ayuda de una regla y una cuchilla. Â¡Pero cuidado con los dedos! Para un mayor nÃºmero de documentos merece la pena recurrir a guillotinas manuales especiales</Text>
+<Text id="79">Para grandes volÃºmenes, por ejemplo mÃ¡s de 20 documentos, recomendamos pedir permiso a una imprenta o copisterÃ­a para utilizar su guillotina profesional. RecuÃ©rdese que es preciso extraer los clips y las grapas para no daÃ±ar las cuchillas.</Text>
+</Content>
+</Section>
+<Section id="the_scanning_process">
+<Title>
+<Text id="80">El proceso de escaneado</Text>
+</Title>
+<Content>
+<Text id="81">Con el programa informÃ¡tico suministrado con el escÃ¡ner se genera a partir de cada pÃ¡gina una imagen electrÃ³nica, que se transforma en una imagen Bitmap o TIFF y se memoriza acto seguido en el disco duro, asignando a cada archivo un nombre normalizado. Una vez escaneados todos o una parte de los documentos de un lote empieza el proceso de OCR, del que puede ocuparse el operador del escÃ¡ner o cualquier otra persona.</Text>
+<Text id="82">En general se necesita una resoluciÃ³n de 300 ppp, aunque a veces tambiÃ©n resulte aceptable un valor de 200 ppp.</Text>
+<Subsection id="quality_control">
+<Title>
+<Text id="83">Control de calidad</Text>
+</Title>
+<Content>
+<Text id="84">La digitalizaciÃ³n sirve para obtener una versiÃ³n perfecta de las publicaciones en formato de texto o HTML mediante el proceso de OCR, o bien para crear archivos grÃ¡ficos mejorados como los PDF. En ambos casos es de suma importancia que la imagen sea de buena calidad. En caso contrario los archivos grÃ¡ficos resultan poco nÃ­tidos y consumen mÃ¡s memoria. La calidad influye sobremanera en el proceso de OCR: con imÃ¡genes de calidad mediocre la productividad puede caer hasta en un 40%. Sabiendo que el OCR suele representar mÃ¡s del 90% del costo total, se deduce que la calidad del escaneado es determinante para el costo final del proceso.</Text>
+<Text id="85">Es posible mejorar la calidad de un archivo TIFF adaptando el proceso de escaneado a cada tipo de papel mediante las opciones de ajuste que ofrece el programa del escÃ¡ner. Un tipo de papel relativamente transparente requerirÃ¡ parÃ¡metros mÃ¡s claros, el contraste deberÃ¡ ajustarse en funciÃ³n de la calidad de la impresiÃ³n, etc.</Text>
+<Text id="86">Ante todo conviene dividir el material en lotes de documentos que presenten similar calidad de papel e impresiÃ³n, y despuÃ©s realizar pruebas de OCR con una muestra del primer lote para determinar los parÃ¡metros de ajuste idÃ³neos. A continuaciÃ³n se escanearÃ¡n todos los documentos de ese primer lote antes de continuar con el siguiente.</Text>
+</Content>
+</Subsection>
+<Subsection id="filename_conventions">
+<Title>
+<Text id="87">Convenciones para designar los archivos</Text>
+</Title>
+<Content>
+<Text id="88">Es preciso asignar a cada libro o documento un nÃºmero de trabajo o cÃ³digo Ãºnico, que a su vez darÃ¡ nombre a la carpeta en la que se archiven todas las imÃ¡genes TIFF correspondientes a ese documento. SegÃºn el sistema operativo del que se trate (DOS, Windows, UNIX, LINUX, etc.), el nombre de un archivo puede comprender entre 8 y 128 caracteres, aunque es aconsejable limitarse a un mÃ¡ximo de 16 caracteres. Si se utilizan 8 caracteres, los cinco primeros servirÃ­an para identificar el documento, el siguiente serÃ­a una letra indicativa del cÃ³digo de idioma y los dos restantes caracteres indicarÃ­an el nÃºmero de pÃ¡gina. Por ejemplo: el identificadorÂ <i>u7548e12.tif</i>Â corresponderÃ­a a la imagen TIFF de la pÃ¡gina 12 de un libro escrito en inglÃ©s que tuviera por cÃ³digoÂ <i>u7548e.</i>
+</Text>
+<Text id="89">Conviene asignar un directorio del disco duro a los trabajos de escaneado (por ejemplo con el nombre deÂ <i>scanjobs</i>). DespuÃ©s se puede crear un subdirectorio para cada uno de los trabajos, en cuyo interior se crearÃ¡ un nuevo subdirectorio para cada publicaciÃ³n (en el ejemplo anterior,Â <i>u7548e</i>), donde se guardan todas las imÃ¡genes TIFF correspondientes a esa publicaciÃ³n, incluidas las imÃ¡genes en color.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="productivity_and_resources">
+<Title>
+<Text id="90">Productividad y recursos necesarios</Text>
+</Title>
+<Content>
+<Text id="91">No hay que subestimar la carga de trabajo que suponen los procesos de escaneado y, sobre todo, de OCR. Es preferible considerar que ambos procesos son completamente independientes y elegir el procedimiento idÃ³neo (desde el punto de vista econÃ³mico y tambiÃ©n prÃ¡ctico) para cada uno de ellos por separado.</Text>
+<Text id="92">Entre los aspectos que conviene tener en cuenta cabe seÃ±alar: la inversiÃ³n necesaria en escÃ¡neres y computadoras, la existencia de los recursos humanos y el espacio necesarios, la formaciÃ³n del personal, los gastos salariales, el nÃºmero inicial y total de pÃ¡ginas por escanear, los plazos en que ha de realizarse el trabajo y la posibilidad de subcontratarlo a terceros.</Text>
+<Subsection id="scanning_costs">
+<Title>
+<Text id="93">Costos del proceso de escaneado</Text>
+</Title>
+<Content>
+<Text id="94">Es importante decidir si se ha de invertir en un equipo de escaneado y asumir internamente esa labor o bien subcontratarla a una empresa especializada. Las principales consideraciones que deben tenerse en cuenta son:</Text>
+<BulletList>
+<Bullet>
+<Text id="95">los plazos en que ha de realizarse el trabajo;</Text>
+</Bullet>
+<Bullet>
+<Text id="96">el nÃºmero total de pÃ¡ginas;</Text>
+</Bullet>
+<Bullet>
+<Text id="97">los costos salariales correspondientes a las personas encargadas del escaneado.</Text>
+</Bullet>
+</BulletList>
+<Text id="98">Las personas a quienes se encomiende el escaneado deben estar muy motivadas y preparadas tÃ©cnicamente, y tener muy clara la importancia de cumplir los criterios de calidad.</Text>
+<Text id="99">Una empresa especializada suele cobrar 0,06 dÃ³lares por pÃ¡gina, a lo que hay que aÃ±adir los gastos de envÃ­o, que pueden ser de hasta 0,03 dÃ³lares por pÃ¡gina cuando se remite el material de un paÃ­s en desarrollo a un paÃ­s desarrollado y de 0,015 dÃ³lares por pÃ¡gina cuando se trata de un envÃ­o nacional.</Text>
+<Text id="100">En el Cuadro <CrossRef target="Table" ref="table_scanning_cost"/> se ofrecen estimaciones de los costos de escaneado por cuenta propia segÃºn el tipo de escÃ¡ner que se utilice. Conviene tener en cuenta que estas cifras son aproximadas y corresponden mÃ¡s bien a Ã³rdenes generales de magnitud, basados en la experiencia de los autores. En las tres primeras columnas se presentan los costos laborales. En la primera se indica la productividad (en pÃ¡ginas mensuales) suponiendo que se trabaje a jornada completa. Dividiendo las horas mensuales de trabajo por la productividad en pÃ¡ginas/mes se obtienen los recursos necesarios en tÃ©rminos de horas de trabajo/pÃ¡gina, guarismo que figura en la segunda columna (suponiendo que se trabajen 180 horas al mes).</Text>
+<Table id="table_scanning_cost">
+<Title>
+<Text id="101">Costos del proceso de escaneado</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="90"/>
+<th width="71">
+<Text id="102">Rendimiento (pÃ¡ginas/mes)</Text>
+</th>
+<th width="75">
+<Text id="103">Horas/pÃ¡gina (180 horas/mes)</Text>
+</th>
+<th width="83">
+<Text id="104">Costo/pÃ¡gina (suponiendo 4 dÃ³lares/hora)</Text>
+</th>
+<th width="60">
+<Text id="105">AdquisiciÃ³n del escÃ¡ner (dÃ³lares)</Text>
+</th>
+<th width="66">
+<Text id="106">Vida Ãºtil del escÃ¡ner (pÃ¡ginas)</Text>
+</th>
+<th width="85">
+<Text id="107">PÃ¡ginas que se podrÃ­an subcontratar por el precio del escÃ¡ner (a 0,06 dÃ³lares c/u)</Text>
+</th>
+</tr>
+<tr>
+<th width="90">
+<Text id="108">EscÃ¡ner plano</Text>
+</th>
+<th width="71">
+<Text id="109">2.500</Text>
+</th>
+<th width="75">
+<Text id="110">0,072</Text>
+</th>
+<th width="83">
+<Text id="111">0,288</Text>
+</th>
+<th width="60">
+<Text id="112">300</Text>
+</th>
+<th width="66">
+<Text id="113">7.000</Text>
+</th>
+<th width="85">
+<Text id="114">5.000</Text>
+</th>
+</tr>
+<tr>
+<th width="90">
+<Text id="115">EscÃ¡ner con alimentador de papel</Text>
+</th>
+<th width="71">
+<Text id="116">8.000</Text>
+</th>
+<th width="75">
+<Text id="117">0,0225</Text>
+</th>
+<th width="83">
+<Text id="118">0,09</Text>
+</th>
+<th width="60">
+<Text id="119">800</Text>
+</th>
+<th width="66">
+<Text id="120">30.000 </Text>
+</th>
+<th width="85">
+<Text id="121">13.000</Text>
+</th>
+</tr>
+<tr>
+<th width="90">
+<Text id="122">Profesional: dÃºplex de gama baja</Text>
+</th>
+<th width="71">
+<Text id="123">40.000</Text>
+</th>
+<th width="75">
+<Text id="124">0,0045</Text>
+</th>
+<th width="83">
+<Text id="125">0,018</Text>
+</th>
+<th width="60">
+<Text id="126">6.000</Text>
+</th>
+<th width="66">
+<Text id="127">600.000</Text>
+</th>
+<th width="85">
+<Text id="128">100.000</Text>
+</th>
+</tr>
+<tr>
+<th width="90">
+<Text id="129">Profesional: dÃºplex de gama alta</Text>
+</th>
+<th width="71">
+<Text id="130">150.000</Text>
+</th>
+<th width="75">
+<Text id="131">0,0012</Text>
+</th>
+<th width="83">
+<Text id="132">0,0048</Text>
+</th>
+<th width="60">
+<Text id="133">50.000</Text>
+</th>
+<th width="66">
+<Text id="134">8.000.000</Text>
+</th>
+<th width="85">
+<Text id="135">833.000</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="136">Para determinar el precio por pÃ¡gina se multiplican los costos salariales por hora totales (que dependerÃ¡n de cada caso) por la segunda columna del Cuadro <CrossRef target="Table" ref="table_scanning_cost"/>. En la tercera columna se indica, a tÃ­tulo de ejemplo, el precio de escanear por cuenta propia suponiendo que se pague un sueldo de 4 dÃ³lares/hora, excluidos los gastos de inversiÃ³n.</Text>
+<Text id="137">Estos cÃ¡lculos presuponen que se procesa un nÃºmero de pÃ¡ginas suficiente para justificar la adquisiciÃ³n de un escÃ¡ner. En las tres Ãºltimas columnas del Cuadro <CrossRef target="Table" ref="table_scanning_cost"/> se ofrece informaciÃ³n sobre los costos derivados del propio escÃ¡ner. En la primera de ellas se indica el precio de adquisiciÃ³n de la mÃ¡quina, en la siguiente el tiempo de vida Ãºtil que se le supone y en la Ãºltima el nÃºmero de pÃ¡ginas que podrÃ­an subcontratarse por el precio del escÃ¡ner, contando una tarifa de 0,06 dÃ³lares/pÃ¡gina.</Text>
+<Text id="138">Hay, desde luego, muchos otros factores que influyen en la decisiÃ³n de adquirir o no un escÃ¡ner: la disponibilidad de fondos suficientes, la necesidad de reducir al mÃ­nimo la dependencia para con terceras partes, el deseo de crear capacidades a escala local, la obligaciÃ³n que imponen las bibliotecas de escanear los libros en la propia localidad y no transportarlos, etc.</Text>
+<Text id="139">Las cifras del Cuadro 1 dan una idea aproximada del nÃºmero de pÃ¡ginas necesario para justificar distintos niveles de inversiÃ³n. No es frecuente que una instituciÃ³n u otra entidad necesite escanear 800.000 pÃ¡ginas. Con tales niveles de trabajo se plantean cuestiones mÃ¡s complejas que no vamos a tratar en estas lÃ­neas, como el mantenimiento del equipo o la posibilidad de recuperar gastos ofreciendo a terceros el servicio de escaneado.</Text>
+<Text id="140">Es tentador contemplar el desarrollo de la capacidad de escaneado como una actividad comercial, sobre todo en los paÃ­ses en desarrollo. Pero conviene tener muy en cuenta que no se trata de un proceso repetitivo. Una vez escaneado un documento, el cliente nunca cursarÃ¡ un nuevo pedido para repetir la operaciÃ³n, por muy buena que haya sido su relaciÃ³n de trabajo con la empresa. Desde un punto de vista comercial, se requiere un enorme trabajo de publicidad y comercializaciÃ³n. Desaconsejamos a cualquier ONG u otras organizaciones sin fines de lucro que se aventuren en este terreno sin haber procedido a ensayos exhaustivos y elaborado un minucioso plan comercial.</Text>
+<Text id="141">En conclusiÃ³n, para escanear entre 10.000 y 50.000 pÃ¡ginas conviene plantearse la posibilidad de subcontratar el trabajo. Los cerca de 6.000 dÃ³lares que cuesta un escÃ¡ner profesional de gama baja sÃ³lo se amortizan a partir de un volumen superior a las 100.000 pÃ¡ginas. Otra posible soluciÃ³n consiste en asociarse con otras instituciones (ONG o bibliotecas, por ejemplo) para adquirir colectivamente un escÃ¡ner de ese tipo.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="ocr">
+<Title>
+<Text id="142">OCR: reconocimiento Ã³ptico de caracteres</Text>
+</Title>
+<Content>
+<Text id="143">Los sistemas de reconocimiento Ã³ptico de caracteres (OCR) transforman en texto una imagen escaneada. El punto de partida es una imagen digitalizada en formato TIFF o Bitmap, de la mayor nitidez y calidad posibles, y el resultado final un archivo de texto (generalmente en formato RTF o Word) o para la Web (formato HTML). </Text>
+<Text id="144">El proceso de conversiÃ³n de un documento impreso en un archivo informÃ¡tico comprende las siguientes etapas:</Text>
+<BulletList>
+<Bullet>
+<Text id="145">escaneado;</Text>
+</Bullet>
+<Bullet>
+<Text id="146">anÃ¡lisis de la compaginaciÃ³n;</Text>
+</Bullet>
+<Bullet>
+<Text id="147">reconocimiento Ã³ptico de caracteres;</Text>
+</Bullet>
+<Bullet>
+<Text id="148">escaneado de ilustraciones y cuadros.</Text>
+</Bullet>
+</BulletList>
+<Text id="149">A lo largo del proceso se efectÃºan controles de calidad de los archivos resultantes y se memorizan Ã©stos en el formato apropiado.</Text>
+<Text id="150">El mercado ofrece muchos y buenos programas de OCR, con precios que oscilan entre los 100 y los 400 dÃ³lares<FootnoteRef id="2"/>. Entre muchos otros ejemplos cabe citar los siguientes:</Text>
+<BulletList>
+<Bullet>
+<Text id="151"><i>Read-Iris</i>Â (http://www.readiris.com/)</Text>
+</Bullet>
+<Bullet>
+<Text id="152"><i>Omnipage</i>Â (http://www.omnipage.com/)</Text>
+</Bullet>
+<Bullet>
+<Text id="153"><i>Fine-Reader</i>Â (http://www.finereader.com/)</Text>
+</Bullet>
+</BulletList>
+<Text id="154">En los sitios Web de los fabricantes se ofrece toda la informaciÃ³n necesaria, comprendida la lista de distribuidores locales. Los autores, de acuerdo con su experiencia,Â  consideran que los programas de mÃ¡s fÃ¡cil manejo son Fine-Reader y Omnipage. El primero, que cuesta unos 100 dÃ³lares, es el mÃ¡s barato y ofrece no sÃ³lo gran flexibilidad sino tambiÃ©n el mayor repertorio de idiomas.</Text>
+<Text id="155">Es necesario decidir si se efectÃºan los procesos de escaneado y OCR internamente o se subcontratan a una empresa especializada. Hacerlo por cuenta propia exige disponer de un escÃ¡ner, de un programa de OCR, de conocimientos tÃ©cnicos en la materia y de personal muy motivado y atento a los requisitos de calidad.</Text>
+<Section id="the_ocr_process">
+<Title>
+<Text id="156">El proceso de OCR</Text>
+</Title>
+<Content>
+<Text id="157">El proceso de OCR difiere segÃºn se utilice uno u otro programa de OCR, y cada uno de ellos exige un tiempo considerable de aprendizaje. En el manual de cada programa se exponen todos los detalles relativos al proceso. Hay cuatro aspectos que merecen especial atenciÃ³n: el control de calidad, los cuadros, las ilustraciones y los textos especiales como fÃ³rmulas, caracteres extranjeros, etc.</Text>
+<Subsection id="quality_control_1">
+<Title>
+<Text id="158">Control de calidad</Text>
+</Title>
+<Content>
+<Text id="159">Es preciso insistir en la importancia del control de calidad. Lo ideal es que esos controles estÃ©n a cargo de personas cuya lengua materna sea el idioma en que estÃ¡ escrito el documento o de gente con un excelente dominio del mismo. El perfil idÃ³neo es el de alguien con estudios universitarios o secundarios. Conviene saber ademÃ¡s que en este tipo de tarea los jÃ³venes suelen mantener un nivel de concentraciÃ³n superior.</Text>
+<Text id="160">Normalmente hay cuatro controles de calidad.</Text>
+<Text id="161">El primero se efectÃºa al mismo tiempo que el proceso de OCR. Cada programa tiene un verificador ortogrÃ¡fico incorporado que seÃ±ala todas las posibles letras errÃ³neas y muestra la imagen de la palabra entera para facilitar la comprobaciÃ³n y eventual correcciÃ³n del error.</Text>
+<Text id="162">El segundo es un control general del texto una vez finalizado el proceso de OCR. Uno de los errores mÃ¡s frecuentes es la omisiÃ³n de una pÃ¡gina, un pÃ¡rrafo, los tÃ­tulos de un capÃ­tulo, etc. Debe llevarse a cabo un repaso general para comprobar que no falta ninguna pÃ¡gina. Es esencial asimismo comprobar los tÃ­tulos, los encabezamientos de capÃ­tulo, los pÃ¡rrafos y los cuadros.</Text>
+<Text id="163">El tercer control es el ortogrÃ¡fico, para el que en general se utiliza Word de Microsoft porque su diccionario suele ser mÃ¡s completo que el de los programas de OCR. Importando el libro a un archivo Word y realizando un control ortogrÃ¡fico con este programa se puede detectar y corregir un mayor nÃºmero de errores. Es indispensable aÃ±adir al verificador ortogrÃ¡fico cualquier palabra especialmente difÃ­cil o susceptible de generar una seÃ±al de error, asÃ­ como los tÃ©rminos cientÃ­ficos y tÃ©cnicos que abunden en el tipo de publicaciÃ³n con que se estÃ© trabajando. </Text>
+<Text id="164">Finalmente, otra persona debe efectuar un Ãºltimo control del documento finalizado, tomando al azar fragmentos del libro completo y cerciorÃ¡ndose de que no haya errores o problemas con los cuadros, las ilustraciones, las leyendas o el aspecto general del documento. SÃ³lo despuÃ©s de este Ãºltimo control puede considerarse que el libro estÃ¡ listo para su difusiÃ³n electrÃ³nica.</Text>
+</Content>
+</Subsection>
+<Subsection id="tables">
+<Title>
+<Text id="165">Cuadros</Text>
+</Title>
+<Content>
+<Text id="166">Los cuadros suelen plantear dificultades a los programas de OCR. Controlar su contenido es ademÃ¡s una labor ardua: contienen muchos dÃ­gitos, a veces con puntos y comas, y es fÃ¡cil que las cifras acaben colocadas en la casilla equivocada. Es una tarea que exige concentraciÃ³n, dedicaciÃ³n, un intenso trabajo de relectura, comprobaciones minuciosas y un buen control de calidad. Hay bÃ¡sicamente tres formas distintas de proceder.</Text>
+<Text id="167">La primera consiste simplemente en escanear los cuadros como si fueran imÃ¡genes en blanco y negro e insertarlos con este formato en el lugar correspondiente del documento. Esta es la soluciÃ³n mÃ¡s sencilla, pues no genera errores y no exige mÃ¡s tiempo que el necesario para crear la imagen. Pero consume mÃ¡s memoria que las dos restantes, y ademÃ¡s la resoluciÃ³n obtenida no siempre basta para trabajar en la computadora con cuadros de gran tamaÃ±o: si se reduce todo el cuadro a los lÃ­mites de la pantalla, la resoluciÃ³n es demasiado pequeÃ±a; si por el contrario el cuadro desborda la pantalla, el usuario debe desplazarse para ver todas las columnas y filas, con lo que pierde visiÃ³n de conjunto.</Text>
+<Text id="168">El segundo mÃ©todo es la copia manual: crear un nuevo cuadro con el mismo nÃºmero de filas y columnas y copiar los valores correspondientes a cada casilla, carÃ¡cter por carÃ¡cter.</Text>
+<Text id="169">La tercera soluciÃ³n consiste en someter el cuadro al proceso de OCR. Aunque este procedimiento ahorra tiempo en comparaciÃ³n con el manual, la probabilidad de error es mÃ¡s alta. A veces las columnas quedan fusionadas, o el programa es incapaz de reconocer los puntos y comas.</Text>
+</Content>
+</Subsection>
+<Subsection id="images">
+<Title>
+<Text id="170">Ilustraciones</Text>
+</Title>
+<Content>
+<Text id="171">Las ilustraciones contenidas en una publicaciÃ³n corresponden en general a tres grandes tipos de imagen:</Text>
+<BulletList>
+<Bullet>
+<Text id="172">ilustraciones en blanco y negro, sin tonos intermedios;</Text>
+</Bullet>
+<Bullet>
+<Text id="173">fotografÃ­as en blanco y negro;</Text>
+</Bullet>
+<Bullet>
+<Text id="174">fotografÃ­as en color.</Text>
+</Bullet>
+</BulletList>
+<Text id="175">Las ilustraciones en blanco y negro deben escanearse en modo âdibujos de lÃ­neas simplesâ y guardarse en formato GIF o PNG. Para las fotografÃ­as en blanco y negro conviene utilizar el modo âescala de grisesâ y guardar el resultado en archivos GIF o JPEG. En cuanto a las fotografÃ­as en color, es preciso escanearlas en modo âcolorâ y guardarlas en archivos JPEG. En tÃ©rminos generales, el formato JPEG de calidad media ofrece una resoluciÃ³n suficiente.</Text>
+<Text id="176">Las ilustraciones suelen consumir gran parte del espacio que ocupa una colecciÃ³n en el disco duro o el CD-ROM. De ahÃ­ la importancia de lograr para cada imagen la mayor claridad y visibilidad junto con el menor tamaÃ±o posible. Para ahorrar espacio cabe la posibilidad de prescindir de algunas imÃ¡genes o de todas ellas cuando no sean necesarias para entender el texto.</Text>
+<Text id="177">Las ilustraciones deben escanearse por separado, una por una. Para denominar los archivos grÃ¡ficos recomendamos un nombre compuesto por los cinco o seis primeros caracteres utilizados para designar el documento seguidos del nÃºmero de la pÃ¡gina en que se encuentre la ilustraciÃ³n. Una alternativa, suponiendo que haya un directorio para cada documento, consiste simplemente en utilizar la letraÂ <i>p</i>Â [Â <i>picture</i>Â ] seguida del nÃºmero de la pÃ¡gina. Cuando en una misma pÃ¡gina haya varias ilustraciones, bastarÃ¡ con aÃ±adir una letraÂ <i>a, b, c ...</i>Â al nombre del archivo. Por ejemplo, a una imagen JPEG que aparezca en la pÃ¡gina 36 de la antedicha publicaciÃ³nÂ <i>u7548e</i>Â corresponderÃ¡ un archivo llamadoÂ <i>u7548e36.jpg</i>Â oÂ <i>p36.jpg.</i></Text>
+<Text id="178">Una vez escaneadas las imÃ¡genes, se pueden aplicar programas de procesamiento por lotes para modificar las dimensiones o mejorar la definiciÃ³n de todas las imÃ¡genes a la vez.</Text>
+</Content>
+</Subsection>
+<Subsection id="specialized_material">
+<Title>
+<Text id="179">Textos con caracterÃ­sticas especiales</Text>
+</Title>
+<Content>
+<Text id="180">Muchos documentos contienen elementos que conviene tratar aparte (caracteres especiales, fÃ³rmulas, pÃ¡ginas especialmente dificultosas, etc.). Los caracteres especiales suelen provenir de idiomas distintos u ostentar marcas diacrÃ­ticas. En tal caso hay que seleccionar el idioma del que se trate en la opciÃ³n âidiomaâ del programa OCR. Las fÃ³rmulas deberÃ¡n reproducirse manualmente, lo que a veces es imposible con un programa de OCR, en cuyo caso hay que recurrir a un procesador de texto como Word de Microsoft. Las pÃ¡ginas de las que no pueda obtenerse una imagen nÃ­tida, ya sea por la complejidad del texto o por el mal estado en que se encuentren, deberÃ¡n ser reproducidas manualmente.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="productivity_and_resources_1">
+<Title>
+<Text id="181">Productividad y recursos necesarios</Text>
+</Title>
+<Content>
+<Text id="182">Como hemos dicho, no hay que subestimar la dificultad del proceso de OCR. Aunque conviene estudiar separadamente las alternativas econÃ³micas y prÃ¡cticas del proceso de escaneado y del de OCR, ambos plantean interrogantes parecidos: la inversiÃ³n necesaria en computadoras, la disponibilidad de personal y de capacidad de gestiÃ³n, la formaciÃ³n del personal, los costos salariales, el nÃºmero total de pÃ¡ginas que deben tratarse y las posibilidades de subcontratar el trabajo a terceros.</Text>
+<Text id="183">Esta secciÃ³n se basa en la experiencia de los autores en el trabajo de OCR en BÃ©lgica, Rumania y la India. Todos los ejemplos, cÃ¡lculos y cifras que aquÃ­ se exponen corresponden a una situaciÃ³n ordinaria: documentos de dificultad normal (con cuadros e ilustraciones) como los que pueden encontrarse en la mayorÃ­a de los archivos o bibliotecas, resultados de muy buena calidad y trabajo a medio o largo plazo.</Text>
+<Subsection id="intensive_ocr">
+<Title>
+<Text id="184">Trabajo intensivo de OCR</Text>
+</Title>
+<Content>
+<Text id="185">El OCR es un proceso difÃ­cil, que exige gran concentraciÃ³n y destreza. Antes de alcanzar un nivel Ã³ptimo de rendimiento y calidad, el operador necesita un periodo de aprendizaje de unas seis semanas.</Text>
+<Text id="186">Los mejores resultados y la productividad mÃ¡s alta se consiguen por lo general durante las primeras horas de trabajo. Al cabo de tres horas la productividad baja con rapidez, quizÃ¡ hasta un 50% del nivel inicial. Al cabo de seis horas, la mayorÃ­a de la gente se encuentra muy cansada.</Text>
+<Text id="187">Algo parecido ocurre durante las primeras semanas de trabajo, en las que todo el mundo alcanza una productividad bastante elevada. Posteriormente, sin embargo, hasta dos tercios de los operadores de OCR empiezan a sentirse aburridos y descontentos. A la larga esas personas acaban abandonando el trabajo o rindiendo poco en tÃ©rminos de calidad y productividad. Incluso los que superan el periodo crÃ­tico de tres a cinco semanas y se integran en el equipo de trabajo suelen renunciar y partir en busca de una mejor ocupaciÃ³n al cabo de 6 a 12 meses.</Text>
+<Text id="188">Las observaciones sobre el personal que formulamos en la secciÃ³n <CrossRef target="Section" ref="the_ocr_process"/>  son especialmente aplicables al trabajo intensivo de OCR. Los controles de calidad resultan mejores cuando corren a cargo de hablantes nativos o profundos conocedores del idioma en cuestiÃ³n. En general los jÃ³venes pueden mantener un nivel de concentraciÃ³n superior al de las personas mayores en las labores de OCR. La experiencia demuestra que las personas de entre 18 y 23 aÃ±os de edad tienden a adaptarse mejor a ese cometido que las mayores de 25 aÃ±os.</Text>
+<Text id="189">Por Ãºltimo, considerando lo aburrido que puede resultar el trabajo de OCR, la motivaciÃ³n y un constante prurito de calidad son elementos de excepcional importancia.</Text>
+<Text id="190">De todo lo dicho se desprenden las siguientes directrices generales sobre el proceso de OCR:</Text>
+<BulletList>
+<Bullet>
+<Text id="191">Los jÃ³venes de entre 18 y 25 aÃ±os de edad son los mÃ¡s aptos para este tipo de trabajo. </Text>
+</Bullet>
+<Bullet>
+<Text id="192">Dado que las primeras horas son siempre las mÃ¡s productivas, conviene organizar turnos de trabajo a tiempo parcial o, en su defecto, encomendar la labor a jornada completa a las personas mÃ¡s motivadas y con mayor capacidad de concentraciÃ³n.</Text>
+</Bullet>
+<Bullet>
+<Text id="193">DespuÃ©s de tres a cinco semanas de actividad, dos tercios de los operadores tienden a renunciar o a sentirse hastiados. Ello se traduce en un descenso de la calidad y la productividad en las Ãºltimas semanas.</Text>
+</Bullet>
+<Bullet>
+<Text id="194">Es preciso un suministro periÃ³dico de trabajo para justificar la necesaria formaciÃ³n del personal, mantener la concentraciÃ³n y conservar alta la moral del equipo.</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Subsection>
+<Subsection id="achievable_productivity">
+<Title>
+<Text id="195">Objetivos asequibles de productividad</Text>
+</Title>
+<Content>
+<Table id="table_ocr_productivity">
+<Title>
+<Text id="196">Productividad en el proceso de OCR</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="161"/>
+<th width="142">
+<Text id="197">Horas de trabajo/dÃ­a</Text>
+</th>
+<th width="123">
+<Text id="198">PÃ¡ginas/dÃ­a</Text>
+</th>
+<th width="104">
+<Text id="199">PÃ¡ginas/mes</Text>
+</th>
+</tr>
+<tr>
+<th width="161">
+<Text id="200">FormaciÃ³n inicialÂ (seis semanas)</Text>
+</th>
+<th width="142">
+<Text id="201">3</Text>
+</th>
+<th width="123">
+<Text id="202">6</Text>
+</th>
+<th width="104">
+<Text id="203">120</Text>
+</th>
+</tr>
+<tr>
+<th width="161">
+<Text id="204">Nivel Ã³ptimo de productividad</Text>
+</th>
+<th width="142">
+<Text id="205">3</Text>
+</th>
+<th width="123">
+<Text id="206">9</Text>
+</th>
+<th width="104">
+<Text id="207">150 a 200</Text>
+</th>
+</tr>
+<tr>
+<th width="161">Â </th>
+<th width="142">
+<Text id="208">7</Text>
+</th>
+<th width="123">
+<Text id="209">28</Text>
+</th>
+<th width="104">
+<Text id="210">500 a 600</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="211">En el Cuadro <CrossRef target="Table" ref="table_ocr_productivity"/> se presentan las cifras mÃ¡s frecuentes de productividad en el trabajo de OCR. Teniendo en cuenta que puede tratarse de documentos de todos los tamaÃ±os y niveles de calidad, estas cifras parten del supuesto de que el conjunto de documentos contiene un nÃºmero promedio de ilustraciones y cuadros (por ejemplo una ilustraciÃ³n y un cuadro de 5x5 cada ocho pÃ¡ginas), que las ilustraciones son de calidad entre media y alta (recordemos que ello depende de la calidad del escaneado) y que los operadores de OCR dominan el idioma en que estÃ¡ escrito el documento.</Text>
+<Text id="212">En el Cuadro <CrossRef target="Table" ref="table_ocr_productivity"/> se distingue entre las estadÃ­sticas de personas en periodo de formaciÃ³n y las de quienes han alcanzado su nivel Ã³ptimo de productividad. Si un miembro del personal administrativo dedicara tres horas diarias al trabajo de OCR, su rendimiento serÃ­a de entre 180 y 200 pÃ¡ginas al mes. Un operador a jornada completa bien formado, con gran capacidad de concentraciÃ³n y escrupulosa atenciÃ³n a los criterios de calidad, en cambio, podrÃ­a alcanzar una productividad de entre 500 y 600 pÃ¡ginas al mes.</Text>
+<Text id="213">Sin embargo, con pÃ¡ginas de especial dificultad y escasa calidad, con abundantes cuadros o columnas, se obtienen cifras muy inferiores (quizÃ¡ de 300 a 400 pÃ¡ginas mensuales a jornada completa).</Text>
+<Text id="214">Supongamos que el costo salarial de un operador a jornada completa muy aplicado y motivado asciende a 400 dÃ³lares mensuales, y que los gastos generales (gastos de gestiÃ³n, computadoras, espacio de oficina, instalaciones, etc.) suponen otros 300 a 400 dÃ³lares mensuales por persona. En tal caso, el costo del proceso de OCR viene a ser de 1,2 a 1,6 dÃ³lares por pÃ¡gina. Si ademÃ¡s se toma en cuenta el periodo de formaciÃ³n, el volumen total, el lapso de tiempo considerado y los eventuales costes de la suspensiÃ³n de las operaciones cuando falte el trabajo, el costo asciende a un valor entre 1,5 y 2,5 dÃ³lares por pÃ¡gina.</Text>
+<Text id="215">Conviene comparar los costos del proceso de OCR efectuado por cuenta propia con los de la subcontrataciÃ³n a una empresa especializada. Estas empresas suelen cobrar entre 1,5 y 4 dÃ³lares por pÃ¡gina, incluyendo las ilustraciones y los cuadros. Human Info/Simple Word, que posee una unidad de este tipo en Rumania, aplica tarifas especiales para las organizaciones humanitarias sin fines de lucro (entre 1,2 y 2 dÃ³lares por pÃ¡gina). Puede solicitarse informaciÃ³n o asesoramiento escribiÃ©ndonos a la direcciÃ³n:scanning@humaninfo.org.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="alternatives_to_ocr">
+<Title>
+<Text id="216">Alternativas al proceso de OCR</Text>
+</Title>
+<Content>
+<Text id="217">En las siguientes lÃ­neas exponemos dos posibles alternativas al OCR.</Text>
+<Subsection id="manual_retyping">
+<Title>
+<Text id="218">Mecanografiado manual</Text>
+</Title>
+<Content>
+<Text id="219">La primera posibilidad, que ademÃ¡s elimina buena parte del escaneado, consiste en mecanografiar de nuevo los documentos con un programa de tratamiento de texto. Utilizando este procedimiento hay que escanear Ãºnicamente las ilustraciones y la cubierta (y no las restantes pÃ¡ginas), lo que hace innecesario disponer de un escÃ¡ner y un programa de OCR potentes. </Text>
+<Text id="220">No es preciso que los operadores entiendan el texto. SÃ³lo tienen que ser buenos mecanÃ³grafos y reproducir exactamente lo que ven. Dado que este proceso suele generar errores, a menudo se utiliza el doble mecanografiado para detectarlos y corregirlos. Este mÃ©todo requiere que dos personas mecanografÃ­en independientemente el mismo documento, despuÃ©s de lo cual un operador provisto del texto original compara ambas versiones electrÃ³nicas palabra por palabra, con ayuda de un programa informÃ¡tico especial. Se parte de la premisa de que si una misma palabra ha sido escrita dos veces por separado de la misma manera, serÃ¡ correcta. Pero ello no siempre es asÃ­, y cuando se quiere trabajar con la mÃ¡xima fiabilidad se recurre al triple mecanografiado.</Text>
+<Text id="221">Teniendo en cuenta que el uso de un programa de OCR entraÃ±a el de computadoras de gran potencia, la ventaja bÃ¡sica de este mÃ©todo es que prescinde del OCR y por lo tanto permite utilizar computadoras mÃ¡s antiguas, sencillas o de segunda mano, lo que supone un ahorro considerable. AdemÃ¡s, esta labor requiere trabajadores menos especializados. En cuanto a sus inconvenientes, Ã©stos residen en el periodo de formaciÃ³n (de al menos dos meses) que se necesita y en la abundancia de errores que suelen darse con un proceso de mecanografiado Ãºnico, lo que obliga a trabajar por duplicado o triplicado.</Text>
+<Text id="222">Los costos de este procedimiento dependen exclusivamente del nivel salarial. Los mecanÃ³grafos de paÃ­ses en desarrollo suelen cobrar unos 150 dÃ³lares mensuales. Su productividad oscila entre 20 y 30 pÃ¡ginas diarias, lo que equivale a 400 pÃ¡ginas mensuales, comprendidas las ilustraciones. Suponiendo que se trabaje por duplicado, los costos salariales suman en total 300 dÃ³lares al mes, sin contar los gastos generales.</Text>
+</Content>
+</Subsection>
+<Subsection id="image_files">
+<Title>
+<Text id="223">Archivos grÃ¡ficos</Text>
+</Title>
+<Content>
+<Text id="224">Una alternativa sumamente barata al proceso de OCR consiste en utilizar simplemente una versiÃ³n grÃ¡fica en PDF de las pÃ¡ginas del documento, lo que reduce los costos a unos 0,1 dÃ³lares por pÃ¡gina (una pequeÃ±a fracciÃ³n de lo que costarÃ­a un proceso de OCR).</Text>
+<Text id="225">Una vez concluido el escaneado y creados los archivos TIFF, se utiliza un convertidor automÃ¡tico (en general Acrobat o Photoshop de Adobe) para convertir en formato PDF todos los archivos TIFF correspondientes a las pÃ¡ginas del libro.</Text>
+<Text id="226">El problema es que en esos archivos no se pueden efectuar bÃºsquedas y que ademÃ¡s son bastante pesados (por lo general 50 Kb por pÃ¡gina, con un margen de variaciÃ³n del 20% segÃºn la calidad del archivo TIFF original).</Text>
+<Text id="227">La descarga de un archivo grÃ¡fico PDF es un proceso lento, a veces imposible o de precio prohibitivo en los paÃ­ses en desarrollo. Esos archivos caben rara vez en un disquete y no admiten operaciones de manipulaciÃ³n del texto como la de âcortar y pegarâ.</Text>
+<Text id="228">SÃ³lo se optarÃ¡ por esta soluciÃ³n cuando se carezca del presupuesto necesario para un proceso de OCR o cuando se trate de documentos destinados a un pÃºblico poco numeroso y provisto de una conexiÃ³n a Internet de bajo costo y alta velocidad.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="combining_scanning_and_ocr">
+<Title>
+<Text id="229">CombinaciÃ³n de escaneado y OCR</Text>
+</Title>
+<Content>
+<Text id="230">La mayorÃ­a de los programas de OCR pueden escanear una pÃ¡gina y efectuar inmediatamente el reconocimiento Ã³ptico, a condiciÃ³n de que el escÃ¡ner estÃ© conectado directamente a la computadora que ejecuta el programa. Aunque escanear y efectuar el OCR pÃ¡gina a pÃ¡gina es un mÃ©todo razonable cuando se trabaja con pocos documentos, resulta muy largo para trabajos mÃ¡s voluminosos y continuos.</Text>
+<Text id="231">Esta soluciÃ³n es adecuada para cantidades entre 100 a 150 pÃ¡gina al mes. Para tratar volÃºmenes superiores, en cambio, es mÃ¡s rÃ¡pido y eficaz escanear en primer lugar el documento y aplicar despuÃ©s el proceso de OCR a todas las pÃ¡ginas de una sola vez.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="three_examples">
+<Title>
+<Text id="232">De 1.000 a 100.000 pÃ¡ginas en tres ejemplos</Text>
+</Title>
+<Content>
+<Section id="typical_small_collection">
+<Title>
+<Text id="233">Una colecciÃ³n de pequeÃ±as dimensiones: de 500 a 1.000 pÃ¡ginas</Text>
+</Title>
+<Content>
+<Text id="234">La mayorÃ­a de las ONG tienen un volumen de 500 a 1.000 pÃ¡ginas por escanear. Si disponen de voluntarios motivados pueden asumir por cuenta propia el proceso de OCR.</Text>
+<Part id="scanning">
+<Title>
+<Text id="235">Escaneado</Text>
+</Title>
+<Content>
+<Text id="236">El primer paso consiste en escanear las publicaciones para generar un archivo TIFF de alta calidad para cada pÃ¡gina y una imagen bitmap independiente (ya sea de dibujo de lÃ­neas simples, escala de grises o color) para cada ilustraciÃ³n. Suponiendo que deban escanearse 1.000 pÃ¡ginas, ello puede equivaler a cerca de un mes de trabajo a tiempo parcial (sÃ³lo para el escaneado). Los archivos TIFF ocuparÃ­an entre 60 y 80 Mb de espacio en el disco duro, por lo que es aconsejable utilizar un CD-ROM para dar cabida a esos archivos. Un escÃ¡ner plano de precio reducido (entre 100 y 300 dÃ³lares) basta para realizar ese trabajo, del que puede ocuparse un voluntario despuÃ©s de la jornada laboral o durante los fines de semana, ya sea en la oficina o en casa.</Text>
+</Content>
+</Part>
+<Part id="ocr">
+<Title>
+<Text id="237">OCR</Text>
+</Title>
+<Content>
+<Text id="238">La segunda etapa es la del proceso de OCR, que se encomendarÃ¡ a otro voluntario, o equipo de voluntarios, con buenos conocimientos lingÃŒÃ­sticos y de correcciÃ³n ortogrÃ¡fica. Cabe la posibilidad de repartir los archivos TIFF entre varias computadoras o bien de utilizar una sola mÃ¡quina para la totalidad del trabajo. Por lo general se requieren entre cinco y seis meses de trabajo a tiempo parcial (a razÃ³n de 20 horas semanales, por ejemplo) para convertir 1.000 pÃ¡ginas en documentos impecables en formato Word o HTML.</Text>
+</Content>
+</Part>
+<Part id="outsourcing">
+<Title>
+<Text id="239">SubcontrataciÃ³n</Text>
+</Title>
+<Content>
+<Text id="240">Una posibilidad alternativa es la de subcontratar los procesos de escaneado y OCR. La conversiÃ³n de todos los documentos en archivos Word y HTML impecables costarÃ­a probablemente entre 1.500 y 2.000 dÃ³lares.</Text>
+</Content>
+</Part>
+</Content>
+</Section>
+<Section id="all_publications_from_an_organization">
+<Title>
+<Text id="241">Todas las publicaciones de una organizaciÃ³n: 5.000 pÃ¡ginas</Text>
+</Title>
+<Content>
+<Text id="242">Los archivos de muchas organizaciones de mayor tamaÃ±o pueden contener unas 5.000 pÃ¡ginas de libros (en catÃ¡logo o agotados), revistas, boletines, documentos, etc.</Text>
+<Part id="scanning_1">
+<Title>
+<Text id="243">Escaneado</Text>
+</Title>
+<Content>
+<Text id="244">Se trata de un volumen excesivo para un escÃ¡ner plano, lo que deja dos opciones: subcontratar el trabajo (contando unos 400 dÃ³lares por 5.000 pÃ¡ginas) o adquirir un escÃ¡ner con alimentador de papel (aproximadamente 900 dÃ³lares). Otra alternativa es que varias instituciones u ONG adquieran conjuntamente un escÃ¡ner mÃ¡s caro (6.000 dÃ³lares, divididos por el nÃºmero de participantes). Las 5.000 pÃ¡ginas en formato TIFF ocuparÃ­an entre 300 y 400 Mb en el disco duro. SeÃ±alemos de nuevo la conveniencia de utilizar un CD-ROM para guardar esos archivos.</Text>
+</Content>
+</Part>
+<Part id="ocr_1">
+<Title>
+<Text id="245">OCR</Text>
+</Title>
+<Content>
+<Text id="246">A continuaciÃ³n hay que ocuparse del proceso de OCR, que puede encargarse a otro voluntario, o equipo de voluntarios, diestro en tÃ©cnicas de OCR y correcciÃ³n ortogrÃ¡fica. Como en el caso anterior, es posible utilizar varias computadoras o una sola para esta tarea. La conversiÃ³n de 5.000 pÃ¡ginas en archivos Word o HTML impecables exigirÃ­a entre 25 y 30 meses de trabajo a tiempo parcial (a razÃ³n de 20 horas semanales), lo que en la prÃ¡ctica descarta el empleo exclusivo de voluntarios porque lleva demasiado tiempo y requiere un uso excesivo de la computadora. Para concluir el trabajo en un plazo razonable y con un buen nivel de calidad habrÃ­a que pagar a los voluntarios, supervisar su rendimiento y la calidad de su labor, proporcionarles espacio adecuado, etc.</Text>
+<Text id="247">Una posibilidad alternativa es la de crear archivos grÃ¡ficos PDF, que ocuparÃ­an entre 300 y 400 Mb de memoria y resultarÃ­an mÃ¡s difÃ­ciles de descargar de Internet.</Text>
+</Content>
+</Part>
+<Part id="outsourcing_1">
+<Title>
+<Text id="248">SubcontrataciÃ³n</Text>
+</Title>
+<Content>
+<Text id="249">Otra alternativa es la de subcontratar los procesos de escaneado y OCR, lo que costarÃ­a probablemente entre 7.500 y 10.000 dÃ³lares.</Text>
+</Content>
+</Part>
+</Content>
+</Section>
+<Section id="a_small_library">
+<Title>
+<Text id="250">Una pequeÃ±a biblioteca: 100.000 pÃ¡ginas</Text>
+</Title>
+<Content>
+<Text id="251">Otras entidades de mayor envergadura, universidades, gobiernos o bibliotecas especializadas podrÃ­an tener una biblioteca entera por digitalizar, algo asÃ­ como unas 100.000 pÃ¡ginas. Lo primero que se debe tener en cuenta es la situaciÃ³n de las publicaciones en materia de derecho de autor: bien estÃ¡n incluidas en el dominio pÃºblico o bien hay que obtener permiso explÃ­cito de los titulares de los derechos para poder digitalizarlas. Conviene cerciorarse asimismo de que los documentos no existen ya en formato electrÃ³nico.</Text>
+<Part id="scanning_2">
+<Title>
+<Text id="252">Escaneado</Text>
+</Title>
+<Content>
+<Text id="253">100.000 pÃ¡ginas son demasiadas para un escÃ¡ner con alimentador de papel, por lo que caben dos opciones: subcontratar el trabajo (a unos 8.000 dÃ³lares las 100.000 pÃ¡ginas) o adquirir, conjuntamente con otras instituciones u ONG, un equipo de mayor calidad y precio (6.000 dÃ³lares, divididos entre los participantes). 100.000 pÃ¡ginas en formato TIFF ocuparÃ¡n entre 6 y 8 Gb en el disco duro. Lo ideal es crear copias de esos archivos en discos CD-ROM.</Text>
+</Content>
+</Part>
+<Part id="ocr_2">
+<Title>
+<Text id="254">OCR</Text>
+</Title>
+<Content>
+<Text id="255">La segunda etapa es el proceso de OCR (en el caso de documentos menos utilizados, tambiÃ©n cabe la posibilidad de crear archivos PDF). Convertir 100.000 pÃ¡ginas en archivos Word o HTML impecables llevarÃ­a entre 500 y 700 meses de trabajo a tiempo parcial, lo que a todas luces descarta el uso de voluntarios para esta tarea, mÃ¡s propia de profesionales.</Text>
+<Text id="256">Para ahorrar costos se pueden convertir en PDF algunas de las pÃ¡ginas menos utilizadas (digamos el 80%, u 80.000 pÃ¡ginas), reservando los formatos Word o HTML para las 20.000 pÃ¡ginas restantes. Los archivos PDF ocuparÃ­an entre 4 y 6 Gb de espacio y no serÃ­a fÃ¡cil descargarlos de Internet, pero en cambio saldrÃ­an baratos si los creara una empresa especializada (sÃ³lo 0,2 dÃ³lares por pÃ¡gina, lo que supone un costo total de 16.000 dÃ³lares). Utilizando voluntarios para crear 80.000 archivos PDF a partir de archivos TIFF mediante programas de conversiÃ³n como Acrobat de Adobe se precisarÃ­an 10 a 20 meses de trabajo a tiempo parcial con una computadora de gran potencia.</Text>
+</Content>
+</Part>
+<Part id="outsourcing_2">
+<Title>
+<Text id="257">SubcontrataciÃ³n</Text>
+</Title>
+<Content>
+<Text id="258">Una posible alternativa es la de subcontratar el trabajo. Suponiendo que se mantuviera la mencionada proporciÃ³n del 80% en PDF y el 20% en HTML, los archivos PDF costarÃ­an unos 16.000 dÃ³lares y los archivos HTML entre 30.000 y 40.000 dÃ³lares, con lo que el presupuesto total ascenderÃ­a a unos 50.000 dÃ³lares. Si se sometieran todos los documentos a un proceso de OCR, convertir toda la colecciÃ³n en archivos Word y HTML impecables costarÃ­a entre 150.000 y 200.000 dÃ³lares.</Text>
+</Content>
+</Part>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="creating_an_electronic_collection">
+<Title>
+<Text id="259">CreaciÃ³n de una colecciÃ³n digital</Text>
+</Title>
+<Content>
+<Text id="260">Hay tres aspectos importantes que conviene tener en cuenta a la hora de crear una colecciÃ³n digital. En primer lugar es preciso organizarla. A mayor volumen de contenido, mayor necesidad hay de Ã­ndices y sistemas potentes de bÃºsqueda, indispensables cuando la colecciÃ³n supera las 3.000 a 5.000 pÃ¡ginas. En segundo lugar, deben prevalecer las necesidades del usuario final. Es preciso identificar los grupos que usarÃ¡n la colecciÃ³n y establecer un proceso de consulta periÃ³dica con ellos. En tercer lugar, el presupuesto disponible determinarÃ¡ quÃ© tanto se puede hacer.</Text>
+<Section id="methods_of_collection_building">
+<Title>
+<Text id="261">MÃ©todos para crear colecciones</Text>
+</Title>
+<Content>
+<Text id="262">Abundan los ejemplos de excelentes CD-ROM elaborados siguiendo el modelo de una pÃ¡gina Web, en la que por medio de hipervÃ­nculos se insertan y enlazan entre sÃ­ documentos en formato HTML, PDF o Word. El uso de hipervÃ­nculos, marcos y grupos estructurados, palabras clave, Ã­ndices y demÃ¡s elementos de este tipo hace fÃ¡cil y atractiva la navegaciÃ³n. Estos sistemas funcionan bien con volÃºmenes de unos cuantos miles de pÃ¡ginas, pero a partir de 3.000 a 5.000 pÃ¡ginas es importante que la colecciÃ³n estÃ© bien organizada y ofrezca un dispositivo de bÃºsqueda potente. AhÃ­ es donde el programa Greenstone puede resultar de utilidad.</Text>
+<Text id="263">El programa Greenstone crea una biblioteca digital estructurada y provista de un poderoso buscador y un mecanismo de recuperaciÃ³n. Es posible indexar hasta 150,000 pÃ¡ginas en un solo CD-ROM, que ademÃ¡s puede funcionar como servidor de Internet. Greenstone es un software de cÃ³digo fuente abierto y por lo tanto puede obtenerse gratuitamente bajo las condiciones estipuladas en la Licencia PÃºblica General de GNU.</Text>
+<Text id="264">En los manuales de consulta que acompaÃ±an al programa se explica cÃ³mo crear colecciones Greenstone. BÃ¡sicamente existen tres formas de hacerlo.</Text>
+<BulletList>
+<Bullet>
+<Text id="265">Con la interfaz de bibliotecario</Text>
+</Bullet>
+<Bullet>
+<Text id="266">Con el programa de recopilaciÃ³n, tambiÃ©n conocido como Colector</Text>
+</Bullet>
+<Bullet>
+<Text id="267">Crearlas desde la lÃ­nea de comandos.</Text>
+</Bullet>
+</BulletList>
+<Text id="268">El primer mÃ©todo corresponde a la interfaz de bibliotecario descrita laÂ <i>GuÃ­a del Usuario de la Biblioteca Digital Greenstone</i>Â (CapÃ­tulo 3, âCreando colecciones Greenstoneâ). Ãsta es una herramienta interactiva para la creaciÃ³n de colecciones que permite reunir grupos de documentos, importar o asignar metadatos e integrarlos a una colecciÃ³n. El segundo mÃ©todo es el subsistema de recopilaciÃ³n descrito en el CapÃ­tulo 4 de laÂ <i>GuÃ­a del Usuario</i>Â llamado âColectorâ. Se trata de una herramienta que aparece en versiones anteriores y ofrece una alternativa para la creaciÃ³n de colecciones de pÃ¡ginas web u otros documentos, guiÃ¡ndolo a travÃ©s de una secuencia de pÃ¡ginas Web interactivas que solicitan la informaciÃ³n conforme vaya siendo necesaria. No obstante, no proporciona ninguna forma de agregar metadatos a los documentos y, debido a su interfaz Web, no es realmente adecuada para colecciones cuya construcciÃ³n requiera mÃ¡s de unos cuantos minutos. El tercer mÃ©todo es ejecutar los programas que permiten construir la colecciÃ³n directamente desde la lÃ­nea de comandos que se encuentra en el CapÃ­tulo 1 de laÂ <i>GuÃ­a del Programador de la Biblioteca Digital Greenstone</i>. Este mÃ©todo le ofrece una mayor flexibilidad para ejecutar los programas de manera individual y le ahorra los pasos intermedios que quizÃ¡ fueran deseables para colecciones que requirieran de muchas horas en su construcciÃ³n. TambiÃ©n necesitarÃ¡ leer el CapÃ­tulo 2 con el fin de aprovechar todo el poder que le ofrece Greenstone para la creaciÃ³n de colecciones avanzadas.</Text>
+<Text id="269">Existe una cuarta herramienta para crear y editar el material asociado a una colecciÃ³n llamada Organizador. Sin embargo, sus funciones han sido sustituidas por las de la interfaz de bibliotecario mencionada arriba. Este mÃ©todo se describe en el documento tituladoÂ <i>Uso del Organizador.</i>
+</Text>
+</Content>
+</Section>
+<Section id="getting_started_in_seven_steps_and_15_minutes">
+<Title>
+<Text id="270">Aprendiendo a usar la interfaz en siete pasos y 15 minutos</Text>
+</Title>
+<Content>
+<Text id="271">La mejor forma de conocer las caracterÃ­sticas y el funcionamiento de la interfaz de bibliotecario Â es crear una pequeÃ±a biblioteca de prueba. Si dispone de 15 minutos, por favor siga los pasos que se indican a continuaciÃ³n y asÃ­ usted obtendrÃ¡ una mejor comprensiÃ³n de este programa.</Text>
+<Text id="272">Antes de empezar lo primero que deberÃ¡ hacer es instalar Greenstone (vea laÂ <i>GuÃ­a de InstalaciÃ³n</i>), el cual incluye una colecciÃ³n de muestra en formato DLS y sus archivos fuente.Â <b>Recuerde, si desea aÃ±adir a su colecciÃ³n cualquiera de los 140 documentos de la colecciÃ³n DLS completa (en vez de sÃ³lo los 11 de esta colecciÃ³n de muestra) tambiÃ©n deberÃ¡ instalar la DLS como una de las bibliotecas Greenstone de muestra.</b>Â Las colecciones de muestra y DLS se instalarÃ¡n enÂ <i>C:\Program Files\gsdl\collect</i>, en los subdirectoriosÂ <i>demo</i>Â yÂ <i>dls</i>Â respectivamente. Si anteriormente usted ya instalÃ³ Greenstone sin la colecciÃ³n DLS y desea instalarla ahora, sÃ³lo tiene que insertar nuevamente el CD-ROM Greenstone y aÃ±adir la colecciÃ³n. No es necesario desinstalar Greenstone primero.</Text>
+<Text id="273">Le sugerimos que imprima las instrucciones que aparecen a continuaciÃ³n y las siga paso a pasoÂ :</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="274">Para iniciar la interfaz bajo Windows seleccioneÂ <i>Biblioteca Digital Greenstone</i>Â en la secciÃ³n deÂ <i>Programas</i>Â del menÃº deÂ <i>Inicio</i>Â y elijaÂ <i>Interfaz de Bibliotecario</i>Si en vez de Windows usted estÃ¡ usando UNIX escriba:</Text>
+<CodeLine>cd ~/gsdl</CodeLine>
+<CodeLine>cd gli</CodeLine>
+<CodeLine>./gli.sh</CodeLine>
+<Text id="275">dondeÂ <i>~/gsdl</i>Â es el directorio que contiene su sistema Greenstone.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="276">SeleccioneÂ <i>Nueva</i>Â en el menÃº Archivo que se encuentra en la barra horizontal en la parte superior de la ventana. Dele un tÃ­tulo, por ejemplo âMi primera colecciÃ³nâ y escriba su direcciÃ³n de correo electrÃ³nico y una breve descripciÃ³n de la colecciÃ³n. En el menÃº âBasar esta colecciÃ³n enâ elija âcolecciÃ³n de muestra Greenstoneâ o âSubconjunto de la Biblioteca para el Desarrolloâ (DLS por sus siglas en inglÃ©s). El efecto es el mismo, ya que ambas colecciones tienen la misma estructura.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="277">AÃ±ada algunos documentos de la colecciÃ³n de muestra (o de la colecciÃ³n DLS si estÃ¡ instalada) a su nueva colecciÃ³n. Para ello haga doble click en la carpeta deÂ <i>Colecciones Greenstone</i>Â en el cuadro izquierdo y a continuaciÃ³n haga doble click en la colecciÃ³n que prefiera. Los documentos que hay en ella aparecerÃ¡n en pantalla. Seleccione uno, arrÃ¡strelo y colÃ³quelo en el cuadro derecho. Este panel representa la colecciÃ³n que estÃ¡ construyendo. Elija varios documentos y arrÃ¡strelos uno por uno o seleccione y arrastre varios de ellos al mismo tiempo de la manera normal.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="278">Agregue algunos de sus propios documentos que no estÃ©n en la colecciÃ³n de muestra o en la DLS. Cierre la carpeta deÂ <i>Colecciones Greenstone</i>Â en el cuadro izquierdo y haga doble click en la carpetaÂ <i>Local Filespace (Espacio de archivo local)</i>Vaya a un directorio que contenga algunos documentos (p. ej. pequeÃ±os archivos de Word o HTML) y arrastre unos cuantos de ellos al cuadro derecho para incluirlos en su colecciÃ³n.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="279">AÃ±ada metadatos a los documentos de su colecciÃ³n. Hasta este momento usted ha estado operando en el panel indicado por medio de la pestaÃ±aÂ <i>Gather (Reunir)</i>Â que se encuentra debajo de la barra de menÃºs horizontal en la parte superior de la ventana. Haga click en la pestaÃ±aÂ <i>Enrich (Enriquecer)</i>Â que se encuentra a un lado. Los documentos de su colecciÃ³n aparecerÃ¡n ahora en el cuadro del lado izquierdo. Haga click en uno y examine los metadatos asociados a Ã©l que se muestran en la tablaÂ <i>âElement ... Valueâ (Elemento ... Valor)</i>Â en la parte superior derecha. Use el cuadro que estÃ¡ debajo para cambiar los valores individuales seleccionando el elemento que desee y escogiendo un valor existente de la lista o escribiendo un nuevo valor en el recuadro que se encuentra cerca de la parte inferior. AÃ±ada los metadatosÂ <i>TÃ­tulo</i>,Â <i>OrganizaciÃ³n</i>Â yÂ <i>Palabra clave</i>Â para cada uno de sus documentos que quiera poner en la colecciÃ³n. DespuÃ©s de escribir cada valor usted necesitarÃ¡ hacer click enÂ <i>âAppendâ (Agregar)</i>Â para guardar dicho valor.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="280">Haga click en la pestaÃ±aÂ <i>Create (Crear)</i>Â para salir del modoÂ <i>Enriquecer</i>Â y crear su nueva colecciÃ³n. Haga click en el botÃ³nÂ <i>Build Collection (Construir la colecciÃ³n)</i>Â que se encuentra en la parte inferior. Conforme la computadora va construyendo la colecciÃ³n usted recibirÃ¡ informaciÃ³n sobre lo que estÃ¡ haciendo.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="281">Una vez que haya terminado haga click en la pestaÃ±aÂ <i>Preview (Vista previa)</i>Â para ver la colecciÃ³n desde el interior de la interfaz de bibliotecario. Revise las listas deÂ <i>tÃ­tulos de la âaâ la âzâ</i>,Â <i>organizaciones</i>Â yÂ <i>cÃ³mo hacer</i>Â para asegurarse de que sus documentos han sido incluidos en la colecciÃ³n. Asimismo cuando visite su pÃ¡gina principal de Greenstone usted encontrarÃ¡ que la colecciÃ³n ha sido instalada como una de las colecciones regulares.</Text>
+</NumberedItem>
+</NumberedList>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<FootnoteList>
+<Footnote id="1">
+<Text id="282">Todos los importes indicados en este documento se expresan en dÃ³lares estadounidenses y corresponden a las tarifas vigentes en 2001.</Text>
+</Footnote>
+<Footnote id="2">
+<Text id="283">Recordemos que todos los importes estÃ¡n expresados en dÃ³lares estadounidenses de 2001 y corresponden a las tarifas vigentes en 2001.</Text>
+</Footnote>
+</FootnoteList>
+</Manual>
Index: /tags/start/gsdl-documentation/manuals/xml-source/es/User_es.xml
===================================================================
--- /tags/start/gsdl-documentation/manuals/xml-source/es/User_es.xml	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/xml-source/es/User_es.xml	(revision 13666)
@@ -0,0 +1,2504 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Manual>
+<Heading>
+<Text id="1">BIBLIOTECA DIGITAL GREENSTONE</Text>
+</Heading>
+<Title>
+<Text id="2">GUÃA DEL USUARIO</Text>
+</Title>
+<Author>
+<Text id="3">Ian H. Witten, Stefan Boddie y John Thompson</Text>
+</Author>
+<Affiliation>
+<Text id="4">Departamento de InformÃ¡ticaÂ <br/>Universidad de Waikato, Nueva Zelanda</Text>
+<Text id="5">Greenstone es un conjunto de programas y aplicaciones de software especialmente diseÃ±ados para la creaciÃ³n y difusiÃ³n de colecciones documentales digitales, el cual le ofrece una nueva forma de organizar la informaciÃ³n y publicarla en Internet o CD-ROM. Greenstone ha sido elaborado como parte del proyecto de Biblioteca Digital de Nueva Zelanda de la Universidad de Waikato y actualmente es desarrollado y distribuido en colaboraciÃ³n con la UNESCO y la ONG Human Info. Es un software de cÃ³digo abierto disponible enÂ <i>http://greenstone.org</i>Â bajo los tÃ©rminos y condiciones de la Licencia PÃºblica General de GNU.</Text>
+</Affiliation>
+<Comment>
+<Text id="6">Queremos estar seguros que este software trabaje bien para usted. Por favor comunÃ­quenos cualquier problema que tenga con Ã©l a la siguiente direcciÃ³n: <i> greenstone@cs.waikato.ac.nz</i></Text>
+</Comment>
+<Version>
+<Text id="7">Greenstone gsdl-2.70</Text>
+</Version>
+<Date>
+<Text id="8">Marzo de 2006</Text>
+</Date>
+<Section id="acknowledgements">
+<Title>
+<Text id="9">Acerca de este manual</Text>
+</Title>
+<Content>
+<Text id="10">Este manual ofrece una descripciÃ³n completa de la manera de utilizar el programa Greenstone para crear y tener acceso a colecciones de bibliotecas digitales.</Text>
+<Text id="11">En la SecciÃ³n <CrossRef target="Chapter" ref="overview_of_greenstone"/> se da una visiÃ³n general de las posibilidades del programa. En la SecciÃ³n <CrossRef target="Chapter" ref="using_greenstone_collections"/> se explica cÃ³mo utilizar las colecciones de Greenstone. La interfaz es lo suficientemente explÃ­cita y la mejor manera de aprender es utilizÃ¡ndola; esta secciÃ³n comprende la informaciÃ³n de ayuda en lÃ­nea para una colecciÃ³n tÃ­pica. En la SecciÃ³n <CrossRef target="Chapter" ref="making_greenstone_collections"/> se explica la forma de crear su propia colecciÃ³n bibliogrÃ¡fica utilizando la Interfaz de Bibliotecario de Greenstone. En la SecciÃ³n <CrossRef target="Chapter" ref="administration"/> se presenta la utilerÃ­a de administraciÃ³n, que le permite al administrador del sistema seguir de cerca el proceso y controlar las autorizaciones para la creaciÃ³n de colecciones.</Text>
+<Text id="12">En los apÃ©ndices se enumeran las caracterÃ­sticas del programa Greenstone y se presenta un glosario de los tÃ©rminos utilizados en la documentaciÃ³n de Greenstone.</Text>
+</Content>
+</Section>
+<Section id="companion_documents">
+<Title>
+<Text id="13">Conjunto de documentos</Text>
+</Title>
+<Content>
+<Text id="14">La serie completa de documentos comprende cuatro volÃºmenes:</Text>
+<BulletList>
+<Bullet>
+<Text id="15">La GuÃ­a de InstalaciÃ³n de la Biblioteca Digital Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="16">La GuÃ­a del Usuario de la Biblioteca Digital Greenstone (<i>el presente documento</i>)</Text>
+</Bullet>
+<Bullet>
+<Text id="17">La GuÃ­a del Programador de la Biblioteca Digital Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="18">La Biblioteca Digital Greenstone: del Papel a la ColecciÃ³n</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Section>
+<Section id="acknowledgements">
+<Title>
+<Text id="19">Agradecimientos</Text>
+</Title>
+<Content>
+<Text id="20">El programa Greenstone es fruto de la colaboraciÃ³n de muchas personas. Rodger McNab y Stefan Boddie son los principales arquitectos y programadores. TambiÃ©n han contribuido David Bainbridge, George Buchanan, Hong Chen, Michael Dewsnip, Katherine Don, Elke Duncker, Carl Gutwin, Geoff Holmes, Dana McKay, John McPherson, Craig Nevill-Manning, Dynal Patel, Gordon Paynter, Bernhard Pfahringer, Todd Reed, Bill Rogers, John Thompson y Stuart Yeates. Otros miembros del proyecto Biblioteca Digital de Nueva Zelanda que proporcionaron asesorÃ­a y valiosas ideas para la concepciÃ³n del sistema son: Mark Apperley, Sally Jo Cunningham, Matt Jones, Steve Jones, Te Taka Keegan, Michel Loots, Malika Mahoui, Gary Marsden, Dave Nichols y Lloyd Smith. TambiÃ©n queremos dar las gracias a todos aquellos que contribuyeron a los paquetes de programas con licencias GNU incluidos en esta distribuciÃ³n: MG, GDBM, PDFTOHTML, PERL, WGET, WVWARE y XLHTML.</Text>
+</Content>
+</Section>
+<Chapter id="overview_of_greenstone">
+<Title>
+<Text id="21">VISIÃN GENERAL DE GREENSTONE</Text>
+</Title>
+<Content>
+<Text id="22">Greenstone es un sistema completo de creaciÃ³n y presentaciÃ³n de colecciones compuestas de miles o millones de documentos, que incluyen texto, imÃ¡genes, sonido y vÃ­deo.</Text>
+<Section id="collections">
+<Title>
+<Text id="23">Las colecciones</Text>
+</Title>
+<Content>
+<Text id="24">Una biblioteca digital tÃ­pica creada con Greenstone contendrÃ¡ muchas colecciones, organizadas individualmente, pero muy parecidas entre sÃ­. De fÃ¡cil mantenimiento, las colecciones pueden aumentarse y reorganizarse automÃ¡ticamente.</Text>
+<Text id="25">En la mayorÃ­a de las colecciones Greenstone hay varias maneras de encontrar informaciÃ³n. Por ejemplo, se puedenÂ <i>buscar palabras especÃ­ficas</i>Â que aparecen en un texto o en una secciÃ³n de un documento. Se puedenÂ <i>consultar documentos por tÃ­tulo</i>Â ; basta con hacer clic en un libro para poder leerlo. Se puedenÂ <i>consultar documentos por tema</i>. Los temas estÃ¡n representados por estantes; basta con hacer clic en un estante para ver los libros. Cuando procede, los documentos vienen acompaÃ±ados de un Ã­ndice: se puede entonces hacer clic en un capÃ­tulo o una subsecciÃ³n para abrirlo, visualizar el Ã­ndice completo o presentar el documento Ã­ntegro en la ventana de su navegador (lo cual es Ãºtil para la impresiÃ³n). El sitio Web de la Biblioteca Digital de Nueva Zelanda (Â <i>nzdl.org</i>) ofrece numerosos ejemplos de colecciones.</Text>
+<Text id="26">En la primera plana de cada colecciÃ³n se indica su objetivo y cobertura, y se explica su organizaciÃ³n. Se puede tener acceso a la mayorÃ­a de las colecciones mediante las funciones deÂ <i>bÃºsqueda</i>Â yÂ <i>consulta</i>. En la bÃºsqueda, el programa Greenstone examina el texto completo de todos los documentos incluidos en la colecciÃ³n (esto se denomina âbÃºsqueda en texto completoâ). En la mayorÃ­a de las colecciones los usuarios pueden escoger entre los Ã­ndices creados sobre la base de diferentes partes de los documentos. Algunas colecciones disponen de un Ã­ndice de documentos completos, un Ã­ndice de los pÃ¡rrafos y un Ã­ndice de los tÃ­tulos, en los que se pueden buscar determinadas palabras o frases. De este modo, se pueden encontrar todos los documentos que contienen un conjunto especÃ­fico de palabras (las palabras pueden estar dispersas en todo el documento), o todos los pÃ¡rrafos que contienen ese conjunto de palabras (que deben aparecer todas en el mismo pÃ¡rrafo), o todos los documentos cuyo tÃ­tulo contiene las palabras buscadas (todas las palabras deben aparecer en el tÃ­tulo del documento). Puede haber otros Ã­ndices, por ejemplo un Ã­ndice de secciones y un Ã­ndice de encabezados de secciones. Durante el proceso de consulta el usuario examina unas listas: listas de autores, listas de tÃ­tulos, listas de fechas, estructuras de clasificaciÃ³n jerÃ¡rquica, etc. Las diferentes colecciones ofrecen diferentes posibilidades de consulta.</Text>
+</Content>
+</Section>
+<Section id="finding_information">
+<Title>
+<Text id="27">BÃºsqueda de informaciÃ³n</Text>
+</Title>
+<Content>
+<Text id="28">Greenstone crea Ã­ndices de texto completo a partir del texto del documento, es decir, Ã­ndices que permiten buscar cualquier palabra en el texto completo del documento. Se pueden buscar en los Ã­ndices determinadas palabras, combinaciones de palabras, o frases, y los resultados se ordenan segÃºn su pertinencia con respecto a la consulta formulada.</Text>
+<Text id="29">En la mayorÃ­a de las colecciones, los datos descriptivos, como el autor, el tÃ­tulo, la fecha, las palabras clave, etc., se asocian a cada documento. Esta informaciÃ³n se denominaÂ <i>metadatos</i>. Muchas colecciones tambiÃ©n contienen Ã­ndices de texto completo de algunos tipos de metadatos. Por ejemplo, muchas colecciones tienen un Ã­ndice de tÃ­tulos de documentos que permite la bÃºsqueda.</Text>
+<Text id="30">Los usuarios pueden consultar de forma interactiva las listas y estructuras jerÃ¡rquicas que se generan a partir de los metadatos asociados con cada documento de la colecciÃ³n. Los metadatos forman la materia prima para la consulta. Se los debe suministrar explÃ­citamente o deben poder derivarse automÃ¡ticamente de los propios documentos. Cada colecciÃ³n ofrece distintas funciones de bÃºsqueda y de consulta. Los Ã­ndices para la bÃºsqueda y la consulta se constituyen durante un proceso de âcreaciÃ³nâ, con arreglo a la informaciÃ³n que figura en el archivo de configuraciÃ³n de la colecciÃ³n.</Text>
+<Text id="31">Greenstone crea todas las estructuras de Ã­ndices automÃ¡ticamente a partir de los documentos y los archivos conexos; nada se hace manualmente. Si se aÃ±aden nuevos documentos con el mismo formato, se los puede incorporar a la colecciÃ³n automÃ¡ticamente. En efecto, en muchas colecciones esto se lleva a cabo mediante procesos que se ponen en marcha periÃ³dicamente, localizan el material nuevo y reconstituyen los Ã­ndices, todo ello sin ninguna intervenciÃ³n manual.</Text>
+</Content>
+</Section>
+<Section id="document_formats">
+<Title>
+<Text id="32">Formatos de documentos</Text>
+</Title>
+<Content>
+<Text id="33">Los documentos de origen se presentan en diversos formatos y se convierten a un formato normalizado xml para la indexaciÃ³n mediante plugins. Los plugins distribuidos con Greenstone tratan documentos en texto sin formato, HTML, word y pdf, y los mensajes Usenet y de correo electrÃ³nico. Pueden escribirse nuevos plugins para distintos tipos de documentos (para ello es necesario consultar laÂ <i>GuÃ­a del Programador de la Biblioteca Digital Greenstone</i>). Para crear estructuras de consulta a partir de metadatos, se utiliza un sistema anÃ¡logo de âclasificadoresâ. Ãstos crean Ã­ndices de consulta de diversos tipos: listas desplegables, selectores alfabÃ©ticos, fechas y jerarquÃ­as arbitrarias. Una vez mÃ¡s, los programadores Greenstone pueden crear nuevas estructuras de consulta.</Text>
+</Content>
+</Section>
+<Section id="multimedia_and_multilingual_documents">
+<Title>
+<Text id="34">Documentos multimedia y plurilingÃŒes</Text>
+</Title>
+<Content>
+<Text id="35">Las colecciones pueden contener texto, imÃ¡genes, sonido y vÃ­deo. Los contenidos no textuales se enlazan con los documentos textuales o se acompaÃ±an de descripciones textuales (como las leyendas de las figuras) para poder buscar y consultar en modo de texto completo.</Text>
+<Text id="36">Greenstone utiliza constantemente Unicode, un sistema normalizado para la representaciÃ³n de los conjuntos de caracteres empleados en los idiomas del mundo. Ello permite tratar y presentar cualquier idioma de manera uniforme. Se han creado colecciones que contienen textos en Ã¡rabe, chino, inglÃ©s, francÃ©s, maorÃ­ y espaÃ±ol. Las colecciones plurilingÃŒes disponen de una funciÃ³n de reconocimiento automÃ¡tico de idioma y la interfaz estÃ¡ disponible en todos los idiomas antes mencionados (entre otros).</Text>
+</Content>
+</Section>
+<Section id="distributing_greenstone">
+<Title>
+<Text id="37">DistribuciÃ³n de Greenstone</Text>
+</Title>
+<Content>
+<Text id="38">Las colecciones pueden consultarse en Internet o estÃ¡n publicadas, en forma idÃ©ntica, en un CD-ROM que se instala automÃ¡ticamente en computadoras equipadas con Windows. El texto y los Ã­ndices estÃ¡n compactados y un protocolo Corba permite administrar las colecciones distribuidas y las interfaces de consultas grÃ¡ficas.</Text>
+<Text id="39">La Biblioteca Digital de Nueva Zelanda (<i>nzdl.org</i>) ofrece muchos ejemplos de colecciones, entre ellas de documentos histÃ³ricos, informaciÃ³n humanitaria y sobre desarrollo, informes tÃ©cnicos y bibliografÃ­as, obras literarias y publicaciones periÃ³dicas. </Text>
+<Text id="40">Por ser un programa de cÃ³digo fuente abierto, Greenstone puede ampliarse fÃ¡cilmente e incorporar mÃ³dulos sujetos a la Licencia PÃºblica General de GNU para la recuperaciÃ³n de informaciÃ³n en texto completo, la gestiÃ³n de bases de datos y la extracciÃ³n de texto a partir de formatos de documentos patentados. SÃ³lo mediante una cooperaciÃ³n internacional se lograrÃ¡ que los programas de biblioteca digital sean lo suficientemente completos para responder a las necesidades mundiales con la riqueza y la flexibilidad que los usuarios merecen.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="using_greenstone_collections">
+<Title>
+<Text id="41">UtilizaciÃ³n de las colecciones Greenstone</Text>
+</Title>
+<Content>
+<Text id="42">El programa Greenstone se concibiÃ³ para utilizarse con facilidad. Las interfaces de las colecciones son idÃ©nticas, tanto en la Web como en los CD-ROM. Es muy fÃ¡cil instalar Greenstone a partir de un CD-ROM en cualquier computadora equipada de Windows o Linux; se utiliza un programa de instalaciÃ³n normalizado y unos binarios precompilados. Una colecciÃ³n puede consultarse a partir de la computadora local en que estÃ¡ instalada; por otra parte, si la computadora estÃ¡ conectada a una red, el programa permite de forma automÃ¡tica y transparente el acceso a esa misma colecciÃ³n desde todas las demÃ¡s computadoras de la red.</Text>
+<Text id="43">En la siguiente secciÃ³n se explica cÃ³mo instalar un CD-ROM de Greenstone. A continuaciÃ³n, veremos las funciones de bÃºsqueda y consulta que ofrece una colecciÃ³n Greenstone representativa: la colecciÃ³n de âdemostraciÃ³nâ que viene con el programa Greenstone. Las demÃ¡s colecciones ofrecen las mismas funciones: saber utilizar una es saber utilizarlas todas. En la Ãºltima secciÃ³n se explica de quÃ© manera adaptar la interfaz a las necesidades propias, utilizando la pÃ¡gina de Preferencias.</Text>
+<Section id="using_a_greenstone_cd-rom">
+<Title>
+<Text id="44">UtilizaciÃ³n de un CD-ROM de Greenstone</Text>
+</Title>
+<Content>
+<Text id="45">El programa de Biblioteca Digital Greenstone propiamente dicho viene en un CD-ROM, y usted o el administrador de sistemas probablemente ya lo habrÃ¡ instalado en su sistema, siguiendo las instrucciones de laÂ <i>GuÃ­a de InstalaciÃ³n de la Biblioteca Digital Greenstone</i>. Si Greenstone ya estÃ¡ instalado en su computadora, no necesita leer el resto de esta secciÃ³n y puede pasar directamente a la siguiente.</Text>
+<Text id="46">Algunas colecciones Greenstone vienen en un CD-ROM Greenstone autÃ³nomo, que contiene los archivos de programa suficientes para utilizar Ãºnicamente esa colecciÃ³n. Basta sencillamente con insertar el CD-ROM en el lector correspondiente de una computadora con un sistema Windows. Es muy probable (si la computadora admite la funciÃ³n âejecuciÃ³n automÃ¡ticaâ), que aparezca una ventana en que se le invita a instalar el programa Greenstone. De no ser asÃ­, localice el lector de CD-ROM (en los sistemas Windows actuales puede encontrarlo haciendo clic en el icono âMi PCâ sobre el Escritorio), haga clic dos veces en Ã©l y despuÃ©s en el archivoÂ <i>Setup.exe</i>Â que se encuentra dentro. Se activarÃ¡ asÃ­ el programaÂ <i>Setup</i>Â de Greenstone, que lo guiarÃ¡ durante el proceso de instalaciÃ³n. En la mayorÃ­a de los casos, los usuarios responden âsÃ­â a todas las preguntas.</Text>
+<Text id="47">Al final del procedimiento de instalaciÃ³n, encontrarÃ¡ la biblioteca en el submenÃºÂ <i>Programas</i>Â del menÃºÂ <i>Inicio</i>Â de Windows, con el nombre de la colecciÃ³n (por ejemplo, âBiblioteca para el desarrolloâ o âUniversidad de las Naciones Unidasâ).</Text>
+<Text id="48">Una vez instalado el programa, se entrarÃ¡ automÃ¡ticamente en la biblioteca cada vez que vuelva a insertar el CD-ROM, siempre que estÃ© activada la funciÃ³n de ejecuciÃ³n automÃ¡tica.</Text>
+</Content>
+</Section>
+<Section id="finding_information_1">
+<Title>
+<Text id="49">BÃºsqueda de informaciÃ³n</Text>
+</Title>
+<Content>
+<Text id="50">La manera mÃ¡s fÃ¡cil de aprender a utilizar una colecciÃ³n de Greenstone es ejercitÃ¡ndose. No se preocupe, no va a romper nada. Pulse libremente: se puede hacer clic en la mayorÃ­a de las imÃ¡genes que aparecen en la pantalla. Si se mantiene el cursor quieto sobre una imagen, en la mayorÃ­a de los navegadores aparece un mensaje en que se explica lo que sucederÃ¡ si se hace clic.</Text>
+<Text id="51">Â¡Experimente! Busque palabras comunes como âtheâ (el) y âandâ (y) para obtener con certeza respuestas, y no tema, que nada se va a romper.</Text>
+<Text id="52">Los sistemas de bibliotecas digitales Greenstone suelen comprender varias colecciones independientes: por ejemplo, informes tÃ©cnicos de informÃ¡tica, obras literarias, preguntas mÃ¡s frecuentes en Internet, publicaciones periÃ³dicas. El sistema de biblioteca digital dispondrÃ¡ de una pÃ¡gina principal que le permitirÃ¡ tener acceso a cualquier colecciÃ³n puesta a disposiciÃ³n del pÃºblico; ademÃ¡s, cada colecciÃ³n tiene su propia pÃ¡gina âAcerca deâ que le darÃ¡ informaciÃ³n sobre la organizaciÃ³n de la colecciÃ³n y los principios por los que se rige su contenido. Para volver a la pÃ¡gina âAcerca deâ en cualquier momento, basta con hacer clic en el icono âColecciÃ³nâ que aparece en la parte superior izquierda de todas las pÃ¡ginas de bÃºsqueda y consulta.</Text>
+<Text id="53">En la Figura 1 se muestra una imagen de pantalla de la colecciÃ³n de demostraciÃ³n que viene con el programa Greenstone, y que representa un subconjunto muy pequeÃ±o de la colecciÃ³n de bibliotecas para el desarrollo; utilizaremos este documento como ejemplo para explicar las diferentes formas de encontrar informaciÃ³n. Si no puede encontrar la colecciÃ³n de demostraciÃ³n, use en su lugar el Subconjunto de biblioteca para el desarrollo, su aspecto es el mismo. En primer lugar, se puede hacer clic en casi todos los iconos. Varios iconos aparecen en la parte superior de, prÃ¡cticamente, todas las pÃ¡ginas. En el Cuadro 1 se explica su significado.</Text>
+<Figure id="using_the_demo_collection">
+<Title>
+<Text id="54">UtilizaciÃ³n de la colecciÃ³n de demostraciÃ³n</Text>
+</Title>
+<File width="529" height="227" url="images/User_Fig_1.png"/>
+</Figure>
+<Table id="what_the_icons_at_the_top_of_each_page_mean">
+<Title>
+<Text id="55">Significado de los iconos en la parte superior de cada pÃ¡gina</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<File width="144" height="66" url="images/User_Icon_1.gif"/>
+</th>
+<th width="397">
+<Text id="56">Esto lo lleva a la pÃ¡gina âacerca deâ</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<File width="65" height="20" url="images/User_Icon_2.gif"/>
+</th>
+<th width="397">
+<Text id="57">Esto le lleva a la pÃ¡gina principal de la biblioteca digital, a partir de la cual se puede seleccionar otra colecciÃ³n</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<File width="46" height="20" url="images/User_Icon_3.gif"/>
+</th>
+<th width="397">
+<Text id="58">Esto le ofrece un texto de ayuda semejante al que estÃ¡ leyendo en este momento</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<File width="87" height="20" url="images/User_Icon_4.gif"/>
+</th>
+<th width="397">
+<Text id="59">Esto le permite seleccionar algunas opciones de interfaz de usuario y de bÃºsqueda que se utilizarÃ¡n en adelante</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="60">La barra horizontal âÂ <i>buscar ... temas ... tÃ­tulos a-z ... organizaciones ... cÃ³mo</i>Â â da acceso a las funciones de bÃºsqueda y consulta. El botÃ³n a la izquierda sirve para la bÃºsqueda y los que estÃ¡n a su derecha (que en esta colecciÃ³n son cuatro) indican diferentes funciones de consulta. Estos Ãºltimos cuatro botones pueden ser diferentes de una colecciÃ³n a otra.</Text>
+<Subsection id="how_to_find_information">
+<Title>
+<Text id="61">CÃ³mo encontrar informaciÃ³n</Text>
+</Title>
+<Content>
+<Text id="62">En el cuadro 2 se muestran las cinco maneras de encontrar informaciÃ³n en la colecciÃ³n de demostraciÃ³n.</Text>
+<Table id="table_icons_on_the_search_browse_bar">
+<Title>
+<Text id="63">Significado de los iconos en la barra bÃºsqueda/consulta</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="123">
+<File width="87" height="17" url="images/User_Icon_5.gif"/>
+</th>
+<th width="407">
+<Text id="64">BÃºsqueda de determinadas palabras </Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="87" height="17" url="images/User_Icon_6.gif"/>
+</th>
+<th width="407">
+<Text id="65">Acceso a las publicaciones por tema</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="87" height="17" url="images/User_Icon_7.gif"/>
+</th>
+<th width="407">
+<Text id="66">Acceso a las publicaciones por tÃ­tulo</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="127" height="17" url="images/User_Icon_8.gif"/>
+</th>
+<th width="407">
+<Text id="67">Acceso a las publicaciones por organizaciÃ³n</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="87" height="17" url="images/User_Icon_9.gif"/>
+</th>
+<th width="407">
+<Text id="68">Acceso a las publicaciones por lista de âÃ­ndicesâ</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="69">A partir de la pÃ¡gina âbuscarâ puedeÂ <i>buscar palabras especÃ­ficas</i>Â que aparecen en el texto (esta pÃ¡gina es similar a la pÃ¡gina âacerca deâ que se muestra en la Figura 1, salvo que no contiene el texto âAcerca de esta colecciÃ³nâ). Se puede llegar a la pÃ¡gina de bÃºsqueda a partir de otras pÃ¡ginas pulsando el botÃ³nÂ <i>buscar</i>. Se puede tener acceso a las publicaciones por tema pulsando el botÃ³nÂ <i>temas</i>. Esto hace aparecer una lista de temas, representados por estantes que pueden desplegarse haciendo clic en ellos. Puede acceder a lasÂ <i>publicaciones por tÃ­tulo</i>Â pulsando el botÃ³nÂ <i>tÃ­tulos a-z</i>. Aparece entonces una lista de libros, por orden alfabÃ©tico. Se puede acceder a lasÂ <i>publicaciones por organizaciÃ³n</i>Â pulsando el botÃ³nÂ <i>organizaciones</i>. Aparece entonces una lista de organizaciones. Se puede acceder a lasÂ <i>publicaciones por lista de âÃ­ndicesâ</i>Â pulsando el botÃ³nÂ <i>cÃ³mo</i>. Aparece entonces una lista de âÃ­ndicesâ. Todos estos botones estÃ¡n representados en la Figura 1.</Text>
+</Content>
+</Subsection>
+<Subsection id="how_to_read_the_documents">
+<Title>
+<Text id="70">CÃ³mo leer los documentos</Text>
+</Title>
+<Content>
+<Text id="71">En la colecciÃ³n de demostraciÃ³n, se puede saber cuando se ha llegado a un libro determinado porque aparecerÃ¡ una fotografÃ­a de su portada (Figura 2). AdemÃ¡s de la foto, habrÃ¡ un Ã­ndice; el renglÃ³n en negritas le indica dÃ³nde estÃ¡, en este caso,Â <i>IntroducciÃ³n y resumen</i>Â â SecciÃ³n <CrossRef target="Chapter" ref="overview_of_greenstone"/> del libro en cuestiÃ³n. Este Ã­ndice puede desplegarse; para abrir o cerrar las carpetas, haga clic en ellas. Para cerrar el libro abierto que figura en la parte superior, haga clic en el icono correspondiente.</Text>
+<Text id="72">Debajo estÃ¡ el texto con la secciÃ³n abierta (âÂ <i>The international demand for tropical butterflies</i>...â en el ejemplo, que comienza en la parte inferior de la ilustraciÃ³n). Al final de la lectura, se pueden pulsar unas flechas para pasar a la secciÃ³n siguiente o volver a la anterior.</Text>
+<Text id="73">Debajo de la fotografÃ­a hay cuatro botones; haga clic enÂ <i>separar</i>, para abrir una nueva ventana de consulta para este libro (es Ãºtil para comparar libros, o leer varios a la vez). Si ha llegado a este libro mediante una operaciÃ³n de bÃºsqueda, los tÃ©rminos de la bÃºsqueda aparecerÃ¡n resaltados; esta funciÃ³n se puede cancelar con el botÃ³nÂ <i>no resaltar</i>. Haga clic enÂ <i>texto completo</i>Â para ampliar el texto completo de la secciÃ³n o el libro que se estÃ¡ consultando. Haga clic enÂ <i>expandir Ã­ndice</i>Â para ampliar todo el Ã­ndice, a fin de poder ver los tÃ­tulos de todos los capÃ­tulos y subsecciones.</Text>
+<Text id="74">En algunas colecciones, los documentos no tienen este tipo de estructura jerÃ¡rquica. En este caso, no aparece ningÃºn Ã­ndice cuando se entra en un documento: sÃ³lo figura el texto del documento. A veces, los documentos estÃ¡n divididos en pÃ¡ginas, y se pueden leer secuencialmente, o saltar de una pÃ¡gina a otra.</Text>
+<Figure id="a_book_in_the_demo_collection">
+<Title>
+<Text id="75">Un libro en la colecciÃ³n de demostraciÃ³n</Text>
+</Title>
+<File width="532" height="526" url="images/User_Fig_2.png"/>
+</Figure>
+</Content>
+</Subsection>
+<Subsection id="what_the_icons_mean">
+<Title>
+<Text id="76">Significado de los iconos</Text>
+</Title>
+<Content>
+<Text id="77">Cuando usted consulte la colecciÃ³n, encontrarÃ¡ las funciones que aparecen en el Cuadro 3.</Text>
+</Content>
+</Subsection>
+<Subsection id="how_to_search_for_particular_words">
+<Title>
+<Text id="78">BÃºsqueda de determinadas palabras</Text>
+</Title>
+<Content>
+<Text id="79">A partir de la pÃ¡gina de bÃºsqueda, siga estos pasos sencillos para hacer una consulta:</Text>
+<BulletList>
+<Bullet>
+<Text id="80">Especifique en quÃ© unidades desea buscar: en la colecciÃ³n de demostraciÃ³n puede buscarÂ  en los tÃ­tulos de secciones o en el texto completo de los libros.</Text>
+</Bullet>
+<Bullet>
+<Text id="81">Indique si desea buscar todas las palabras o sÃ³lo algunas de ellas.</Text>
+</Bullet>
+<Bullet>
+<Text id="82">Escriba las palabras que desea buscar en la casilla de consulta.</Text>
+</Bullet>
+<Bullet>
+<Text id="83">Haga clic en el botÃ³nÂ <i>Iniciar la bÃºsqueda</i></Text>
+</Bullet>
+</BulletList>
+<Text id="84">Al efectuar una consulta, aparecerÃ¡n los tÃ­tulos de hasta 20 documentos pertinentes. Si pulsa el botÃ³n del final, aparecerÃ¡n los prÃ³ximos 20. A partir de allÃ­ encontrarÃ¡ botones que le mostrarÃ¡n nuevamente otros 20, o que le permitirÃ¡n volver a los primeros 20, etc. Sin embargo, por razones de eficacia se impone un mÃ¡ximo de 100 documentos encontrados por cada consulta. PodrÃ¡ cambiar ese nÃºmero haciendo clic en el botÃ³nÂ <i>preferencias</i>, en la parte superior de la pÃ¡gina.</Text>
+<Table id="table_icons_that_you_will_encounter_when_browsing">
+<Title>
+<Text id="85">Iconos que encontrarÃ¡ durante la consulta</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="123">
+<File width="18" height="11" url="images/User_Icon_10.png"/>
+</th>
+<th width="407">
+<Text id="86">Haga clic en el icono de un libro para leer el libro correspondiente</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="20" height="16" url="images/User_Icon_11.png"/>
+</th>
+<th width="407">
+<Text id="87">Haga clic en el icono de un estante para buscar libros sobre el tema</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="23" height="15" url="images/User_Icon_12.png"/>
+</th>
+<th width="407">
+<Text id="88">Visualizar este documento</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="23" height="15" url="images/User_Icon_13.png"/>
+</th>
+<th width="407">
+<Text id="89">Abrir esta carpeta y visualizar su contenido</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="28" height="23" url="images/User_Icon_14.png"/>
+</th>
+<th width="407">
+<Text id="90">Haga clic en este icono para cerrar el libro</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="23" height="15" url="images/User_Icon_15.png"/>
+</th>
+<th width="407">
+<Text id="91">Haga clic en este icono para cerrar la carpeta</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="30" height="16" url="images/User_Icon_16.png"/>
+</th>
+<th width="407">
+<Text id="92">Haga clic en la flecha para pasar a la secciÃ³n siguiente ...</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="30" height="16" url="images/User_Icon_17.png"/>
+</th>
+<th width="407">
+<Text id="93">... o volver a la secciÃ³n anterior</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="65" height="30" url="images/User_Icon_18.gif"/>
+</th>
+<th width="407">
+<Text id="94">Abrir esta pÃ¡gina en una nueva ventana</Text>
+</th>
+</tr>
+<tr>
+<th>
+<File width="65" height="30" url="images/User_Icon_19.gif"/>
+</th>
+<th>
+<Text id="95">Ampliar el Ã­ndice</Text>
+</th>
+</tr>
+<tr>
+<th>
+<File width="65" height="30" url="images/User_Icon_20.gif"/>
+</th>
+<th>
+<Text id="96">Mostrar todo el texto</Text>
+</th>
+</tr>
+<tr>
+<th>
+<File width="65" height="30" url="images/User_Icon_21.gif"/>
+</th>
+<th>
+<Text id="97">Resaltar los tÃ©rminos de la bÃºsqueda </Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="98">Para abrir un documento, haga clic en el tÃ­tulo o en el pequeÃ±o icono que estÃ¡ al lado. El icono puede representar un documento, o una carpeta, o una pÃ¡gina: si su bÃºsqueda es en libros, el icono serÃ¡ un libro; en los demÃ¡s casos, si su bÃºsqueda es en secciones, el icono serÃ¡ una carpeta o una pÃ¡gina, segÃºn que en la secciÃ³n haya subsecciones o no.</Text>
+<Part id="search_terms">
+<Title>
+<Text id="99">TÃ©rminos de la bÃºsqueda </Text>
+</Title>
+<Content>
+<Text id="100">Todo lo que escriba en la casilla de consulta se interpretarÃ¡ como una lista de palabras llamada âtÃ©rminos de la bÃºsquedaâ. Cada tÃ©rmino de la bÃºsqueda contiene solamente caracteres alfabÃ©ticos y dÃ­gitos. Los tÃ©rminos estÃ¡n separados por un espacio en blanco. Si aparecen otros tipos de caracteres, por ejemplo signos de puntuaciÃ³n, estos sirven para separar los tÃ©rminos como si fueran espacios y se harÃ¡ caso omiso de ellos. No se puede efectuar una bÃºsqueda con palabras que incluyan signos de puntuaciÃ³n.</Text>
+<Text id="101">Por ejemplo, la consulta:</Text>
+<Text id="102">Agro-forestry in the Pacific Islands: Systems for Sustainability (1993)</Text>
+<Text id="103">se tratarÃ¡ de la misma manera que:</Text>
+<Text id="104">Agro forestry in the Pacific Islands Systems for Sustainability 1993</Text>
+</Content>
+</Part>
+<Part id="query_type">
+<Title>
+<Text id="105">Tipos de consulta</Text>
+</Title>
+<Content>
+<Text id="106">Hay dos tipos diferentes de consultas.</Text>
+<BulletList>
+<Bullet>
+<Text id="107">Consultas basadas en todas las palabras. En este caso se buscan los documentos (o capÃ­tulos, o tÃ­tulos) que contengan todas la palabras que se han especificado. Aparecen los documentos que responden a la consulta.</Text>
+</Bullet>
+<Bullet>
+<Text id="108">Consulta basada en algunas palabras. Indica sÃ³lo algunos tÃ©rminos que probablemente aparezcan en los documentos en que se estÃ¡ buscando. Los documentos se presentan en el orden de pertinencia con respecto a la consulta. Para determinar el grado de correspondencia, se tendrÃ¡ en cuenta que:</Text>
+</Bullet>
+<Bullet>
+<Text id="109">cuanto mÃ¡s tÃ©rminos de bÃºsqueda contenga el documento, mayor serÃ¡ la correspondencia;</Text>
+</Bullet>
+<Bullet>
+<Text id="110">los tÃ©rminos poco frecuentes son mÃ¡s importantes que los comunes;</Text>
+</Bullet>
+<Bullet>
+<Text id="111">los documentos cortos se adaptan mejor a la bÃºsqueda que los largos.</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Part>
+<Text id="112">Utilice todos los tÃ©rminos de bÃºsqueda que desee, es decir, una oraciÃ³n completa o incluso un pÃ¡rrafo entero. Si especifica Ãºnicamente un tÃ©rmino, no importarÃ¡ si utiliza la consulta de todas las palabras o de sÃ³lo algunas, salvo que en el segundo caso los resultados estarÃ¡n clasificados por la frecuencia de apariciÃ³n del tÃ©rmino de la bÃºsqueda.</Text>
+</Content>
+</Subsection>
+<Subsection id="scope_of_queries">
+<Title>
+<Text id="113">Alcance de las consultas</Text>
+</Title>
+<Content>
+<Text id="114">En la mayorÃ­a de las colecciones se puede escoger entre diversos Ã­ndices de bÃºsqueda, por ejemplo, Ã­ndices de autores o de tÃ­tulos. TambiÃ©n pueden ser Ã­ndices de capÃ­tulos o pÃ¡rrafos. En general, el documento que corresponde plenamente a la consulta aparece con independencia del Ã­ndice de bÃºsqueda utilizado.</Text>
+<Text id="115">Si los documentos son libros, se abrirÃ¡n en el lugar apropiado.</Text>
+</Content>
+</Subsection>
+<Subsection id="advanced_search_features">
+<Title>
+<Text id="116">Funciones de bÃºsqueda avanzada</Text>
+</Title>
+<Content>
+<Text id="117">Si bien los pasos antes indicados son suficientes para responder a la mayorÃ­a de las necesidades de bÃºsqueda, Greenstone propone funciones de bÃºsqueda mÃ¡s avanzada. Estas se activan a partir de la pÃ¡gina deÂ <i>preferencias</i>, a la que se llega haciendo clic en el botÃ³n deÂ <i>preferencias</i>Â en la parte superior de la pÃ¡gina. Si cambia usted sus preferencias, no haga clic en el botÃ³nÂ <i>AtrÃ¡s</i>Â de su navegador, ya que ello anularÃ­a los cambios. En cambio, haga clic en cualquiera de los botones de la barra de bÃºsqueda/consulta.</Text>
+<Part id="case_sensitivity_and_stemming">
+<Title>
+<Text id="118">Reconocimiento de mayÃºsculas y minÃºsculas y truncamiento de tÃ©rminos</Text>
+</Title>
+<Content>
+<Text id="119">Cuando especifique los tÃ©rminos de bÃºsqueda, puede usted optar por que las mayÃºsculas y minÃºsculas que aparecen en la consulta correspondan a las del documento; esto se llama âreconocimiento de mayÃºsculas y minÃºsculasâ. TambiÃ©n puede optar por hacer caso omiso o no del final de la palabra: esto se llama âtruncamientoâ.</Text>
+<Text id="120">En las Preferencias de bÃºsqueda de la pÃ¡gina de preferencias, encontrarÃ¡ un par de botones con la etiqueta ignorar diferencias entre mayÃºsculas y minÃºsculas y deben corresponder mayÃºsculas y minÃºsculas; de esta manera se controla el reconocimiento de mayÃºsculas y minÃºsculas en sus consultas. Debajo hay otros dos botones con la etiqueta ignorar las terminaciones de las palabras y debe corresponder la palabra completa; de esta manera se controla el truncamiento o no del tÃ©rmino.</Text>
+<Text id="121">Por ejemplo, si se seleccionan los botones ignorar diferencias entre mayÃºsculas y minÃºsculas e ignorar las terminaciones de las palabras, la consulta:</Text>
+<Text id="122">African building</Text>
+<Text id="123">se tratarÃ¡ de la misma manera que:</Text>
+<Text id="124">africa builds</Text>
+<Text id="125">ya que la mayÃºscula de âAfricanâ pasarÃ¡ a ser minÃºscula, y se harÃ¡ caso omiso de los sufijos ânâ e âingâ de las palabras âAfricanâ y âbuildingâ respectivamente (tampoco se tendrÃ¡ en cuenta la âsâ de âbuildsâ).</Text>
+<Text id="126">Se recomienda en general no tener en cuenta la distinciÃ³n entre mayÃºsculas y minÃºsculas y la desinencia de la palabra, a menos que se estÃ© buscando un nombre o una sigla en particular.</Text>
+</Content>
+</Part>
+<Part id="phrase_searching">
+<Title>
+<Text id="127">BÃºsqueda de frases</Text>
+</Title>
+<Content>
+<Text id="128">Si en su consulta incluye una frase entre comillas, sÃ³lo aparecerÃ¡n los documentos que contengan esa frase, exactamente como se la escribiÃ³.</Text>
+<Text id="129">Si desea utilizar la funciÃ³n de bÃºsqueda de frases, deberÃ¡ aprender un poco sobre su funcionamiento. LasÂ frases se procesan mediante un examen posterior a la recuperaciÃ³n (<i>post-retrieval scan</i>). La consulta se efectÃºa primero de modo normal, es decir, todas las palabras contenidas en las frases se incluyen como tÃ©rminos de la bÃºsqueda, y luego los documentos presentados son filtrados para eliminar aquÃ©llos en que no aparece esa frase.</Text>
+<Text id="130">Durante el examen posterior a la recuperaciÃ³n, se buscan las frases exactas, incluido cualquier signo de puntuaciÃ³n. Por ejemplo, en la consulta:</Text>
+<Text id="131">whatâs a âpost-retrieval scan?â</Text>
+<Text id="132">encontraremos en primer lugar todos los documentos que contienen las palabras:</Text>
+<CodeLine>what s a post retrieval scan</CodeLine>
+<Text id="133">y a continuaciÃ³n en los documentos presentados se buscarÃ¡ la frase:</Text>
+<Text id="134">post-retrieval scan?</Text>
+<Text id="135">Si se selecciona la opciÃ³nÂ <i>ignorar diferencias entre mayÃºsculas y minÃºsculas</i>Â en la pÃ¡gina deÂ <i>preferencias</i>, la correspondencia encontrada para la frase harÃ¡ caso omiso de la distinciÃ³n entre mayÃºsculas y minÃºsculas.</Text>
+</Content>
+</Part>
+<Part id="advanced_query_mode">
+<Title>
+<Text id="136">Modo de consulta avanzada</Text>
+</Title>
+<Content>
+<Text id="137">En el modo de consulta avanzada, que se puede seleccionar en la pÃ¡gina deÂ <i>preferencias</i>, las bÃºsquedas deÂ <i>todas</i>Â las palabras son en realidad consultas con operadores booleanos. Se trata de una lista de tÃ©rminos enlazados por los operadores lÃ³gicos â&amp;â (y), â |â (o) y â!â (no). La ausencia de operadores entre los tÃ©rminos de bÃºsquedas se interpreta como un â&amp;â (y); de esta manera, una consulta sin operadores remite a documentos en que aparecenÂ <i>todos</i>Â los tÃ©rminos.</Text>
+<Text id="138">Si en su consulta aparecen las palabras AND, OR y NOT (respectivamente, âyâ, âoâ y ânoâ en inglÃ©s), se las trata como tÃ©rminos de bÃºsqueda ordinaria, y no como operadores. Para que se consideren operadores, se deben utilizar los signos â&amp;â, â |â y â!â. AdemÃ¡s, se pueden utilizar parÃ©ntesis para agrupar.</Text>
+</Content>
+</Part>
+<Part id="using_search_history">
+<Title>
+<Text id="139">UtilizaciÃ³n del historial de bÃºsqueda</Text>
+</Title>
+<Content>
+<Text id="140">Cuando se acciona la propiedadÂ <i>historial de bÃºsquedas</i>Â en la pÃ¡gina deÂ <i>preferencias</i>, aparecerÃ¡n sus Ãºltimas bÃºsquedas junto con el nÃºmero de resultados obtenidos. Haga clic en el botÃ³n que estÃ¡ al lado de una de las bÃºsquedas anteriores para copiar el texto correspondiente en la casilla de bÃºsqueda. De esta manera resulta mÃ¡s fÃ¡cil repetir versiones ligeramente modificadas de consultas anteriores.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="changing_the_preferences">
+<Title>
+<Text id="141">Cambio de preferencias</Text>
+</Title>
+<Content>
+<Figure id="the_preferences_page">
+<Title>
+<Text id="142">La pÃ¡gina de Preferencias</Text>
+</Title>
+<File width="529" height="524" url="images/User_Fig_3.png"/>
+</Figure>
+<Text id="143">Si pulsa usted el botÃ³nÂ <i>preferencias</i>Â en la parte superior de la pÃ¡gina, podrÃ¡ cambiar algunas caracterÃ­sticas de la interfaz para que se adapte a sus necesidades. Las preferencias dependen de la colecciÃ³n; en la Figura 3 se muestra un ejemplo. Para ajustar sus preferencias de bÃºsqueda, pulse el botÃ³nÂ <i>fijar preferencias</i>Â que aparece en la Figura 3. Tras seleccionar las preferencias, no utilice el botÃ³nÂ <i>AtrÃ¡s</i>Â de su navegador, ya que anularÃ­a la operaciÃ³n. En lugar de ello, haga clic en uno de los botones de la barra de acceso, cerca de la parte superior de la pÃ¡gina.</Text>
+<Subsection id="collection_preferences">
+<Title>
+<Text id="144">Preferencias de colecciones</Text>
+</Title>
+<Content>
+<Text id="145">Algunas colecciones contienen varias subcolecciones, en las que pueden hacerse bÃºsquedas independientemente o en conjunto, como si constituyeran una unidad. En ese caso, puede usted elegir en la pÃ¡gina deÂ <i>preferencias</i>Â quÃ© subcolecciones han de incluirse en sus bÃºsquedas.</Text>
+</Content>
+</Subsection>
+<Subsection id="language_preferences">
+<Title>
+<Text id="146">Preferencias de idiomas</Text>
+</Title>
+<Content>
+<Text id="147">Cada colecciÃ³n tiene un idioma de presentaciÃ³n por defecto, pero que se puede sustituir por otro idioma, si lo desea. TambiÃ©n puede usted modificar el sistema de codificaciÃ³n utilizado por Greenstone para manejar el navegador: el programa elige las opciones por defecto razonables, pero con algunos navegadores pueden obtenerse mejores resultados visuales pasando a un sistema de codificaciÃ³n diferente. Todas las colecciones permiten pasar del formato estÃ¡ndar de interfaz grÃ¡fica a uno textual. Esto es particularmente Ãºtil para los usuarios con deficiencias visuales, que utilizan en su computadora caracteres de pantalla de gran tamaÃ±o o sintetizadores vocales.</Text>
+</Content>
+</Subsection>
+<Subsection id="presentation_preferences">
+<Title>
+<Text id="148">Preferencias de presentaciÃ³n</Text>
+</Title>
+<Content>
+<Text id="149">SegÃºn la colecciÃ³n, puede usted seleccionar otras opciones para controlar la presentaciÃ³n. Las colecciones de pÃ¡ginas Web le permiten suprimir la barra de navegaciÃ³n Greenstone en la parte superior de cada pÃ¡gina del documento, de modo que una vez que haya hecho una bÃºsqueda llegue a la pÃ¡gina Web exacta que coincide con su consulta, sin ningÃºn encabezado Greenstone. Para efectuar otra bÃºsqueda deberÃ¡ pulsar el botÃ³nÂ <i>AtrÃ¡s</i>Â de su navegador. Estas colecciones tambiÃ©n le permiten suprimir el mensaje de alerta de Greenstone que aparece cuando usted pulsa un enlace que lo saca de la biblioteca digital y lo lleva a la Web propiamente dicha. AdemÃ¡s, en algunas colecciones Web se puede determinar si los enlaces sobre la pÃ¡ginaÂ <i>resultados de la bÃºsqueda</i>Â lo llevan directamente a la URL en cuestiÃ³n o a la copia de la pÃ¡gina en la biblioteca digital.</Text>
+</Content>
+</Subsection>
+<Subsection id="search_preferences">
+<Title>
+<Text id="150">Preferencias de bÃºsqueda</Text>
+</Title>
+<Content>
+<Text id="151">En la funciÃ³nÂ <i>Preferencias de bÃºsqueda</i>Â que se muestra en la Figura 3, los dos primeros botones permiten obtener una casilla de consulta de gran tamaÃ±o, en la que se puede efectuar fÃ¡cilmente una bÃºsqueda del tamaÃ±o de un pÃ¡rrafo. En Greenstone, la bÃºsqueda de porciones de texto muy extensas es sorprendentemente rÃ¡pida. Los dos pares de botones siguientes controlan el tipo de texto encontrado mediante las bÃºsquedas efectuadas. El primer grupo (denominado âÂ <i>Reconocimiento de mayÃºsculas y minÃºsculas</i>Â â) controla la distinciÃ³n entre mayÃºsculas y minÃºsculas. El segundo (âÂ <i>Terminaciones de las palabras</i>Â â) controla si se toma en cuenta o no la desinencia de las palabras.</Text>
+<Text id="152">Con el siguiente par de botones se puede pasar al modo de consulta âavanzadaâ antes mencionado, que le permite especificar consultas mÃ¡s precisas, mediante la combinaciÃ³n de tÃ©rminos que utilizan âyâ (&amp;), âoâ (|) y ânoâ (!). Se puede activar o desactivar la funciÃ³n de historial de bÃºsqueda antes mencionada. Por Ãºltimo, gracias al Ãºltimo renglÃ³n que aparece en la Figura 3, usted puede controlar el nÃºmero de resultados obtenidos y el nÃºmero de resultados presentado en cada pantalla.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="making_greenstone_collections">
+<Title>
+<Text id="153">CREACIÃN DE COLECCIONES GREENSTONE</Text>
+</Title>
+<Content>
+<Text id="154">La forma mÃ¡s sencilla de crear nuevas colecciones es por medio de la Interfaz de Bibliotecario de Greenstone (GLI por sus siglas en inglÃ©s), la cual permite reunir conjuntos de documentos, importarlos o asignarles metadatos y construir con ellos una colecciÃ³n Greenstone. La Interfaz de Bibliotecario de Greenstone cuenta con soporte para cinco actividades bÃ¡sicas, las cuales pueden intercalarse, aunque nominalmente se toman en el siguiente orden:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="155">Copiar documentos desde el espacio de archivos de la computadora, incluyendo colecciones existentes, e incluirlos en una nueva colecciÃ³n. Los documentos âconservanâ los metadatos anteriores y tambiÃ©n pueden bajarse de Internet a travÃ©s de un programa de espejeo integrado.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="156">Enriquecer los documentos aÃ±adiendo mÃ¡s metadatos a los documentos individuales o a grupos de documentos.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="157">Designar la colecciÃ³n determinando su apariencia y los programas de acceso que a los que darÃ¡ soporte.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="158">Construir la colecciÃ³n por medio de Greenstone.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="159">Tener una vista previa de la colecciÃ³n que se acaba de crear, la cual se habrÃ¡ instalado en su pÃ¡gina principal Greenstone como una de las colecciones regulares.</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="160">La interfaz de bibliotecario le permite aÃ±adir lo que la gente llama metadatos âexternosâ a los documentos, es decir, metadatos que pertenecen al documento como un todo. Pero los documentos a menudo necesitan estar estructurados en secciones y subsecciones, con lo que tambiÃ©n puede haber metadatos âinternosâ asociados a cada parte. En Greenstone los documentos de origen pueden estar etiquetados con esta informaciÃ³n, tal como se explica en la SecciÃ³n 3.3.</Text>
+<Text id="161">Finalmente, tambiÃ©n se cuenta con una forma alternativa para crear colecciones a travÃ©s del Colector, que le ayuda a crear nuevas colecciones, modificar o aÃ±adir colecciones existentes o eliminarlas. Aunque este programa de recopilaciÃ³n antecede a la interfaz de bibliotecario, para fines prÃ¡cticos se recomienda usar esta Ãºltima en lugar del Colector. El Colector se describe en la SecciÃ³n 3.4</Text>
+<Text id="162">Para poder aprovechar todo el poder que le ofrece Greenstone para construir colecciones avanzadas, usted tambiÃ©n necesitarÃ¡ leer el CapÃ­tulo 2 de la GuÃ­a del Programador.</Text>
+<Section id="the_librarian_interface">
+<Title>
+<Text id="163">La Interfaz de Bibliotecario</Text>
+</Title>
+<Content>
+<Text id="164">Para explicar el funcionamiento de la interfaz de bibliotecario de Greenstone nos gustarÃ­a hacerlo a travÃ©s de un sencillo ejemplo. Las figuras de la 4 a la 15 son imÃ¡genes en pantalla de los diferentes momentos de la acciÃ³n. Este ejemplo utiliza documentos delÂ <i>Subconjunto de la Biblioteca para el Desarrollo</i>Â (DLS por sus siglas en inglÃ©s), la cual se distribuye junto con Greenstone. Para los fines de esta exposiciÃ³n, la explicaciÃ³n toma la forma de un sencillo paseo por los pasos mencionados arriba. No obstante, una patrÃ³n de uso mÃ¡s realista es ir de atrÃ¡s para adelante a travÃ©s de las diferentes etapas conforme la tarea avanza.</Text>
+<Text id="165">La interfaz del bibliotecario puede iniciarse en uno de cuatro posibles modos: Asistente de biblioteca, Bibliotecario, Especialista de sistemas de biblioteca, y Avanzado. Estos modos controlan el nivel de detalle dentro de cada interfaz, y pueden cambiarse usando la opciÃ³n de "Preferencias" en el menÃº de "Archivo". El recorrido en esta secciÃ³n supone que la interfaz de bibliotecario se encuentra operando en el modo Bibliotecario.</Text>
+<Subsection id="getting_started">
+<Title>
+<Text id="166">Para empezar</Text>
+</Title>
+<Content>
+<Text id="167">Si cuenta con Windows inicie la interfaz de bibliotecario de seleccionandoÂ <i>Biblioteca Digital Greenstone</i>Â en la secciÃ³n deÂ <i>Programas</i>Â del menÃº deÂ <i>Inicio</i>Â y eligiendoÂ <i>Interfaz de Bibliotecario</i>. Si estÃ¡ usando UNIX, entonces escriba:</Text>
+<CodeLine>cd ~/gsdl</CodeLine>
+<CodeLine>cd gli</CodeLine>
+<CodeLine>./gli.sh</CodeLine>
+<Text id="168">dondeÂ <i>~/gsdl</i>Â es el directorio que contiene el sistema Greenstone. Para empezar usted debe abrir una colecciÃ³n existente o iniciar una nueva. La figura 4 muestra al usuario en el proceso de iniciar una nueva colecciÃ³n, seleccionandoÂ <i>New [Nuevo]</i>Â en el menÃº de archivos y llenando la informaciÃ³n general acerca de la colecciÃ³n: tÃ­tulo, direcciÃ³n de correo electrÃ³nico del responsable de la colecciÃ³n y una breve descripciÃ³n de su contenido. El tÃ­tulo de la colecciÃ³n es una frase corta que se utilizarÃ¡ aÂ  lo largo de toda la biblioteca digital para identificar su contenido. Las colecciones existentes tienen nombres comoÂ <i>Biblioteca de la AlimentaciÃ³n y la NutriciÃ³n</i>,Â <i>BibliotecaÂ  Mundial del Medio Ambiente</i>, etc. Cuando se escribe el tÃ­tulo el sistema le asigna un identificador mnemotÃ©cnico Ãºnico, que equivale al ânombreâ de la colecciÃ³n para uso interno (usted puede cambiarlo si asÃ­ lo desea). La direcciÃ³n de correo electrÃ³nico corresponde al primer punto de contacto para cualquier problema que se tenga con la colecciÃ³n.</Text>
+<Text id="169">La descripciÃ³n es una breve relaciÃ³n de los principios que rigen la selecciÃ³n de los materiales que van a formar parte de la colecciÃ³n. Aparece bajo el encabezadoÂ <i>About this collection [Acerca de esta colecciÃ³n]</i>Â en la pÃ¡gina inicial.</Text>
+<Figure id="starting_a_new_collection">
+<Title>
+<Text id="170">Iniciando una nueva colecciÃ³n</Text>
+</Title>
+<File width="380" height="297" url="images/User_Fig_4.png"/>
+</Figure>
+<Figure id="exploring_the_local_file_space">
+<Title>
+<Text id="171">Explorando el espacio de archivos</Text>
+</Title>
+<File width="380" height="297" url="images/User_Fig_5.png"/>
+</Figure>
+<Text id="172">En este punto el usuario decide si desea que la nueva colecciÃ³n se base en la misma estructura que una colecciÃ³n existente o construir un tipo de colecciÃ³n totalmente nuevo. En la figura 4 el usuario decidiÃ³ basarla en elÂ <i>Subconjunto de la Biblioteca para el Desarrollo</i>Â (DLS por sus siglas en inglÃ©s). Esto implica que el conjunto de metadatos âDLSâ que se utiliza en esta colecciÃ³n se usarÃ¡ para la nueva colecciÃ³n. (De hecho, este conjunto de metadatos se ha usado para crear varias colecciones Greenstone que comparten una misma estructura y organizaciÃ³n, pero con diferentes contenidos, incluyendo las colecciones deÂ <i>Muestra</i>Â y la delÂ <i>Subconjunto de la Biblioteca para el Desarrollo</i>Â que se incluyen como ejemplos junto con Greenstone.)</Text>
+<Text id="173">El conjunto de metadatos DLS contiene los siguientes elementos:</Text>
+<BulletList>
+<Bullet>
+<Text id="174">TÃ­tulo</Text>
+</Bullet>
+<Bullet>
+<Text id="175">Tema</Text>
+</Bullet>
+<Bullet>
+<Text id="176">Idioma</Text>
+</Bullet>
+<Bullet>
+<Text id="177">OrganizaciÃ³n</Text>
+</Bullet>
+<Bullet>
+<Text id="178">Palabra clave (es decir, âCÃ³moâ).</Text>
+</Bullet>
+</BulletList>
+<Text id="179">(Existe ademÃ¡s un elemento de metadato llamadoÂ <i>AZList</i>Â que se utiliza para determinar quÃ© compartimento de la lista alfabÃ©tica contiene el tÃ­tulo del documento, con valores como âA-Bâ o âC-D-Eâ. Esto se utiliza para lograr un control preciso sobre las divisiones de la lista. En la mayorÃ­a de las otras colecciones estos compartimentos estÃ¡n ausentes y Greenstone los asigna por sÃ­ mismo.)</Text>
+<Text id="180">Si en cambio el usuario eligiÃ³ âNueva ColecciÃ³nâ, se le pedirÃ¡ que seleccione los conjuntos de metadatos que se van a usar en la nueva colecciÃ³n. Se ofrecen tres conjuntos estÃ¡ndar: Dublin Core, el conjunto de metadatos DLS mencionado arriba y un conjunto que comprende elementos de metadatos extraÃ­dos automÃ¡ticamente por Greenstone de los documentos de la colecciÃ³n. El usuario tambiÃ©n puede crear nuevos conjuntos de metadatos por medio de una pantalla que se activa a travÃ©s del menÃº âmetadatosâ.</Text>
+<Text id="181">Varios conjuntos de metadatos diferentes se pueden asociar a la misma colecciÃ³n, ya que el sistema los mantiene separados (de tal manera que los documentos, por ejemplo, pueden tener unÂ <i>TÃ­tulo</i>Â en Dublin Core y uno en DLS). Estos conjuntos se mantienen claramente diferenciados en la interfaz. Entre bastidores los conjuntos de metadatos se representan en XML.</Text>
+</Content>
+</Subsection>
+<Subsection id="assembling_the_source_material">
+<Title>
+<Text id="182">Reuniendo el material</Text>
+</Title>
+<Content>
+<Text id="183">DespuÃ©s de hacer click en el botÃ³nÂ <i>Aceptar</i>Â las partes restantes de la interfaz que habÃ­an permanecido sombreadas hasta este momento se activarÃ¡n. La pantallaÂ <i>Reunir</i>, seleccionado por medio de la pestaÃ±a del mismo nombre que se encuentra cerca de la parte superior de la figura 4, aparecerÃ¡ en pantalla. Esto le permitirÃ¡ al usuario explorar el espacio de archivos y las colecciones existentes en su computadora, y reunir los documentos seleccionados para la nueva colecciÃ³n. La pantalla se divide en dos secciones: la izquierda para explorar las estructuras existentes y la derecha para los documentos que integrarÃ¡n la colecciÃ³n.</Text>
+<Text id="184">Las operaciones disponibles en esta etapa incluyen:</Text>
+<BulletList>
+<Bullet>
+<Text id="185">Navegar de manera normal por las jerarquÃ­as de la estructura de archivos existente y por la que se estÃ¡ creando.</Text>
+</Bullet>
+<Bullet>
+<Text id="186">Arrastrar y colocar archivos en la nueva colecciÃ³n.</Text>
+</Bullet>
+<Bullet>
+<Text id="187">Seleccionar varios archivos a la vez.</Text>
+</Bullet>
+<Bullet>
+<Text id="188">Arrastrar y colocar subjerarquÃ­as completas.</Text>
+</Bullet>
+<Bullet>
+<Text id="189">Eliminar documentos de la naciente colecciÃ³n.</Text>
+</Bullet>
+<Bullet>
+<Text id="190">Crear nuevas subjerarquÃ­as dentro de la colecciÃ³n.</Text>
+</Bullet>
+<Bullet>
+<Text id="191">Filtrar los archivos que son visibles, tanto en el sistema local de archivos como en la colecciÃ³n, con base en grupos predeterminados o en tÃ©rminos de correspondencia de archivos estÃ¡ndar.</Text>
+</Bullet>
+<Bullet>
+<Text id="192">Llamar al programa apropiado para que muestre en pantalla los contenidos de un archivo seleccionado haciendo doble click en Ã©l.</Text>
+</Bullet>
+</BulletList>
+<Text id="193">Se ha tenido especial cuidado en evitar los conflictos entre nombres cuando archivos con el mismo nombre en diferentes partes de la estructura de directorios de la computadora se copian en la misma carpeta de la colecciÃ³n.</Text>
+<Text id="194">En la figura 5 el usuario estÃ¡ utilizando la pantalla interactiva del Ã¡rbol de archivos para explorar el sistema de archivos local. En esta etapa la colecciÃ³n a la derecha estÃ¡ vacÃ­a. El usuario la llena arrastrando y colocando los archivos correspondientes de la parte izquierda a la parte derecha de la pantalla. Estos archivos se âcopianâ en vez de âmoverseâ, de tal manera que el sistema original de archivos no resulta afectado. Las tÃ©cnicas usuales para seleccionar varios archivos, arrastrarlos y colocarlos, estructurar la nueva colecciÃ³n creando subdirectorios (âcarpetasâ) y eliminar archivos de ella moviÃ©ndolos al basurero o a la papelera de reciclaje estÃ¡n todas ellas disponibles.</Text>
+<Text id="195">Las colecciones existentes se representan por medio de un subdirectorio a la izquierda llamado âColecciones Greenstoneâ, el cual puede abrirse y explorarse como cualquier otro directorio. Sin embargo, los documentos que se encuentran ahÃ­ difieren de los archivos comunes debido a que ya tienen metadatos adjuntos y estos se conservan cuando pasan a formar parte de la nueva colecciÃ³n. Los conflictos podrÃ­an surgir debido a que sus metadatos tal vez les fueron asignados usando un conjunto diferente de metadatos del que se usa para la nueva colecciÃ³n, por lo que el usuario deberÃ¡ resolver esto. En la figura 6 el usuario ha seleccionado algunos documentos de la colecciÃ³n existente y los ha arrastrado a la nueva colecciÃ³n. La ventana que aparece explica que el elemento de metadatoÂ <i>Organization [OrganizaciÃ³n]</i>Â no se pudo importar automÃ¡ticamente y le pide al usuario que seleccione un conjunto de metadatos y presioneÂ <i>A Ã±adir</i>Â para aÃ±adir el elemento de metadato a dicho conjunto,<FootnoteRef id="1"/>o que elija un conjunto de metadatos, luego un elemento y presioneÂ <i>Combinar</i>Â para nombrar nuevamente el antiguo elemento de metadato de acuerdo al nuevo y combinarlos. Los metadatos de los siguientes documentos de la misma colecciÃ³n serÃ¡n tratados automÃ¡ticamente de la misma manera.</Text>
+<Text id="196">Cuando se seleccionen, arrastren y coloquen grandes conjuntos de archivos en la nueva colecciÃ³n, la operaciÃ³n de copiado puede llevar algÃºn tiempo, particularmente si esto incluye la conversiÃ³n de metadatos. Para indicar el grado de avance la interfaz muestra el archivo que se estÃ¡ copiando y el porcentaje de archivos que se han procesado.</Text>
+<Text id="197">TambiÃ©n se cuenta con programas especiales para tratar con grandes conjuntos de archivos. Por ejemplo, el usuario puede filtrar los directorios y subdirectorios para mostrar Ãºnicamente ciertos archivos por medio de un menÃº de tipos de archivos que se encuentra debajo. En la figura 7 Ãºnicamente se muestran los archivos HTM y HTML y sÃ³lo se copiarÃ¡n estos archivos al momento de arrastrarlos y colocarlos en la nueva colecciÃ³n.</Text>
+</Content>
+</Subsection>
+<Subsection id="enriching_the_documents">
+<Title>
+<Text id="198">Enriqueciendo los documentos</Text>
+</Title>
+<Content>
+<Text id="199">La siguiente fase es enriquecer los documentos aÃ±adiendo los metadatos. La pestaÃ±aÂ <i>Enriquecer</i>Â despliega una nueva pantalla de informaciÃ³n (figura 8), la cual muestra los directorios y subdirectorios de la colecciÃ³n a la izquierda y a la derecha permite aÃ±adir los metadatos a los documentos individuales o a los grupos de documentos.</Text>
+<Text id="200">Los documentos que se copiaron durante el primer paso incluyen todos los metadatos que se les hayan asociado. Si un documento es parte de una colecciÃ³n Greenstone, los metadatos definidos previamente pasan a formar parte de la nueva colecciÃ³n. Ciertamente, es posible que esta nueva colecciÃ³n tenga un conjunto diferente de metadatos, o quizÃ¡ sÃ³lo un subconjunto de los metadatos definidos y Ãºnicamente se conserven los metadatos que pertenecen al conjunto de la nueva colecciÃ³n. La soluciÃ³n de este tipo de conflictos tal vez requiera la intervenciÃ³n del usuario por medio de un diÃ¡logo suplementario (figura 6). Cualquier selecciÃ³n que se haga se recordarÃ¡ para la copia de los siguientes archivos.</Text>
+<Text id="201">La pantallaÂ <i>Enriquecer</i>Â permite asignar los valores de los metadatos a los documentos de la colecciÃ³n Por ejemplo, se pueden agregar nuevos valores al conjunto de los valores existentes para un elemento. Si los valores del elemento tienen una estructura jerÃ¡rquica, la jerarquÃ­a se puede extender de la misma forma.</Text>
+<Figure id="importing_existing_metadata">
+<Title>
+<Text id="202">Importando metadatos existentes</Text>
+</Title>
+<File width="380" height="296" url="images/User_Fig_6.png"/>
+</Figure>
+<Figure id="filtering_the_file_trees.">
+<Title>
+<Text id="203">Filtrando los Ã¡rboles de archivos.</Text>
+</Title>
+<File width="380" height="297" url="images/User_Fig_7.png"/>
+</Figure>
+<Figure id="assigning_metadata_using_enrich_view">
+<Title>
+<Text id="204">Asignando metadatos por medio de la pantallaÂ <i>Enriquecer</i>.</Text>
+</Title>
+<File width="376" height="294" url="images/User_Fig_8.png"/>
+</Figure>
+<Figure id="viewing_all_metadata_for_selected_files">
+<Title>
+<Text id="205">Viendo todos los metadatos de los archivos seleccionados.</Text>
+</Title>
+<File width="376" height="294" url="images/User_Fig_9.png"/>
+</Figure>
+<Text id="206">Los valores de los metadatos tambiÃ©n pueden asignarse a carpetas justo de la misma manera. Los documentos que se encuentran en estas carpetas y para los cuales no se hayan especificado estos metadatos heredan sus valores. Sin embargo, estos pueden sustituirse posteriormente proporcionando valores diferentes para cada documento.</Text>
+<Text id="207">Las operaciones en esta etapa del proceso incluyen:</Text>
+<BulletList>
+<Bullet>
+<Text id="208">Asignar valores de metadatos nuevos y existentes a los documentos.</Text>
+</Bullet>
+<Bullet>
+<Text id="209">Asignar metadatos a un documento individual.</Text>
+</Bullet>
+<Bullet>
+<Text id="210">Asignar metadatos a una carpeta (estos son heredados por todos los documentos de la carpeta, incluyendo los que se encuentran en las carpetas anidadas).</Text>
+</Bullet>
+<Bullet>
+<Text id="211">Asignar metadatos jerÃ¡rquicos, cuya estructura pueda actualizarse dinÃ¡micamente en caso necesario.</Text>
+</Bullet>
+<Bullet>
+<Text id="212">Editar o actualizar metadatos.</Text>
+</Bullet>
+<Bullet>
+<Text id="213">Revisar los metadatos asignados a una selecciÃ³n de archivos y directorios.</Text>
+</Bullet>
+</BulletList>
+<Text id="214">Siguiendo con nuestro ejemplo, en la figura 8 el usuario ha seleccionado la carpetaÂ <i>ec121e</i>Â y le ha asignado el valor âEC Courierâ como metadato de laÂ <i>OrganizaciÃ³n</i>. Los botones para actualizar y eliminar el metadato se activan, dependiendo de las selecciones que se hayan hecho.</Text>
+<Text id="215">Durante la fase de enriquecimiento e inclusive en cualquier otro momento el usuario puede ver todos los metadatos que se le han asignado a los documentos de la colecciÃ³n. Esto se hace seleccionando el conjunto de documentos y eligiendoÂ <i>Metadatos Asignados</i>Â en el menÃº de conjuntos de metadato, el cual despliega una ventana como la que se puede ver en la figura 9. Esta ventana muestra los metadatos en forma de hoja de cÃ¡lculo. Para grandes colecciones resulta de gran utilidad poder ver solamente los metadatos asociados a ciertos tipos de documentos y si el usuario ha especificado un filtro de archivos tal como se menciona arriba, Ãºnicamente se mostrarÃ¡n los documentos seleccionados en la pantalla de metadatos.</Text>
+<Text id="216">La pantalla en la figura 10 le permite al usuario editar los conjuntos de metadatos. AquÃ­ el usuario estÃ¡ viendo el elementoÂ <i>Subject [Tema]</i>Â del conjunto DLS. Los valores de este elemento forman una jerarquÃ­a y el usuario estÃ¡ examinando y tal vez cambiando la lista de valores asignados. La misma pantalla tambiÃ©n le permite cambiar el âperfilâ para mapear los elementos de un conjunto de metadatos a otro. Este perfil se crea al momento de importar documentos de colecciones que tienen metadatos asignados previamente.</Text>
+<Figure id="editing_the_metadata_set">
+<Title>
+<Text id="217">Editando el conjunto de metadatos.</Text>
+</Title>
+<File width="376" height="294" url="images/User_Fig_10.png"/>
+</Figure>
+<Figure id="designing_the_collection">
+<Title>
+<Text id="218">DiseÃ±ando la colecciÃ³n</Text>
+</Title>
+<File width="376" height="294" url="images/User_Fig_11.png"/>
+</Figure>
+<Figure id="specifying_which_plug-ins_to_use">
+<Title>
+<Text id="219">Especificando los plugins que se van a usar.</Text>
+</Title>
+<File width="376" height="294" url="images/User_Fig_12.png"/>
+</Figure>
+<Figure id="configuring_arguments_to_a_plug-in">
+<Title>
+<Text id="220">Configurando los argumentos de los plugins.</Text>
+</Title>
+<File width="376" height="294" url="images/User_Fig_13.png"/>
+</Figure>
+</Content>
+</Subsection>
+<Subsection id="designing_the_collection_1">
+<Title>
+<Text id="221">DiseÃ±ando la colecciÃ³n</Text>
+</Title>
+<Content>
+<Text id="222">La pantallaÂ <i>DiseÃ±o</i>Â (figuras 11â13) le permite a uno especificar la estructura, organizaciÃ³n y presentaciÃ³n de la colecciÃ³n que se estÃ¡ creando. Tal como se mencionÃ³ antes, el resultado de este proceso se registra en un âarchivo de configuraciÃ³n de la colecciÃ³nâ, que es la forma que tiene Greenstone de expresar las funciones y programas que requiere una colecciÃ³n. Este paso incluye una serie de pantallas separadas, cada una de las cuales trata un aspecto relativo al diseÃ±o de la colecciÃ³n y sirve, en efecto, como un equivalente grÃ¡fico al proceso normal de editar manualmente el archivo de configuraciÃ³n.</Text>
+<Text id="223">Las operaciones incluyen:</Text>
+<BulletList>
+<Bullet>
+<Text id="224">Revisar y editar los metadatos a nivel de colecciÃ³n, como el tÃ­tulo, autor y disponibilidad de la colecciÃ³n.</Text>
+</Bullet>
+<Bullet>
+<Text id="225">Definir quÃ© Ã­ndices de texto completo se van a crear.</Text>
+</Bullet>
+<Bullet>
+<Text id="226">Crear subcolecciones y armar los Ã­ndices de las mismas. </Text>
+</Bullet>
+<Bullet>
+<Text id="227">AÃ±adir o eliminar el soporte de la interfaz para idiomas predefinidos.</Text>
+</Bullet>
+<Bullet>
+<Text id="228">Construir una lista de los plugins que se usarÃ¡n junto con sus argumentos. </Text>
+</Bullet>
+<Bullet>
+<Text id="229">Presentar la lista al usuario para que la revise y modifique.</Text>
+</Bullet>
+<Bullet>
+<Text id="230">Configurar plugins individuales.</Text>
+</Bullet>
+<Bullet>
+<Text id="231">Construir una lista de âclasificadoresâ, sus argumentos, asignaciÃ³n y configuraciÃ³n.</Text>
+</Bullet>
+<Bullet>
+<Text id="232">Asignar cadenas de formato a varios controles dentro de la colecciÃ³n, alterando asÃ­ su apariencia.</Text>
+</Bullet>
+<Bullet>
+<Text id="233">Revisar los conjuntos de metadatos usados en la colecciÃ³n junto con sus elementos.</Text>
+</Bullet>
+</BulletList>
+<Text id="234">En la figura 11 el usuario ha hecho click en la pestaÃ±aÂ <i>DiseÃ±o</i> y estÃ¡ revisando la informaciÃ³n general acerca de la colecciÃ³n, ingresada al momento de crearla. A la izquierda aparece una lista de las diferentes facetas que el usuario puede configurar: general, plugins de documento, tipos de bÃºsqueda, Ã­ndices de bÃºsqueda, Ã­ndices de particiÃ³n, bÃºsqueda cruzada a travÃ©s de varias colecciones, clasificadores de exploraciÃ³n, caracterÃ­sticas del formato, traducciÃ³n de texto y conjuntos de metadatos. La apariencia y funcionalidad varÃ­a entre ellas. Por ejemplo, al hacer click en el botÃ³nÂ <i>Plugins de documento</i>Â aparece la pantalla que se muestra en la figura 12, la cual le permite aÃ±adir, eliminar o configurar los plugins, asÃ­ como cambiar el orden en el que se aplican a los documentos.</Text>
+<Text id="235">Los plugins y clasificadores tienen varios argumentos u âopcionesâ diferentes que el usuario puede proporcionar. El cuadro de diÃ¡logo que aparece en la figura 13 muestra los argumentos que el usuario ha especificado para algunos de los plugins. Los campos sombreados se activan cuando el usuario aÃ±ade la opciÃ³n haciendo click en el recuadro que se encuentra a su lado. Debido a que Greenstone es un sistema abierto en constante crecimiento, el nÃºmero de opciones tiende a aumentar conforme los programadores aÃ±aden nuevos programas y funciones. Para arreglÃ¡rselas con esto, Greenstone tiene un programa de âinformaciÃ³n de pluginsâÂ  que muestra una lista de las opciones disponibles para cada plugin y la interfaz de bibliotecario recurre automÃ¡ticamente a esta lista para determinar las opciones que debe mostrar. Esto le permite a la interfaz del usuario mantener automÃ¡ticamente el ritmo de los desarrollos del programa de software.</Text>
+<Figure id="getting_ready_to_create_new_collection.">
+<Title>
+<Text id="236">PreparÃ¡ndose para crear una nueva colecciÃ³n.</Text>
+</Title>
+<File width="380" height="297" url="images/User_Fig_14.png"/>
+</Figure>
+<Figure id="previewing_the_newly_built_collection">
+<Title>
+<Text id="237">Vista previa de la nueva colecciÃ³n.</Text>
+</Title>
+<File width="380" height="272" url="images/User_Fig_15.png"/>
+</Figure>
+</Content>
+</Subsection>
+<Subsection id="building_the_collection">
+<Title>
+<Text id="238">Creando la colecciÃ³n</Text>
+</Title>
+<Content>
+<Text id="239">La pantallaÂ <i>Crear</i>Â (figura 14) se utiliza para construir una colecciÃ³n basada en los documentos y metadatos asignados. El peso de este trabajo lo lleva el cÃ³digo Greenstone. El usuario controla el proceso externo a travÃ©s de una serie de pantallas separadas, cada una de las cuales trata con los argumentos proporcionados durante las diferentes etapas del proceso de creaciÃ³n.</Text>
+<Text id="240">El usuario observa el proceso de construcciÃ³n a travÃ©s de una ventana que muestra no sÃ³lo los textos generados por los guiones de importaciÃ³n y creaciÃ³n de Ã­ndices de Greenstone, sino tambiÃ©n las barras de progreso que indican el grado general de avance de cada guiÃ³n.</Text>
+<Text id="241">La figura 14 muestra la pantallaÂ <i>Crear</i>. En la parte superior se muestran algunas opciones que pueden aplicarse durante el proceso de creaciÃ³n. El usuario selecciona los valores apropiados para cada opciÃ³n. Esta figura muestra asimismo un cuadro de ârecomendacionesâ que estÃ¡ disponible a travÃ©s de toda la interfaz para explicar la funciÃ³n de cada argumento.</Text>
+<Text id="242">Una vez que el usuario estÃ© satisfecho con los argumentos, deberÃ¡ hacer clickÂ en <i>Build Collection [Crear ColecciÃ³n]</i>Â . Greenstone imprime continuamente el texto que indica el grado de avance y Ã©ste se acompaÃ±a de una barra de progreso que muestra de forma aÃºn mÃ¡s clara esta informaciÃ³n.</Text>
+</Content>
+</Subsection>
+<Subsection id="previewing">
+<Title>
+<Text id="243">PresentaciÃ³n preliminar de la colecciÃ³n</Text>
+</Title>
+<Content>
+<Text id="244">El botÃ³n de Vista Previa de la colecciÃ³n (figura 14) se utiliza para ver la imagen de la colecciÃ³n que se acaba de crear. Al oprimir este botÃ³n se inicia un navegador de web que muestra la pÃ¡gina inicial de la colecciÃ³n (Figura 15). En la prÃ¡ctica la vista previa a menudo muestra las deficiencias en el diseÃ±o de la colecciÃ³n o en los valores de los metadatos individuales, por lo que con frecuencia el usuario debe regresar a etapas anteriores para poder corregirlas. Este botÃ³n se activa una vez que la colecciÃ³n se ha creado. La nueva colecciÃ³n tambiÃ©n se habrÃ¡ instalado en su pÃ¡gina principal Greenstone como una de las colecciones regulares.</Text>
+</Content>
+</Subsection>
+<Subsection id="help">
+<Title>
+<Text id="245">Ayuda</Text>
+</Title>
+<Content>
+<Text id="246">La ayuda en lÃ­nea siempre estÃ¡ disponible y se puede acudir a ella usando el elementoÂ <i>Ayuda</i>Â que se encuentra a la derecha de la barra principal de menÃºs en la parte superior de cada pantalla. Ãste abre un archivo estructurado jerÃ¡rquicamente con texto de ayuda, el cual toma en cuenta el contexto actual del usuario para destacar la secciÃ³n correspondiente a dicha etapa del proceso. MÃ¡s aÃºn, como se mencionÃ³ arriba cada vez que el cursor se mantenga sobre un objeto interactivo aparecerÃ¡ una pequeÃ±a ventana con ârecomendacionesâ, como se puede ver en la parte inferior de la figura 14.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="librarian_interface_user_guide">
+<Title>
+<Text id="247">Guia del Usuario de la Interfaz de Bibliotecario</Text>
+</Title>
+<Content>
+<Subsection id="starting_off">
+<Title>
+<Text id="248">Para empezar</Text>
+</Title>
+<Content>
+<Text id="249">Esta secciÃ³n explica cÃ³mo crear, cargar, guardar y borrar colecciones.</Text>
+<Part id="creating_a_new_collection">
+<Title>
+<Text id="250">Creando una nueva colecciÃ³n</Text>
+</Title>
+<Content>
+<Text id="251">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="252">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="253">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="254">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="255">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="256">Si hace click en "Cancelar" regresarÃ¡ inmediatamente a la pantalla principal.</Text>
+</Content>
+</Part>
+<Part id="saving_the_collection">
+<Title>
+<Text id="257">Guardar la colecciÃ³n</Text>
+</Title>
+<Content>
+<Text id="258">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 Produciendo una colecciÃ³n).</Text>
+<Text id="259">La Interfaz de Bibliotecario protege su trabajo guardÃ¡ndolo cada vez que salga del programa o cargue otra colecciÃ³n.</Text>
+<Text id="260">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>
+</Content>
+</Part>
+<Part id="opening_an_existing_collection">
+<Title>
+<Text id="261">Abriendo una colecciÃ³n existente</Text>
+</Title>
+<Content>
+<Text id="262">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="263">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="264">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 Importando Metadatos Previamente Asignados.</Text>
+</Content>
+</Part>
+<Part id="deleting_collections">
+<Title>
+<Text id="265">Borrando colecciones</Text>
+</Title>
+<Content>
+<Text id="266">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>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="downloading_files_from_the_internet">
+<Title>
+<Text id="267">Descargando archivos de Internet</Text>
+</Title>
+<Content>
+<Text id="268">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>
+<Part id="the_download_view">
+<Title>
+<Text id="269">La vista en Bajar</Text>
+</Title>
+<Content>
+<Text id="270">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="271">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="272">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="273">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="274">La secciÃ³n Preferencias 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>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="collecting_files_for_your_collection">
+<Title>
+<Text id="275">Reuniendo archivos para su colecciÃ³n</Text>
+</Title>
+<Content>
+<Text id="276">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>
+<Part id="the_gather_view">
+<Title>
+<Text id="277">La pantalla de selecciÃ³n de documentos</Text>
+</Title>
+<Content>
+<Text id="278">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="279">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="280">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 AsociaciÃ³n de archivos).</Text>
+<Text id="281">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="282">La estructura de directorios y subdirectorios de la colecciÃ³n muestra sus contenidos. Inicialmente estÃ¡ vacÃ­a.</Text>
+<Text id="283">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="284">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="285">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 Creando carpetas), 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="286">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="287">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>
+</Content>
+</Part>
+<Part id="creating_folders">
+<Title>
+<Text id="288">Creando carpetas</Text>
+</Title>
+<Content>
+<Text id="289">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="290">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="291">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>
+</Content>
+</Part>
+<Part id="adding_files">
+<Title>
+<Text id="292">AÃ±adiendo archivos</Text>
+</Title>
+<Content>
+<Text id="293">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="294">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="295">Ã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="296">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 Importando metadatos previamente asignados. 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>
+</Content>
+</Part>
+<Part id="removing_files">
+<Title>
+<Text id="297">Eliminando archivos</Text>
+</Title>
+<Content>
+<Text id="298">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 selecciÃ³n de documentos para la colecciÃ³n.</Text>
+<Text id="299">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>
+</Content>
+</Part>
+<Part id="filtering_the_tree">
+<Title>
+<Text id="300">Filtrando la estructura de directorios y subdirectorios</Text>
+</Title>
+<Content>
+<Text id="301">"Filtrar" la estructura de directorios y subdirectorios de la colecciÃ³n limita la bÃºsqueda a determinados tipos de archivos.</Text>
+<Text id="302">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="303">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>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="enriching_the_collection_with_metadata">
+<Title>
+<Text id="304">Enriqueciendo la colecciÃ³n con metadatos</Text>
+</Title>
+<Content>
+<Text id="305">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>
+<Part id="the_enrich_view">
+<Title>
+<Text id="306">La pantalla de asignaciÃ³n de metadatos</Text>
+</Title>
+<Content>
+<Text id="307">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="308">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="309">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="310">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="311">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="312">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>
+</Content>
+</Part>
+<Part id="selecting_metadata_sets">
+<Title>
+<Text id="313">Seleccionando conjuntos de metadatos</Text>
+</Title>
+<Content>
+<Text id="314">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="315">Para controlar los conjuntos de metadatos usados en una colecciÃ³n, utilice la opciÃ³n "Conjuntos de metadatos" en la vista DiseÃ±o.</Text>
+</Content>
+</Part>
+<Part id="appending_new_metadata">
+<Title>
+<Text id="316">Agregando nuevos metadatos</Text>
+</Title>
+<Content>
+<Text id="317">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="318">A continuaciÃ³n, seleccione el elemento de metadato que desea aÃ±adir haciendo click en la fila correspondiente de la tabla.</Text>
+<Text id="319">Escriba el valor en el campo de valores. Use el carÃ¡cter "|" para aÃ±adir estructura, tal y como se explica en Vista para Enriquecer. 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="320">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>
+</Content>
+</Part>
+<Part id="adding_previously_defined_metadata">
+<Title>
+<Text id="321">AÃ±adiendo Metadatos Previamente Definidos</Text>
+</Title>
+<Content>
+<Text id="322">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="323">El proceso de aÃ±adir metadatos con valores existentes a carpetas o a varios archivos juntos es exactamente igual.</Text>
+</Content>
+</Part>
+<Part id="editing_or_removing_metadata">
+<Title>
+<Text id="324">Editar o Borrar Metadatos</Text>
+</Title>
+<Content>
+<Text id="325">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="326">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="327">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>
+</Content>
+</Part>
+<Part id="reviewing_assigned_metadata">
+<Title>
+<Text id="328">Revisando los metadatos asignados</Text>
+</Title>
+<Content>
+<Text id="329">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="330">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="331">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="332">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="333">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="334">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>
+</Content>
+</Part>
+<Part id="importing_previously_assigned_metadata">
+<Title>
+<Text id="335">Importando metadatos previamente asignados</Text>
+</Title>
+<Content>
+<Text id="336">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="337">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="338">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="339">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="340">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>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="designing_your_collection_appearance">
+<Title>
+<Text id="341">DiseÃ±ando la apariencia de su colecciÃ³n</Text>
+</Title>
+<Content>
+<Text id="342">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>
+<Part id="the_design_view">
+<Title>
+<Text id="343">La pantalla de diseÃ±o</Text>
+</Title>
+<Content>
+<Text id="344">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="345">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="346">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="347">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>
+</Content>
+</Part>
+<Part id="general">
+<Title>
+<Text id="348">General</Text>
+</Title>
+<Content>
+<Text id="349">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="350">AquÃ­ pueden modificarse los valores proporcionados durante la fase de creaciÃ³n de la colecciÃ³n.</Text>
+<Text id="351">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 Creando una nueva colecciÃ³n.</Text>
+</Content>
+</Part>
+<Part id="document_plugins">
+<Title>
+<Text id="352">Plugins</Text>
+</Title>
+<Content>
+<Text id="353">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="354">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="355">Para quitar un plugin de la lista, selecciÃ³nelo y haga click en "Eliminar plugin".</Text>
+<Text id="356">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="357">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="358">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="359">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 Preferencias). </Text>
+</Content>
+</Part>
+<Part id="search_types">
+<Title>
+<Text id="360">Tipos de bÃºsqueda</Text>
+</Title>
+<Content>
+<Text id="361">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="362">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="363">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="364">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>
+</Content>
+</Part>
+<Part id="search_indexes">
+<Title>
+<Text id="365">Ãndices de bÃºsqueda</Text>
+</Title>
+<Content>
+<Text id="366">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="367">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="368">Para editar un Ã­ndice, selecciÃ³nelo, cambie los detalles del Ã­ndice, y pulse "Reemplazar Ãndice".</Text>
+<Text id="369">Para quitar un Ã­ndice de la lista de Ã­ndices asignados, selecciÃ³nelo y haga click en "Eliminar Ã­ndice".</Text>
+<Text id="370">Para crear un Ã­ndice que cubra todo el texto y todos los metadatos, pulse sobre "AÃ±adir todos".</Text>
+<Text id="371">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="372">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="373">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>
+</Content>
+</Part>
+<Part id="partition_indexes">
+<Title>
+<Text id="374">Particiones</Text>
+</Title>
+<Content>
+<Text id="375">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="376">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="377">La pantalla de ParticiÃ³n de Ãndices sÃ³lo se activa en los modos Especialista de Sistemas Bibliotecarios y Experto (vea la secciÃ³n Preferencias). 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>
+</Content>
+</Part>
+<Part id="define_filters">
+<Title>
+<Text id="378">Definir filtros</Text>
+</Title>
+<Content>
+<Text id="379">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="380">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="381">Para quitar un filtro de la lista, selecciÃ³nelo y haga click en "Eliminar filtro".</Text>
+<Text id="382">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>
+</Content>
+</Part>
+<Part id="assign_partitions">
+<Title>
+<Text id="383">Asignar particiones</Text>
+</Title>
+<Content>
+<Text id="384">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="385">Para quitar una particiÃ³n de la lista, selecciÃ³nela y haga click en "Eliminar particiÃ³n".</Text>
+<Text id="386">Para hacer que una particiÃ³n determinada sea el valor por omisiÃ³n, selecciÃ³nela de la lista y haga click en "Predeterminar".</Text>
+</Content>
+</Part>
+<Part id="assign_languages">
+<Title>
+<Text id="387">Asignar idiomas</Text>
+</Title>
+<Content>
+<Text id="388">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="389">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="390">Para quitar un idioma, escÃ³jalo de la lista "SelecciÃ³n de idiomas" y haga click en "Eliminar idioma".</Text>
+<Text id="391">Para establecer un idioma por omisiÃ³n, selecciÃ³nelo de la lista y haga click en "Predeterminar".</Text>
+</Content>
+</Part>
+<Part id="cross-collection_search">
+<Title>
+<Text id="392">BÃºsqueda cruzada a travÃ©s de varias colecciones</Text>
+</Title>
+<Content>
+<Text id="393">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="394">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="395">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="396">Para mayor informaciÃ³n vea el CapÃ­tulo 1 de la GuÃ­a del Programador de Greenstone.</Text>
+</Content>
+</Part>
+<Part id="browsing_classifiers">
+<Title>
+<Text id="397">Clasificadores de exploraciÃ³n</Text>
+</Title>
+<Content>
+<Text id="398">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="399">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 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="400">Para quitar un clasificador de la lista, selecciÃ³nelo y haga click en "Eliminar clasificador".</Text>
+<Text id="401">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="402">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="403">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>
+</Content>
+</Part>
+<Part id="format_features">
+<Title>
+<Text id="404">Formatos</Text>
+</Title>
+<Content>
+<Text id="405">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="406">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="407">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="408">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="409">Para quitar un comando de formato de la lista, selecciÃ³nelo y haga click en "Eliminar formato".</Text>
+<Text id="410">Para cambiar un comando de formato, selecciÃ³nelo de la lista, modifique sus parÃ¡metros y haga click en "Reemplazar formato".</Text>
+<Text id="411">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="412">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>
+</Content>
+</Part>
+<Part id="translate_text">
+<Title>
+<Text id="413">TraducciÃ³n de textos</Text>
+</Title>
+<Content>
+<Text id="414">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="415">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="416">Para quitar una traducciÃ³n existente, selecciÃ³nela de la tabla "Traducciones asignadas" y haga click en "Eliminar traducciÃ³n".</Text>
+<Text id="417">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>
+</Content>
+</Part>
+<Part id="metadata_sets">
+<Title>
+<Text id="418">Conjuntos de metadatos</Text>
+</Title>
+<Content>
+<Text id="419">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="420">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="421">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="422">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="423">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>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="producing_your_collection">
+<Title>
+<Text id="424">Produciendo una colecciÃ³n</Text>
+</Title>
+<Content>
+<Text id="425">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>
+<Part id="the_create_view">
+<Title>
+<Text id="426">La pantalla de creaciÃ³n de la colecciÃ³n</Text>
+</Title>
+<Content>
+<Text id="427">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="428">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="429">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>
+</Content>
+</Part>
+<Part id="import_and_build_settings">
+<Title>
+<Text id="430">Controles de importaciÃ³n y construcciÃ³n </Text>
+</Title>
+<Content>
+<Text id="431">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="432">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 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>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="miscellaneous">
+<Title>
+<Text id="433">MiscelÃ¡nea</Text>
+</Title>
+<Content>
+<Text id="434">Esta secciÃ³n describe funciones y caracterÃ­sticas de la Interfaz de Bibliotecario que no estÃ¡n asociadas a ninguna pantalla en particular.</Text>
+<Part id="preferences">
+<Title>
+<Text id="435">Preferencias</Text>
+</Title>
+<Content>
+<Text id="436">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="437">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="438">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="439">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="440">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="441">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 Descargando Archivos del Internet 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="442">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>
+</Content>
+</Part>
+<Part id="file_associations">
+<Title>
+<Text id="443">AsociaciÃ³n de archivos</Text>
+</Title>
+<Content>
+<Text id="444">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="445">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="446">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="447">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="448">Las asociaciones de archivos se guardan en la carpeta principal de la Interfaz de Bibliotecario en un archivo llamado "associations.xml".</Text>
+</Content>
+</Part>
+<Part id="exporting_collections_to_cddvd">
+<Title>
+<Text id="449">Exportando colecciones a un CD/DVD</Text>
+</Title>
+<Content>
+<Text id="450">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="451">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="452">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>
+</Content>
+</Part>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="tagging_document_files">
+<Title>
+<Text id="453">Etiquetado de los Archivos de Documento</Text>
+</Title>
+<Content>
+<Text id="454">Muy a menudo es necesario estructurar los documentos de origen (<i>source documents</i>) en secciones y subsecciones y se necesita comunicar esta informaciÃ³n a Greenstone para que preserve la estructura jerÃ¡rquica. AdemÃ¡s, se pueden asociar metadatos, generalmente el tÃ­tulo, a cada secciÃ³n y subsecciÃ³n.</Text>
+<Text id="455">Los documentos de origen obtenidos mediante un proceso de OCR suelen ser una serie de archivos de tratamiento de texto con sus ilustraciones. Cuando se trate de archivos en formato Word de Microsoft, podrÃ¡ utilizarse elÂ <i>plugin</i>Â Word para introducirlos en Greenstone. De otra forma, cabe la posibilidad de convertirlos en archivos HTML e incorporarlos a Greenstone mediante el plugin HTML.</Text>
+<Text id="456">En cualquiera de los dos casos es preciso indicar la estructura jerÃ¡rquica de un documento insertando etiquetas en el texto, como sigue:</Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>&lt;Description&gt;</CodeLine>
+<Text id="457">Â Â Â Â Â  &lt;Metadata name=âTitleâ&gt; Realizing human rights for poor people: Strategies for achieving the international development targets &lt;/Metadata&gt;</Text>
+<CodeLine>&lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="458"><i>(el texto de la secciÃ³n va aquÃ­)</i></Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="459">Se utilizan los marcadores &lt;!-- y --&gt; porque indican que se trata de comentarios en HTML, y de esta forma las etiquetas de una secciÃ³n no influirÃ¡n en el formato del documento. Debe incluir estos marcadores alrededor de sus etiquetas de secciÃ³n, aÃºn cuando el documento que estÃ© trabajando no sea HTML (por ejemplo si es un archivo Word de Microsoft).</Text>
+<Text id="460">En la parte correspondiente a la descripciÃ³n (entre las etiquetas &lt;Description&gt; y &lt;/Description&gt;) pueden especificarse otros tipos de metadatos, aunque no se haga para colecciones como las aquÃ­ descritas.</Text>
+<Text id="461">Es importante recordar que cuando inserta etiquetas de secciÃ³n, estÃ¡ creando una tabla de contenidos jerÃ¡rquica. Esto significa que las secciones pueden estar anidadas dentro de otras secciones. De hecho, todas las secciones deben estar anidadas dentro de una Ãºnica secciÃ³n que abarca a todo el documento.</Text>
+<Text id="462">El siguiente ejemplo muestra un documento con dos capÃ­tulos, el segundo de los cuales contiene dos subsecciones. Para ver ejemplos reales de documentos de origen etiquetados de esta manera, vea los documentos de origen para las colecciones Demo y DLS.</Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>Â  &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;Metadata name="TÃ­tulo"&gt;Mi Documento&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â  &lt;/Description&gt;</CodeLine>
+<CodeLine>Â  &lt;Section&gt; </CodeLine>
+<CodeLine>Â Â Â  &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â  &lt;Metadata name="TÃ­tulo"&gt;CapÃ­tulo 1&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="463"><i>(el texto del capÃ­tulo 1 va aquÃ­)</i></Text>
+<CodeLine>&lt;!â</CodeLine>
+<CodeLine>Â  &lt;/Section&gt;</CodeLine>
+<CodeLine>Â  &lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â  &lt;Metadata name="TÃ­tulo"&gt;CapÃ­tulo 2&lt;/Metadata&gt; </CodeLine>
+<CodeLine>Â Â Â  &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â  &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â  &lt;Metadata name="TÃ­tulo"&gt;SubsecciÃ³n 1&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â  &lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="464"><i>(el texto de la subsecciÃ³n 1Â  va aquÃ­)</i></Text>
+<CodeLine>&lt;!â</CodeLine>
+<CodeLine>Â Â Â  &lt;/Section&gt;</CodeLine>
+<CodeLine>Â Â Â  &lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â  &lt;Description&gt; </CodeLine>
+<CodeLine>Â Â Â Â Â Â Â  &lt;Metadata name="TÃ­tulo"&gt;SubsecciÃ³n 2&lt;/Metadata&gt; </CodeLine>
+<CodeLine>Â Â Â Â Â  &lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="465"><i>(el texto de la subsecciÃ³n 2Â  va aquÃ­)</i></Text>
+<CodeLine>&lt;!â</CodeLine>
+<CodeLine>Â Â Â  &lt;/Section&gt;</CodeLine>
+<CodeLine>Â  &lt;/Section&gt;</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="466">Recuerde que el metadato asignado desde adentro de una etiqueta de secciÃ³n en un documento de origen tiene prioridad sobre aquel que le fue asignado al documento como un todo. Esto significa que usted no deberÃ¡ especificar explÃ­citamente el metadato TÃ­tulo para la secciÃ³n de nivel superior dentro de un documento de origen a menos que quiera que sustituya el tÃ­tulo que le dio al momento de especificar el metadato. En el ejemplo de arriba, a menos que usted quiera sustituir el tÃ­tulo existente del documento deberÃ¡ omitir la lÃ­nea que dice:</Text>
+<CodeLine>&lt;Metadata name="TÃ­tulo"&gt;Mi Documento&lt;/Metadata&gt;</CodeLine>
+</Content>
+</Section>
+<Section id="the_collector">
+<Title>
+<Text id="467">El Colector</Text>
+</Title>
+<Content>
+<Text id="468">El Colector es una funciÃ³n que le ayuda a crear nuevas colecciones y modificar, aÃ±adir o suprimir colecciones. Para hacerlo, serÃ¡ guiado por una secuencia de pÃ¡ginas Web en que se le pedirÃ¡ la informaciÃ³n necesaria. La secuencia es muy fÃ¡cil de seguir y en esta secciÃ³n se le proporcionarÃ¡n las explicaciones necesarias. En lugar de utilizar el Colector, tambiÃ©n se pueden crear colecciones a partir de la lÃ­nea de comandos; en las primeras pÃ¡ginas de laÂ <i>GuÃ­a del Programador</i>Â se explica en detalle cÃ³mo hacerlo.</Text>
+<Text id="469">Antes de crear y distribuir colecciones de informaciÃ³n, hay que reflexionar sobre las consecuencias y las responsabilidades que ello entraÃ±a. Hay cuestiones jurÃ­dicas de derecho de autor: poder tener acceso a documentos no significa necesariamente poder comunicarlos a terceros. Hay tambiÃ©n cuestiones de tipo social: en el manejo de las colecciones se deben respetar los usos y costumbres de la comunidad de la que proceden los documentos. Y hay tambiÃ©n cuestiones Ã©ticas: algunos documentos no deben ponerse a disposiciÃ³n de nadie. Â¡La pluma es mÃ¡s poderosa que la espada! Sea consciente del poder de la informaciÃ³n y utilÃ­celo con prudencia.</Text>
+<Text id="470">Para acceder al Colector, haga clic en el enlace correspondiente en la pÃ¡gina principal de la biblioteca digital.</Text>
+<Text id="471">En Greenstone, la estructura de una colecciÃ³n en particular se determina en el momento de su creaciÃ³n. Ello incluye el formato de los documentos de origen, la manera de mostrarlos en la pantalla, la fuente de los metadatos, las funciones de consulta que deben suministrarse, los Ã­ndices de bÃºsqueda en texto completo que deben proporcionarse, y la manera en que deben mostrarse los resultados de las bÃºsquedas. Una vez creada la colecciÃ³n, es fÃ¡cil aÃ±adirle nuevos documentos, siempre que tengan el mismo formato que los documentos existentes y se suministre el mismo tipo de metadatos, exactamente de la misma manera.</Text>
+<Text id="472">El Colector tiene las funciones bÃ¡sicas siguientes:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="473">Crear una nueva colecciÃ³n con la misma estructura que una existente.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="474">Crear una nueva colecciÃ³n con una estructura diferente de las existentes.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="475">AÃ±adir nuevo material a una colecciÃ³n existente.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="476">Modificar la estructura de una colecciÃ³n existente.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="477">Suprimir una colecciÃ³n. </Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="478">Grabar una colecciÃ³n existente en un CD-ROM autÃ³nomo y de instalaciÃ³n automÃ¡tica.</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="479">En la Figura 16 se muestra la utilizaciÃ³n del Colector para la creaciÃ³n de una nueva colecciÃ³n, en este caso a partir de un conjunto de archivos HTML almacenados localmente. Se debe decidir en primer lugar si se ha de trabajar con una colecciÃ³n existente o crear una nueva. En el primer caso se presentan las opciones 1 y 2 arriba mencionadas; en el segundo, las opciones 3 a 6. En la Figura 16a, el usuario opta por crear una nueva colecciÃ³n.</Text>
+<Figure id="using_the_collector_to_build_a_new_collection">
+<Title>
+<Text id="480">UtilizaciÃ³n del Colector para crear una nueva colecciÃ³nÂ (continuaciÃ³n en las pÃ¡ginas siguientes)</Text>
+<SubTitle>
+<Text id="481">(a)</Text>
+</SubTitle>
+</Title>
+<File width="484" height="628" url="images/User_Fig_16a.png"/>
+</Figure>
+<Subsection id="logging_in">
+<Title>
+<Text id="482">Inicio de sesiÃ³n</Text>
+</Title>
+<Content>
+<Text id="483">En cualquier caso, es necesario en primer lugar iniciar la sesiÃ³n. Por lo general los usuarios utilizan su navegador Web para acceder a la funciÃ³n de creaciÃ³n de colecciÃ³n en una computadora remota y crear la colecciÃ³n en ese servidor. Obviamente, no podemos permitir que cualquier persona cree colecciones (aunque sÃ³lo sea por motivos de derechos), por lo cual Greenstone contiene un sistema de seguridad que obliga a las personas que desean crear colecciones iniciar en primer lugar la sesiÃ³n. Esto permite a un sistema central ofrecer un servicio a quienes desean crear colecciones de informaciÃ³n y utilizar ese servidor para ponerlas a disposiciÃ³n de otros. Por otra parte, si utiliza Greenstone en su propia computadora, puede crear colecciones localmente, pero sigue siendo necesario iniciar la sesiÃ³n, ya que otras personas que utilicen el sistema Greenstone en la misma computadora no estarÃ¡n habilitadas a crear colecciones sin una autorizaciÃ³n previa.</Text>
+</Content>
+</Subsection>
+<Subsection id="dialog_structure">
+<Title>
+<Text id="484">Estructura de diÃ¡logo</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_1">
+<Title>
+<Text id="485">UtilizaciÃ³n del Colector para crear una nueva colecciÃ³nÂ (continuaciÃ³n)</Text>
+<SubTitle>
+<Text id="486">(b)</Text>
+</SubTitle>
+</Title>
+<File width="484" height="628" url="images/User_Fig_16b.png"/>
+</Figure>
+<Text id="487">Una vez iniciada la sesiÃ³n, aparece la pÃ¡gina presentada en la Figura 16b. En Ã©sta se muestra la secuencia de pasos que supone la creaciÃ³n de una colecciÃ³n. Estos pasos son:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="488">Informaciones sobre la colecciÃ³n</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="489">Datos fuente</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="490">Configurar la colecciÃ³n</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="491">Crear la colecciÃ³n</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="492">Visualizar la colecciÃ³n</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="493">El primer paso consiste en especificar el nombre de la colecciÃ³n y la informaciÃ³n conexa. El segundo, en indicar la procedencia de los datos de origen. El tercero consiste en ajustar las opciones de configuraciÃ³n, etapa que resulta mÃ¡s Ãºtil a medida que usted adquiere experiencia con Greenstone. En el cuarto paso es donde la computadora efectÃºa toda su labor. Durante el proceso de âcreaciÃ³nâ el sistema elabora todos los Ã­ndices y reÃºne todas las demÃ¡s informaciones necesarias para el buen funcionamiento de la colecciÃ³n. El quinto paso consiste en visualizar la colecciÃ³n que se ha creado.</Text>
+<Text id="494">Estos cinco pasos se muestran como una secuencia lineal de botones grises en la parte inferior de la pantalla de la Figura 16b, y en la parte inferior de todas las demÃ¡s pÃ¡ginas generadas por el Colector. Esta pantalla ayuda a los usuarios a ubicarse en el proceso. El botÃ³n que se debe pulsar para continuar la secuencia aparece en verde (<i>informaciones sobre la colecciÃ³n</i>Â en la Figura 16b). Los botones grises (todos los demÃ¡s de la Figura 16b) estÃ¡n desactivados. Los botones cambian a color amarillo a medida que se avanza en la secuencia, y el usuario puede volver a cualquier paso anterior haciendo clic en el botÃ³n amarillo correspondiente. Esta pantalla sigue el modelo de los âasistentesâ que se utilizan ampliamente en los programas comerciales para guiar a los usuarios a travÃ©s de las diferentes etapas necesarias para la instalaciÃ³n de un nuevo programa.</Text>
+</Content>
+</Subsection>
+<Subsection id="collection_information">
+<Title>
+<Text id="495">Informaciones sobre la colecciÃ³n</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_2">
+<Title>
+<Text id="496">UtilizaciÃ³n del Colector para crear una nueva colecciÃ³nÂ (continuaciÃ³n)</Text>
+<SubTitle>
+<Text id="497">(c)</Text>
+</SubTitle>
+</Title>
+<File width="484" height="557" url="images/User_Fig_16c.png"/>
+</Figure>
+<Text id="498">En la Figura 16c se muestra el prÃ³ximo paso en la secuencia: las informaciones sobre la colecciÃ³n. Cuando se crea una nueva colecciÃ³n es necesario proporcionar algunas informaciones al respecto:</Text>
+<BulletList>
+<Bullet>
+<Text id="499">el tÃ­tulo</Text>
+</Bullet>
+<Bullet>
+<Text id="500">la direcciÃ³n de correo electrÃ³nico de contacto, y</Text>
+</Bullet>
+<Bullet>
+<Text id="501">una descripciÃ³n breve.</Text>
+</Bullet>
+</BulletList>
+<Text id="502">El tÃ­tulo de la colecciÃ³n es una frase breve que se utiliza constantemente en la biblioteca digital para identificar el contenido de la colecciÃ³n. Como ejemplos de tÃ­tulos pueden mencionarseÂ <i>Biblioteca de la alimentaciÃ³n y la nutriciÃ³n, Biblioteca sobre el medio ambiente mundial, Biblioteca para el desarrollo</i>, etc. La direcciÃ³n de correo electrÃ³nico especifica el primer punto de contacto para cualquier problema que se plantee con la colecciÃ³n. Si el programa Greenstone detecta un problema, puede enviarse un informe de diagnÃ³stico a esta direcciÃ³n. Por Ãºltimo, la descripciÃ³n breve consiste en una oraciÃ³n en que se enuncian los principios por los que se rige el contenido de la colecciÃ³n. Aparece en la primera pÃ¡gina, debajo del encabezadoÂ <i>acerca de esta colecciÃ³n</i>, cuando se presenta la colecciÃ³n.</Text>
+<Text id="503">La etapa en que se encuentra el usuario en la secuencia de creaciÃ³n de una colecciÃ³n estÃ¡ indicada por una flecha que aparece en la parte inferior de la pantalla, en este caso concreto, como muestra la Figura 16c, nos encontramos en la etapa de lasÂ <i>informaciones sobre la colecciÃ³n</i>. El usuario sigue a la Figura 16d pulsando el botÃ³n verdeÂ <i>datos fuente</i>.</Text>
+</Content>
+</Subsection>
+<Subsection id="source_data">
+<Title>
+<Text id="504">Datos fuente</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_3">
+<Title>
+<Text id="505">UtilizaciÃ³n del Colector para crear una nueva colecciÃ³nÂ (continuaciÃ³n)</Text>
+<SubTitle>
+<Text id="506">(d)</Text>
+</SubTitle>
+</Title>
+<File width="484" height="613" url="images/User_Fig_16d.png"/>
+</Figure>
+<Text id="507">La Figura 16d ilustra el momento en que el usuario especifica el texto de origen que corresponde a la colecciÃ³n. Puede usted basar su colecciÃ³n en una de las estructuras por defecto suministradas, o en la estructura de una colecciÃ³n existente.</Text>
+<Text id="508">Si opta por la estructura por defecto, la nueva colecciÃ³n podrÃ¡ contener documentos HTML (archivos que terminan enÂ <i>.htm</i>Â oÂ <i>.html</i>), documentos de texto sin formato (archivos que terminan enÂ <i>.txt</i>Â oÂ <i>.text</i>), documentos en formato Microsoft Word (archivos que terminan enÂ <i>.doc</i>), documentos pdf (archivos que terminan enÂ <i>.pdf</i>) o documentos de correo electrÃ³nico (archivos que terminan enÂ <i>.email</i>). En la secciÃ³n 3.9 se da mÃ¡s informaciÃ³n sobre los diferentes formatos de documento que pueden incluirse.</Text>
+<Text id="509">Si basa su nueva colecciÃ³n en una existente, los archivos de la nueva colecciÃ³n deben ser exactamente del mismo tipo que los utilizados para la creaciÃ³n de la colecciÃ³n existente. Conviene observar que algunas colecciones utilizan formatos de archivos de entrada no normalizados, mientras que otras utilizan metadatos especificados en archivos auxiliares. Si sus nuevos datos carecen de esta informaciÃ³n, algunas funciones de consulta pueden no funcionar correctamente. Por ejemplo, si usted clona la colecciÃ³n de demostraciÃ³n, podrÃ¡ percatarse de que los botonesÂ <i>temas, organizaciones</i>Â eÂ <i>Ã­ndices</i>Â no pueden activarse.</Text>
+<Text id="510">En la pÃ¡gina Web aparecen casillas para indicar la localizaciÃ³n de los documentos de origen: como se indica en la Figura 16d, se pueden especificar hasta tres fuentes distintas. Si necesita mÃ¡s, basta con hacer clic en el botÃ³n marcadoÂ <i>more sources</i>Â (mÃ¡s fuentes).</Text>
+<Text id="511">Hay tres tipos de especificaciones:</Text>
+<BulletList>
+<Bullet>
+<Text id="512">un nombre de directorio en el sistema del servidor Greenstone (que comienza con âfile://â)</Text>
+</Bullet>
+<Bullet>
+<Text id="513">una direcciÃ³n que comienza por âhttp://â para los archivos que han de descargarse de la Web</Text>
+</Bullet>
+<Bullet>
+<Text id="514">una direcciÃ³n que comienza por âftp://â para los archivos que han de descargarse utilizando un FTP anÃ³nimo.</Text>
+</Bullet>
+</BulletList>
+<Text id="515">Si utilizaÂ <i>file://</i>Â oÂ <i>ftp://</i>Â para especificar un archivo, se descargarÃ¡ ese archivo.</Text>
+<Text id="516">Si utilizaÂ <i>http://</i>, todo depende si la URL correspondiente hace aparecer en su navegador una pÃ¡gina Web normal o una lista de archivos. Si se trata de una pÃ¡gina, Ã©sta se descargarÃ¡, asÃ­ como todas las pÃ¡ginas con las que tiene un enlace y las pÃ¡ginas con las que Ã©stas tienen enlace, etc., siempre que residan en el mismo sitio, bajo esa URL.</Text>
+<Text id="517">Si utilizaÂ <i>file://</i>Â oÂ <i>ftp://</i>Â para especificar una carpeta o un directorio, o emplea una URLhttp://que lleva a una lista de archivos, todo lo que se encuentre en la carpeta y todas sus subcarpetas se incluirÃ¡n en la colecciÃ³n.</Text>
+<Text id="518">Puede usted especificar fuentes de varios tipos.</Text>
+<Text id="519">En este caso (Figura 16d) la nueva colecciÃ³n contendrÃ¡ documentos tomados de un sistema de archivos local asÃ­ como de un sitio Web remoto, que se copiarÃ¡ durante el proceso de creaciÃ³n de la colecciÃ³n.</Text>
+<Text id="520">Si se pulsa el botÃ³nÂ <i>configurar la colecciÃ³n</i>Â para pasar a la siguiente etapa de la creaciÃ³n, el Colector verificarÃ¡ que se puede llegar a todas las fuentes de datos que usted ha especificado. Esto puede tomar algunos segundos, o incluso algunos minutos si ha especificado varias fuentes. Si una o varias de las fuentes de datos que usted ha especificado no estÃ¡n disponibles, aparecerÃ¡ una pÃ¡gina como la de la Figura 16e, en que se marcan las fuentes no disponibles (en este caso, las dos).</Text>
+<Figure id="using_the_collector_to_build_a_new_collection_4">
+<Title>
+<Text id="521">UtilizaciÃ³n del Colector para crear una nueva colecciÃ³nÂ (continuaciÃ³n)</Text>
+<SubTitle>
+<Text id="522">(e)</Text>
+</SubTitle>
+</Title>
+<File width="484" height="613" url="images/User_Fig_16e.png"/>
+</Figure>
+<Text id="523">Las fuentes pueden no estar disponibles porque: </Text>
+<BulletList>
+<Bullet>
+<Text id="524">el archivo, el sitio FTP o la URL no existen;</Text>
+</Bullet>
+<Bullet>
+<Text id="525">necesita conectarse primero con su proveedor de servicios Internet; </Text>
+</Bullet>
+<Bullet>
+<Text id="526">estÃ¡ tratando de tener acceso a una URL protegida por un cortafuegos (<i>firewall</i>).</Text>
+</Bullet>
+</BulletList>
+<Text id="527">El Ãºltimo caso es posiblemente el mÃ¡s misterioso. Normalmente se produce si tiene que suministrar un nombre de usuario y una contraseÃ±a para tener acceso a Internet. A veces, si se introduce la URL, es posible ver la pÃ¡gina desde su navegador Web, aunque el Colector anuncia que no estÃ¡ disponible. La explicaciÃ³n es que la pÃ¡gina en su navegador puede venir de una copia almacenada localmente (<i>cache</i>). Por desgracia, las copias almacenadas localmente en la memoriaÂ <i>cache</i>Â son invisibles para el Colector. En este caso, recomendamos que descargue las pÃ¡ginas utilizando primero su navegador.</Text>
+</Content>
+</Subsection>
+<Subsection id="configuring_the_collection">
+<Title>
+<Text id="528">ConfiguraciÃ³n de la colecciÃ³n</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_5">
+<Title>
+<Text id="529">UtilizaciÃ³n del Colector para crear una nueva colecciÃ³nÂ (continuaciÃ³n)</Text>
+<SubTitle>
+<Text id="530">(f)</Text>
+</SubTitle>
+</Title>
+<File width="484" height="446" url="images/User_Fig_16f.png"/>
+</Figure>
+<Text id="531">En la Figura 16f se muestra la siguiente etapa. La creaciÃ³n y presentaciÃ³n de todas las colecciones se controlan mediante especificaciones registradas en un archivo especial de configuraciÃ³n de colecciÃ³n (vÃ©ase mÃ¡s abajo). Los usuarios experimentados podrÃ¡n utilizar esta pÃ¡gina para modificar los parÃ¡metros de configuraciÃ³n, pero la mayorÃ­a pasarÃ¡ directamente a la etapa final. En efecto, en la Figura 16d los botonesÂ <i>configurar la colecciÃ³n</i>Â yÂ <i>crear la colecciÃ³n</i>Â aparecen en color verde, lo cual significa que se puede obviar por completo el paso 3.</Text>
+<Text id="532">En nuestro ejemplo, el usuario ha introducido una pequeÃ±a modificaciÃ³n en el archivo de configuraciÃ³n por defecto, incluyendo el indicadorÂ <i>file_is_url</i>Â mediante el plugin HTML. El efecto de este indicador es que se insertan el metadato de URL en cada documento, basÃ¡ndose en la convenciÃ³n de nombre de archivo adoptada por el programa que crea la copia. Estos metadatos se utilizan en la colecciÃ³n para que los lectores puedan remitirse a la versiÃ³n original del documento y no a una copia local.</Text>
+</Content>
+</Subsection>
+<Subsection id="building_the_collection_1">
+<Title>
+<Text id="533">CreaciÃ³n de la colecciÃ³n</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_6">
+<Title>
+<Text id="534">UtilizaciÃ³n del Colector para crear una nueva colecciÃ³nÂ (continuaciÃ³n)</Text>
+<SubTitle>
+<Text id="535">(g)</Text>
+</SubTitle>
+</Title>
+<File width="484" height="445" url="images/User_Fig_16g.png"/>
+</Figure>
+<Text id="536">En la Figura 16g se muestra la etapa de âcreaciÃ³nâ. Hasta ahora, las respuestas al diÃ¡logo de la interfaz se han registrado meramente en un archivo temporal. La etapa de creaciÃ³n es aquÃ©lla en que se efectÃºa todo el trabajo.</Text>
+<Text id="537">Durante la creaciÃ³n de la colecciÃ³n se elaboran los Ã­ndices de consulta y de bÃºsqueda, siguiendo las instrucciones del archivo de configuraciÃ³n de la colecciÃ³n. El proceso de creaciÃ³n lleva entre varios minutos y varias horas, segÃºn el tamaÃ±o de la colecciÃ³n y la potencia de su computadora. En algunas colecciones muy voluminosas, la creaciÃ³n puede llevar mÃ¡s de un dÃ­a.</Text>
+<Text id="538">Al llegar a esta etapa, en la parte inferior de la pÃ¡gina Web aparece una lÃ­nea de estado que le informa cÃ³mo estÃ¡ progresando la operaciÃ³n, con una actualizaciÃ³n cada cinco segundos. El mensaje visible en la Figura 16f indica que cuando se tomÃ³ la instantÃ¡nea de la pantalla, se estaba convirtiendo un archivo de entrada.</Text>
+<Text id="539">Aparecen mensajes de alerta si se piden archivos de entrada o URL que no existen, o que existen pero no se dispone de un plugin para procesarlos, o el plugin no puede encontrar un archivo asociado, como un archivo de imagen incorporada en un documento HTML. La intenciÃ³n es que usted siga de cerca los progresos manteniendo esta ventana abierta en su navegador. Si algunos errores provocan el final prematuro del proceso, Ã©stos quedan registrados en esta zona de estado.</Text>
+<Text id="540">Puede detener el proceso de creaciÃ³n en cualquier momento haciendo clic en el botÃ³nÂ <i>Interrumpir la creaciÃ³n</i>Â que se muestra en la Figura 16g. Si sale de la pÃ¡gina Web (y no ha cancelado el proceso de creaciÃ³n con el botÃ³nÂ <i>Interrumpir la creaciÃ³n</i>), la operaciÃ³n de creaciÃ³n continuarÃ¡ y la nueva colecciÃ³n se instalarÃ¡ al final de la operaciÃ³n.</Text>
+</Content>
+</Subsection>
+<Subsection id="viewing_the_collection">
+<Title>
+<Text id="541">VisualizaciÃ³n de la colecciÃ³n</Text>
+</Title>
+<Content>
+<Text id="542">Cuando la colecciÃ³n estÃ¡ creada e instalada, aparece en la parte inferior de la Figura 16g la secuencia de botones visibles en la parte inferior de las Figuras 4b a 4f, con el botÃ³nÂ <i>visualizar la colecciÃ³n</i>Â activado. Al pulsar este botÃ³n, el usuario llega directamente a la colecciÃ³n reciÃ©n creada.</Text>
+<Text id="543">Por Ãºltimo, existe una funciÃ³n de correo electrÃ³nico para enviar un mensaje a la direcciÃ³n digital de contacto de la colecciÃ³n, asÃ­ como al administrador del sistema, cada vez que se crea (o se modifica) una colecciÃ³n. Esto permite que esos responsables se enteren de todos los cambios que se producen y sigan de cerca lo que sucede en el sistema. Esta funciÃ³n estÃ¡ desactivada por defecto, pero puede reactivarse modificando el archivo de configuraciÃ³nÂ <i>main.cfg</i>Â (vÃ©ase a este respecto la SecciÃ³n <CrossRef target="Chapter" external="Develop" lang="es" ref="configuring_your_greenstone_site"/> de laÂ <i>GuÃ­a del Programador de la Biblioteca Digital Greenstone</i>).</Text>
+</Content>
+</Subsection>
+<Subsection id="working_with_existing_collections">
+<Title>
+<Text id="544">Trabajar con colecciones existentes</Text>
+</Title>
+<Content>
+<Text id="545">Cuando comience a utilizar el Colector debe especificar si desea crear una colecciÃ³n totalmente nueva o trabajar con una existente, aÃ±adiÃ©ndole datos o suprimiÃ©ndolos. Como Greenstone crea automÃ¡ticamente todas las estructuras de bÃºsqueda y consulta a partir de los propios documentos, eso facilita la adiciÃ³n de nuevas informaciones a las colecciones existentes. Puesto que no se insertan enlaces manualmente, se pueden incorporar automÃ¡ticamente a la colecciÃ³n los nuevos documentos disponibles en el mismo formato.</Text>
+<Text id="546">Para trabajar con una colecciÃ³n existente, hay que seleccionar primero la colecciÃ³n a partir de una lista propuesta por el programa. Algunas colecciones estÃ¡n âprotegidas contra escrituraâ y no pueden ser alteradas: Ã©stas no aparecen en la lista de selecciÃ³n. Una vez escogida la colecciÃ³n, usted puede:</Text>
+<BulletList>
+<Bullet>
+<Text id="547">AÃ±adir nuevos datos y reconstituir la colecciÃ³n</Text>
+</Bullet>
+<Bullet>
+<Text id="548">Modificar el archivo de configuraciÃ³n de la colecciÃ³n</Text>
+</Bullet>
+<Bullet>
+<Text id="549">Suprimir completamente la colecciÃ³n</Text>
+</Bullet>
+<Bullet>
+<Text id="550">Exportar la colecciÃ³n a un CD-ROM</Text>
+</Bullet>
+</BulletList>
+<Part id="add_new_data">
+<Title>
+<Text id="551">AÃ±adir nuevos datos</Text>
+</Title>
+<Content>
+<Text id="552">Se aÃ±adirÃ¡n a la colecciÃ³n los archivos que usted especifique. CerciÃ³rese de no volver a especificar archivos que ya existen en la colecciÃ³n, pues de otro modo habrÃ¡ dos ejemplares. Los archivos se identifican por su ruta de acceso completa y las pÃ¡ginas Web por su direcciÃ³n Web absoluta. Se deben especificar los directorios y archivos del mismo modo que cuando se crea una nueva colecciÃ³n.</Text>
+<Text id="553">Si desea usted aÃ±adir datos a una colecciÃ³n y por algÃºn motivo el proceso de creaciÃ³n se interrumpe, la antigua versiÃ³n de la colecciÃ³n permanecerÃ¡ inalterada.</Text>
+</Content>
+</Part>
+<Part id="edit_configuration_file">
+<Title>
+<Text id="554">Modificar el archivo de configuraciÃ³n</Text>
+</Title>
+<Content>
+<Text id="555">Los usuarios experimentados pueden modificar el archivo de configuraciÃ³n de la colecciÃ³n, del mismo modo que cuando se crea una nueva colecciÃ³n. En la SecciÃ³n <CrossRef target="Chapter" ref="administration"/>Â <i>infra</i>Â se explican los parÃ¡metros de configuraciÃ³n.</Text>
+</Content>
+</Part>
+<Part id="delete_the_collection">
+<Title>
+<Text id="556">Suprimir la colecciÃ³n</Text>
+</Title>
+<Content>
+<Text id="557">Se le pedirÃ¡ que confirme si realmente desea suprimir la colecciÃ³n. Â¡Una vez suprimida, Greenstone no podrÃ¡ recuperarla!</Text>
+</Content>
+</Part>
+<Part id="export_the_collection">
+<Title>
+<Text id="558">Exportar la colecciÃ³n</Text>
+</Title>
+<Content>
+<Text id="559">Puede usted exportar la colecciÃ³n en una forma que permita grabarla en un CD-ROM Greenstone para Windows autÃ³nomo y de instalaciÃ³n automÃ¡tica. Como los programas comerciales que crean discos CD-ROM de instalaciÃ³n automÃ¡tica son onerosos, esta funciÃ³n incluye un mÃ³dulo de instalaciÃ³n propio del sistema.</Text>
+<Text id="560">Al exportar la colecciÃ³n, el cuadro de diÃ¡logo le informa del nombre del directorio en que se ha colocado el resultado. El contenido Ã­ntegro del directorio se grabarÃ¡ en el CD-ROM utilizando un programa estÃ¡ndar de grabaciÃ³n de CD.</Text>
+<Text id="561">La inmensa variedad de las diferentes configuraciones Windows posibles nos ha impedido probar y depurar el instalador de Greenstone en todas las condiciones posibles. Aunque produce discos CD-ROM que funcionan en la mayorÃ­a de los sistemas Windows, el instalador estÃ¡ aÃºn en proceso de elaboraciÃ³n. Si surgen problemas y dispone usted de un paquete de instalaciÃ³n comercial (por ejemplo, InstallShield), lo puede utilizar para crear discos CD-ROM a partir de la informaciÃ³n suministrada por Greenstone. El directorio de exportaciÃ³n antes mencionado contiene cuatro archivos relativos al proceso de instalaciÃ³n, y tres subdirectorios que contienen la colecciÃ³n y el programa informÃ¡tico completos. Quite los cuatro archivos y use InstallShield para obtener una imagen de CD-ROM que instalarÃ¡ esos directorios y crearÃ¡ un acceso directo al programaÂ <i>gsdl\server.exe</i>.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="document_formats_1">
+<Title>
+<Text id="562">Formatos de documentos</Text>
+</Title>
+<Content>
+<Text id="563">Cuando se crea una colecciÃ³n, Greenstone procesa cada diferente formato o documento de origen buscando un plugin que admita ese formato en particular. Los plugins estÃ¡n especificados en el archivo de configuraciÃ³n de la colecciÃ³n. Greenstone suele utilizar el nombre de archivo para determinar los formatos de documentos, por ejemplo,Â <i>foo.txt</i>Â se procesa como un archivo de texto,Â <i>foo.html</i>, como un archivo HTML yÂ <i>foo.doc</i>Â como un archivo Word.</Text>
+<Text id="564">Se ofrece a continuaciÃ³n un resumen de los plugins que estÃ¡n disponibles para los formatos de documento mÃ¡s utilizados. En laÂ <i>GuÃ­a del Programador de la Biblioteca Digital Greenstone</i>Â pueden consultarse mÃ¡s detalles sobre estos plugins y los plugins adicionales para formatos utilizados con menos frecuencia.</Text>
+<Part id="textplug">
+<Title>
+<Text id="565">TEXTPlug (*.txt,*.text)</Text>
+</Title>
+<Content>
+<Text id="566">TEXPlug interpreta un archivo de texto sin formato como un documento sencillo. AÃ±ade los metadatosÂ <i>tÃ­tulo</i>Â basÃ¡ndose en la primera lÃ­nea del archivo.</Text>
+</Content>
+</Part>
+<Part id="htmlplug">
+<Title>
+<Text id="567">htmlPlug (*.htm,*.html; tambiÃ©n .shtml, .shm, .asp, .php, .cgi)</Text>
+</Title>
+<Content>
+<Text id="568">htmlPlug procesa los archivos HTML. Extrae los metadatos deÂ <i>tÃ­tulo</i>Â basÃ¡ndose en la etiqueta &lt;title&gt;; tambiÃ©n puede extraer otros datos expresados utilizando una sintaxis de la âmetaetiquetaâ HTML. Este plugin ofrece muchas opciones que se presentan en laÂ <i>GuÃ­a del Programador de la Biblioteca Digital Greenstone</i>.</Text>
+</Content>
+</Part>
+<Part id="wordplug">
+<Title>
+<Text id="569">WORDPlug (*.doc)</Text>
+</Title>
+<Content>
+<Text id="570">WORDPlug importa documentos de formato Microsoft Word. Hay muchas variantes diferentes en el formato Word, e incluso los programas Microsoft cometen con frecuencia errores de conversiÃ³n. Greenstone utiliza programas independientes para convertir los archivos Word en HTML. En el caso de algunos formatos Word mÃ¡s antiguos, el sistema recurre a un algoritmo sencillo de extracciÃ³n que encuentra todas las porciones de texto en el archivo de entrada.</Text>
+</Content>
+</Part>
+<Part id="pdfplug">
+<Title>
+<Text id="571">PDFPlug (*.pdf)</Text>
+</Title>
+<Content>
+<Text id="572">PDFPlug importa documentos de formato Pdf de Adobe (âformato de documento portableâ). Al igual que WORDPlug, utiliza un programa independiente, en este casoÂ <i>pdftohtml</i>, para convertir los archivos PDF en HTML.</Text>
+<Text id="573">A semejanza de WORDPlug, las colecciones por defecto mostrarÃ¡n el equivalente HTML del archivo cuando el usuario haga clic en el iconoÂ <i>documento</i>Â ; sin embargo, es posible ajustar las cadenas de formato en el archivo de configuraciÃ³n de la colecciÃ³n para dar al usuario acceso al archivo PDF original, y le recomendamos que proceda asÃ­. Una vez mÃ¡s, basta con sustituir las etiquetas &lt;link&gt;...&lt;/link&gt; por &lt;srclink&gt;...&lt;/srclink&gt;.</Text>
+<Text id="574">El programaÂ <i>pdftohtml</i>Â no funciona con algunos archivos PDF. Lo que sucede es que el proceso de conversiÃ³n lleva un tiempo excepcionalmente prolongado y con frecuencia aparece en la pantalla un mensaje de error relativo a dicho proceso. Si ello ocurre, la Ãºnica soluciÃ³n que podemos ofrecerle es retirar de la colecciÃ³n el documento causante del error. PDFPlug tampoco puede tratar archivos PDF codificados.</Text>
+</Content>
+</Part>
+<Part id="psplug">
+<Title>
+<Text id="575">PSPlug (*.ps)</Text>
+</Title>
+<Content>
+<Text id="576">PSPlug importa documentos de formato PostScript. Funciona mejor si ya estÃ¡ instalado en su computadora un programa Linux estÃ¡ndar llamadoÂ <i>ps2ascii</i>. Este estÃ¡ disponible en la mayorÃ­a de las instalaciones Linux, pero no en Windows. Si el programa no estÃ¡ disponible, PSPlug se limita a un simple algoritmo de extracciÃ³n de texto.</Text>
+</Content>
+</Part>
+<Part id="emailplug">
+<Title>
+<Text id="577">EMAILPlug (*.email)</Text>
+</Title>
+<Content>
+<Text id="578">EMAILPlug importa los archivos que contienen mensajes de correo electrÃ³nico y puede funcionar con los formatos de correo electrÃ³nico comunes, como los utilizados por los usuarios de correo electrÃ³nico de Netscape, Eudora y Unix. Cada documento de origen se examina para determinar si contiene uno o varios mensajes de correo electrÃ³nico unidos en un archivo Ãºnico, y en ese caso se procesa el contenido. El plugin extrae los metadatosÂ <i>Subject (âAsuntoâ), To (âDestinatarioâ, âAâ), From (âRemitenteâ, âDeâ)</i>Â yÂ <i>Date (âFechaâ)</i>. Sin embargo, este plugin no puede todavÃ­a procesar correctamente los mensajes codificados de formato MIME, que aunque son legibles, tienen con frecuencia un aspecto extraÃ±o.</Text>
+</Content>
+</Part>
+<Part id="zipplug">
+<Title>
+<Text id="579">ZIPPlug (.gz, .z, .tgz, .taz, .bz, .zip, .tar)</Text>
+</Title>
+<Content>
+<Text id="580">El plugin ZIPPlug trata los siguientes formatos de entrada comprimidos y/o archivados: gzip (<i>.gz, .z, .tgz, .taz),</i>Â bzipÂ <i>(.bz,)</i>, zip (Â <i>.zip .jar)</i>Â y tarÂ <i>(.tar)</i>. Se basa en los programasÂ <i>gunzip, bunzip, unzip</i>Â yÂ <i>tar</i>, que son programas utilitarios Linux estÃ¡ndar. ZIPPlug estÃ¡ desactivado en las computadoras equipadas con Windows.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="administration">
+<Title>
+<Text id="581">AdministraciÃ³n</Text>
+</Title>
+<Content>
+<Text id="582">En toda instalaciÃ³n Greenstone estÃ¡ incluida una funciÃ³n âadministrativaâ. Para acceder a esta funciÃ³n, haga clic en el enlace correspondiente en la pÃ¡gina principal.</Text>
+<Text id="583">La pÃ¡gina principal, que se muestra en la Figura 17, proporciona informaciÃ³n sobre cada una de las colecciones que ofrece el sistema. Conviene observar que estÃ¡n incluidasÂ <i>todas</i>Â las colecciones, pues puede haber algunas âprivadasâ que no aparecen en la pÃ¡gina principal Greenstone. Para cada una se suministra su nombre abreviado, su nombre completo, se indica si estÃ¡ a disposiciÃ³n del pÃºblico y si estÃ¡ o no en funcionamiento. Si se hace clic en la abreviatura de una colecciÃ³n en particular (la primera columna de los enlaces en la Figura 17), se obtiene informaciÃ³n sobre esa colecciÃ³n, recopilada a partir del archivo de configuraciÃ³n de la colecciÃ³n y de otras estructuras internas creadas para esa colecciÃ³n. Si la colecciÃ³n es pÃºblica y estÃ¡ en funcionamiento, al hacer clic en el nombre completo de la colecciÃ³n (el segundo enlace) se visualizarÃ¡ la colecciÃ³n propiamente dicha.</Text>
+<Text id="584">La colecciÃ³n que hemos creado en las secciones 3.2 a 3.6 se llamaÂ <i>wohiex</i>, abreviatura deÂ <i>Womenâs History Excerpt</i>Â (Extractos de la Historia de las Mujeres), y estÃ¡ visible cerca de la parte inferior de la Figura 17. En la Figura 18 se muestra la informaciÃ³n que aparece cuando se hace clic en este enlace. En la primera secciÃ³n se dan algunas informaciones sobre el archivo de configuraciÃ³n y el tamaÃ±o de la colecciÃ³n (unos 1.000 documentos, cerca de 1 millÃ³n de palabras, mÃ¡s de 6 Mb). Las secciones siguientes contienen informaciÃ³n interna relacionada con el protocolo de comunicaciÃ³n utilizado para acceder a las colecciones. Por ejemplo, las opciones de filtro para âQueryFilterâ muestran las opciones y los valores posibles que pueden utilizarse cuando se consultan las colecciones.</Text>
+<Text id="585">La funciÃ³n administrativa presenta tambiÃ©n informaciÃ³n de configuraciÃ³n acerca de la instalaciÃ³n y permite modificarla. Facilita el examen de los registros de errores que dejan constancia de los errores internos, y de los registros de usuarios que dejan constancia de la utilizaciÃ³n de la colecciÃ³n. Permite que un usuario (o varios usuarios) especÃ­fico(s) autorice(n) a otros a crear colecciones y aÃ±adir nuevo material al existente. Se puede acceder a todas estas funciones de forma interactiva, a partir de los elementos de menÃº que se muestran en la parte izquierda de la Figura 17.</Text>
+<Figure id="greenstone_administration_facility">
+<Text id="586">FunciÃ³n de AdministraciÃ³n en Greenstone</Text>
+<File width="529" height="408" url="images/User_Fig_17.png"/>
+</Figure>
+<Figure id="information_about_the_womens_history_excerpt_collection">
+<Text id="587">InformaciÃ³n sobre la colecciÃ³nÂ <b><i>Womenâs History Excerpt</i></b></Text>
+<File width="529" height="355" url="images/User_Fig_18a.png"/>
+<File width="529" height="355" url="images/User_Fig_18b.png"/>
+</Figure>
+<Section id="configuration_files">
+<Title>
+<Text id="588">Archivos de configuraciÃ³n</Text>
+</Title>
+<Content>
+<Text id="589">Hay dos archivos de configuraciÃ³n que controlan el funcionamiento de Greenstone: el archivo de configuraciÃ³n de sitioÂ <i>gsdlsite.cfg</i>Â y el archivo de configuraciÃ³n principalÂ <i>main.cfg.</i></Text>
+<Text id="590">El archivoÂ <i>gsdlsite.cfg</i>Â Â  se utiliza para configurar el programa Greenstone para el sitio en que estÃ¡ instalado. EstÃ¡ concebido para registrar las opciones de configuraciÃ³n propias de un sitio determinado como, por ejemplo, el nombre del directorio en que se guarda el programa Greenstone, la direcciÃ³n HTTP del sistema Greenstone, y si se estÃ¡ utilizando o no la funciÃ³nÂ <i>fastcgi</i>. En laÂ <i>GuÃ­a de InstalaciÃ³n de la Biblioteca Digital Greenstone</i>Â se describen los elementos que contiene este archivo.</Text>
+<Text id="591">El archivoÂ <i>main.cfg</i>Â contiene informaciÃ³n comÃºn a la interfaz de todas las colecciones presentadas en el sitio Greenstone. Incluye la direcciÃ³n de correo electrÃ³nico del encargado del mantenimiento del sistema, indica si las pÃ¡ginas de estado y del Colector estÃ¡n activadas o no, si se llevan o no los registros de las actividades de los usuarios y si se utilizan o no âÂ <i>cookies</i>Â â para identificar a los usuarios.</Text>
+</Content>
+</Section>
+<Section id="logs">
+<Title>
+<Text id="592">Registros</Text>
+</Title>
+<Content>
+<Text id="593">Se pueden examinar tres tipos de registros: registros de uso, registros de errores y registros de inicializaciÃ³n. Los dos Ãºltimos sÃ³lo interesan de hecho a las personas encargadas del mantenimiento del programa.</Text>
+<Text id="594">Todas las actividades del usuario, es decir, cada pÃ¡gina que el usuario visita, pueden quedar registradas en el programa Greenstone, aunque en los registros no se almacena informaciÃ³n nominativa. La tenedurÃ­a de registros (<i>logging</i>), desactivada por defecto, se activa incluyendo las lÃ­neas siguientes:</Text>
+<CodeLine>logcgiargsÂ Â Â Â  true</CodeLine>
+<CodeLine>usecookiesÂ Â Â Â  true</CodeLine>
+<Text id="595">en el archivo principal de configuraciÃ³n del sistema. Ambas opciones tienen por defecto el valorÂ <i>false</i>, por lo que es necesario asignarles el valorÂ <i>true</i>Â para activar la tenedurÃ­a de registros. La lÃ­neaÂ <i>logcgiargs</i>Â es la que activa o desactiva esta funciÃ³n. ActivandoÂ <i>usecookies</i>Â se asigna a cada usuario un cÃ³digo de identificaciÃ³n Ãºnico que permite seguir en el archivo de registro las interacciones de cada usuario.</Text>
+<Text id="596">Cada lÃ­nea del registro de usuarios corresponde a una pÃ¡gina visitada, Â¡aun las pÃ¡ginas generadas para la consulta de los archivos de registro! Comprende: a) la direcciÃ³n IP de la computadora del usuario, b) la marca de fecha y hora entre corchetes, c) los argumentos CGI entre parÃ©ntesis y d) el nombre del navegador del usuario (Netscape Navigator se denomina âMozillaâ). A continuaciÃ³n se presenta una lÃ­nea de muestra, dividida y anotada para facilitar su lectura:</Text>
+<CodeLine>Â Â Â  /fast-cgi-bin/niupepalibrary</CodeLine>
+<CodeLine>a)Â Â  its-wwwl.massey.ac.nz</CodeLine>
+<CodeLine>b)Â Â  [Thu Dec 07 23:47:00 NZDT 2000]</CodeLine>
+<CodeLine>c)Â Â  (a=p, b=0, bcp=, beu=, c=niupepa, cc=, ccp=0, ccs=0, cl=, cm=, cq2=, d=, e=, er=, f=0, fc=1, gc=0, gg=text, gt=0, h=, h2=, hl=1, hp=, il=1, j=, j2=, k=1, ky=, l=en, m=50, n=, n2=, o=20, p=home, pw=, q=, q2=, r=1, s=0, sp=frameset, t=1, ua=, uan=, ug=, uma=listusers, umc=, umnpwl=, umnpw2=, impw=, umug=, umun=, umus=, un=, us=invalid, v=0, w=w, x=0, z=130.123.128.4-950647871)</CodeLine>
+<CodeLine>d)Â Â  âMozilla/4.08 [en]Â  (Win95; I; Nav)â</CodeLine>
+<Text id="597">El Ãºltimo argumento CGI, âzâ, es un cÃ³digo de identificaciÃ³n o âÂ <i>cookie</i>Â â generado por el navegador del usuario; comprende el nÃºmero IP del usuario, seguido por la marca de fecha y hora de su primera visita a la biblioteca digital.</Text>
+<Text id="598">El archivo de registroÂ <i>usage.txt</i>Â se sitÃºa en el directorioÂ <i>etc.</i>, en la estructura de archivos de Greenstone (vÃ©ase laÂ <i>GuÃ­a del Programador de la Biblioteca Digital Greenstone</i>). Cuando se activa la funciÃ³n de tenedurÃ­a de registros, se consigna cada acciÃ³n de cada usuario. Sin embargo, el enlaceÂ <i>Registro de uso</i>Â que aparece en la Figura 17 sÃ³lo muestra las Ãºltimas 100 anotaciones en el archivo de registro.</Text>
+</Content>
+</Section>
+<Section id="user_management">
+<Title>
+<Text id="599">GestiÃ³n de los usuarios</Text>
+</Title>
+<Content>
+<Text id="600">Greenstone incorpora un sistema de autenticaciÃ³n que puede utilizarse para controlar el acceso a determinadas funciones. Por el momento el sistema se utiliza Ãºnicamente para restringir el nÃºmero de personas que estÃ¡n autorizadas a utilizar el Colector y algunas funciones de administraciÃ³n. Si, en el caso de una colecciÃ³n en particular, fuera necesario autentificar a los usuarios antes de hacerles llegar la informaciÃ³n, ello tambiÃ©n es posible. Se podrÃ­a, por ejemplo, proteger determinados documentos a fin de que sÃ³lo los usuarios registrados puedan tener acceso a ellos tecleando una contraseÃ±a. Ahora bien, ninguna de las colecciones utiliza actualmente esta funciÃ³n. La autenticaciÃ³n se efectÃºa pidiendo un nombre de usuario y una contraseÃ±a, tal como se ilustra en la Figura 16a.</Text>
+<Text id="601">A partir de la pÃ¡gina de administraciÃ³n, se puede hacer una lista de los usuarios, aÃ±adir nuevos usuarios y suprimir antiguos. Obviamente, la capacidad para hacerlo tambiÃ©n estÃ¡ protegida: sÃ³lo los usuarios que disponen de privilegios administrativos pueden aÃ±adir nuevos usuarios. Es tambiÃ©n posible que cada usuario pertenezca a âgruposâ diferentes. Por el momento, los Ãºnicos existentes son âÂ <i>administrator</i>Â â (administrador) y âÂ <i>colbuilder</i>Â â (creador de colecciÃ³n). Los miembros del primer grupo pueden aÃ±adir y suprimir usuarios y modificar sus grupos. Los miembros del segundo pueden acceder a las funciones antes descritas para crear nuevas colecciones y modificar (o suprimir) colecciones existentes.</Text>
+<Text id="602">Cuando se instala Greenstone, hay un solo usuario llamadoÂ <i>admin</i>Â que pertenece a ambos grupos. Su contraseÃ±a se establece durante el proceso de instalaciÃ³n. Este usuario puede crear nuevos nombres y contraseÃ±as Ãºnicamente para los usuarios pertenecientes al grupoÂ <i>colbuilder</i>, modo recomendado de brindar a otros usuarios la posibilidad de crear colecciones. La informaciÃ³n de usuario se registra en dos bases de datos situadas en la estructura de archivos de Greenstone (vÃ©ase laÂ <i>GuÃ­a del Programador de la Biblioteca Digital Greenstone</i>).</Text>
+</Content>
+</Section>
+<Section id="technical_information">
+<Title>
+<Text id="603">Informaciones tÃ©cnicas</Text>
+</Title>
+<Content>
+<Text id="604">Los enlaces situados debajo del encabezadoÂ <i>Informaciones tÃ©cnicas</i>Â proporcionan informaciÃ³n suplementaria sobre la instalaciÃ³n. El enlaceÂ <i>general</i>Â da acceso a la informaciÃ³n tÃ©cnica, incluidos los directorios de almacenamiento. El elemento de menÃºÂ <i>protocolos</i>Â proporciona, para cada tipo posible de protocolo, informaciones sobre cada una de las colecciones accesibles por ese protocolo.</Text>
+<Text id="605">Por Ãºltimo, el cÃ³digo de la interfaz de usuario (llamado el ârecepcionistaâ) utilizaÂ <i>acciones</i>Â para comunicar al sistema los deseos del usuario. Estas acciones corresponden al argumento CGI etiquetado âÂ <i>a</i>Â â. Por ejemplo, siÂ <i>a=status</i>, el recepcionista activa la acciÃ³nÂ <i>status</i>Â (que muestra la pÃ¡gina de estados). Un elemento de menÃº da acceso a la lista de todas las acciones propuestas por el sistema y otro lleva a los argumentos aceptados por esas acciones.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="appendix_a_software_features">
+<Title>
+<Text id="606">ApÃ©ndice A: CaracterÃ­sticas del programa</Text>
+</Title>
+<Content>
+<Table class="hidden" id="table_appendixa">
+<Title/>
+<TableContent>
+<tr>
+<th>
+<Text id="607"><i>Accesible mediante un navegador Web</i></Text>
+</th>
+<th>
+<Text id="608">Se accede a las colecciones mediante un navegador Web estÃ¡ndar (Netscape o Internet Explorer), con una combinaciÃ³n de funciones de consulta sencillas y una poderosa capacidad de bÃºsqueda.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="609"><i>BÃºsqueda en texto completo y por campos</i></Text>
+</th>
+<th>
+<Text id="610">El usuario puede efectuar bÃºsquedas en el texto completo de los documentos, o elegir entre los diversos Ã­ndices constituidos a partir de diferentes porciones de los documentos. Por ejemplo, algunas colecciones tienen un Ã­ndice de los documentos completos, un Ã­ndice de las secciones, un Ã­ndice de los tÃ­tulos y un Ã­ndice de los autores, y en cada uno de ellos se pueden efectuar bÃºsquedas de determinadas palabras o frases. Los resultados pueden ordenarse por pertinencia o clasificarse mediante un metadato.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="611"><i>Flexibilidad de la consulta</i></Text>
+</th>
+<th>
+<Text id="612">El usuario puede consultar listas de autores, listas de tÃ­tulos, listas de fechas, estructuras de clasificaciÃ³n, etc. Las diferentes colecciones pueden ofrecer distintas funciones de consulta, e incluso dentro de una colecciÃ³n se dispondrÃ¡ de una amplia variedad de interfaces de consulta. Las interfaces de consulta y de bÃºsqueda se elaboran durante el proceso de creaciÃ³n, con arreglo a la informaciÃ³n de configuraciÃ³n de la colecciÃ³n.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="613"><i>CreaciÃ³n automÃ¡tica de estructuras de acceso</i></Text>
+</th>
+<th>
+<Text id="614">El programa Greenstone crea colecciones de informaciÃ³n cuyo mantenimiento es muy fÃ¡cil. Todas las estructuras de bÃºsqueda y consulta se elaboran directamente a partir de los propios documentos. No se inserta manualmente ningÃºn enlace, sino que se mantienen los enlaces existentes en los originales. Gracias a esta caracterÃ­stica, los nuevos documentos en el mismo formato pueden incorporarse automÃ¡ticamente a la colecciÃ³n. En algunas colecciones, esto se hace mediante procesos que se ponen en marcha periÃ³dicamente, localizan el material nuevo y reconstituyen los Ã­ndices, todo ello sin intervenciÃ³n manual.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="615"><i>UtilizaciÃ³n de los metadatos disponibles</i></Text>
+</th>
+<th>
+<Text id="616">Los metadatos, es decir, las informaciones descriptivas tales como el autor, el tÃ­tulo, la fecha, las palabras clave, etc., pueden asociarse a cada documento o a cada secciÃ³n de documento. Los metadatos constituyen la materia prima de los Ã­ndices de consulta. Se los debe suministrar explÃ­citamente o deben poder extraerse automÃ¡ticamente de los documentos de origen. Para la mayorÃ­a de los documentos electrÃ³nicos se utiliza el sistema de metadatos Dublin Core, aunque se contempla la posibilidad de utilizar otros sistemas.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="617"><i>Los plugins amplÃ­an las capacidades del sistema</i></Text>
+</th>
+<th>
+<Text id="618">Para poder utilizar varios tipos de documentos de origen, el programa estÃ¡ organizado de manera que puedan escribirse plugins para nuevos tipos de documentos. En la actualidad existen plugins para textos sin formato, HTML, Word, PDF, PostScript, correo electrÃ³nico, algunos formatos patentados, asÃ­ como para la exploraciÃ³n recursivaÂ  de estructuras de directorio y archivos comprimidos que contienen tales documentos. Una colecciÃ³n puede tener documentos de origen de diferentes formas. Para elaborar los Ã­ndices de consulta a partir de los metadatos se utiliza un sistema anÃ¡logo de âclasificadoresâ que crean Ã­ndices de consulta de diversos tipos, basados en los metadatos.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="619"><i>Programa diseÃ±ado para colecciones de varios gigabytes</i></Text>
+</th>
+<th>
+<Text id="620">Las colecciones pueden contener millones de documentos, por lo cual el sistema Greenstone puede manejar colecciones de hasta varios gigabytes.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="621"><i>Los documentos pueden estar en cualquier idioma</i></Text>
+</th>
+<th>
+<Text id="622">En todo el programa se utiliza Unicode, sistema que permite procesar cualquier idioma de forma sistemÃ¡tica. Hasta la fecha, se han creado colecciones que contienen documentos en francÃ©s, espaÃ±ol, maorÃ­, chino, Ã¡rabe e inglÃ©s. Se utiliza una conversiÃ³n âal vueloâ (on-the-fly) para convertir el formato Unicode en un alfabeto reconocido por el navegador Web del usuario.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="623"><i>La interfaz de usuario estÃ¡ disponible en numerosos idiomas</i></Text>
+</th>
+<th>
+<Text id="624">La interfaz puede presentarse en numerosos idiomas. Actualmente esa interfaz estÃ¡ disponible en alemÃ¡n, Ã¡rabe, chino, espaÃ±ol, inglÃ©s, maorÃ­, neerlandÃ©s y portuguÃ©s. Pueden aÃ±adirse fÃ¡cilmente nuevos idiomas.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="625"><i>Las colecciones pueden contener texto, imagen, sonido y vÃ­deo</i></Text>
+</th>
+<th>
+<Text id="626">Las colecciones Greenstone pueden contener texto, imÃ¡genes, sonidos y videoclips. La mayor parte del material no textual estÃ¡ enlazado a los documentos textuales o va acompaÃ±ado de descripciones textuales (por ejemplo, las leyendas de las figuras) para permitir la bÃºsqueda y consulta en texto completo. Sin embargo, la arquitectura del programa permite la utilizaciÃ³n de plugins y clasificadores aun para datos no textuales.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="627"><i>UtilizaciÃ³n de tÃ©cnicas de compresiÃ³n avanzadas</i></Text>
+</th>
+<th>
+<Text id="628">Se utilizan tÃ©cnicas de compresiÃ³n para reducir el tamaÃ±o de los Ã­ndices y el texto. La reducciÃ³n del tamaÃ±o de los Ã­ndices mediante la compresiÃ³n tiene la ventaja adicional de aumentar la velocidad de recuperaciÃ³n de la informaciÃ³n textual.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="629"><i>Suministro de una funciÃ³n de administraciÃ³n</i></Text>
+</th>
+<th>
+<Text id="630">Una funciÃ³n âde administraciÃ³nâ permite que usuarios especificados autoricen a nuevos usuarios a crear colecciones, posibilita la protecciÃ³n de los documentos de talÂ  modo que sÃ³lo los usuarios registrados puedan tener acceso a ellos tecleando una contraseÃ±a, permite examinar la composiciÃ³n de todas las colecciones, etc. Gracias a los registros de actividades de los usuarios, se puede tener constancia de todas las consultas hechas a todas las colecciones de Greenstone.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="631"><i>PresentaciÃ³n dinÃ¡mica de las nuevas colecciones</i></Text>
+</th>
+<th>
+<Text id="632">Se pueden actualizar las colecciones y proponer nuevas colecciones en todo momento, sin apagar el sistema; el proceso encargado de la interfaz de usuario tomarÃ¡ nota (mediante sondeos periÃ³dicos) de las nuevas colecciones que aparezcan y las aÃ±adirÃ¡ a la lista presentada al usuario.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="633"><i>Las colecciones pueden publicarse en Internet o en CD-ROM</i></Text>
+</th>
+<th>
+<Text id="634">Se puede utilizar el programa para difundir colecciones por Internet. Las colecciones de Greenstone se pueden tambiÃ©n distribuir, en exactamente la misma forma, en CD-ROM. La interfaz de usuario funciona mediante un navegador Web estÃ¡ndar (Netscape viene en cada disco) y la interacciÃ³n es la misma que por la Web, con la salvedad de que los tiempos de respuesta son mÃ¡s previsibles. Los CD-ROM funcionan con todas las versiones del sistema operativo Windows.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="635"><i>Las colecciones pueden distribuirse entre diferentes computadoras</i></Text>
+</th>
+<th>
+<Text id="636">Una estructura de proceso flexible permite la distribuciÃ³n de diferentes colecciones por diferentes computadoras, aunque todas se presentan al usuario de la misma manera, en la misma pÃ¡gina Web y como parte de la misma biblioteca digital.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="637"><i>Funcionamiento con Windows y Unix</i></Text>
+</th>
+<th>
+<Text id="638">Greenstone funciona con los sistemas Windows (3.1/3.11, 95/98/Me, NT/2000) y Unix (Linux y SunOS). Cualquiera de estos sistemas puede utilizarse como servidor Web. Las colecciones no pueden crearse con versiones antiguas de Windows (3.1/3.11), pero pueden transferirse a esos sistemas colecciones previamente creadas.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="639"><i>Ventajas de Greenstone</i></Text>
+</th>
+<th>
+<Text id="640">La Biblioteca Digital Greenstone es un programa de cÃ³digo fuente abierto, disponible en el sitio Web de la Biblioteca Digital de Nueva Zelanda (nzdl.org), segÃºn las condiciones estipuladas en la Licencia PÃºblica General de GNU. El programa incluye todo lo que se ha mencionado mÃ¡s arriba: la funciÃ³n de servidor Web, la creaciÃ³n de discos CD-ROM, la creaciÃ³n de colecciones, posibilidades plurilingÃŒes, plugins y clasificadores para diversos tipos de documentos de origen. Comprende una funciÃ³n de autoinstalaciÃ³n que permite instalar fÃ¡cilmente el programa en Windows y Unix. Con arreglo al principio de los programas de cÃ³digo fuente abierto, se alienta a los usuarios a aportar modificaciones y mejoras.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Chapter>
+<Chapter id="appendix_b_glossary_of_terms">
+<Title>
+<Text id="641">APÃNDICE B: GLOSARIO DE TÃRMINOS</Text>
+</Title>
+<Content>
+<Table id="appendixb" class="hidden">
+<Title/>
+<TableContent>
+<tr>
+<th>
+<Text id="642"><b>TÃ©rmino</b></Text>
+</th>
+<th>
+<Text id="643"><b>Significado</b></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="644"><i>autoconf</i></Text>
+</th>
+<th>
+<Text id="645">Programa Unix utilizado para configurar el paquete de instalaciÃ³n del programa Greenstone a fin que se adapte a su sistema</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="646"><i>Autorun</i></Text>
+</th>
+<th>
+<Text id="647">FunciÃ³n de Windows que arranca automÃ¡ticamente un programa cada vez que se inserta un CD-ROM</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="648">Consulta booleana</Text>
+</th>
+<th>
+<Text id="649">Consulta en un sistema de recuperaciÃ³n de informaciÃ³n que puede contener Y, O y NO booleanos</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="650">Consulta</Text>
+</th>
+<th>
+<Text id="651">Acceso a una colecciÃ³n recorriendo una lista organizada de valores de metadatos asociados a los documentos (tales como el autor, el tÃ­tulo, la fecha, palabras claves)</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="652"><i>Buildcol.pl</i></Text>
+</th>
+<th>
+<Text id="653">Programa de Greenstone utilizado para crear colecciones</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="654">CreaciÃ³n</Text>
+</th>
+<th>
+<Text id="655">Proceso de constituciÃ³n de las estructuras de indexaciÃ³n y consulta que se utilizan para tener acceso a una colecciÃ³n</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="656">C++</Text>
+</th>
+<th>
+<Text id="657">Lenguaje de programaciÃ³n en que estÃ¡ escrita la mayor parte del programa Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="658">Ignorar las diferencias entre mayÃºsculas y minÃºsculas</Text>
+</th>
+<th>
+<Text id="659">FunciÃ³n cuyo objeto es que en las operaciones de bÃºsqueda no se distinga entre las palabras en mayÃºsculas y minÃºsculas</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="660">CGI</Text>
+</th>
+<th>
+<Text id="661"><i>Common Gateway Interface</i>Â (interfaz comÃºn de pasarela). Sistema que permite que los usuarios puedan activar programas en la computadora central (o servidor), haciendo clic en pÃ¡ginas Web</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="662">GuiÃ³n CGI</Text>
+</th>
+<th>
+<Text id="663">CÃ³digo asociado a un botÃ³n, un menÃº, o un enlace en una pÃ¡gina Web, que especifica lo que ha de hacer la computadora central cuando se hace clic en ese objeto</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="664"><i>cgi-bin</i></Text>
+</th>
+<th>
+<Text id="665">Directorio en que estÃ¡n almacenados los guiones cgi</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="666">Clasificador</Text>
+</th>
+<th>
+<Text id="667">MÃ³dulo de cÃ³digo de Greenstone que examina los metadatos del documento para elaborar un Ã­ndice de consulta</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="668">ColecciÃ³n</Text>
+</th>
+<th>
+<Text id="669">Conjunto de documentos agrupados en una interfaz de bÃºsqueda y consulta homogÃ©nea</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="670">Archivo de configuraciÃ³n de colecciÃ³n</Text>
+</th>
+<th>
+<Text id="671">Archivo que especifica de quÃ© manera ha de importarse y crearse la colecciÃ³n, quÃ© Ã­ndices e interfaces de idiomas han de suministrarse, etc.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="672">Servidor de colecciÃ³n</Text>
+</th>
+<th>
+<Text id="673">Programa que da acceso a una colecciÃ³n en curso de utilizaciÃ³n</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="674">Archivo de configuraciÃ³n</Text>
+</th>
+<th>
+<Text id="675">VÃ©ase âArchivo de configuraciÃ³n de colecciÃ³nâ, âArchivo de configuraciÃ³n principalâ, âArchivo de configuraciÃ³n de sitioâ</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="676">CVS</Text>
+</th>
+<th>
+<Text id="677">Concurrent Versioning System (sistema de versiones concurrentes). Sistema que permite mantener el cÃ³digo fuente utilizado en el programa Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="678"><i>db2txt</i></Text>
+</th>
+<th>
+<Text id="679">Herramienta Greenstone que permite visualizar en forma textual una base de datos GDBM (vÃ©ase âGDBMâ)</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="680">ColecciÃ³n de demostraciÃ³n</Text>
+</th>
+<th>
+<Text id="681">Un subconjunto de la biblioteca para el desarrollo, distribuido con el programa Greenstone y utilizado para ilustrar esta guÃ­a didÃ¡ctica</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="682">Biblioteca digital</Text>
+</th>
+<th>
+<Text id="683">ColecciÃ³n de objetos digitales (texto, sonido, vÃ­deo), junto con mÃ©todos de acceso y recuperaciÃ³n de informaciÃ³n, asÃ­ como de selecciÃ³n, organizaciÃ³n y mantenimiento</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="684">DLS</Text>
+</th>
+<th>
+<Text id="685">Subconjunto de biblioteca para el desarrollo. Una colecciÃ³n Greenstone de informaciÃ³n humanitaria para los paÃ­ses en desarrollo</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="686">Documento</Text>
+</th>
+<th>
+<Text id="687">Unidad bÃ¡sica a partir de la cual se crean las colecciones de biblioteca digital; puede incluir texto, grÃ¡ficos, sonido, vÃ­deo, etc.</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="688">Dublin Core</Text>
+</th>
+<th>
+<Text id="689">Forma estÃ¡ndar de describir los metadatos</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="690">Fast-CGI</Text>
+</th>
+<th>
+<Text id="691">FunciÃ³n que permite que los guiones CGI permanezcan continuamente en funcionamiento, a fin de que no sea necesario reiniciarlos desde cero cada vez que se los activa</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="692">Programa de filtro</Text>
+</th>
+<th>
+<Text id="693">Parte del servidor de colecciones Greenstone que ejecuta las operaciones de bÃºsqueda y consulta</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="694">Cadena de formato</Text>
+</th>
+<th>
+<Text id="695">Cadena que especifica cÃ³mo visualizar en Greenstone los documentos y otras listas</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="696">CodificaciÃ³n GB</Text>
+</th>
+<th>
+<Text id="697">Forma estÃ¡ndar de codificar el idioma chino</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="698">GDBM</Text>
+</th>
+<th>
+<Text id="699"><i>GNU DataBase Manager</i>Â (administrador de base de datos de GNU). Programa utilizado por Greenstone para almacenar los metadatos de cada documento</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="700">GIMP</Text>
+</th>
+<th>
+<Text id="701"><i>GNU Image-Manipulation Program</i>Â (programa de manipulaciÃ³n de imÃ¡genes de GNU). Programa utilizado (en Unix) para crear iconos en Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="702">GML</Text>
+</th>
+<th>
+<Text id="703"><i>Greenstone Markup Language</i>Â (lenguaje de marcado Greenstone). Formato compatible con XML utilizado para almacenar documentos internamente</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="704">Licencia PÃºblica General GNU </Text>
+</th>
+<th>
+<Text id="705">Licencia de programas informÃ¡ticos que permite a los usuarios copiar y distribuir gratuitamente programas informÃ¡ticos y modificarlos, siempre que todas las modificaciones publicadas se pongan a disposiciÃ³n del pÃºblico en forma de cÃ³digo fuente</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="706">Greenstone</Text>
+</th>
+<th>
+<Text id="707">Nombre de este programa de biblioteca digital</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="708">GSDL </Text>
+</th>
+<th>
+<Text id="709">Abreviatura deÂ <i>Greenstone Digital Library</i>Â (Biblioteca Digital Greenstone)</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="710"><i>%GSDLHOME%</i></Text>
+</th>
+<th>
+<Text id="711">Variable del sistema operativo Windows que representa el directorio principal en que se almacenan todos los programas y colecciones de Greenstone (<i>$GSDLHOME</i>Â en los sistema Unix)</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="712"><i>%GSDLOS%</i></Text>
+</th>
+<th>
+<Text id="713">Variable del sistema operativo Windows que representa el sistema operativo en curso de utilizaciÃ³n (<i>$GSDLOS</i>Â en los sistemas Unix)</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="714"><i>hashfile</i></Text>
+</th>
+<th>
+<Text id="715">Programa Greenstone utilizado en el momento de la importaciÃ³n o creaciÃ³n de colecciones para generar el identificador de objeto (OID) de cada documento</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="716">HTML</Text>
+</th>
+<th>
+<Text id="717"><i>HyperText Markup Language</i>Â (lenguaje de marcado de hipertexto). Lenguaje en que estÃ¡n escritos los documentos Web</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="718"><i>Â import.pl</i></Text>
+</th>
+<th>
+<Text id="719">Programa Greenstone utilizado para importar documentos</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="720">ImportaciÃ³n</Text>
+</th>
+<th>
+<Text id="721">Proceso de incorporaciÃ³n de colecciones de documentos al sistema Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="722">Ãndice</Text>
+</th>
+<th>
+<Text id="723">Estructura de informaciÃ³n utilizada para la bÃºsqueda o consulta en una colecciÃ³n</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="724">InstallShield</Text>
+</th>
+<th>
+<Text id="725">Programa Windows, utilizado para los CD-ROM Greenstone, que permite instalar un sistema a partir de un CD-ROM</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="726">Archivo de configuraciÃ³n principal</Text>
+</th>
+<th>
+<Text id="727">Archivo que contiene las especificaciones comunes a todas las colecciones que se ofrecen en este sitio</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="728">Metadatos</Text>
+</th>
+<th>
+<Text id="729">Datos descriptivos, tales como el autor, el tÃ­tulo, la fecha, palabras clave, etc., asociados a un documento (o colecciÃ³n de documentos)</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="730">MG</Text>
+</th>
+<th>
+<Text id="731"><i>Managing Gigabytes</i>Â (gestiÃ³n de gigabytes). Programa utilizado en el sistema Greenstone para la indexaciÃ³n en texto completo, que incorpora tÃ©cnicas de compresiÃ³n (vÃ©ase al respecto Witten, I.H; Mofft, A. y Bell, TÂ <i>Managing Gigabytes: compressing and indexing documents and images</i>Â (GestiÃ³n de gigabytes: compresiÃ³n e indexaciÃ³n de documentos e imÃ¡genes), Morgan Kaufmann, segunda ediciÃ³n, 1999)</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="732"><i>mgbuild</i></Text>
+</th>
+<th>
+<Text id="733">Programa MG para la constituciÃ³n de un Ã­ndice comprimido de texto completo</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="734"><i>mgquery</i></Text>
+</th>
+<th>
+<Text id="735">Programa MG para efectuar bÃºsquedas en un Ã­ndice comprimido de texto completo</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="736"><i>mkcol.pl</i></Text>
+</th>
+<th>
+<Text id="737">Programa Greenstone que crea e inicializa la estructura de directorio de una nueva colecciÃ³n</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="738">Proyecto de BibliotecaÂ  Digital de Nueva Zelanda</Text>
+</th>
+<th>
+<Text id="739">Proyecto de investigaciÃ³n del Departamento de InformÃ¡tica de la Universidad de Waikato, Nueva Zelanda, que creÃ³ el programa Greenstone (<i>nzdl.org)</i></Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="740">OID</Text>
+</th>
+<th>
+<Text id="741"><i>Object Identifier</i>Â (identificador de objeto). CÃ³digo de identificaciÃ³n Ãºnico asociado a un documento</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="742">Perl</Text>
+</th>
+<th>
+<Text id="743">Lenguaje de programaciÃ³n utilizado para una gran parte de las operaciones de tratamiento de texto durante el proceso de creaciÃ³n de una colecciÃ³n</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="744">Ping</Text>
+</th>
+<th>
+<Text id="745">Mensaje enviado a un sistema para determinar si estÃ¡ en funcionamiento o no</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="746">plugin</Text>
+</th>
+<th>
+<Text id="747">MÃ³dulo de cÃ³digo que administra los documentos de diferentes formatos, utilizado durante los procesos de importaciÃ³n y creaciÃ³n de colecciones</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="748">Protocolo</Text>
+</th>
+<th>
+<Text id="749">Conjunto de convenciones mediante las cuales el ârecepcionistaâ de Greenstone se comunica con un servidor de colecciÃ³n</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="750">Consulta ordenada</Text>
+</th>
+<th>
+<Text id="751">Consulta en lenguaje natural de un sistema de recuperaciÃ³n de informaciÃ³n, en virtud del cual los documentos que corresponden a la consulta solicitada se ordenan por orden de pertinencia</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="752">Recepcionista</Text>
+</th>
+<th>
+<Text id="753">Programa que organiza la interfaz de usuario de Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="754">RTF</Text>
+</th>
+<th>
+<Text id="755"><i>Rich Text Format</i>Â (formato de texto enriquecido). Formato estÃ¡ndar para el intercambio de documentos textuales</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="756">BÃºsqueda</Text>
+</th>
+<th>
+<Text id="757">Acceso a una colecciÃ³n a travÃ©s de una bÃºsqueda en texto completo de su contenido (o de una parte de su contenido, por ejemplo, los tÃ­tulos de secciones)</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="758">Servidor</Text>
+</th>
+<th>
+<Text id="759">VÃ©ase âServidor de colecciÃ³nâ y âServidor Webâ</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="760"><i>Â setup.bat, setup.sh, setup.csh</i></Text>
+</th>
+<th>
+<Text id="761">GuiÃ³n utilizado para instalar el entorno necesario para el reconocimiento del programa Greenstone</Text>
+</th>
+</tr> 
+<tr>
+<th>
+<Text id="762">Archivo de configuraciÃ³n de sitio</Text>
+</th>
+<th>
+<Text id="763">Archivo que contiene las especificaciones utilizadas para configurar el programa Greenstone para el sitio en que estÃ¡ instalado</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="764">Â Truncamiento</Text>
+</th>
+<th>
+<Text id="765">Corte del final de un tÃ©rmino de consulta para hacerlo mÃ¡s genÃ©rico</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="766">Â STL</Text>
+</th>
+<th>
+<Text id="767"><i>Standard Template Library</i>Â (biblioteca estÃ¡ndar de plantillas). Biblioteca de cÃ³digos C++ muy difundida, elaborada por Silicon Graphics</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="768"><i>Â txt2db</i></Text>
+</th>
+<th>
+<Text id="769">Programa Greenstone utilizado en el momento de la creaciÃ³n para constituir la base de datos GDBM</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="770">Â Unicode</Text>
+</th>
+<th>
+<Text id="771">Sistema estÃ¡ndar de representaciÃ³n de los conjuntos de caracteres utilizados en los idiomas del mundo</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="772">UNU</Text>
+</th>
+<th>
+<Text id="773">Universidad de las Naciones Unidas; esta sigla se utiliza tambiÃ©n para referirse a una colecciÃ³n Greenstone creada para esa organizaciÃ³n</Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="774">Servidor Web</Text>
+</th>
+<th>
+<Text id="775">Programa estÃ¡ndar que utilizan las computadoras para difundir informaciÃ³n por Internet </Text>
+</th>
+</tr>
+<tr>
+<th>
+<Text id="776">XML</Text>
+</th>
+<th>
+<Text id="777">Formato estÃ¡ndar para los documentos y datos estructurados en la Web (el lenguaje de marcado Greenstone es un formato compatible con XML)</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Chapter>
+<FootnoteList>
+<Footnote id="1">
+<Text id="778">Esta opciÃ³n se inhabilita si ya existe un elemento con el mismo nombre.</Text>
+</Footnote>
+</FootnoteList>
+</Manual>
Index: /tags/start/gsdl-documentation/manuals/xml-source/fr/Develop_fr.xml
===================================================================
--- /tags/start/gsdl-documentation/manuals/xml-source/fr/Develop_fr.xml	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/xml-source/fr/Develop_fr.xml	(revision 13666)
@@ -0,0 +1,5218 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Manual>
+<Heading>
+<Text id="1"/>
+</Heading>
+<Title>
+<Text id="2">Guide du dÃ©veloppeur de la bibliothÃšque numÃ©rique Greenstone</Text>
+</Title>
+<Author>
+<Text id="3">David Bainbridge, Dana McKay et Ian H. Witten</Text>
+</Author>
+<Affiliation>
+<Text id="4">DÃ©partement d'informatique,<br/>UniversitÃ© de Waikato, Nouvelle-ZÃ©lande</Text>
+</Affiliation>
+<Text id="5">Greenstone est une suite logicielle destinÃ©e Ã  la construction et Ã  la distribution de collections de bibliothÃšques numÃ©riques. Cette suite fournit une nouvelle maniÃšre d'organiser l'information et de la publier sur l'Internet ou sur un cÃ©dÃ©rom. Greenstone est produit par le projet de bibliothÃšque numÃ©rique de Nouvelle-ZÃ©lande (dÃ©pendant de l'universitÃ© de Waikato), et distribuÃ© en coopÃ©ration avec l'UNESCO et le projet de bibliothÃšques pour l'humanitÃ©. C'est un logiciel Open Source, qu'on peut obtenir Ã  l'URLhttp://greenstone.org, et qui est diffusÃ© selon les termes de la licence publique gÃ©nÃ©rale de GNU.</Text>
+<Comment>
+<Text id="6">Nous souhaitons nous assurer que ce logiciel fonctionne bien pour vous.<br/>Faites-nous part, en anglais, de tout problÃšme Ã  l'adresse Ã©lectronique<br/>.</Text>
+</Comment>
+<Version>
+<Text id="7">Greenstone gsdl-2.50</Text>
+</Version>
+<Date>
+<Text id="8">Mars 2004</Text>
+</Date>
+<Section id="about_this_manual">
+<Title>
+<Text id="9">Ã propos de ce manuel</Text>
+</Title>
+<Content>
+<Text id="10">Ce manuel explique le fonctionnement de Greenstone. Il vise ceux qui souhaitent personnaliser des collections et dÃ©velopper ou maintenir le logiciel.</Text>
+<Text id="11">La sectionÂ <CrossRef target="Chapter" ref="understanding_the_collection-building_process"/> expose le processus de construction de collection vu de l'intÃ©rieur, comprenant la structure de rÃ©pertoire, le format de document interne, et le fichier de configuration qui gouverne la structure de chaque collection. La section <CrossRef target="Chapter" ref="getting_the_most_out_of_your_documents"/> dÃ©crit les parties de Greenstone qui traitent les documents source (et leurs mÃ©ta-donnÃ©es) et dictent la maniÃšre dont on accÃšde Ã  l'information depuis l'interface utilisateur. Elle dÃ©crit Ã©galement des composants logiciels Â«externesÂ», distribuÃ©s avec Greenstone. La sectionÂ <CrossRef target="Chapter" ref="the_greenstone_runtime_system"/> explique la structure du systÃšme d'exÃ©cution de Greenstone, et donne aussi des dÃ©tails du logiciel pour aider Ã  comprendre son fonctionnement et comment le modifier pour correspondre Ã  des besoins particuliers. La sectionÂ <CrossRef target="Chapter" ref="configuring_your_greenstone_site"/> dÃ©crit les fichiers de configuration de Greenstone, et une annexe propose une introduction Ã  la bibliothÃšque standard de patrons (templates) pour C++.</Text>
+<Text id="12">Lors de votre travail avec le logiciel Greenstone, vous trouverez peut-Ãªtre des rÃ©fÃ©rences Ã  des fonctionnalitÃ©s qui ne sont pas dÃ©crites dans le prÃ©sent manuel, car Greenstone est en perpÃ©tuel dÃ©veloppement. Pour en savoir plus sur les travaux en cours, rejoignez la liste de diffusion de Greenstone (vous trouverez les instructions pour cela sur le site webgreenstone.org).</Text>
+</Content>
+</Section>
+<Section id="companion_documents">
+<Title>
+<Text id="13">Documents d'accompagnement</Text>
+</Title>
+<Content>
+<Text id="14">L'ensemble des documents de Greenstone comprend cinq volumes:</Text>
+<BulletList>
+<Bullet>
+<Text id="15">Guide d'installation de la bibliothÃšque numÃ©rique Greenstone </Text>
+</Bullet>
+<Bullet>
+<Text id="16">Guide de l'utilisateur de la bibliothÃšque numÃ©rique Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="17">Guide du dÃ©veloppeur de la bibliothÃšque numÃ©rique Greenstone (<i>ce document-ci</i>)</Text>
+</Bullet>
+<Bullet>
+<Text id="18">BibliothÃšque numÃ©rique Greenstone: du papier Ã  la collection</Text>
+</Bullet>
+<Bullet>
+<Text id="19">BibliothÃšque numÃ©rique Greenstone: Utilisation de "L'organizer"</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Section>
+<Section id="acknowledgements">
+<Title>
+<Text id="20">Remerciements</Text>
+</Title>
+<Content>
+<Text id="21">Le logiciel Greenstone a vu le jour grÃ¢ce Ã  un effort de collaboration entre de nombreuses personnes. Rodger McNab et Stefan Boddie en sont les principaux architectes et dÃ©veloppeurs. Des contributions ont Ã©tÃ© faites par David Bainbridge, George Buchanan, Hong Chen, Michael Dewsnip, Katherine Don, Elke Duncker, Carl Gutwin, Geoff Holmes, Dana McKay, John McPherson, Craig Nevill-Manning, Dynal Patel, Gordon Paynter, Bernhard Pfahringer, Todd Reed, Bill Rogers, John Thompson, et Stuart Yeates. D'autres membres du Projet de bibliothÃšque numÃ©rique de Nouvelle-ZÃ©lande ont Ã©galement donnÃ© des conseils et inspirÃ© les concepteurs du systÃšme: Mark Apperley, Sally Jo Cunningham, Steve Jones, Te Taka Keegan, Michel Loots, Malika Mahoui, et Lloyd Smith. Nous remercions aussi tous ceux qui ont contribuÃ© au dÃ©veloppement des modules sous licence GNU GPL qui font partie de cette distribution: MG, GDBM, PDFTOHTML, PERL, WGET, WVWARE, XLHTML.</Text>
+</Content>
+</Section>
+<Chapter id="understanding_the_collection-building_process">
+<Title>
+<Text id="22">Comprendre le processus de construction d'une collection</Text>
+</Title>
+<Content>
+<Text id="23">Les utilisateurs finals de Greenstone peuvent construire des collections Ã  l'aide du Collector, dÃ©crit dans la section 3 du Guide de l'utilisateur de la bibliothÃšque numÃ©rique Greenstone. Il facilite beaucoup la construction de collections sur le modÃšle de collections existantes, mais avec des contenus nouveaux. Cependant, il n'est pas rÃ©ellement possible d'utiliser le Collector pour crÃ©er des collections avec des structures complÃštement nouvelles. Le Collector vous invite bien Ã  Ã©diter le fichier de configuration de la collection, qui gouverne cette structure de collection, mais il faut trÃšs bien connaÃ®tre Greenstone pour pouvoir y effectuer des modifications radicales et efficaces. La prÃ©sente section vous explique ce qu'il faut savoir pour opÃ©rer ainsi. Elle dÃ©crit Ã©galement la structure de rÃ©pertoire de Greenstone et le format interne de stockage des documents.</Text>
+<Text id="24">Tout au long de ce manuel nous supposerons que vous avez installÃ© Greenstone sur votre ordinateur, que ce dernier fonctionne sous Windows ou sous Unix. Si tel n'est pas encore le cas vous devriez consulter le Guide d'installation de la bibliothÃšque numÃ©rique Greenstone. Le nom GSDLHOME reprÃ©sentera le rÃ©pertoire racine de Greenstone, qui s'appelle %GSDLHOME% sur des systÃšmes Windows et $GSDLHOME sur des systÃšmes Unix. On dÃ©termine ce rÃ©pertoire pendant la procÃ©dure d'installation.</Text>
+<Section id="building_collections_from_the_command_line">
+<Title>
+<Text id="25">Construire des collections depuis la ligne de commande</Text>
+</Title>
+<Content>
+<Text id="26">CommenÃ§ons par dÃ©crire pas Ã  pas les opÃ©rations nÃ©cessaires pour construire une collection depuis la ligne de commande, ce qui facilitera la comprÃ©hension du processus. Bien sÃ»r, c'est le Collector qu'il faut plutÃŽt utiliser pour construire des collections de maniÃšre plus agrÃ©able. La collection que nous prenons en exemple est l'une des collections distribuÃ©es sur le cÃ©dÃ©rom du logiciel Greenstone, et elle contient les pages web personnelles de nombreux contributeurs au projet de bibliothÃšque numÃ©rique de Nouvelle-ZÃ©lande et au logiciel Greenstone.</Text>
+<Text id="27">Les sections suivantes dÃ©taillent la construction sous Windows et sous Unix. En rÃ©alitÃ©, les deux se ressemblent presque complÃštementÂ --Â ne lisez que celle qui concerne votre systÃšme. Lorsque vous suivrez ces Ã©tapes, vous penserez peut-Ãªtre que certaines opÃ©rations sont mystÃ©rieuses ou des arcanes, mais ne les en suivez pas moins fidÃšlementÂ --Â elles prendront tout leur sens plus tard. Suivra un bref rÃ©sumÃ© des diffÃ©rences entre les processus de construction sous les deux systÃšmes.</Text>
+<Subsection id="collection_building_under_windows">
+<Title>
+<Text id="28">Construire des collections sous Windows</Text>
+</Title>
+<Content>
+<Text id="29">Le premier dÃ©fi lors de la construction d'une collection Ã  la ligne de commande sous Windows, c'est de parvenir Ã  l'Â«interprÃ©teur de commandesÂ», qui est l'endroit oÃ¹ l'on tape les commandes. Dans le menu DÃ©marrer ou le sous-menu Programmes, recherchez une ligne Invite MS-DOS, Invite DOS, ou InterprÃ©teur de commandes. Si vous ne trouvez rien de tel, invoquez l'entrÃ©e ExÃ©cuter et tentez de taper command (ou cmd) dans la boÃ®te de dialogue qui va apparaÃ®tre. Si rien de tout ceci ne fonctionne, faites-vous assister par une personne qui s'y connaÃ®t, telle que votre administrateur systÃšme.</Text>
+<Text id="30">Rendez-vous dans le rÃ©pertoire d'installation de Greenstone. En supposant que Greenstone a Ã©tÃ© installÃ© dans l'emplacement standard, vous vous y rendrez en tapant:</Text>
+<CodeLine>cd "C:\Program Files\gsdl "</CodeLine>
+<Text id="31">Les apostrophes doubles sont nÃ©cessaires Ã  cause de l'espace dans Program Files. Tapez ensuite Ã  l'invite:</Text>
+<CodeLine>setup.bat</CodeLine>
+<Text id="32">Ce fichier de commandes (que vous pouvez lire si vous en avez la curiositÃ©) explique au systÃšme oÃ¹ trouver les programmes de Greenstone<FootnoteRef id="1"/>. Si lors de votre session Ã  l'invite de commandes DOS, vous souhaitez revenir au rÃ©pertoire racine de Greenstone, vous pourrez toujours ce faire en tapant cd "%GSDLHOME%" (ici encore, les apostrophes doubles sont nÃ©cessaires: elles sont dues Ã  la prÃ©sence d'espaces dans le nom de fichier). Si vous fermez votre fenÃªtre DOS et en ouvrez une autre, il faudra de nouveau invoquer le fichier setup.bat.</Text>
+<Text id="33">Vous avez maintenant la possibilitÃ© de compiler, construire, et construire Ã  nouveau des collections. Le premier programme que vous allons examiner est le programme Perl mkcol.pl, dont le nom signifie Â«make a collectionÂ» (compiler une collection). Commencez par exÃ©cuter le programme en tapant perl -S mkcol.pl pour obtenir Ã  l'Ã©cran une description de la syntaxe et une liste des arguments possiblesÂ --Â si votre environnement Windows est configurÃ© de maniÃšre Ã  associer l'application Perl aux fichiers se terminant en .pl, il vous suffira de taper mkcol.pl pour obtenir ce rÃ©sultat. Comme vous pourrez le lire dans le message qui apparaÃ®t, l'unique argument obligatoire est creator, qui sert Ã  spÃ©cifier qui a construit la collection.</Text>
+<Text id="34">Utilisons cette commande pour crÃ©er les fichiers et sous-rÃ©pertoires initiaux nÃ©cessaires Ã  notre collection des pages personnelles des membres du projet de bibliothÃšque numÃ©rique Greenstone. Pour affecter Ã  la collection le nom dlpeople (Â«gens de la bibliothÃšque numÃ©riqueÂ» en anglais et en abrÃ©gÃ©), j'ai tapÃ©:</Text>
+<CodeLine>perl âS mkcol.pl âcreator me@cs.waikato.ac.nz dlpeople</CodeLine>
+<Text id="35">(on peut se contenter de taper<i>mkcol.pl -creator me@cs.waikato.ac.nz dlpeople</i>si Perl est associÃ© aux extensions de fichiers en<i>.pl</i>). N'oubliez pas de remplacer mon adresse Ã©lectronique par la vÃŽtre!</Text>
+<Text id="36">Pour visualiser les fichiers nouvellement crÃ©Ã©s, on se dÃ©place dans le rÃ©pertoire de la collection en tapant:</Text>
+<CodeLine>cd "%GSDLHOME%\collect\dlpeople "</CodeLine>
+<Figure id="collection_configuration_file_created_by_mkcol">
+<Title>
+<Text id="37">Fichier de configuration de collection crÃ©Ã© par mkcol.pl</Text>
+</Title>
+<CodeLine>creatorÂ Â Â Â Â Â Â Â Â Â Â Â Â me@cs.waikato.ac.nz</CodeLine>
+<CodeLine>maintainerÂ Â Â Â Â Â Â Â Â Â me@cs.waikato.ac.nz</CodeLine>
+<CodeLine>publicÂ Â Â Â Â Â Â Â Â Â Â Â Â Â true</CodeLine>
+<CodeLine>betaÂ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â true</CodeLine>
+<CodeLine>indexesÂ Â Â Â Â Â Â Â Â Â Â Â Â document:text</CodeLine>
+<CodeLine>defaultindexÂ Â Â Â Â Â Â Â document:text</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â ZIPPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â GAPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â TEXTPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â HTMLPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â EMAILPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â ArcPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â RecPlug</CodeLine>
+<CodeLine>classifyÂ Â Â Â Â Â Â Â Â Â Â Â AZList -metadata "Title"</CodeLine>
+<CodeLine>collectionmetaÂ collectionnameÂ Â Â Â "dlpeople"</CodeLine>
+<CodeLine>collectionmetaÂ iconcollectionÂ Â Â Â ""</CodeLine>
+<CodeLine>collectionmetaÂ collectionextraÂ Â Â ""</CodeLine>
+<CodeLine>collectionmetaÂ .document:textÂ Â Â Â "documents "</CodeLine>
+</Figure>
+<Text id="38">On peut alors lister le contenu du rÃ©pertoire en tapant dir. Il devrait s'y trouver sept sous-rÃ©pertoires: archives, building, etc, images, import, index, et perllib.</Text>
+<Text id="39">Il faut maintenant peupler la collection d'Ã©chantillons de documents. Les documents source de la collection dlpeople se trouvent sur le cÃ©dÃ©rom de la distribution Greenstone dans le rÃ©pertoire collectdlpeople. InsÃ©rez d'abord le cÃ©dÃ©rom dans le lecteur (par exemple, sous D). Copiez ensuite le contenu du rÃ©pertoire Dcollectdlpeople dans le rÃ©pertoire import de la collection dlpeople. Vous pouvez procÃ©der comme suit:</Text>
+<Indented>
+<Text id="40">sÃ©lectionner le contenu du rÃ©pertoire dlpeople, et le faire glisser dans le rÃ©pertoire import de la collection dlpeople.</Text>
+</Indented>
+<Text id="41">Vous pouvez aussi taper la commande:</Text>
+<CodeLine>xcopy /s d:\collect\dlpeople\* import</CodeLine>
+<Text id="42">Dans le rÃ©pertoire etc de la collection, on trouve un fichier appelÃ© collect.cfg. Ouvrez-le dans votre Ã©diteur de texte prÃ©fÃ©rÃ©Â --Â edit est basique mais communÃ©ment disponible. Il devrait ressembler Ã  ce que prÃ©sente la figureÂ <CrossRef target="Figure" ref="collection_configuration_file_created_by_mkcol"/>, qui montre le fichier de configuration de collection crÃ©Ã© par la commande:</Text>
+<Text id="43">Nous sommes dÃ©sormais disposÃ©s Ã  Â«importerÂ» la collection. Il s'agit du processus qui apporte les documents dans le systÃšme Greenstone, en normalisant le format des documents, la maniÃšre dont les mÃ©ta-donnÃ©es sont spÃ©cifiÃ©es, et la structure de fichiers de stockage des documents. Tapez perl -S import.pl Ã  l'invite pour obtenir une liste de toutes les options du programme d'import. L'option -removeold s'assure que tout document prÃ©alablement importÃ© est effacÃ© dans un premier temps.</Text>
+<CodeLine>perl âS import.pl -removeold dlpeople</CodeLine>
+<Text id="44">Ne vous inquiÃ©tez pas du texte qui dÃ©file: il s'agit d'un compte-rendu de la progression de l'import. Sachez que l'import de cette collection prend environ cinq minutes sur une machine Ã  1Â GHz, et d'autant plus longtemps sur des machines plus lentes. Vous remarquerez qu'il n'est pas besoin de se trouver dans les rÃ©pertoires collect ou dlpeople lors de la saisie de cette commande: la variable GSDLHOME Ã©tant dÃ©jÃ  positionnÃ©e, le logiciel Greenstone peut trouver tous les fichiers nÃ©cessaires.</Text>
+<Text id="45">Modifions dÃ©sormais quelque peu le fichier de configuration de la collection pour en personnaliser la reprÃ©sentation. Donnons d'abord un nom Ã  la collection. Il sera utilisÃ© par les navigateurs web en tant que page de titre pour la premiÃšre page de la collection, et servira d'icone de collection si aucune image n'est fournie. Remplacez la ligne<i>collectionmeta collectionname "dlpeople"</i>par quelque chose comme<i>collectionmeta collectionname "Les membres du projet NZDL"</i>(NZDL est l'acronyme anglais du projet de bibliothÃšque numÃ©rique de Nouvelle-ZÃ©lande: New Zealand Digital Library Project).</Text>
+<Text id="46">Ajoutez une description de votre collection entre les apostrophes doubles de la ligne collectionmeta collectionextra "". Elle servira de texte pour le paragraphe Ã  propos sur la page d'accueil de la collection. J'ai personnellement ajoutÃ©: "Cette collection comprend les pages personnelles de certains membres du projet NZDL.". Il est important de saisir cette description sous la forme d'une seule ligne dans l'Ã©diteurÂ --Â ne soyez pas tentÃ© de revenir Ã  la ligne si vous arrivez sur le bord droit de la fenÃªtre, mais continuez simplement Ã  taper!Â --Â sans quoi le fichier de configuration ne pourra pas Ãªtre correctement analysÃ©. Si vous souhaitez que votre collection puisse Ãªtre utilisÃ©e avec diffÃ©rentes interfaces de langues, il est possible de faire en sorte que cette description dÃ©pende de la langue choisie: ce procÃ©dÃ© est dÃ©crit dans la sectionÂ <CrossRef target="Section" ref="configuration_file"/>, plus bas.</Text>
+<Text id="47">On peut retenir toute image utilisable dans un navigateur web en tant qu'icone de collectionÂ --Â l'image que j'ai crÃ©Ã©e est prÃ©sentÃ©e figure <CrossRef target="Figure" ref="collection_icon"/>. Tapez l'emplacement de l'image entre les apostrophes doubles de la ligne<i>collectionmeta iconcollection ""</i>du fichier de configuration. On peut utiliser le raccourci _httpprefix_ pour remplacer le dÃ©but d'une URL qui pointe vers une image situÃ©e dans la zone de fichiers de Greenstone. Cela rend Ã©galement les configurations plus portables. Vous pouvez par exemple taper:<i>_httpprefix_/collect/dlpeople/images/icon.gif</i>si vous avez placÃ© une image convenable dans le rÃ©pertoire images de la collection (collectdlpeopleimages dans l'exemple qui nous intÃ©resse).</Text>
+<Text id="48">Sauvegardez le fichier de configuration de la collection et refermez-leÂ --Â vous n'en aurez plus besoin au cours de ce didacticiel.</Text>
+<Text id="49">La prochain Ã©tape consiste Ã  Â«construireÂ» la collection, ce qui crÃ©e tous les index et fichiers qui lui permettront de fonctionner. Tapez perl -S buildcol.pl Ã  l'invite pour obtenir la liste des options de construction de collection. Ces options sont prÃ©sentÃ©es plus en dÃ©tails dans la section section <CrossRef target="Section" ref="import_and_build_processes"/>. Pour l'instant, nous nous contenterons des valeurs par dÃ©faut en tapant:</Text>
+<CodeLine>perl âS buildcol.pl dlpeople</CodeLine>
+<Text id="50">Ã  l'invite. Ici non plus, ne vous inquiÃ©tez pas en voyant dÃ©filer le compte-rendu de progression.</Text>
+<Text id="51">Â«ActivezÂ» la collection comme suit:</Text>
+<Text id="52">sÃ©lectionnez le contenu du rÃ©pertoire building de la collection dlpeople, et faites-le glisser dans le rÃ©pertoire index.</Text>
+<Text id="53">Vous pouvez aussi effacer le rÃ©pertoire index (et tout ce qu'il contient) en tapant la commande:</Text>
+<CodeLine>rd /s index                 # on Windows NT/2000</CodeLine>
+<CodeLine>deltree /Y index       # on Windows 95/98</CodeLine>
+<Text id="54">et rebaptiser ensuite le rÃ©pertoire building en index avec:</Text>
+<CodeLine>ren building index</CodeLine>
+<Text id="55">Enfin, tapez:</Text>
+<CodeLine>mkdir building</CodeLine>
+<Text id="56">en vue de futures reconstructions. Il est important de taper ces commandes dans le bon rÃ©pertoire (Ã  la diffÃ©rence des commandes mkcol.pl, import.pl et buildcol.pl de Greenstone). Si le rÃ©pertoire actuel n'est pas dlpeople, tapez:<i>cd "%GSDLHOME%\collect\dlpeople"</i>avant de procÃ©der Ã  la sÃ©quence rd, ren, et mkdir donnÃ©e ci-dessus.</Text>
+<Text id="57">Vous devriez pouvoir accÃ©der Ã  la collection nouvellement construite depuis la page d'accueil de Greenstone. Il vous faudra rÃ©actualiser ou recharger cette page si elle Ã©tait dÃ©jÃ  ouverte dans votre navigateur, voire fermer le navigateur et le redÃ©marrer (pour Ã©viter les problÃšmes de tampon ou cache). Il se peut aussi, dans le cas oÃ¹ vous utilisez la version Â«BibliothÃšque localeÂ» de Greenstone, que vous deviez redÃ©marrer le programme library. Pour visualiser la nouvelle collection, cliquez sur l'image. Le resultat devrait alors ressembler Ã  la figureÂ <CrossRef target="Figure" ref="about_page_for_the_new_collection"/>.</Text>
+<Figure id="collection_icon">
+<Title>
+<Text id="58">Icone de collection </Text>
+</Title>
+<File width="156" height="120" url="images/Dev_Fig_2.png"/>
+</Figure>
+<Text id="59">Si nous nous rÃ©sumons, l'ensemble des commandes tapÃ©es pour produire la collection dlpeople sont:</Text>
+<CodeLine>cd "C:\Program Files\gsdl " # assuming default location</CodeLine>
+<CodeLine>setup.bat</CodeLine>
+<CodeLine>perl âS mkcol.pl âcreator me@cs.waikato.ac.nz dlpeople</CodeLine>
+<CodeLine>cd "%GSDLHOME%\collect\dlpeople "</CodeLine>
+<CodeLine>xcopy   /s   d:\collect\dlpeople\*   import # assuming D drive</CodeLine>
+<CodeLine>perl âS import.pl dlpeople</CodeLine>
+<CodeLine>perl âS buildcol.pl dlpeople</CodeLine>
+<CodeLine>rd /s index           # on Windows NT/2000</CodeLine>
+<CodeLine>deltree /Y index # on Windows 95/98</CodeLine>
+<CodeLine>ren building index</CodeLine>
+<CodeLine>mkdir building</CodeLine>
+</Content>
+</Subsection>
+<Subsection id="collection_building_under_unix">
+<Title>
+<Text id="60">Construire des collections sous Unix</Text>
+</Title>
+<Content>
+<Text id="61">Commencez par vous rendre dans le rÃ©pertoire d'installation de Greenstone. Si par exemple Greenstone a Ã©tÃ© installÃ© dans l'emplacement standard, dans votre rÃ©pertoire personnel, vous vous y rendrez en tapant:</Text>
+<CodeLine>cd ~/gsdl</CodeLine>
+<Text id="62">Tapez ensuite Ã  l'invite:</Text>
+<CodeLine>source setup.bash     # if you're running the BASH shell</CodeLine>
+<CodeLine>source setup.csh       # if you're running the C shell</CodeLine>
+<Text id="63">Ces fichiers de commandes (que vous pouvez lire si vous en avez la curiositÃ©) expliquent au systÃšme oÃ¹ trouver les programmes de Greenstone. Si lors de votre session Ã  l'interprÃ©teur de commandes, vous souhaitez revenir au rÃ©pertoire racine de Greenstone, vous pourrez toujours ce faire en tapant cd $GSDLHOME.</Text>
+<Text id="64">Si vous ignorez le type d'interprÃ©teur de commandes que vous utilisez, tapez echo $0 Ã  l'inviteÂ --Â cela affichera l'information recherchÃ©e. Si vous utilisez un autre interprÃ©teur de commandes, demandez conseil Ã  votre administrateur systÃšme.</Text>
+<Text id="65">AprÃšs avoir chargÃ© le bon fichier de rÃ©glages, vous avez maintenant la possibilitÃ© de compiler, construire, et construire Ã  nouveau des collections. Le premier programme que vous allons examiner est le programme Perl mkcol.pl, dont le nom signifie Â«make a collectionÂ» (compiler une collection). Commencez par exÃ©cuter le programme en tapant simplement mkcol.pl pour obtenir Ã  l'Ã©cran une description de la syntaxe et une liste des arguments possibles. Comme vous pourrez le lire dans le message qui apparaÃ®t, l'unique argument obligatoire est creator, qui sert Ã  spÃ©cifier qui a construit la collection.</Text>
+<Figure id="about_page_for_the_new_collection">
+<Title>
+<Text id="66">Page Â«Ã  proposÂ» de la nouvelle collection</Text>
+</Title>
+<File width="389" height="409" url="images/Dev_Fig_3.png"/>
+</Figure>
+<Text id="67">Utilisons cette commande pour crÃ©er les fichiers et sous-rÃ©pertoires initiaux nÃ©cessaires Ã  notre collection des pages personnelles des membres du projet de bibliothÃšque numÃ©rique Greenstone. Pour affecter Ã  la collection le nom dlpeople (Â«gens de la bibliothÃšque numÃ©riqueÂ» en anglais et en abrÃ©gÃ©), j'ai tapÃ©:</Text>
+<CodeLine>mkcol.pl âcreator me@cs.waikato.ac.nz dlpeople</CodeLine>
+<Text id="68">N'oubliez pas de remplacer mon adresse Ã©lectronique par la vÃŽtre!</Text>
+<Text id="69">Pour visualiser les fichiers nouvellement crÃ©Ã©s, on se dÃ©place dans le rÃ©pertoire de la collection en tapant:</Text>
+<CodeLine>cd $GSDLHOME/collect/dlpeople</CodeLine>
+<Text id="70">On peut alors lister le contenu du rÃ©pertoire en tapant ls. Il devrait s'y trouver sept sous-rÃ©pertoires: archives, building, etc, images, import, index, et perllib.</Text>
+<Text id="71">Il faut maintenant peupler la collection d'Ã©chantillons de documents. Les documents source de la collection dlpeople se trouvent sur le cÃ©dÃ©rom de la distribution Greenstone dans le rÃ©pertoire collect/dlpeople. Pour lire des informations sur un cÃ©dÃ©rom depuis Linux, insÃ©rez le disque dans le lecteur et tapez</Text>
+<CodeLine>mount /cdrom</CodeLine>
+<Text id="72">Ã  l'invite (cette commande peut varier d'un systÃšme Ã  l'autre). Une fois montÃ©, le cÃ©dÃ©rom peut s'utiliser comme tout autre rÃ©pertoire; vous pouvez donc taper ls /cdrom/collect. VoilÃ  qui devrait rÃ©vÃ©ler un rÃ©pertoire dlpeople sur le cÃ©dÃ©rom.</Text>
+<Text id="73">Copiez ensuite le contenu du rÃ©pertoire /cdrom/collect/dlpeople dans le rÃ©pertoire GSDLHOME/collect/dlpeople/import. Pour ce faire, tapez la commande:</Text>
+<CodeLine>cp âr /cdrom/collect/dlpeople/*   import/</CodeLine>
+<Text id="74">puis tapez</Text>
+<CodeLine>umount /cdrom</CodeLine>
+<Text id="75">pour fermer le lecteur de cÃ©dÃ©rom. </Text>
+<Text id="76">Dans le rÃ©pertoire etc de la collection, on trouve un fichier appelÃ© collect.cfg. Ouvrez-le dans votre Ã©diteur de texte prÃ©fÃ©rÃ©Â --Â emacs est un Ã©diteur populaire sous Linux.Il devrait ressembler Ã  ce que prÃ©sente la figureÂ 1, qui montre le fichier de configuration de collection crÃ©Ã© par la commande:<i>mkcol.pl -creator me@cs.waikato.ac.nz dlpeople</i></Text>
+<Text id="77">Nous sommes dÃ©sormais disposÃ©s Ã  Â«importerÂ» la collection. Il s'agit du processus qui apporte les documents dans le systÃšme Greenstone, en normalisant le format des documents, la maniÃšre dont les mÃ©ta-donnÃ©es sont spÃ©cifiÃ©es, et la structure de fichiers de stockage des documents. Tapez import.pl Ã  l'invite pour obtenir une liste de toutes les options du programme d'import. L'option -removeold s'assure que tout document prÃ©alablement importÃ© est effacÃ© dans un premier temps.</Text>
+<CodeLine>import.pl âremoveold dlpeople</CodeLine>
+<Text id="78">Ne vous inquiÃ©tez pas du texte qui dÃ©file: il s'agit d'un compte-rendu de la progression de l'import. Sachez que l'import de cette collection prend environ cinq minutes sur une machine Ã  1Â GHz, et d'autant plus longtemps sur des machines plus lentes. Vous remarquerez qu'il n'est pas besoin de se trouver dans les rÃ©pertoires collect ou dlpeople lors de la saisie de cette commande: la variable GSDLHOME Ã©tant dÃ©jÃ  positionnÃ©e, le logiciel Greenstone peut trouver tous les fichiers nÃ©cessaires.</Text>
+<Text id="79">Modifions dÃ©sormais quelque peu le fichier de configuration de la collection pour en personnaliser la reprÃ©sentation. Donnons d'abord un nom Ã  la collection. Il sera utilisÃ© par les navigateurs web en tant que page de titre pour la premiÃšre page de la collection, et servira d'icone de collection si aucune image n'est fournie. Remplacez la ligne<i>collectionmeta collectionname "dlpeople"</i>par quelque chose comme<i>collectionmeta collectionname "Les membres du projet NZDL"</i>(NZDL est l'acronyme anglais du projet de bibliothÃšque numÃ©rique de Nouvelle-ZÃ©lande: New Zealand Digital Library Project).</Text>
+<Text id="80">Ajoutez une description de votre collection entre les apostrophes doubles de la ligne collectionmeta collectionextra "". Elle servira de texte pour le paragraphe Â«Ã  proposÂ» sur la page d'accueil de la collection. J'ai personnellement ajoutÃ©: "Cette collection comprend les pages personnelles de certains contributeurs au projet NZDL.". Il est important de saisir cette description sous la forme d'une seule ligne dans l'Ã©diteurÂ --Â ne soyez pas tentÃ© de revenir Ã  la ligne si vous arrivez sur le bord droit de la fenÃªtre, mais continuez simplement Ã  taper!Â --Â sans quoi le fichier de configuration ne pourra pas Ãªtre correctement analysÃ©. Si vous souhaitez que votre collection puisse Ãªtre utilisÃ©e avec diffÃ©rentes interfaces de langues, il est possible de faire en sorte que cette description dÃ©pende de la langue choisie: ce procÃ©dÃ© est dÃ©crit dans la sectionÂ <CrossRef target="Section" ref="configuration_file"/>, ci-dessous.</Text>
+<Text id="81">On peut retenir toute image utilisable dans un navigateur web en tant qu'icone de collectionÂ --Â l'image que j'ai crÃ©Ã©e est prÃ©sentÃ©e figureÂ <CrossRef target="Figure" ref="collection_icon"/>. Tapez l'emplacement de l'image entre les apostrophes doubles de la ligne<i>collectionmeta iconcollection ""</i>du fichier de configuration. On peut utiliser le raccourci _httpprefix_ pour remplacer le dÃ©but d'une URL qui pointe vers une image situÃ©e dans la zone de fichiers de Greenstone. Cela rend Ã©galement les configurations plus portables. Vous pouvez par exemple taper:<i>_httpprefix_/collect/dlpeople/images/icon.gif</i>si vous avez placÃ© une image convenable dans le rÃ©pertoire images de la collection (collect/dlpeople/images dans l'exemple qui nous intÃ©resse).</Text>
+<Text id="82">Sauvegardez le fichier de configuration de la collection et refermez-leÂ --Â vous n'en aurez plus besoin au cours de ce didacticiel.</Text>
+<Text id="83">La prochain Ã©tape consiste Ã  Â«construireÂ» la collection, ce qui crÃ©e tous les index et fichiers qui lui permettront de fonctionner. Tapez buildcol.pl Ã  l'invite pour obtenir la liste des options de construction de collection. Ces options sont prÃ©sentÃ©es plus en dÃ©tails dans la section section <CrossRef target="Section" ref="import_and_build_processes"/>. Pour l'instant, nous nous contenterons des valeurs par dÃ©faut en tapant:</Text>
+<CodeLine>buildcol.pl dlpeople</CodeLine>
+<Text id="84">Ã  l'invite. Ici non plus, ne vous inquiÃ©tez pas en voyant dÃ©filer le compte-rendu de progression.</Text>
+<Text id="85">Â«ActivezÂ» la collection en dÃ©plaÃ§ant toutes les donnÃ©es qui viennent d'Ãªtre placÃ©es dans le rÃ©pertoire building vers le rÃ©pertoire index. Si vous avez dÃ©jÃ  construit cette collection de par le passÃ©, commencez d'abord par enlever l'ancien rÃ©pertoire index avec la commande:</Text>
+<CodeLine>rm âr index/*</CodeLine>
+<Text id="86">(en supposant que vous vous trouvez alors dans le rÃ©pertoire dlpeople). Puis tapez</Text>
+<CodeLine>mv building/* index/</CodeLine>
+<Table id="collection-building_differences_between_windows_and_linux">
+<Title>
+<Text id="87">DiffÃ©rences entre Windows et Linux pour la construction de collections</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="265">
+<Text id="88"><b>Windows</b></Text>
+</th>
+<th width="265">
+<Text id="89"><b>Linux</b></Text>
+</th>
+</tr>
+<tr>
+<th width="265">
+<Text id="90">ExÃ©cuter<i>setup.bat</i>pour rendre disponibles les programmes de Greenstone </Text>
+</th>
+<th width="265">
+<Text id="91">Charger<i>setup.bash</i>ou<i>setup.csh</i>pour rendre les programmes disponibles</Text>
+</th>
+</tr>
+<tr>
+<th width="265">
+<Text id="92">Copier les fichiers depuis le cÃ©dÃ©rom en utilisant le gestionnaire de fichiers graphique ou des commandes DOS</Text>
+</th>
+<th width="265">
+<Text id="93">Copier les fichiers depuis le cÃ©dÃ©rom en utilisant<i>mount</i>et d'autres commandes Unix</Text>
+</th>
+</tr>
+<tr>
+<th width="265">
+<Text id="94">L'ancien index de collection est remplacÃ© en tapant<i>rd /s index</i>puis<i>ren building index</i>suivis de<i>mkdir building</i>, ou en utilisant le gestionnaire de fichiers graphique</Text>
+</th>
+<th width="265">
+<Text id="95">L'ancien index de collection est remplacÃ© en tapant<i>rm âr index/*</i>puis<i>mv building/* index</i></Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="96">Vous devriez pouvoir accÃ©der Ã  la collection nouvellement construite depuis la page d'accueil de Greenstone. Il vous faudra rÃ©actualiser ou recharger cette page si elle Ã©tait dÃ©jÃ  ouverte dans votre navigateur, voire fermer le navigateur et le redÃ©marrer (pour Ã©viter les problÃšmes de tampon ou cache). Pour visualiser la nouvelle collection, cliquez sur l'image. Le resultat devrait alors ressembler Ã  la figureÂ <CrossRef target="Figure" ref="about_page_for_the_new_collection"/>.</Text>
+<Text id="97">Si nous nous rÃ©sumons, l'ensemble des commandes tapÃ©es pour produire la collection dlpeople sont:</Text>
+<CodeLine>cd ~/gsdl # assuming default Greenstone in home directory</CodeLine>
+<CodeLine>source setup.bash     # if you're running the BASH shell</CodeLine>
+<CodeLine>source setup.csh       # if you're running the C shell</CodeLine>
+<CodeLine>mkcol.pl âcreator me@cs.waikato.ac.nz dlpeople</CodeLine>
+<CodeLine>cd $GSDLHOME/collect/dlpeople</CodeLine>
+<CodeLine>mount /cdrom # assuming this is where CD-ROM is mapped to</CodeLine>
+<CodeLine>cp âr /cdrom/collect/dlpeople/* import/</CodeLine>
+<CodeLine>umount /cdrom</CodeLine>
+<CodeLine>import.pl dlpeople</CodeLine>
+<CodeLine>buildcol.pl dlpeople</CodeLine>
+<CodeLine>rm -r index/*</CodeLine>
+<CodeLine>mv building/* index</CodeLine>
+</Content>
+</Subsection>
+<Subsection id="differences_between_windows_and_unix">
+<Title>
+<Text id="98">DiffÃ©rences entre Windows et Unix</Text>
+</Title>
+<Content>
+<Text id="99">Les processus de construction de collection sont trÃšs similaires sous Unix et sous Windows, mais quelques petites diffÃ©rences demeurent, diffÃ©rences que nous avons rÃ©sumÃ©es dans la tableÂ <CrossRef target="Table" ref="collection-building_differences_between_windows_and_linux"/>.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="greenstone_directories">
+<Title>
+<Text id="100">Les rÃ©pertoires de Greenstone</Text>
+</Title>
+<Content>
+<Text id="101">La figureÂ <CrossRef target="Figure" ref="structure_of_the_gsdlhome_directory"/> montre la structure du rÃ©pertoire GSDLHOME. La tableÂ <CrossRef target="Table" ref="where_to_find_information_about_directories"/> donne une brÃšve description du contenu de chacun des rÃ©pertoires reprÃ©sentÃ©s dans le diagramme. Certains rÃ©pertoires seront plus dÃ©taillÃ©s plus loin dans le manuelÂ --Â utilisez le guide des sections de la tableÂ <CrossRef target="Table" ref="where_to_find_information_about_directories"/> pour savoir oÃ¹ aller chercher des informations supplÃ©mentaires.</Text>
+<Figure id="structure_of_the_gsdlhome_directory">
+<Title>
+<Text id="102">Structure du rÃ©pertoire GSDLHOME</Text>
+</Title>
+<File width="415" height="143" url="images/Dev_Fig_4.png"/>
+</Figure>
+<Table id="where_to_find_information_about_directories">
+<Title>
+<Text id="103">OÃ¹ trouver de l'information Ã  propos des rÃ©pertoires</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="331">
+<Text id="104"><b>Contenu</b></Text>
+</th>
+<th width="66">
+<Text id="105">Section</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="106"><i>bin</i></Text>
+</th>
+<th width="331">
+<Text id="107">Code exÃ©cutable, comprenant des binaires dans le rÃ©pertoire portant le nom de votre systÃšme d'exploitation.</Text>
+</th>
+<th width="66">
+<Text id="108">â</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="109"><i>bin/script</i></Text>
+</th>
+<th width="331">
+<Text id="110">Scripts Perl utilisÃ©s pour la crÃ©ation et la construction de collections (tels que<i>import.pl</i>et<i>buildcol.pl</i>). Pour obtenir une description de ces programmes, tapez leur nom Ã  l'invite de commandes.</Text>
+</th>
+<th width="66">
+<Text id="111">1.3</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="112"><i>perllib</i></Text>
+</th>
+<th width="331">
+<Text id="113">Modules Perl utilisÃ©s au moment de l'import et de la construction (tels que les greffons, ou<i>plugins</i>)</Text>
+</th>
+<th width="66">
+<Text id="114">2.1</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="115"><i>perllib/plugins</i></Text>
+</th>
+<th width="331">
+<Text id="116">Code Perl pour les greffons (<i>plugins</i>) de traitement de documents. </Text>
+</th>
+<th width="66">
+<Text id="117">2.1</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="118"><i>perllib/classify</i></Text>
+</th>
+<th width="331">
+<Text id="119">Code Perl pour les classificateurs (tels que le code AZList, qui crÃ©e une liste de documents en se basant sur l'ordre alphabÃ©tique d'un attribut.)</Text>
+</th>
+<th width="66">
+<Text id="120">2.2</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="121"><i>cgi-bin</i></Text>
+</th>
+<th width="331">
+<Text id="122">Tous les scripts CGI de Greenstone, qui seront dÃ©placÃ©s vers le rÃ©pertoire<i>cgi-bin</i>du systÃšme.</Text>
+</th>
+<th width="66">
+<Text id="123">â</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="124"><i>tmp</i></Text>
+</th>
+<th width="331">
+<Text id="125">RÃ©pertoire utilisÃ© par Greenstone pour le stockage des fichiers temporaires.</Text>
+</th>
+<th width="66">
+<Text id="126">â</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="127"><i>etc</i></Text>
+</th>
+<th width="331">
+<Text id="128">Fichiers de configuration, journaux d'initialisation et d'erreur, bases de donnÃ©es d'autorisation des utilisateurs.</Text>
+</th>
+<th width="66">
+<Text id="129">â</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="130"><i>src</i></Text>
+</th>
+<th width="331">
+<Text id="131">Code C++ utilisÃ© pour servir des collections sur un serveur web.</Text>
+</th>
+<th width="66">
+<Text id="132">3</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="133"><i>src/colservr</i></Text>
+</th>
+<th width="331">
+<Text id="134">Code C++ pour servir des collectionsâpour rÃ©pondre aux requÃªtes et ce genre de choses.</Text>
+</th>
+<th width="66">
+<Text id="135"><CrossRef target="Section" ref="protocol"/></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="136"><i>src/recpt</i></Text>
+</th>
+<th width="331">
+<Text id="137">Code C++ pour obtenir des requÃªtes depuis l'interface utilisateur et mettre en forme les rÃ©ponses aux requÃªtes pour cette interface.</Text>
+</th>
+<th width="66">
+<Text id="138">3.9</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="139"><i>packages</i></Text>
+</th>
+<th width="331">
+<Text id="140">Code source des paquetages logiciels externes Ã  Greenstone mais utilisÃ©s par ce dernier.</Text>
+</th>
+<th width="66">
+<Text id="141">2.5</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="142"><i>packages/mg</i></Text>
+</th>
+<th width="331">
+<Text id="143">Code source de MG, logiciel de compression et d'indexation utilisÃ© par Greenstone.</Text>
+</th>
+<th width="66">
+<Text id="144">2.5</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="145"><i>mappings</i></Text>
+</th>
+<th width="331">
+<Text id="146">Tables de correspondance Unicode (comme par exemple pour le jeu de caractÃšres chinois GB).</Text>
+</th>
+<th width="66">
+<Text id="147">â</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="148"><i>macros</i></Text>
+</th>
+<th width="331">
+<Text id="149">Les fichiers de macros utilisÃ©s pour l'interface utilisateur.</Text>
+</th>
+<th width="66">
+<Text id="150">2.4</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="151"><i>collect</i></Text>
+</th>
+<th width="331">
+<Text id="152">Collections servies par cette copie de Greenstone.</Text>
+</th>
+<th width="66">
+<Text id="153">1.1</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="154"><i>lib</i></Text>
+</th>
+<th width="331">
+<Text id="155">Code C++ utilisÃ© Ã  la fois par le serveur de collection et par le rÃ©ceptionniste.</Text>
+</th>
+<th width="66">
+<Text id="156">3.1</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="157"><i>images</i></Text>
+</th>
+<th width="331">
+<Text id="158">Images utilisÃ©es dans l'interface utilisateur.</Text>
+</th>
+<th width="66">
+<Text id="159">â</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="160"><i>docs</i></Text>
+</th>
+<th width="331">
+<Text id="161">Documentation.</Text>
+</th>
+<th width="66">
+<Text id="162">â</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Section>
+<Section id="import_and_build_processes">
+<Title>
+<Text id="163">Les processus d'import et de construction</Text>
+</Title>
+<Content>
+<Text id="164">Dans le processus de construction de collection dÃ©crit Ã  la sectionÂ <CrossRef target="Section" ref="building_collections_from_the_command_line"/>, on utilise une commande pour importer des documents (import.pl) et une autre commande pour construire la collection (buildcol.pl). Nous dÃ©taillons dans la prÃ©sente section ce que ces programmes font et les options qu'ils acceptent. Nous utiliserons la variable nom_col pour nous rÃ©fÃ©rer Ã  la collection en cours de construction ou d'import.</Text>
+<Text id="165">Les processus d'import et de construction sont trÃšs similaires, ce qui explique le nombre d'options communes qu'ils comptent, options dÃ©crites dans la tableÂ <CrossRef target="Table" ref="options_for_the_import_and_build_processes"/> (souvenez-vous que pour obtenir la liste des options acceptÃ©es par tout script Greenstone, il suffit de taper son nom seul, sans argument, Ã  l'invite de commandes).</Text>
+<Table id="options_for_the_import_and_build_processes">
+<Title>
+<Text id="166">Options des processus d'import et de construction</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="104">
+<Text id="167"><b>Argument</b></Text>
+</th>
+<th width="293">
+<Text id="168"><b>Fonction</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="169"><i>-verbosity</i></Text>
+</th>
+<th width="104">
+<Text id="170">Nombre de 0 Ã  3</Text>
+</th>
+<th width="293">
+<Text id="171">ContrÃŽle la quantitÃ© d'informations sur le processus qui sont affichÃ©es sur la sortie d'erreur standard: Â«0Â» en donne un peu, Â«3Â» en donne beaucoup.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="172"><i>-archivedir</i></Text>
+</th>
+<th width="104">
+<Text id="173">Nom de rÃ©pertoire</Text>
+</th>
+<th width="293">
+<Text id="174">SpÃ©cifie oÃ¹ les fichiers d'archives de Greenstone sont stockÃ©s, c'est-Ã -dire oÃ¹<i>import.pl</i>les enregistre et oÃ¹<i>buildcol.pl</i>les trouve. La valeur par dÃ©faut est<i>GSDLHOME/collect/nom_col/archives</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="175"><i>-maxdocs</i></Text>
+</th>
+<th width="104">
+<Text id="176">Nombre &gt;0</Text>
+</th>
+<th width="293">
+<Text id="177">Nombre maximal de documents Ã  importer ou Ã  construire. Option utile lors de tests de fichiers de configuration d'une nouvelle collection, ou de nouveaux greffons<i>plugins</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="178"><i>-collectdir</i></Text>
+</th>
+<th width="104">
+<Text id="179">Nom de rÃ©pertoire</Text>
+</th>
+<th width="293">
+<Text id="180">SpÃ©cifie oÃ¹ la collection se trouve. La valeur par dÃ©faut est<i>GSDLHOME/collect</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="181"><i>-out</i></Text>
+</th>
+<th width="104">
+<Text id="182">Nom de fichier</Text>
+</th>
+<th width="293">
+<Text id="183">SpÃ©cifie un fichier oÃ¹ Ã©crire tous les messages produits, le comportement par dÃ©faut Ã©tant de les afficher sur la sortie d'erreur standard (c'est-Ã -dire l'Ã©cran). Option utile lorsque l'on travaille avec des niveaux de dÃ©bogage.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="184"><i>-keepold</i></Text>
+</th>
+<th width="104">
+<Text id="185">Aucun</Text>
+</th>
+<th width="293">
+<Text id="186">N'efface pas le rÃ©sultat de l'ancienne opÃ©ration d'import ou de construction. Dans le cas de l'import, ceci signifie que l'on n'efface pas le contenu du rÃ©pertoire<i>archives</i>; dans le cas de la construction, ceci signifie que l'on n'efface pas le contenu du rÃ©pertoire<i>building</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="187"><i>âdebug</i></Text>
+</th>
+<th width="104">
+<Text id="188">Aucun</Text>
+</th>
+<th width="293">
+<Text id="189">Affiche la sortie du greffon<i>plugin</i>sur la sortie standard.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Subsection id="the_import_process">
+<Title>
+<Text id="190">Le processus d'import</Text>
+</Title>
+<Content>
+<Text id="191">Le processus d'import a pour but principal de convertir les documents depuis leur format d'origine vers le format d'archivage de Greenstone utilisÃ© de maniÃšre interne par Greenstone, et d'Ã©crire un fichier de compte-rendu (archives.inf) qui sera utilisÃ© lors de la construction de la collection. Le programme import.pl a besoin de connaÃ®tre les greffons (plugins) Ã  utiliser, et de savoir oÃ¹ trouver les fichiers des documents originaux. La tableÂ <CrossRef target="Table" ref="options_for_the_import_and_build_processes"/> montre les options communes aux processus d'import et de construction; la tableÂ <CrossRef target="Table" ref="additional_options_for_the_import_process"/> montre les options propres au processus d'import. L'option OIDtype mÃ©rite quelques explications. Chaque document dispose d'un identifiant d'objet associÃ©, ou OID (Object IDentifier). La meilleure faÃ§on de calculer un tel identifiant est de calculer une somme de contrÃŽle (Â«hacherÂ») le contenu du document (c'est la mÃ©thode hash). Cependant, cette mÃ©thode Ã©tant lente, il est possible de choisir une solution plus simple, incrÃ©mentale, qui se contente de numÃ©roter les documents sÃ©quentiellement dans leur ordre de fourniture (c'est la mÃ©thode incremental). Vous pouvez utiliser la mÃ©thode incremental pour aller plus vite, mais utilisez la mÃ©thode hash si vous avez l'intention d'ajouter des documents Ã  votre collection plus tard, sans recommencer tout le processus d'import.</Text>
+<Table id="additional_options_for_the_import_process">
+<Title>
+<Text id="192">Options propres au processus d'import</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="104">
+<Text id="193"><b>Argument</b></Text>
+</th>
+<th width="293">
+<Text id="194"><b>Fonction</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="195"><i>-importdir</i></Text>
+</th>
+<th width="104">
+<Text id="196">Nom de rÃ©pertoire</Text>
+</th>
+<th width="293">
+<Text id="197">SpÃ©cifie oÃ¹ trouver les contenus Ã  importer. La valeur par dÃ©faut est Defaults to<i>GSDLHOME/collect/nom_col/import</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="198"><i>-removeold</i></Text>
+</th>
+<th width="104">
+<Text id="199">Aucun</Text>
+</th>
+<th width="293">
+<Text id="200">Efface le contenu du rÃ©pertoire <i>archives</i>avant l'import.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="201"><i>-gzip</i></Text>
+</th>
+<th width="104">
+<Text id="202">Aucun</Text>
+</th>
+<th width="293">
+<Text id="203">Compresse l'archive de documents Greenstone produite par<i>import</i>(<i>ZIPPlug</i>doit faire partie de la liste des plugins greffons, et le programme<i>gzip</i>doit Ãªtre installÃ© sur votre machine).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="204"><i>-groupsize</i></Text>
+</th>
+<th width="104">
+<Text id="205">Nombre &gt;0</Text>
+</th>
+<th width="293">
+<Text id="206">Nombre de documents Ã  rassembler dans un fichier d'archive de Greenstone. La valeur par dÃ©faut est 1 (c'est-Ã -dire que chaque fichier ne renferme qu'un document).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="207"><i>âsortmeta</i></Text>
+</th>
+<th width="104">
+<Text id="208">Nom de balise de mÃ©ta-donnÃ©es</Text>
+</th>
+<th width="293">
+<Text id="209">Trie les documents par ordre alphabÃ©tique selon le contenu de la balise de mÃ©ta-donnÃ©es. Cette fonctionnalitÃ© est dÃ©sactivÃ©e si la collection compte plus d'un groupe (c'est-Ã -dire que<i>groupsize</i>&gt;1).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="210"><i>-OIDtype</i></Text>
+</th>
+<th width="104">
+<Text id="211"><i>hash</i>ou<br/>
+<i>incremental</i></Text>
+</th>
+<th width="293">
+<Text id="212">MÃ©thode de crÃ©ation des <i>OIDs</i>pour les documents:<i>hash</i>calcule une somme de contrÃŽle du contenu mais est lente;<i>incremental</i>se contente d'affecter des numÃ©ros de documents de maniÃšre sÃ©quentielle, elle est donc plus rapide.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Figure id="steps_in_the_import_process">
+<Title>
+<Text id="213">Ãtapes du processus d'import</Text>
+</Title>
+<File width="402" height="379" url="images/Dev_Fig_5.png"/>
+</Figure>
+<Text id="214">La figureÂ <CrossRef target="Figure" ref="steps_in_the_import_process"/> reprÃ©sente le processus d'import tel qu'implÃ©mentÃ© par le programme import.pl. Chaque ovale reprÃ©sente un module utilisÃ© pour mener Ã  bien les tÃ¢ches relatives Ã  une partie spÃ©cifique du systÃšme Greenstone. On peut trouver tous ces modules dans le rÃ©pertoire GSDLHOME/perllib.</Text>
+<Text id="215">Pour l'Ã©tape 3, remarquez que des variables d'import telles que importdir et archivedir peuvent Ãªtre positionnÃ©es dans le fichier de configuration de la collection ou depuis la ligne de commande. Si elles sont positionnÃ©es dans la ligne de commande, toute valeur spÃ©cifiÃ©e dans le fichier de configuration sera ignorÃ©e.</Text>
+<Text id="216">L'Ã©tape 6 voit la crÃ©ation du fichier d'information d'archives (archives.inf).</Text>
+<Text id="217">L'Ã©tape 7 crÃ©e un objet qui saura oÃ¹ sauvegarder les documents, et qui suivra toute instruction particuliÃšre de sauvegarde (telle que sortmeta, qui trie les documents selon une balise de mÃ©ta-donnÃ©es spÃ©cifiÃ©e).</Text>
+<Text id="218">La plupart du travail effectuÃ© par le processus d'import est en fait accompli par les greffons (plugins), qui sont appelÃ©s par le module plugin. Ce module met en place un pipe-line des greffons spÃ©cifiÃ©s dans le fichier de configuration de collection. Il gÃšre aussi l'Ã©criture des documents d'archive de Greenstone (en utilisant un objet document).</Text>
+</Content>
+</Subsection>
+<Subsection id="the_build_process">
+<Title>
+<Text id="219">Le processus de construction</Text>
+</Title>
+<Content>
+<Text id="220">Lors du processus de construction le texte est compactÃ©, et les index de corps du texte spÃ©cifiÃ©s dans le fichier de configuration de collection sont crÃ©Ã©s. De plus, les informations relatives Ã  la collection qui apparaÃ®tront sur le web sont prÃ©-calculÃ©es et incorporÃ©es dans la collectionÂ --Â il s'agit par exemple des informations relatives aux icones et aux titres, ainsi que des informations produites par des classificateurs. Le programme buildcol.pl partage de nombreuses options avec import.pl; elles sont dÃ©taillÃ©es dans la tableÂ <CrossRef target="Table" ref="options_for_the_import_and_build_processes"/>. La tableÂ <CrossRef target="Table" ref="additional_options_for_the_build_process"/> prÃ©sente les options qui lui sont propres.</Text>
+<Table id="additional_options_for_the_build_process">
+<Title>
+<Text id="221">Options propres au processus de construction</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="104">
+<Text id="222"><b>Argument</b></Text>
+</th>
+<th width="293">
+<Text id="223"><b>Fonction</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="224"><i>-builddir</i></Text>
+</th>
+<th width="104">
+<Text id="225">Nom de rÃ©pertoire</Text>
+</th>
+<th width="293">
+<Text id="226">SpÃ©cifie oÃ¹ trouver le rÃ©sultat de la construction (la valeur par dÃ©faut est<i>GSDLHOME/collect/nom_col/building</i>).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="227"><i>-index</i></Text>
+</th>
+<th width="104">
+<Text id="228">Nom d'index (ex.<br/>
+<i>section:Title</i>)</Text>
+</th>
+<th width="293">
+<Text id="229">SpÃ©cifie quels index construire. La valeur par dÃ©faut est l'ensemble des index indiquÃ©s dans le fichier de configuration de la collection.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="230"><i>-allclassifications</i></Text>
+</th>
+<th width="104">
+<Text id="231">Aucun</Text>
+</th>
+<th width="293">
+<Text id="232">EmpÃªche le processus de construction d'effacer les classifications qui ne contiennent aucun document (comme par exemple la classification Â«XÂ» dans les titres si aucun document n'a un titre commenÃ§ant par la lettre Â«XÂ»).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="233"><i>-create_images</i></Text>
+</th>
+<th width="104">
+<Text id="234">Aucun</Text>
+</th>
+<th width="293">
+<Text id="235">CrÃ©e automatiquement les icones de collection (pour utiliser ceci, il faut avoir installÃ© GIMP et le module Perl Gimp).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="236"><i>-mode</i></Text>
+</th>
+<th width="104">
+<Text id="237"><i>all</i>,<br/>
+<i>compress_text</i>,<br/>
+<i>infodb</i>, or<br/>
+<i>build_index</i></Text>
+</th>
+<th width="293">
+<Text id="238">DÃ©termine ce que le processus de construction doit faire (la valeur par dÃ©faut est<i>all</i>). Le mode<i>All</i>effectue une construction complÃšte,<i>compress_text</i>se contente de compacter le texte du document,<i>infodb</i>crÃ©e une base de donnÃ©es des informations relatives Ã  la collectionânom, fichiers, fichiers associÃ©s, informations de classification etc.âet<i>build_index</i>construit les index spÃ©cifiÃ©s dans le fichier de configuration de collection ou Ã  la ligne de commande.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="239"><i>âno_text</i></Text>
+</th>
+<th width="104"/>
+<th width="293">
+<Text id="240">Ne stocke pas de texte compactÃ©. Cette option est utile pour minimiser la taille des index construits si l'on souhaite toujours afficher les documents originaux au moment de l'exÃ©cution.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Figure id="steps_in_the_build_process">
+<Title>
+<Text id="241">Ãtapes du processus de construction</Text>
+</Title>
+<File width="308" height="234" url="images/Dev_Fig_6.png"/>
+</Figure>
+<Text id="242">Le diagramme de la figureÂ <CrossRef target="Figure" ref="steps_in_the_build_process"/> reprÃ©sente l'exÃ©cution du programme buildcol.pl. De nombreuses Ã©tapes sont communes avec le processus d'import. La premiÃšre Ã©tape qui diffÃšre est l'Ã©tape 4 (Ã  gauche sur la figure). Cette Ã©tape n'est effectuÃ©e que si l'option create_images a Ã©tÃ© activÃ©e. Les images sont alors crÃ©Ã©es et consignÃ©es dans le fichier de configuration de collection Ã  l'aide d'une fonction du script buildcol.pl. Pour que ceci fonctionne correctement, il faut avoir installÃ© et configurÃ© convenablement GIMP (GNU Image-Manipulation Program, programme de manipulation d'images de GNU) et le module Perl Gimp. Il faut aussi disposer d'un accÃšs en Ã©criture (et en lecture) sur le fichier de configuration de collection.</Text>
+<Text id="243">L'Ã©tape 5 contrÃŽle d'abord l'existence ou non d'une procÃ©dure de construction propre Ã  la collection. Certaines collections impliquent des traitements particuliers au moment de la construction, auquel cas il faut Ã©crire un constructeur propre Ã  la collection et le placer dans son rÃ©pertoire perllib, sous le nom de la collection auquel on aura concatÃ©nÃ© la chaÃ®ne Â«builderÂ» (constructeur). Les constructeurs propres aux collections hÃ©ritent de mgbuilder. Dans l'Ã©tape 5 le constructeur (qu'il s'agisse du constructeur par dÃ©faut ou d'un constructeur propre Ã  la collection) est initialisÃ© avec des informations telles que le nombre de documents Ã  inclure, s'il faut ou non garder l'ancienne version de la collection, et oÃ¹ les rÃ©pertoires building et archive sont localisÃ©s.</Text>
+<Text id="244">L'Ã©tape 6 est l'Ã©tape de construction, au cours de laquelle le texte des documents est compactÃ© et indexÃ©, les titres et les icones de collection sont stockÃ©s dans la base de donnÃ©es d'informations de la collection, et les structures de donnÃ©es sont construites pour supporter les classificateurs appelÃ©s par les greffons (plugins) de la collection. Toutes ces Ã©tapes sont menÃ©es Ã  bien par mgbuilder (ou un constructeur propre Ã  la collection), qui lui-mÃªme utilise MG (Managing Gigabytes (gÃ©rer les giga-octets), voir Witten<i>et al.</i>, 1999), logiciel de compression et d'indexation.</Text>
+<Text id="245">L'option mode permet de spÃ©cifier les portions de collection Ã  construire, mais par dÃ©faut tout est construit: texte compactÃ©, index, et base de donnÃ©es d'informations de la collection.</Text>
+<Text id="246">Pour publier une collection sur le web aprÃšs construction, il faut la dÃ©placer du rÃ©pertoire building vers le rÃ©pertoire index. Les collections ne sont pas construites directement dans le rÃ©pertoire index car des collections volumineuses peuvent prendre plusieurs heures ou jours Ã  construire. Il est important que le processus de construction n'affecte pas une copie existante de la collection tant qu'il n'est pas terminÃ©.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="greenstone_archive_documents">
+<Title>
+<Text id="247">Documents d'archives de Greenstone</Text>
+</Title>
+<Content>
+<Text id="248">Tous les documents source sont importÃ©s dans le systÃšme Greenstone aprÃšs conversion dans le format d'archivage de Greenstone. C'est un style XML qui divise les documents en sections, et qui peut renfermer des mÃ©ta-donnÃ©es au niveau du document ou de chaque section. Vous ne devriez pas avoir Ã  crÃ©er des fichiers d'archives de Greenstone manuellementÂ --Â c'est le travail des greffons (plugins) de traitement de documents dÃ©crits dans le chapitre suivant. Il est cependant utile de comprendre le format des fichiers Greenstone, et c'est pourquoi nous le dÃ©crivons ici.</Text>
+<Text id="249">En XML, les mots-clefs sont entourÃ©s de chevrons pour le balisage. Le format d'archivage de Greenstone encode des documents dÃ©jÃ  en HTML, et tout caractÃšre &lt;, &gt;, ou " compris dans le texte original est Ã©chappÃ© grÃ¢ce Ã  la convention standard &amp;lt;, &amp;gt;, et &amp;quot;.</Text>
+<Figure id="greenstone_archive_format">
+<Title>
+<Text id="250">Format d'archivage de Greenstone: (a) dÃ©finition de type de document (DTD); (b) document d'exemple</Text>
+<SubTitle>
+<Text id="251">(a)</Text>
+</SubTitle>
+</Title>
+<CodeLine>&lt;!DOCTYPE GreenstoneArchive [</CodeLine>
+<CodeLine>Â Â Â &lt;!ELEMENT Section (Description,Content,Section*)&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;!ELEMENT Description (Metadata*)&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;!ELEMENT Content (#PCDATA)&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;!ELEMENT Metadata (#PCDATA)&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;ATTLIST Metadata name CDATA #REQUIRED&gt;</CodeLine>
+<CodeLine>]&gt;</CodeLine>
+</Figure>
+<Figure id="greenstone_archive_format_1">
+<Title>
+<Text id="252"/>
+<SubTitle>
+<Text id="253">(b)</Text>
+</SubTitle>
+</Title>
+<CodeLine>&lt;?xml version="1.0"?&gt;</CodeLine>
+<CodeLine>&lt;!DOCTYPE GreenstoneArchive SYSTEM</CodeLine>
+<CodeLine>"http://greenstone.org/dtd/GreenstoneArchive/1.0/GreenstoneArchive.dtd" &gt;</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Metadata name= "gsdlsourcefilename"&gt;ec158e.txt&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Metadata name= "Title"&gt;Freshwater Resources in Arid Lands&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Metadata name= "Identifier"&gt;HASH0158f56086efffe592636058&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Metadata name= "gsdlassocfile"&gt;cover.jpg:image/jpeg:&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Metadata name= "gsdlassocfile"&gt;p07a.png:image/png:&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â &lt;Metadata name= "Title"&gt;Preface&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Content&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <i>This is the text of the preface</i>
+</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;/Content&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;/Section&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â &lt;Metadata name= "Title"&gt;First and only chapter&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &lt;Metadata name= "Title"&gt;Part 1&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â &lt;Content&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <i>This is the first part of the first and only chapter</i>
+</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â &lt;/Content&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;/Section&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â &lt;Metadata name= "Title"&gt;Part 2&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â &lt;Content&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <i>This is the second part of the first and only chapter</i>
+</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â &lt;/Content&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;/Section&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;/Section&gt;</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+</Figure>
+<Text id="254">La premiÃšre partie de la figureÂ <CrossRef target="Figure" ref="greenstone_archive_format"/> donne la dÃ©finition de type de document (DTD) pour le format d'archivage de Greenstone. Pour simplifier, un document est divisÃ© en Ã©lÃ©ments Section, et les sections peuvent Ãªtre imbriquÃ©es. Chaque Section renferme une Description qui comprend zÃ©ro ou plusieurs Ã©lÃ©ments Metadata (mÃ©ta-donnÃ©es), et un Ã©lÃ©ment Content (contenu), qui peut Ãªtre vide, et qui renferme les donnÃ©es du document Ã  proprement parler. Ã chaque Ã©lÃ©ment Metadata on associe un attribut de nom (dont le nom est libre), et des donnÃ©es textuelles. En XML, PCDATA signifie Â«parsed character dataÂ» (donnÃ©es de type caractÃšre analysÃ©es), c'est-Ã -dire du texte, tout simplement.</Text>
+<Text id="255">La deuxiÃšme partie de la figureÂ <CrossRef target="Figure" ref="greenstone_archive_format_1"/> montre un document simple Ã©crit dans ce format, qui est un petit livre avec deux images associÃ©es. Le livre consiste en deux sections appelÃ©es respectivement PrÃ©face et Premier et unique chapitre, la deuxiÃšme section se divisant en deux sous-sections. Remarquez qu'il n'existe aucune notion de Â«chapitreÂ» en tant que tel: un chapitre est simplement reprÃ©sentÃ© comme une section de premier niveau.</Text>
+<Table id="greenstone_archive_format_values">
+<Title>
+<Text id="256">Format d'archivage de Greenstone: valeurs pour l'attribut<i>name</i>de la balise<i>Metadata</i></Text>
+</Title>
+<TableContent>
+<tr>
+<th width="130">
+<Text id="257"><i>gsdlsourcefilename</i></Text>
+</th>
+<th width="400">
+<Text id="258">Fichier original Ã  partir duquel on a gÃ©nÃ©rÃ© le fichier d'archive de Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th width="130">
+<Text id="259"><i>gsdlassocfile</i></Text>
+</th>
+<th width="400">
+<Text id="260">Fichier associÃ© au document (un fichier d'image par exemple)</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="261">La balise &lt;Section&gt; dÃ©note le dÃ©but de chaque section de document, et la balise fermante correspondante (&lt;/Section&gt;) marque la fin de cette section. Ã la suite de chaque balise &lt;Section&gt; on trouve un Ã©lÃ©ment &lt;Description&gt;. S'y trouve un nombre quelconque d'Ã©lÃ©ments &lt;Metadata&gt;. On peut ainsi associer diffÃ©rentes mÃ©ta-donnÃ©es Ã  diffÃ©rentes sections du document. La plupart de ces mÃ©ta-donnÃ©es sont des types particuliers de mÃ©ta-donnÃ©es tels que &lt;Title&gt; (titre). Les deux valeurs de l'attribut name (nom) montrÃ©es dans la tableÂ <CrossRef target="Table" ref="greenstone_archive_format_values"/> reÃ§oivent de Greenstone un traitement particulier; toutes les autres sont considÃ©rÃ©es comme des mÃ©ta-donnÃ©es attachÃ©es Ã  cette section.</Text>
+<Text id="262">Dans certaines collections les documents dont divisÃ©s en pages. Ces derniÃšres sont alors traitÃ©es comme des sections. Un livre peut par exemple disposer de sections de premier niveau qui correspondent Ã  des chapitres, au sein desquels on trouvera un certain nombre de Â«sectionsÂ» qui correspondront en rÃ©alitÃ© aux diffÃ©rentes pages du chapitre.</Text>
+<Subsection id="document_metadata">
+<Title>
+<Text id="263">MÃ©ta-donnÃ©es de document</Text>
+</Title>
+<Content>
+<Text id="264">Les mÃ©ta-donnÃ©es sont des informations de description associÃ©es Ã  un document telles que l'auteur, le titre, la date, des mots-clefs, etc. Nous avons dÃ©jÃ  signalÃ© que les mÃ©ta-donnÃ©es Ã©taient stockÃ©es avec les documents. En observant la figureÂ <CrossRef target="Figure" ref="greenstone_archive_format"/>, on remarque que les balises &lt;Metadata&gt; spÃ©cifient le nom du type de mÃ©ta-donnÃ©es, et lui donnent une valeur. On a par exemple la ligne &lt;Metadata name="Title"&gt;Premier et unique chapitre&lt;/Metadata&gt; dans la deuxiÃšme partie de la figureÂ <CrossRef target="Figure" ref="greenstone_archive_format_1"/>Â --Â le titre d'un document est une mÃ©ta-donnÃ©e qui lui est associÃ©e. On utilise le standard de mÃ©ta-donnÃ©es Dublin Core pour dÃ©finir des types de mÃ©ta-donnÃ©es (Dublin Core, 2001; Weibel, 1999; Thiele, 1997).</Text>
+<Text id="265">La tableÂ <CrossRef target="Table" ref="dublin_core_metadata_standard"/> montre les types disponibles dans le standard, les Ã©toiles signalant les entrÃ©es disponibles Ã  ce jour sur le site web de la bibliothÃšque numÃ©rique de Nouvelle-ZÃ©lande. Si aucun type ne dÃ©crit correctement un certain type de mÃ©ta-donnÃ©es, on peut aussi utiliser des types de mÃ©ta-donnÃ©es absentes du standard Dublin Core. La collection Â«DemoÂ» contient par exemple les mÃ©ta-donnÃ©es how to (comment faire) et Magazine.</Text>
+<Table id="dublin_core_metadata_standard">
+<Title>
+<Text id="266">Standard de mÃ©ta-donnÃ©es</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="133">
+<Text id="267"><b>Nom</b></Text>
+</th>
+<th width="94">
+<Text id="268"><b>Balise de mÃ©ta-donnÃ©es</b></Text>
+</th>
+<th width="305">
+<Text id="269"><b>DÃ©finition</b></Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="270">*Title</Text>
+</th>
+<th width="94">
+<Text id="271">Title</Text>
+</th>
+<th width="305">
+<Text id="272">Nom donnÃ© Ã  la ressource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="273">*CrÃ©ateur</Text>
+</th>
+<th width="94">
+<Text id="274"><i>Creator</i></Text>
+</th>
+<th width="305">
+<Text id="275">EntitÃ© principalement responsable de la fabrication du contenu de la ressource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="276">*ThÃšme et mots-clefs</Text>
+</th>
+<th width="94">
+<Text id="277"><i>Subject</i></Text>
+</th>
+<th width="305">
+<Text id="278">ThÃšme du contenu de la ressource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="279">*Description</Text>
+</th>
+<th width="94">
+<Text id="280"><i>Description</i></Text>
+</th>
+<th width="305">
+<Text id="281">Compte-rendu du contenu de la ressource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="282">*Ãditeur</Text>
+</th>
+<th width="94">
+<Text id="283"><i>Publisher</i></Text>
+</th>
+<th width="305">
+<Text id="284">EntitÃ© responsable de la publication de la ressource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="285">Contributeur</Text>
+</th>
+<th width="94">
+<Text id="286"><i>Contributor</i></Text>
+</th>
+<th width="305">
+<Text id="287">EntitÃ© responsable de contributions au contenu de la ressource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="288">*Date</Text>
+</th>
+<th width="94">
+<Text id="289"><i>Date</i></Text>
+</th>
+<th width="305">
+<Text id="290">Date de publication de la ressource ou toute autre date importante associÃ©e Ã  la ressource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="291">Type de ressource</Text>
+</th>
+<th width="94">
+<Text id="292"><i>Type</i></Text>
+</th>
+<th width="305">
+<Text id="293">Nature ou genre du contenu de la ressource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="294">Format</Text>
+</th>
+<th width="94">
+<Text id="295"><i>Format</i></Text>
+</th>
+<th width="305">
+<Text id="296">ReprÃ©sentation physique ou numÃ©rique de la ressource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="297">*Identificateur de resource</Text>
+</th>
+<th width="94">
+<Text id="298"><i>Identifier</i></Text>
+</th>
+<th width="305">
+<Text id="299">RÃ©fÃ©rence univoque Ã  la ressource dans un contexte donnÃ©: il s'agit de l'identifiant d'objet, ou<i>OID</i></Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="300">*Source</Text>
+</th>
+<th width="94">
+<Text id="301"><i>Source</i></Text>
+</th>
+<th width="305">
+<Text id="302">RÃ©fÃ©rence Ã  une ressource d'oÃ¹ la prÃ©sente ressource est tirÃ©e</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="303">*Langue</Text>
+</th>
+<th width="94">
+<Text id="304"><i>Language</i></Text>
+</th>
+<th width="305">
+<Text id="305">Langue du contenu intellectuel de la ressource </Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="306">Relation</Text>
+</th>
+<th width="94">
+<Text id="307"><i>Relation</i></Text>
+</th>
+<th width="305">
+<Text id="308">RÃ©fÃ©rence Ã  une ressource liÃ©e</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="309">*Couverture</Text>
+</th>
+<th width="94">
+<Text id="310"><i>Coverage</i></Text>
+</th>
+<th width="305">
+<Text id="311">PortÃ©e ou Ã©tendue du contenu de la ressource</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="312">Gestion des droits</Text>
+</th>
+<th width="94">
+<Text id="313"><i>Rights</i></Text>
+</th>
+<th width="305">
+<Text id="314">Informations sur les droits attachÃ©s Ã  la ressource ou dans celle-ci</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+<Subsection id="inside_greenstone_archive_documents">
+<Title>
+<Text id="315">Au coeur des documents d'archive de Greenstone</Text>
+</Title>
+<Content>
+<Text id="316">Le format d'archivage de Greenstone impose peu de structure aux documents individuels. Les document sont divisÃ©s en paragraphes. Ils peuvent Ãªtre divisÃ©s hiÃ©rarchiquement en sections et en sous-sections, que l'on peut imbriquer jusqu'Ã  une profondeur arbitraire. Ã chaque document est associÃ© un identifiant de document ou OIDÂ --Â ces derniers servant aussi Ã  identifier les sections et les sous-sections par l'ajout de numÃ©ros de sections et de sous-sections, sÃ©parÃ©s par des points, Ã  l'OID du document. On se rÃ©fÃ©rera par exemple Ã  la sous-section 3 de la section 2 du document HASHa7 sous la forme HASHa7.2.3.</Text>
+<Text id="317">Quand on lit un livre dans une collection de Greenstone, la hiÃ©rarchie des sections est reportÃ©e dans la table des matiÃšres du livre. Les livres de la collection Â«DemoÂ», par exemple, disposent d'une table des matiÃšres hiÃ©rarchique qui montre des chapitres, des sections, et des sous-sections, comme l'illustre la figureÂ <CrossRef target="Figure" ref="hierarchical_structure_in_the_demo_collection"/>. Les documents de la collection Computer Science Technical Reports (rapports techniques en informatique) ne disposent pas d'une structure hiÃ©rarchique de sections, mais chaque document est divisÃ© en pages et on peut naviguer parmi les pages d'un document rapatriÃ©. Les chapitres, les sections, les sous-sections, et les pages sont tous simplement implÃ©mentÃ©s en tant que Â«sectionsÂ» au sein du document.</Text>
+<Figure id="hierarchical_structure_in_the_demo_collection">
+<Title>
+<Text id="318">Structure hiÃ©rarchique de la collection Â«DemoÂ»</Text>
+<SubTitle>
+<Text id="318a">(a)</Text>
+</SubTitle>
+</Title>
+<File width="373" height="251" url="images/Dev_Fig_8a.png"/>
+</Figure>
+<Figure id="hierarchical_structure_in_the_demo_collection_1">
+<Title>
+<Text id="318b">Structure hiÃ©rarchique de la collection Â«DemoÂ»</Text>
+<SubTitle>
+<Text id="318c">(b)</Text>
+</SubTitle>
+</Title>
+<File width="373" height="251" url="images/Dev_Fig_8b.png"/>
+</Figure>
+<Text id="319">La structure de document sert aussi aux index de recherche. Il existe trois niveaux possibles d'index:<i>document</i>,<i>section</i>, et<i>paragraphe</i>, bien que la plupart des collections ne les utilisent pas tous trois. Un index de<i>document</i>contient tout le documentÂ --Â on peut l'utiliser pour trouver tous les documents contenant un ensemble particulier de mots (qui peuvent alors Ãªtre Ã©parpillÃ©s tout au long du document, loin les uns des autres). Lors de la crÃ©ation d'un index de<i>section</i>, toute portion de texte indexÃ©e s'Ã©tend d'une balise ouvrante &lt;Section&gt; Ã  la prochaine balise &lt;Section&gt;Â --Â un chapitre qui dÃ©bute immÃ©diatement par une autre section crÃ©era donc un document vide dans l'index. Les sections et les sous-sections sont traitÃ©es de la mÃªme maniÃšre: la structure hiÃ©rarchique de document est aplatie dans le but de crÃ©er des index de recherche. Les index de<i>paragraphe</i>considÃšrent chaque paragraphe comme un document Ã  part entiÃšre, et sont utiles pour mener des recherches plus ciblÃ©es.</Text>
+<Text id="320">Le menu dÃ©roulant de la figureÂ <CrossRef target="Figure" ref="hierarchical_structure_in_the_demo_collection_1"/> montre les index de recherche de la collection Â«DemoÂ». Les chapitres et les titres des sections sont des index au niveau de la section. alors que les livres entiers reprÃ©sentent des index au niveau des documents. Ã l'instar des index de texte, on peut crÃ©er des index pour tout type de mÃ©ta-donnÃ©es. Certaines collections proposent par exemple des exemples des titres de sections, comme illustrÃ© sur la figureÂ <CrossRef target="Figure" ref="hierarchical_structure_in_the_demo_collection_1"/>.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="configuration_file">
+<Title>
+<Text id="321">Fichier de configuration de la collection</Text>
+</Title>
+<Content>
+<Text id="322">Le fichier de configuration de la collection gouverne la structure de la collection telle qu'elle est vue par l'utilisateur, ce qui permet d'en personnaliser l'apparence et l'ergonomie, ainsi que la maniÃšre dont ses documents sont traitÃ©s et prÃ©sentÃ©s. Le programme mkcol.pl crÃ©e un fichier de configuration de collection simple, en enregistrant votre adresse de courrier Ã©lectronique en tant que crÃ©ateur et mainteneur. Nous avons vu lors de l'exploration pas Ã  pas du processus en ligne de commande que le crÃ©ateur est un argument obligatoire, et il sera Ã©galement enregistrÃ© en tant que mainteneur sauf si on fournit cette information sÃ©parÃ©ment.</Text>
+<Table id="items_in_the_collection_configuration_file">
+<Title>
+<Text id="323">ÃlÃ©ments du fichier de configuration de la collection</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<CodeLine>creator</CodeLine>
+</th>
+<th width="397">
+<Text id="324">Adresse de courrier Ã©lectronique du crÃ©ateur de la collection</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>maintainer</i></CodeLine>
+</th>
+<th width="397">
+<Text id="325">Adresse de courrier Ã©lectronique du mainteneur de la collection</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>public</i></CodeLine>
+</th>
+<th width="397">
+<Text id="326">La collection doit-elle Ãªtre rendue publique ou non?</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>beta</i></CodeLine>
+</th>
+<th width="397">
+<Text id="327">La collection est-elle une version bÃªta ou non? </Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>indexes</i></CodeLine>
+</th>
+<th width="397">
+<Text id="328">Liste des index Ã  construire</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>defaultindex</i></CodeLine>
+</th>
+<th width="397">
+<Text id="329">Index par dÃ©faut</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>subcollection</i></CodeLine>
+</th>
+<th width="397">
+<Text id="330">DÃ©finit une sous-collection fondÃ©e sur des mÃ©ta-donnÃ©es </Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>indexsubcollections</i></CodeLine>
+</th>
+<th width="397">
+<Text id="331">SpÃ©cifie quelles sous-collections indexer</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>defaultsubcollection</i></CodeLine>
+</th>
+<th width="397">
+<Text id="332">L'<i>indexsubcollection</i>par dÃ©faut</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>languages</i></CodeLine>
+</th>
+<th width="397">
+<Text id="333">Liste des langues dans lesquelles construire des index</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>defaultlanguage</i></CodeLine>
+</th>
+<th width="397">
+<Text id="334">Index de langue par dÃ©faut</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>collectionmeta</i></CodeLine>
+</th>
+<th width="397">
+<Text id="335">DÃ©finit des mÃ©ta-donnÃ©es au niveau de la collection</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>plugin</i></CodeLine>
+</th>
+<th width="397">
+<Text id="336">SpÃ©cifie un greffon (\lang{plugin}) Ã  utiliser au moment de la construction </Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>format</i></CodeLine>
+</th>
+<th width="397">
+<Text id="337">ChaÃ®ne de formatage (notion expliquÃ©e ci-dessous) </Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>classify</i></CodeLine>
+</th>
+<th width="397">
+<Text id="338">SpÃ©cifie un classificateur Ã  utiliser au moment de la construction</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="339">Chaque ligne du fichier de configuration de collection est sur le modÃšle de la paire Â«attribut, valeurÂ». Chaque attribut donne une information sur la collection qui affecte la maniÃšre dont elle sera reprÃ©sentÃ©e ou dont les documents seront traitÃ©s. La tableÂ <CrossRef target="Table" ref="items_in_the_collection_configuration_file"/> montre les Ã©lÃ©ments que l'on peut inclure dans un fichier de configuration de collection, et Ã  quoi sert chaque Ã©lÃ©ment. En plus de ceux-ci, on peut aussi spÃ©cifier toutes les options de ligne de commande des programmes import.pl et buildcol.pl dans un fichier de configuration de collection. Par exemple, une ligne disant no_text true (true signifie Â«vraiÂ» ou Â«activÃ©Â» dans ce contexte) positionnera l'option no_text du programme buildcol.pl.</Text>
+<Text id="340">Le fichier de configuration de collection crÃ©Ã© par le script mkcol.pl et prÃ©sentÃ© tableÂ <CrossRef target="Table" ref="collection_configuration_file_created_by_mkcd"/>, est trÃšs simple et ne contient que le strict minimum d'informations. Les lignes 1 et 2 proviennent de la valeur de creator fournie au programme mkcol.pl, et renferment les adresses de courrier Ã©lectronique des responsables de la crÃ©ation et de la maintenance de la collection (qui peuvent Ãªtre distincts).</Text>
+<Table id="collection_configuration_file_created_by_mkcd">
+<Title>
+<Text id="341">Fichier de configuration de collection crÃ©Ã© par<i>mkcd.pl</i></Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="342"><b>Attribute</b></Text>
+</th>
+<th width="265">
+<Text id="343"><b>Valeur</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>1</CodeLine>
+</th>
+<th width="132">
+<CodeLine>creator</CodeLine>
+</th>
+<th width="265">
+<Text id="344">utilisateur@email.com</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>2</CodeLine>
+</th>
+<th width="132">
+<CodeLine>maintainer</CodeLine>
+</th>
+<th width="265">
+<Text id="345">utilisateur@email.com</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>3</CodeLine>
+</th>
+<th width="132">
+<CodeLine>public</CodeLine>
+</th>
+<th width="265">
+<Text id="346">True</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>4</CodeLine>
+</th>
+<th width="132">
+<CodeLine>beta</CodeLine>
+</th>
+<th width="265">
+<Text id="347">True</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>5</CodeLine>
+</th>
+<th width="132">
+<CodeLine>indexes</CodeLine>
+</th>
+<th width="265">
+<Text id="348">document:text</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>6</CodeLine>
+</th>
+<th width="132">
+<CodeLine>defaultindex</CodeLine>
+</th>
+<th width="265">
+<Text id="349">document:text</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>7</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="350">ZIPPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>8</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="351">GAPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>9</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="352">TextPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>10</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="353">HTMLPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>11</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="354">EMAILPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>12</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="355">ArcPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>13</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="356">RecPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>14</CodeLine>
+</th>
+<th width="132">
+<CodeLine>classify</CodeLine>
+</th>
+<th width="265">
+<Text id="357">AZList metadata Title</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>15</CodeLine>
+</th>
+<th width="132">
+<CodeLine>collectionmeta</CodeLine>
+</th>
+<th width="265">
+<Text id="358">collectionname "collection d'exemple"</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>16</CodeLine>
+</th>
+<th width="132">
+<CodeLine>collectionmeta</CodeLine>
+</th>
+<th width="265">
+<Text id="359">iconcollection ""</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>17</CodeLine>
+</th>
+<th width="132">
+<CodeLine>collectionmeta</CodeLine>
+</th>
+<th width="265">
+<Text id="360">collectionextra ""</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>18</CodeLine>
+</th>
+<th width="132">
+<CodeLine>collectionmeta</CodeLine>
+</th>
+<th width="265">
+<Text id="361">.document:text "documents"</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="362">La ligne 3 indique si la collection sera accessible au public aprÃšs construction, et peut prendre les valeurs true (valeur par dÃ©faut, qui signifie que la collection sera publiquement disponible), ou false (qui signifie que cela ne sera pas le cas). C'est utile lorsque l'on construit des collections pour tester le logiciel, ou pour usage personnel. La ligne 4 indique si la collection est une version bÃªta ou non (la valeur par dÃ©faut ici aussi est true, ce qui signifie que la collection est une version bÃªta).</Text>
+<Text id="363">La ligne 5 dÃ©termine les index de collection Ã  crÃ©er au moment de la construction: dans cet exemple, seul le texte du document sera indexÃ©. Il existe trois niveaux possibles d'index:<i>document</i>,<i>section</i>, et<i>paragraphe</i>(paragraph en anglais). Ils peuvent contenir les donnÃ©es au format texte (text) ou dans toute mÃ©ta-donnÃ©eÂ --Â la plus commune est le titre (Title). On spÃ©cifie un index en prÃ©cisant niveaudonnÃ©es. Par exemple, pour inclure Ã©galement un index des titres de sections, il faudrait remplacer la ligne 5 par indexes documenttext sectionTitle. On inclut plusieurs types de donnÃ©es dans le mÃªme index en les sÃ©parant par des virgules. Pour crÃ©er par exemple un index au niveau de la section de titres, de texte et de dates, il faudrait avoir en ligne 5 indexes sectiontext,Title,Date. Le defaultindex dÃ©fini en ligne 6 est l'index Ã  utiliser par dÃ©faut sur la page de recherche de la collection.</Text>
+<Text id="364">Les lignes 7 Ã  13 spÃ©cifient les greffons (plugins) Ã  utiliser lors de la conversion de documents vers le format d'archivage de Greenstone et lors de la construction de collections depuis des fichiers d'archives. La sectionÂ <CrossRef target="Section" ref="plugins"/> dÃ©taille les greffons disponibles. L'ordre dans lequel les greffons sont listÃ©s est l'ordre dans lequel ils sont appliquÃ©s sur chaque document. DÃšs qu'un greffon a Ã©tÃ© capable de traiter un document, les suivants de la liste ne sont pas appelÃ©s.</Text>
+<Text id="365">La ligne 14 spÃ©cifie qu'il faudra crÃ©er une liste alphabÃ©tique des titres Ã  des fins de navigation. Les structures de navigation sont construites par des Â«classificateursÂ». La sectionÂ <CrossRef target="Section" ref="classifiers"/> dÃ©taille les classificateurs et leurs possibilitÃ©s.</Text>
+<Text id="366">Les lignes 15 Ã  18 servent Ã  spÃ©cifier les mÃ©ta-donnÃ©es au niveau de la collection. L'attribut collectionname dÃ©finit la forme longue du nom de la collection, qui sera utilisÃ©e en tant que Â«titreÂ» pour le navigateur web. L'attribut collectionicon donne l'URL de l'icone de la collection. Si comme ligne 18 on spÃ©cifie un index, la chaÃ®ne suivante sera affichÃ©e comme le nom de cet index sur la page de recherche de la collection. Une mÃ©ta-donnÃ©e au niveau de la collection particuliÃšrement importante est collectionextra, qui fournit un texte, entourÃ© d'apostrophes doubles, dÃ©crivant la collection. Il servira de texte pour le paragraphe Â«Ã  proposÂ». On peut fournir diffÃ©rentes versions de l'attribut collectionextra pour diffÃ©rentes langues d'interface en ajoutant une spÃ©cification de langue entre crochets. Par exemple, </Text>
+<Indented>
+<Text id="367">collectionmeta collectionextra "collection description"</Text>
+</Indented>
+<Indented>
+<Text id="368">collectionmeta collectionextra [l=fr] "description en franÃ§ais"</Text>
+</Indented>
+<Indented>
+<Text id="369">collectionmeta collectionextra [l=mi] "description en maori"</Text>
+</Indented>
+<Text id="370">Si la langue d'interface est positionnÃ©e Ã  Â«frÂ» ou Â«miÂ», la version appropriÃ©e de la description sera affichÃ©e. Pour d'autres langues c'est la version par dÃ©faut qui apparaÃ®tra. </Text>
+<Text id="371">Ce fichier de configuration de collection simple ne fournit aucun exemple de chaÃ®ne de formatage, ni des possibilitÃ©s de sous-collection et de langue proposÃ©es par le fichier de configuration. Les chaÃ®nes de format seront couvertes plus en dÃ©tail dans la sectionÂ <CrossRef target="Section" ref="formatting_greenstone_output"/>, mais nous traiterons des sous-collections et des langues ici-mÃªme.</Text>
+<Subsection id="subcollections">
+<Title>
+<Text id="372">Sous-collections</Text>
+</Title>
+<Content>
+<Text id="373">Greenstone permet de dÃ©finir des sous-collections et de construire des index sÃ©parÃ©s pour chacune d'entre elles. Une collection comprend par exemple un sous-ensemble important de documents appelÃ© Food and Nutrition Bulletin (bulletin de la nourriture et de la nutrition). Nous l'utiliserons en tant qu'exemple.</Text>
+<Text id="374">Cette collection compte trois index, tous trois au niveau de la section: le premier pour toute la collection, le deuxiÃšme pour le Food and Nutrition Bulletin, et le troisiÃšme pour les documents restants. On peut lire ci-aprÃšs les lignes concernÃ©es du fichier de configuration de collection:</Text>
+<CodeLine>indexes                           section:text</CodeLine>
+<CodeLine>subcollection               fn "Title/^Food and Nutrition Bulletin/i "</CodeLine>
+<CodeLine>subcollection               other "!Title/^Food and Nutrition Bulletin/i "</CodeLine>
+<CodeLine>indexsubcollections fn   other   fn,other</CodeLine>
+<Text id="375">Les lignes deux et trois dÃ©finissent des sous-collections appelÃ©es fn, qui contiendra les documents du Food and Nutrition Bulletin, et other, qui contiendra les documents restants. Le troisiÃšme champ de ces dÃ©finitions est une expression rationnelle de Perl qui identifie ces sous-ensembles en utilisant la mÃ©ta-donnÃ©e Title: on recherche des titres qui commencent par Food and Nutrition Bulletin dans le premier cas, et les titres qui ne commencent pas ainsi dans le second (remarquez le "!" de nÃ©gation). L'i final rend la reconnaissance de motif indÃ©pendante de la casse: majuscules et minuscules seront confondues. Le champ de mÃ©ta-donnÃ©es, qui dans le cas prÃ©sent est Title, peut Ãªtre n'importe quel champ valide, ou Filename (nom de fichier) pour reconnaÃ®tre le nom de fichier original du document. La quatriÃšme ligne, indexsubcollections, spÃ©cifie trois index: un pour la collection fn, un pour la sous-collection other, et le troisiÃšme pour les deux sous-collections (c'est-Ã -dire pour tous les documents). Remarquez que si deux entrÃ©es avaient Ã©tÃ© spÃ©cifiÃ©es sur la premiÃšre ligne, indexes, le nombre total d'index gÃ©nÃ©rÃ©s aurait Ã©tÃ© de six et non pas de trois.</Text>
+<Text id="376">Si une collection contient des documents dans des langues diffÃ©rentes, on peut construire des index sÃ©parÃ©s pour chaque langue. La langue est une mÃ©ta-donnÃ©e; les valeurs sont spÃ©cifiÃ©es Ã  l'aide des codes en deux lettres du standard ISOÂ 639 reprÃ©sentant les noms des languesÂ --Â par exemple, en est l'anglais, fr le franÃ§ais, zh le chinois, et mi le maori. Ãtant donnÃ© que l'on peut spÃ©cifier des valeurs de mÃ©ta-donnÃ©es au niveau de la section, on peut avoir certaines portions de documents dans des langues diffÃ©rentes.</Text>
+<Text id="377">Si par exemple le fichier de configuration contenait</Text>
+<CodeLine>indexes section:text section:Title document:text paragraph:text</CodeLine>
+<CodeLine>languages en zh mi</CodeLine>
+<Text id="378">les index de texte de sections, de titres de sections, de texte de document et de texte de paragraphe seraient crÃ©Ã©s en anglais, en chinois, et en maoriÂ --Â pour un total de douze index. Si on ajoute quelques sous-collections, voilÃ  qui augmente d'autant le nombre d'index, et d'une multiplication! Il faut prendre garde Ã  la surenchÃšre des index.</Text>
+<Text id="379">(On pourrait obtenir une telle spÃ©cification d'index avec subcollection plutÃŽt qu'avec la fonctionnalitÃ© languages. Mais la syntaxe excluant la crÃ©ation de sous-collections de sous-collections, il serait alors impossible d'indexer chaque langue sÃ©parÃ©ment dans chaque sous-collection.)</Text>
+</Content>
+</Subsection>
+<Subsection id="cross-collection_searching">
+<Title>
+<Text id="380">Recherche inter-collections</Text>
+</Title>
+<Content>
+<Text id="381">Greenstone propose une fonctionnalitÃ© de recherche transverse aux collections, qui permet d'effectuer une recherche parmi plusieurs collections Ã  la fois, et de combiner les rÃ©sultats en coulisses de maniÃšre Ã  donner Ã  l'utilisateur l'impression qu'il a menÃ© sa recherche dans une unique collection unifiÃ©e. On peut rechercher tout sous-ensemble de collections: la page de PrÃ©fÃ©rences laisse choisir quelles collections inclure dans les recherches.</Text>
+<Text id="382">On active la recherche inter-collections par une ligne</Text>
+<CodeLine>supercollection col _1 col _2 âŠ.</CodeLine>
+<Text id="383">oÃ¹ les collections impliquÃ©es sont appelÃ©es col_1, col_2, ... La mÃªme ligne devrait apparaÃ®tre dans les fichiers de configuration de toutes les collections impliquÃ©es.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="getting_the_most_out_of_your_documents">
+<Title>
+<Text id="384">Exploitez vos documents au maximum</Text>
+</Title>
+<Content>
+<Text id="385">On peut individualiser les collections pour rendre accessibles les informations qu'elles contiennent de diverses maniÃšres. Le prÃ©sent chapitre dÃ©crit la maniÃšre dont Greenstone extrait l'information des documents et la prÃ©sente Ã  l'utilisateur: le traitement des documents (sectionÂ <CrossRef target="Section" ref="plugins"/>), les structures de classification (sectionÂ <CrossRef target="Section" ref="classifiers"/>), et les outils d'interface utilisateur (sectionsÂ <CrossRef target="Section" ref="formatting_greenstone_output"/> etÂ <CrossRef target="Section" ref="controlling_the_greenstone_user_interface"/>).</Text>
+<Section id="plugins">
+<Title>
+<Text id="386">Greffons (plugins)</Text>
+</Title>
+<Content>
+<Text id="387">Les greffons analysent les documents importÃ©s et en extraient les mÃ©ta-donnÃ©es. Par exemple, le greffon HTML convertit des pages HTML en format d'archivage de Greenstone et extrait les mÃ©ta-donnÃ©es explicites dans le format de documentÂ --Â telles que les titres, entourÃ©s de balises &lt;title&gt;&lt;/title&gt;. </Text>
+<Text id="388">Les greffons sont Ã©crits en Perl. Ils sont tous inspirÃ©s d'un greffon de base appelÃ© BasPlug, qui effectue les opÃ©rations partout nÃ©cessaires, telles que crÃ©er un nouveau document d'archive de Greenstone avec lequel travailler, affecter un identifiant d'objet (OID), et gÃ©rer les sections d'un document. Les greffons se trouvent dans le rÃ©pertoire perllib/plugins.</Text>
+<Text id="389">Pour en savoir plus sur un greffon particulier, tapez<i>pluginfo.pl nom-de-greffon</i>Ã  l'invite de commandes (il vous faudra d'abord invoquer le script de rÃ©glages appropriÃ© si vous ne l'avez pas encore fait, et sous Windows il vous faudra taper perl -S pluginfo.pl plugin-name si votre environnement n'est pas rÃ©glÃ© pour associer les fichiers se terminant en .pl Ã  l'interprÃ©teur Perl). Ceci affichera des informations relatives au greffon Ã  l'Ã©cranÂ --Â les options spÃ©cifiques qu'il accepte, et quelles options gÃ©nÃ©rales sont autorisÃ©es.</Text>
+<Text id="390">On peut facilement Ã©crire de nouveaux greffons qui traitent des formats de documents non couverts par les greffons existants, mettent les documents en forme d'une maniÃšre particuliÃšre, ou extraient un nouveau type de mÃ©ta-donnÃ©es.</Text>
+<Subsection id="general_options">
+<Title>
+<Text id="391">Options gÃ©nÃ©rales</Text>
+</Title>
+<Content>
+<Text id="392">La tableÂ <CrossRef target="Table" ref="options_applicable_to_all_plugins"/> montre les options acceptÃ©es par tout greffon hÃ©ritant de BasPlug.</Text>
+<Table id="options_applicable_to_all_plugins">
+<Title>
+<Text id="393">Options valables pour tous les greffons</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<CodeLine><i>input_encoding</i></CodeLine>
+</th>
+<th width="397">
+<Text id="394">Encodage de caractÃšres utilisÃ© dans les documents source. Par dÃ©faut Greenstone devine automatiquement l'encodage utilisÃ© dans chaque document. Il est parfois utile cependant de positionner cette valeur: si par exemple vous savez que tous vos documents sont en ASCII brut, positionner l'encodage en entrÃ©e Ã  la valeur<i>ascii</i>augmentera considÃ©rablement la vitesse d'import et de construction de votre collection. Il existe de nombreuses valeurs possibles; tapez<i>pluginfo.pl BasPlug</i>pour en obtenir la liste complÃšte.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>default_encoding</i></CodeLine>
+</th>
+<th width="397">
+<Text id="395">L'encodage utilisÃ© si<i>input_encoding</i>vaut<i>auto</i>et que la dÃ©tection automatique d'encodage Ã©choue.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>process_exp</i></CodeLine>
+</th>
+<th width="397">
+<Text id="396">Une expression rationnelle de Perl Ã  utiliser sur les noms de fichier (pour localiser par exemple un certain type d'extension de fichier). Ceci dicte les fichiers qu'un greffon doit traiter. Chaque greffon dispose d'une valeur par dÃ©faut (la valeur par dÃ©faut de<i>HTMLPlug</i>est<i>(?i).html?</i>âc'est-Ã -dire tout fichier d'extension<i>.htm</i>ou<i>.html</i>).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>block_exp</i></CodeLine>
+</th>
+<th width="397">
+<Text id="397">Une expression rationnelle de Perl Ã  utiliser sur les noms de fichier qui ne doivent pas Ãªtre passÃ©s aux greffons suivants. Ceci peut Ã©viter l'apparition d'ennuyeux messages d'erreur qui ne vous intÃ©ressent pas. Certains greffons disposent d'expressions de blocage par dÃ©fautâpar exemple, le greffon<i>HTMLPlug</i>bloque les fichiers d'extensions<i>.gif</i>,<i>.jpg</i>,<i>.jpeg</i>,<i>.png</i>,<i>.rtf</i>and<i>.css</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>cover_image</i></CodeLine>
+</th>
+<th width="397">
+<Text id="398">Recherche un fichier<i>.jpg</i>(portant le mÃªme nom que le fichier en cours de traitement) et l'associe au document en tant qu'image de couverture.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>extract_acronyms</i></CodeLine>
+</th>
+<th width="397">
+<Text id="399">Extrait les acronymes des documents et les ajoute en tant que mÃ©ta-donnÃ©es aux documents d'archive de Greenstone correspondants.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>markup_acronyms</i></CodeLine>
+</th>
+<th width="397">
+<Text id="400">Ajoute des informations sur les acronymes dans le texte du document.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>extract_language</i></CodeLine>
+</th>
+<th width="397">
+<Text id="401">Identifie la langue de chaque document et l'associe en tant que mÃ©ta-donnÃ©e. Ceci est automatique si l'option <i>input_encoding</i>a la valeur<i>auto</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>default_language</i></CodeLine>
+</th>
+<th width="397">
+<Text id="402">Si l'extraction automatique de la langue Ã©choue, la mÃ©ta-donnÃ©e de langue est positionnÃ©e Ã  cette valeur.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>first</i></CodeLine>
+</th>
+<th width="397">
+<Text id="403">Extrait une liste sÃ©parÃ©e par des virgules de la premiÃšre portion de texte et l'ajoute en tant que mÃ©ta-donnÃ©e <i>FirstNNN</i>(souvent utilisÃ© en remplacement de<i>Title</i>).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>extract_email</i></CodeLine>
+</th>
+<th width="397">
+<Text id="404">Extrait les adresses de courrier Ã©lectronique et les ajoute aux mÃ©ta-donnÃ©es du document.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>extract_date</i></CodeLine>
+</th>
+<th width="397">
+<Text id="405">Extrait les dates relatives au contenu de documents historiques et les ajoute en tant que mÃ©ta-donnÃ©es de type<i>Coverage</i>.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+<Subsection id="document_processing_plugins">
+<Title>
+<Text id="406">Greffons de traitement de documents</Text>
+</Title>
+<Content>
+<Table id="greenstone_plugins">
+<Title>
+<Text id="407">Greffons (<i>plugins</i>) de Greenstone</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="60"/>
+<th width="72"/>
+<th width="236">
+<Text id="408"><b>Purpose</b></Text>
+</th>
+<th width="85">
+<Text id="409"><b>File types</b></Text>
+</th>
+<th width="76">
+<Text id="410"><b>Ignores files</b></Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="411"><b>GÃ©nÃ©raux</b></Text>
+</th>
+<th width="72">
+<Text id="412"><i>ArcPlug</i></Text>
+</th>
+<th width="236">
+<Text id="413">Traite les fichiers mentionnÃ©s dans le fichier<i>archives.inf</i>, qui est utilisÃ© comme vecteur de communication entre les processus d'import et de construction. Doit Ãªtre inclus (sauf si<i>import.pl</i>n'est pas utilisÃ©).</Text>
+</th>
+<th width="85">
+<Text id="414"><i>â</i></Text>
+</th>
+<th width="76">
+<Text id="415"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="416"><i>RecPlug</i></Text>
+</th>
+<th width="236">
+<Text id="417">Explore rÃ©cursivement une structure arborescente de rÃ©pertoire en regardant si les fichiers sont des rÃ©pertoires et si c'est le cas, en insÃ©rant tous les fichiers du rÃ©pertoire dans le pipe-line des greffons. Affecte les mÃ©ta-donnÃ©es si l'option<i>âuse_metadata_files</i>est positionnÃ©e et si des fichiers<i>metadata.xml</i>sont prÃ©sents.</Text>
+</th>
+<th width="85">
+<Text id="418"><i>â</i></Text>
+</th>
+<th width="76">
+<Text id="419"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="420"><i>GAPlug</i></Text>
+</th>
+<th width="236">
+<Text id="421">Traite les fichiers d'archive de Greenstone gÃ©nÃ©rÃ©s par le programme<i>import.pl.</i>Doit Ãªtre inclus (sauf si <i>import.pl</i>n'est pas utilisÃ©).</Text>
+</th>
+<th width="85">
+<Text id="422"><i>.xml</i></Text>
+</th>
+<th width="76">
+<Text id="423"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="424">TEXTPlug</Text>
+</th>
+<th width="236">
+<Text id="425">Traite le texte brut en le plaÃ§ant entre balises<i>&lt;pre&gt; &lt;/pre&gt;</i>(et en le traitant comme s'il Ã©tait prÃ©-formatÃ©).</Text>
+</th>
+<th width="85">
+<Text id="426"><i>.txt, .text</i></Text>
+</th>
+<th width="76">
+<Text id="427"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="428"><i>HTMLPlug</i></Text>
+</th>
+<th width="236">
+<Text id="429">Traite le HTML en remplaÃ§ant les liens hypertexte de maniÃšre appropriÃ©e. Si le document cible d'un lien n'est pas dans la collection, une page intermÃ©diaire est insÃ©rÃ©e, avertissant l'utilisateur qu'il quitte la collection. Extrait les mÃ©ta-donnÃ©es dÃ©jÃ  disponibles telles que<i>Title</i>.</Text>
+</th>
+<th width="85">
+<Text id="430"><i>.htm, .html, .cgi, .php, .asp, .shm, .shtml</i></Text>
+</th>
+<th width="76">
+<Text id="431"><i>.gif, .jpeg, .jpg, .png, .css, .rtf</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="432"><i>WordPlug</i></Text>
+</th>
+<th width="236">
+<Text id="433">Traite les fichiers au format Microsoft Word, en extrayant l'auteur et le titre s'ils sont disponibles, et en laissant les diagrammes et les images aux endroits appropriÃ©s. Les outils de conversion utilisÃ©s par ce greffon produisent parfois du HTML mal mis en forme, et nous recommandons que vous fournissiez les documents originaux Ã  des fins de visualisation lors de la construction de collections de fichiers Word. Le texte extrait est cependant convenable Ã  des fins de recherche et d'indexation.</Text>
+</th>
+<th width="85">
+<Text id="434"><i>.doc</i></Text>
+</th>
+<th width="76">
+<Text id="435"><i>.gif, .jpeg, .jpg, .png, .css, .rtf</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="436"><i>PDFPlug</i></Text>
+</th>
+<th width="236">
+<Text id="437">Traite les documents PDF, en extrayant la premiÃšre ligne de texte en tant que titre. Le programme<i>pdftohtml</i>ne parvient pas Ã  traiter certains fichiers PDF. Le processus de conversion prend un temps exponentiellement long, et on voit souvent apparaÃ®tre Ã  l'Ã©cran un message traitant de ce processus. Si cela se produit, la seule solution que nous puissions proposer est d'ÃŽter le document concernÃ© de la collection et de recommencer le processus d'import.</Text>
+</th>
+<th width="85">
+<Text id="438"><i>.pdf</i></Text>
+</th>
+<th width="76">
+<Text id="439"><i>.gif, .jpeg, .jpg, .png, .css, .rtf</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="440"><i>PSPlug</i></Text>
+</th>
+<th width="236">
+<Text id="441">Traite les documents PostScript, en extrayant optionnellement les mÃ©ta-donnÃ©es de date, de titre, et de numÃ©ro de page.</Text>
+</th>
+<th width="85">
+<Text id="442"><i>.ps</i></Text>
+</th>
+<th width="76">
+<Text id="443"><i>.eps</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="444"><i>EMAILPlug</i></Text>
+</th>
+<th width="236">
+<Text id="445">Traite les messages de courrier Ã©lectronique, en reconnaissant l'auteur, le thÃšme, la date, etc. Ce greffon ne traite pas encore correctement les courriers Ã©lectroniques encodÃ©s au format MIMEâbien que lisibles, ils ont souvent un aspect Ã©trange.</Text>
+</th>
+<th width="85">
+<Text id="446">Doit se terminer par des chiffres ou des chiffres suivis de<i>.Email</i></Text>
+</th>
+<th width="76">
+<Text id="447"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="448"><i>BibTexPlug</i></Text>
+</th>
+<th width="236">
+<Text id="449">Traite les fichiers de bibliographie au format<i>BibTex</i>.</Text>
+</th>
+<th width="85">
+<Text id="450"><i>.bib</i></Text>
+</th>
+<th width="76">
+<Text id="451"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="452"><i>ReferPlug</i></Text>
+</th>
+<th width="236">
+<Text id="453">Traite les fichiers de bibliographie au format<i>refer</i>.</Text>
+</th>
+<th width="85">
+<Text id="454"><i>.bib</i></Text>
+</th>
+<th width="76">
+<Text id="455"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="456"><i>SRCPlug</i></Text>
+</th>
+<th width="236">
+<Text id="457">Traite les fichiers de code source</Text>
+</th>
+<th width="85">
+<Text id="458"><i>Makefile, Readme, .c, .cc, .cpp, .h, .hpp, .pl, .pm, .sh</i></Text>
+</th>
+<th width="76">
+<Text id="459"><i>.o, .obj, .a, .so, .dll</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="460"><i>ImagePlug</i></Text>
+</th>
+<th width="236">
+<Text id="461">Traite les fichiers d'images pour crÃ©er une bibliothÃšque d'images. Ne fonctionne que sous Unix.</Text>
+</th>
+<th width="85">
+<Text id="462"><i>.jpeg, .jpg, .gif, .png, .bmp, .xbm, .tif, .tiff</i></Text>
+</th>
+<th width="76">
+<Text id="463"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="464"><i>SplitPlug</i></Text>
+</th>
+<th width="236">
+<Text id="465">Ã l'instar de BasPlug et de ConvertToPlug, il ne faut pas appelÃ© ce greffon directement; il faut plutÃŽt que des greffons qui ont besoin de traiter des fichiers contenant plusieurs documents en hÃ©ritent.</Text>
+</th>
+<th width="85">
+<Text id="466"><i>â</i></Text>
+</th>
+<th width="76">
+<Text id="467"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="468"><i>FOXPlug</i></Text>
+</th>
+<th width="236">
+<Text id="469">Traite les fichiers dbt de FoxBASE</Text>
+</th>
+<th width="85">
+<Text id="470"><i>.dbt, .dbf</i></Text>
+</th>
+<th width="76">
+<Text id="471"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="472"><i>ZIPPlug</i></Text>
+</th>
+<th width="236">
+<Text id="473">DÃ©compacte les fichiers<i>gzip</i>,<i>bzip</i>,<i>zip</i>, et<i>tar</i>files, pour peu que les outils GNU appropriÃ©s soient disponibles.</Text>
+</th>
+<th width="85">
+<Text id="474"><i>.gzip, .bzip, .zip, .tar, .gz, .bz, .tgz, .taz</i></Text>
+</th>
+<th width="76">
+<Text id="475"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="476"><b>Propres Ã  une collection</b></Text>
+</th>
+<th width="72">
+<Text id="477"><i>PrePlug</i></Text>
+</th>
+<th width="236">
+<Text id="478">Traite la sortie HTML en utilisant PRESCRIPT, divisant les documents en pages pour la collection <i>Computer Science Technical Reports</i>.</Text>
+</th>
+<th width="85">
+<Text id="479"><i>.html, .html.gz</i></Text>
+</th>
+<th width="76">
+<Text id="480"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="481"><i>GBPlug</i></Text>
+</th>
+<th width="236">
+<Text id="482">Traite le texte Ã©lectronique du projet Gutenbergâqui comprend des informations de titre saisies manuellement.</Text>
+</th>
+<th width="85">
+<Text id="483"><i>.txt.gz, .html, .htm</i></Text>
+</th>
+<th width="76">
+<Text id="484"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="485"><i>TCCPlug</i></Text>
+</th>
+<th width="236">
+<Text id="486">Traite les documents de courrier Ã©lectronique de la collection<i>Computists' Weekly</i>(l'hebdomadaire des informaticiens) </Text>
+</th>
+<th width="85">
+<Text id="487">Doit commencer par<i>tcc</i>ou<i>cw</i></Text>
+</th>
+<th width="76">
+<Text id="488"><i>â</i></Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="489">Les greffons de traitement de documents sont utilisÃ©s par le logiciel de construction de collection pour analyser chaque document source d'une maniÃšre qui dÃ©pend de son format. Le fichier de configuration d'une collection liste tous les greffons utilisÃ©s lors de sa construction. Lors de l'opÃ©ration d'import, chaque fichier ou chaque rÃ©pertoire est passÃ© tour Ã  tour Ã  tous les greffons jusqu'Ã  ce qu'un greffon soit trouvÃ© qui puisse traiter l'objetÂ --Â c'est pourquoi les premiers greffons listÃ©s ont la prioritÃ© sur des greffons apparaissant plus tard dans la liste. Si aucun greffon ne peut traiter le fichier, un avertissement est affichÃ© (sur la sortie d'erreur standard) et le traitement passe au fichier suivant (c'est pourquoi l'option block_exp peut Ãªtre utileÂ --Â pour Ã©viter ces messages d'erreur dans le cas de fichiers qui sont peut-Ãªtre prÃ©sents mais n'ont pas besoin d'Ãªtre traitÃ©s). Lors de la construction, on utilise la mÃªme procÃ©dure, mais c'est le rÃ©pertoire archives qui est traitÃ© en lieu et place du rÃ©pertoire import.</Text>
+<Text id="490">Les greffons standard de Greenstone sont listÃ©s tableÂ <CrossRef target="Table" ref="greenstone_plugins"/>. Il est nÃ©cessaire d'utiliser un processus rÃ©cursif pour traverser des hiÃ©rarchies de rÃ©pertoires. Bien que les programmes d'import et de construction n'effectuent pas de rÃ©cursion explicite, certains greffons provoquent une rÃ©cursion indirecte en passant des noms de fichiers ou de rÃ©pertoires dans le pipe-line des greffons. Par exemple, la maniÃšre habituelle d'opÃ©rer rÃ©cursivement Ã  travers une hiÃ©rarchie de rÃ©pertoire est de spÃ©cifier RecPlug, qui travaille exactement ainsi. S'il est prÃ©sent, il devrait Ãªtre en derniÃšre position dans le pipe-line. Seuls les deux premiers greffons de la tableÂ <CrossRef target="Table" ref="greenstone_plugins"/> provoquent une rÃ©cursion indirecte.</Text>
+<Text id="491">Certains greffons sont Ã©crits pour des collections spÃ©cifiques, avec un format de document que l'on ne trouve nulle part ailleurs, tel que le texte Ã©lectronique utilisÃ© dans la collection Gutenberg<FootnoteRef id="2"/>. Ces greffons spÃ©cifiques Ã  une collection se trouvent dans le rÃ©pertoire perllib/plugins de la collection. On peut utiliser des greffons spÃ©cifiques Ã  une collection pour remplacer des greffons gÃ©nÃ©raux portant le mÃªme nom, qui ne seront alors pas appelÃ©s.</Text>
+<Text id="492">Certains greffons de traitement de documents utilisent des programmes externes qui analysent des formats de fichiers propriÃ©taires spÃ©cifiquesÂ --Â tel que par exemple Microsoft WordÂ --Â et les transforment en texte brut ou en HTML. Un greffon gÃ©nÃ©ral appelÃ© ConvertToPlug invoque le programme de conversion appropriÃ© et en passe le rÃ©sultat aux greffons TEXTPlug ou HTMLPlug. Nous dÃ©crirons cette opÃ©ration plus en dÃ©tail sous peu.</Text>
+<Text id="493">Certains greffons disposent d'options individuelles, qui les contrÃŽlent de maniÃšre plus fine que ce que permettent les options gÃ©nÃ©rales. C'est la tableÂ <CrossRef target="Table" ref="plugin-specific_options"/> qui dÃ©crit ces options individuelles.</Text>
+<Table id="plugin-specific_options">
+<Title>
+<Text id="494">Options propres aux greffons</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="495"><b>Option</b></Text>
+</th>
+<th width="265">
+<Text id="496"><b>But</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="497"><i>HTMLPlug</i></Text>
+</th>
+<th width="132">
+<Text id="498"><i>nolinks</i></Text>
+</th>
+<th width="265">
+<Text id="499">Ne piÃšge pas de liens dans la collection. Ceci accÃ©lÃšre les processus d'import et de construction, mais tout lien contenu dans la collection sera cassÃ©.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="500"><i>description_tags</i></Text>
+</th>
+<th width="265">
+<Text id="501">InterprÃšte les fichiers de documents balisÃ©s comme dans la sous-section 2.1.5.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="502"><i>keep_head</i></Text>
+</th>
+<th width="265">
+<Text id="503">N'enlÃšve pas les en-tÃªtes HTML.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="504"><i>no_metadata</i></Text>
+</th>
+<th width="265">
+<Text id="505">Ne recherche aucune mÃ©ta-donnÃ©e (ceci peut accÃ©lÃ©rer les processus d'import et de construction).</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="506"><i>metadata_fields</i></Text>
+</th>
+<th width="265">
+<Text id="507">Prend une liste sÃ©parÃ©e par des virgules de types de mÃ©ta-donnÃ©es Ã  extraire (dont la valeur par dÃ©faut est<i>Title</i>).Pour changer le nom des mÃ©ta-donnÃ©es dans le fichier d'archive de Greenstone, utilisez<i>balise&lt;nouveaunom&gt;</i>oÃ¹<i>balise</i>est la balise HTML recherchÃ©e et<i>nouveaunom</i>son nouveau nom.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="508"><i>hunt_creator_metadata</i></Text>
+</th>
+<th width="265">
+<Text id="509">Trouve autant de mÃ©ta-donnÃ©es que possible relatives Ã  la paternitÃ© du document et les consigne dans le document d'archive de Greenstone sous la forme de mÃ©ta-donnÃ©es<i>Creator</i>. Il faut aussi inclure<i>Creator</i>avec l'option<i>metadata_fields</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="510"><i>file_is_url</i></Text>
+</th>
+<th width="265">
+<Text id="511">Utilisez cette option si un programme de miroir web a Ã©tÃ© utilisÃ© pour crÃ©er la structure des documents Ã  importer.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="512"><i>assoc_files</i></Text>
+</th>
+<th width="265">
+<Text id="513">Donne une expression rationnelle de Perl qui dÃ©crit les types de fichiers Ã  traiter comme des fichiers associÃ©s. Les types par dÃ©faut sont<i>.jpg</i>,<i>.jpeg</i>,<i>.gif</i>,<i>.png</i>,<i>.css</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="514"><i>rename_assoc_files</i></Text>
+</th>
+<th width="265">
+<Text id="515">Change le nom des fichiers associÃ©s aux documents. Lors de ce processus la structure de rÃ©pertoire de tout fichier associÃ© rÃ©trÃ©cira beaucoup (ce qui est utile s'il faut stocker la collection dans un espace disque limitÃ©).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="516"><i>HTMLPlug</i>et<br/>
+<i>TEXTPlug</i></Text>
+</th>
+<th width="132">
+<Text id="517"><i>title_sub</i></Text>
+</th>
+<th width="265">
+<Text id="518">Expression de substitution Perl pour modifier les titres.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="519"><i>PSPlug</i></Text>
+</th>
+<th width="132">
+<Text id="520"><i>extract_date</i></Text>
+</th>
+<th width="265">
+<Text id="521">Extrait la date de crÃ©ation de l'en-tÃªte PostScript et la stocke en tant que mÃ©ta-donnÃ©e.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="522"><i>extract_title</i></Text>
+</th>
+<th width="265">
+<Text id="523">Extrait le titre du document de l'en-tÃªte PostScript et le stocke en tant que mÃ©ta-donnÃ©e de titre.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="524"><i>extract_pages</i></Text>
+</th>
+<th width="265">
+<Text id="525">Extrait les numÃ©ros de pages du document PostScript et les ajoute aux sections appropriÃ©es en tant que mÃ©ta-donnÃ©es sous la balise<i>Pages</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="526"><i>RecPlug</i></Text>
+</th>
+<th width="132">
+<Text id="527"><i>use_metadata_files</i></Text>
+</th>
+<th width="265">
+<Text id="528">Affecte des mÃ©ta-donnÃ©es Ã  partir d'un fichier tel que dÃ©crit dans la sous-section 2.1.4.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="529"><i>ImagePlug</i></Text>
+</th>
+<th width="132">
+<Text id="530">Diverses options</Text>
+</th>
+<th width="265">
+<Text id="531">Voir<i>ImagePlug.pm.</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="532"><i>SRCPlug</i></Text>
+</th>
+<th width="132">
+<Text id="533"><i>remove_prefix</i></Text>
+</th>
+<th width="265">
+<Text id="534">Donne une expression rationnelle de Perl d'un motif Ã  chercher en tÃªte et qu'il faut ÃŽter du nom de fichier. Le comportement par dÃ©faut est d'ÃŽter tout le chemin.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+<Subsection id="plugins_to_import_proprietary_formats">
+<Title>
+<Text id="535">Greffons d'import de formats propriÃ©taires</Text>
+</Title>
+<Content>
+<Text id="536">Les formats propriÃ©taires posent des problÃšmes difficiles pour tout systÃšme de bibliothÃšque numÃ©rique. Bien qu'ils soient parfois documentÃ©s, ils sont susceptibles de changer sans prÃ©avis, et il est difficile de suivre le rythme des changements. Greenstone a fait le choix d'utiliser des outils de conversion publiÃ©s selon les termes de la GPL (licence publique gÃ©nÃ©rale de GNU) par des gens focalisÃ©s sur telle ou telle tÃ¢che de conversion. Les outils pour convertir les formats Word et PDF sont inclus dans le rÃ©pertoire packages. Tous convertissent des documents au format texte ou au format HTML. Les greffons HTMLPlug et TEXTPlug prennent ensuite la relÃšve et convertissent ce rÃ©sultat intermÃ©diaire au format d'archivage de Greenstone. C'est ConvertToPlug qui est utilisÃ© pour inclure les outils de conversion. BasPlug n'est jamais appelÃ© directement, mais les greffons traitant des formats particuliers en hÃ©ritent, comme illustrÃ© figureÂ <CrossRef target="Figure" ref="plugin_inheritance_hierarchy"/>. ConvertToPlug utilise le systÃšme d'hÃ©ritage dynamique de Perl pour hÃ©riter soit de TEXTPlug soit de HTMLPlug, selon le format dans lequel le document source a Ã©tÃ© converti.</Text>
+<Figure id="plugin_inheritance_hierarchy">
+<Title>
+<Text id="537">HiÃ©rarchie d'hÃ©ritage des greffons (plugins)</Text>
+</Title>
+<File width="229" height="193" url="images/Dev_Fig_9.png"/>
+</Figure>
+<Text id="538">Quand ConvertToPlug reÃ§oit un document, il appelle gsConvert.pl (qui se trouve dans le rÃ©pertoire GSDLHOME/bin/script) pour invoquer l'outil de conversion appropriÃ©. AprÃšs conversion, le document est renvoyÃ© vers le greffon ConvertToPlug, qui invoque ensuite le greffon texte ou HTML, selon les cas. Tout greffon hÃ©ritant de ConvertToPlug dispose d'une option convert_to (convertit vers), dont l'argument est soit text (texte) soit html, pour spÃ©cifier le format intermÃ©diaire prÃ©fÃ©rÃ©. Le format texte est plus rapide, mais le format HTML rend mieux en gÃ©nÃ©ral, et comprend des images.</Text>
+<Text id="539">Il existe parfois plusieurs outils de conversion pour traiter un format particulier, et le programme gsConvert peut en essayer plusieurs sur un document donnÃ©. Par exemple, l'outil habituel de conversion du format Work, wvWare, ne traite pas les formats antÃ©rieurs Ã  Word 6, et c'est un programme appelÃ© AnyToHTML, qui se contente d'extraire toutes les chaÃ®nes de texte qu'il peut trouver, qui est appelÃ© pour convertir les documents au format Word 5.</Text>
+<Text id="540">Voici les Ã©tapes nÃ©cessaires pour ajouter un nouvel outil externe de conversion de document:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="541">Installez le nouvel outil de conversion de maniÃšre qu'il soit accessible Ã  Greenstone (placez-le dans le rÃ©pertoire packages).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="542">Modifiez gsConvert.pl pour utiliser le nouvel outil de conversion. Il s'agit d'ajouter une nouvelle clause Ã  l'instruction if de la fonction main, et d'ajouter une fonction qui appelle l'outil de conversion.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="543">Ãcrivez un greffon de premier niveau qui hÃ©rite de ConvertToPlug pour intercepter le format et le passer Ã  la suite de la chaÃ®ne.</Text>
+</NumberedItem>
+</NumberedList>
+</Content>
+</Subsection>
+<Subsection id="assigning_metadata_from_a_file">
+<Title>
+<Text id="544">Affecter des mÃ©ta-donnÃ©es Ã  partir d'un fichier</Text>
+</Title>
+<Content>
+<Text id="545">Le greffon standard RecPlug incorpore Ã©galement une mÃ©thode pour positionner des mÃ©ta-donnÃ©es dans les documents de maniÃšre manuelle (ou automatique) Ã  partir de fichiers XML crÃ©Ã©s manuellement (ou automatiquement). Nous dÃ©taillons quelque peu ceci, de maniÃšre que vous puissiez crÃ©er des fichiers de mÃ©ta-donnÃ©es dans le format appropriÃ©. Si l'option use_metadata_files est prÃ©cisÃ©e, RecPlug utilise un fichier de mÃ©ta-donnÃ©es auxiliaire, metadata.xml. La premiÃšre partie de la figureÂ <CrossRef target="Figure" ref="xml_format"/> illustre la dÃ©finition de type de document (DTD) XML pour le format du fichier de mÃ©ta-donnÃ©es, et la deuxiÃšme partie de la figureÂ <CrossRef target="Figure" ref="xml_format_1"/> montre un exemple de fichier metadata.xml.</Text>
+<Figure id="xml_format">
+<Title>
+<Text id="546">Format XML: (a) DÃ©finition de type de document (DTD); (b) Fichier de mÃ©ta-donnÃ©es d'exemple</Text>
+<SubTitle>
+<Text id="547">(a)</Text>
+</SubTitle>
+</Title>
+<CodeLine>&lt;!DOCTYPE GreenstoneDirectoryMetadata [</CodeLine>
+<CodeLine>   &lt;!ELEMENT DirectoryMetadata (FileSet*)&gt;</CodeLine>
+<CodeLine>   &lt;!ELEMENT FileSet (FileName+,Description)&gt;</CodeLine>
+<CodeLine>   &lt;!ELEMENT FileName (#PCDATA)&gt;</CodeLine>
+<CodeLine>   &lt;!ELEMENT Description (Metadata*)&gt;</CodeLine>
+<CodeLine>   &lt;!ELEMENT Metadata (#PCDATA)&gt;</CodeLine>
+<CodeLine>   &lt;ATTLIST Metadata name CDATA #REQUIRED&gt;</CodeLine>
+<CodeLine>   &lt;ATTLIST Metadata mode (accumulate|override) "override"&gt;</CodeLine>
+<CodeLine>]&gt;</CodeLine>
+</Figure>
+<Figure id="xml_format_1">
+<Title>
+<Text id="548"/>
+<SubTitle>
+<Text id="549">(b)</Text>
+</SubTitle>
+</Title>
+<CodeLine>&lt;?xml version="1.0" ?&gt;</CodeLine>
+<CodeLine>&lt;!DOCTYPE GreenstoneDirectoryMetadata SYSTEM</CodeLine>
+<CodeLine>"http://greenstone.org/dtd/GreenstoneDirectoryMetadata/<br/>1.0/GreenstoneDirectoryMetadata.dtd"&gt;</CodeLine>
+<CodeLine>&lt;DirectoryMetadata&gt;</CodeLine>
+<CodeLine>   &lt;FileSet&gt;</CodeLine>
+<CodeLine>       &lt;FileName&gt;nugget.*&lt;/FileName&gt;</CodeLine>
+<CodeLine>       &lt;Description&gt;</CodeLine>
+<CodeLine>       &lt;Metadata name="Title"&gt;Nugget Point Lighthouse&lt;/Metadata&gt;</CodeLine>
+<CodeLine>           &lt;Metadata name="Place" mode="accumulate"&gt;Nugget Point&lt;/Metadata&gt;</CodeLine>
+<CodeLine>       &lt;/Description&gt;</CodeLine>
+<CodeLine>   &lt;/FileSet&gt;</CodeLine>
+<CodeLine>   &lt;FileSet&gt;</CodeLine>
+<CodeLine>       &lt;FileName&gt;nugget-point-1.jpg&lt;/FileName&gt;</CodeLine>
+<CodeLine>       &lt;Description&gt;</CodeLine>
+<CodeLine>           &lt;Metadata name="Title"&gt;Nugget Point Lighthouse , The Catlins &lt;/Metadata&gt;</CodeLine>
+<CodeLine>           &lt;Metadata name="Subject"&gt;Lighthouse&lt;/Metadata&gt;</CodeLine>
+<CodeLine>       &lt;/Description&gt;</CodeLine>
+<CodeLine>   &lt;/FileSet&gt;</CodeLine>
+<CodeLine>&lt;/DirectoryMetadata&gt;</CodeLine>
+</Figure>
+<Text id="550">Le fichier d'exemple contient deux structures de mÃ©ta-donnÃ©es. Dans chacune, l'Ã©lÃ©ment filename dÃ©crit les fichiers auxquels les mÃ©ta-donnÃ©es s'appliquent, sous la forme d'une expression rationnelle. &lt;FileName&gt;nugget.*&lt;/FileName&gt; indique ainsi que le premier enregistrement de mÃ©ta-donnÃ©es s'applique Ã  tous les fichiers dont le nom commence par Â«nuggetÂ»<FootnoteRef id="3"/>. Pour ces fichiers, la mÃ©ta-donnÃ©e Title vaudra Â«Phare de Nugget PointÂ».</Text>
+<Text id="551">Les Ã©lÃ©ments de mÃ©ta-donnÃ©es sont traitÃ©s dans l'ordre dans lequel ils apparaissent. La deuxiÃšme structure de la figureÂ 10 positionne la mÃ©ta-donnÃ©e Title pour le fichier nugget-point-1.jpg Ã  la valeur Â«Phare de Nugget Point, CatlinsÂ», en Ã©crasant la spÃ©cification prÃ©cÃ©dente. Elle ajoute Ã©galement un champ Subject dans les mÃ©ta-donnÃ©es.</Text>
+<Text id="552">Parfois, les mÃ©ta-donnÃ©es sont multi-valuÃ©es et les nouvelles valeurs devraient s'accumuler au lieu d'Ã©craser les prÃ©cÃ©dentes. L'attribut mode=accumulate a cet effet. Il est appliquÃ© Ã  la mÃ©ta-donnÃ©e Place (lieu) dans la premiÃšre spÃ©cification de la figureÂ 10, cette mÃ©ta-donnÃ©e sera donc multi-valuÃ©e. Pour revenir Ã  une mÃ©ta-donnÃ©e simple, Ã©crivez<i>&lt;Metadata name="Place" mode="override"&gt;Nouvelle-ZÃ©lande&lt;/Metadata&gt;</i>En fait, on peut nÃ©gliger de prÃ©ciser cette spÃ©cification de mode puisque tout Ã©lÃ©ment Ã©crase le prÃ©cÃ©dent par dÃ©faut, sauf indication contraire. Pour accumuler les mÃ©ta-donnÃ©es dans un champ particulier, il faut prÃ©ciser mode=accumulate Ã  chaque occurrence.</Text>
+<Text id="553">Quand son option use_metadata_files est activÃ©e, le greffon RecPlug recherche dans chaque rÃ©pertoire en entrÃ©e un fichier XML appelÃ© metadata.xml et applique son contenu Ã  tous les fichiers et sous-rÃ©pertoires du rÃ©pertoire courant.</Text>
+<Text id="554">Le mÃ©canisme metadata.xml instanciÃ© dans le greffon RecPlug n'est qu'une maniÃšre de spÃ©cifier des mÃ©ta-donnÃ©es pour des documents. Il est facile d'Ã©crire des greffons diffÃ©rents qui accepteront des spÃ©cifications de mÃ©ta-donnÃ©es dans des formats complÃštement diffÃ©rents.</Text>
+</Content>
+</Subsection>
+<Subsection id="tagging_document_files">
+<Title>
+<Text id="555">Baliser les fichiers de documents</Text>
+</Title>
+<Content>
+<Text id="556">Il faut souvent structurer les documents source en sections et sous-sections, et donc communiquer cette information Ã  Greenstone de maniÃšre qu'il puisse reproduire la structure hiÃ©rarchique du document. On peut aussi associer Ã  chaque section et sous-section des mÃ©ta-donnÃ©es, et en particulier un titre.</Text>
+<Text id="557">La maniÃšre la plus simple de procÃ©der est souvent d'Ã©diter les fichiers source, tout simplement. Le greffon HTML dispose d'un option description_tags qui traite les balises dans le texte comme suit:</Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>   &lt;Description&gt;</CodeLine>
+<CodeLine>       &lt;Metadata name="Title"&gt; Realizing human rights for poor people: Strategies for achieving the international development targets&lt;/Metadata&gt;</CodeLine>
+<CodeLine>   &lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="558"><i>(texte de la section)</i></Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="559">On utilise les marqueurs<i>&lt;!-- ... --&gt;</i>car ils dÃ©notent des commentaires en HTML; ces balises de section n'auront donc aucun impact sur la mise en forme du document. On peut spÃ©cifier d'autres types de mÃ©ta-donnÃ©es dans la portion Description, mais ce n'est pas le cas du style de collection dÃ©crit ici. On peut aussi imbriquer des balises, de telle sorte que la ligne<i>(texte de la section)</i>ci-dessus peut elle-mÃªme inclure des sous-sections, telles que</Text>
+<Text id="560"><i>(texte de la premiÃšre partie de la section)</i></Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>   &lt;Description&gt;</CodeLine>
+<CodeLine>       &lt;Metadata name="Title"&gt; The international development targets&lt;/Metadata&gt;</CodeLine>
+<CodeLine>   &lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="561"><i>(texte de la sous-section)</i></Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="562"><i>(texte de la derniÃšre partie de la section)</i></Text>
+<Text id="563">Cette fonctionnalitÃ© est hÃ©ritÃ©e par tout greffon utilisant HTMLPlug. En particulier, le greffon Word convertit les donnÃ©es qu'il reÃ§oit au format HTML: on peut donc procÃ©der exactement de la mÃªme maniÃšre pour spÃ©cifier des mÃ©ta-donnÃ©es dans les fichiers Word (et RTF). Ceci implique un peu de travail en coulisses, puisque lors de la conversion de documents Word vers HTML, le programme prend soin, normalement, de neutraliser les caractÃšres significatifs pour HTML, tels que<i>&lt;</i>et<i>&gt;</i>; nous nous sommes arrangÃ©s pour contourner cette neutralisation dans le cas des spÃ©cifications mentionnÃ©es ci-dessus. Il faut alors utiliser exactement le mÃªme format, mÃªme dans des fichiers Word, et ne pas oublier les<i>&lt;!--</i>et<i>--&gt;</i>qui entourent les mÃ©ta-donnÃ©es. Le choix des polices et l'espacement n'ont aucune importance.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="classifiers">
+<Title>
+<Text id="564">Classificateurs</Text>
+</Title>
+<Content>
+<Text id="565">Les classificateurs servent Ã  crÃ©er les index de navigation d'une collection, comme par exemple l'index titres A-Z de la collection dlpeople, et les index thÃšme, comment faire, organisation et titres A-Z dans la bibliothÃšque de dÃ©veloppement pour l'humanitÃ©, dont la collection Â«DemoÂ» est un sous-ensemble. La barre de navigation situÃ©e au sommet des copies d'Ã©cran dans les figuresÂ 3 etÂ 8a inclut la fonction Rechercher, qui est toujours disponible, suivie par autant de boutons que de classificateurs dÃ©finis. Les informations servant Ã  la navigation sont stockÃ©es dans la base de donnÃ©es d'informations de la collection, et y sont placÃ©es par des classificateurs lors de la phase finale du programme buildcol.pl.</Text>
+<Figure id="azlist_classifier">
+<Title>
+<Text id="566">Classificateur<i>AZList</i></Text>
+</Title>
+<File width="390" height="182" url="images/Dev_Fig_11.png"/>
+</Figure>
+<Text id="567">Les classificateurs, Ã  l'instar des greffons, sont spÃ©cifiÃ©s dans le fichier de configuration de la collection. Ã chacun correspond une ligne dÃ©butant par le mot-clef classify et suivie du nom du classificateur et des options qu'il accepte. Le fichier de configuration de collection simple Ã©tudiÃ© dans la sectionÂ <CrossRef target="Section" ref="configuration_file"/> comprend la ligne classify AZList -metadata Title, qui crÃ©e une liste alphabÃ©tique des titres en prenant tous les documents pourvus d'un champ de mÃ©ta-donnÃ©es Title, en triant ces derniers et en les ventilant en intervalles alphabÃ©tiques. On trouvera un exemple dans la figureÂ <CrossRef target="Figure" ref="azlist_classifier"/>.</Text>
+<Figure id="list_classifier">
+<Title>
+<Text id="568">Classificateur<i>List</i></Text>
+</Title>
+<File width="394" height="143" url="images/Dev_Fig_12.png"/>
+</Figure>
+<Text id="569">Un classificateur plus simple, appelÃ© List, et illustrÃ© dans la figureÂ <CrossRef target="Figure" ref="list_classifier"/>, crÃ©e une liste triÃ©e d'une mÃ©ta-donnÃ©e spÃ©cifiÃ©e et l'affiche sans crÃ©er de tranches alphabÃ©tiques. Un exemple est la mÃ©ta-donnÃ©e how to de la collection Â«DemoÂ», qui est produite par la ligne classify List -metadata Howto dans le fichier de configuration de la collection<FootnoteRef id="4"/>. Un autre classificateur de liste gÃ©nÃ©rique est DateList, illustrÃ© dans la figureÂ <CrossRef target="Figure" ref="datelist_classifier"/>, qui engendre une liste de sÃ©lection d'intervalles de dates (le classificateur DateList est Ã©galement utilisÃ© dans la collection Â«ArchivesÂ» de Greenstone).</Text>
+<Figure id="datelist_classifier">
+<Title>
+<Text id="570">Classificateur<i>DateList</i></Text>
+</Title>
+<File width="390" height="159" url="images/Dev_Fig_13.png"/>
+</Figure>
+<Text id="571">D'autres classifications engendrent des structures de navigation qui sont explicitement hiÃ©rarchiques. Les classifications hiÃ©rarchiques sont utiles pour des classifications et sous-classifications de thÃšmes, et les hiÃ©rarchies organisationnelles. Le fichier de configuration de la collection Â«DemoÂ» contient la ligne classify Hierarchy -hfile sub.txt -metadata Subject -sort Title, et la figureÂ <CrossRef target="Figure" ref="hierarchy_classifier"/> ontre la hiÃ©rarchie de thÃšmes que cette ligne produit. L'Ã©tagÃšre portant un titre en gras et l'Ã©tagÃšre actuellement utilisÃ©e; la classification de thÃšme Ã  laquelle elle appartient la surplombe. Dans cet exemple la hiÃ©rarchie utilisÃ©e pour la classification est stockÃ©e dans un simple fichier texte, sous le nom sub.txt.</Text>
+<Figure id="hierarchy_classifier">
+<Title>
+<Text id="572">Classificateur<i>Hierarchy</i></Text>
+</Title>
+<File width="394" height="198" url="images/Dev_Fig_14.png"/>
+</Figure>
+<Text id="573">Tous les classificateurs gÃ©nÃšrent une structure hiÃ©rarchique qui est utilisÃ©e pour afficher un index de navigateur. Les niveaux les plus bas de la hiÃ©rarchie (les feuilles) sont gÃ©nÃ©ralement les documents, mais dans certains classificateurs ce sont les sections. Les noeuds internes de la hiÃ©rarchie sont Vlist, Hlist, ou Datelist. Un noeud Vlist est une liste d'objets affichÃ©s verticalement et descendant la page, telle que l'index Â«comment faireÂ» de la collection Â«DemoÂ» (figureÂ <CrossRef target="Figure" ref="list_classifier"/>). Un noeud Hlist est affichÃ© horizontalement; par exemple l'affichage AZList de la figureÂ <CrossRef target="Figure" ref="azlist_classifier"/> est une hiÃ©rarchie Ã  deux niveaux de noeuds internes consistant en un noeud Hlist (donnant le sÃ©lecteur A-Z) et dont les enfants sont des noeuds VlistÂ --Â parents, Ã  leur tour, de documents. Un noeud Datelist (figureÂ <CrossRef target="Figure" ref="datelist_classifier"/>) est un cas particulier de noeud Vlist qui permet d'effectuer des sÃ©lections par annÃ©e et par mois.</Text>
+<Text id="574">Les lignes spÃ©cifiant des classificateurs dans les fichiers de configuration de collection contiennent un argument metadata qui identifie les mÃ©ta-donnÃ©es selon lesquelles classifier et trier les documents. Tout document de la collection ne disposant pas de cette mÃ©ta-donnÃ©e sera omis par le classificateur (mais il sera quand mÃªme indexÃ©, et les recherches le prendront donc en compte). En l'absence de spÃ©cification d'argument metadata, tous les documents sont inclus dans le classificateur, dans l'ordre dans lequel le processus de construction les a trouvÃ©s. C'est utile si vous souhaitez obtenir une liste de tous les documents de votre collection.</Text>
+<Table id="greenstone_classifiers">
+<Title>
+<Text id="575">Classificateurs de Greenstone</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="576"><b>Argument</b></Text>
+</th>
+<th width="305">
+<Text id="577"><b>But</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="578"><i>Hierarchy</i></Text>
+</th>
+<th width="92"/>
+<th width="305">
+<Text id="579">Classification hiÃ©rarchique</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="580"><i>hfile</i></Text>
+</th>
+<th width="305">
+<Text id="581">Fichier de classification</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="582"><i>metadata</i></Text>
+</th>
+<th width="305">
+<Text id="583">ÃlÃ©ment de mÃ©ta-donnÃ©e Ã  confronter Ã  l'identifiant<i>hfile</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="584"><i>sort</i></Text>
+</th>
+<th width="305">
+<Text id="585">ÃlÃ©ment de mÃ©ta-donnÃ©e utilisÃ© pour trier les documents au sein des feuilles (valeur par dÃ©faut:<i>Title</i>)</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="586"><i>buttonname</i></Text>
+</th>
+<th width="305">
+<Text id="587">Nom du bouton utilisÃ© pour accÃ©der Ã  ce classificateur (valeur par dÃ©faut: valeur de l'argument<i>metadata</i>)</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="588"><i>List</i></Text>
+</th>
+<th width="92"/>
+<th width="305">
+<Text id="589">Liste alphabÃ©tique des documents</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="590"><i>metadata</i></Text>
+</th>
+<th width="305">
+<Text id="591">Inclut les documents contenant cet Ã©lÃ©ment de mÃ©ta-donnÃ©e</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="592"><i>buttonname</i></Text>
+</th>
+<th width="305">
+<Text id="593">Nom du bouton utilisÃ© pour accÃ©der Ã  ce classificateur (valeur par dÃ©faut: valeur de l'argument<i>metadata</i>)</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="594"><i>SectionList</i></Text>
+</th>
+<th width="92"/>
+<th width="305">
+<Text id="595">Liste des sections dans les documents</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="596"><i>AZList</i></Text>
+</th>
+<th width="92"/>
+<th width="305">
+<Text id="597">Liste des documents ventilÃ©s en intervalles alphabÃ©tiques</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="598"><i>metadata</i></Text>
+</th>
+<th width="305">
+<Text id="599">Inclut les documents contenant cet Ã©lÃ©ment de mÃ©ta-donnÃ©e</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="600"><i>buttonname</i></Text>
+</th>
+<th width="305">
+<Text id="601">Nom du bouton utilisÃ© pour accÃ©der Ã  ce classificateur (valeur par dÃ©faut: valeur de l'argument<i>metadata</i>)</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="602"><i>AZSectionList</i></Text>
+</th>
+<th width="92"/>
+<th width="305">
+<Text id="603">Comme<i>AZList</i>mais inclut chaque section du document</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="604"><i>DateList</i></Text>
+</th>
+<th width="92"/>
+<th width="305">
+<Text id="605">Similaire Ã <i>AZList</i>mais en triant par date</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="606">Les classificateurs actuellement disponibles sont listÃ©s dans la table <CrossRef target="Table" ref="greenstone_classifiers"/>. De mÃªme que l'on peut utiliser le programme pluginfo.pl pour en savoir plus sur un greffon quelconque, on peut utiliser le programme classinfo.pl pour en savoir plus sur un classificateur et sur les options qu'il propose.</Text>
+<Text id="607">Tous les classificateurs acceptent l'argument buttonname, qui dÃ©finit ce qui est Ã©crit sur le bouton de navigation de Greenstone qui invoque le classificateur (sa valeur par dÃ©faut est le nom de l'argument metadata). Des boutons sont fournis pour chacun des types de mÃ©ta-donnÃ©es du systÃšme Dublin Core, ainsi que pour quelques autres types de mÃ©ta-donnÃ©es.</Text>
+<Text id="608">Chaque classificateur reÃ§oit un nom implicite en fonction de sa position dans le fichier de configuration. Par exemple, le troisiÃšme classificateur spÃ©cifiÃ© dans le fichier s'appellera CL3. Ces noms sont utilisÃ©s dans les champs de la base de donnÃ©es d'informations de la collection, qui dÃ©finit la hiÃ©rarchie des classificateurs.</Text>
+<Text id="609">On peut Ã©crire des classificateurs propres Ã  une collection; ils sont alors stockÃ©s dans son rÃ©pertoire perllib/classify. La bibliothÃšque de dÃ©veloppement pour l'humanitÃ© dispose d'un classificateur propre de collection qui s'appelle HDLList, et qui est une variante mineure d'AZList.</Text>
+<Subsection id="list_classifiers">
+<Title>
+<Text id="610">Classificateurs de listes</Text>
+</Title>
+<Content>
+<Text id="611">Voici les diffÃ©rentes possibilitÃ©s de classificateurs de listes:</Text>
+<BulletList>
+<Bullet>
+<Text id="612">SectionListÂ --Â comme List mais les feuilles sont des sections et non pas des documents. Toutes les sections du document sont incluses Ã  l'exception des sections de premier niveau. Cela sert Ã  crÃ©er des listes de sections (ou d'articles, de chapitres, ou ...) cVoici les diffÃ©rentes omme dans la collection Computists' Weekly (l'hebdomadaire des informaticiens), disponible depuis le site webnzdl.org, dont chaque numÃ©ro est un unique document qui comprend plusieurs dÃ©pÃªches indÃ©pendantes, chacune Ã©tant placÃ©e dans sa propre section.</Text>
+</Bullet>
+<Bullet>
+<Text id="613">AZListÂ --Â gÃ©nÃšre une hiÃ©rarchie Ã  deux niveaux comprenant un noeud HList dont les enfants sont des noeuds VList, parents Ã  leur tour de documents. Le noeud HList est un sÃ©lecteur A-Z qui divise les documents en intervalles alphabÃ©tiques. Les documents sont triÃ©s alphabÃ©tiquement selon des mÃ©ta-donnÃ©es, et la liste rÃ©sultante est ventilÃ©e en intervalles.</Text>
+</Bullet>
+<Bullet>
+<Text id="614">AZSectionListÂ --Â comme AZList, mais les feuilles sont des sections, et non pas des documents.</Text>
+</Bullet>
+<Bullet>
+<Text id="615">DateListÂ --Â comme AZList Ã  ceci prÃšs que le noeud HList de premier niveau permet des sÃ©lections par annÃ©e et que ses enfants sont des noeuds de type DateList et non pas de type VList. La valeur par dÃ©faut de l'argument metadata est Date.</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Subsection>
+<Subsection id="the_hierarchy_classifier">
+<Title>
+<Text id="616">Le classificateur hierarchy</Text>
+</Title>
+<Content>
+<Text id="617">Tous les classificateurs sont hiÃ©rarchiques. Cependant, les classificateurs de la sectionÂ 2.1.1 disposent d'un nombre fixÃ© de niveaux, alors que le classificateur hierarchy dÃ©crit dans la prÃ©sente section peut crÃ©er un nombre de niveaux arbitraire: il est plus complexe Ã  spÃ©cifier que les classificateurs de listes.</Text>
+<Figure id="part_of_the_file_sub">
+<Title>
+<Text id="618">Portion du fichier sub.txt</Text>
+</Title>
+<CodeLine>1           1       "General reference"</CodeLine>
+<CodeLine>1.2       1.2       "Dictionaries, glossaries, language courses, terminology</CodeLine>
+<CodeLine>2           2       "Sustainable Development, International cooperation, Pro</CodeLine>
+<CodeLine>2.1       2.1       "Development policy and theory, international cooperatio</CodeLine>
+<CodeLine>2.2       2.2       "Development, national planning, national plans"</CodeLine>
+<CodeLine>2.3       2.3       "Project planning and evaluation (incl. project managem</CodeLine>
+<CodeLine>2.4       2.4       "Regional development and planning incl. regional profil</CodeLine>
+<CodeLine>2.5       2.5       "Nongovernmental organisations (NGOs) in general, self-</CodeLine>
+<CodeLine>2.6       2.6       "Organisations, institutions, United Nations (general, d</CodeLine>
+<CodeLine>2.6.1   2.6.1       "United Nations"</CodeLine>
+<CodeLine>2.6.2   2.6.2       "International organisations"</CodeLine>
+<CodeLine>2.6.3   2.6.3       "Regional organisations"</CodeLine>
+<CodeLine>2.6.5   2.6.5       "European Community - European Union"</CodeLine>
+<CodeLine>2.7       2.7       "Sustainable Development, Development models and example</CodeLine>
+<CodeLine>2.8       2.8       "Basic Human Needs"</CodeLine>
+<CodeLine>2.9       2.9       "Hunger and Poverty Alleviation"</CodeLine>
+</Figure>
+<Text id="619">L'argumentÂ hfile donne le nom d'un fichier, tel que celui de la figureÂ <CrossRef target="Figure" ref="part_of_the_file_sub"/>, qui dÃ©finit la hiÃ©rarchie de mÃ©ta-donnÃ©es. Chaque ligne dÃ©crit une classification, et les descriptions comptent trois parties:</Text>
+<BulletList>
+<Bullet>
+<Text id="620">Un identifiant, qui fait correspondre la valeur de la mÃ©ta-donnÃ©e (donnÃ©e par l'argument metadata) Ã  la classification.</Text>
+</Bullet>
+<Bullet>
+<Text id="621">Un marqueur de position dans la hiÃ©rarchie, sous forme numÃ©rique en plusieurs parties, comme par exemple 2, 2.12, 2.12.6.</Text>
+</Bullet>
+<Bullet>
+<Text id="622">Le nom de la classification (s'il contient des espaces, il faut le placer entre apostrophes doubles).</Text>
+</Bullet>
+</BulletList>
+<Text id="623">La figureÂ <CrossRef target="Figure" ref="part_of_the_file_sub"/> est une portion du fichier sub.txt, utilisÃ© pour crÃ©er la hiÃ©rarchie de thÃšmes dans la bibliothÃšque de dÃ©veloppement pour l'HumanitÃ© (et dans la collection Â«DemoÂ»). Cet exemple n'est pas trÃšs clair puisque le nombre reprÃ©sentant la hiÃ©rarchie apparaÃ®t deux fois sur chaque ligne. Le type de mÃ©ta-donnÃ©e Hierarchy est reprÃ©sentÃ© dans les documents avec des valeurs sous forme numÃ©rique hiÃ©rarchique, ce qui correspond Ã  la premiÃšre occurrence. C'est la deuxiÃšme occurrence qui est utilisÃ©e pour dÃ©terminer la hiÃ©rarchie implÃ©mentÃ©e dans la hiÃ©rarchie de navigation.</Text>
+<Text id="624">Le classificateur hierarchy dispose d'un argument facultatif, sort, qui dÃ©termine la maniÃšre dont les documents sont ordonnÃ©s au niveau des feuilles. On peut spÃ©cifier n'importe quelle mÃ©ta-donnÃ©e comme clef de tri. Le comportement par dÃ©faut est de produire la liste dans l'ordre dans lequel le processus de construction rencontre les documents. Au niveau des noeuds internes, l'ordre est dÃ©terminÃ© par celui des spÃ©cifications dans l'argument hfile.</Text>
+</Content>
+</Subsection>
+<Subsection id="how_classifiers_work">
+<Title>
+<Text id="625">Fonctionnement des classificateurs</Text>
+</Title>
+<Content>
+<Text id="626">Les classificateurs sont des objets Perl, hÃ©ritant de BasClas.pm, et stockÃ©s dans le rÃ©pertoire perllib/classify. Ils sont utilisÃ©s lors de la construction de la collection. Leur exÃ©cution se fait en quatre Ã©tapes:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="627">La mÃ©thode new crÃ©e l'objet classificateur.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="628">La mÃ©thode init initialise l'objet avec des paramÃštres tels que le type de mÃ©ta-donnÃ©e, le nom du bouton, et le critÃšre de tri.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="629">La mÃ©thode classify est invoquÃ©e une fois par document, et stocke les informations de la classification effectuÃ©e dans l'objet classificateur. </Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="630">La mÃ©thode get_classify_info renvoie la classification stockÃ©e localement vers le processus de construction, qui l'Ã©crit Ã  son tour dans la base de donnÃ©es d'informations de la collection Ã  des fins d'utilisation lors de l'affichage de la collection, au moment de l'exÃ©cution.</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="631">La mÃ©thode classify rapatrie l'OID de chaque document, la valeur de mÃ©ta-donnÃ©e selon laquelle classifier le document, et, si nÃ©cessaire, la valeur de mÃ©ta-donnÃ©e selon laquelle trier les documents. La mÃ©thode get_classify_info s'occupe du tri et de tout traitement propre au classificateur. Dans le cas du classificateur AZList par exemple, elle ventile la liste en intervalles.</Text>
+<Text id="632">Le processus de construction initialise les classificateurs dÃšs que l'objet builder est construit. Les classifications sont crÃ©Ã©es pendant la phase de construction, lors de la crÃ©ation de la base de donnÃ©es d'informations, par classify.pm, qui rÃ©side dans le rÃ©pertoire perllib de Greenstone.</Text>
+<Table id="items_appearing_in_format_strings">
+<Title>
+<Text id="633">Objets apparaissant dans les chaÃ®nes de formatage</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="634"><i>[Text]</i></Text>
+</th>
+<th width="397">
+<Text id="635">Texte du document</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="636"><i>[link] âŠ [/link]</i></Text>
+</th>
+<th width="397">
+<Text id="637">Portion de HTML Ã  relier au document lui-mÃªme</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="638"><i>[icon]</i></Text>
+</th>
+<th width="397">
+<Text id="639">Une icone appropriÃ©e (telle que la petite icone de texte dans une chaÃ®ne<i>RÃ©sultats de la recherche</i>)</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="640"><i>[num]</i></Text>
+</th>
+<th width="397">
+<Text id="641">NumÃ©ro du document (utile pour dÃ©boguer)</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="642"><i>[metadata-name]</i></Text>
+</th>
+<th width="397">
+<Text id="643">Valeur de cet Ã©lÃ©ment de mÃ©ta-donnÃ©e pour le document, tel que<i>[Title]</i></Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="formatting_greenstone_output">
+<Title>
+<Text id="644">Mettre en forme la sortie de Greenstone</Text>
+</Title>
+<Content>
+<Text id="645">Les pages web que vous pouvez voir lorsque vous utilisez Greenstone ne sont stockÃ©es nulle part; elles sont gÃ©nÃ©rÃ©es Â«Ã  la volÃ©eÂ» en fonction des besoins. L'apparence de nombreux aspects de ces pages est contrÃŽlÃ©e Ã  l'aide de Â«chaÃ®nes de formatageÂ» (dans le sens de Â«mise en formeÂ», et pas de Â«remise Ã  zÃ©roÂ»). Les chaÃ®nes de formatage se trouvent dans le fichier de configuration de la collection, introduites par le mot-clef format lui-mÃªme suivi du nom de l'Ã©lÃ©ment concernÃ© par la mise en forme. Il existe deux types d'Ã©lÃ©ments de page contrÃŽlÃ©s par des chaÃ®nes de formatage. Le premier comprend les Ã©lÃ©ments de la page qui affichent des documents ou des portions de documents. Le second comprend les listes produites par les classificateurs et les recherches. Toutes les chaÃ®nes de formatage sont interprÃ©tÃ©es au moment de l'affichage des pages. Elles prennent donc effet dÃšs que le fichier collect.cfg est modifiÃ© et sauvegardÃ©; il est par consÃ©quent rapide et facile de faire des expÃ©riences avec les chaÃ®nes de formatage.</Text>
+<Text id="646">La tableÂ <CrossRef target="Table" ref="items_appearing_in_format_strings"/> montre les instructions qui affectent la reprÃ©sentation des documents. L'option DocumentButtons contrÃŽle les boutons qui sont affichÃ©s sur une page de document. Ici, chaÃ®ne est une liste de boutons (sÃ©parÃ©s par<i>|</i>), dont les valeurs possibles sont Detach (dÃ©tacher), Highlight (mettre en valeur), Expand Text (dÃ©velopper le texte), et Expand Contents (dÃ©velopper la table des matiÃšres). Modifier l'ordre de la liste a le mÃªme effet sur les boutons.</Text>
+<Table id="the_format_options">
+<Title>
+<Text id="647">Les options du mot-clef<i>format</i></Text>
+</Title>
+<TableContent>
+<tr>
+<th width="246">
+<Text id="648"><i>format DocumentImages true/false</i></Text>
+</th>
+<th width="283">
+<Text id="649">Si la valeur est<i>true</i>, affiche une image de couverture en haut Ã  gauche de la page du document (la valeur par dÃ©faut est<i>false</i>).</Text>
+</th>
+</tr>
+<tr>
+<th width="246">
+<Text id="650"><i>format DocumentHeading chaÃ®ne_de_formatage</i></Text>
+</th>
+<th width="283">
+<Text id="651">Si l'option<i>DocumentImages</i>a la valeur<i>false</i>, la chaÃ®ne de formatage contrÃŽle la reprÃ©sentation de l'en-tÃªte de document apparaissant en haut Ã  gauche de la page du document (la valeur par dÃ©faut est<i>[Title]</i>).</Text>
+</th>
+</tr>
+<tr>
+<th width="246">
+<Text id="652"><i>format DocumentContents true/false</i></Text>
+</th>
+<th width="283">
+<Text id="653">Affiche la table des matiÃšres (si le document a une structure hiÃ©rarchique), ou des flÃšches pour se rendre Ã  la section prÃ©cÃ©dente ou suivante et le texte Â«page k sur nÂ» (dans le cas contraire).</Text>
+</th>
+</tr>
+<tr>
+<th width="246">
+<Text id="654"><i>format DocumentButtons chaÃ®ne</i></Text>
+</th>
+<th width="283">
+<Text id="655">ContrÃŽle les boutons affichÃ©s sur une page de document (la valeur par dÃ©faut est<i>Detach|Highlight</i>).</Text>
+</th>
+</tr>
+<tr>
+<th width="246">
+<Text id="656"><i>format DocumentText chaÃ®ne_de_formatage</i></Text>
+</th>
+<th width="283">
+<Text id="657">Format du texte Ã  afficher sur une page de document; la valeur par dÃ©faut est</Text>
+<CodeLine>Â Â Â Â <i>&lt;center&gt;&lt;table width=537&gt;</i></CodeLine>
+<CodeLine><i>Â Â Â Â Â Â &lt;tr&gt;&lt;td&gt;[Text]&lt;/td&gt;&lt;/tr&gt;</i></CodeLine>
+<CodeLine><i>Â Â Â Â Â Â &lt;/table&gt;&lt;/center&gt;</i></CodeLine>
+</th>
+</tr>
+<tr>
+<th width="246">
+<Text id="658"><i>format DocumentArrowsBottom true/false</i></Text>
+</th>
+<th width="283">
+<Text id="659">Affiche des flÃšches pour se rendre Ã  la section prÃ©cÃ©dente ou suivante au pied de la page du document (la valeur par dÃ©faut est<i>true</i>, qui active ce comportement).</Text>
+</th>
+</tr>
+<tr>
+<th width="246">
+<Text id="660"><i>format DocumentUseHTML true/false</i></Text>
+</th>
+<th width="283">
+<Text id="661">Si la valeur est<i>true</i>, chaque document sera affichÃ© dans un cadre<i>frame</i>diffÃ©rent. La page de<i>PrÃ©fÃ©rences</i>changera un peu Ã©galement, et proposera de nouvelles options pour les documents HTML, telles que la possibilitÃ© de se rendre directement sur le document source original (partout sur le web) plutÃŽt que sur la copie faite par Greenstone.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Subsection id="formatting_greenstone_lists">
+<Title>
+<Text id="662">Formatage des listes de Greenstone</Text>
+</Title>
+<Content>
+<Text id="663">Les chaÃ®nes de formatage qui contrÃŽlent l'apparence des listes peuvent s'appliquer Ã  divers niveaux de la structure d'affichage. Elles peuvent altÃ©rer toutes les listes d'un certain type au sein d'une collection (comme par exemple DateList), toutes les parties d'une liste (comme par exemple toutes les entrÃ©es de la liste Rechercher), ou des portions spÃ©cifiques d'une liste particuliÃšre (comme par exemple la portion verticale de la liste du classificateur AZList appliquÃ© sur des titres).</Text>
+<Text id="664">Le mot-clef format prÃ©cÃšde un mot-clef en deux parties, dont une seule est obligatoire. La premiÃšre partie identifie la liste oÃ¹ s'applique le format. La liste gÃ©nÃ©rÃ©e par une recherche s'appelle Search (rechercher), tandis que les listes gÃ©nÃ©rÃ©es par des classificateurs sont appelÃ©es CL1, CL2, CL3,... pour respectivement le premier, le deuxiÃšme, le troisiÃšme... classificateur spÃ©cifiÃ© dans le fichier collect.cfg. La deuxiÃšme partie du mot-clef est la portion de la liste Ã  laquelle appliquer la mise en formeÂ --Â soit HList (pour une liste horizontale, telle que le sÃ©lecteur dans un noeud AZList), VList (pour une liste verticale, telle que la liste des tous les titres sous un noeud de type AZList), ou DateList. Par exemple:</Text>
+<Indented>
+<Text id="665">format CL4VList ... s'applique Ã  tous les VList de CL4</Text>
+</Indented>
+<Indented>
+<Text id="666">format CL2HList ... s'applique Ã  tous les HList de CL2</Text>
+</Indented>
+<Indented>
+<Text id="667">format CL1DateList ... s'applique Ã  tous les DateList de CL1</Text>
+</Indented>
+<Indented>
+<Text id="668">format SearchVList ... s'applique Ã  la liste de RÃ©sultats de la recherche</Text>
+</Indented>
+<Indented>
+<Text id="669">format CL3 ... s'applique Ã  tous les noeuds de CL3, sauf indication contraire</Text>
+</Indented>
+<Indented>
+<Text id="670">format VList ... s'applique Ã  tous les VList de tous les classificateurs, sauf indication contraire</Text>
+</Indented>
+<Text id="671">Les<i>"..."</i>de ces exemples reprÃ©sentent des spÃ©cifications de formatage HTML qui contrÃŽlent l'information et sa reprÃ©sentation, apparaissant sur des pages web reprÃ©sentant le classificateur. Comme pour les spÃ©cifications HTML, toute mÃ©ta-donnÃ©e peut apparaÃ®tre entre crochets: sa valeur est interpolÃ©e Ã  l'endroit indiquÃ©. Tout Ã©lÃ©ment de la tableÂ <CrossRef target="Table" ref="the_format_options"/> peut Ã©galement apparaÃ®tre dans des chaÃ®nes de formatage. La syntaxe des chaÃ®nes prÃ©voit Ã©galement une instruction conditionnelle, qui est illustrÃ©e plus bas.</Text>
+<Text id="672">Rappelez-vous que tous les classificateurs produisent des hiÃ©rarchies. Chaque niveau de la hiÃ©rarchie est affichÃ© de l'une de quatre maniÃšres possibles. Nous avons dÃ©jÃ  mentionnÃ© HList, VList, et DateList. Il existe Ã©galement Invisible, qui est la maniÃšre dont les tous premiers niveaux des hiÃ©rarchies sont reprÃ©sentÃ©sÂ --Â le nom du classificateur apparaÃ®t dÃ©jÃ  sÃ©parÃ©ment, en effet, sur la barre de navigation de Greenstone.</Text>
+</Content>
+</Subsection>
+<Subsection id="examples_of_classifiers_and_format_strings">
+<Title>
+<Text id="673">Exemples de classificateurs et de chaÃ®nes de formatage</Text>
+</Title>
+<Content>
+<Figure id="excerpt_from_the_demo_collection_collect" class="withLineNumber">
+<Title>
+<Text id="674">Extrait du fichier collect.cfg de la collection Â«DemoÂ»</Text>
+</Title>
+<CodeLine>classify Hierarchy -hfile sub.txt -metadata Subject -sort Title</CodeLine>
+<CodeLine>classify AZList       -metadata Title</CodeLine>
+<CodeLine>classify Hierarchy -hfile org.txt -metadata Organisation -sort Title</CodeLine>
+<CodeLine>classify List           -metadata Howto</CodeLine>
+<CodeLine>format SearchVList " &lt;td valign=top [link][icon][/link]&lt;/td&gt;&lt;td&gt;{If}</CodeLine>
+<CodeLine>                                       {[parent(All':'):Title],[parent(All':'):Title]:}</CodeLine>
+<CodeLine>                                       [link][Title][/link]&lt;/td&gt; "</CodeLine>
+<CodeLine>format CL4Vlist                 "&lt;br&gt;[link][Howto][/link] "</CodeLine>
+<CodeLine>format DocumentImages   true</CodeLine>
+<CodeLine>format DocumentText       "&lt;h3&gt;[Title]&lt;/h3&gt;\\n\\n&lt;p&gt;[Text]"</CodeLine>
+<CodeLine>format DocumentButtons " Expand Text|Expand contents|Detach|Highlight"</CodeLine>
+</Figure>
+<Text id="675">La figureÂ <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/> reprÃ©sente une portion du fichier de configuration de la collection Â«DemoÂ». Nous l'utilisons comme exemple, car il comprend plusieurs classificateurs avec un formatage riche. Remarquez que les instructions des fichiers de configuration ne peuvent pas contenir de retour Ã  la ligne, et que dans la figure, nous avons scindÃ© les lignes les plus longues pour des raisons de lisibilitÃ©.</Text>
+<Text id="676">La ligne 4 spÃ©cifie le classificateur How To (comment faire) de la collection Â«DemoÂ». C'est le quatriÃšme classificateur du fichier de configuration de la collection; on s'y rÃ©fÃšre donc sous le nom CL4. L'instruction de formatage correspondante est la ligne 7 de la figureÂ <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/>. Cette information d'Â«indiceÂ» est engendrÃ©e par le classificateur List, et sa structure est la liste brute des titres affichÃ©s figureÂ <CrossRef target="Figure" ref="list_classifier"/>. Les titres sont reliÃ©s aux documents eux-mÃªmes: cliquer sur un titre affiche le document correspondant. Les enfants du premier niveau de la hiÃ©rarchie sont affichÃ©s sous la forme d'une VList (liste verticale), qui liste les sections verticalement. Comme l'indique l'instruction format associÃ©e, chaque Ã©lÃ©ment de la liste apparaÃ®t sur une nouvelle ligne ("&lt;br&gt;") et contient le texte de Howto, lui-mÃªme reliÃ© par lien hypertexte au document lui-mÃªme.</Text>
+<Text id="677">La ligne 1 spÃ©cifie la classification Subject (ThÃšme) de la collection Â«DemoÂ», Ã  laquelle on se rÃ©fÃ©rera sous le nom CL1 (puisqu'elle est la premiÃšre du fichier de configuration), et la ligne 3 spÃ©cifie la classification Organisation CL3. Toutes deux sont gÃ©nÃ©rÃ©es par le classificateur Hierarchy et comprennent donc une structure hiÃ©rarchique d'objets VList.</Text>
+<Text id="678">La ligne 2 spÃ©cifie la derniÃšre classification de la collection Â«DemoÂ», titres A-Z (CL2). Remarquez qu'il n'existe pas de chaÃ®nes de formatage associÃ©es aux classificateurs CL1 Ã  CL3. Greenstone dispose de valeurs par dÃ©faut pour chaque type de chaÃ®ne de formatage; il n'est donc pas nÃ©cessaire de positionner une chaÃ®ne de formatage quand on ne souhaite pas obtenir un comportement diffÃ©rent du comportement par dÃ©faut.</Text>
+<Figure id="formatting_the_document">
+<Title>
+<Text id="679">Mise en forme du document</Text>
+</Title>
+<File width="394" height="277" url="images/Dev_Fig_17.png"/>
+</Figure>
+<Text id="680">VoilÃ  pour les quatre lignes classify de la figureÂ <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/>. On y trouve aussi quatre lignes format. Nous avons dÃ©jÃ  expliquÃ© la ligne CL4Vlist. Les trois lignes restantes sont du premier type de chaÃ®ne de formatage, documentÃ© dans la tableÂ <CrossRef target="Table" ref="items_appearing_in_format_strings"/>. Par exemple, la ligne 8 place l'image de couverture en haut Ã  gauche de chaque page de document. La ligne 9 formate le texte du document Ã  proprement parler, et place le titre du chapitre ou de la section concernÃ©e juste avant le texte. Tous ces effets sont illustrÃ©s dans la figureÂ <CrossRef target="Figure" ref="formatting_the_document"/>.</Text>
+<Figure id="formatting_the_search_results">
+<Title>
+<Text id="681">Mise en forme des rÃ©sultats de la recherche</Text>
+</Title>
+<File width="396" height="243" url="images/Dev_Fig_18.png"/>
+</Figure>
+<Text id="682">La ligne 5 de la figureÂ <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/> est une spÃ©cification quelque peu complexe qui formate la liste de rÃ©sultats Ã  une requÃªte renvoyÃ©e par une recherche, dont les portions sont illustrÃ©es Ã  la figureÂ <CrossRef target="Figure" ref="formatting_the_search_results"/>. Voici une version simplifiÃ©e de la chaÃ®ne de formatage:</Text>
+<CodeLine>&lt;td valign=top&gt;[link][icon][/link]&lt;/td&gt;</CodeLine>
+<CodeLine>&lt;td&gt;[link][Title][/link]&lt;/td&gt;</CodeLine>
+<Text id="683">Ceci est conÃ§u pour apparaÃ®tre comme une ligne dans un tableau, ce qui est la maniÃšre dont la liste de rÃ©sultats Ã  une requÃªte est mise en forme. Comme d'habitude, on obtient une petite icone cliquable qui mÃšne au texte, et le titre du document, ancre d'un lien hypertexte qui mÃšne au document Ã  proprement parler.</Text>
+<Text id="684">Dans cette collection, les documents sont hiÃ©rarchiques. En fait, l'ancre de lien hypertexte ci-dessus se transforme en le titre de la section renvoyÃ©e par le requÃªte. Il serait nÃ©anmoins prÃ©fÃ©rable de lui adjoindre Ã©galement le titre de la section qui la contient, du chapitre qui contient cette derniÃšre, et du livre oÃ¹ ce chapitre apparaÃ®t. Il existe un objet de mÃ©ta-donnÃ©e particulier, parent, qui n'est pas stockÃ© dans les documents mais qui est implicite dans tout document hiÃ©rarchique, qui produit une telle liste. Elle renvoie soit le document parent ou, si elle est utilisÃ©e avec le qualificateur All (tout), la liste de tous les ancÃªtres au sens hiÃ©rarchique, sÃ©parÃ©s par une chaÃ®ne de caractÃšres que l'on peut prÃ©ciser aprÃšs le qualificateur All. Ainsi:</Text>
+<CodeLine>&lt;td valign=top&gt;[link][icon][/link]&lt;/td&gt; <br/>&lt;td&gt;{[parent(All': '):Title]: }[link][Title][/link]&lt;/td&gt;</CodeLine>
+<Text id="685">a pour effet de produire une liste contenant le titre du livre, le titre du chapitre, etc., qui entourent la section cible; titres sÃ©parÃ©s par des caractÃšres deux points, et un dernier caractÃšre deux points est suivi d'un lien hypertexte menant au titre de la section cible.</Text>
+<Text id="686">Malheureusement, dans le cas oÃ¹ la cible est un livre, elle n'aura aucun parent et on verra donc apparaÃ®tre une chaÃ®ne vide suivie d'un caractÃšre deux points. Pour Ã©viter de tels problÃšmes, on peut utiliser dans une chaÃ®ne de formatage des instructions conditionnelles if and or ... else (si et ou ... sinon):</Text>
+<CodeLine>{If}{[metadata], action-if-non-null, action-if-null}</CodeLine>
+<CodeLine>{Or}{action, else another-action, else another-action, etc}</CodeLine>
+<Text id="687">Dans chaque cas les accolades signalent que les instructions doivent Ãªtre interprÃ©tÃ©es, et non pas simplement affichÃ©es comme du texte. L'instruction If teste si la mÃ©ta-donnÃ©e est vide, et prend la premiÃšre clause si ce n'est pas le cas, et la deuxiÃšme clause si c'est le cas (et si une deuxiÃšme clause est fournie). On peut utiliser tout Ã©lÃ©ment de mÃ©ta-donnÃ©es, y compris la mÃ©ta-donnÃ©e spÃ©ciale parent. L'instruction Or Ã©value chaque action tour Ã  tour jusqu'au moment oÃ¹ elle en rencontre une qui n'est pas vide. Cette action est alors renvoyÃ©e en sortie et le reste de la ligne est ignorÃ©.</Text>
+<Text id="688">Si l'on revient Ã  la ligne 5 de la figureÂ <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/>, la chaÃ®ne de formatage complÃšte est:</Text>
+<CodeLine>&lt;td valign=top&gt;[link][icon][/link]&lt;/td&gt;</CodeLine>
+<CodeLine>&lt;td&gt;{If}{[parent(All': '):Title],</CodeLine>
+<CodeLine>           [parent(All': '):Title]:}</CodeLine>    
+<CodeLine>      [link][Title][/link]&lt;/td&gt;</CodeLine>
+<Text id="689">Ceci fait prÃ©cÃ©der la spÃ©cification parent d'un test qui examine si le rÃ©sultat est vide et n'affiche la chaÃ®ne du parent que lorsque ce dernier est prÃ©sent. On peut aussi qualifier parent par Top (sommet) au lieu de All (tout), ce qui donne le nom de document de niveau le plus Ã©levÃ© qui entoure une sectionÂ --Â dans le cas prÃ©sent, le nom du livre. Nul besoin, avec Top, de chaÃ®ne de sÃ©paration.</Text>
+<Text id="690">Voici quelques derniers exemples pour illustrer d'autres fonctionnalitÃ©s. Le classificateur DateList, dans la figureÂ <CrossRef target="Figure" ref="datelist_classifier"/>, est utilisÃ© dans la classification Dates de la collection Computists' Weekly (l'hebdomadaire des informaticiens), et il se trouve qu'il en est le deuxiÃšme classificateur, soit CL2. Le classificateur et les spÃ©cifications de formatage sont indiquÃ©s ci-dessous. Le classificateur DateList diffÃšre d'AZList en ce sens qu'il trie toujours selon la mÃ©ta-donnÃ©e Date, et que les branches situÃ©es au pied de la hiÃ©rarchie de navigation utilisent DateList au lieu de VList, ce qui ajoute Ã  gauche des listes de documents, l'annÃ©e et le mois.</Text>
+<CodeLine>classify AZSectionList metadata=Creator</CodeLine>
+<CodeLine>format CL2Vlist "&lt;td&gt;[link][icon][/link]&lt;/td&gt; <br/>&lt;td&gt;[Creator]&lt;/td&gt; <br/>&lt;td&gt;&amp;nbsp;&amp;nbsp;[Title]&lt;/td&gt; <br/>&lt;td&gt;[parent(Top):Date]&lt;/td&gt; "</CodeLine>
+<Text id="691">La spÃ©cification de formatage affiche ces VLists de maniÃšre appropriÃ©e.</Text>
+<Text id="692">Le mÃ©canisme de chaÃ®ne de formatage est souple mais difficile Ã  apprendre. La meilleure maniÃšre de procÃ©der est d'Ã©tudier des fichiers de configuration de collections existantes.</Text>
+</Content>
+</Subsection>
+<Subsection id="linking_to_different_document_versions">
+<Title>
+<Text id="693">Tirer des liens vers diffÃ©rentes versions d'un document</Text>
+</Title>
+<Content>
+<Text id="694">Utiliser le mÃ©canisme<i>[link] ... [/link]</i>dans une chaÃ®ne de formatage a pour effet d'insÃ©rer un lien hypertexte menant au texte du document, en version HTML. Il est utile dans certaines collections de pouvoir afficher d'autres versions du document. Dans une collection de documents au format Microsoft Word, par exemple, il est bon d'Ãªtre capable d'afficher la version Word de chaque document plutÃŽt que le HTML qui en fut extrait; de mÃªme pour des documents PDF.</Text>
+<Text id="695">Pour pouvoir afficher diffÃ©rentes versions d'un document, la clef est d'embarquer les informations nÃ©cessaires (c'est-Ã -dire oÃ¹ se trouvent les autres versions du document) dans le format d'archivage de Greenstone du document. On reprÃ©sente cette information sous la forme de mÃ©ta-donnÃ©es. Souvenez-vous qu'en plaÃ§ant</Text>
+<CodeLine>[link][Title][/link]</CodeLine>
+<Text id="696">dans une chaÃ®ne de formatage, on crÃ©e un lien vers la version HTML du document, lien dont l'ancre est le titre du document. Les greffons Word et PDF gÃ©nÃ©rent tous deux la mÃ©ta-donnÃ©e srclink de telle sorte qu'Ã©crire</Text>
+<CodeLine>[srclink][Title][/srclink]</CodeLine>
+<Text id="697">dans une chaÃ®ne de formatage crÃ©era un lien vers la version Word ou PDF du document; lien dont l'ancre sera dans cet exemple aussi, le titre du document. Pour permettre d'afficher l'icone appropriÃ©e pour les documents Word et PDF, ces greffons gÃ©nÃ©rent aussi la mÃ©ta-donnÃ©e srcicon de telle sorte que</Text>
+<CodeLine>[srclink][srcicon][/srclink]</CodeLine>
+<Text id="698">crÃ©era un lien Ã©tiquetÃ© par l'icone standard pour le format Word ou PDF (selon le cas), et non pas par le titre du document.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="controlling_the_greenstone_user_interface">
+<Title>
+<Text id="699">ContrÃŽler l'interface utilisateur de Greenstone</Text>
+</Title>
+<Content>
+<Text id="700">L'interface utilisateur de Greenstone est entiÃšrement contrÃŽlÃ©e par des macros placÃ©es dans le rÃ©pertoire GSDLHOME/macros. Elles sont Ã©crites dans un langage conÃ§u spÃ©cialement pour Greenstone, et sont utilisÃ©es au moment de l'exÃ©cution pour engendrer des pages web. La traduction du langage de macros en HTML est la derniÃšre Ã©tape de l'affichage d'une page. Ainsi, toute modification Ã  un fichier de macros affecte immÃ©diatement l'affichage, il est donc rapide et facile de faire des expÃ©riences avec les macros. Tous les fichiers de macros utilisÃ©s par Greenstone sont listÃ©s dans le fichier GSDLHOME/etc/main.cfg et sont chargÃ©s Ã  chaque dÃ©marrage. Signalons l'exception de la version Â«BibliothÃšque localeÂ» sous Windows; dans ce cas il est nÃ©cessaire de redÃ©marrer le processus.</Text>
+<Text id="701">Les pages web sont gÃ©nÃ©rÃ©es Ã  la volÃ©e pour de nombreuses raisons, et le systÃšme de macros est la maniÃšre dont Greenstone implÃ©mente la souplesse nÃ©cessaire. On peut prÃ©senter des pages dans de nombreuses langues diffÃ©rentes, et on utilise un fichier de macros diffÃ©rent pour stocker tout le texte de l'interface dans chaque langue. Quand Greenstone affiche une page l'interprÃ©teur de macros consulte une variable de langue et charge la page dans la langue appropriÃ©e (ce systÃšme ne va pas, malheureusement, jusqu'Ã  traduire le contenu du document). De mÃªme, les valeurs de certaines variables d'affichage, telles que le nombre de documents trouvÃ©s par une recherche, ne sont pas connues Ã  l'avance: elles sont interpolÃ©es dans le texte de la page Ã  l'aide de macros.</Text>
+<Subsection id="the_macro_file_format">
+<Title>
+<Text id="702">Le format des fichiers de macros</Text>
+</Title>
+<Content>
+<Text id="703">Les fichiers de macros ont pour extension .dm. Chaque fichier dÃ©finit un ou plusieurs paquetages, et chaque paquetage dÃ©finit une sÃ©rie de macros utilisÃ©es dans un but prÃ©cis et unique. Ã l'instar des classificateurs et des greffons, il existe une base Ã  partir de laquelle construire des macros, appelÃ©e base.dm; ce fichier dÃ©finit le contenu de base d'une page.</Text>
+<Text id="704">Les macros portent des noms qui commencent et finissent par un caractÃšre de soulignement, et leur contenu est dÃ©fini Ã  l'aide d'accolades. Leur contenu peut consister en du texte brut, du HTML (y compris de liens vers des appliquettes (applets) Java ou du JavaScript), des noms de macros, ou toute combinaison de ces Ã©lÃ©ments. La macro suivante, extraite du fichier base.dm, dÃ©finit le contenu d'une page en l'absence de toute macro de remplacement:</Text>
+<CodeLine>_content_ {&lt;p&gt;&lt;h2&gt;Oops&lt;/h2&gt;_textdefaultcontent_}</CodeLine>
+<Text id="705">Cette page affichera Â«OopsÂ» Ã  son sommet, suivi du contenu de la macro d'erreur correspondante, _textdefaultcontent_ qui est en anglais dÃ©finie comme suit: Global:textdefaultcontentThe requested page could not be found. Please use your browsers 'back' button or the above home button to return to the Greenstone Digital Library.; dans d'autres langues, elle affichera une traduction appropriÃ©e de cette phrase. En franÃ§ais, on obtiendra par exemple Global:textdefaultcontentLa page demandÃ©e n'a pu Ãªtre trouvÃ©e. Utilisez s'il-vous-plaÃ®t le bouton Â«retourÂ» de votre navigateur, ou le bouton Â«accueilÂ» pour retourner Ã  la BibliothÃšque NumÃ©rique Greenstone.</Text>
+<Text id="706">Les deux macros _textdefaultcontent_ (contenu textuel par dÃ©faut) et _content_ (contenu) se trouvent dans le paquetage global car elles sont requises dans toutes les portions de l'interface utilisateur. Les macros peuvent utiliser des macros d'autres paquetages en tant que contenu, mais il faut alors qu'elles en prÃ©fixent les noms par le nom du paquetage. Exemple:</Text>
+<CodeLine>_collectionextra_ {This collection contains _about:numdocs_ documents. It was last built _about:builddate_ days ago.)</CodeLine>
+<Text id="707">provient du fichier french.dm (macros pour le franÃ§ais), et elle est utilisÃ©e comme description par dÃ©faut d'une collection. Elle fait partie du paquetage intitulÃ© global, mais les macros _numdocs_ et _builddate_ se trouvent toutes deux dans le paquetage about (Ã  propos de...)Â --Â d'oÃ¹ le about qui prÃ©fixe leurs noms.</Text>
+<Text id="708">Les macros renferment souvent des conditionnelles, qui ressemblent aux conditonnelles de chaÃ®nes de formatage dÃ©crites plus haut, Ã  ceci prÃšs que leur apparence est un peu diffÃ©rente. Le format de base est _If_(x,y,z), oÃ¹ x est une condition, y est le contenu de macro Ã  utiliser si cette condition est vÃ©rifiÃ©e, z le contenu Ã  utiliser dans le cas contraire. Les opÃ©rateurs de comparaison sont les mÃªmes que les opÃ©rateurs simples utilisÃ©s dans Perl (moins que, plus que, Ã©gale, diffÃ©rent de). L'exemple suivant, extrait du fichier base.dm, sert Ã  dÃ©terminer comment afficher le sommet de la page Ã propos de cette collection d'une collection:</Text>
+<CodeLine>_imagecollection_ {</CodeLine>
+<CodeLine>       _If_( "_iconcollection_ " ne "",</CodeLine>
+<CodeLine>                 &lt;a href = "_httppageabout_ "&gt; </CodeLine>
+<CodeLine>                         &lt;img src = "_iconcollection_ " border = 0&gt;</CodeLine>
+<CodeLine>                         &lt;/a&gt;,</CodeLine>
+<CodeLine>                 _imagecollectionv_)</CodeLine>
+<CodeLine>}</CodeLine>
+<Text id="709">VoilÃ  qui peut sembler abscons. La macro _iconcollection_ vaut la chaÃ®ne vide si la collection ne dispose pas d'une icone, ou le nom de l'image dans le cas contraire. Pour paraphraser le code ci-dessus en franÃ§ais: s'il existe une image de collection, afficher l'en-tÃªte de page Ã  propos (Ã  laquelle on se rÃ©fÃšre par _httppageabout_) et puis cette image; sinon afficher la solution de secours _imagecollectionv_.</Text>
+<Text id="710">Les macros peuvent prendre des arguments. Voici une autre dÃ©finition de la macro _imagecollection_, suivant immÃ©diatement la dÃ©finition donnÃ©e plus haut, dans le fichier base.dm:</Text>
+<CodeLine>_imagecollection_[v=1]{_imagecollectionv_}</CodeLine>
+<Text id="711">L'argument [v=1] spÃ©cifie qu'il faut utiliser cette deuxiÃšme dÃ©finition quand Greenstone fonctionne en mode texte seul. Les macros de langue fonctionnent de maniÃšre similaireÂ --Â Ã  l'exception du fichier english.dm, qui est le fichier utilisÃ© par dÃ©faut, toutes les macros de langue spÃ©cifient leur langue en argument. Par exemple:</Text>
+<CodeLine>_textimagehome_ {Home Page}</CodeLine>
+<Text id="712">apparaÃ®t dans le fichier de macros pour la langue anglaise, alors que la version allemande est:</Text>
+<CodeLine>_textimagehome_ [l=de] {Hauptaseite}</CodeLine>
+<Text id="713">Les versions anglaise et allemande se trouvent dans le mÃªme paquetage, bien qu'elles soient stockÃ©es dans des fichiers sÃ©parÃ©s (les dÃ©finitions de paquetages peuvent occuper plusieurs fichiers). Greenstone utilise son argument l au moment de l'exÃ©cution pour dÃ©cider quelle langue afficher.</Text>
+<Figure id="part_of_the_aboutdm_macro_file">
+<Title>
+<Text id="714">Portion du fichier de macro about.dm</Text>
+</Title>
+<CodeLine>package about</CodeLine>
+<CodeLine>##############################################</CodeLine>
+<CodeLine># about page content</CodeLine>
+<CodeLine>###############################################</CodeLine>
+<CodeLine>_pagetitle_ {_collectionname_}</CodeLine>
+<CodeLine>_content_ {</CodeLine>
+<CodeLine>&lt;center&gt;</CodeLine>
+<CodeLine>_navigationbar_</CodeLine>
+<CodeLine>&lt;/center&gt;</CodeLine>
+<CodeLine>_query:queryform_</CodeLine>
+<CodeLine>&lt;p&gt;_iconblankbar_</CodeLine>
+<CodeLine>&lt;p&gt;_textabout_</CodeLine>
+<CodeLine>_textsubcollections_</CodeLine>
+<CodeLine>&lt;h3&gt;_help:textsimplehelpheading_&lt;/h3&gt;</CodeLine>
+<CodeLine>_help:simplehelp_</CodeLine>
+<CodeLine>}</CodeLine>
+<CodeLine>_textabout_ {</CodeLine>
+<CodeLine>&lt;h3&gt;_textabcol_&lt;/h3&gt;</CodeLine>
+<CodeLine>_Global:collectionextra_</CodeLine>
+<CodeLine>}</CodeLine>
+</Figure>
+<Text id="715">Comme dernier exemple, la figureÂ <CrossRef target="Figure" ref="part_of_the_aboutdm_macro_file"/> montre un extrait du fichier de macros about.dm, utilisÃ© pour gÃ©nÃ©rer la page Ã  propos de chaque collection. Elle montre la dÃ©finition de trois macros, _pagetitle_ (titre de page), _content_ (contenu), et _textabout_ (texte Â«Ã  propos de...Â»).</Text>
+</Content>
+</Subsection>
+<Subsection id="using_macros">
+<Title>
+<Text id="716">Utiliser les macros</Text>
+</Title>
+<Content>
+<Text id="717">Les macros sont puissantes, et peuvent sembler un peu obscures. Mais avec une bonne connaissance de HTML et un peu de pratique elles deviennent une maniÃšre rapide et facile de personnaliser votre site Greenstone.</Text>
+<Text id="718">Supposons par exemple que vous souhaitiez crÃ©er une page statique qui ressemble Ã  votre site Greenstone actuel. Vous pouvez crÃ©er un nouveau paquetage, que vous appellerez static par exemple, dans un nouveau fichier, et y redÃ©finir la macro _content_. Ajoutez ce nom de fichier dans GSDLHOME/etc/main.cfg, que Greenstone charge Ã  chaque fois qu'il est invoquÃ©. Vous accÃ©derez Ã  la nouvelle page en utilisant votre URL habituelle pour Greenstone et en lui ajoutant les arguments ?a=p&amp;p=static (on obtiendra par exemple l'URL complÃšte suivante:http://serveur/cgi-bin/library?a=p&amp;p=static).</Text>
+<Text id="719">Pour modifier l'apparence et l'ergonomie de Greenstone vous pouvez Ã©diter les paquetages base et style. Pour modifier la page d'accueil de Greenstone, Ã©ditez le paquetage home (ceci est dÃ©crit dans le Guide d'installation de la bibliothÃšque numÃ©rique Greenstone). Pour modifier la page de requÃªtes, Ã©ditez le fichier query.dm.</Text>
+<Text id="720">ExpÃ©rimentez sans crainte avec les macros. Les modifications apparaissent instantanÃ©ment, puisque les macros sont interprÃ©tÃ©es lors de l'affichage des pages. Le langage de macros est un outil puissant que vous pouvez utiliser pour vous approprier vraiment votre site Greenstone.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="the_packages_directory">
+<Title>
+<Text id="721">Le rÃ©pertoire packages</Text>
+</Title>
+<Content>
+<Table id="the_packages_directory_1">
+<Title>
+<Text id="722">Le rÃ©pertoire<i>packages</i></Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="217">
+<Text id="723"><b>Paquetage</b></Text>
+</th>
+<th width="180">
+<Text id="724"><b>URL</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="725"><i>mg</i></Text>
+</th>
+<th width="217">
+<Text id="726">MG, abrÃ©viation de âManaging Gigabytesâ (gÃ©rer les giga-octets). Logiciel de compression, d'indexation et de recherche utilisÃ© pour gÃ©rer les donnÃ©es textuelles dans les collections de Greenstone.</Text>
+</th>
+<th width="180">
+<Text id="727"><i>www.citri.edu.au/mg</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="728"><i>wget</i></Text>
+</th>
+<th width="217">
+<Text id="729">Logiciel de miroir web utilisÃ© par Greenstone. Ãcrit en C++.</Text>
+</th>
+<th width="180">
+<Text id="730"><i>www.tuwien.ac.at/~prikryl/ wget.html</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="731"><i>w3mir</i></Text>
+</th>
+<th width="217">
+<Text id="732">Logiciel de miroir web Ã©crit en Perl. Ce n'est pas le programme de miroir web prÃ©fÃ©rÃ© par Greenstone car il repose sur une version spÃ©cifique mais dÃ©passÃ©e d'un certain module Perl (qui est distribuÃ© dans le rÃ©pertoire<i>w3mir</i>).</Text>
+</th>
+<th width="180">
+<Text id="733"><i>www.math.uio.no/~janl/w3mir</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="734"><i>windows</i></Text>
+</th>
+<th width="217">
+<Text id="735">Paquetages utilisÃ©s lors de l'exÃ©cution sous Windows.</Text>
+</th>
+<th width="180">
+<Text id="736"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="737"><i>windows/gdbm</i></Text>
+</th>
+<th width="217">
+<Text id="738">Version du gestionnaire de bases de donnÃ©es de GNU crÃ©Ã©e pour Windows. GDBM est fourni en standard sous Linux.</Text>
+</th>
+<th width="180">
+<Text id="739"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="740"><i>windows/crypt</i></Text>
+</th>
+<th width="217">
+<Text id="741">Programme de chiffrement utilisÃ© pour les mots de passe des fonctions administratives de Greenstone.</Text>
+</th>
+<th width="180">
+<Text id="742"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="743"><i>windows/stlport</i></Text>
+</th>
+<th width="217">
+<Text id="744">bibliothÃšque standard de patrons (<i>templates</i>), utilisÃ©e lors de la compilation de Greenstone avec certains compilateurs pour Windows.</Text>
+</th>
+<th width="180">
+<Text id="745"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="746"><i>wv</i></Text>
+</th>
+<th width="217">
+<Text id="747">Convertisseur du format Microsoft Word (pour construire des collections Ã  partir de documents Word), allÃ©gÃ©e pour Greenstone.</Text>
+</th>
+<th width="180">
+<Text id="748"><i>sourceforge.net/projects/wvware</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="749"><i>pdftohtml</i></Text>
+</th>
+<th width="217">
+<Text id="750">Convertisseur du format PDF utilisÃ© pour construire des collections Ã  partir de documents PDF.</Text>
+</th>
+<th width="180">
+<Text id="751"><i>www.ra.informatik.uni-stutt gart.de/~gosho/pdftohtml</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="752"><i>yaz</i></Text>
+</th>
+<th width="217">
+<Text id="753">Programme client Z39.50 utilisÃ© lors des expÃ©rimentations de recherche pour rendre Greenstone compatible Z39.50. Le fichier<i>README.gsdl</i>rend compte des progrÃšs Ã  ce sujet.</Text>
+</th>
+<th width="180">
+<Text id="754"><i>www.indexdata.dk</i></Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="755">Le rÃ©pertoire packages (paquetages), dont le contenu est reprÃ©sentÃ© dans la tableÂ <CrossRef target="Table" ref="the_packages_directory_1"/>, est l'endroit de stockage de tout le code utilisÃ© par Greenstone mais Ã©crit par des tiers ou d'autres Ã©quipes de recherche. Tout le logiciel distribuÃ© avec Greenstone a Ã©tÃ© publiÃ© sous la licence publique gÃ©nÃ©rale de GNU (GPL). Les exÃ©cutables produits par ces paquetages sont placÃ©s dans le rÃ©pertoire bin de Greenstone. Chaque paquetage est stockÃ© dans son propre rÃ©pertoire. Les diffÃ©rents paquetages ont des fonctions trÃšs diverses, allant de l'indexation et de la compression Ã  la conversion de documents du format Microsoft Word en HTML. Chaque paquetage dispose d'un fichier README (lisez-moi) qui fournit des informations complÃ©mentaires le concernant.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="the_greenstone_runtime_system">
+<Title>
+<Text id="756">Le systÃšme d'exÃ©cution de Greenstone</Text>
+</Title>
+<Content>
+<Text id="757">Le prÃ©sent chapitre dÃ©crit le systÃšme d'exÃ©cution de Greenstone pour que vous puissiez comprendre, augmenter et Ã©tendre ses fonctionnalitÃ©s. Le logiciel est Ã©crit en C++ est utilise intensivement l'hÃ©ritage virtuel. Si vous ne connaissez pas bien ce langage il est prÃ©fÃ©rable que vous l'appreniez avant de continuer la lecture. Deitel et Deitel (1994) proposent un didacticiel complet, mais la rÃ©fÃ©rence incontournable est le Stroustrup (1997).</Text>
+<Text id="758">Nous commenÃ§ons par expliquer la philosophie de la conception qui a sous-tendu le systÃšme d'exÃ©cution car elle a des consÃ©quences importantes sur l'implÃ©mentation. Nous fournissons ensuite les dÃ©tails d'implÃ©mentation, qui forment la partie principale de ce chapitre. La version de Greenstone dÃ©crite ici est la version CGI (ou version BibliothÃšque Web pour les utilisateurs de Windows). La version BibliothÃšque locale utilise le mÃªme code source mais dispose en frontal d'un serveur web intÃ©grÃ©. C'est Ã©galement un processus persistent.</Text>
+<Section id="process_structure">
+<Title>
+<Text id="759">Structure des processus</Text>
+</Title>
+<Content>
+<Figure id="overview_of_a_general_greenstone_system">
+<Title>
+<Text id="760">Vue d'ensemble d'un systÃšme Greenstone gÃ©nÃ©rique</Text>
+</Title>
+<File width="382" height="335" url="images/Dev_Fig_20.png"/>
+</Figure>
+<Text id="761">La figureÂ <CrossRef target="Figure" ref="overview_of_a_general_greenstone_system"/> montre plusieurs utilisateurs, reprÃ©sentÃ©s par des terminaux informatiques en haut du diagramme, en train d'accÃ©der Ã  trois collections Greenstone. Avant d'Ãªtre mises en ligne, ces collections subissent les processus d'import et de construction dÃ©crits dans les chapitres prÃ©cÃ©dents. Tout d'abord, les documents, reprÃ©sentÃ©s en bas de la figure, sont importÃ©s dans le format d'archivage de Greenstone, qui est compatible XML. Les fichiers d'archives servent ensuite Ã  la construction de plusieurs index de recherche et d'une base de donnÃ©es d'informations de la collection comprenant les structures hiÃ©rarchiques permettant la navigation. La collection est alors prÃªte Ã  Ãªtre mise en ligne et Ã  rÃ©pondre Ã  des requÃªtes d'informations.</Text>
+<Text id="762">Deux composants sont centraux dans la conception du systÃšme d'exÃ©cution: les Â«rÃ©ceptionnistesÂ» et les Â«serveurs de collectionÂ». Du point de vue de l'utilisateur, un rÃ©ceptionniste est le point de contact avec la bibliothÃšque numÃ©rique. Il accepte les donnÃ©es fournies par l'utilisateur, gÃ©nÃ©ralement sous la forme de saisies au clavier et de clics de souris; il les analyse; et il Ã©met ensuite une requÃªte au(x) serveur(s) de collection appropriÃ©s. Ce dernier localise l'information recherchÃ©e et la renvoie au rÃ©ceptionniste pour que ce dernier la prÃ©sente Ã  l'utilisateur. Les serveurs de collection se comportent comme un mÃ©canisme abstrait qui gÃšre le contenu de la collection, alors que les rÃ©ceptionnistes gÃšrent l'interface utilisateur.</Text>
+<Figure id="greenstone_system_using_the_null_protocol">
+<Title>
+<Text id="763">SystÃšme Greenstone utilisant le Â«protocole videÂ»</Text>
+</Title>
+<File width="329" height="424" url="images/Dev_Fig_21.png"/>
+</Figure>
+<Text id="764">Comme illustrÃ© dans la figureÂ <CrossRef target="Figure" ref="overview_of_a_general_greenstone_system"/>, les rÃ©ceptionnistes communiquent avec les serveurs de collection en utilisant un protocole dÃ©fini. L'implÃ©mentation de ce protocole dÃ©pend de l'ordinateur et de la configuration du systÃšme de bibliothÃšque numÃ©rique. Le cas le plus frÃ©quent et le plus simple est celui d'un rÃ©ceptionniste et d'un serveur de collection, fonctionnant tous deux sur le mÃªme ordinateur. C'est ce qui est produit par l'installation par dÃ©faut de Greenstone. Les deux processus sont alors combinÃ©s dans un unique exÃ©cutable (appelÃ© library), et le protocole se rÃ©duit par consÃ©quent Ã  des appels de fonctions. C'est ce que nous appelons le<i>protocole vide</i>(null protocol). C'est la base des systÃšmes de bibliothÃšque numÃ©rique Greenstone clef en main. Cette configuration simplifiÃ©e est illustrÃ©e figureÂ <CrossRef target="Figure" ref="greenstone_system_using_the_null_protocol"/>, oÃ¹ le rÃ©ceptionniste, le protocole et le serveur de collection sont regroupÃ©s sous la forme d'une unique entitÃ©, le programme library. Le prÃ©sent chapitre a pour but d'expliquer son fonctionnement.</Text>
+<Text id="765">Un Â«serveurÂ» est habituellement un processus persistent qui, une fois dÃ©marrÃ©, fonctionne indÃ©finiment, en rÃ©pondant aux requÃªtes entrantes. MalgrÃ© son nom, cependant, le serveur de collection dans la configuration du protocole vide n'est pas un serveur au sens habituel. En fait, Ã  chaque requÃªte d'une page web de Greenstone, le programme library est dÃ©marrÃ© (par le mÃ©canisme CGI), rÃ©pond Ã  la requÃªte, et quitte. Nous n'appelons le serveur de collection Â«serveurÂ» que parce qu'il est Ã©galement conÃ§u pour fonctionner dans la configuration plus gÃ©nÃ©rale de la figureÂ <CrossRef target="Figure" ref="overview_of_a_general_greenstone_system"/>.</Text>
+<Text id="766">De maniÃšre surprenante, ce cycle de dÃ©marrage, traitement, et fin d'exÃ©cution n'est pas aussi lent qu'on pourrait le craindre, et le service fourni est parfaitement utilisable. Il est clair cependant que ce systÃšme est inefficace. Un mÃ©canisme appelÃ© Fast-CGI (www.fastcgi.com) fournit un compromis. Si on l'utilise, le programme library demeure en mÃ©moire aprÃšs la premiÃšre exÃ©cution, et les lots suivants d'arguments CGI lui sont communiquÃ©s, ce qui Ã©vite les surcharges d'initialisation, et ressemble beaucoup Ã  un serveur au sens classique. Fast-CGI est une option dans Greenstone, que l'on active en recompilant le code source de Greenstone avec les bibliothÃšques appropriÃ©es.</Text>
+<Text id="767">Pour fournir un autre choix que le protocole vide, nous avons Ã©galement dÃ©veloppÃ© le protocole Greenstone en utilisant le cÃ©lÃšbre systÃšme CORBA (Slama<i>et al.</i>, 1999). Il utilise un paradigme orientÃ© objet unifiÃ© pour activer diffÃ©rents processus, fonctionnant sur diffÃ©rentes plates-formes, et implÃ©mentÃ©s en diffÃ©rents langages de programmation, pour accÃ©der au mÃªme ensemble d'objets distribuÃ©s sur l'Internet (ou tout autre rÃ©seau). Des scÃ©narios comme celui de la figureÂ <CrossRef target="Figure" ref="overview_of_a_general_greenstone_system"/> peuvent ensuite Ãªtre entiÃšrement implÃ©mentÃ©s, avec des rÃ©ceptionnistes et des serveurs de collection fonctionnant sur des ordinateurs diffÃ©rents.</Text>
+<Figure id="graphical_query_interface_to_greenstone">
+<Title>
+<Text id="768">Interface graphique de requÃªtes de Greenstone</Text>
+</Title>
+<File width="397" height="348" url="images/Dev_Fig_22.png"/>
+</Figure>
+<Text id="769">Ceci permet la mise en place d'interfaces bien plus sophistiquÃ©es pour mettre en place exactement les mÃªmes collections de bibliothÃšques numÃ©riques. Un exemple parmi tant d'autres, la figureÂ <CrossRef target="Figure" ref="graphical_query_interface_to_greenstone"/> reprÃ©sente une interface graphique de requÃªtes, fondÃ©e sur des diagrammes de Venn, qui permet aux utilisateurs de manipuler directement des requÃªtes boolÃ©ennes. Ãcrite en Java, cette interface fonctionne localement, sur l'ordinateur de l'utilisateur. Utilisant CORBA, elle accÃšde Ã  un serveur de collection Greenstone distant, Ã©crit en C++.</Text>
+<Text id="770">Ce protocole distribuÃ© faisant toujours l'objet de recherches en raffinement et utilisabilitÃ©, le prÃ©sent manuel ne le dÃ©taillera pas davantage (voir Bainbridge<i>et al.</i>, 2001, pour des informations complÃ©mentaires Ã  ce sujet). </Text>
+</Content>
+</Section>
+<Section id="conceptual_framework">
+<Title>
+<Text id="771">Cadre conceptuel</Text>
+</Title>
+<Content>
+<Figure id="generating_the_about_this_collection_page">
+<Title>
+<Text id="772">GÃ©nÃ©ration de la page Â«Ã  proposÂ»</Text>
+</Title>
+<File width="398" height="354" url="images/Dev_Fig_23.png"/>
+</Figure>
+<Text id="773">La figureÂ <CrossRef target="Figure" ref="generating_the_about_this_collection_page"/> reprÃ©sente la page Â«Ã  proposÂ» d'une collection Greenstone particuliÃšre (la collection du projet Gutenberg). Examinez l'URL au sommet de la figure: cette page est gÃ©nÃ©rÃ©e par l'exÃ©cution du programme CGI library, qui est l'exÃ©cutable mentionnÃ© plus haut, comprenant Ã  la fois le rÃ©ceptionniste et le serveur de collection, reliÃ©s entre eux par le protocole vide. Les arguments passÃ©s au programme library sont c=gberg, a=p, et p=about. On peut les interprÃ©ter comme suit:</Text>
+<Indented>
+<Text id="774"><i>Pour la collection du projet Gutenberg (c=gberg), l'action est de gÃ©nÃ©rer une page (a=p), et la page Ã  gÃ©nÃ©rer s'appelle aboutÂ --Â Ã  propos de ...Â --Â (p=about).</i></Text>
+</Indented>
+<Figure id="greenstone_runtime_system">
+<Title>
+<Text id="775">SystÃšme d'exÃ©cution de Greenstone</Text>
+</Title>
+<File width="534" height="345" url="images/Dev_Fig_24.png"/>
+</Figure>
+<Text id="776">La figureÂ <CrossRef target="Figure" ref="greenstone_runtime_system"/> illustre les portions principales du systÃšme d'exÃ©cution de Greenstone. Au sommet, le rÃ©ceptionniste initialise d'abord ses composants, puis analyse les arguments CGI pour savoir quelle action appeler. Lors de l'exÃ©cution de l'action (ce qui comprend d'autres traitements des arguments CGI), le logiciel utilise le protocole pour accÃ©der au contenu de la collection. La rÃ©ponse est utilisÃ©e pour gÃ©nÃ©rer une page web, avec l'aide du composant de mise en forme et du langage de macros.</Text>
+<Text id="777">Le langage de macros, que nous avons rencontrÃ© sectionÂ <CrossRef target="Section" ref="controlling_the_greenstone_user_interface"/>, fournit un systÃšme de bibliothÃšque numÃ©rique Greenstone d'un style consistant, et permet de crÃ©er des interfaces dans diffÃ©rentes langues. L'interaction avec la bibliothÃšque fournit les squelettes des pages web; les macros du rÃ©pertoire GSDLHOME/macros leur donnent chair.</Text>
+<Text id="778">L'objet de langage de macros reprÃ©sentÃ© figureÂ <CrossRef target="Figure" ref="greenstone_runtime_system"/> a pour rÃŽle de lire ces fichiers et de stocker le rÃ©sultat de l'analyse en mÃ©moire. Toute action peut utiliser cet objet pour dÃ©velopper une macro. On peut mÃªme crÃ©er de nouvelles dÃ©finitions de macros pour en Ã©craser d'anciennes, ce qui ajoute une dimension dynamique Ã  l'utilisation des macros.</Text>
+<Text id="779">La reprÃ©sentation de la page Â«Ã  proposÂ» (figureÂ <CrossRef target="Figure" ref="generating_the_about_this_collection_page"/>) est connue avant l'exÃ©cution, et consignÃ©e dans le fichier de macros about.dm. Les en-tÃªtes, les pieds, et l'image de fond n'y sont mÃªme pas mentionnÃ©s car ils se trouvent dans le paquetage de macros global. Cependant, le texte spÃ©cifique d'Â«Ã  proposÂ» d'une collection particuliÃšre n'est pas connu d'avance; il est stockÃ© dans la base de donnÃ©es d'informations de la collection lors du processus de construction. Cette information, rapatriÃ©e Ã  l'aide du protocole, est stockÃ©e sous _collectionextra_ dans le paquetage de macros global. Vous remarquerez que ce nom de macro ressemble presque exactement au nom utilisÃ© pour exprimer cette information dans le fichier de configuration de collection dÃ©crit sectionÂ <CrossRef target="Section" ref="configuration_file"/>. Pour gÃ©nÃ©rer le contenu de la page, la macro _content_ (contenu) du paquetage about (prÃ©sentÃ© figureÂ <CrossRef target="Figure" ref="part_of_the_aboutdm_macro_file"/>) est dÃ©veloppÃ©e, ce qui Ã  son tour dÃ©veloppe _textabout_ (texte d'Ã  propos), qui accÃšde Ã  la macro _collectionextra_, qui venait d'Ãªtre placÃ©e lÃ  de faÃ§on dynamique.</Text>
+<Text id="780">Un autre ingrÃ©dient important est l'objet de mise en forme, ou formatage. Les instructions de mise en forme du fichier de configuration de collection affectent la prÃ©sentation de portions particuliÃšres de la collection, comme nous l'avons expliquÃ© sectionÂ <CrossRef target="Section" ref="formatting_greenstone_output"/>. Elles sont gÃ©rÃ©es par l'objet de mise en forme reprÃ©sentÃ© figureÂ <CrossRef target="Figure" ref="greenstone_runtime_system"/>. La tÃ¢che principale de cet objet est d'analyser et d'Ã©valuer des instructions telles que les chaÃ®nes de formatage de la figureÂ <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/>. Comme nous l'avons vu en sectionÂ <CrossRef target="Section" ref="formatting_greenstone_output"/>, de telles chaÃ®nes peuvent comprendre des rÃ©fÃ©rences Ã  des mÃ©ta-donnÃ©es entre crochets (comme par exemple [Title] pour le titre), qu'il faut ensuite rapatrier du serveur de collection. Les objets de mise en forme et de langage de macros interagissent, car les instructions de formatage peuvent comprendre des macros qui, une fois dÃ©veloppÃ©es, incluent des mÃ©ta-donnÃ©es, qui une fois dÃ©veloppÃ©es incluent des macros, etc.</Text>
+<Text id="781">Le serveur de collection, au bas de la figureÂ <CrossRef target="Figure" ref="greenstone_runtime_system"/>, connaÃ®t lui aussi une phase d'initialisation, prÃ©parant les objets filtre et source pour rÃ©pondre Ã  des requÃªtes entrantes fournies selon le protocole, et un objet de recherche pour les assister dans cette tÃ¢che. Les objets de recherche accÃšdent en fin de chaÃ®ne aux index et Ã  la base de donnÃ©es d'informations de la collection, tous crÃ©Ã©s lors de la construction de la collection.</Text>
+<Text id="782">Si on ne compte pas les lignes vides, le rÃ©ceptionniste contient 15Â 000 lignes de code. Le serveur de collection en compte 5Â 000, dont les trois quarts correspondent Ã  des fichiers d'en-tÃªtes. Le serveur de collection est plus compact car le rapatriement de donnÃ©es se fait Ã  travers deux programmes prÃ©-compilÃ©s. MG, un systÃšme de rapatriement dans le corps du texte, sert Ã  la recherche, et GDBM, un systÃšme de gestion de bases de donnÃ©es, renferme la base de donnÃ©es d'informations de la collection.</Text>
+<Text id="783">Pour encourager extensibilitÃ© et souplesse, Greenstone utilise largement l'hÃ©ritageÂ --Â en particulier dans les objets d'action, de filtre, de source, et de recherche. Pour une simple bibliothÃšque numÃ©rique ne contenant que des collections textuelles, ceci signifie qu'il vous faudra en apprendre un peu plus pour programmer le systÃšme. Mais cela signifie aussi qu'on pourrait facilement remplacer MG et GDBM si le besoin devait un jour s'en faire sentir. De plus, l'architecture du logiciel est assez riche pour accepter toutes les fonctionnalitÃ©s multimÃ©dia, telles que le contrÃŽle de l'interface par des systÃšmes de reconnaissance vocale, ou la soumission de requÃªtes sous la forme d'images dessinÃ©es.</Text>
+</Content>
+</Section>
+<Section id="how_the_conceptual_framework_fits_together">
+<Title>
+<Text id="784">Agencement du cadre conceptuel</Text>
+</Title>
+<Content>
+<Text id="785">Les sectionsÂ <CrossRef target="Section" ref="collection_server"/> etÂ <CrossRef target="Section" ref="receptionist"/> dÃ©taillent le fonctionnement du serveur de collection et du rÃ©ceptionniste, en passant plus de temps sur chacun des modules de la figureÂ <CrossRef target="Figure" ref="greenstone_runtime_system"/> et en dÃ©crivant leur implÃ©mentation. Il est utile de commencer par travailler sur des exemples d'interaction utilisateur avec Greenstone et de dÃ©crire ce qui se passe en coulisses. Nous supposerons pour le moment que tous les objects sont correctement initialisÃ©s. L'initialisation est une procÃ©dure assez compliquÃ©e, que nous revisiterons dans la sectionÂ <CrossRef target="Section" ref="initialisation"/>.</Text>
+<Subsection id="performing_a_search">
+<Title>
+<Text id="786">Effectuer une recherche</Text>
+</Title>
+<Content>
+<Figure id="searching_gutenberg_for_darcy">
+<Title>
+<Text id="787">Recherche de Â«DarcyÂ» dans le projet Gutenberg</Text>
+</Title>
+<File width="396" height="353" url="images/Dev_Fig_25.png"/>
+</Figure>
+<Text id="788">Quand un utilisateur effectue une requÃªte en pressant le boutton DÃ©marrer la recherche sur la page de recherche, une nouvelle action de Greenstone est invoquÃ©e, qui aboutit Ã  la gÃ©nÃ©ration d'une nouvelle page HTML Ã  l'aide du langage de macros. La figureÂ <CrossRef target="Figure" ref="searching_gutenberg_for_darcy"/> montre le rÃ©sultat de la recherche dans la collection du projet Gutenberg du nom Darcy. La page de recherche comprenait originellement l'instruction a=q cachÃ©e dans le HTML. Cette instruction est activÃ©e lorsque le bouton de recherche est enfoncÃ©, et appelle l'action queryaction. L'exÃ©cution de queryaction effectue un appel Ã  l'objet de filtre de la collection (c=gberg) Ã  travers le protocole.</Text>
+<Text id="789">Les filtres sont une fonction de base importante des serveurs de collection. AdaptÃ©s aux activitÃ©s de recherche et de navigation, ils fournissent une maniÃšre de sÃ©lectionner un sous-ensemble d'informations dans la collection. Dans le cas prÃ©sent, queryaction met en place une requÃªte de filtre en:</Text>
+<BulletList>
+<Bullet>
+<Text id="790">plaÃ§ant le type de requÃªte de filtre Ã  QueryFilter (filtre de requÃªte; la sectionÂ <CrossRef target="Section" ref="collection_server"/> dÃ©crit les diffÃ©rents types de filtres);</Text>
+</Bullet>
+<Bullet>
+<Text id="791">stockant les prÃ©fÃ©rences de recherche de l'utilisateurÂ --Â sensibilitÃ© Ã  la casse, troncature et autresÂ --Â dans la requÃªte de filtre;</Text>
+</Bullet>
+<Bullet>
+<Text id="792">appelant la fonction filter() (filtre) Ã  travers le protocole vide.</Text>
+</Bullet>
+</BulletList>
+<Text id="793">Les appels du protocole sont synchrones: le rÃ©ceptionniste est effectivement bloquÃ© tant que la requÃªte de filtre n'a pas Ã©tÃ© traitÃ©e par le serveur de collection et que les donnÃ©es gÃ©nÃ©rÃ©es n'ont pas Ã©tÃ© renvoyÃ©es.</Text>
+<Text id="794">Lors d'un appel de protocole de type QueryFilter, l'objet de filtre (de la figureÂ <CrossRef target="Figure" ref="greenstone_runtime_system"/>) dÃ©code les options et effectue un appel Ã  l'objet de recherche, qui utilise MG pour la recherche proprement dite. L'objet de recherche a pour rÃŽle de fournir une interface abstraite de programme qui permet la recherche, indÃ©pendamment de l'outil de recherche utilisÃ© de faÃ§on sous-jacente. Le format utilisÃ© pour le renvoi des rÃ©sultats utilise lui aussi l'abstraction, ce qui oblige l'objet de recherche Ã  traduire les donnÃ©es gÃ©nÃ©rÃ©es par l'outil de recherche sous une forme standard.</Text>
+<Text id="795">Lorsque les rÃ©sultats de la recherche ont Ã©tÃ© renvoyÃ©s au rÃ©ceptionniste, la suite des Ã©vÃ©nements consiste Ã  mettre en forme les rÃ©sultats pour les afficher, en utilisant les objets de mise en forme et de langage de macros. Comme le montre la figureÂ <CrossRef target="Figure" ref="searching_gutenberg_for_darcy"/>, ceci suppose de gÃ©nÃ©rer l'en-tÃªte, le pied de page, la barre de navigation et le fond de page standard de Greenstone; de rÃ©pÃ©ter la partie principale de la page de requÃªtes juste en dessous de la barre de navigation; et d'afficher une icone de livre ainsi que le titre et l'auteur pour chacun des rÃ©sultats de la recherche. La mise en forme de cette derniÃšre partie est dictÃ©e par l'instruction format SearchVList du fichier de configuration de collection. Avant qu'on puisse afficher les mÃ©ta-donnÃ©es de titre et d'auteur, il faut les rapatrier depuis le serveur de collection, ce qui suppose des appels supplÃ©mentaires Ã  travers le protocole, en utilisant cette fois BrowseFilter (filtre de navigation).</Text>
+</Content>
+</Subsection>
+<Subsection id="retrieving_a_document">
+<Title>
+<Text id="796">Rapatrier un document</Text>
+</Title>
+<Content>
+<Text id="797">Ã la suite de la requÃªte prÃ©cÃ©dente pour Darcy, voyons ce qui se passe lors de l'affichage d'un document. La figureÂ <CrossRef target="Figure" ref="the_golf_course_mystery"/> montre ce qui se passe quand on clique sur l'icone jouxtant le titre The Golf Course Mystery (le mystÃšre du parcours de golf) dans la figureÂ <CrossRef target="Figure" ref="searching_gutenberg_for_darcy"/>.</Text>
+<Figure id="the_golf_course_mystery">
+<Title>
+<Text id="798">The Golf Course Mystery (le mystÃšre du parcours de golf)</Text>
+</Title>
+<File width="393" height="349" url="images/Dev_Fig_26.png"/>
+</Figure>
+<Text id="799">Le texte source de la collection Gutenberg consiste en un long fichier par livre. Au moment de la construction, ces fichiers sont ventilÃ©s sous forme de pages diffÃ©rentes environ toutes les 200 lignes, et les informations relatives Ã  chaque page sont stockÃ©es dans les index et la base de donnÃ©es d'informations de la collection. Au sommet de la figureÂ <CrossRef target="Figure" ref="the_golf_course_mystery"/> on constate que ce livre comprend 104 pages engendrÃ©es automatiquement, et on remarque juste en dessous le dÃ©but de la premiÃšre page: le copiste, le titre, l'auteur, et le dÃ©but d'une table des matiÃšres (qui fait partie du texte source de Gutenberg; elle n'a pas Ã©tÃ© engendrÃ©e par Greenstone). En haut Ã  gauche on trouve des boutons qui contrÃŽlent la mise en forme du document: une seule page ou tout le document; s'il faut mettre en valeur le terme de la requÃªte ou non; et s'il faut que le livre soit ou non affichÃ© dans sa propre fenÃªtre, dÃ©tachÃ©e des activitÃ©s principales de recherche et de navigation. En haut Ã  droite on trouve une aide Ã  la navigation qui propose un accÃšs direct Ã  n'importe quelle page du livre: il suffit de taper le numÃ©ro de la page et d'enfoncer le bouton Â«aller Ã  la pageÂ». On peut aussi se rendre aux pages prÃ©cÃ©dente ou suivante en cliquant sur les icones de flÃšches aux cÃŽtÃ©s de l'outil de sÃ©lection de page.</Text>
+<Text id="800">L'action de rapatriement des documents, documentaction, est spÃ©cifiÃ©e par a=d et elle accepte quelques arguments supplÃ©mentaires. Le plus important est le document Ã  rapatrier: il est spÃ©cifiÃ© par la variable d. Dans la figureÂ <CrossRef target="Figure" ref="the_golf_course_mystery"/>, il a la valeur<i>d=HASH51e598821ed6cbbdf0942b.1</i>pour rapatrier la premiÃšre page du document d'identifiant<i>HASH51e598821ed6cbbdf0942b</i>qui s'appelle aussi, de maniÃšre plus agrÃ©able, The Golf Course Mystery (le mystÃšre du parcours de golf). Il existe d'autres variables, spÃ©cifiant s'il faut ou non mettre en valeur le terme de la requÃªte (hl, pour highlighting) et quelle page du livre afficher (gt). Ces variables permettent de proposer les fonctionnalitÃ©s offertes par les boutons prÃ©sentÃ©s sur la page web de la figureÂ <CrossRef target="Figure" ref="the_golf_course_mystery"/>, et dÃ©crits ci-dessus. Si l'une de ces variables manque Ã  l'appel, c'est le comportement par dÃ©faut correspondant qui sera utilisÃ©.</Text>
+<Text id="801">Cette action suit une procÃ©dure similaire Ã  celle de queryaction: Ã©valuation des arguments CGI, accÃšs au serveur de collection en utilisant le protocole, et utilisation du rÃ©sultat pour engendrer une page web. Les options relatives au document sont dÃ©codÃ©es Ã  partir des arguments CGI et stockÃ©es dans l'objet pour plus tard. Pour rapatrier le document depuis le serveur de collection, on n'a besoin que de l'identifiant de document pour effectuer l'appel de protocole Ã  get_document() (obtenir le document). AprÃšs l'envoi du texte, un travail considÃ©rable de remise en forme est nÃ©cessaire. Pour ce faire, le code de documentaction accÃšde aux arguments stockÃ©s dans l'objet et utilise les objets de mise en forme et de langage de macros.</Text>
+</Content>
+</Subsection>
+<Subsection id="browsing_a_hierarchical_classifier">
+<Title>
+<Text id="802">Navigation dans un classificateur hiÃ©rarchique</Text>
+</Title>
+<Content>
+<Text id="803">La figureÂ <CrossRef target="Figure" ref="browsing_titles_in_the_gutenberg_collection"/> montre un exemple de navigation, oÃ¹ l'utilisateur a choisi titres A-Z et choisi le lien hypertexte de la lettre K. C'est Ã©galement documentaction qui gÃšre cela, ce qu'on constate en observant l'argument CGI a=d, comme prÃ©cÃ©demment. Cependant, alors qu'auparavant la requÃªte CGI comprenait une variable d, il n'y en a aucune cette fois-ci. Ã la place, le noeud Ã  afficher pour navigation dans la hiÃ©rarchie de classification est spÃ©cifiÃ© dans la variable cl. Dans notre cas, ceci reprÃ©sente les titres groupÃ©s sous la lettre K. Cette liste a Ã©tÃ© formÃ©e au moment de la construction et fut stockÃ©e dans la base de donnÃ©es d'informations de la collection.</Text>
+<Figure id="browsing_titles_in_the_gutenberg_collection">
+<Title>
+<Text id="804">Navigation dans les titres de la collection Gutenberg</Text>
+</Title>
+<File width="394" height="351" url="images/Dev_Fig_27.png"/>
+</Figure>
+<Text id="805">Les enregistrements reprÃ©sentant des noeuds de classificateur dans la base de donnÃ©es utilisent le prÃ©fixe CL, suivi de nombres sÃ©parÃ©s par des points (.) pour dÃ©signer oÃ¹ ils rÃ©sident au sein de la structure rÃ©cursive. Si on ignore le bouton de recherche, situÃ© tout Ã  gauche de la barre de navigation, les classificateurs sont numÃ©rotÃ©s sÃ©quentiellement et par ordre croissant, de gauche Ã  droite, en commenÃ§ant Ã  1. Ainsi, le noeud de classificateur de premier niveau pour les titres dans notre exemple est CL1 et la page recherchÃ©e est engendrÃ©e en positionnant cl=CL1.11. On peut observer cela dans l'URL au sommet de la figureÂ <CrossRef target="Figure" ref="browsing_titles_in_the_gutenberg_collection"/>.</Text>
+<Text id="806">Lors du traitement d'une requÃªte de document de type cl, l'objet de filtre est utilisÃ© pour rapatrier le noeud Ã  travers le protocole. Selon les donnÃ©es renvoyÃ©es, d'autres appels de protocole sont effectuÃ©s pour rapatrier les mÃ©ta-donnÃ©es des documents. Dans le cas prÃ©sent, ce sont les titres des livres qui sont rapatriÃ©s. Mais si le noeud avait Ã©tÃ© un noeud interne dont les fils avaient eux-mÃªmes Ã©tÃ© des noeuds, les titres des noeuds fils auraient eux aussi Ã©tÃ© rapatriÃ©s. Du point de vue du code cela revient Ã  la mÃªme chose, et c'est gÃ©rÃ© par le mÃªme mÃ©canisme.</Text>
+<Text id="807">Enfin, toutes les informations rapatriÃ©es sont reliÃ©es les unes aux autres Ã  l'aide du langage de macros, pour produire la page web reprÃ©sentÃ©e figureÂ <CrossRef target="Figure" ref="browsing_titles_in_the_gutenberg_collection"/>.</Text>
+</Content>
+</Subsection>
+<Subsection id="generating_the_home_page">
+<Title>
+<Text id="808">GÃ©nÃ©ration de la page d'accueil</Text>
+</Title>
+<Content>
+<Figure id="greenstone_home_page">
+<Title>
+<Text id="809">Page d'accueil de Greenstone</Text>
+</Title>
+<File width="397" height="393" url="images/Dev_Fig_28.png"/>
+</Figure>
+<Text id="810">Comme dernier exemple, examinons le cas de la gÃ©nÃ©ration de la page d'accueil de Greenstone. La figureÂ <CrossRef target="Figure" ref="greenstone_home_page"/> montreÂ --Â dans le cas de l'installation par dÃ©faut de GreenstoneÂ --Â la page d'accueil aprÃšs l'installation de certaines collections de test. Son URL, qu'on peut voir au sommet de la capture d'Ã©cran, comprend les arguments a=p et p=home. Ainsi, Ã  l'instar de la page Â«Ã  proposÂ», elle a Ã©tÃ© engendrÃ©e par pageaction (a=p), mais dans le cas prÃ©sent la page Ã  produire est la page homeÂ --Â accueilÂ --Â (p=home). Le langage de macros accÃšde par consÃ©quent au fichier home.dm. Nul besoin de spÃ©cifier une collection (Ã  l'aide de la variable c) dans le cas prÃ©sent.</Text>
+<Text id="811">La page d'accueil a pour but de prÃ©senter les collections disponibles. Cliquer sur une icone emmÃšne l'utilisateur sur la page Ã  propos de la collection choisie. Le menu des collections est gÃ©nÃ©rÃ© automatiquement Ã  chaque chargement de la page, en se fondant sur les collections prÃ©sentes dans le systÃšme de fichiers Ã  ce moment-lÃ . Quand une nouvelle collection est mise en ligne, elle apparaÃ®t automatiquement sur la page d'accueil lorsque cette page est rechargÃ©e ou rÃ©actualisÃ©e, pour peu que cette collection ait Ã©tÃ© spÃ©cifiÃ©e comme Â«publiqueÂ».</Text>
+<Text id="812">Pour ce faire, le rÃ©ceptionniste utilise, Ã©videmment, le protocole. Dans le cadre de l'Ã©valuation des arguments CGI, pageaction est programmÃ© pour dÃ©tecter le cas particulier p=home. L'action utilise alors get_collection_list() (obtenir la liste des collections), appel de protocole servant Ã  Ã©tablir l'ensemble actuel de collections mises en ligne. Pour chacune de ces collections il appelle get_collectinfo() (obtenir les informations de collection) pour recevoir les informations la concernant. Ces informations prÃ©cisent si la collection est publiquement disponible, quelle est l'URL menant Ã  l'icone de la collection (si une telle icone existe), et le nom complet de la collection, et elles sont utilisÃ©es pour gÃ©nÃ©rer l'entrÃ©e appropriÃ©e sur la page d'accueil de la collection.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="source_code">
+<Title>
+<Text id="813">Code source</Text>
+</Title>
+<Content>
+<Table id="standalone_programs_included_in_greenstone">
+<Title>
+<Text id="814">Programmes indÃ©pendants inclus dans Greenstone</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="815"><i>setpasswd/</i></Text>
+</th>
+<th width="397">
+<Text id="816">Support des mots de passe sous Windows.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="817"><i>getpw/</i></Text>
+</th>
+<th width="397">
+<Text id="818">Support des mots de passe sous Unix.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="819"><i>txt2db/</i></Text>
+</th>
+<th width="397">
+<Text id="820">Convertit un format de texte ASCII Ã  la XML en le format de la base de donnÃ©es de GNU.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="821"><i>db2txt/</i></Text>
+</th>
+<th width="397">
+<Text id="822">Convertit le format de la base de donnÃ©es de GNU en un format de texte ASCII Ã  la XML.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="823"><i>phind/</i></Text>
+</th>
+<th width="397">
+<Text id="824">Outil de navigation hiÃ©rarchique dans les groupes de mots.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="825"><i>hashfile/</i></Text>
+</th>
+<th width="397">
+<Text id="826">Calcule un identifiant de document unique, fondÃ© sur le contenu du fichier.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="827"><i>mgpp/</i></Text>
+</th>
+<th width="397">
+<Text id="828">Version rÃ©-Ã©crite et mise Ã  jour du paquetage<i>Managing Gigabytes</i>(gÃ©rer les giga-octets), en C++.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="829"><i>w32server/</i></Text>
+</th>
+<th width="397">
+<Text id="830">Serveur de bibliothÃšque locale pour Windows.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="831"><i>checkis/</i></Text>
+</th>
+<th width="397">
+<Text id="832">Support spÃ©cifique pour l'installation de Greenstone sous Windows. </Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="833">Le code source du systÃšme d'exÃ©cution se trouve dans GSDLHOME/src. Il occupe deux sous-rÃ©pertoires, recpt pour le code du rÃ©ceptionniste, et colservr pour celui du serveur de collection. Greenstone fonctionne sur les systÃšmes Windows Ã  partir de la version 3.1, qui impose malheureusement une limite de huit caractÃšres sur les noms de fichiers et de rÃ©pertoires; c'est ce qui explique l'utilisation d'abrÃ©viations cryptiques telles que recpt et colservr. Les sous-rÃ©pertoires restants comprennent des outils indÃ©pendants, principalement utilisÃ©s en renfort du processus de construction. Ils sont listÃ©s dans la tableÂ <CrossRef target="Table" ref="standalone_programs_included_in_greenstone"/>.</Text>
+<Text id="834">Un autre rÃ©pertoire, GSDLHOME/lib, inclut des objets de bas niveau utilisÃ©s Ã  la fois par le rÃ©ceptionniste et par le serveur de collection. Ce code est dÃ©crit dans la sectionÂ <CrossRef target="Section" ref="common_greenstone_types"/>.</Text>
+<Text id="835">Greenstone utilise Ã©normÃ©ment la bibliothÃšque standard de patrons (STL), une bibliothÃšque bibliothÃšque trÃšs rÃ©pandue de code C++, dÃ©veloppÃ©e par Silicon Graphics (www.sgi.com), et qui est l'aboutissement de nombreuses annÃ©es de conception et de dÃ©veloppement. Ã l'instar de toutes les bibliothÃšques de programmation, il faut un certain temps pour l'apprendre. L'annexeÂ AppendixA donne un bref aperÃ§u de ses principales portions utilisÃ©es tout au long du code de Greenstone. Pour une description plus dÃ©taillÃ©e, consultez le manuel de rÃ©fÃ©rence officiel de STL, disponible en ligne sur le site webwww.sgi.com, ou l'un des nombreux manuels traitant de STL, tel que celui de Josuttis (1999).</Text>
+</Content>
+</Section>
+<Section id="common_greenstone_types">
+<Title>
+<Text id="836">Types de base de Greenstone</Text>
+</Title>
+<Content>
+<Text id="837">Les objets dÃ©finis dans le rÃ©pertoire GSDLHOME/lib sont des objets de bas niveau de Greenstone, construits par-dessus STL, et qui sont utilisÃ©s tout au long du code source. Nous dÃ©taillons tout d'abord text_t, un objet utilisÃ© pour reprÃ©senter du texte Unicode. Nous rÃ©sumerons ensuite le but de chacun des fichiers de bibliothÃšque.</Text>
+<Subsection id="the_text_t_object">
+<Title>
+<Text id="838">L'objet text_t</Text>
+</Title>
+<Content>
+<Text id="839">Greenstone fonctionne avec de nombreuses langues, tant pour le contenu d'une collection que pour l'interface utilisateur. Pour gÃ©rer cela, nous avons utilisÃ© Unicode tout au long du code source, et l'objet sous-jacent qui rÃ©alise une chaÃ®ne Unicode s'appelle text_t.</Text>
+<Figure id="the_text_t_api" class="withLineNumber">
+<Title>
+<Text id="840">API de text_t (abrÃ©gÃ©e)</Text>
+</Title>
+<CodeLine>typedef vector&lt;unsigned short&gt; usvector;</CodeLine>
+<CodeLine/>
+<CodeLine>class text_t {</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>usvector text;</CodeLine>
+<CodeLine>unsigned short encoding; // 0 = unicode, 1 = other</CodeLine>
+<CodeLine/>
+<CodeLine>public:</CodeLine>
+<CodeLine>   // constructors</CodeLine>
+<CodeLine>   text_t ();</CodeLine>
+<CodeLine>   text_t (int i);</CodeLine>
+<CodeLine>   text_t (char *s); // assumed to be a normal c string</CodeLine>
+<CodeLine/>
+<CodeLine>   void setencoding (unsigned short theencoding);</CodeLine>
+<CodeLine>   unsigned short getencoding ();</CodeLine>
+<CodeLine/>
+<CodeLine>   // STL container support</CodeLine>
+<CodeLine>   iterator begin ();</CodeLine>
+<CodeLine>   iterator end ();</CodeLine>
+<CodeLine/>
+<CodeLine>   void erase(iterator pos);</CodeLine>
+<CodeLine>   void push_back(unsigned short c);</CodeLine>
+<CodeLine>   void pop_back();</CodeLine>
+<CodeLine/>
+<CodeLine>   void reserve (size_type n);</CodeLine>
+<CodeLine/>
+<CodeLine>   bool empty () const {return text.empty();}</CodeLine>
+<CodeLine>   size_type size() const {return text.size();}</CodeLine>
+<CodeLine/>
+<CodeLine>   // added functionality</CodeLine>
+<CodeLine>   void clear ();</CodeLine>
+<CodeLine>   void append (const text_t &amp;t);</CodeLine>
+<CodeLine/>
+<CodeLine>   // support for integers</CodeLine>
+<CodeLine>   void appendint (int i);</CodeLine>
+<CodeLine>   void setint (int i);</CodeLine>
+<CodeLine>   int getint () const;</CodeLine>
+<CodeLine/>
+<CodeLine>   // support for arrays of chars</CodeLine>
+<CodeLine>   void appendcarr (char *s, size_type len);</CodeLine>
+<CodeLine>   void setcarr (char *s, size_type len);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="841">Unicode stocke chaque caractÃšre sur deux octets. La figureÂ <CrossRef target="Figure" ref="the_text_t_api"/> montre les fonctionnalitÃ©s principales de l'interface de programmation (API, pour Application Program Interface) de text_t. Les deux octets sont assurÃ©s par l'utilisation du type standard C++ short, dÃ©fini comme Ã©tant un entier sur deux octets. Le type de donnÃ©es central de l'objet text_t est un tableau dynamique de short non signÃ©s, construit par la dÃ©claration STL vector&lt;unsigned short&gt;, et baptisÃ© usvector (pour unsigned short vector).</Text>
+<Text id="842">Les fonctions de construction (lignes 10-12) gÃšrent explicitement trois formes d'initialisation: construction sans paramÃštres, qui engendre une chaÃ®ne Unicode vide; construction avec un paramÃštre entier, qui engendre une version texte Unicode de la valeur numÃ©rique fournie; et construction avec un paramÃštre char*, qui traite l'argument comme une chaÃ®ne C++ terminÃ©e par un caractÃšre nul et en gÃ©nÃšre une version Unicode.</Text>
+<Text id="843">Ensuite, la plus grande partie du code (lignes 17-28) s'occupe de maintenir un conteneur de type vecteur STL: begin() (dÃ©but), end() (fin), push_back() (remettre), empty() (vide), etc. On peut aussi effacer des chaÃ®nes, concatÃ©ner des chaÃ®nes, ainsi que convertir une valeur entiÃšre dans une chaÃ®ne de texte Unicode et renvoyer la valeur entiÃšre correspondant Ã  un texte qui reprÃ©sente un nombre.</Text>
+<Figure id="overloaded_operators_to_text_t" class="withLineNumber">
+<Title>
+<Text id="844">OpÃ©rateurs surchargÃ©s pour text_t</Text>
+</Title>
+<CodeLine>class text_t {</CodeLine>
+<CodeLine>   // ...</CodeLine>
+<CodeLine>   public:</CodeLine>
+<CodeLine>   text_t &amp;operator=(const text_t &amp;x);</CodeLine>
+<CodeLine>   text_t &amp;operator+= (const text_t &amp;t);</CodeLine>
+<CodeLine>   reference operator[](size_type n);</CodeLine>
+<CodeLine/>
+<CodeLine>   text_t &amp;operator=(int i);</CodeLine>
+<CodeLine>   text_t &amp;operator+= (int i);^ \\</CodeLine>
+<CodeLine>   text_t &amp;operator= (char *s);</CodeLine>
+<CodeLine>   text_t &amp;operator+= (char *s);</CodeLine>
+<CodeLine/>
+<CodeLine>   friend inline bool operator!=(const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>   friend inline bool operator==(const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>   friend inline bool operator&lt; (const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>   friend inline bool operator&gt; (const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>   friend inline bool operator&gt;=(const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>   friend inline bool operator&lt;=(const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>   // ...</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="845">De nombreux opÃ©rateurs surchargÃ©s n'apparaissent pas dans la figureÂ <CrossRef target="Figure" ref="the_text_t_api"/>. Ils sont montrÃ©s dans la figureÂ <CrossRef target="Figure" ref="overloaded_operators_to_text_t"/> pour donner un avant-goÃ»t des opÃ©rations possibles. La ligne 4 permet l'affectation d'un objet text_t Ã  un autre, et la ligne 5 surcharge l'opÃ©rateur +=, pour fournir une maniÃšre plus naturelle de concatÃ©ner un objet text_t Ã  la fin d'un autre. Il est Ã©galement possible, Ã  travers la ligne 6, d'accÃ©der Ã  un caractÃšre Unicode particulier (reprÃ©sentÃ© sous la forme d'un short) en utilisant des indices de tableaux [ ]. On fournit aussi des opÃ©rateurs d'affectation et de concatÃ©nation pour les entiers et les chaÃ®nes C++. Les lignes 12-18 fournissent des opÃ©rateurs boolÃ©ens de comparaison de deux objets text_t: Ã©gale, diffÃ©rent de, prÃ©cÃšde alphanumÃ©riquement, etc.</Text>
+<Text id="846">Il existe aussi des fonctions membre qui prennent des arguments de type const au lieu d'arguments de type non-const, mais elles ne sont pas reprÃ©sentÃ©es ici. Une telle rÃ©pÃ©tition est habituelle dans des objets C++, ce qui augmente le code de l'API mais ne la rend pas plus grosse conceptuellement. En fait, de nombreuses fonctions sont implÃ©mentÃ©es sous la forme d'instructions tenant sur une ligne. Pour plus de dÃ©tails, reportez-vous au fichier source GSDLHOME/lib/text_t.h.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_greenstone_library_code">
+<Title>
+<Text id="847">Le code des bibliothÃšques Greenstone</Text>
+</Title>
+<Content>
+<Text id="848">Les fichiers d'en-tÃªtes du rÃ©pertoire GSDLHOME/lib comprennent un mÃ©lange de fonctions et d'objets qui fournissent un support utile au systÃšme d'exÃ©cution de Greenstone. LÃ  oÃ¹ l'efficacitÃ© prime, les fonctions et les fonctions membre sont dÃ©clarÃ©es inline. Dans la majoritÃ© des cas, les dÃ©tails d'implÃ©mentation sont contenus dans le fichier .cpp correspondant au fichier d'en-tÃªtes.</Text>
+<Table class="hidden">
+<Title/>
+<TableContent>
+<tr>
+<th width="100">
+<Text id="849">cfgread.h</Text>
+</th>
+<th width="450">
+<Text id="850">Fonctions de lecture et d'Ã©crite de fichiers de configuration. Par exemple, la fonction read_cfg_line() (lit une ligne de configuration) prend comme arguments le flux Ã  utiliser en entrÃ©e et le tableau text_tarray (raccourci pour vector &lt;text_t&gt;) Ã  remplir avec les donnÃ©es lues.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="851">display.h</Text>
+</th>
+<th width="450">
+<Text id="852">Objet sophistiquÃ© utilisÃ© par le rÃ©ceptionniste pour positionner, stocker et dÃ©velopper les macros, et gÃ©rer les types, La sectionÂ <CrossRef target="Section" ref="receptionist"/> le dÃ©taille.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="853">fileutil.h</Text>
+</th>
+<th width="450">
+<Text id="854">Support fonctionnel pour des fonctionnalitÃ©s de gestion de fichiers indÃ©pendantes du systÃšme d'exploitation. Par exemple, la fonction de nom filename_cat() (affiche nom-de-fichier) accepte jusqu'Ã  arguments text_t et renvoie un text_t qui est le rÃ©sultat de la concatÃ©nation des Ã©lÃ©ments en utilisant le sÃ©parateur de rÃ©pertoires appropriÃ© pour le systÃšme d'exploitation en cours d'utilisation.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="855">gsdlconf.h</Text>
+</th>
+<th width="450">
+<Text id="856">Fonctions propres au systÃšme qui rÃ©pondent Ã  des questions telles que: le systÃšme d'exploitation a-t-il besoin d'accÃ©der au fichier strings.h aussi bien qu'au fichier string.h? Toutes les valeurs appropriÃ©s pour le verrouillage de fichier sont-elles correctement positionnÃ©es?</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="857">gsdltimes.h</Text>
+</th>
+<th width="450">
+<Text id="858">Support fonctionnel pour la date et l'heure. Par exemple, la fonction time2text() (temps vers texte) prend l'heure de l'ordinateur, exprimÃ©e en nombre de secondes Ã©coulÃ©es depuis le premier janvier 1970, et la convertit sous la forme AAAA/MM/JJ hhmmss, qu'elle renvoie comme un objet text_t.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="859">gsdltools.h</Text>
+</th>
+<th width="450">
+<Text id="860">Support variÃ© pour le systÃšme d'exÃ©cution de Greenstone: clarifie le cÃŽtÃ© petit boutien (littleEndian) ou grand boutien (bigEndian); vÃ©rifie si Perl est disponible; exÃ©cute une commande systÃšme (avec quelques gadgets); et Ã©chappe les caractÃšres spÃ©ciaux de macros dans une chaÃ®ne text_t.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="861">gsdlunicode.h</Text>
+</th>
+<th width="450">
+<Text id="862">SÃ©rie d'objets hÃ©ritÃ©s qui gÃšrent le traitement de chaÃ®nes Unicode text_t Ã  travers des flux en entrÃ©e et en sortie, comme par exemple les conversions Unicode vers UTF-8 et vice versa; et la destruction des espaces de largeur nulle. GÃšre Ã©galement les fichiers de correspondance Ã  travers l'objet mapconvert, et les tables de correspondance sont chargÃ©es dans le rÃ©pertoire GSDLHOME/mappings.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="863">text_t.h</Text>
+</th>
+<th width="450">
+<Text id="864">Principalement, l'objet de texte Unicode dÃ©crit ci-dessus. Fournit Ã©galement deux classes de conversion de flux: inconvertclass (classe de conversion en entrÃ©e) et outconvertclass (classe de conversion en sortie). Ce sont les classes de base utilisÃ©es dans le fichier gsdlunicode.h.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="collection_server">
+<Title>
+<Text id="865">Serveur de collection</Text>
+</Title>
+<Content>
+<Text id="866">Nous allons maintenant expliquer systÃ©matiquement tous les objets apparaissant dans le cadre conceptuel de la figureÂ <CrossRef target="Figure" ref="greenstone_runtime_system"/>. Nous commenÃ§ons au bas du diagrammeÂ --Â c'est-Ã -dire aux fondations du systÃšmeÂ --Â avec les objets de recherche, source, et de filtre, et remonterons les couches du protocole vers les composants centraux du rÃ©ceptionniste: actions, mise en forme, et langage de macros. Nous nous concentrerons ensuite sur l'initialisation des objets, puisque cette derniÃšre est plus facile Ã  comprendre quand on connaÃ®t le rÃŽle des diffÃ©rents objets.</Text>
+<Text id="867">La plupart des classes centrales du cadre conceptuel sont exprimÃ©es Ã  l'aide d'hÃ©ritage virtuel pour favoriser l'extensibilitÃ©. Avec l'hÃ©ritage virtuel, les objets hÃ©ritÃ©s peuvent Ãªtre passÃ©s en tant que leur classe de base, mais tout appel de fonction invoque la version dÃ©finie dans l'objet hÃ©ritÃ©. En assurant que le code source de Greenstone utilise partout la classe de base, sauf aux endroits oÃ¹ s'effectue la construction des objets Ã  proprement parler, nous garantissons donc que diffÃ©rentes implÃ©mentationsÂ --Â utilisant peut-Ãªtre des technologies sous-jacentes radicalement diffÃ©rentesÂ --Â peuvent facilement Ãªtre mises en place.</Text>
+<Text id="868">Supposons par exemple qu'une classe de base nommÃ©e BaseCalc (calculs de base) fournisse l'arithmÃ©tique classique: additions, soustractions, multiplications et divisions. Si toutes ses fonctions sont dÃ©clarÃ©es virtuelles, et que tous les arguments et types renvoyÃ©s sont dÃ©clarÃ©s comme des chaÃ®nes, on peut facilement implÃ©menter des versions hÃ©ritÃ©es de l'objet. L'une, FixedPrecisionCalc (calcul en prÃ©cision finie), pourrait utiliser les fonctions de la bibliothÃšque C pour faire les conversions entre chaÃ®nes et entiers, et implÃ©menter les calculs en utilisant les opÃ©rateurs arithmÃ©tiques standard: +, -, *, et /. Une autre, appelÃ©e InfinitePrecisionCalc (calcul en prÃ©cision infinie), pourrait accÃ©der aux arguments des chaÃ®nes caractÃšre par caractÃšre, en implÃ©mentant les opÃ©rations arithmÃ©tiques qui sont en principe d'une prÃ©cision infinie. En Ã©crivant un programme qui utilise partout BaseCalc, l'implÃ©mentation peut passer de la prÃ©cision finie Ã  la prÃ©cision infinie ou inversement en modifiant une seule ligne: l'endroit oÃ¹ l'objet de calcul est construit.</Text>
+<Subsection id="the_search_object">
+<Title>
+<Text id="869">L'objet de recherche</Text>
+</Title>
+<Content>
+<Figure id="search_base_class_api">
+<Title>
+<Text id="870">API de la classe de base de recherche Search</Text>
+</Title>
+<CodeLine>class searchclass {</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   searchclass ();</CodeLine>
+<CodeLine>   virtual ~searchclass ();</CodeLine>
+<CodeLine>   // the index directory must be set before any searching</CodeLine>
+<CodeLine>   // is done</CodeLine>
+<CodeLine>   virtual void setcollectdir (const text_t &amp;thecollectdir);</CodeLine>
+<CodeLine>   // the search results are returned in queryresults</CodeLine>
+<CodeLine>   // search returns 'true' if it was able to do a search</CodeLine>
+<CodeLine>   virtual bool search(const queryparamclass &amp;queryparams,</CodeLine>
+<CodeLine>                         queryresultsclass &amp;queryresults)=0;</CodeLine>
+<CodeLine>   // the document text for 'docnum' is placed in 'output'</CodeLine>
+<CodeLine>   // docTargetDocument returns 'true' if it was able to</CodeLine>
+<CodeLine>   // try to get a document</CodeLine>
+<CodeLine>   // collection is needed to see if an index from the</CodeLine>
+<CodeLine>   // collection is loaded. If no index has been loaded</CodeLine>
+<CodeLine>   // defaultindex is needed to load one</CodeLine>
+<CodeLine>   virtual bool docTargetDocument(const text_t &amp;defaultindex,</CodeLine>
+<CodeLine>                                               const text_t &amp;defaultsubcollection,</CodeLine>
+<CodeLine>                                               const text_t &amp;defaultlanguage,</CodeLine>
+<CodeLine>                                               const text_t &amp;collection,</CodeLine>
+<CodeLine>                                               int docnum,</CodeLine>
+<CodeLine>                                               text_t &amp;output)=0;</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>   querycache *cache;</CodeLine>
+<CodeLine>   text_t collectdir; // the collection directory</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="871">La figureÂ <CrossRef target="Figure" ref="search_base_class_api"/> montre l'API de la classe de base de l'objet de recherche prÃ©sentÃ© dans la figureÂ <CrossRef target="Figure" ref="greenstone_runtime_system"/>. Elle dÃ©finit deux fonctions membre virtuelles: search() (recherche) et docTargetDocument() (doc document-cible). Comme le signifie le =0 qui suit la dÃ©claration des arguments, il s'agit de fonctions puresÂ --Â ce qui signifie qu'une classe qui hÃ©rite de cet objet devra implÃ©menter ces deux fonctions, faute de quoi le compilateur se plaindra.</Text>
+<Text id="872">La classe comprend Ã©galement deux champs de donnÃ©es protÃ©gÃ©s: collectdir (rÃ©pertoire de collection) et cache (tampon). Un objet de recherche est instanciÃ© pour une collection particuliÃšre, et le champ collectdir sert Ã  stocker l'endroit du systÃšme de fichiers oÃ¹ la collection (et en particulier ses fichiers d'index) se trouve. Le champ cache retient les rÃ©sultats d'une requÃªte. Il sert Ã  accÃ©lÃ©rer des requÃªtes ultÃ©rieures qui rÃ©pÃ©teraient la mÃªme requÃªte (et ses paramÃštres). Il peut sembler improbable qu'on effectue des requÃªtes identiques, mais dans la pratique c'est un phÃ©nomÃšne frÃ©quent. Le protocole de Greenstone est sans Ã©tat. Pour gÃ©nÃ©rer une page de rÃ©sultats semblable Ã  la figureÂ <CrossRef target="Figure" ref="searching_gutenberg_for_darcy"/> mais en prÃ©sentant les rÃ©sultats 11-20 de la mÃªme requÃªte, la recherche est Ã  nouveau transmise, en spÃ©cifiant cette fois-ci qu'il faut renvoyer les documents 11-20. L'utilisation de tampon rend ceci efficace, car le fait que cette recherche a dÃ©jÃ  eu lieu est dÃ©tectÃ© et les rÃ©sultats sont obtenus directement depuis le tampon.</Text>
+<Text id="873">Ces deux champs de donnÃ©es s'appliquent Ã  tout objet hÃ©ritÃ© qui implÃ©mente un mÃ©canisme de recherche. C'est pourquoi ils apparaissent dans la classe de base, et ils sont dÃ©clarÃ©s dans une section protÃ©gÃ©e de la classe de maniÃšre que les classes hÃ©ritÃ©es puissent y accÃ©der directement.</Text>
+</Content>
+</Subsection>
+<Subsection id="search_and_retrieval_with_mg">
+<Title>
+<Text id="874">Recherche et rapatriement avec MG</Text>
+</Title>
+<Content>
+<Text id="875">Greenstone utilise MG (abrÃ©viation de Â«Managing GigabytesÂ»Â --Â gÃ©rer les giga-octets; voir Witten<i>et al.</i>, 1999) pour indexer et rapatrier les documents, et son code source est inclus dans le rÃ©pertoire GSDLHOME/packages. MG utilise des techniques de compression pour optimiser l'utilisation de l'espace disque sans impacter la vitesse d'exÃ©cution. Pour une collection de documents Ã©crits en anglais, le texte compactÃ© et les index de corps du texte occupent en tout, en moyenne, un tiers de l'espace disque requis par le texte original, non compactÃ©. La recherche et le rapatriement sont souvent plus rapides que les opÃ©rations Ã©quivalentes sur la version non compactÃ©e car elles impliquent moins d'opÃ©rations sur le disque dur. </Text>
+<Figure id="api_for_direct_access_to_mg">
+<Title>
+<Text id="876">API pour accÃ©der directement Ã  MG (abrÃ©gÃ©e)</Text>
+</Title>
+<CodeLine>enum result_kinds {</CodeLine>
+<CodeLine>   result_docs,           // Return the documents found in last search</CodeLine>
+<CodeLine>   result_docnums,     // Return document id numbers and weights</CodeLine>
+<CodeLine>   result_termfreqs, // Return terms and frequencies</CodeLine>
+<CodeLine>   result_terms           // Return matching query terms</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine>int mgq_ask(char *line);</CodeLine>
+<CodeLine>int mgq_results(enum result_kinds kind, int skip, int howmany,</CodeLine>
+<CodeLine>                               int (*sender)(char *, int, int, float, void *),</CodeLine>
+<CodeLine>                               void *ptr);</CodeLine>
+<CodeLine>int mgq_numdocs(void);</CodeLine>
+<CodeLine>int mgq_numterms(void);</CodeLine>
+<CodeLine>int mgq_equivterms(unsigned char *wordstem,</CodeLine>
+<CodeLine>                           int (*sender)(char *, int, int, float, void *),</CodeLine>
+<CodeLine>                           void *ptr);</CodeLine>
+<CodeLine>int mgq_docsretrieved (int *total_retrieved, int *is_approx);</CodeLine>
+<CodeLine>int mgq_getmaxstemlen ();</CodeLine>
+<CodeLine>void mgq_stemword (unsigned char *word);</CodeLine>
+</Figure>
+<Text id="877">L'utilisation normale de MG se fait interactivement, en tapant des commandes Ã  l'invite, et une maniÃšre d'implÃ©menter la classe mgsearchclass serait d'utiliser l'appel system() de la bibliothÃšque C au sein de l'objet pour exÃ©cuter les commandes MG appropriÃ©es. Mais une approche plus efficace consiste Ã  taper directement dans le code de MG avec des appels de fonctions. Bien que ceci nÃ©cessite une meilleure comprÃ©hension du code de MG, on peut masquer une grande partie de la complexitÃ© derriÃšre une nouvelle API qui deviendra le point de contact pour l'objet mgsearchclass. C'est le rÃŽle du fichier colserver/mgq.c, dont l'API est prÃ©sentÃ©e figureÂ <CrossRef target="Figure" ref="api_for_direct_access_to_mg"/>.</Text>
+<Text id="878">On fournit des paramÃštres Ã  MG Ã  travers la fonction mgq_ask() (demande mgq), qui prend des options de texte dans un format identique Ã  celui utilisÃ© Ã  la ligne de commande, tel que:</Text>
+<CodeLine>mgq_ask( ".set casefold off ");</CodeLine>
+<Text id="879">Il sert aussi Ã  invoquer une requÃªte. On accÃšde Ã  ses rÃ©sultats Ã  travers la fonction mgq_results (rÃ©sultats de mgq), qui prend un pointeur vers une fonction comme quatriÃšme paramÃštre. Ceci fournit une maniÃšre souple de convertir l'information renvoyÃ©e dans les structures de donnÃ©es de MG en le format requis par mgsearchclass. Des appels tels que mgq_numdocs() (mgq-numÃ©ros de documents), mgq_numterms() et mgq_docsretrieved() (respectivement, mgq-numÃ©ros de termes et mgq-documents rapatriÃ©s) renvoient Ã©galement des informations, qui sont cette fois plus prÃ©cisÃ©ment prescrites. Les deux derniÃšres fonctions gÃšrent la troncature.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_source_object">
+<Title>
+<Text id="880">L'objet source</Text>
+</Title>
+<Content>
+<Figure id="source_base_class_api">
+<Title>
+<Text id="881">API de la classe de base source</Text>
+</Title>
+<CodeLine>class sourceclass {</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   sourceclass ();</CodeLine>
+<CodeLine>   virtual ~sourceclass ();</CodeLine>
+<CodeLine>   // configure should be called once for each configuration line</CodeLine>
+<CodeLine>   virtual void configure (const text_t &amp;key, const text_tarray &amp;cfgline);</CodeLine>
+<CodeLine>   // init should be called after all the configuration is done but</CodeLine>
+<CodeLine>   // before any other methods are called</CodeLine>
+<CodeLine>   virtual bool init (ostream &amp;logout);</CodeLine>
+<CodeLine>   // translate_OID translates OIDs using " .pr " , . " fc " etc.</CodeLine>
+<CodeLine>   virtual bool translate_OID (const text_t &amp;OIDin, text_t &amp;OIDout, comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   // get_metadata fills out the metadata if possible, if it is not</CodeLine>
+<CodeLine>   // responsible for the given OID then it return s false.</CodeLine>
+<CodeLine>   virtual bool get_metadata (const text_t &amp;requestParams, const text_t &amp;refParams,</CodeLine>
+<CodeLine>                           bool getParents, const text_tset &amp;fields, const text_t &amp;OID,</CodeLine>
+<CodeLine>                           MetadataInfo_tmap &amp;metadata, comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual bool get_document (const text_t &amp;OID, text_t &amp;doc, </CodeLine>
+<CodeLine>                           comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="882">Le rÃŽle de l'objet source dans la figureÂ <CrossRef target="Figure" ref="greenstone_runtime_system"/> est d'accÃ©der aux mÃ©ta-donnÃ©es et au texte du document, et l'API de sa classe de base est prÃ©sentÃ©e figureÂ <CrossRef target="Figure" ref="source_base_class_api"/>. Une fonction membre associe Ã  chaque tÃ¢che les fonctions get_metadata() (obtient les mÃ©ta-donnÃ©es) et get_document() (obtient le document) , respectivement. Toutes deux sont dÃ©clarÃ©es virtual, la version fournie par une implÃ©mentation particuliÃšre de la classe de base n'est donc appelÃ©e qu'au moment de l'exÃ©cution. Une version hÃ©ritÃ©e de cet objet utilise GDBM pour implÃ©menter get_metadata() et MG pour implÃ©menter get_document(): nous dÃ©taillons cette version ci-dessous. </Text>
+<Text id="883">On trouve d'autres fonctions membre dans la figureÂ <CrossRef target="Figure" ref="source_base_class_api"/>, telles que configure(), init(), et translate_OID() (traduire l'identifiant d'objet). Les deux premiÃšres sont liÃ©es au processus d'initialisation dÃ©crit sectionÂ <CrossRef target="Section" ref="initialisation"/>.</Text>
+<Text id="884">La derniÃšre, translate_OID(), gÃšre la syntaxe pour exprimer les identifiants de documents. Nous avons vu figureÂ <CrossRef target="Figure" ref="the_golf_course_mystery"/> comment on pouvait ajouter un numÃ©ro de page Ã  un identifiant de document pour ne rapatrier que la page correspondante. Ceci est possible car les pages ont Ã©tÃ© stockÃ©es en tant que Â«sectionsÂ» lors de la construction de la collection. Ajouter Â«.1Â» Ã  un OID rapatrie la premiÃšre section du document correspondant. Les sections peuvent Ãªtre imbriquÃ©es; on y accÃšde alors on concatÃ©nant les numÃ©ros de sections et en sÃ©parant les numÃ©ros par des points.</Text>
+<Text id="885">En plus des numÃ©ros hiÃ©rarchiques de sections, la syntaxe de l'identifiant de document permet des accÃšs relatifs. Par rapport Ã  la section actuelle du document il est possible d'accÃ©der au<i>premier fils</i>(<i>first child</i>) en ajoutant .fc, au<i>dernier fils</i>(<i>last child</i>) en ajoutant .lc, au<i>parent</i>en ajoutant .pr, au<i>frÃšre suivant</i>(<i>next sibling</i>) en ajoutant .ns, et au<i>frÃšre prÃ©cÃ©dent</i>(<i>previous sibling</i>) en ajoutant .ps.</Text>
+<Text id="886">La fonction translate_OID() utilise les paramÃštres OIDin (OID en entrÃ©e) et OIDout (OID en sortie) pour renfermer la source et le rÃ©sultat de la conversion. Elle prend aussi deux autres paramÃštres, err (erreur) et logout (journal en sortie). Ils communiquent tout Ã©tat d'erreur qui peut se produire lors de l'opÃ©ration de traduction, et dÃ©terminent oÃ¹ envoyer les informations de journalisation. Ces paramÃštres dÃ©pendent Ã©troitement du protocole, comme nous le verrons dans la sectionÂ <CrossRef target="Section" ref="protocol"/>.</Text>
+<Part id="database_retrieval_with_gdbm">
+<Title>
+<Text id="887">Rapatriement de base de donnÃ©es avec gdbm</Text>
+</Title>
+<Content>
+<Text id="888">GDBM est le gestionnaire de bases de donnÃ©es de GNU (www.gnu.org). Il implÃ©mente une structure d'enregistrements plats de couples clef/donnÃ©es, et il est compatible en arriÃšre avec DBM et NDBM. Les opÃ©rations fournies comprennent le stockage, le rapatriement, et la destruction d'enregistrements par clef, et un parcours non ordonnÃ© de toutes les clefs.</Text>
+<Figure id="gdbm_database_for_the_gutenberg_collection">
+<Title>
+<Text id="889">Base de donnÃ©es GDBM pour la collection (extrait)</Text>
+</Title>
+<CodeLine>[HASH01d7b30d4827b51282919e9b]</CodeLine>
+<CodeLine>&lt;doctype&gt;         doc</CodeLine>
+<CodeLine>&lt;hastxt&gt;           0</CodeLine>
+<CodeLine>&lt;Title&gt;             The Winter's Tale</CodeLine>
+<CodeLine>&lt;Creator&gt;         William Shakespeare</CodeLine>
+<CodeLine>&lt;archivedir&gt;   HASH01d7/b30d4827.dir</CodeLine>
+<CodeLine>&lt;thistype&gt;       Invisible</CodeLine>
+<CodeLine>&lt;childtype&gt;     Paged</CodeLine>
+<CodeLine>&lt;contains&gt;        " .1; " .2; " .3; " .4; " .5; " .6; " .7; " .8; " .9; " .10; " .11; " .12;            \ <br/>                           " .13; " .14; " .15; " .16; " .17; " .18; " .19; " .20; " .21; " .22;            \ <br/>                           " .23; " .24; " .25; " .26; " .27; " .28; " .29; " .30; " .31; " .32;            \ <br/>                           " .33; " .34; " .35</CodeLine>
+<CodeLine>&lt;docnum&gt;           168483</CodeLine>
+<CodeLine>âââââââââââââââââââââââ-</CodeLine>
+<CodeLine>[CL1]</CodeLine>
+<CodeLine>&lt;doctype&gt;         classify</CodeLine>
+<CodeLine>&lt;hastxt&gt;           0</CodeLine>
+<CodeLine>&lt;childtype&gt;     HList</CodeLine>
+<CodeLine>&lt;Title&gt;             Title</CodeLine>
+<CodeLine>&lt;numleafdocs&gt; 1818</CodeLine>
+<CodeLine>&lt;thistype&gt;       Invisible</CodeLine>
+<CodeLine>&lt;contains&gt;       " .1; " .2; " .3; " .4; " .5; " .6; " .7; " .8; " .9; " .10; " .11; " .12;          \ <br/>                           " .13; " .14; " .15; " .16; " .17; " .18; " .19; " .20; " .21; " .22;          \ <br/>                            " .23; " .24</CodeLine>
+<CodeLine>âââââââââââââââââââââââ-</CodeLine>
+<CodeLine>[CL1.1]</CodeLine>
+<CodeLine>&lt;doctype&gt;         classify</CodeLine>
+<CodeLine>&lt;hastxt&gt;           0</CodeLine>
+<CodeLine>&lt;childtype&gt;     VList</CodeLine>
+<CodeLine>&lt;Title&gt;             A</CodeLine>
+<CodeLine>&lt;numleafdocs&gt; 118</CodeLine>
+<CodeLine>&lt;contains&gt;      HASH0130bc5f9f90089b3723431f;HASH9cba43bacdab5263c98545;\</CodeLine>
+<CodeLine>                          HASH12c88a01da6e8379df86a7;HASH9c86579a83e1a2e4cf9736;   \</CodeLine>
+<CodeLine>                           HASHdc2951a7ada1f36a6c3aca;HASHea4dda6bbc7cdeb4abfdee;   \</CodeLine>
+<CodeLine>                          HASHce55006513c47235ac38ba;HASH012a33acaa077c0e612b9351;\</CodeLine>
+<CodeLine>                          HASH010dd1e923a123826ae30e4b;HASHaf674616785679fed4b7ee;\</CodeLine>
+<CodeLine>                         HASH0147eef4b9d1cb135e096619;HASHe69b9dbaa83ffb045d963b;\</CodeLine>
+<CodeLine>                         HASH01abc61c646c8e7a8ce88b10;HASH5f9cd13678e21820e32f3a;\</CodeLine>
+<CodeLine>                         HASHe8cbba1594c72c98f9aa1b;HASH01292a2b7b6b60dec96298bc;\</CodeLine>
+<CodeLine>                         ...</CodeLine>
+</Figure>
+<Text id="890">La figureÂ <CrossRef target="Figure" ref="gdbm_database_for_the_gutenberg_collection"/> montre un extrait de la base de donnÃ©es d'informations de la collection crÃ©Ã©e lors de la construction de la collection Gutenberg. Cet extrait fut produit Ã  l'aide de l'outil Greenstone db2txt, qui convertit le format binaire de base de donnÃ©es GDBM sous forme textuelle. La figureÂ <CrossRef target="Figure" ref="gdbm_database_for_the_gutenberg_collection"/> contient trois enregistrements, sÃ©parÃ©s par des lignes horizontales. Le premier est une entrÃ©e de document, les deux autres sont des portions de la hiÃ©rarchie crÃ©Ã©es par le classificateur AZList pour les titres de la collection. La premiÃšre ligne de chaque enregistrement est sa clef.</Text>
+<Text id="891">L'enregistrement de document stocke le titre du livre, son auteur, et toute autre mÃ©ta-donnÃ©e fournie (ou extraite) lors de la construction de la collection. Il contient aussi des valeurs pour usage interne: oÃ¹ les fichiers associÃ©s Ã  ce document se trouvent (&lt;archivedir&gt;) et le numÃ©ro de document utilisÃ© de maniÃšre interne par MG (&lt;docnum&gt;).</Text>
+<Text id="892">Le champ &lt;contains&gt; (contient) stocke une liste d'Ã©lÃ©ments, sÃ©parÃ©s par des points-virgules, qui pointent vers des enregistrement relatifs dans la base de donnÃ©es. Pour un enregistrement de document, &lt;contains&gt; sert Ã  pointer vers les sections imbriquÃ©es. On formera des clefs d'enregistrement en concatÃ©nant la clef courante Ã  l'un des Ã©lÃ©ments fils (le sÃ©parateur Ã©tant un point).</Text>
+<Text id="893">Le deuxiÃšme enregistrement de la figureÂ <CrossRef target="Figure" ref="gdbm_database_for_the_gutenberg_collection"/> est le noeud principal de la hiÃ©rarchie de classification de titres A-Z. Ses enfants, auxquels on accÃšde Ã  travers le champ &lt;contains&gt;, comprennent CL1.1, CL1.2, CL1.3 etc., et correspondent aux pages individuelles pour les lettres A, B, C, etc. Il n'en existe que 24: le classificateur AZList a rassemblÃ© les lettres Q-R et Y-Z car elles ne concernaient que peu de titres.</Text>
+<Text id="894">Les enfants du champ &lt;contains&gt; du troisiÃšme enregistrement, CL1.1, sont les documents proprement dits. On peut trouver des structures plus compliquÃ©esÂ --Â le champ &lt;contains&gt; peut inclure un mÃ©lange de documents et d'autres noeuds CL. Les clefs exprimÃ©es relativement Ã  la clef courante se reconnaissent des clefs absolues car elles commencent par une apostrophe double. (").</Text>
+</Content>
+</Part>
+<Part id="using_mg_and_gdbm_to_implement_a_source_object">
+<Title>
+<Text id="895">Utiliser MG et GDBM pour implÃ©menter un objet source</Text>
+</Title>
+<Content>
+<Figure id="api_for_mg_and_gdbm_based_version_of_sourceclass">
+<Title>
+<Text id="896">API de la version de sourceclass basÃ©e sur MG et GDBM (abrÃ©gÃ©e)</Text>
+</Title>
+<CodeLine>class mggdbmsourceclass : public sourceclass {</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>   // Omitted, data fields that store:</CodeLine>
+<CodeLine>   //     collection specific file information</CodeLine>
+<CodeLine>   //     index substructure</CodeLine>
+<CodeLine>   //     information about parent</CodeLine>
+<CodeLine>   //     pointers to gdbm and mgsearch objects</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   mggdbmsourceclass ();</CodeLine>
+<CodeLine>   virtual ~mggdbmsourceclass ();</CodeLine>
+<CodeLine>   void set_gdbmptr (gdbmclass *thegdbmptr);</CodeLine>
+<CodeLine>   void set_mgsearchptr (searchclass *themgsearchptr);</CodeLine>
+<CodeLine>   void configure (const text_t &amp;key, const text_tarray &amp;cfgline);</CodeLine>
+<CodeLine>   bool init (ostream &amp;logout);</CodeLine>
+<CodeLine>   bool translate_OID (const text_t &amp;OIDin, text_t &amp;OIDout,</CodeLine>
+<CodeLine>                                           comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   bool get_metadata (const text_t &amp;requestParams,</CodeLine>
+<CodeLine>                                           const text_t &amp;refParams,</CodeLine>
+<CodeLine>                                         bool getParents, const text_tset &amp;fields,</CodeLine>
+<CodeLine>                                         const text_t &amp;OID, MetadataInfo_tmap &amp;metadata,</CodeLine>
+<CodeLine>                                         comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   bool get_document (const text_t &amp;OID, text_t &amp;doc,</CodeLine>
+<CodeLine>                                         comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="897">L'objet qui rassemble MG et GDBM pour rÃ©aliser une implÃ©mentation de sourceclass s'appelle mggdbmsourceclass. La figureÂ <CrossRef target="Figure" ref="api_for_mg_and_gdbm_based_version_of_sourceclass"/> prÃ©sente son API. Les deux fonctions membre set_gdbmptr() et set_mgsearchptr() (respectivement, positionne le pointeur gdbm et recherche le pointeur mg) stockent des pointeurs vers leurs objets respectifs, de sorte que les implÃ©mentations de get_metadata() (obtient les mÃ©ta-donnÃ©es) et get_document() (obtient le document) puissent accÃ©der aux outils appropriÃ©s pour mener leur tÃ¢che Ã  bien.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="the_filter_object">
+<Title>
+<Text id="898">L'objet de filtre</Text>
+</Title>
+<Content>
+<Figure id="api_for_the_filter_base_class">
+<Title>
+<Text id="899">API de la classe de base de filtre</Text>
+</Title>
+<CodeLine>class filterclass {</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>   text_t gsdlhome;</CodeLine>
+<CodeLine>   text_t collection;</CodeLine>
+<CodeLine>   text_t collectdir;</CodeLine>
+<CodeLine>   FilterOption_tmap filterOptions;</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   filterclass ();</CodeLine>
+<CodeLine>   virtual ~filterclass ();</CodeLine>
+<CodeLine>   virtual void configure (const text_t &amp;key,Â const text_tarray &amp;cfgline);</CodeLine>
+<CodeLine>   virtual bool init (ostream &amp;logout);</CodeLine>
+<CodeLine>   // returns the name of this filter</CodeLine>
+<CodeLine>   virtual text_t get_filter_name ();</CodeLine>
+<CodeLine>   // returns the current filter options</CodeLine>
+<CodeLine>   virtual void get_filteroptions (InfoFilterOptionsResponse_t &amp;response,</CodeLine>
+<CodeLine>                                 comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void filter (const FilterRequest_t &amp;request,</CodeLine>
+<CodeLine>                         FilterResponse_t &amp;response,</CodeLine>
+<CodeLine>                         comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="900">L'API de la classe de base de l'objet de filtre de la figureÂ <CrossRef target="Figure" ref="greenstone_runtime_system"/> est prÃ©sentÃ©e dans la figureÂ <CrossRef target="Figure" ref="api_for_the_filter_base_class"/>. Elle commence par les champs de donnÃ©es protÃ©gÃ©s gsdlhome, collection, et collectdir, frÃ©quents dans les classes qui ont besoin d'accÃ©der Ã  des fichiers propres Ã  des collections.</Text>
+<BulletList>
+<Bullet>
+<Text id="901">gsdlhome est la mÃªme chose que GSDLHOME, de sorte que l'objet puisse localiser les fichiers de Greenstone.</Text>
+</Bullet>
+<Bullet>
+<Text id="902">collection est le nom du rÃ©pertoire correspondant Ã  la collection.</Text>
+</Bullet>
+<Bullet>
+<Text id="903">collectdir est le chemin complet du rÃ©pertoire de collection (ceci est nÃ©cessaire car une collection ne se trouve pas toujours dans la zone GSDLHOME).</Text>
+</Bullet>
+</BulletList>
+<Text id="904">mggdbsourceclass est une autre classe qui inclut ces trois champs de donnÃ©es.</Text>
+<Text id="905">Les fonctions membre configure() et init() (d'abord vues dans la fonction sourceclass) sont utilisÃ©es par le processus d'initialisation. L'objet lui-mÃªme est intimement alignÃ© avec la portion de filtre lui correspondant dans le protocole; en particulier les fonctions get_filteroptions() et filter() correspondent exactement. </Text>
+<Figure id="how_a_filter_option_is_stored">
+<Title>
+<Text id="906">ManiÃšre de stocker une option de filtre</Text>
+</Title>
+<CodeLine>struct FilterOption_t {</CodeLine>
+<CodeLine>   void clear (); \   void check_defaultValue ();</CodeLine>
+<CodeLine>   FilterOption_t () {clear();}</CodeLine>
+<CodeLine>   text_t name;</CodeLine>
+<CodeLine>   enum type_t {booleant=0, integert=1, enumeratedt=2, stringt=3};</CodeLine>
+<CodeLine>   type_t type;</CodeLine>
+<CodeLine>   enum repeatable_t {onePerQuery=0, onePerTerm=1, nPerTerm=2};</CodeLine>
+<CodeLine>   repeatable_t repeatable;</CodeLine>
+<CodeLine>   text_t defaultValue;</CodeLine>
+<CodeLine>   text_tarray validValues;</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine>struct OptionValue_t {</CodeLine>
+<CodeLine>   void clear ();</CodeLine>
+<CodeLine>   text_t name;</CodeLine>
+<CodeLine>   text_t value;</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="907">Les deux classes prÃ©sentÃ©es dans la figureÂ <CrossRef target="Figure" ref="how_a_filter_option_is_stored"/> sont centrales pour les options de filtre. FilterOption_t (filtre d'option) stocke le nom de l'option, son type, et si elle peut ou non Ãªtre rÃ©pÃ©tÃ©e (repeatable). validValues est interprÃ©tÃ© selon le type de l'option. Pour un type boolÃ©en, la premiÃšre valeur est la valeur fausse false, la deuxiÃšme valeur est la valeur vraie true. Pour un type entier, la premiÃšre valeur est la valeur minimale, la deuxiÃšme valeur est la valeur maximale. Pour un type Ã©numÃ©rÃ© toutes les valeurs sont listÃ©es. Pour un type de chaÃ®ne la valeur est ignorÃ©e. Pour des situations plus simples, on utilise OptionValue_t (valeur d'option), qui enregistre sous forme de text_t le nom de l'option et sa valeur.</Text>
+<Text id="908">Les objets de requÃªte et de rÃ©ponse passÃ©s en paramÃštres Ã  filterclass sont construits Ã  partir de ces deux classes, en utilisant des tableaux associatifs pour stocker un ensemble d'options telles que les options nÃ©cessaires Ã  la fonction InfoFilterOptionsResponse_t. On peut trouver des dÃ©tails complÃ©mentaires dans le fichier GSDLHOME/src/recpt/comtypes.h.</Text>
+</Content>
+</Subsection>
+<Subsection id="inherited_filter_objects">
+<Title>
+<Text id="909">Objets de filtre hÃ©ritÃ©s</Text>
+</Title>
+<Content>
+<Figure id="inheritance_hierarchy_for_filter">
+<Title>
+<Text id="910">HiÃ©rarchie d'hÃ©ritage pour l'objet de filtre</Text>
+</Title>
+<File width="337" height="245" url="images/Dev_Fig_38.png"/>
+</Figure>
+<Text id="911">Les filtres utilisent deux niveaux d'hÃ©ritage, comme illustrÃ© dans la figureÂ <CrossRef target="Figure" ref="inheritance_hierarchy_for_filter"/>. Tout d'abord on distingue les filtres de requÃªte et de navigation, et il existe pour les premiers une implÃ©mentation spÃ©cifique, fondÃ©e sur MG. Pour fonctionner correctement, mgqueryfilterclass doit accÃ©der Ã  MG Ã  travers mgsearchclass et Ã  GDBM Ã  travers gdbmclass. browsefilterclass n'a besoin que d'accÃ©der Ã  GDBM. Les pointeurs vers ces objets sont stockÃ©s sous la forme de champs de donnÃ©es protÃ©gÃ©s au sein des classes respectives.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_collection_server_code">
+<Title>
+<Text id="912">Code du serveur de collection</Text>
+</Title>
+<Content>
+<Text id="913">Voici les fichiers d'en-tÃªtes du rÃ©pertoire GSDLHOME/src/colservr, suivis de leur description. Le nom de fichier correspond gÃ©nÃ©ralement au nom de l'objet qu'il renferme.</Text>
+<Table class="hidden">
+<Title/>
+<TableContent>
+<tr>
+<th width="120">
+<Text id="914">browsefilter.h</Text>
+</th>
+<th width="420">
+<Text id="915">(filtre de navigation) HÃ©ritÃ© de filterclass (classe de filtre), cet objet fournit un accÃšs Ã  GDBM (dÃ©crit plus haut).</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="916">collectserver.h</Text>
+</th>
+<th width="420">
+<Text id="917">(serveur de collection) Cet objet relie les objets de filtre et source d'une collection, pour former l'objet de collection reprÃ©sentÃ© figureÂ <CrossRef target="Figure" ref="greenstone_runtime_system"/>.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="918">colservrconfig.h</Text>
+</th>
+<th width="420">
+<Text id="919">(configuration du serveur de collection) Support fonctionnel pour la lecture des fichiers propres Ã  une collection etc/collect.cfg et index/build.cfg. Le premier est le fichier de configuration de la collection; le deuxiÃšme est un fichier gÃ©nÃ©rÃ© par le processus de construction qui enregistre le moment de la derniÃšre construction menÃ©e Ã  bien, une liste des correspondances d'index, combien de documents ont Ã©tÃ© indexÃ©s, et leur taille (non compactÃ©e) en octets.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="920">filter.h</Text>
+</th>
+<th width="420">
+<Text id="921">(filtre) La classe de base de l'objet filtre filterclass dÃ©crit ci-dessus.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="922">maptools.h</Text>
+</th>
+<th width="420">
+<Text id="923">DÃ©finit une classe stringmap (correspondance de chaÃ®ne) qui fournit une correspondance se rappelant l'ordre original d'une correspondance text_t, mais qui est d'une consultation rapide. mggdbmsourceclass ainsi que queryfilterclass s'en servent.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="924">mggdbmsource.h</Text>
+</th>
+<th width="420">
+<Text id="925">HÃ©ritÃ© de sourceclass, cet objet donne accÃšs Ã  MG et GDBM (dÃ©crit plus haut).</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="926">mgppqueryfilter.h</Text>
+</th>
+<th width="420">
+<Text id="927">HÃ©ritÃ© de queryfilterclass, cet objet fournit une implÃ©mentation de QueryFilter fondÃ©e sur MG++, version amÃ©liorÃ©e de MG Ã©crite en C++. Remarquez que Greenstone est par dÃ©faut configurÃ© pour utiliser MG, puisque MG++ est toujours en cours de dÃ©veloppement.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="928">mgppsearch.h</Text>
+</th>
+<th width="420">
+<Text id="929">HÃ©ritÃ© de searchclass, cet objet fournit une implÃ©mentation de l'objet de recherche avec MG++. Comme mgppqueryfilterclass, ceci n'est pas utilisÃ© par dÃ©faut.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="930">mgq.h</Text>
+</th>
+<th width="420">
+<Text id="931">Interface fonctionnelle au paquetage MG. Ses fonctions principales sont mg_ask() et mg_results().</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="932">mgqueryfilter.h</Text>
+</th>
+<th width="420">
+<Text id="933">HÃ©ritÃ© de queryfilterclass, cet objet fournit une implÃ©mentation de QueryFilter fondÃ©e sur MG.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="934">mgsearch.h</Text>
+</th>
+<th width="420">
+<Text id="935">HÃ©ritÃ© de searchclass, cet objet fournit une implÃ©mentation de l'objet de recherche qui utilise MG (dÃ©crit plus haut).</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="936">phrasequeryfilter.h</Text>
+</th>
+<th width="420">
+<Text id="937">HÃ©ritÃ© de mgqueryclass, cet objet fournit une classe de requÃªte fondÃ©e sur les groupes de mots. Il n'est pas utilisÃ© dans l'installation par dÃ©faut. C'est mgqueryfilterclass qui fournit cette fonctionnalitÃ© Ã  travers un support fonctionnel depuis phrasesearch.h.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="938">phrasesearch.h</Text>
+</th>
+<th width="420">
+<Text id="939">Support fonctionnel pour rechercher des groupes de mots comme une opÃ©ration post-traitement.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="940">querycache.h</Text>
+</th>
+<th width="420">
+<Text id="941">UtilisÃ© par searchclass et les classes qui en hÃ©ritent pour garder dans un tampon les rÃ©sultats d'une requÃªte, afin de gÃ©nÃ©rer plus efficacement la gÃ©nÃ©ration des pages de rÃ©sultats suivantes (dÃ©crit plus haut).</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="942">queryfilter.h</Text>
+</th>
+<th width="420">
+<Text id="943">HÃ©ritÃ© de la classe de base de filtre filterclass, cet objet Ã©tablit une classe de base pour les objets de filtre de requÃªte (dÃ©crit plus haut).</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="944">queryinfo.h</Text>
+</th>
+<th width="420">
+<Text id="945">Support pour la recherche: structures de donnÃ©es et objets pour contenir les paramÃštres des requÃªtes, les documents rÃ©sultats et les frÃ©quences des termes.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="946">search.h</Text>
+</th>
+<th width="420">
+<Text id="947">La classe de base de l'objet de recherche searchclass (dÃ©crite plus haut).</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="948">source.h</Text>
+</th>
+<th width="420">
+<Text id="949">La classe de base de l'objet source sourceclass (dÃ©crite plus haut).</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="protocol">
+<Title>
+<Text id="950">Le protocole</Text>
+</Title>
+<Content>
+<Table id="list_of_protocol_calls">
+<Title>
+<Text id="951">Liste des appels de protocole</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="952"><i>get_protocol_name()</i></Text>
+</th>
+<th width="397">
+<Text id="953">Renvoie le nom de ce protocole. Les valeurs possibles comprennent<i>nullproto</i>(protocole vide),<i>corbaproto</i>(protocole CORBA), et<i>z3950proto</i>. UtilisÃ© par des portions du systÃšme d'exÃ©cution qui dÃ©pendent du protocole pour dÃ©cider quel code exÃ©cuter.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="954"><i>get_collection_list()</i></Text>
+</th>
+<th width="397">
+<Text id="955">Renvoie la liste des collections que ce protocole connaÃ®t.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="956"><i>has_collection()</i></Text>
+</th>
+<th width="397">
+<Text id="957">Renvoie la valeur vraie<i>true</i>si le protocole peut communiquer avec la collection nommÃ©e, c'est-Ã -dire si cette collection fait partie de sa liste de collections.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="958"><i>ping()</i></Text>
+</th>
+<th width="397">
+<Text id="959">Renvoie la valeur vraie<i>true</i>si on a pu Ã©tablir une connexion Ã  la collection nommÃ©e. Dans le cas du protocole vide l'implÃ©mentation est la mÃªme que celle de<i>has_collection().</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="960"><i>get_collectinfo()</i></Text>
+</th>
+<th width="397">
+<Text id="961">Obtient des informations gÃ©nÃ©riques relatives Ã  la collection nommÃ©e: date de derniÃšre construction, nombre de documents qu'elle contient, etc. Inclut aussi des mÃ©ta-donnÃ©es du fichier de configuration de la collection: le texte Â«\menu{Ã  propos}Â»; l'icone de collection Ã  utiliser, etc.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="962"><i>get_filterinfo()</i></Text>
+</th>
+<th width="397">
+<Text id="963">Obtient une liste de tous les objets de filtre pour la collection nommÃ©e.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="964"><i>get_filteroptions()</i></Text>
+</th>
+<th width="397">
+<Text id="965">Obtient toutes les options pour un objet de filtre particulier au sein de la collection nommÃ©e.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="966"><i>filter()</i></Text>
+</th>
+<th width="397">
+<Text id="967">Permet la recherche et la navigation. Pour un type de filtre donnÃ© et des rÃ©glages d'options, accÃšde au contenu de la collection nommÃ©e pour produire un ensemble rÃ©sultat qui est filtrÃ© selon les rÃ©glages d'options. Les champs de donnÃ©es renvoyÃ©s dÃ©pendent Ã©galement des rÃ©glages d'options, comme par exemple la frÃ©quence des termes de requÃªte et les mÃ©ta-donnÃ©es de document.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="968"><i>get_document()</i></Text>
+</th>
+<th width="397">
+<Text id="969">Obtient un document ou une section d'un document.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="970">La tableÂ <CrossRef target="Table" ref="list_of_protocol_calls"/> liste les appels de fonction au protocole, en rÃ©sumant chaque entrÃ©e. Les exemples donnÃ©s sectionÂ <CrossRef target="Section" ref="how_the_conceptual_framework_fits_together"/> ont couvert la plupart de ces appels. Les fonctions non mentionnÃ©es prÃ©cÃ©demment sont les fonctions has_collection(), ping(), get_protocol_name() et get_filteroptions(). Les deux premiÃšres rÃ©pondent par oui ou par non aux questions Â«la collection existe-t-elle sur ce serveur?Â» et Â«est-elle en cours de fonctionnement?Â», respectivement. Le but des deux autres est de supporter des protocoles multiples au sein d'une architecture distribuÃ©e sur des ordinateurs diffÃ©rents, et non pas le simple exÃ©cutable fondÃ© sur le protocole vide et dÃ©crit ici. L'une d'entre elles fait une distinction selon le protocole en cours d'utilisation. L'autre permet Ã  un rÃ©ceptionniste d'interroger un serveur de collection pour trouver les options supportÃ©es, afin de s'auto-configurer dynamiquement pour profiter des services offerts par un serveur particulier.</Text>
+<Figure id="null_protocol_api">
+<Title>
+<Text id="971">API du protocole vide (abrÃ©gÃ©e)</Text>
+</Title>
+<CodeLine>class nullproto : public recptproto {</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   virtual text_t get_protocol_name ();</CodeLine>
+<CodeLine>   virtual void get_collection_list (text_tarray &amp;collist,</CodeLine>
+<CodeLine>                comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void has_collection (const text_t &amp;collection,</CodeLine>
+<CodeLine>                bool &amp;hascollection,</CodeLine>
+<CodeLine>                comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void ping (const text_t &amp;collection,</CodeLine>
+<CodeLine>                  bool &amp;wassuccess,</CodeLine>
+<CodeLine>                  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void get_collectinfo (const text_t &amp;collection,</CodeLine>
+<CodeLine>                  ColInfoResponse_t &amp;collectinfo,</CodeLine>
+<CodeLine>                  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void get_filterinfo (const text_t &amp;collection,</CodeLine>
+<CodeLine>                   InfoFiltersResponse_t &amp;response,</CodeLine>
+<CodeLine>                   comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void get_filteroptions (const text_t &amp;collection,</CodeLine>
+<CodeLine>                   const InfoFilterOptionsRequest_t &amp;request,</CodeLine>
+<CodeLine>                   InfoFilterOptionsResponse_t &amp;response,</CodeLine>
+<CodeLine>                   comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void filter (const text_t &amp;collection,</CodeLine>
+<CodeLine>                   FilterRequest_t &amp;request,</CodeLine>
+<CodeLine>                   FilterResponse_t &amp;response,</CodeLine>
+<CodeLine>                   comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void get_document (const text_t &amp;collection,</CodeLine>
+<CodeLine>                  const DocumentRequest_t &amp;request,</CodeLine>
+<CodeLine>                  DocumentResponse_t &amp;response,</CodeLine>
+<CodeLine>                  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="972">La figureÂ <CrossRef target="Figure" ref="null_protocol_api"/> montre l'API pour le protocole vide. Les commentaires, ainsi que certains dÃ©tails de bas niveau, ont Ã©tÃ© omis (consultez le fichier source, c'est-Ã -dire recpt/nullproto.h, pour avoir tous les dÃ©tails).</Text>
+<Text id="973">Ce protocole hÃ©rite de la classe de base recptproto. On utilise l'hÃ©ritage virtuel de telle sorte que plus d'un type de protocoleÂ --Â y compris des protocoles pas encore conÃ§usÂ --Â puisse Ãªtre facilement supportÃ© dans le reste du code source. Ceci est possible car l'objet de classe de base recptproto est utilisÃ© tout au long du code source, Ã  l'exception de l'endroit de la construction. Nous spÃ©cifions ici la vÃ©ritable variÃ©tÃ© de protocole que nous souhaitons utiliserÂ --Â dans ce cas-ci, le protocole vide.</Text>
+<Text id="974">Ã l'exception de get_protocol_name(), qui ne prend aucun paramÃštre et renvoie le nom du protocole sous la forme d'une chaÃ®ne au format Unicode, toutes les fonctions du protocole incluent un paramÃštre d'erreur et un flux de sortie en tant que leurs deux derniers arguments. Le paramÃštre d'erreur enregistre toute erreur qui se produit pendant l'exÃ©cution de l'appel de protocole, et le flux de sortie est utilisÃ© Ã  des fins de journalisation. Les fonctions sont de type void--elles ne renvoient pas explicitement des informations dans leur derniÃšre instruction, mais renvoient plutÃŽt des donnÃ©es Ã  travers des paramÃštres dÃ©signÃ©s tels que le paramÃštre d'erreur (dont on vient de parler). Dans certains langages de programmation, de tels sous-programmes s'appelleraient Â«procÃ©duresÂ» et non Â«fonctionsÂ», mais le C++ n'opÃšre pas de telle distinction syntaxique.</Text>
+<Text id="975">La plupart des fonctions prennent le nom de la collection en argument. Trois des fonctions membre (les fonctions get_filteroptions(), filter(), et get_document()) suivent le schÃ©ma de fournir un paramÃštre de requÃªte et de recevoir les rÃ©sultats dans un paramÃštre de rÃ©ponse.</Text>
+</Content>
+</Section>
+<Section id="receptionist">
+<Title>
+<Text id="976">Le rÃ©ceptionniste</Text>
+</Title>
+<Content>
+<Text id="977">C'est la derniÃšre couche du modÃšle conceptuel. AprÃšs analyse des arguments du CGI, l'activitÃ© principale est l'exÃ©cution d'une action, assistÃ©e par les objets de mise en forme et de langage de macros. Ces derniers sont dÃ©crits plus bas. Bien qu'ils soient reprÃ©sentÃ©s comme des objets dans le cadre conceptuel, les objets de mise en forme et de langage de macros ne sont pas strictement des objets au sens du C++. En fait, l'objet de mise en forme est une collection de structures de donnÃ©es et un ensemble de fonction qui opÃšre sur ces derniÃšres, et l'objet de langage de macros est construit autour de displayclass, dÃ©finie dans lib/display.h, avec un support de conversion de flux provenant de lib/gsdlunicode.h.</Text>
+<Subsection id="actions">
+<Title>
+<Text id="978">Les actions</Text>
+</Title>
+<Content>
+<Table id="actions_in_greenstone">
+<Title>
+<Text id="979">Les actions dans Greenstone</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="980"><i>action</i></Text>
+</th>
+<th width="397">
+<Text id="981">Classe de base pour l'hÃ©ritage virtuel.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="982"><i>authenaction</i></Text>
+</th>
+<th width="397">
+<Text id="983">Support de l'authentification utilisateur: demande Ã  l'utilisateur un mot de passe si aucun n'a Ã©tÃ© saisi; vÃ©rifie sa validitÃ©; et oblige l'utilisateur Ã  se rÃ©-authentifier si trop de temps s'est Ã©coulÃ© entre deux accÃšs.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="984"><i>collectoraction</i></Text>
+</th>
+<th width="397">
+<Text id="985">GÃ©nÃšre les pages pour le Collector.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="986"><i>documentaction</i></Text>
+</th>
+<th width="397">
+<Text id="987">Rapatrie les documents, les sections de documents, les portions de la hiÃ©rarchie de classification, ou les informations de mise en forme.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="988"><i>extlinkaction</i></Text>
+</th>
+<th width="397">
+<Text id="989">EmmÃšne un utilisateur directement vers une URL externe Ã  la collection, en gÃ©nÃ©rant ou non d'abord une page d'alerte (selon les<i>PrÃ©fÃ©rences</i>).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="990"><i>pageaction</i></Text>
+</th>
+<th width="397">
+<Text id="991">GÃ©nÃšre une page en conjonction avec le langage de macros.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="992"><i>pingaction</i></Text>
+</th>
+<th width="397">
+<Text id="993">VÃ©rifie si une collection est en ligne ou non.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="994"><i>queryaction</i></Text>
+</th>
+<th width="397">
+<Text id="995">Effectue une recherche.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="996"><i>statusaction</i></Text>
+</th>
+<th width="397">
+<Text id="997">GÃ©nÃšre les pages d'administration.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="998"><i>tipaction</i></Text>
+</th>
+<th width="397">
+<Text id="999">Affiche une astuce alÃ©atoire Ã  l'utilisateur.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1000"><i>usersaction</i></Text>
+</th>
+<th width="397">
+<Text id="1001">GÃšre l'ajout, la destruction, et la gestion des accÃšs utilisateur.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="1002">Greenstone supporte les onze actions rÃ©sumÃ©es dans la tableÂ <CrossRef target="Table" ref="actions_in_greenstone"/>.</Text>
+<Figure id="using_the_cgiargsinfoclass_from_pageactioncpp" class="withLineNumber">
+<Title>
+<Text id="1003">Utilisation de cgiargsinfoclass depuis pageaction.cpp</Text>
+</Title>
+<CodeLine>cgiarginfo arg_ainfo;</CodeLine>
+<CodeLine>arg_ainfo.shortname = " a " ;</CodeLine>
+<CodeLine>arg_ainfo.longname = " action" ;</CodeLine>
+<CodeLine>arg_ainfo.multiplechar = true;</CodeLine>
+<CodeLine>arg_ainfo.argdefault = " p" ;</CodeLine>
+<CodeLine>arg_ainfo.defaultstatus = cgiarginfo::weak;</CodeLine>
+<CodeLine>arg_ainfo.savedarginfo = cgiarginfo::must;</CodeLine>
+<CodeLine>argsinfo.addarginfo (NULL, arg_ainfo);</CodeLine>
+<CodeLine/>
+<CodeLine>arg_ainfo.shortname = " p" ;</CodeLine>
+<CodeLine>arg_ainfo.longname = " page" ;</CodeLine>
+<CodeLine>arg_ainfo.multiplechar = true;</CodeLine>
+<CodeLine>arg_ainfo.argdefault = " home" ;</CodeLine>
+<CodeLine>arg_ainfo.defaultstatus = cgiarginfo::weak;</CodeLine>
+<CodeLine>arg_ainfo.savedarginfo = cgiarginfo::must;</CodeLine>
+<CodeLine>argsinfo.addarginfo (NULL, arg_ainfo);</CodeLine>
+</Figure>
+<Text id="1004">Les arguments CGI nÃ©cessaires Ã  une action sont formellement dÃ©clarÃ©s dans sa fonction constructeur avec cgiarginfo (dÃ©finie dans recpt/cgiargs.h). La figure <CrossRef target="Figure" ref="using_the_cgiargsinfoclass_from_pageactioncpp"/> montre un extrait de la fonction constructeur pageaction, qui dÃ©finit la taille et les propriÃ©tÃ©s des arguments CGI a et p.</Text>
+<Text id="1005">Pour chaque argument CGI, le constructeur doit spÃ©cifier son nom court (lignes 2 et 10), qui est le nom de la variable CGI Ã  proprement parler; un nom long (lignes 3 et 11) qui est utilisÃ© pour fournir une description plus parlante de l'action; s'il reprÃ©sente une valeur de caractÃšre simple ou multiple (lignes 4 et 12); possiblement, une valeur par dÃ©faut (lignes 5 et 13); ce qui se produit quand plusieurs valeurs par dÃ©faut sont fournies (lignes 6 et 14, Ã©tant donnÃ© qu'on peut positionner des valeurs par dÃ©faut dans les fichiers de configuration); et s'il faut ou non que la valeur soit conservÃ©e Ã  la fin de cette action (lignes 7 et 15).</Text>
+<Text id="1006">Ãtant donnÃ© qu'elle est embarquÃ©e dans le code, on peut gÃ©nÃ©rer automatiquement des pages web qui dÃ©taillent cette information. L'action statusaction produit cette information, et on peut la visualiser en saisissant l'URL de la page d'administration de Greenstone.</Text>
+<Text id="1007">Les douze actions hÃ©ritÃ©es sont construites dans main(), la fonction de premier niveau de l'exÃ©cutable library, dont la dÃ©finition est donnÃ©e dans le fichier recpt/librarymain.cpp. C'est aussi lÃ  que l'objet receptionist (dÃ©fini dans recpt/receptionist.cpp) est construit. La responsabilitÃ© de toutes les actions est passÃ©e Ã  l'objet receptionist, qui les traite en maintenant, sous la forme d'un champ de donnÃ©es, un tableau associatif de la classe de base d'action, indexÃ© par les noms d'actions.</Text>
+<Figure id="action_base_class_api">
+<Title>
+<Text id="1008">API de la classe de base d'action</Text>
+</Title>
+<CodeLine>class action {</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>   cgiargsinfoclass argsinfo;</CodeLine>
+<CodeLine>   text_t gsdlhome;</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   action ();</CodeLine>
+<CodeLine>   virtual ~action ();</CodeLine>
+<CodeLine>   virtual void configure (const text_t &amp;key, const text_tarray &amp;cfgline);</CodeLine>
+<CodeLine>   virtual bool init (ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual text_t get_action_name ();</CodeLine>
+<CodeLine>   cgiargsinfoclass getargsinfo ();</CodeLine>
+<CodeLine>   virtual bool check_cgiargs (cgiargsinfoclass &amp;argsinfo,</CodeLine>
+<CodeLine>              cgiargsclass &amp;args, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual bool check_external_cgiargs (cgiargsinfoclass &amp;argsinfo,</CodeLine>
+<CodeLine>              cgiargsclass &amp;args,</CodeLine>
+<CodeLine>              outconvertclass &amp;outconvert,</CodeLine>
+<CodeLine>              const text_t &amp;saveconf,</CodeLine>
+<CodeLine>              ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void get_cgihead_info (cgiargsclass &amp;args,</CodeLine>
+<CodeLine>              recptprotolistclass *protos,</CodeLine>
+<CodeLine>              response_t &amp;response,</CodeLine>
+<CodeLine>              text_t &amp;response_data,</CodeLine>
+<CodeLine>              ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual bool uses_display (cgiargsclass &amp;args);</CodeLine>
+<CodeLine>   virtual void define_internal_macros (displayclass &amp;disp,</CodeLine>
+<CodeLine>              cgiargsclass &amp;args,</CodeLine>
+<CodeLine>              recptprotolistclass *protos,</CodeLine>
+<CodeLine>              ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void define_external_macros (displayclass &amp;disp,</CodeLine>
+<CodeLine>              cgiargsclass &amp;args,</CodeLine>
+<CodeLine>              recptprotolistclass *protos,</CodeLine>
+<CodeLine>              ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual bool do_action (cgiargsclass &amp;args,</CodeLine>
+<CodeLine>              recptprotolistclass *protos,</CodeLine>
+<CodeLine>              browsermapclass *browsers,</CodeLine>
+<CodeLine>              displayclass &amp;disp,</CodeLine>
+<CodeLine>              outconvertclass &amp;outconvert,</CodeLine>
+<CodeLine>              ostream &amp;textout,</CodeLine>
+<CodeLine>              ostream &amp;logout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="1009">La figureÂ <CrossRef target="Figure" ref="action_base_class_api"/> montre l'API de la classe de base d'action. Lors de l'exÃ©cution d'une action, l'objet receptionist appelle plusieurs fonctions, en commenÃ§ant par check_cgiargs(). La plupart l'aident Ã  vÃ©rifier, positionner, et dÃ©finir des valeurs et des macros, alors que la fonction do_action() engendre pour de bon la page produite. Si un objet hÃ©ritÃ© particulier ne dispose d'aucune dÃ©finition pour une fonction membre donnÃ©e, il passe Ã  la dÃ©finition de la classe de base qui implÃ©mente un comportement par dÃ©faut appropriÃ©.</Text>
+<Text id="1010">Voici des explications des fonctions membre:</Text>
+<BulletList>
+<Bullet>
+<Text id="1011">get_action_name()renvoie la valeur de l'argument CGIa, qui spÃ©cifie cette action. Le nom devrait Ãªtre court, mais peut faire plus d'un caractÃšre.</Text>
+</Bullet>
+<Bullet>
+<Text id="1012">check_cgiargs()est appelÃ©e avant les fonctionsget_cgihead_info(),define_external_macros(), etdo_action(). En cas d'erreur un message est Ã©crit surlogout; si l'erreur est importante la fonction renvoie la valeur faussefalseet ne produit aucun contenu de page.</Text>
+</Bullet>
+<Bullet>
+<Text id="1013">check_external_cgiargs()est appelÃ©e aprÃšscheck_cgiargs()pour toutes les actions. Il n'a d'usage que d'Ã©craser certains comportements par dÃ©faut, comme par exemple produire une page de connexion quand la page demandÃ©e exige une authentification. </Text>
+</Bullet>
+<Bullet>
+<Text id="1014">get_cgihead_info()positionne les informations de l'en-tÃªte CGI. Si la variableresponsevautlocation, alorsresponse_datacontient l'adresse de redirection. Siresponsevautcontent, alorsresponse_datacontient le type de contenu.</Text>
+</Bullet>
+<Bullet>
+<Text id="1015">uses_display()renvoietruesi la classe d'affichagedisplayclassest nÃ©cessaire pour produire le contenu de la page (comportement par dÃ©faut).</Text>
+</Bullet>
+<Bullet>
+<Text id="1016">define_internal_macros()dÃ©finit toutes les macros liÃ©es aux pages gÃ©nÃ©rÃ©es par cette action.</Text>
+</Bullet>
+<Bullet>
+<Text id="1017">define_external_macros()dÃ©finit toutes les macros qui pourraient Ãªtre utilisÃ©es par d'autres actions pour produire des pages.</Text>
+</Bullet>
+<Bullet>
+<Text id="1018">do_action()gÃ©nÃšre la page produite, normalement dans un flux Ã  travers l'objet de langage de macrodisplayet l'objet de conversion de la sortietextout. Renvoie la valeur faussefalsesi une erreur a empÃªchÃ© l'action de produire quoi que ce soit.</Text>
+</Bullet>
+</BulletList>
+<Text id="1019">Au dÃ©but de la dÃ©finition de classe, argsinfo est le champ de donnÃ©es protÃ©gÃ© (utilisÃ© dans l'extrait de code reprÃ©sentÃ© dans la figureÂ <CrossRef target="Figure" ref="using_the_cgiargsinfoclass_from_pageactioncpp"/>) qui stoke les informations d'argument CGI spÃ©cifiÃ©es dans une fonction constructeur d'action hÃ©ritÃ©e. L'autre champ de donnÃ©es, gsdlhome, enregistre GSDLHOME pour pouvoir y accÃ©der plus facilement<FootnoteRef id="5"/>. L'objet inclut Ã©galement les fonctions configure() et init() Ã  des fins d'initialisation.</Text>
+</Content>
+</Subsection>
+<Subsection id="formatting">
+<Title>
+<Text id="1020">Mise en forme</Text>
+</Title>
+<Content>
+<Figure id="core_data_structures_in_format">
+<Title>
+<Text id="1021">Structures de donnÃ©es centrales de la classe de mise en forme</Text>
+</Title>
+<CodeLine>enum command_t {comIf, comOr, comMeta, comText, comLink, comEndLink,</CodeLine>
+<CodeLine>         comNum, comIcon, comDoc,</CodeLine>
+<CodeLine>         comHighlight, comEndHighlight};</CodeLine>
+<CodeLine>enum pcommand_t {pNone, pImmediate, pTop, pAll};</CodeLine>
+<CodeLine>enum dcommand_t {dMeta, dText};</CodeLine>
+<CodeLine>enum mcommand_t {mNone, mCgiSafe};</CodeLine>
+<CodeLine>struct metadata_t {</CodeLine>
+<CodeLine>   void clear();</CodeLine>
+<CodeLine>   metadata_t () {clear();}</CodeLine>
+<CodeLine>   text_t metaname;</CodeLine>
+<CodeLine>   mcommand_t metacommand;</CodeLine>
+<CodeLine>   pcommand_t parentcommand;</CodeLine>
+<CodeLine>   text_t parentoptions;</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine>// The decision component of an {If}{decision,true-text,false-text}</CodeLine>
+<CodeLine>// formatstring. The decision can be based on metadata or on text;</CodeLine>
+<CodeLine>// normally that text would be a macro like</CodeLine>
+<CodeLine>// _cgiargmode_.</CodeLine>
+<CodeLine>struct decision_t {</CodeLine>
+<CodeLine>   void clear();</CodeLine>
+<CodeLine>   decision_t () {clear();}</CodeLine>
+<CodeLine>   dcommand_t command;</CodeLine>
+<CodeLine>   metadata_t meta;</CodeLine>
+<CodeLine>   text_t text;</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine>struct format_t {</CodeLine>
+<CodeLine>   void clear();</CodeLine>
+<CodeLine>   format_t () {clear();}</CodeLine>
+<CodeLine>   command_t command;</CodeLine>
+<CodeLine>   decision_t decision;</CodeLine>
+<CodeLine>   text_t text;</CodeLine>
+<CodeLine>   metadata_t meta;</CodeLine>
+<CodeLine>   format_t *nextptr;</CodeLine>
+<CodeLine>   format_t *ifptr;</CodeLine>
+<CodeLine>   format_t *elseptr;</CodeLine>
+<CodeLine>   format_t *orptr;</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="1022">Bien que la mise en forme soit reprÃ©sentÃ©e comme une seule entitÃ© dans la figureÂ <CrossRef target="Figure" ref="greenstone_runtime_system"/>, elle constitue en rÃ©alitÃ© une collection de structures de donnÃ©es et de fonctions, rassemblÃ©es dans le fichier d'en-tÃªtes recpt/formattools.h. Les structures de donnÃ©es centrales de la classe sont reprÃ©sentÃ©es figureÂ <CrossRef target="Figure" ref="core_data_structures_in_format"/>.</Text>
+<Figure id="data_structures_built_for_sample_format_statement">
+<Title>
+<Text id="1023">Structures de donnÃ©es construites pour l'exemple d'instruction de mise en forme</Text>
+</Title>
+<File width="395" height="152" url="images/Dev_Fig_43.png"/>
+</Figure>
+<Text id="1024">L'implÃ©mentation est plus facile Ã  expliquer avec un exemple. Quand l'instruction de mise en forme</Text>
+<CodeLine>format CL1Vlist</CodeLine>
+<Text id="1025" type="code">"[link][Title]{If}{[Creator], par [Creator]}[/link]"</Text>
+<Text id="1026">est lue dans un fichier de configuration de collection, elle est analysÃ©e par les fonctions de formattools.cpp et la structure de donnÃ©es interconnectÃ©e montrÃ©e figureÂ <CrossRef target="Figure" ref="data_structures_built_for_sample_format_statement"/> est construite. Quand il faut faire Ã©valuer l'instruction de mise en forme par une action, la structure de donnÃ©es est traversÃ©e. Le chemin pris au niveau des noeuds comIf et comOr dÃ©pend des mÃ©ta-donnÃ©es renvoyÃ©es par un appel au protocole.</Text>
+<Text id="1027">Il se peut que lors du rapatriement de mÃ©ta-donnÃ©es, le rÃ©sultat contienne d'autres macros et syntaxes de mise en forme. Ceci est gÃ©rÃ© par des allers-retours entre l'analyse et l'Ã©valuation, en fonction des besoins.</Text>
+</Content>
+</Subsection>
+<Subsection id="macro_language">
+<Title>
+<Text id="1028">Le langage de macros</Text>
+</Title>
+<Content>
+<Text id="1029">L'entitÃ© de langage de macros de la figureÂ <CrossRef target="Figure" ref="greenstone_runtime_system"/>, tout comme celle de mise en forme, ne correspond pas Ã  une unique classe C++. Dans ce cas-ci il existe une classe centrale, mais l'implÃ©mentation du langage de macros dÃ©pend aussi de fonctions et de classes de support.</Text>
+<Text id="1030">Ici encore, on expliquera mieux l'implÃ©mentation en utilisant un exemple. Donnons d'abord quelques dÃ©finitions d'Ã©chantillons de macros qui illustrent les prioritÃ©s entre macros, puisÂ --Â Ã  l'aide d'un diagrammeÂ --Â nous dÃ©crirons les structures de donnÃ©es de base construites pour supporter cette activitÃ©. Enfin, nous prÃ©senterons et dÃ©crirons les fonctions membre publiques de displayclass, l'objet de macro de premier niveau.</Text>
+<Figure id="illustration_of_macro_precedence">
+<Title>
+<Text id="1031">Illustration de la prioritÃ© entre les macros</Text>
+</Title>
+<CodeLine>package query</CodeLine>
+<CodeLine>_header_ []         {_querytitle_}</CodeLine>
+<CodeLine>_header_ [l=en]     {Search page}</CodeLine>
+<CodeLine>_header_ [c=demo]   {&lt;table bgcolor=green&gt;&lt;tr&gt;&lt;td&gt;_querytitle_&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;}</CodeLine>
+<CodeLine>_header_ [v=1]      {_textquery_}</CodeLine>
+<CodeLine>_header_ [l=fr,v=1,c=hdl] {HDL Page de recherche}</CodeLine>
+</Figure>
+<Text id="1032">Dans une collection Greenstone habituelle, la prioritÃ© entre les macros est normalement: c (pour la collection) passe avant v (pour une interface graphique ou textuelle), qui passe avant l (pour la langue). Ceci est mis en place par la ligne</Text>
+<CodeLine>macroprecedence c,v,l</CodeLine>
+<Text id="1033">dans le fichier de configuration principal main.cfg. Les instructions de macros de la figureÂ <CrossRef target="Figure" ref="illustration_of_macro_precedence"/> dÃ©finissent des exemples de macros pour l'en-tÃªte _header_ du paquetage de requÃªte pour diverses valeurs de c, v, et l. Si les arguments CGI donnÃ©s lors de l'invocation d'une action comprennent c=hdl, v=1, et l=en, la macro _header_[v=1] serait alors sÃ©lectionnÃ©e pour l'affichage. Elle serait sÃ©lectionnÃ©e avant _content_[l=en] car v a la prioritÃ© sur l. La macro _content_[l=fr,v=1,c=hdl] ne serait pas sÃ©lectionnÃ©e parce que le paramÃštre de page pour l est diffÃ©rent.</Text>
+<Figure id="data_structures_representing_the_default_macros">
+<Title>
+<Text id="1034">Structures de donnÃ©es reprÃ©sentant les macros par dÃ©faut</Text>
+</Title>
+<File width="382" height="194" url="images/Dev_Fig_45.png"/>
+</Figure>
+<Text id="1035">La figureÂ <CrossRef target="Figure" ref="data_structures_representing_the_default_macros"/> montre la structure de donnÃ©es principale construite lors de la lecture des fichiers de macros spÃ©cifiÃ©s dans etc/main.cfg. Il s'agit essentiellement d'un tableau associatif de tableaux associatifs de tableaux associatifs. Le niveau le plus Ã©levÃ© (Ã  gauche) indexe le paquetage dont provient la macro, et le deuxiÃšme niveau indexe le nom de la macro. Le dernier niveau indexe tous les paramÃštres spÃ©cifiÃ©s, en stockant chacun sous le type mvalue qui enregistre, en plus de la valeur de la macro, le fichier dont elle provient. Par exemple, on peut trouver le texte dÃ©fini pour _header_[l=en] dans la figureÂ <CrossRef target="Figure" ref="illustration_of_macro_precedence"/> stockÃ© dans le plus bas des deux enregistrements mvalue dans la figureÂ <CrossRef target="Figure" ref="data_structures_representing_the_default_macros"/>.</Text>
+<Figure id="displayclass_api">
+<Title>
+<Text id="1036">API de la classe d'affichage displayclass</Text>
+</Title>
+<CodeLine>class displayclass</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   displayclass ();</CodeLine>
+<CodeLine>   ~displayclass ();</CodeLine>
+<CodeLine>   int isdefaultmacro (text_t package, const text_t &amp;macroname);</CodeLine>
+<CodeLine>   int setdefaultmacro (text_t package, const text_t &amp;macroname,  </CodeLine>
+<CodeLine>         text_t params, const text_t &amp;macrovalue);</CodeLine>
+<CodeLine>   int loaddefaultmacros (text_t thisfilename);</CodeLine>
+<CodeLine>   void openpage (const text_t &amp;thispageparams,</CodeLine>
+<CodeLine>         const text_t &amp;thisprecedence);</CodeLine>
+<CodeLine>   void setpageparams (text_t thispageparams,</CodeLine>
+<CodeLine>         text_t thisprecedence);</CodeLine>
+<CodeLine>   int setmacro (const text_t &amp;macroname,</CodeLine>
+<CodeLine>         text_t package,</CodeLine>
+<CodeLine>         const text_t &amp;macrovalue);</CodeLine>
+<CodeLine>   void expandstring (const text_t &amp;inputtext, text_t &amp;outputtext);</CodeLine>
+<CodeLine>   void expandstring (text_t package, const text_t &amp;inputtext,</CodeLine>
+<CodeLine>         text_t &amp;outputtext, int recursiondepth = 0);</CodeLine>
+<CodeLine>   void setconvertclass (outconvertclass *theoutc) {outc = theoutc;}</CodeLine>
+<CodeLine>   outconvertclass *getconvertclass () {return outc;}</CodeLine>
+<CodeLine>   ostream *setlogout (ostream *thelogout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="1037">L'objet central de support du langage de macros est displayclass, dÃ©fini dans lib/display.h. Ses fonctions membre publiques sont reprÃ©sentÃ©es figureÂ <CrossRef target="Figure" ref="displayclass_api"/>. La classe lit les fichiers de macros spÃ©cifiÃ©s Ã  l'aide de loaddefaultmacros(), en stockant dans une section protÃ©gÃ©e de la classe (non reprÃ©sentÃ©e), le type de la structure de donnÃ©es montrÃ©e figureÂ <CrossRef target="Figure" ref="data_structures_representing_the_default_macros"/>. Il est Ã©galement permis au systÃšme d'exÃ©cution de positionner des macros Ã  l'aide de setmacro() (dans le dernier exemple de la sectionÂ <CrossRef target="Section" ref="how_the_conceptual_framework_fits_together"/>, pageaction positionne _homeextra_ comme Ã©tant la table des collections dynamiquement gÃ©nÃ©rÃ©e en utilisant cette fonction). Ceci est supportÃ© par un ensemble de tableaux associatifs similaires Ã  ceux utilisÃ©s pour reprÃ©senter les fichiers de macros (ce n'est pas identique, car le premier n'a pas besoin d'une couche de Â«paramÃštresÂ»). Dans displayclass, Les macros lues dans le fichier s'appellent les<i>macros par dÃ©faut</i>. Les macros locales spÃ©cifiÃ©es Ã  travers setmacro() s'appellent<i>macros courantes</i>, et sont effacÃ©es de la mÃ©moire aprÃšs la gÃ©nÃ©ration de la page.</Text>
+<Text id="1038">Quand il faut produire une page, openpage() est d'abord appelÃ©e pour communiquer les rÃ©glages courants des paramÃštres de page (l=en etc.). Ensuite, le texte et les macros passent dans un flux Ã  travers la classeÂ --Â typiquement depuis une actionclassÂ --Â en utilisant du code tel que:</Text>
+<CodeLine>cout &lt;&lt; text_t2ascii &lt;&lt; display &lt;&lt; "_amacro_ "</CodeLine>
+<CodeLine>         &lt;&lt; "_anothermacro_ ";</CodeLine>
+<Text id="1039">Le rÃ©sultat est que les macros sont dÃ©veloppÃ©es selon les rÃ©glages des paramÃštres de page. Si nÃ©cessaire, ces rÃ©glages peuvent Ãªtre modifiÃ©s en cours de procÃ©dure Ã  l'aide d'une action en utilisant setpageparams(). Les fonctions membre publiques restantes fournissent le support de bas niveau.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_receptionist_code">
+<Title>
+<Text id="1040">Le code du rÃ©ceptionniste</Text>
+</Title>
+<Content>
+<Text id="1041">Nous avons maintenant dÃ©crit les objets principaux du rÃ©ceptionniste. Nous dÃ©taillons ci-dessous les classes de support, situÃ©es dans GSDLHOME/src/recpt. Ã l'exception des cas oÃ¹ l'efficacitÃ© primeÂ --Â les dÃ©finitions sont alors inlineÂ --Â les dÃ©tails d'implÃ©mentation sont contenus dans le fichier .cpp correspondant au fichier d'en-tÃªtes. Les fichiers de support comportent souvent le mot tool (outil) dans leur nom, comme par exemple OIDtools.h et formattools.h.</Text>
+<Text id="1042">Un autre ensemble de fichiers de portÃ©e lexicale comprend le prÃ©fixe z3950. Ces fichiers fournissent un accÃšs distant aux bases de donnÃ©es et aux catalogues en ligne publiquement accessibles Ã  travers le protocole Z39.50.</Text>
+<Text id="1043">Le terme browserclass est inclus dans un autre groupe important de fichiers de support. Ces fichiers sont liÃ©s Ã  travers une hiÃ©rarchie d'hÃ©ritage virtuel. En tant que groupe, ils supportent une notion abstraite de navigation: gÃ©nÃ©ration de pages en sÃ©rie comportant des contenus de documents compartimentÃ©s ou des mÃ©ta-donnÃ©es. Les possibilitÃ©s des navigation comportent la lecture de documents triÃ©s par ordre alphabÃ©tique des titres ou par ordre chronologique des dates; l'exploration des rÃ©sultats d'une requÃªte par lot de dix entrÃ©es; et l'accÃšs aux pages individuelles d'un livre en utilisant le mÃ©canisme aller Ã  la page.... Chaque possibilitÃ© de navigation hÃ©rite de la classe de base, browserclass:</Text>
+<BulletList>
+<Bullet>
+<Text id="1044">datelistbrowserclass fournit le support pour les listes chronologiques;</Text>
+</Bullet>
+<Bullet>
+<Text id="1045">hlistbrowserclass fournit le support pour les listes horizontales;</Text>
+</Bullet>
+<Bullet>
+<Text id="1046">htmlbrowserclass fournit le support pour les pages HTML;</Text>
+</Bullet>
+<Bullet>
+<Text id="1047">invbrowserclass fournit le support pour les listes invisibles;</Text>
+</Bullet>
+<Bullet>
+<Text id="1048">pagedbrowserclass fournit le support pour aller Ã  une page particuliÃšre;</Text>
+</Bullet>
+<Bullet>
+<Text id="1049">vlistbrowserclass fournit le support pour les listes verticales.</Text>
+</Bullet>
+</BulletList>
+<Text id="1050">Les actions accÃšdent aux objets browserclass Ã  travers browsetools.h.</Text>
+<Table class="hidden">
+<Title/>
+<TableContent>
+<tr>
+<th width="140">
+<Text id="1051">OIDtools.h</Text>
+</th>
+<th width="390">
+<Text id="1052">Support fonctionnel pour l'Ã©valuation des identifiants de documents sur le protocole.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1053">action.h</Text>
+</th>
+<th width="390">
+<Text id="1054">Classe de base pour l'entitÃ© d'action dÃ©crite figureÂ <CrossRef target="Figure" ref="greenstone_runtime_system"/>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1055">authenaction.h</Text>
+</th>
+<th width="390">
+<Text id="1056">Action hÃ©ritÃ©e pour la gestion de l'authentification d'un utilisateur.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1057">browserclass.h</Text>
+</th>
+<th width="390">
+<Text id="1058">Classe de base pour les activitÃ©s de navigation abstraites.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1059">browsetools.h</Text>
+</th>
+<th width="390">
+<Text id="1060">Support fonctionnel pour l'accÃšs Ã  browserclass (hiÃ©rarchie). Les fonctionnalitÃ©s comprennent le dÃ©veloppement et la contraction de contenus, l'affichage d'une table des matiÃšres, et la gÃ©nÃ©ration de contrÃŽles tels que le mÃ©canisme aller Ã  la page....</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1061">cgiargs.h</Text>
+</th>
+<th width="390">
+<Text id="1062">DÃ©finit cgiarginfo, utilisÃ© dans la figureÂ <CrossRef target="Figure" ref="using_the_cgiargsinfoclass_from_pageactioncpp"/>, ainsi que le support d'autres structures de donnÃ©es pour les arguments CGI.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1063">cgiutils.h</Text>
+</th>
+<th width="390">
+<Text id="1064">Support fonctionnel pour les arguments CGI utilisant les structures de donnÃ©es dÃ©finies dans le fichier cgiargs.h.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1065">cgiwrapper.h</Text>
+</th>
+<th width="390">
+<Text id="1066">Support fonctionnel qui fait tout ce qui est nÃ©cessaire pour produire une page en utilisant le protocole CGI. L'accÃšs se fait Ã  travers la fonction</Text>
+<CodeLine>void cgiwrapper (receptionist &amp;recpt, text_t collection);</CodeLine>
+<Text id="1067">qui est la seule fonction dÃ©clarÃ©e dans le fichier d'en-tÃªtes. Tout le reste du fichier .cpp correspondant a une portÃ©e lexicale locale au fichier (par l'utilisation du mot-clef C++ static). Si la fonction est employÃ©e pour une collection particuliÃšre alors il faudrait positionner collection, sinon cette chaÃ®ne doit Ãªtre la chaÃ®ne vide "". Ce code comprend du support pour Fast-CGI.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1068">collectoraction.h</Text>
+</th>
+<th width="390">
+<Text id="1069">Action hÃ©ritÃ©e qui facilite la construction de collections par l'utilisateur final Ã  travers le Collector. La page gÃ©nÃ©rÃ©e provient de collect.dm et elle est contrÃŽlÃ©e par l'argument CGI p=page.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1070">comtypes.h</Text>
+</th>
+<th width="390">
+<Text id="1071">Types centraux du protocole.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1072">converter.h</Text>
+</th>
+<th width="390">
+<Text id="1073">Support objet pour les convertisseurs de flux.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1074">datelistbrowserclass.h</Text>
+</th>
+<th width="390">
+<Text id="1075">HÃ©ritÃ© de browserclass, cet objet fournit un support de navigation pour les listes chronologiques telles que celle qu'on peut voir dans la collection Â«ArchivesÂ» de Greenstone sous Dates dans la barre de navigation.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1076">documentaction.h</Text>
+</th>
+<th width="390">
+<Text id="1077">Action hÃ©ritÃ©e utilisÃ©e pour rapatrier une document ou une portion d'une hiÃ©rarchie de classification.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1078">extlinkaction.h</Text>
+</th>
+<th width="390">
+<Text id="1079">Action hÃ©ritÃ©e qui contrÃŽle si un utilisateur se rend directement Ã  un lien externe, ou s'il doit passer par une page d'avertissement qui l'alerte du fait qu'il s'apprÃªte Ã  sortir du systÃšme de bibliothÃšque numÃ©rique.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1080">formattools.h</Text>
+</th>
+<th width="390">
+<Text id="1081">Support fonctionnel pour l'analyse et l'Ã©valuation des instructions format de configuration de collection. DÃ©taillÃ© dans la sectionÂ <CrossRef target="Subsection" ref="formatting"/>, ci-dessus.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1082">historydb.h</Text>
+</th>
+<th width="390">
+<Text id="1083">Structures de donnÃ©es et support fonctionnel pour la gestion d'une base de donnÃ©es des requÃªtes prÃ©cÃ©dentes de telle sorte qu'un utilisateur puisse faire une nouvelle requÃªte en reprenant d'anciens termes.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1084">hlistbrowserclass.h</Text>
+</th>
+<th width="390">
+<Text id="1085">HÃ©ritÃ© de browserclass, cet objet fournit le support de navigation pour les listes horizontales.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1086">htmlbrowserclass.h</Text>
+</th>
+<th width="390">
+<Text id="1087">HÃ©ritÃ© de browserclass, cet objet fournit le support de navigation pour les pages HTML.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1088">htmlgen.h</Text>
+</th>
+<th width="390">
+<Text id="1089">Support fonctionnel pour mettre en valeur les termes de requÃªte dans une chaÃ®ne text_t.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1090">htmlutils.h</Text>
+</th>
+<th width="390">
+<Text id="1091">Support fonctionnel qui convertit une chaÃ®ne text_t en le HTML Ã©quivalent. Les symboles ", &amp;, &lt;, et &gt; sont respectivement convertis en &amp;quot;, &amp;amp;, &amp;lt;, et &amp;gt;.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1092">infodbclass.h</Text>
+</th>
+<th width="390">
+<Text id="1093">DÃ©finit deux classes: gdbmclass et infodbclass. La premiÃšre fournit l'API de Greenstone pour GDBM; la deuxiÃšme est la classe objet utilisÃ©e pour stocker une entrÃ©e d'enregistrement lue dans une base de donnÃ©es GDBM, et c'est essentiellement un tableau associatif de tableaux de chaÃ®nes text_t indicÃ©es par des entiers.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1094">invbrowserclass.h</Text>
+</th>
+<th width="390">
+<Text id="1095">HÃ©ritÃ© de browserclass, cet objet fournit le support de navigation pour les listes qui ne sont pas censÃ©es Ãªtre affichÃ©es (invisibles). </Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1096">nullproto.h</Text>
+</th>
+<th width="390">
+<Text id="1097">HÃ©ritÃ©e de recptproto, cette classe rÃ©alise le protocole vide, implÃ©mentÃ© par des appels de fonctions du rÃ©ceptionniste vers le serveur de collection.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1098">pageaction.h</Text>
+</th>
+<th width="390">
+<Text id="1099">Action hÃ©ritÃ©e qui, en conjonction avec le fichier de macros nommÃ© dans l'argument p=page, gÃ©nÃšre une page web.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1100">pagedbrowserclass.h</Text>
+</th>
+<th width="390">
+<Text id="1101">HÃ©ritÃ© de browserclass, cet objet fournit le support de navigation pour le mÃ©canisme aller Ã  la page..., vu par exemple dans la collection Gutenberg.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1102">pingaction.h</Text>
+</th>
+<th width="390">
+<Text id="1103">Action hÃ©ritÃ©e qui vÃ©rifie si une collection particuliÃšre rÃ©pond aux requÃªtes.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1104">queryaction.h</Text>
+</th>
+<th width="390">
+<Text id="1105">Action hÃ©ritÃ©e qui prend la requÃªte, les rÃ©glages et les prÃ©fÃ©rences stipulÃ©s, et effectue une recherche, en gÃ©nÃ©rant comme rÃ©sultat le sous-ensemble des documents o=num correspondants, en commenÃ§ant Ã  la position r=num.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1106">querytools.h</Text>
+</th>
+<th width="390">
+<Text id="1107">Support fonctionnel pour les requÃªtes.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1108">receptionist.h</Text>
+</th>
+<th width="390">
+<Text id="1109">Objet de premier niveau du rÃ©ceptionniste. Maintient un enregistrement des informations d'arguments CGI, des instantiations de chaque action hÃ©ritÃ©e, des instantiations de chaque objet de navigation, l'objet central de langage de macros displayclass, et tous les convertisseurs possibles.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1110">recptconfig.h</Text>
+</th>
+<th width="390">
+<Text id="1111">Support fonctionnel pour la lecture des fichiers de configuration principal et de site.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1112">recptproto.h</Text>
+</th>
+<th width="390">
+<Text id="1113">Classe de base pour le protocole.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1114">statusaction.h</Text>
+</th>
+<th width="390">
+<Text id="1115">Action hÃ©ritÃ©e qui gÃ©nÃšre, en conjonction avec le fichier status.dm, les diverses pages d'administration.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1116">tipaction.h</Text>
+</th>
+<th width="390">
+<Text id="1117">Action hÃ©ritÃ©e qui produit, en conjonction avec tip.dm, une page web contenant une astuce choisie au hasard parmi la liste d'astuces stockÃ©e dans le fichier tip.dm.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1118">userdb.h</Text>
+</th>
+<th width="390">
+<Text id="1119">Structure de donnÃ©es et support fonctionnel pour maintenir une base de donnÃ©es GDBM d'utilisateurs: leur mot de passe, leurs groupes, etc.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1120">usersaction.h</Text>
+</th>
+<th width="390">
+<Text id="1121">Une action d'administration hÃ©ritÃ©e de la classe de base qui supporte l'ajout et la destruction d'utilisateurs, ainsi que la modification de la liste des groupes auxquels ils appartiennent.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1122">vlistbrowserclass.h</Text>
+</th>
+<th width="390">
+<Text id="1123">HÃ©ritÃ© de browserclass, cet objet fournit un support de navigation pour les listes verticales, point d'appui des classificateurs. Par exemple, les fils du noeud des titres commenÃ§ant par la lettre N sont stipulÃ©s comme formant une VList.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1124">z3950cfg.h</Text>
+</th>
+<th width="390">
+<Text id="1125">Support de structure de donnÃ©es pour le protocole Z39.50. UtilisÃ© par z3950proto.cpp, qui dÃ©finit la classe de protocole principale (hÃ©ritÃ©e de la classe de base recptproto) et l'analyseur de fichier de configuration zparse.y (Ã©crit en YACC).</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1126">z3950proto.h</Text>
+</th>
+<th width="390">
+<Text id="1127">HÃ©ritÃ©e de recptproto, cette classe rÃ©alise le protocole de rÃ©fÃ©rence Z39.50 de sorte que le rÃ©ceptionniste de Greenstone puisse accÃ©der Ã  des sites de bibliothÃšques distantes hÃ©bergÃ©s sur serveur Z39.50.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1128">z3950server.h</Text>
+</th>
+<th width="390">
+<Text id="1129">Support complÃ©mentaire pour le protocole Z39.50.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="initialisation">
+<Title>
+<Text id="1130">Initialisation</Text>
+</Title>
+<Content>
+<Text id="1131">Dans Greenstone, l'initialisation est une opÃ©ration compliquÃ©e qui traite les fichiers de configuration et affecte des valeurs par dÃ©faut aux champs de donnÃ©es. En plus des fonctions d'hÃ©ritage et constructeur, les objets centraux dÃ©finissent les fonctions init() et configure() pour faciliter la normalisation de la tÃ¢che. MÃªme ainsi, l'ordre d'exÃ©cution peut Ãªtre difficile Ã  suivre. La prÃ©sente section dÃ©crit ce qui se passe.</Text>
+<Text id="1132">Greenstone utilise plusieurs fichiers de configuration pour des raisons diffÃ©rentes, mais tous suivent la mÃªme syntaxe. Ã moins qu'une ligne ne contienne que des blancs ou commence par un caractÃšre diÃšse (<i>#</i>), le premier mot dÃ©finit un mot-clef et les mots suivants reprÃ©sentent une configuration particuliÃšre pour ce mot-clef.</Text>
+<Text id="1133">Les lignes des fichiers de configuration sont passÃ©es une Ã  une Ã  la fonction configure() sous la forme de deux arguments: le mot-clef et un tableau des mots restants. En se fondant sur le mot-clef, un version particuliÃšre de la fonction configure() dÃ©cide si l'information l'intÃ©resse, et dans l'affirmative, la stocke. Par exemple, collectserver (qui correspond Ã  l'objet de collection de la figureÂ <CrossRef target="Figure" ref="greenstone_runtime_system"/>) traite les instructions de mise en forme du fichier de configuration de collection. Quand la fonction configure() reÃ§oit le mot-clef format, elle dÃ©clenche une instruction if qui stocke dans l'objet une copie du deuxiÃšme argument de la fonction. </Text>
+<Text id="1134">AprÃšs le traitement du mot-clef et avant de rendre la main, certaines versions de configure() passent les donnÃ©es aux fonctions configure() d'autres objets. L'objet rÃ©ceptionniste appelle les fonctions configure() des objets d'actions, de protocoles, et de navigation. L'objet de protocole vide appelle la fonction configure() de chaque objet de collection; l'objet de collection appelle les objets de filtre et source.</Text>
+<Text id="1135">En C++, les champs de donnÃ©es sont normalement initialisÃ©s par la fonction qui construit l'objet. Cependant, dans Greenstone, certaines initialisations dÃ©pendent de valeurs lues dans des fichiers de configuration, il faut donc procÃ©der Ã  un deuxiÃšme tour d'initialisations. C'est le but des fonctions membre init(), et dans certains cas cela mÃšne Ã  d'autres appels de fonctions configure().</Text>
+<Figure id="initialising_greenstone_using_the_null_protocol">
+<Title>
+<Text id="1136">Initialisation de Greenstone avec le protocole vide</Text>
+</Title>
+<CodeLine>============</CodeLine>
+<CodeLine>Main program</CodeLine>
+<CodeLine>============</CodeLine>
+<CodeLine>Statically construct Receptionist</CodeLine>
+<CodeLine>Statically construct NullProtocol</CodeLine>
+<CodeLine>Establish the value for 'gsdlhome' by reading gsdlsite.cfg</CodeLine>
+<CodeLine>Foreach directory in GSDLHOME/collect that isn't "modelcol":</CodeLine>
+<CodeLine>   Add directory name (now treated as collection name) to NullProtocol:</CodeLine>
+<CodeLine>       Dynamically construct Collection</CodeLine>
+<CodeLine>       Dynamically construct Gdbm class</CodeLine>
+<CodeLine>       Dynamically construct the Null Filter</CodeLine>
+<CodeLine>       Dynamically construct the Browse Filter</CodeLine>
+<CodeLine>       Dynamically construct MgSearch</CodeLine>
+<CodeLine>       Dynamically construct the QueryFilter</CodeLine>
+<CodeLine>       Dynamically construct the MgGdbmSource</CodeLine>
+<CodeLine>       Configure Collection with 'collection'</CodeLine>
+<CodeLine>           Passing 'collection' value on to Filters and Sources:</CodeLine>
+<CodeLine>       Configure Receptionist with 'collectinfo':</CodeLine>
+<CodeLine>           Passing 'collectinfo' value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>Add NullProtocol to Receptionist</CodeLine>
+<CodeLine>Add in UTF-8 converter</CodeLine>
+<CodeLine>Add in GB converter</CodeLine>
+<CodeLine>Add in Arabic converter</CodeLine>
+<CodeLine>Foreach Action:</CodeLine>
+<CodeLine>   Statically construct Action</CodeLine>
+<CodeLine>   Add Action to Receptionist</CodeLine>
+<CodeLine>Foreach Browsers:</CodeLine>
+<CodeLine>   Statically construct Browser</CodeLine>
+<CodeLine>   Add Browser to Receptionist</CodeLine>
+<CodeLine>Call function cgiwrapper:</CodeLine>
+<CodeLine>   =================</CodeLine>
+<CodeLine>   Configure objects</CodeLine>
+<CodeLine>   =================</CodeLine>
+<CodeLine>   Configure Receptionist with 'collection'</CodeLine>
+<CodeLine>       Passing 'collection' value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>       NullProtocol not interested in 'collection'</CodeLine>
+<CodeLine>   Configure Receptionist with 'httpimg'</CodeLine>
+<CodeLine>       Passing 'httpimg' value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>       NullProtocol passing 'httpimg' on to Collection</CodeLine>
+<CodeLine>       Passing 'httpimg' value on to Filters and Sources:</CodeLine>
+<CodeLine>   Configure Receptionist with 'gwcgi'</CodeLine>
+<CodeLine>       Passing 'gwcgi' value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>       NullProtocol passing 'gwcgi' on to Collection</CodeLine>
+<CodeLine>           Passing 'gwcgi' value on to Filters and Sources:</CodeLine>
+<CodeLine>   Reading in site configuration file gsdlsite.cfg</CodeLine>
+<CodeLine>       Configure Recptionist with 'gsdlhome'</CodeLine>
+<CodeLine>           Passing 'gsdlhome' value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>           NullProtocol passing 'gsdlhome' on to Collection</CodeLine>
+<CodeLine>               Passing 'gsdlhome' value on to Filters and Sources:</CodeLine>
+<CodeLine>       Configure Recptionist with ...</CodeLine>
+<CodeLine>       ... and so on for all entries in gsdlsite.cfg</CodeLine>
+<CodeLine>   Reading in main configuration file main.cfg</CodeLine>
+<CodeLine>       Confiugre Recptionist with ...</CodeLine>
+<CodeLine>       ... and so on for all entries in main.cfg</CodeLine>
+<CodeLine>   ====================</CodeLine>
+<CodeLine>   Initialising objects</CodeLine>
+<CodeLine>   ====================</CodeLine>
+<CodeLine>   Initialise the Receptionist</CodeLine>
+<CodeLine>       Configure Receptionist with 'collectdir'</CodeLine>
+<CodeLine>           Passing 'collectdir' value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>           NullProtocol not interested in 'collectdir'</CodeLine>
+<CodeLine>       Read in Macro files</CodeLine>
+<CodeLine>       Foreach Actions</CodeLine>
+<CodeLine>           Initialise Action</CodeLine>
+<CodeLine>       Foreach Protocol</CodeLine>
+<CodeLine>           Initialise Protocol</CodeLine>
+<CodeLine>           When Protocol==NullProtocol:</CodeLine>
+<CodeLine>               Foreach Collection</CodeLine>
+<CodeLine>                   Reading Collection's build.cfg</CodeLine>
+<CodeLine>                   Reading Collection's collect.cfg</CodeLine>
+<CodeLine>                       Configure Collection with 'creator'</CodeLine>
+<CodeLine>                           Passing 'creator' value on to Filters and Sources:</CodeLine>
+<CodeLine>                       Configure Collection with 'maintainer'</CodeLine>
+<CodeLine>                           Passing 'maintainer' value on to Filters and Sources:</CodeLine>
+<CodeLine>                       ... and so on for all entries in collect.cfg</CodeLine>
+<CodeLine>       Foreach Browsers</CodeLine>
+<CodeLine>           Initialise Browser</CodeLine>
+<CodeLine>   =============</CodeLine>
+<CodeLine>   Generate page</CodeLine>
+<CodeLine>   =============</CodeLine>
+<CodeLine>   Parse CGI arguments</CodeLine>
+<CodeLine>   Execute designated Action to produce page</CodeLine>
+<CodeLine>End.</CodeLine>
+</Figure>
+<Text id="1137">Les lignesÂ <CrossRef target="Figure" ref="initialising_greenstone_using_the_null_protocol"/> prÃ©sentent les messages de diagnostics gÃ©nÃ©rÃ©s par une version de Greenstone configurÃ©e pour mettre en valeur le processus d'initialisation. Le programme dÃ©marre Ã  la fonction main() du fichier recpt/librarymain.cpp. Il construit un objet de rÃ©ceptionniste et un objet de protocole vide, puis parcourt le fichier gsdlsite.cfg (situÃ© dans le mÃªme rÃ©pertoire que l'exÃ©cutable library) Ã  la recherche de gsdlhome et stocke son rÃ©sultat dans une variable. Pour chaque collection en ligneÂ --Â liste Ã©tablie en lisant les rÃ©pertoires prÃ©sents dans GSDLHOME/collectÂ --Â le programme construit un objet de collection, Ã  travers l'objet de protocole vide, qui contient des objets de filtre, de recherche et source, ainsi que quelques appels cÃ¢blÃ©s Ã  la fonction configure().</Text>
+<Text id="1138">La fonction main() ajoute ensuite l'objet de protocole vide au rÃ©ceptionniste, qui conserve un tableau de classe de base de protocoles dans un champ de donnÃ©es protÃ©gÃ©, et positionne ensuite plusieurs convertisseurs. La fonction main() construit tous les objets d'action et de navigation utilisÃ©s dans l'exÃ©cutable et les ajoute Ã  l'objet rÃ©ceptionniste. La fonction conclut en appelant la fonction cgiwrapper() de cgiwrapper.cpp, qui comporte elle-mÃªme une certaine quantitÃ© d'initialisation d'objets.</Text>
+<Text id="1139">La fonction cgiwrapper() comprend trois parties: configuration, initialisation, et gÃ©nÃ©ration de page. Tout d'abord, quelques appels cÃ¢blÃ©s Ã  la fonction configure() sont effectuÃ©s. Le fichier gsdlsite.cfg est ensuite lu et la fonction configure() est appelÃ©e pour chacune de ses lignes. MÃªme chose pour le fichier etc/main.cfg.</Text>
+<Text id="1140">La deuxiÃšme phase de la fonction cgiwrapper() effectue des appels Ã  init(). L'objet rÃ©ceptionniste ne fait qu'un appel Ã  sa fonction, mais cette invocation appelle les fonctions init() des diffÃ©rents objets qu'il contient. Un appel cÃ¢blÃ© Ã  configure() est d'abord effectuÃ© pour positionner collectdir, puis les fichiers de macros sont lus. La fonction init() de chaque action est appelÃ©e. MÃªme chose pour chaque protocole utilisÃ© dans le rÃ©ceptionnisteÂ --Â mais dans le cas du systÃšme dÃ©crit ici, seul le protocole vide y est stockÃ©. L'appel de la fonction init() de cet objet provoque d'autres configurations: pour chaque collection du protocole vide, les fichiers propres Ã  la collection build.cfg et collect.cfg sont lus et traitÃ©s, chaque ligne provoquant un appel Ã  la fonction configure().</Text>
+<Text id="1141">La phase finale de cgiwrapper() consiste Ã  analyser les arguments CGI, et appeler ensuite l'action appropriÃ©e. Tous ces appels sont effectuÃ©s avec le support de l'objet rÃ©ceptionniste.</Text>
+<Text id="1142">Les codes de configuration, initialisation, et de gÃ©nÃ©ration de page sont sÃ©parÃ©s car Greenstone est optimisÃ© pour fonctionner en tant que serveur (avec Fast-CGI, ou le protocole CORBA, ou la version Â«BibliothÃšque localeÂ» sous Windows). Dans ce mode de fonctionnement, le code de configuration et d'initialisation n'est effectuÃ© qu'une fois, et le programme demeure ensuite en mÃ©moire et gÃ©nÃšre de nombreuses pages web en rÃ©ponse aux requÃªtes des clients, sans nÃ©cessiter de rÃ©initialisation.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="configuring_your_greenstone_site">
+<Title>
+<Text id="1143">Configurer son site Greenstone</Text>
+</Title>
+<Content>
+<Text id="1144">Dans Greenstone, deux fichiers de configuration sont utilisÃ©s pour configurer divers aspects du site Greenstone. Il s'agit du fichier de configuration Â«principalÂ» main.cfg, qui se trouve dans GSDLHOME/etc, et du fichier de configuration Â«de siteÂ» gsdlsite.cfg, qui se trouve dans GSDLHOME/cgi-bin. Ces fichiers contrÃŽlent tous deux des aspects spÃ©cifiques de la configuration du site, et tous deux peuvent Ãªtre visualisÃ©s depuis la page d'administration de Greenstone.</Text>
+<Section id="main_configuration_file">
+<Title>
+<Text id="1145">Fichier de configuration principal</Text>
+</Title>
+<Content>
+<Text id="1146">Le fichier de configuration principal main.cfg sert Ã  configurer le rÃ©ceptionnisteÂ --Â la partie de Greenstone qui prÃ©sente les requÃªtes et affiche les pages. Vous pouvez tout contrÃŽler, des langues que l'interface peut utiliser aux journaux qui seront conservÃ©s.</Text>
+<Subsection id="site_maintenance_and_logging">
+<Title>
+<Text id="1147">Maintenance du site et journalisation</Text>
+</Title>
+<Content>
+<Text id="1148">Les lignes du fichier de configuration dictent la maniÃšre dont votre site Greenstone sera maintenu, quelles fonctionnalitÃ©s il offrira, quels Ã©vÃ©nements seront journalisÃ©s, et quelles notifications seront faites au mainteneur. La tableÂ <CrossRef target="Table" ref="configuration_options_for_site_maintenance_and_logging"/> dÃ©taille certaines des options disponibles; les options restantes sont dÃ©crites dans les sections suivantes.</Text>
+<Table id="configuration_options_for_site_maintenance_and_logging">
+<Title>
+<Text id="1149">Options de configuration pour la maintenance et la journalisation</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="1150"><b>Valeur</b></Text>
+</th>
+<th width="246">
+<Text id="1151"><b>But</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1152"><i>maintainer</i></Text>
+</th>
+<th width="151">
+<Text id="1153">vide ou une adresse de courrier Ã©lectronique </Text>
+</th>
+<th width="246">
+<Text id="1154">Adresse de courrier Ã©lectronique du mainteneur de site Ã  utiliser pour certaines notifications. Si elle est vide, les Ã©vÃ©nements de courrier Ã©lectronique sont dÃ©sactivÃ©s</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1155"><i>MailServer</i></Text>
+</th>
+<th width="151">
+<Text id="1156">vide ou un nom de serveur</Text>
+</th>
+<th width="246">
+<Text id="1157">Serveur de courrier Ã©lectronique sortant pour le site. Si elle est vide, c'est<i>mail.domaine-du-mainteneur</i>qui sera utilisÃ© (si par exemple le mainteneur est<i>aide@exemple.com</i>, la valeur par dÃ©faut sera<i>mail.exemple.com</i>). Si ceci n'aboutit pas Ã  un serveur SMTP valide, les Ã©vÃ©nements de courrier Ã©lectronique ne fonctionneront pas</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1158"><i>status</i></Text>
+</th>
+<th width="151">
+<Text id="1159"><i>enabled</i>(activÃ©e) ou<i>disabled</i>(dÃ©sactivÃ©e)</Text>
+</th>
+<th width="246">
+<Text id="1160">DÃ©termine si la page de<i>Maintenance et administration</i>doit Ãªtre rendue disponible</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1161"><i>collector</i></Text>
+</th>
+<th width="151">
+<Text id="1162"><i>enabled</i>(activÃ©e) ou<i>disabled</i>(dÃ©sactivÃ©e)</Text>
+</th>
+<th width="246">
+<Text id="1163">DÃ©termine si l'outil Â«CollectorÂ» de construction de collection pour l'utilisateur final est disponible</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1164"><i>logcgiargs</i></Text>
+</th>
+<th width="151">
+<Text id="1165"><i>true</i>(vraie) ou<i>false</i>(fausse)</Text>
+</th>
+<th width="246">
+<Text id="1166">Si la valeur est<i>true</i>, , un journal d'utilisation est conservÃ© dans le fichier <i>usage.txt</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1167"><i>usecookies</i></Text>
+</th>
+<th width="151">
+<Text id="1168"><i>true</i>(vraie) ou<i>false</i>(fausse)</Text>
+</th>
+<th width="246">
+<Text id="1169">Si la valeur est<i>true</i>,des informations relatives aux utilisateurs du site sont collectÃ©es (Ã  l'aide de<i>cookies</i>) et consignÃ©es dans le journal<i>usage.txt</i>(ceci ne fonctionne que si l'option<i>logcgiargs</i>a la valeur<i>true</i>)</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1170"><i>LogDateFormat</i></Text>
+</th>
+<th width="151">
+<Text id="1171"><i>LocalTime</i>(heure locale) ou<br/>
+<i>UTCTime</i>(heure du temps universelâGMT) ou<br/>
+<i>Absolute</i>(heure absolue)</Text>
+</th>
+<th width="246">
+<Text id="1172">Format dans lequel consigner les dates et les heures dans les journaux.<i>LocalTime</i>produit le format Â«Thu Dec 07 12:34 NZDT 2000Â»,<i>UTCTime</i>est le mÃªme format mais en temps universel, et<i>absolute</i>est un entier reprÃ©sentant le nombre de secondes Ã©coulÃ©es depuis Â«00:00:00 01/01/1970 GMTÂ»</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1173"><i>LogEvents</i></Text>
+</th>
+<th width="151">
+<Text id="1174"><i>AllEvents</i>(tous les Ã©vÃ©nements) ou<br/>
+<i>CollectorEvents</i>(Ã©vÃ©nements du Collector) ou<br/>
+<i>disabled</i>(dÃ©sactivÃ©e)</Text>
+</th>
+<th width="246">
+<Text id="1175">Consigne certains Ã©vÃ©nements dans le journal<i>events.txt</i>.<i>AllEvents</i>consigne tous les Ã©vÃ©nements de Greenstone,<i>CollectorEvents</i>ne consigne que les Ã©vÃ©nements liÃ©s au Collector, et<i>disabled</i>ne consigne aucun Ã©vÃ©nement</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1176"><i>EmailEvents</i></Text>
+</th>
+<th width="151">
+<Text id="1177"><i>enabled</i>(activÃ©e) ou<i>disabled</i>(dÃ©sactivÃ©e)</Text>
+</th>
+<th width="246">
+<Text id="1178">Envoie un courrier Ã©lectronique au mainteneur (s'il y en a unâvoir l'option maintainer) Ã  chaque fois qu'un Ã©vÃ©nement se produit</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1179"><i>EmailUserEvents</i></Text>
+</th>
+<th width="151">
+<Text id="1180"><i>enabled</i>(activÃ©e) ou<i>disabled</i>(dÃ©sactivÃ©e)</Text>
+</th>
+<th width="246">
+<Text id="1181">Envoie un courrier Ã©lectronique Ã  l'utilisateur lors de certains Ã©vÃ©nementsâtels que la fin de la construction d'une collection par le Collector</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1182"><i>macrofiles</i></Text>
+</th>
+<th width="151">
+<Text id="1183">liste de noms de fichiers de macros</Text>
+</th>
+<th width="246">
+<Text id="1184">DÃ©termine quelles macros sont disponibles pour le logiciel d'interface utilisateur de Greenstone</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+<Subsection id="language_support">
+<Title>
+<Text id="1185">Support des langues</Text>
+</Title>
+<Content>
+<Text id="1186">Le fichier de configuration main.cfg contient deux types d'entrÃ©es qui affectent la gestion des diffÃ©rentes langues. Elles dÃ©terminent quelles langues et quels encodages seront disponibles dans la page de PrÃ©fÃ©rences. Les lignes encoding (encodage) spÃ©cifient les diffÃ©rents types d'encodage de caractÃšres qui peuvent Ãªtre sÃ©lectionnÃ©s. Les lignes language (langue) spÃ©cifient quelles langues on pourra sÃ©lectionner pour l'interface utilisateur (il doit bien sÃ»r exister une macro de langue pour chaque langue possible).</Text>
+<Text id="1187">La ligne encoding peut contenir quatre valeurs possibles: shortname (nom court), longname (nom long), map (correspondance), et multibyte (multi-octets). La valeur shortname est l'Ã©tiquette du jeu de caractÃšres standard, et doit Ãªtre spÃ©cifiÃ©e pour tous les encodages. La valeur longname donne le nom d'encodage spÃ©cifiÃ© sur la page de PrÃ©fÃ©rences. En son absence la valeur par dÃ©faut est celle de shortname. La valeur map est obligatoire pour tous les encodages Ã  l'exception de l'UTF-8, qui est gÃ©rÃ© de maniÃšre interne (et qui devrait toujours Ãªtre activÃ©). La valeur multibyte devrait Ãªtre positionnÃ©e pour tous les jeux de caractÃšres qui nÃ©cessitent plus d'un octet par caractÃšre. Le fichier main.cfg spÃ©cifie de nombreux encodages, dont la plupart sont dÃ©sactivÃ©s car commentÃ©s. Pour activer un encodage, ÃŽtez le caractÃšre de commentaire Â«<i>#</i>Â».</Text>
+<Text id="1188">Chaque ligne language peut contenir trois valeurs possibles: shortname (nom court), longname (nom long), et default_encoding (encodage par dÃ©faut). La valeur shortname est le symbole de langue en deux lettres ISO 639, et elle est obligatoire. La valeur longname donne le nom de la langue spÃ©cifiÃ© sur la page de PrÃ©fÃ©rences. En son absence la valeur par dÃ©faut est celle de shortname. L'option default_encoding sert Ã  spÃ©cifier l'encodage prÃ©fÃ©rÃ© pour cette langue.</Text>
+</Content>
+</Subsection>
+<Subsection id="page_parameters_and_cgi_arguments">
+<Title>
+<Text id="1189">ParamÃštres de page et arguments CGI</Text>
+</Title>
+<Content>
+<Text id="1190">On peut dÃ©finir des paramÃštres de page et des arguments CGI dans le fichier de configuration main.cfg. Rappelez-vous qu'Ã  la figureÂ <CrossRef target="Figure" ref="using_the_cgiargsinfoclass_from_pageactioncpp"/> la plupart des arguments CGI sont dÃ©finis au sein mÃªme du code C++ de la bibliothÃšque. Cependant, il est parfois utile de dÃ©finir de nouveaux arguments ou d'Ã©diter les arguments existants dans les fichiers de configuration, ce qui Ã©vite de recompiler la bibliothÃšque.</Text>
+<Text id="1191">Pour ce faire, vous utiliserez l'option de configuration cgiarg. Elle peut prendre jusqu'Ã  six arguments, qui sont les suivants: shortname (nom court), longname (nom long), multiplechar (caractÃšres multiples), argdefault (argument par dÃ©faut), defaultstatus (Ã©tat par dÃ©faut), et savedarginfo (informations de sauvegarde d'argument). Ces arguments correspondent aux options d'arguments CGI dÃ©crits sectionÂ <CrossRef target="Section" ref="receptionist"/>. Par exemple, dans le fichier main.cfg, par dÃ©faut, l'option de configuration cgiarg sert Ã  positionner les valeurs par dÃ©faut des arguments CGI existants a et p Ã  p et home, respectivement. </Text>
+<Text id="1192">Les paramÃštres de page sont un cas particulier d'arguments CGI qui correspondent aux paramÃštres des fichiers de macros de Greenstone. Par exemple, l'argument CGI l correspond directement au paramÃštre l= dans les fichiers de macros. On utilise l'option de configuration pageparam pour dÃ©finir un argument CGI comme Ã©tant Ã©galement un paramÃštre de page.</Text>
+<Text id="1193">La meilleure maniÃšre d'apprendre les diffÃ©rentes options de configuration possibles dans le fichier de configuration main.cfg est de faire des expÃ©riences avec ce dernier. Souvenez-vous que si vous utilisez la version Â«BibliothÃšque localeÂ» de Greenstone sous Windows, il faut redÃ©marrer le serveur pour que toute modification des fichiers de configuration soit prise en compte.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="site_configuration_file">
+<Title>
+<Text id="1194">Fichier de configuration de site</Text>
+</Title>
+<Content>
+<Table id="lines_in_gsdlsitecfg">
+<Title>
+<Text id="1195">Lignes du fichier<i>gsdlsite.cfg</i></Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="1196"><b>Ligne</b></Text>
+</th>
+<th width="397">
+<Text id="1197"><b>Fonction</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1198"><i>gsdlhome</i></Text>
+</th>
+<th width="397">
+<Text id="1199">Un chemin vers le rÃ©pertoire<i>GSDLHOME</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1200"><i>httpprefix</i></Text>
+</th>
+<th width="397">
+<Text id="1201">L'adresse web de<i>GSDLHOME</i>. Si la racine de documents de votre serveur web a la valeur<i>GSDLHOME</i>vous n'avez pas besoin de cette ligne.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1202"><i>httpimage</i></Text>
+</th>
+<th width="397">
+<Text id="1203">L'adresse web du rÃ©pertoire contenant les images de l'interface utilisateur. Si la racine de documents de votre serveur web a la valeur<i>GSDLHOME</i>ceci vaudra<i>/images</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1204"><i>gwcgi</i></Text>
+</th>
+<th width="397">
+<Text id="1205">L'adresse web du prÃ©sent script CGI (se termine gÃ©nÃ©ralement par<i>library</i>). Ceci n'est pas nÃ©cessaire si votre serveur web positionne la variable d'environnement<i>SCRIPT_NAME</i>(nom de script).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1206"><i>maxrequests</i></Text>
+</th>
+<th width="397">
+<Text id="1207">(Ne s'applique que si l'on utilise<i>fast-cgi</i>.) Nombre de requÃªtes que Fast-CGI doit traiter avant de rendre la main. Lors du dÃ©bogage de la bibliothÃšque il faut positionner ceci Ã  une faible valeur, et Ã  une valeur Ã©levÃ©e dans le cas contraire, en production.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="1208">Le fichier de configuration de site gsdlsite.cfg positionne des variables utilisÃ©es par le logiciel de bibliothÃšque et le serveur web au moment de l'exÃ©cution, et se trouve dans le mÃªme rÃ©pertoire que le programme library. La tableÂ <CrossRef target="Table" ref="lines_in_gsdlsitecfg"/> dÃ©crit les lignes de ce fichier; elles sont expliquÃ©es dans la sectionÂ 5 du Guide d'installation de la bibliothÃšque numÃ©rique Greenstone.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="appendix_a_stl">
+<Title>
+<Text id="1209">A. La bibliothÃšque standard de patrons (templates) pour C++</Text>
+</Title>
+<Content>
+<Text id="1210">La bibliothÃšque standard de patrons (STL) est une bibliothÃšque bibliothÃšque trÃšs rÃ©pandue de code C++, dÃ©veloppÃ©e par Silicon Graphics (www.sgi.com). Cette annexe donne un bref aperÃ§u de ses fonctions principales, utilisÃ©es tout au long du code de Greenstone. Pour une description plus dÃ©taillÃ©e, consultez le manuel de rÃ©fÃ©rence officiel de STL, disponible en ligne sur le site webwww.sgi.com, ou l'un des nombreux manuels traitant de STL, tel que celui de Josuttis (1999).</Text>
+<Text id="1211">Comme le suggÃšre le mot Â«patronÂ», STL n'est pas juste une bibliothÃšque d'objets prÃªts Ã  l'emploi. CouplÃ©e avec le mÃ©canisme de patrons de C++, elle fournit aux programmeurs une solution pour dÃ©velopper leurs propres objets de maniÃšre concise, objets qui tapent dans les fonctionnalitÃ©s algorithmiques embarquÃ©es dans STL. VoilÃ  qui ajoute une couche de complexitÃ©, mais cela en vaut la peine.</Text>
+<Text id="1212">Pour aider Ã  comprendre les extraits de code Greenstone donnÃ©s dans le prÃ©sent manuel, nous donnons quelques exemples de STL Ã  des fins de didacticiel.</Text>
+<Section id="lists">
+<Title>
+<Text id="1213">A..1 Listes</Text>
+</Title>
+<Content>
+<Figure id="programming_a_list_of_integers" class="withLineNumber">
+<Title>
+<Text id="1214">Programmer une liste d'entiers</Text>
+</Title>
+<CodeLine>#include &lt;iostream.h&gt;</CodeLine>
+<CodeLine/>
+<CodeLine>#define nil 0</CodeLine>
+<CodeLine/>
+<CodeLine>struct intlist {</CodeLine>
+<CodeLine>   int val;</CodeLine>
+<CodeLine>   struct intlist* next;</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine/>
+<CodeLine>int total_int_list(intlist* head)</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>   int total = 0;</CodeLine>
+<CodeLine>   intlist* curr = head;</CodeLine>
+<CodeLine>   while (curr!=nil)</CodeLine>
+<CodeLine>   {</CodeLine>
+<CodeLine>       total += curr-&gt;val;</CodeLine>
+<CodeLine>       curr = curr-&gt;next;</CodeLine>
+<CodeLine>   }</CodeLine>
+<CodeLine/>
+<CodeLine>   return total;</CodeLine>
+<CodeLine>}</CodeLine>
+<CodeLine/>
+<CodeLine>void main()</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>   intlist node1 = { 5, nil };</CodeLine>
+<CodeLine>   intlist node2 = { 4, nil };</CodeLine>
+<CodeLine>   node2.next = &amp;node1;</CodeLine>
+<CodeLine/>
+<CodeLine>   int total = total_int_list(&amp;node2);</CodeLine>
+<CodeLine>  cout &lt;&lt; " List items total to: " &lt;&lt; total &lt;&lt; endl;</CodeLine>
+<CodeLine>}</CodeLine>
+</Figure>
+<Text id="1215">Ãtudions tout d'abord deux programmes qui implÃ©mentent une liste d'entiers. L'un utilise des types C++ de base (la Â«bonne vieille maniÃšre de faireÂ»), tandis que l'autre utilise STL. La figureÂ <CrossRef target="Figure" ref="programming_a_list_of_integers"/> montre le code source de l'implÃ©mentation qui n'utilise<i>pas</i>STL. Les lignes 5-8 dÃ©finissent les structures de donnÃ©es de base que nous allons utiliser: le champ val stocke la valeur de l'entier, et next (prochain) pointe vers le prochain Ã©lÃ©ment de la listeÂ --Â une implÃ©mentation classique d'une liste chaÃ®nÃ©e, en somme.</Text>
+<Text id="1216">Pour illustrer l'utilisation de la structure de donnÃ©es, le programme principal (lignes 23-32) initialise une liste d'entiers avec les Ã©lÃ©ments [5, 4]. Il appelle ensuite la fonction total_int_list (total des entiers de la liste, dÃ©finie lignes 10-21), fonction qui prend pour unique argument un pointeur vers la tÃªte d'une liste et qui fait la somme de toutes les valeurs que la liste contient. La valeur renvoyÃ©e (Â«9Â», dans notre cas) est affichÃ©e Ã  l'Ã©cran.</Text>
+<Text id="1217">Le gros du travail est accompli par les lignes 12-18. On commence par un peu d'initialisation: la variable locale total est mise Ã  zÃ©ro, et curr (courant) pointe vers le dÃ©but de la liste. Une boucle while ajoute ensuite l'Ã©lÃ©ment entier courant au sous-total courant (total += curr-&gt;val;) avant de passer au prochain Ã©lÃ©ment (curr = curr-&gt;next;). La boucle while termine quand curr vaut nil (vide), ce qui signifie qu'il ne reste plus aucun Ã©lÃ©ment de la liste Ã  traiter.</Text>
+<Figure id="programming_a_list_of_integers_using_stl">
+<Title>
+<Text id="1218">Programmer une liste d'entiers en utilisant STL</Text>
+</Title>
+<CodeLine>#include &lt;iostream.h&gt;</CodeLine>
+<CodeLine>#include &lt;list&gt;</CodeLine>
+<CodeLine/>
+<CodeLine>int total_int_list(list&lt;int&gt;* head)</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>   int total = 0;</CodeLine>
+<CodeLine>   list&lt;int&gt;::iterator curr = head-&gt;begin();</CodeLine>
+<CodeLine>   while (curr!=head-&gt;end())</CodeLine>
+<CodeLine>   {</CodeLine>
+<CodeLine>       total += *curr;</CodeLine>
+<CodeLine>       curr++;</CodeLine>
+<CodeLine>   }</CodeLine>
+<CodeLine/>
+<CodeLine>   return total;</CodeLine>
+<CodeLine>}</CodeLine>
+<CodeLine/>
+<CodeLine>void main()</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>   list&lt;int&gt; vals;</CodeLine>
+<CodeLine>   vals.push_back(5);</CodeLine>
+<CodeLine>   vals.push_back(4);</CodeLine>
+<CodeLine/>
+<CodeLine>   int total = total_int_list(&amp;vals);</CodeLine>
+<CodeLine>   cout &lt;&lt; " List items total to: " &lt;&lt; total &lt;&lt; endl;</CodeLine>
+<CodeLine>}</CodeLine>
+</Figure>
+<Text id="1219">La figureÂ <CrossRef target="Figure" ref="programming_a_list_of_integers_using_stl"/> montre un programme Ã©quivalent qui utilise STL. Il n'est plus nÃ©cessaire de dÃ©finir une structure de donnÃ©es adÃ©quate dans le code; seule la directive #include &lt;list&gt; de la ligne 2, qui inclut le patron de liste dÃ©fini dans STL, est nÃ©cessaire. L'objet est appelÃ© une Â«classe de contenanceÂ» car lors de la dÃ©claration d'une variable de ce type on spÃ©cifie aussi le type qu'on souhaite qu'elle stocke. On rÃ©alise une liste d'entiers ligne 19 avec l'instruction list&lt;int&gt; vals;. On peut ajouter des Ã©lÃ©ments Ã  l'objet en utilisant la fonction membre push_back(), comme dans les lignes 20-21.</Text>
+<Text id="1220">Le gros du travail est accompli par les lignes 6-12. On commence toujours deux initialisations et une boucle while, mais Ã  part cela la nouvelle syntaxe a fort peu en commun avec l'ancienne. Cette nouvelle maniÃšre de faire les choses gravite autour d'une variable de type iterator (itÃ©rateur, ligne 7). De nombreuses classes STL incluent des types iterator pour fournir une maniÃšre uniforme de traverser une suite d'objets de contenance. Le premier Ã©lÃ©ment est renvoyÃ© avec begin() (dÃ©but) et l'Ã©lÃ©ment qui suit le dernier Ã©lÃ©ment est renvoyÃ© avec end(). On passe Ã  l'Ã©lÃ©ment suivant par l'opÃ©ration d'incrÃ©mentation ++, qui est surchargÃ©e par la classe d'itÃ©ration pour implÃ©menter cette tÃ¢che, et on accÃšde Ã  la valeur stockÃ©e par dÃ©rÃ©fÃ©renciation (*curr, ligne), opÃ©ration elle aussi surchargÃ©e.</Text>
+<Text id="1221">L'implÃ©mentation STL de ce programme est un peu plus concise que le code conventionnel (25 lignes, Ã  comparer aux 31 originales). Les gains sont plus importants dans des projets plus volumineux, car l'objet list (liste) de STL est plus puissant que ce que cet exemple en illustre ici. C'est par exemple une liste doublement chaÃ®nÃ©e qui supporte diverses maniÃšres d'insÃ©rer et d'effacerÂ --Â et il faudrait des efforts de programmation supplÃ©mentaires pour intÃ©grer ces fonctionnalitÃ©s Ã  la version de liste d'entiers classique.</Text>
+<Text id="1222">Remarquez que le paramÃštre total_int_list de la figureÂ <CrossRef target="Figure" ref="programming_a_list_of_integers_using_stl"/> a Ã©tÃ© implÃ©mentÃ© sous la forme d'un entier, pour correspondre au pointeur utilisÃ© dans la variable total_int_list dans la figureÂ <CrossRef target="Figure" ref="programming_a_list_of_integers"/>. En STL, il est souvent plus naturel (et plus souhaitable) d'utiliser des rÃ©fÃ©rences plutÃŽt que des pointeurs. Le paramÃštre devient alors list&lt;int&gt;&amp; head, (tÃªte), et ses fonctions membre sont appelÃ©es par la syntaxe head.begin(); (dÃ©but de tÃªte) et ainsi de suite.</Text>
+</Content>
+</Section>
+<Section id="maps">
+<Title>
+<Text id="1223">A..2 Correspondances</Text>
+</Title>
+<Content>
+<Text id="1224">Lorsque l'on implÃ©mente un systÃšme de bibliothÃšque numÃ©rique, il est utile de pouvoir stocker des Ã©lÃ©ments dans un tableau indicÃ© par des chaÃ®nes de texte plutÃŽt que par des nombres. Dans Greenstone, par exemple, ceci simplifie grandement le stockage des fichiers de macros aprÃšs leur lecture; de mÃªme pour les divers fichiers de configuration. Un type de donnÃ©es qui permet un tel accÃšs s'appelle un<i>tableau associatif</i>, et les langages de programmation modernes de haut niveau en proposent souvent. On l'appelle aussi parfois<i>tableau de hachage</i>(surtout en Perl), puisque la technique habituelle d'implÃ©mentation d'un index de texte est de hacher (calculer une somme de contrÃŽle) les valeurs du tableau associatif.</Text>
+<Figure id="using_associative_arrays_in_stl" class="withLineNumber">
+<Title>
+<Text id="1225">Utiliser des tableaux associatifs en STL</Text>
+</Title>
+<CodeLine>#include &lt;iostream.h&gt;</CodeLine>
+<CodeLine>#include &lt;map&gt;</CodeLine>
+<CodeLine/>
+<CodeLine>int total_int_table(map&lt;char*, int&gt;&amp; table)</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>   int total = 0;</CodeLine>
+<CodeLine>   map&lt;char*, int&gt;::iterator curr = table.begin();</CodeLine>
+<CodeLine>   while (curr!=table.end())</CodeLine>
+<CodeLine>   {</CodeLine>
+<CodeLine>       total += (curr-&gt;second);</CodeLine>
+<CodeLine>       curr++;</CodeLine>
+<CodeLine>   }</CodeLine>
+<CodeLine/>
+<CodeLine>   return total;</CodeLine>
+<CodeLine>}</CodeLine>
+<CodeLine/>
+<CodeLine>int main()</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>   map&lt;char*, int&gt; table;</CodeLine>
+<CodeLine>   table["Alice"] = 31;</CodeLine>
+<CodeLine>   table["Peter"] = 24;</CodeLine>
+<CodeLine>   table["Mary"]   = 47;</CodeLine>
+<CodeLine/>
+<CodeLine>   int total = total_int_table(table);</CodeLine>
+<CodeLine>   cout &lt;&lt; " Age total: " &lt;&lt; total &lt;&lt; endl;</CodeLine>
+<CodeLine>  }</CodeLine>
+</Figure>
+<Text id="1226">En STL, on fait des tableaux associatifs en utilisant l'objet map (carte, ou correspondance). La figureÂ <CrossRef target="Figure" ref="using_associative_arrays_in_stl"/> prÃ©sente un exemple quelque peu artificiel qui stocke l'Ã¢ge de trois personnes (Alice, Pierre, et Marie) dans un tableau associatif indicÃ© par leurs prÃ©noms (lignes 19-22). Le problÃšme est d'Ã©crire une fonction qui calcule l'Ã¢ge total de toutes les personnes prÃ©sentes, sans savoir combien elles sont ni qui elles sont. Bien sÃ»r, on pourrait rÃ©soudre ce problÃšme avec un classique tableau d'entiers indicÃ©s numÃ©riquement. L'exemple est contraint d'illustrer les fonctionnalitÃ©s de l'objet map et de mettre en valeur les similaritÃ©s de traitement avec l'objet list Ã©quipÃ© d'un iterator.</Text>
+<Text id="1227">Tout comme list, map est une classe de contenance. Cependant, lorsque l'on dÃ©clare une variable de ce type, il faut spÃ©cifier deux<FootnoteRef id="6"/>choses: le type d'index, et le type d'Ã©lÃ©ment. Comme on peut le voir ligne 19, on obtient un tableau associatif qui stocke des entiers indicÃ©s par des chaÃ®nes en Ã©crivant char* (c'est la maniÃšre de dÃ©clarer une chaÃ®ne en C++) en tant que type d'indiÃ§age suivi de int en tant que type d'Ã©lÃ©ment.</Text>
+<Text id="1228">Il existe plusieurs maniÃšres de stocker des Ã©lÃ©ments dans le tableau associatif. Dans l'exemple, on utilise lignes 20-22 l'indice de tableau [ ], qui est surchargÃ©, pour initialiser le tableau avec les Ã¢ges des trois personnes. La ressemblance entre total_int_tableÂ --Â qui effectue le calcul principal dans le programmeÂ --Â et total_int_list de la figureÂ <CrossRef target="Figure" ref="programming_a_list_of_integers"/> est frappante. Ces deux objets sont en fait presque identiques, et ce n'est pas une coÃ¯ncidence. STL utilise lourdement l'hÃ©ritage de sorte que des objets diffÃ©rents utilisent encore les mÃªmes opÃ©rations fondamentales. C'est particuliÃšrement le cas des itÃ©rateurs (iterator). Les petites diffÃ©rences entre les deux fonctions sont que l'itÃ©rateur est maintenant tirÃ© de map&lt;char*, int&gt;, et que l'accÃšs Ã  ses Ã©lÃ©ments se fait avec curr-&gt;second()Â --Â en effet la dÃ©rÃ©fÃ©renciation de la variable (*curr) est dÃ©finie comme devant renvoyer un objet de type pair. Ceci enregistre Ã  la fois le nom d'index (first, ou Â«premierÂ») et la valeur de l'Ã©lÃ©ment (second, ou Â«deuxiÃšmeÂ»), mais seul la deuxiÃšme nous intÃ©resse. Ã part cela, le code est identique. La seule diffÃ©rence restanteÂ --Â le changement de l'unique argument de la fonction d'un pointeur vers une rÃ©fÃ©renceÂ --Â est superficielle.</Text>
+<Text id="1229">Greenstone utilise largement deux autres types STL: vector (vecteur), et set (ensemble). Le premier facilite les tableaux dynamiques, et le second supporte les opÃ©rations ensemblistes mathÃ©matiques telles que l'union, l'intersection, et la diffÃ©rence ensembliste.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="bibliography">
+<Title>
+<Text id="1230">Bibliographie</Text>
+</Title>
+<Content>
+<Text id="1231">Aulds, C. (2000) Linux Apache Web Server Administration. Sybex.</Text>
+<Text id="1232">Bainbridge, D., Buchanan, G., McPherson, J., Jones, S., Mahoui, A. and Witten, I.H. (2001) Â«Greenstone: A platform for distributed digital library developmentÂ». Rapport de recherche, dÃ©partement d'informatique, universitÃ© de Waikato, Nouvelle-ZÃ©lande.</Text>
+<Text id="1233">Christiansen, T. Torkington, N. and Wall, L. (1998) Perl en action. Ãditions O'Reilly.</Text>
+<Text id="1234">Coar, K.A.L. (1998) Apache Server For Dummies. IDG Books.</Text>
+<Text id="1235">Deitel, H.M. and Deitel, P.J. (1994) C++: How to Program. Prentice Hall, Englewood Cliffs, New Jersey.</Text>
+<Text id="1236">Dublin Core (2001) Â«The Dublin Core Metadata InitiativeÂ» at http://purl.org/dc/, le 16 janvier 2001.</Text>
+<Text id="1237">Josuttis, N.M. (1999) The C++ standard library: a tutorial and reference. Addison-Wesley, 1999.</Text>
+<Text id="1238">Keller, M. and Holden, G. (1999) Apache Server for Windows Little Black Book. Coriolis Group.</Text>
+<Text id="1239">Schwartz, R.L. and Christiansen, T. (1997) Introduction Ã  Perl (2Ãšme Ã©dition). Ãditions O'Reilly.</Text>
+<Text id="1240">Slama, D., Garbis, J. and Russell, P. (1999) Enterprise CORBA. Prentice Hall, Englewood Cliffs, New Jersey.</Text>
+<Text id="1241">Stroustrup, B. (1997) The C++ Programming Language. Addison-Wesley.</Text>
+<Text id="1242">Thiele, H. (1997) Â«The Dublin Core and Warwick Framework: A Review of the Literature, March 1995-September 1997Â»<i>D-Lib Magazine</i>, janvier.&lt;http://www.dlib.org/dlib/january98/01thiele.html&gt;</Text>
+<Text id="1243">Wall, L., Christiansen, T. and Orwant, J. (2000) Programmation en Perl (3Ãšme Ã©dition). Ãditions O'Reilly.</Text>
+<Text id="1244">Weibel, S. (1999) Â«The State of the Dublin Core Metadata InitiativeÂ» <i>D-Lib Magazine</i>, Volume 5 Number 4; avril.&lt;http://www.dlib.org/dlib/april99/04weibel.html&gt;</Text>
+<Text id="1245">Witten, I.H., Moffat, A. and Bell, T.C. (1999) Managing gigabytes: compressing and indexing documents and images. Morgan Kaufmann, San Francisco.</Text>
+</Content>
+</Chapter>
+<FootnoteList>
+<Footnote id="1">
+<Text id="1246">... Greenstone Sur des systÃšmes Windows 95/98, l'exÃ©cution de setup.bat peut Ã©chouer avec le message d'erreur Hors de l'espace d'environnement. Dans ce cas, Ã©ditez le fichier config.sys de votre systÃšme (qui se trouve habituellement sous Cconfig.sys) et ajoutez-y la ligne shell=C:command.com /e:4096 /p (oÃ¹ C reprÃ©sente la lettre de votre lecteur systÃšme) pour agrandir la taille de la table d'environnement. Il vous faudra redÃ©marrer l'ordinateur pour que cette modification soit prise en compte. RÃ©pÃ©tez ensuite les Ã©tapes effectuÃ©es avant l'obtention de ce message d'erreur.</Text>
+</Footnote>
+<Footnote id="2">
+<Text id="1247">... Gutenberg N.D.T.: projet de numÃ©risation de la littÃ©rature classique en langue anglaise libre de droits, disponible sur le web.</Text>
+</Footnote>
+<Footnote id="3">
+<Text id="1248">...nuggetÂ» Attention: dans Greenstone, les expressions rationnelles sont interprÃ©tÃ©es dans le langage Perl, et les conventions diffÃšrent subtilement d'autres conventions. Par exemple, Â«*Â» correspond Ã  zÃ©ro ou plusieurs occurrences du caractÃšre qui prÃ©cÃšde, et Â«.Â» remplace n'importe quel caractÃšreÂ --Â donc Â«nugget.*Â» correspond Ã  toute chaÃ®ne commenÃ§ant par Â«nuggetÂ», que ce prÃ©fixe soit suivi d'un point ou non. Pour imposer un point Ã  cette position il faudrait Ã©chapper le point, et Ã©crire Â«nugget..*Â» Ã  la place.</Text>
+</Footnote>
+<Footnote id="4">
+<Text id="1249">... collection Remarquez que les versions les plus rÃ©centes de la collection Â«DemoÂ» utilisent un classificateur Hierarchy pour reprÃ©senter les mÃ©ta-donnÃ©es how to (comment faire). Dans de tels cas de figure, elles apparaÃ®tront un peu diffÃ©remment que dans la figureÂ <CrossRef target="Figure" ref="list_classifier"/>.</Text>
+</Footnote>
+<Footnote id="5">
+<Text id="1250">... facilement La valeur gsdlhome provient du fichier gsdlsite.cfg situÃ© dans le mÃªme rÃ©pertoire que l'exÃ©cutable CGI library, alors que GSDLHOME est positionnÃ© en exÃ©cutant le script setup qui accÃšde Ã  un fichier diffÃ©rent; il est donc techniquement possible que les deux valeurs soient diffÃ©rentes. C'est possible, mais pas dÃ©sirable, et le texte ci-dessus est Ã©crit dans l'hypothÃšse oÃ¹ ces deux valeurs sont Ã©gales.</Text>
+</Footnote>
+</FootnoteList>
+</Manual>
Index: /tags/start/gsdl-documentation/manuals/xml-source/fr/Install_fr.xml
===================================================================
--- /tags/start/gsdl-documentation/manuals/xml-source/fr/Install_fr.xml	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/xml-source/fr/Install_fr.xml	(revision 13666)
@@ -0,0 +1,1007 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Manual>
+<Heading>
+<Text id="1">GREENSTONE DIGITAL LIBRARY</Text><Updated date="14-Dec-2006 by lh92"/>
+</Heading>
+<Title>
+<Text id="2">Guide d'installation de la bibliothÃšque numÃ©rique Greenstone</Text>
+</Title>
+<Author>
+<Text id="3">Ian H. Witten et Stefan Boddie</Text>
+</Author>
+<Affiliation>
+<Text id="4">DÃ©partement d'informatique,<br/>UniversitÃ© de Waikato, Nouvelle-ZÃ©lande</Text>
+</Affiliation>
+<Text id="5">Greenstone est une suite logicielle destinÃ©e Ã  la construction et Ã  la distribution de collections de bibliothÃšques numÃ©riques. Cette suite fournit une nouvelle maniÃšre d'organiser l'information et de la publier sur l'Internet ou sur un cÃ©dÃ©rom. Greenstone est produit par le projet de bibliothÃšque numÃ©rique de Nouvelle-ZÃ©lande (dÃ©pendant de l'universitÃ© de Waikato), et distribuÃ© en coopÃ©ration avec l'UNESCO et le projet de bibliothÃšques pour l'humanitÃ©. C'est un logiciel Open Source, qu'on peut obtenir Ã  l'URLhttp://greenstone.org, et qui est diffusÃ© selon les termes de la licence publique gÃ©nÃ©rale de GNU.</Text>
+<Comment>
+<Text id="6">Nous souhaitons nous assurer que ce logiciel fonctionne bien pour vous.<br/>Faites-nous part, en anglais, de tout problÃšme Ã  l'adresse Ã©lectronique<br/>.</Text>
+</Comment>
+<Version>
+<Text id="7">Greenstone gsdl-2.50</Text>
+</Version>
+<Date>
+<Text id="8">Mars 2004</Text>
+</Date>
+<Section id="about_this_manual">
+<Title>
+<Text id="9">Ã propos de ce manuel</Text>
+</Title>
+<Content>
+<Text id="10">Ce document explique comment installer Greenstone pour pouvoir l'utiliser sur votre ordinateur. Il explique aussi comment obtenir les logiciels associÃ©s, qui sont librement disponibles: le serveur web Apache et Perl. Nous avons fait au mieux pour simplifier au maximum la procÃ©dure d'installation.</Text>
+<Text id="11">Ce logiciel fonctionne sur diffÃ©rentes plates-formes et diffÃ©rentes configurations. Par consÃ©quent, de nombreux dÃ©tails pourront impacter la procÃ©dure d'installation. La sectionÂ <CrossRef target="Chapter" ref="versions_of_greenstone"/> liste des questions qu'il faudra se poser avant d'installer Greenstone. La sectionÂ <CrossRef target="Chapter" ref="installation_procedure"/> dÃ©taille la procÃ©dure d'installation pour les diffÃ©rentes versions; ne lisez que la portion relative Ã  votre systÃšme d'exploitation. La sectionÂ <CrossRef target="Chapter" ref="greenstone_collections"/> dÃ©crit les collections de bibliothÃšques numÃ©riques de dÃ©monstration comprises dans la distribution. La sectionÂ <CrossRef target="Chapter" ref="setting_up_webserver"/> explique comment configurer des serveurs web communs, Apache et PWS/IIS de Microsoft, de maniÃšre Ã  les faire fonctionner avec Greenstone. La sectionÂ <CrossRef target="Chapter" ref="configuring_your_site"/> dÃ©crit plusieurs options de configuration de Greenstone, et la sectionÂ <CrossRef target="Chapter" ref="personalizing"/> montre comment crÃ©er une page d'accueil personnalisÃ©e pour votre installation de bibliothÃšque numÃ©rique. Enfin, une annexe <CrossRef target="Chapter" ref="appendix_associated_software"/> liste des logiciels associÃ©s et donne pour chacun la maniÃšre de l'obtenir.</Text>
+</Content>
+</Section>
+<Section id="companion_documents">
+<Title>
+<Text id="12">Documents d'accompagnement</Text>
+</Title>
+<Content>
+<Text id="13">L'ensemble des documents de Greenstone comprend cinq volumes:</Text>
+<BulletList>
+<Bullet>
+<Text id="14">Guide d'installation de la bibliothÃšque numÃ©rique Greenstone (<i>ce document-ci</i>)</Text>
+</Bullet>
+<Bullet>
+<Text id="15">Guide de l'utilisateur de la bibliothÃšque numÃ©rique Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="16">Guide du dÃ©veloppeur de la bibliothÃšque numÃ©rique Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="17">BibliothÃšque numÃ©rique Greenstone: du papier Ã  la collection</Text>
+</Bullet>
+<Bullet>
+<Text id="18">BibliothÃšque numÃ©rique Greenstone: Utilisation de "L'organizer"</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Section>
+<Section id="acknowledgements">
+<Title>
+<Text id="19">Remerciements</Text>
+</Title>
+<Content>
+<Text id="20">Le logiciel Greenstone a vu le jour grÃ¢ce Ã  un effort de collaboration entre de nombreuses personnes. Rodger McNab et Stefan Boddie en sont les principaux architectes et dÃ©veloppeurs. Des contributions ont Ã©tÃ© faites par David Bainbridge, George Buchanan, Hong Chen, Michael Dewsnip, Katherine Don, Elke Duncker, Carl Gutwin, Geoff Holmes, Dana McKay, John McPherson, Craig Nevill-Manning, Dynal Patel, Gordon Paynter, Bernhard Pfahringer, Todd Reed, Bill Rogers, John Thompson, et Stuart Yeates. D'autres membres du Projet de bibliothÃšque numÃ©rique de Nouvelle-ZÃ©lande ont Ã©galement donnÃ© des conseils et inspirÃ© les concepteurs du systÃšme: Mark Apperley, Sally Jo Cunningham, Steve Jones, Te Taka Keegan, Michel Loots, Malika Mahoui, et Lloyd Smith. Nous remercions aussi tous ceux qui ont contribuÃ© au dÃ©veloppement des modules sous licence GNU GPL qui font partie de cette distribution: MG, GDBM, PDFTOHTML, PERL, WGET, WVWARE, XLHTML.</Text>
+</Content>
+</Section>
+<Chapter id="versions_of_greenstone">
+<Title>
+<Text id="21">Les versions de Greenstone</Text>
+</Title>
+<Content>
+<Text id="22">Greenstone fonctionne sur diffÃ©rentes plates-formes et configurations, comme rÃ©sumÃ© figureÂ <CrossRef target="Figure" ref="different_options"/>.</Text>
+<Figure id="different_options">
+<Title>
+<Text id="23"><b>Figure:</b>Les options disponibles pour Windows et Unix de Greenstone</Text>
+</Title>
+<File width="542" height="264" url="images/Install_Fig_1.png"/>
+</Figure>
+<Text id="24">La procÃ©dure d'installation dÃ©pend de nombreux paramÃštres. Avant de continuer la lecture, posez-vous les questions suivantes:</Text>
+<BulletList>
+<Bullet>
+<Text id="25">Utilisez-vous Windows ou Unix?</Text>
+</Bullet>
+<Bullet>
+<Text id="26">Si vous utilisez Windows, utilisez-vous 3.1/3.11 ou bien une version plus rÃ©cente? Bien qu'il soit possible de visualiser des collections et de servir d'autres ordinateurs sur le mÃªme rÃ©seau avec des machines pourvues de Windows 3.1/3.11, il n'est pas possible d'y construire de nouvelles collections. La version complÃšte de Greenstone fonctionne sur Windows 95/98/Me, et sur NT/2000.</Text>
+</Bullet>
+<Bullet>
+<Text id="27">Si vous utilisez Unix, s'agit-il de Linux ou d'une autre version d'Unix? Dans le cas de Linux, une version binaire du systÃšme complet, facile Ã  installer, est fournie. Pour d'autres Unix il vous faudra installer le code source et le compiler, ce qui pourra nÃ©cessiter l'installation d'autres logiciels.</Text>
+</Bullet>
+<Bullet>
+<Text id="28">Dans le cas des systÃšmes Windows NT/2000 ou Unix, pouvez-vous vous connecter en tant qu'Â«administrateurÂ» ou Â«rootÂ»? Ceci est parfois nÃ©cessaire pour configurer un serveur web de maniÃšre adÃ©quate pour qu'il puisse fonctionner avec Greenstone.</Text>
+</Bullet>
+<Bullet>
+<Text id="29">Souhaitez-vous disposer du code source? Si vous utilisez Windows ou Linux, vous pouvez vous contenter d'installer des binaires. Mais si vous souhaitez Ã©galement disposer du code source, il est dans la distribution de Greenstone.</Text>
+</Bullet>
+<Bullet>
+<Text id="30">Souhaitez-vous construire de nouvelles collections de bibliothÃšques numÃ©riques? Si tel est le cas, il vous faudra disposer de Perl, qui est librement disponible pour Windows comme pour Unix.</Text>
+</Bullet>
+<Bullet>
+<Text id="31">Votre ordinateur comprend-il un serveur web? Greenstone est fourni avec un serveur web pour Windows. Cependant, si vous disposez dÃ©jÃ  d'un serveur web, vous pouvez souhaitez continuer Ã  l'employer. Dans le cas des systÃšmes Unix, il vous faudra utiliser un serveur web.</Text>
+</Bullet>
+<Bullet>
+<Text id="32">Savez-vous comment configurer votre serveur web? Si vous n'utilisez pas le serveur web fourni avec Greenstone, il vous faudra lÃ©gÃšrement modifier la configuration de votre serveur web pour qu'il puisse reconnaÃ®tre Greenstone.</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Chapter>
+<Chapter id="installation_procedure">
+<Title>
+<Text id="33">La procÃ©dure d'installation</Text>
+</Title>
+<Content>
+<Text id="34">Il existe des versions Windows et Unix de Greenstone, sous formes binaire comme de code source. L'interface utilisateur de Greenstone utilise un navigateur web: Netscape Navigator ou Internet Explorer conviennent tous deux, Ã  partir de leurs versions 4.0. Si vous ne disposez pas de navigateur web, le cÃ©dÃ©rom comprend les versions Windows de Netscape.</Text>
+<Section id="windows">
+<Title>
+<Text id="35">Windows</Text>
+</Title>
+<Content>
+<Text id="36">Si c'est Unix que vous employez, rendez-vous directement Ã  la sectionÂ 2.2. Les utilisateurs de Windows qui se contenteront d'une installation simple et immÃ©diate iront lire quant Ã  eux la procÃ©dure d'installation simplifiÃ©e, sectionÂ 2.1.1. Greenstone occupe environ 40 mÃ©ga-octets d'espace disque.</Text>
+<Text id="37">Si vous souhaitez vous Ã©carter un tant soit peu de la configuration par dÃ©faut, il vous faudra dÃ©cider d'installer le binaire ou le code source. En cas de doute, optez pour le binaire. La procÃ©dure d'installation est la mÃªme dans les deux cas, et les sections suivantes dÃ©taillent les options disponibles.</Text>
+<Text id="38">Ã la fin de l'installation, sautez Ã  la sectionÂ 3.</Text>
+<Subsection id="simple_installation">
+<Title>
+<Text id="39">Installation simplifiÃ©e</Text>
+</Title>
+<Content>
+<Text id="40">Pour installer la version Windows Ã  partir du cÃ©dÃ©rom, insÃ©rez le disque dans le lecteur (par exemple, sous D). Si aprÃšs environ 20 secondes d'attente la procÃ©dure d'installation n'a toujours pas automatiquement dÃ©marrÃ©, cliquez sur le menu DÃ©marrer, choisissez ExÃ©cuter et tapez DWindowsSetup.exe, oÃ¹ Â«DÂ» reprÃ©sente la lettre identifiant votre lecteur de cÃ©dÃ©rom. Les utilisateurs de Windows 3.1 choisiront ExÃ©cuter Ã  partir du Gestionnaire de fichiers et taperont, eux aussi, DWindowsSetup.exe.</Text>
+<Text id="41">Pour que l'installation se dÃ©roule le plus simplement possible, contentez-vous d'accepter les choix par dÃ©faut Ã  chaque Ã©tape en cliquant sur le bouton Suivant. C'est tout! Greenstone est installÃ© dans CProgram Filesgsdl.</Text>
+<Text id="42">Ã la fin de l'installation, vous dÃ©marrerez Greenstone en cliquant sur le bouton DÃ©marrer, ouvrirez le menu Programmes, et sÃ©lectionnerez BibliothÃšque NumÃ©rique Greenstone (Greenstone Digital Library). Ceci invoquera une boÃ®te de dialogue; cliquez simplement sur Entrer dans la bibliothÃšque. VoilÃ  qui dÃ©marrera automatiquement votre navigateur web et chargera la page d'accueil de la bibliothÃšque numÃ©rique Greenstone, qui devrait ressembler Ã  la figureÂ <CrossRef target="Figure" ref="your_greenstone_home_page"/>. Vous pourrez alors entrer dans la collection de dÃ©monstration de Greenstone en cliquant sur son icone.</Text>
+<Figure id="your_greenstone_home_page">
+<Title>
+<Text id="43">La page d'accueil de Greenstone</Text>
+</Title>
+<File width="395" height="327" url="images/Install_Fig_2.png"/>
+</Figure>
+</Content>
+</Subsection>
+<Subsection id="windows_binaries">
+<Title>
+<Text id="44">Binaires pour Windows</Text>
+</Title>
+<Content>
+<Text id="45">Le cÃ©dÃ©rom comprend deux binaires distincts pour Windows: la BibliothÃšque locale et la BibliothÃšque Web. L'installation par dÃ©faut dÃ©crite ci-dessus sÃ©lectionne la version Â«BibliothÃšque localeÂ», que nous vous recommandons chaudement d'utiliser. La Â«BibliothÃšque WebÂ», qui est bien plus difficile Ã  utiliser, n'est nÃ©cessaire que si vous employez dÃ©jÃ  un serveur web et rencontrez des conflits d'affectation de numÃ©ro de port en utilisant la Â«BibliothÃšque localeÂ». MalgrÃ© une appellation modeste, cette derniÃšre fournit un service web complet et autonome.</Text>
+<Text id="46">BibliothÃšque locale. Ceci permet Ã  tout ordinateur Ã©quipÃ© de Windows de servir des collections Greenstone dÃ©jÃ  construites. La collection Greenstone Â«DemoÂ» sera installÃ©e automatiquement; vous pourrez Ã©galement installer les autres collections prÃ©sentes sur le cÃ©dÃ©rom (voyez ceci en <CrossRef target="Chapter" ref="greenstone_collections"/>). Le logiciel de bibliothÃšque locale est le mÃªme que celui qui est prÃ©sent sur les cÃ©dÃ©roms produits par le systÃšme Greenstone.</Text>
+<Text id="47">La bibliothÃšque locale est destinÃ©e aux ordinateurs isolÃ©s, ou aux ordinateurs non Ã©quipÃ©s de serveur web. Elle contient un petit serveur web pour que les autres ordinateurs du mÃªme rÃ©seau puissent Ã©galement accÃ©der Ã  la bibliothÃšque (mais ce serveur web n'est pas trÃšs configurable).</Text>
+<Text id="48">Le logiciel de bibliothÃšque locale dÃ©tecte automatiquement si l'ordinateur dispose de logiciels de communication en rÃ©seau ou s'il est connectÃ© Ã  un rÃ©seau. Il fonctionnera correctement dans toutes les combinaisons possibles, mais on pourra nÃ©anmoins rencontrer deux problÃšmes. Il se peut que Greenstone:</Text>
+<BulletList>
+<Bullet>
+<Text id="49">provoque une connexion tÃ©lÃ©phonique non dÃ©sirÃ©e;</Text>
+</Bullet>
+<Bullet>
+<Text id="50">ou Ã©choue Ã  cause de la prÃ©sence de logiciels de communication en rÃ©seau mal installÃ©s.</Text>
+</Bullet>
+</BulletList>
+<Text id="51">C'est pour de telles situations qu'une version restreinte de la bibliothÃšque locale est fournie, version qui ne fonctionne qu'avec Netscape (et pas Internet Explorer). Lors de l'invocation de la version Â«BibliothÃšque localeÂ» de Greenstone, la boÃ®te de dialogue qui apparaÃ®t propose un bouton pour sÃ©lectionner cette version restreinte. Ã moins que les problÃšmes mentionnÃ©s ci-dessus ne se posent, prÃ©fÃ©rez-lui toujours la version standard.</Text>
+<Text id="52">BibliothÃšque Web. Ceci permet Ã  tout ordinateur disposant d'un serveur web de servir des collections Greenstone dÃ©jÃ  construites. Comme dans le cas de la bibliothÃšque locale mentionnÃ© ci-dessus, la collection Greenstone Â«DemoÂ» sera installÃ©e automatiquement. Vous pourrez Ã©galement installer les autres collections prÃ©sentes sur le cÃ©dÃ©rom (voyez ceci en sectionÂ <CrossRef target="Chapter" ref="greenstone_collections"/>).</Text>
+<Text id="53">La bibliothÃšque web diffÃšre de la bibliothÃšque locale en ce sens qu'elle est destinÃ©e aux ordinateurs qui disposent dÃ©jÃ  d'un serveur web.</Text>
+<Text id="54">Pour utiliser la bibliothÃšque web, vous aurez aussi besoin</Text>
+<BulletList>
+<Bullet>
+<Text id="55">d'un logiciel serveur web, comme Apache par exemple (voyez l'annexe <CrossRef target="Chapter" ref="appendix_associated_software"/> Ã  ce sujet).</Text>
+</Bullet>
+<Bullet>
+<Text id="56">Le Collector. Ce composant, inclus Ã  la fois dans la bibliothÃšque locale et dans la bibliothÃšque web, vous permet de construire des collections autour de contenus de votre choix. Pour l'utiliser, vous aurez aussi besoin de Perl. Nous recommandons ActivePerl (voyez l'annexe <CrossRef target="Chapter" ref="appendix_associated_software"/> Ã  ce sujet).</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Subsection>
+<Subsection id="">
+<Title>
+<Text id="57">Configuration de serveur web pour Windows (ne concerne que la bibliothÃšque web)</Text>
+</Title>
+<Content>
+<Text id="58">La version de Greenstone en bibliothÃšque locale a cet avantage qu'elle fonctionne directement, sans nÃ©cessiter de configuration particuliÃšre. Dans le cas de la version en bibliothÃšque web, il vous faudra en revanche apporter quelques modifications aux rÃ©glages de votre serveur web.</Text>
+<Text id="59">Si vous disposez dÃ©jÃ  d'un serveur web, il faudra apporter quelques modifications Ã  sa configuration pour pouvoir utiliser votre installation de Greenstone. Le script d'installation dÃ©taille ces modifications dans le cas du serveur web ApacheÂ --Â voyez la sectionÂ <CrossRef target="Section" ref="pws_and_iis_webservers"/> pour obtenir des instructions relatives Ã  la configuration des serveurs web PWS et IIS. Vous aurez peut-Ãªtre besoin d'un administrateur systÃšme pour reconfigurer un serveur web dÃ©jÃ  installÃ©Â --Â votre administrateur systÃšme devrait comprendre les instructions fournies par le script d'installation.</Text>
+<Text id="60">Si vous ne disposez pas dÃ©jÃ  d'un serveur web, il vous faudra en installer un (voyez l'annexe <CrossRef target="Chapter" ref="appendix_associated_software"/> pour obtenir des informations sur le serveur Apache). Il vous faudra ensuite le configurer de maniÃšre appropriÃ©e. La sectionÂ <CrossRef target="Chapter" ref="setting_up_webserver"/> dÃ©taille les portions de l'installation d'un serveur web qui concernent Greenstone, et comment il faut les modifier. Tout revient Ã  ajouter une petite dizaine de lignes Ã  un fichier de configuration.</Text>
+</Content>
+</Subsection>
+<Subsection id="windows_source">
+<Title>
+<Text id="61">Code source pour Windows</Text>
+</Title>
+<Content>
+<Text id="62">Le code source de Greenstone occupe 50 mÃ©ga-octets d'espace disque, mais 90 mÃ©ga-octets seront nÃ©cessaires pour procÃ©der Ã  la compilation. Pour compiler ce code source sur Windows vous devrez Ã©galement disposer</Text>
+<BulletList>
+<Bullet>
+<Text id="63">du compilateur Microsoft Visual C++ (nous travaillons actuellement sur l'aplanissement de petits problÃšmes posÃ©s par la compilation de Greenstone avec diverses versions de GCC pour Windows).</Text>
+</Bullet>
+</BulletList>
+<Text id="64">(Vous n'aurez pas besoin de GDBM, le gestionnaire de bases de donnÃ©es de GNU, car il est inclus dans la distribution de Greenstone).</Text>
+<Text id="65">Il est peu probable que vous parveniez Ã  compiler Greenstone sur une machine fonctionnant sous un systÃšme Windows 3.1/3.11.</Text>
+<Text id="66">Au cas oÃ¹ vous recompilez Greenstone et souhaitez utiliser la version recompilÃ©e pour crÃ©er des cÃ©dÃ©roms, sachez que le code produit par les versions rÃ©centes du compilateur Microsoft Visual C++ ne fonctionne pas sous les systÃšmes Windows 3.1/3.11, mais fonctionne sans problÃšmes sous des systÃšmes ultÃ©rieurs (95, 98, Me, NT, 2000). Si vous souhaitez que vos cÃ©dÃ©roms puissent Ãªtre utilisÃ©s sur des versions anciennes de Windows, il vous faudra utiliser une autre version du compilateur. De plus, Greenstone utilise STL, la bibliothÃšque standard de patrons (templates) pour C++, et mÃªme si d'anciens compilateurs sont parfois fournis avec STL, la version fournie ne fonctionne pas toujours trÃšs bien. C'est pourquoi, pour recompiler Greenstone de telle sorte qu'il produise des cÃ©dÃ©roms qui fonctionneront sur d'anciennes versions de Windows, vous aurez besoin</Text>
+<BulletList>
+<Bullet>
+<Text id="67">du compilateur Microsoft Visual C++, version 4.0 ou 4.2.</Text>
+</Bullet>
+<Bullet>
+<Text id="68">d'une version externe de STL, la bibliothÃšque standard de patrons pour C++. STL est empaquetÃ©e avec Greenstone afin d'Ãªtre utilisÃ©e avec ces versions du compilateur.</Text>
+</Bullet>
+</BulletList>
+<Text id="69">Vous remarquerez que la procÃ©dure d'installation pour Windows ne tente pas de compiler Greenstone si vous choisissez d'installer le code source. Pour obtenir des instructions de compilation de Greenstone propres Ã  votre plate-forme et Ã  votre compilateur, voyez le fichier Install, placÃ© dans le rÃ©pertoire principal de Greenstone (CProgram Filesgsdl par dÃ©faut) pendant la procÃ©dure d'installation.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="unix">
+<Title>
+<Text id="70">Unix</Text>
+</Title>
+<Content>
+<Text id="71">La prÃ©sente section s'adresse aux utilisateurs d'Unix; les utilisateurs de Windows auront avantage Ã  consulter la sectionÂ <CrossRef target="Section" ref="how_to_find_greenstone"/>. Il vous faut choisir d'installer le binaire ou le code source: le binaire occupe 50 mÃ©ga-octets d'espace disque, et le code source a besoin de 160 mÃ©ga-octets pour compiler.</Text>
+<Subsection id="unix_binaries">
+<Title>
+<Text id="72">Binaires Unix</Text>
+</Title>
+<Content>
+<Text id="73">Le binaire est prÃ©vu pour une distribution Linux pour puce Intel de type x86, avec support pour les binaires ELF. Voici des exemples de distributions qui remplissent ces conditions:</Text>
+<BulletList>
+<Bullet>
+<Text id="74">RedHat 5.1</Text>
+</Bullet>
+<Bullet>
+<Text id="75">SuSE Linux 6.1</Text>
+</Bullet>
+<Bullet>
+<Text id="76">Debian 2.1</Text>
+</Bullet>
+<Bullet>
+<Text id="77">Slackware 4.0</Text>
+</Bullet>
+</BulletList>
+<Text id="78">Cela devrait Ã©galement Ãªtre le cas de versions plus rÃ©centes de ces distributions.</Text>
+<Text id="79">Il vous faudra un serveur web: nous recommandons Apache. Nous recommandons aussi trÃšs chaudement d'installer le serveur web avant d'installer GreenstoneÂ --Â ceci facilitera grandement la rÃ©ponse aux questions posÃ©es pendant la procÃ©dure d'installation de Greenstone. Si vous souhaitez construire de nouvelles collections de bibliothÃšques numÃ©riques, il vous faudra Ã©galement installer Perl, s'il est absent de votre systÃšme. Pour savoir si Perl est installÃ©, invoquez un terminal, tapez perl -v, et voyez si le message qui apparaÃ®t prÃ©cise, entre autres choses, un numÃ©ro de version. Perl est installÃ© par dÃ©faut dans la plupart des versions de Linux. L'annexe <CrossRef target="Chapter" ref="appendix_associated_software"/> donne des prÃ©cisions sur la maniÃšre d'obtenir Apache et Perl.</Text>
+</Content>
+</Subsection>
+<Subsection id="unix_source">
+<Title>
+<Text id="80">Code source Unix</Text>
+</Title>
+<Content>
+<Text id="81">Le code source est le mÃªme pour Windows et pour Unix. Il a Ã©tÃ© compilÃ© et testÃ© sous les systÃšmes Linux, Solaris, et Macintosh OS/X; cela devrait Ãªtre immÃ©diat de le porter vers d'autres Unix.</Text>
+<Text id="82">Pour compiler le code source de Greenstone sous Unix, il vous faut:</Text>
+<BulletList>
+<Bullet>
+<Text id="83">GCC, le compilateur C++ de GNU;</Text>
+</Bullet>
+<Bullet>
+<Text id="84">GDBM, le gestionnaire de bases de donnÃ©es de GNU.</Text>
+</Bullet>
+</BulletList>
+<Text id="85">Pour faire fonctionner Greenstone, il vous faudra Ã©galement un serveur web et le langage Perl, tel qu'expliquÃ© ci-dessus dans la sectionÂ 2.2.1.</Text>
+</Content>
+</Subsection>
+<Subsection id="unix_installation">
+<Title>
+<Text id="86">Installation sous Unix</Text>
+</Title>
+<Content>
+<Text id="87">Pour installer la version d'Unix du CD-ROM, insÃ©rer le disque dans la commande, et dactylographier</Text>
+<Table class="hidden" id="table_commands">
+<Title/>
+<TableContent>
+<tr>
+<th width="151">
+<CodeLine>mount /cdrom</CodeLine>
+</th>
+<th width="246">
+<Text id="88">monte le pÃ©riphÃ©rique de cÃ©dÃ©roms (cette commande peut changer d'un systÃšme Ã  l'autre; sous OS/X, par exemple, il suffit de se rendre, par la commande cd, dans le rÃ©pertoire /Volumes et de se rendre ensuite dans le sous-rÃ©pertoire appropriÃ© pour le cÃ©dÃ©rom)</Text>
+</th>
+</tr>
+<tr>
+<th width="151">
+<CodeLine>cd /cdrom</CodeLine>
+</th>
+<th width="246">
+<Text id="89">se dÃ©place dans le rÃ©pertoire principal du cÃ©dÃ©rom</Text>
+</th>
+</tr>
+<tr>
+<th width="151">
+<CodeLine>cd Unix</CodeLine>
+</th>
+<th width="246">
+<Text id="90">se dÃ©place dans le rÃ©pertoire abritant le script d'installation pour Unix</Text>
+</th>
+</tr>
+<tr>
+<th width="151">
+<CodeLine>sh Install.sh</CodeLine>
+</th>
+<th width="246">
+<Text id="91">exÃ©cute le processus d'installation (nous prÃ©cisons explicitement le nom de l'interprÃ©teurÂ --Â shÂ --Â car de nombreuses installations interdisent l'exÃ©cution de programmes directement depuis le cÃ©dÃ©rom)</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="92">Cette derniÃšre commande entame un dialogue interactif dont le but est d'obtenir de vous les informations nÃ©cessaires Ã  l'installation de Greenstone sur votre systÃšme, et qui vous donne des informations dÃ©taillÃ©es sur les rÃ©sultats des opÃ©rations effectuÃ©es.</Text>
+<Text id="93">La procÃ©dure d'installation commence par vous demander dans quel rÃ©pertoire installer Greenstone. Le premier fichier qui y sera placÃ© sera Â«uninstallÂ», programme qui nettoiera toute installation partielle, au cas oÃ¹ vous rencontreriez des problÃšmes ou mettriez fin prÃ©maturÃ©ment Ã  la procÃ©dure d'installation. Vous choisirez ensuite si vous souhaitez installer les binaires ou le code source, puis viennent des questions relatives Ã  la configuration de votre serveur web. Vous devez disposer d'un rÃ©pertoire oÃ¹ stocker des scripts CGI exÃ©cutables (communÃ©ment appelÃ© Â«cgi-binÂ» dans les systÃšmes Unix); vous pouvez en crÃ©er un nouveau ou utiliser celui qui existe dÃ©jÃ . Si vous en crÃ©ez un nouveau, il vous faudra en informer votre serveur web par le truchement de son fichier de configuration. Dans chacun de ces deux cas de figure, il vous faudra saisir l'adresse web du rÃ©pertoire CGI. Le dialogue d'installation vous guidera au travers de tous ces choix. Il est important de mettre en place des droits d'accÃšs corrects Ã  certains rÃ©pertoires, et on vous demandera les informations nÃ©cessaires. Enfin, on vous demandera le mot de passe de l'utilisateur en charge de l'administration systÃšme de Greenstone.</Text>
+<Text id="94">Par dÃ©faut, Greenstone s'installe dans le rÃ©pertoire /usr/local/gsdl si c'est l'utilisateur root qui effectue l'installation, et dans le rÃ©pertoire /gsdl dans le cas contraire, oÃ¹ Â«Â» dÃ©note le rÃ©pertoire personnel de l'utilisateur concernÃ©.</Text>
+<Text id="95">L'installation des binaires ne prend que quelques minutes, juste assez pour vous laisser le temps de rÃ©pondre aux questions appropriÃ©es. Si vous installez le code source, le script d'installation procÃ©dera Ã  sa compilation, opÃ©ration qui peut prendre de 10 minutes Ã  une heure ou plus, en fonction de la vitesse de votre processeur.</Text>
+<Text id="96">Pour dÃ©sinstaller le logiciel, tapez:</Text>
+<CodeLine>cd ~/gsdl</CodeLine>
+<Text id="97">ou /usr/local/gsdl si c'est l'utilisateur root qui a installÃ© Greenstone</Text>
+<CodeLine>sh Uni nstall.sh</CodeLine>
+<Text id="98">Pendant la procÃ©dure d'installation, on vous demandera si vous souhaitez installer des collections Greenstone. La collection Greenstone Â«DemoÂ» est installÃ©e automatiquement; les autres collections du cÃ©dÃ©rom sont dÃ©crites en sectionÂ <CrossRef target="Chapter" ref="greenstone_collections"/>.</Text>
+</Content>
+</Subsection>
+<Subsection id="unix_webserver_configuration">
+<Title>
+<Text id="99">Configuration de serveur web sous Unix</Text>
+</Title>
+<Content>
+<Text id="100">Si vous disposez dÃ©jÃ  d'un serveur web, il faudra y apporter quelques modifications pour rendre votre installation de Greenstone opÃ©rationnelle. Le script d'installation dÃ©taille ces modifications. Vous aurez peut-Ãªtre besoin d'un administrateur systÃšme pour reconfigurer le serveur webÂ --Â votre administrateur systÃšme devrait comprendre les instructions fournies par le script d'installation. Pour votre confort, la sortie du script d'installation est consignÃ©e dans un fichier appelÃ© INSTALL_RECORD et situÃ© dans le rÃ©pertoire d'installation de Greenstone.</Text>
+<Text id="101">Si vous ne disposez pas dÃ©jÃ  d'un serveur web, il vous faudra en installer un. L'annexe <CrossRef target="Chapter" ref="appendix_associated_software"/> fournit des informations relatives Ã  Apache. Il vous faudra ensuite le configurer de maniÃšre appropriÃ©e. La sectionÂ <CrossRef target="Chapter" ref="setting_up_webserver"/> dÃ©taille les portions de l'installation d'un serveur web qui concernent Greenstone, et comment il faut les modifier. Tout revient Ã  ajouter une petite dizaine de lignes Ã  un fichier de configuration.</Text>
+<Text id="102">Nul besoin d'effectuer la procÃ©dure d'installation ci-dessus dÃ©taillÃ©e sous l'identifiant Â«rootÂ». Cependant, de tels privilÃšges peuvent Ãªtre nÃ©cessaires pour modifier un serveur Apache existantÂ --Â tout dÃ©pend de sa configuration. Si vous installez Apache vous-mÃªme, vous pouvez procÃ©der en tant que simple utilisateur, sans utiliser de privilÃšges rÃ©servÃ©s Ã  Â«rootÂ». Dans le cas oÃ¹ vous avez affaire Ã  un administrateur systÃšme rÃ©ticent, vous pourrez toujours contourner la difficultÃ© en installant un deuxiÃšme serveur web Apache sur votre ordinateurÂ --Â mÃªme si un tel serveur est dÃ©jÃ  installÃ©.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="how_to_find_greenstone">
+<Title>
+<Text id="103">OÃ¹ trouver Greenstone</Text>
+</Title>
+<Content>
+<Subsection id="local_library_windows_only">
+<Title>
+<Text id="104">BibliothÃšque locale (seulement pour Windows)</Text>
+</Title>
+<Content>
+<Text id="105">Si vous utilisez la bibliothÃšque locale, il suffit d'invoquer le programme Â«GreenstoneÂ» depuis le menu DÃ©marrer. Ceci dÃ©marrera automatiquement le navigateur web et chargera la page d'accueil de la bibliothÃšque numÃ©rique Greenstone, d'oÃ¹ la collection Â«DemoÂ» de Greenstone devrait Ãªtre accessible.</Text>
+</Content>
+</Subsection>
+<Subsection id="web_library_windows_and_unix">
+<Title>
+<Text id="106">BibliothÃšque Web (Windows et Unix)</Text>
+</Title>
+<Content>
+<Text id="107">Si vous utilisez la bibliothÃšque web, utilisez l'URL suivante pour entrer sur le systÃšme Greenstone, aprÃšs avoir installÃ© le logiciel et configurÃ© le serveur web:</Text>
+<Text id="108">http://localhost/gsdl/cgi-bin/library</Text>
+<Text id="109">La collection Â«DemoÂ» de Greenstone devrait Ãªtre accessible depuis cette page.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_collector">
+<Title>
+<Text id="110">Le Collector</Text>
+</Title>
+<Content>
+<Text id="111">Un lien menant vers le Collector est fourni sur la page d'accueil de la bibliothÃšque numÃ©rique.</Text>
+</Content>
+</Subsection>
+<Subsection id="administration">
+<Title>
+<Text id="112">Administration</Text>
+</Title>
+<Content>
+<Text id="113">Un lien menant vers les pages d'administration est fourni sur la page d'accueil de la bibliothÃšque numÃ©rique. L'utilisateur en charge de l'administration s'appelle Â«adminÂ», et vous avez dÃ» spÃ©cifier son mot de passe pendant le processus d'installation. L'administrateur a le droit d'ajouter de nouveaux utilisateurs et de construire des collections.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="the_greenstone_librarian_interface_(gli)">
+<Title>
+<Text id="114">l'Interface BibliothÃ©caire de Greenstone (GLI)</Text>
+</Title>
+<Content>
+<Text id="115">Greenstone "Librarian Interface" (l'Interface BibliothÃ©caire de Greenstone) (GLI) est un outil d'assistance Ã  la mise sur pied de bibliothÃšques numÃ©riques utilisant Greenstone. Il vous donne accÃšs Ã  la fonctionnalitÃ© de crÃ©ation de collection Greenstone, Ã  partir d'une interface commode "pointer et cliquer".</Text>
+<Text id="116">GLI est installÃ© automatiquement avec toutes les distributions de Greenstone. Il est placÃ© dans le sous-rÃ©pertoire "gli" du rÃ©pertoire racine de Greenstone (CProgram Filesgsdlgli, par dÃ©faut ). Il faut noter qu'il fonctionne conjointement avec Greenstone et ne le fera correctement que s'il est placÃ© dans un sous rÃ©pertoire de votre installation Greenstone. Et ce sera le cas si on a tÃ©lÃ©chargÃ© une des distributions de Greenstone.</Text>
+<Text id="117">Pour utiliser "GLI", l'ordinateur doit disposer de l'environnement "JAVA Runtime". Si tel n'est pas le cas, l'installation propose une version incluse dans le CD-ROM. Dans Unix, on doit s'assurer que PERL est installÃ© (pour Windows, Perl est dÃ©jÃ  inclus dans le logiciel Greenstone ). PriÃšre signaler Ã  greenstone@cs.waikato.ac.nz tout problÃšme intervenu dans l'exÃ©cution ou l'utilisation du "Librarian Interface" (Interface BibliothÃ©caire).</Text>
+<Subsection id="running_under_windows">
+<Title>
+<Text id="118">ExÃ©cution sous Windows</Text>
+</Title>
+<Content>
+<Text id="119">Pour exÃ©cuter "GLI" sous Windows, parcourir le rÃ©pertoire gli dans votre installation Greenstone (par exemple en utilisant l'explorateur de Windows), et double-cliquer sur le fichier appelÃ© gli.bat. Ce fichier vÃ©rifie que Greenstone, l'environnement Java Runtime et Perl sont tous installÃ©s, et dÃ©marre "Greenstone Librarian Interface" (l'Interface BibliothÃ©caire de Greenstone).</Text>
+</Content>
+</Subsection>
+<Subsection id="running_under_unix">
+<Title>
+<Text id="120">ExÃ©cution sous Unix</Text>
+</Title>
+<Content>
+<Text id="121">Pour exÃ©cuter GLI sous Unix, passer au rÃ©pertoire gli de votre installation Greenstone, et ensuite exÃ©cuter le script gli.sh. Ce script vÃ©rifie que Greenstone, l'environnement Java Runtime et Perl sont tous installÃ©s et sont sur votre chemin de recherche, et dÃ©marre "Greenstone Librarian Interface" (l'Interface BibliothÃ©caire de Greenstone).</Text>
+</Content>
+</Subsection>
+<Subsection id="getting_help">
+<Title>
+<Text id="122">Obtenir de l'aide</Text>
+</Title>
+<Content>
+<Text id="123">"Greenstone Librarian Interface" (l'Interface BibliothÃ©caire de Greenstone) a en ligne des fonctions d'aide Ã©tendues. On peut obtenir de l'aide en cliquant sur le bouton Help situÃ© en haut Ã  droite de l'Ã©cran. Ceci ouvre le texte sur une section qui traite de ce qu'on est en train de faire, d'un des panneaux utilisÃ©s. On peut parcourir le texte d'aide et s'informer sur ce qu'on cherche. Utilisez-le.</Text>
+</Content>
+</Subsection>
+<Subsection id="compiling_gli">
+<Title>
+<Text id="124">Compiler le l'Interface BibliothÃ©caire de Greenstone</Text>
+</Title>
+<Content>
+<Text id="125">Si on a tÃ©lÃ©chargÃ© une distribution source de Greenstone, le code source Java de "Greenstone Librarian Interface" (l'Interface BibliothÃ©caire de Greenstone) est mis Ã  disposition. Pour le compiler, l'ordinateur doit avoir un kit de dÃ©veloppement Java. L'appendice <CrossRef target="Chapter" ref="appendix_associated_software"/> fournit l'information sur la maniÃšre de l'obtenir. Pour compiler le code source, exÃ©cuter les fichiers makegli.bat (Windows) ou makegli.sh (Unix). Une fois compilÃ©, vous pouvez exÃ©cuter GLI comme dÃ©crit ci-dessus.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="testing_and_troubleshooting">
+<Title>
+<Text id="126">Tests et diagnostics</Text>
+</Title>
+<Content>
+<Text id="127">Pour tester Greenstone, pointez votre navigateur web vers la page d'accueil de Greenstone afin d'explorer la collection Â«DemoÂ» ou toute autre collection installÃ©e. Pas d'inquiÃ©tudeÂ --Â vous ne pouvez rien casser. Cliquez partout et sans crainte: la plupart des images qui apparaÃ®tront sur votre Ã©cran rÃ©agissent aux clics. Si vous maintenez le pointeur de la souris au-dessus d'une image, la plupart des navigateurs afficheront un message qui vous expliquera ce qui se passera si vous cliquez. Faites l'expÃ©rience! Choisissez des mots communs tels que Â«leÂ» (the) ou Â«etÂ» (and) en tant que critÃšres de rechercheÂ --Â voilÃ  qui devrait fournir des rÃ©ponses, et vous ne pourrez rien casser. Pour plus d'informations Ã  ce sujet, consultez le Guide de l'utilisateur de la bibliothÃšque numÃ©rique Greenstone.</Text>
+<Subsection id="troubleshooting">
+<Title>
+<Text id="128">Diagnostics et remÃšdes</Text>
+</Title>
+<Content>
+<Table id="table_troubleshooting">
+<Title/>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="129"><b>ProblÃšme</b></Text>
+</th>
+<th width="246">
+<Text id="130"><b>Essayez ceci</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="131">BIBLIOTHÃQUE LOCALE (SEULEMENT POUR WINDOWS)</Text>
+</th>
+<th width="151">
+<Text id="132">Quand je dÃ©marre Greenstone, mon ordinateur me demande de me connecter Ã  mon fournisseur dâaccÃšs Internet par tÃ©lÃ©phone.</Text>
+</th>
+<th width="246">
+<Text id="133">Cliquez sur le bouton<i>Annuler</i>de la boÃ®te de dialogue. Ceci rÃ©sout gÃ©nÃ©ralement ce problÃšme.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="134">Quand je dÃ©marre Greenstone, mon ordinateur me demande<i>encore</i>de me connecter Ã  mon fournisseur dâaccÃšs Internet par tÃ©lÃ©phone.</Text>
+</th>
+<th width="246">
+<Text id="135">Choisissez la Â«version restreinteÂ» lorsque vous dÃ©marrez Greenstone. Cette version ne fonctionne quâavec Netscape.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="136">Quand je pointe mon navigateur vers la bibliothÃšque numÃ©rique, il ne trouve pas la page dâaccueil.</Text>
+</th>
+<th width="246">
+<Text id="137">VÃ©rifiez vos rÃ©glages de mandataire (<i>proxy</i>) Internet et dÃ©sactivez ces derniers (utilisez<i>Ãditer les prÃ©fÃ©rences</i>pour Netscape ou<i>Options Internet</i>pour Internet Explorer).</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="138">Le Collector me semble fonctionner trÃšs lentement!</Text>
+</th>
+<th width="246">
+<Text id="139">Utilisez-vous Netscape sous Windows 2000 ? Si câest le cas, essayez plutÃŽt dâemployer Internet Explorer â sousWindows 2000 (et seulement sous ce systÃšme), il semble y avoir une incompatibilitÃ© avec Netscape.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="142">BIBLIOTHÃQUE WEB (WINDOWS ET UNIX)</Text>
+</th>
+<th width="151">
+<Text id="143">Quand je dÃ©marre Apache, il termine immÃ©diatement.</Text>
+</th>
+<th width="246">
+<Text id="144">Ajoutez une directive ServerName localhost dans le fichier de configuration dâApache (voyez Ã  ce sujet la section <CrossRef target="Section" ref="apache_web_server"/>).</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="145">Quand je pointe mon navigateur vers la bibliothÃšque numÃ©rique, il affiche nâimporte quoi â un fichier binaire.</Text>
+</th>
+<th width="246">
+<Text id="146">VÃ©rifiez la directive ScriptAlias dans le fichier de configuration dâApache, et assurez-vous quâelle prÃ©cÃšde la directive Alias (voyez Ã  ce sujet la section 4.1).</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="147">Jâobtiens bien la page dâaccueil de Greenstone de la figureÂ <CrossRef target="Figure" ref="your_greenstone_home_page"/>, mais lâicone de la collection Â«DemoÂ» nâapparaÃ®t pas.</Text>
+</th>
+<th width="246">
+<Text id="148">ExÃ©cutez le programme library, situÃ© dans le rÃ©pertoire cgi-bin, depuis lâinterprÃ©teur de commandes de DOS ou du shell, afin dâobtenir des informations de dÃ©bogage qui vous aideront Ã  mieux localiser le problÃšme.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="149">LES DEUX VERSIONS</Text>
+</th>
+<th width="151">
+<Text id="150">Quand je pointe mon navigateur vers la bibliothÃšque numÃ©rique, il ne trouve pas la page dâaccueil.</Text>
+</th>
+<th width="246">
+<Text id="151">Essayez dâutiliser la chaÃ®ne 127.0.0.1 en lieu et place de localhost. Ce numÃ©ro IP rÃ©servÃ© correspond Ã  une Â«boucle de retourÂ» (<i>loopback</i>) vers votre ordinateur local.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="151">
+<br/>
+<Text id="152">Mon navigateur se plaint de ne pas trouver le fichier main.cfg.</Text>
+</th>
+<th width="246">
+<Text id="153">VÃ©rifiez que les fichiers de Greenstone existent bien et sont lisibles par tous. Si vous utilisez la bibliothÃšque web, essayez dâexÃ©cuter le programme library depuis lâinterprÃ©teur de commandes. Sâil sâexÃ©cute sans heurts, le problÃšme est Ã  chercher du cÃŽtÃ© des permissions de fichiers (voir Ã  ce sujet la section <CrossRef target="Section" ref="file_permissions"/>). Dans le cas contraire, la variable GSDLHOME a probablement reÃ§u une valeur incorrecte dans le fichier de configuration gsdlsite.cfg (voir Ã  ce sujet la section <CrossRef target="Section" ref="gsdlsite_configuration_file"/>).</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="154">Jâai des soucis avec le Collector.</Text>
+</th>
+<th width="246">
+<Text id="155">Lisez le Guide de lâutilisateur de la bibliothÃšque numÃ©rique Greenstone, section <CrossRef external="User" lang="fr" target="Chapter" ref="making_greenstone_collections"/>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="156">Jâai ajoutÃ© un nouvel utilisateur mais il ne semble pas pouvoir se connecter.</Text>
+</th>
+<th width="246">
+<Text id="157">VÃ©rifier que le rÃ©pertoire C:\Program Files\gsdl\etc ainsi que tous les fichiers quâil contient sont inscriptibles par tous (voir Ã  ce sujet la section <CrossRef target="Section" ref="file_permissions"/>).</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="learn_more">
+<Title>
+<Text id="158">Pour en savoir plus</Text>
+</Title>
+<Content>
+<Text id="159">Pour en savoir plus sur les entrailles de votre installation de Greenstone, consultez le Guide du dÃ©veloppeur de la bibliothÃšque numÃ©rique Greenstone. Il comprend, entre autres choses, les dÃ©tails de la structure arborescente de rÃ©pertoires qui a Ã©tÃ© mise en place, ainsi que des informations sur la maniÃšre de configurer votre site Greenstone.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="greenstone_collections">
+<Title>
+<Text id="160">Les collections de Greenstone</Text>
+</Title>
+<Content>
+<Text id="161">Plusieurs collections de dÃ©monstration de Greenstone sont inclus dans le CD-ROM. Si vous avez un accÃšs web, beaucoup d'autres peuvent Ãªtre tÃ©lÃ©chargÃ©s sous forme finie ou non, Ã  partir du site web de la "New Zealand Digital Library Project (nzdl.org)".</Text>
+<Text id="162">La collection de dÃ©monstration de Greenstone est un petit composant de "Humanity Development Library (HDL)", une collection bien entretenue. Elle illustre le fait que des possibilitÃ©s de navigation relativement riches peuvent Ãªtre fournies (aussi longtemps qu'une mÃ©ta-donnÃ©e appropriÃ©e est disponible). Elle est automatiquement incluse Ã  l'installation du logiciel.</Text>
+<Text id="163">Greenstone vient aussi avec quelques exemples de collections bien documentÃ©es dont la page "about" dÃ©crit la maniÃšre avec laquelle ils ont Ã©tÃ© Ã©laborÃ©s. Ils dÃ©montrent diverses possibilitÃ©s de Greenstone. La boÃ®te de dialogue "install" vous proposera de les inclure ou non dans l'installation de Greenstone; l'espace disque approximatif nÃ©cessaire Ã  chaque collection est indiquÃ© ci-dessous.</Text>
+<Table class="hidden" id="table_collections">
+<Title/>
+<TableContent>
+<tr>
+<th width="60">
+<Text id="164"><i>demo</i></Text>
+</th>
+<th width="182">
+<Text id="165">DÃ©monstration de Greenstone (7 MO)</Text>
+</th>
+<th width="294">
+<Text id="166">Une petite composante de HDL. Si vous clonez cette collection, la totalitÃ© des fonctions nâapparaÃ®tra que si vos nouveaux fichiers fournissent lâinformation mÃ©ta-donnÃ©e appropriÃ©e.</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="167"><i>dls-e</i></Text>
+</th>
+<th width="182">
+<Text id="168">Sous-ensemble de la collection BibliothÃšque de DÃ©veloppement (150 MO)</Text>
+</th>
+<th width="294">
+<Text id="169">A lâinstar de "Greenstone Demo", câest une composante de HDL, mais plus grande. Elle contient 250 livres de publications, rapports et magazines dans divers domaines du dÃ©veloppement humain (la totalitÃ© de HDL contient 1230 publications). Elle a la mÃªme structure que "Greenstone Demo". Elle est assez complexe et si on est tout juste dÃ©butant, il serait peut-Ãªtre prÃ©fÃ©rable de consulter dâabord dâautres collections (Exemple : dÃ©monstration MS Word et PDF, les archives Greenstone, ou la collection "simple image").</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="170"><i>wrdpdf-e</i></Text>
+</th>
+<th width="182">
+<Text id="171">DÃ©monstration MSWord et PDF (4 MO)</Text>
+</th>
+<th width="294">
+<Text id="172">Elle contient des documents en PDF, MS Word, RTF, et des formats Postscript, qui attestent de la possibilitÃ© de former des collections Ã  partir de documents de diffÃ©rents formats. Le fichier de configuration de la collection est trÃšs simple.</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="173"><i>gsarch-e</i></Text>
+</th>
+<th width="182">
+<Text id="174">Collection des Archives de Greenstone (5 MO)</Text>
+</th>
+<th width="294">
+<Text id="175">Une collection de messages e-mail Ã  partir des archives de listes dâadresses de Greenstone, elle utilise le plugin e-mail qui analyse les fichiers en formats e-mail. Le fichier de configuration de la collection est trÃšs simple.</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="176"><i>cltbib-e</i></Text>
+</th>
+<th width="182">
+<Text id="177">Collection bibliographie (7 MO)</Text>
+</th>
+<th width="294">
+<Text id="178">Avec environ 4000 entrÃ©es bibliographiques, cette collection incorpore une interface de recherche basÃ©e sur un formulaire qui permet une recherche par champ. Elle est assez complexe.</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="179"><i>cltext-e</i></Text>
+</th>
+<th width="182">
+<Text id="180">SupplÃ©ment bibliographie (1 MO)</Text>
+</th>
+<th width="294">
+<Text id="181">Cette petite collection de 10 entrÃ©es bibliographiques illustre la fonction "supercollection" qui recherche plusieurs collections Ã  la fois. Elle fonctionne avec la collection bibliographie et son fichier de configuration est presque le mÃªme.</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="182"><i>MARC-e</i></Text>
+</th>
+<th width="182">
+<Text id="183">Exemple MARC (1 MO)</Text>
+</th>
+<th width="294">
+<Text id="184">BasÃ© sur quelques enregistrements Marc de la Librairie du CongrÃšs, câest est une collection simple (et ne permet pas une recherche basÃ©e sur formulaire).</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="185"><i>oai-e</i></Text>
+</th>
+<th width="182">
+<Text id="186">DÃ©mo OAI (18 MO)</Text>
+</th>
+<th width="294">
+<Text id="187">En utilisant la caractÃ©ristique "Open Archive Protocol" et "Import Form", elle extrait des mÃ©ta-donnÃ©es dâune archive et confectionne une collection Ã  partir des enregistrements. Dans ce cas, ce sont des images ; ainsi, aussi bien les plugins OAI que les images sont utilisÃ©s.</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="188"><i>image-e</i></Text>
+</th>
+<th width="182">
+<Text id="189">Collection dâimages simple (1 MO)</Text>
+</th>
+<th width="294">
+<Text id="190">Cette collection dâimages simples standard ne contient aucun texte et aucune mÃ©tadonnÃ©e explicite, ce qui la rend plutÃŽt irrÃ©aliste. Le fichier de configuration est tout aussi simple et accessible.</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="191"><i>authen-e</i></Text>
+</th>
+<th width="182">
+<Text id="192">DÃ©monstration de formatage et dâauthentification (8 MO)</Text>
+</th>
+<th width="294">
+<Text id="193">Avec le mÃªme matÃ©riel que la collection de dÃ©monstration Greenstone originale, elle affiche deux caractÃ©ristiques indÃ©pendantes : le formatage de document non-standard et lâaccÃšs contrÃŽlÃ© aux documents par le biais dâune authentification de lâutilisateur.</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="194"><i>garish</i></Text>
+</th>
+<th width="182">
+<Text id="195">Version Garish de la collection de dÃ©monstration (8 MO)</Text>
+</th>
+<th width="294">
+<Text id="196">Cette collection contient aussi le mÃªme matÃ©riel que la collection de dÃ©monstration Greenstone. Sa prÃ©sentation a Ã©tÃ© altÃ©rÃ©e pour montrer comment les pages gÃ©nÃ©rÃ©es peuvent Ãªtre affichÃ©es diffÃ©remment. Elle dÃ©pend dâun fichier macro non standard qui est fourni avec Greenstone.</Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="197"><i>isis-e</i></Text>
+</th>
+<th width="182">
+<Text id="198">Exemple CDS/ISIS (1 MO)</Text>
+</th>
+<th width="294">
+<Text id="199">Cette collection est construite a partir des donnÃ©es CDS/ISIS de quelques 150 entrÃ©es bibliographiques. Elle utilize le plugin ISISPlug, qui lit les fichiers standards ISIS .mst et .fdt et les convertit en metadonnÃ©es de Greenstone.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Chapter>
+<Chapter id="setting_up_webserver">
+<Title>
+<Text id="200">Configuration du serveur web</Text>
+</Title>
+<Content>
+<Text id="201">Nous dÃ©crivons dans cette section la maniÃšre de configurer votre serveur web pour qu'il fonctionne avec Greenstone. Toutes ces prÃ©cisions sont inutiles Ã  qui utilise la bibliothÃšque locale sous Windows, car le logiciel fonctionne alors Â«tel queÂ», sans nÃ©cessiter un serveur web.</Text>
+<Text id="202">Nous traiterons Ã  la fois le cas du serveur web Apache, qui est librement disponible pour Windows comme pour Unix (reportez-vous Ã  l'annexe <CrossRef target="Chapter" ref="appendix_associated_software"/> pour plus de dÃ©tails Ã  ce sujet), et des serveurs web Â«Personal Web Server (PWS)Â» et Â«Internet Information Services (IIS)Â» de Microsoft. PWS est le serveur web standard fourni par Microsoft pour Windows 95/98; IIS est celui des versions 2000 et XP de Windows. Windows NT peut utiliser chacun de ces deux serveurs. La description concernant Apache s'applique aussi Ã  la bibliothÃšque web, versions Windows comme Unix (bien que nous utilisions les terminologies et chemins d'accÃšs propres Ã  Windows). La section PWS/IIS ne s'applique qu'Ã  la bibliothÃšque web sous Windows.</Text>
+<Text id="203">AprÃšs avoir installÃ© le serveur web, il faut installer Greenstone. Nous supposerons que lors de la procÃ©dure d'installation, vous avez choisi l'action par dÃ©faut Ã  chaque Ã©tape, en cliquant sur le bouton Suivant. Au final, vous disposez d'un rÃ©pertoire CProgram Filesgsdl contenant le binaire de la bibliothÃšque web, ainsi que quelques fichiers complÃ©mentaires.</Text>
+<Text id="204">Tous les serveurs web utilisent l'URL spÃ©ciale Â«localhostÂ» pour reprÃ©senter l'ordinateur sur lequel le serveur fonctionne. C'est pourquoi, lors de l'installation d'un serveur web, vous pourrez accÃ©der Ã  vos documents HTML en tapant l'URLhttp://localhostdans un navigateur. Si votre ordinateur possÃšde un nom dans le DNS (ou systÃšme de noms), c'est ce nom qui sera utilisÃ© en lieu et place de Â«localhostÂ» pour identifier votre ordinateur depuis des sites distants. C'est ainsi que sur l'ordinateur de la bibliothÃšque numÃ©rique de Nouvelle-ZÃ©lande, les URLhttp://nzdl.orgethttp://localhostsont Ã©quivalentes. Si vous tapezhttp://nzdl.orgsur votre ordinateur, vous accÃ©derez au serveur web de la bibliothÃšque numÃ©rique de Nouvelle-ZÃ©lande, alors que si vous tapezhttp://localhostvous accÃ©derez au serveur web de votre propre ordinateur.</Text>
+<Section id="apache_web_server">
+<Title>
+<Text id="205">Le serveur web Apache</Text>
+</Title>
+<Content>
+<Text id="206">Le serveur web Apache est gÃ©nÃ©ralement installÃ© dans le rÃ©pertoire CProgram FilesApache GroupApache, et il est configurÃ© de sorte que son rÃ©pertoire cgi-bin soit dans le sous-rÃ©pertoire cgi-bin et que le rÃ©pertoire racine des documents corresponde au sous-rÃ©pertoire htdocs. On peut modifier sa configuration en Ã©ditant le fichier de configuration situÃ© sous CProgram FilesApache GroupApacheconfhttpd.conf. Ce fichier Ã©tant un fichier texte, il est trÃšs facile Ã  lire et de voir comment les choses sont configurÃ©es.</Text>
+<Text id="207">En fonction de la configuration des logiciels de communication en rÃ©seau de votre ordinateur, vous devrez peut-Ãªtre ajouter la ligne suivante au fichier de configuration httpd.conf de votre serveur Apache:</Text>
+<CodeLine>ServerName localhost</CodeLine>
+<Text id="208">En l'absence de cette ligne, le systÃšme tentera de dÃ©terminer le nom de votre serveur. Cependant, des bogues prÃ©sents dans certaines versions de Windows font Ã©chouer cette opÃ©ration. Dans un tel cas de figure, Apache sort immÃ©diatement lorsqu'on le dÃ©marre. Il affiche bien un message d'erreur, mais ce dernier est tout de suite effacÃ© et vous n'aurez probablement pas le temps de le lire.</Text>
+<Subsection id="setting_up_cgi-bin_directory">
+<Title>
+<Text id="209">Mettre en place le rÃ©pertoire cgi-bin de Greenstone</Text>
+</Title>
+<Content>
+<Text id="210">Le rÃ©pertoire cgi-bin est celui oÃ¹ le serveur web traite les documents en tant que programmes Ã  exÃ©cuter. On utilise la directive ScriptAlias d'Apache pour crÃ©er un rÃ©pertoire cgi-bin. Vous remarquerez que cette directive permet de transformer n'importe quel rÃ©pertoire en rÃ©pertoire d'exÃ©cutables CGIÂ --Â nul besoin pour le rÃ©pertoire de s'appeler Â«cgi-binÂ»! De mÃªme, un rÃ©pertoire appelÃ© Â«cgi-binÂ» ne joue aucun rÃŽle particulier en l'absence de directive ScriptAlias le concernant.</Text>
+<Text id="211">Une fois installÃ©, Apache possÃšde le rÃ©pertoire cgi-bin suivant: CProgram FilesApache GroupApachecgi-bin. Ceci signifie que si on lui fournit l'URLhttp://localhost/cgi-bin/bonjour, le serveur web tentera d'exÃ©cuter un fichier bonjour situÃ© dans le rÃ©pertoire prÃ©cÃ©dent.</Text>
+<Text id="212">Greenstone comprend un programme, appelÃ© Â«library.exeÂ», qui doit Ãªtre exÃ©cutÃ© par le serveur web: il lit alors un fichier appelÃ© le Â«fichier de configuration de site de GreenstoneÂ», ou Â«gsdlsite.cfgÂ», qui doit se trouver dans le mÃªme rÃ©pertoire.</Text>
+<Text id="213">La meilleure maniÃšre d'obtenir ce rÃ©sultat est d'utiliser la directive ScriptAlias d'Apache pour crÃ©er un nouveau rÃ©pertoire cgi-bin. Voici l'extrait du fichier de configuration d'Apache, httpd.conf, qui ajoute le rÃ©pertoire CProgram Filesgsdlcgi-bin Ã  la liste des rÃ©pertoires de type cgi-bin:</Text>
+<CodeLine>ScriptAlias /gsdl/cgi-bin/ "C:/Program Files/gsdl/cgi-bin/"</CodeLine>
+<CodeLine>&lt;Directory C:/Program Files/gsdl/cgi-bin&gt;</CodeLine>
+<CodeLine>  Options None</CodeLine>
+<CodeLine>  AllowOverride None</CodeLine>
+<CodeLine>&lt;/Directory&gt;</CodeLine>
+<Text id="214">Vous remarquerez que les fichiers de configuration d'Apache utilisent des barres de division ((forward) slash) en lieu et place des barres obliques inversÃ©es (backslash), communes sous Windows.</Text>
+<Text id="215">Ceci signifie que toutes les URL de la formehttp://localhost/gsdl/cgi-bin...seront recherchÃ©es dans le rÃ©pertoire de chemin CProgram Filesgsdlcgi-bin et exÃ©cutÃ©es par le serveur web. Par exemple, si on lui demande l'URLhttp://localhost/gsdl/cgi-bin/bonjour, le serveur web tentera de lire CProgram Filesgsdlcgi-binbonjour, et de l'exÃ©cuter. Mais l'URLhttp://localhost/cgi-bin/bonjourcontinuera comme avant Ã  examiner le rÃ©pertoire cgi-bin d'Apache Ã  la recherche deCProgram FilesApache GroupApachecgi-binbonjour, pour exÃ©cuter ce fichier.</Text>
+</Content>
+</Subsection>
+<Subsection id="document_root_directory">
+<Title>
+<Text id="216">Le rÃ©pertoire racine des documents</Text>
+</Title>
+<Content>
+<Text id="217">Le rÃ©pertoire racine des documents est la racine de la structure arborescente des rÃ©pertoires de votre serveur web. Lors de son installation, Apache dispose comme racine de documents du rÃ©pertoire de chemin CProgram FilesApache GroupApachehtdocs. Cela signifie que si on lui demande l'URLhttp://localhost/bonjour.html, le serveur web tentera de lire un fichier appelÃ© bonjour.html dans le rÃ©pertoire ci-dessus.</Text>
+<Text id="218">Greenstone contient plusieurs fichiers qu'il faut que le serveur web lise. La maniÃšre la plus simple de procÃ©der est d'utiliser la directive Alias, qui ressemble Ã  ScriptAlias Ã  ceci prÃšs qu'elle s'applique aux pages web normales, et pas aux scripts CGI. InsÃ©rez les lignes suivantes dans le fichier de configuration de votre Apache, aprÃšs la directive ScriptAlias, afin d'ajouter le rÃ©pertoire CProgram Filesgsdl comme lieu de recherche de documents.</Text>
+<CodeLine>Alias /gsdl/ "C:/Program Files/gsdl/"</CodeLine>
+<CodeLine>&lt;Directory C:/Program Files/gsdl&gt;</CodeLine>
+<CodeLine> Options Indexes MultiViews FollowSymLinks</CodeLine>
+<CodeLine> AllowOverride None</CodeLine>
+<CodeLine> Order allow,deny</CodeLine>
+<CodeLine> Allow from all</CodeLine>
+<CodeLine>&lt;/Directory&gt;</CodeLine>
+<Text id="219">Ceci signifie que toute URL correspondant au premier argument de la directive Alias (gsdl) est recherchÃ©e sous la forme de fichiers situÃ©s dans le rÃ©pertoire donnÃ© en deuxiÃšme argument. En d'autres termes, une URL de la formehttp://localhost/gsdl/...aura pour effet la recherche de fichiers dans le rÃ©pertoire CProgram Filesgsdl. Si par exemple on fournit au serveur web l'URLhttp://localhost/gsdl/bonjour.html, il tentera de rechercher le fichier CProgram Filesgsdlbonjour.html. Mais l'URLhttp://localhost/bonjour.htmlcontinuera comme avant Ã  examiner le rÃ©pertoire htdocs normal d'Apache Ã  la recherche du fichier CProgram FilesApache GroupApachehtdocsbonjour.html.</Text>
+<Text id="220">Assurez-vous d'ajouter la directive Alias aprÃšs la directive ScriptAlias. DÃ©finir auprÃšs d'Apache l'alias/gsdlavant l'alias/gsdl/cgi-binreconnaÃ®trait l'URL/gsdl/cgi-bin/libraryavec la directive Alias et non pas avec la directive ScriptAlias, et cette URL serait interprÃ©tÃ©e comme une requÃªte de document au lieu d'une requÃªte du rÃ©sultat de l'exÃ©cution d'un programme. On obtiendrait alors l'Â«affichageÂ» du fichier binaire du programme en tant que page web dans le navigateur web, sans jamais l'avoir exÃ©cutÃ©.</Text>
+</Content>
+</Subsection>
+<Subsection id="security">
+<Title>
+<Text id="221">SÃ©curitÃ©</Text>
+</Title>
+<Content>
+<Text id="222">Gardez Ã  l'esprit le fait que si la version Â«bibliothÃšque webÂ» de Greenstone est configurÃ©e en suivant les instructions donnÃ©es ci-dessus, n'importe qui aura le droit de tÃ©lÃ©charger tout fichier situÃ© dans la structure arborescente de rÃ©pertoire dÃ©marrant sous gsdl. Ceci comprend les fichiers d'indexation, les documents source de toute collection que vous construirez, la base de donnÃ©es utilisateur, les journaux d'utilisation, etc.</Text>
+<Text id="223">Si vous souhaitez Ã©viter cela, vous pouvez facilement resserrer la configuration de votre serveur web afin d'en augmenter la sÃ©curitÃ©. Dans le cas du serveur web Apache, remplacez les lignes donnÃ©es dans la section prÃ©cÃ©dente par les lignes suivantes dans le fichier de configuration:</Text>
+<CodeLine>Alias /gsdl/ "C:/Program Files/gsdl/"</CodeLine>
+<CodeLine>&lt;Directory "C:/Program Files/gsdl"&gt;</CodeLine>
+<CodeLine>   Order allow,deny</CodeLine>
+<CodeLine>   Deny from all</CodeLine>
+<CodeLine>   &lt;FilesMatch</CodeLine>
+<CodeLine>"\.(gif|jpe?g|png|css|mov|mpeg|ps|pdf|doc|rtf|jar|class)$"&gt;</CodeLine>
+<CodeLine>         Order allow,deny</CodeLine>
+<CodeLine>         Allow from all</CodeLine>
+<CodeLine>   &lt;/FilesMatch&gt;</CodeLine>
+<CodeLine>&lt;/Directory&gt;</CodeLine>
+<Text id="224">Ceci aura pour effet de n'autoriser en tÃ©lÃ©chargement que les fichiers dont le nom vÃ©rifie l'expression rationnelle donnÃ©e dans la ligne FilesMatch (c'est-Ã -dire, dans le cas prÃ©sent, de n'autoriser qu'une liste fixÃ©e d'extensions de noms de fichiers).</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="pws_and_iis_webservers">
+<Title>
+<Text id="225">Les serveurs web PWS et IIS</Text>
+</Title>
+<Content>
+<Text id="226">Bien qu'aucun de ces deux serveurs ne soit installÃ© par dÃ©faut dans les systÃšmes Windows actuels, on peut facilement les installer Ã  l'aide du panneau de contrÃŽle Ajouter/Supprimer des programmes. Si vous ne les trouvez pas sur le cÃ©dÃ©rom de votre distribution de Windows, il vous faudra les tÃ©lÃ©charger depuis le site web de Microsoft (www.microsoft.com).</Text>
+<Text id="227">La procÃ©dure de mise en place de Greenstone est la mÃªme pour PWS et pour IIS. Invoquez le gestionnaire personnel de web et effectuez les actions suivantes:</Text>
+
+<NumberedList>
+<NumberedItem>
+<Text id="228">SÃ©lectionnez AvancÃ© pour obtenir l'Ã©cran d'Options AvancÃ©es.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="229">SÃ©lectionnez Accueil et cliquez sur Ajouter. Remplissez les champs comme suit:</Text>
+<Text id="230">Champ<i>RÃ©pertoire</i>:<i>C:\Program Files\gsdl</i></Text>
+<Text id="231">Champ<i>Alias</i>:<i>gsdl</i></Text>
+<Text id="232">Permissions dâaccÃšs:<i>Lecture</i></Text>
+<Text id="233">Permissions dâapplication:<i>Aucune</i></Text>
+<Text id="234">Cliquez sur OK.</Text>
+<Text id="235">VoilÃ  qui rendra les fichiers de Greenstone accessibles au serveur web.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="236">De retour dans l'Ã©cran d'Options avancÃ©es, sÃ©lectionnez gsdl et cliquez sur Ajouter. Remplissez les champs comme suit:</Text>
+<Text id="237">Champ<i>RÃ©pertoire</i>:<i>C:\Program Files\gsdl\cgi-bin</i></Text>
+<Text id="238">Champ<i>Alias</i>:<i>cgi-bin</i></Text>
+<Text id="239">Permissions dâaccÃšs:<i>Aucune</i></Text>
+<Text id="240">Permissions dâapplication:<i>ExÃ©cution</i></Text>
+<Text id="241">Cliquez sur OK.</Text>
+<Text id="242">VoilÃ  qui rendra le programme library.exe de Greenstone exÃ©cutable par le serveur web.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="243">Rendez-vous Ã  l'URLhttp://localhost/cgi-bin/library.exe</Text>
+<Text id="244">Remarque: avec les serveurs PWS et IIS, il vous faut prÃ©ciser l'extension de fichier .exe.</Text>
+</NumberedItem>
+</NumberedList>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="configuring_your_site">
+<Title>
+<Text id="245">Configurer son site</Text>
+</Title>
+<Content>
+<Text id="246">Pour que Greenstone puisse fonctionner correctement, il faut mettre en place les droits d'accÃšs Ã  certains fichiers. On trouve aussi un fichier de configuration associÃ© Ã  chaque site Greenstone. La procÃ©dure d'installation crÃ©e un fichier de configuration gÃ©nÃ©rique qui repose sur les choix effectuÃ©s durant l'installation, mais son contenu peut Ãªtre adaptÃ© Ã  diffÃ©rentes situations. La prÃ©sente section dÃ©taille ces deux questions.</Text>
+<Section id="file_permissions">
+<Title>
+<Text id="247">Droits d'accÃšs aux fichiers</Text>
+</Title>
+<Content>
+<Text id="248">La prÃ©sente section ne concerne par les utilisateurs de Windows 95/98, car leurs systÃšmes d'exploitation n'identifient pas les propriÃ©taires des fichiers.</Text>
+<Text id="249">Sous Windows NT et 2000 ainsi que sous les systÃšmes Unix, les scripts CGI ne sont pas exÃ©cutÃ©s avec des droits d'utilisateurs normaux, car il n'est pas possible d'identifier les utilisateurs sur le web. Ils sont plutÃŽt exÃ©cutÃ©s au nom de l'utilisateur qui a dÃ©marrÃ© le serveur web (sur les systÃšmes de type Windows), ou au nom d'un utilisateur particulier (souvent appelÃ© nobody sur les systÃšmes Unix). C'est pourquoi tous les fichiers et rÃ©pertoires contenus dans l'arborescence CProgram Filesgsdl doivent Ãªtre lisibles par tous (ou en tout cas lisibles par l'utilisateur des scripts CGI, qui peut Ãªtre nobody). Pour tester la bonne mise en place des permissions sur les fichiers, exÃ©cutez le programme library.exe depuis l'interprÃ©teur de commandes. Si les fichiers se trouvent aux bons endroits mais que les permissions sont incorrectes, il fonctionnera correctement depuis l'interprÃ©teur de commandes. Cette situation est Ã  comparer Ã  l'exÃ©cution depuis un navigateur web, oÃ¹ il est alors exÃ©cutÃ© avec les droits de l'utilisateur nobody, situation qui devrait Ã©chouer en cas de droits incorrects. Un autre test consiste Ã  l'exÃ©cuter au nom d'un autre utilisateur aprÃšs s'Ãªtre connectÃ© en tant que tel, pour vÃ©rifier si les droits d'accÃšs aux fichiers sont spÃ©cifiques au compte utilisateur original.</Text>
+<Text id="250">Pour fonctionner depuis un navigateur web, tous les rÃ©pertoires de Greenstone doivent Ãªtre lisibles par tous. Le rÃ©pertoire CProgram Filesgsdletc et son contenu doivent de mÃªme Ãªtre inscriptibles par tous. Il s'agit du rÃ©pertoire oÃ¹ le programme library inscrira les journaux d'utilisation, d'erreur et d'initialisation, ainsi que diverses bases de donnÃ©es utilisateur. Si vous Ãªtes rÃ©ticent Ã  rendre ce rÃ©pertoire inscriptible par tous, mettez en place des permissions de sorte que seuls les fichiers errout.txt, initout.txt, key.db, users.db, history.db, et usage.txt soient inscriptibles par l'utilisateur CGI.</Text>
+<Text id="251">Si les droits d'accÃšs sous le rÃ©pertoire CProgram Filesgsdletc sont incorrects, vous remarquerez peut-Ãªtre que l'authentification des utilisateurs et la recherche dans l'historique ne fonctionneront pas, ainsi que l'absence de gÃ©nÃ©ration du journal d'utilisation (usage.txt).</Text>
+</Content>
+</Section>
+<Section id="gsdlsite_configuration_file">
+<Title>
+<Text id="252">Le fichier de configuration gsdlsite.cfg</Text>
+</Title>
+<Content>
+<Text id="253">La procÃ©dure d'installation crÃ©e un fichier de configuration de Greenstone gÃ©nÃ©rique qui repose sur les choix effectuÃ©s durant l'installation. Dans le cas de notre installation c'est CProgram Filesgsdlcgi-bingsdlsite.cfg, dont voici le contenu:</Text>
+<CodeLine># Site configuration file for Greenstone.</CodeLine>
+<CodeLine># Lines begining with</CodeLine>
+<CodeLine># are comments.</CodeLine>
+<CodeLine># This file should be placed in the same directory as your library</CodeLine>
+<CodeLine># executable file. it should be edited to suit your site.</CodeLine>
+<CodeLine># points to the GSDLHOME directory</CodeLine>
+<CodeLine>gsdlhome âC:/Program Files/gsdl â</CodeLine>
+<CodeLine># this is the http address of GSDLHOME</CodeLine>
+<CodeLine># if your webservers DocumentRoot is set to $GSDLHOME</CodeLine>
+<CodeLine># then httpprefix can be commented out</CodeLine>
+<CodeLine>httpprefix /gsdl</CodeLine>
+<CodeLine># this is the http address of the directory which</CodeLine>
+<CodeLine># contains the images for the interface.</CodeLine>
+<CodeLine>httpimg /gsdl/images</CodeLine>
+<CodeLine># should contain the http address of this cgi script. This</CodeLine>
+<CodeLine># is not needed if the http server sets the environment variable</CodeLine>
+<CodeLine># SCRIPT_NAME</CodeLine>
+<CodeLine>#gwcgi         /cgi-bin/library</CodeLine>
+<CodeLine># maxrequests is the most requests a fastcgi process</CodeLine>
+<CodeLine># will serve before it exits. This can be set to a</CodeLine>
+<CodeLine># low figure (like 1) while debugging and then set</CodeLine>
+<CodeLine># to a high figure (like 10000) when everything is</CodeLine>
+<CodeLine># working well.</CodeLine>
+<CodeLine>#maxrequests 10000</CodeLine>
+<Text id="254">Vous pouvez personnaliser votre installation en Ã©ditant ce fichier, mais il est peu probable que vous en Ã©prouviez le besoin.</Text>
+<Text id="255">La ligne gsdlhome pointe tout simplement vers le rÃ©pertoire CProgram Filesgsdl.</Text>
+<Text id="256">httpprefix est l'adresse web du rÃ©pertoire oÃ¹ Greenstone est installÃ©. Nous avons expliquÃ© plus haut comment crÃ©er un alias de maniÃšre que les URL de la formehttp://localhost/gsdl/...soient recherchÃ©es dans le rÃ©pertoire CProgram Filesgsdl. Placer la ligne httpprefix /gsdl dans le fichier de configuration gsdlsite met en place les mÃªmes conventions pour le logiciel Greenstone.</Text>
+<Text id="257">httpimg est l'adresse web de CProgram Filesgsdlimages, rÃ©pertoire qui contient toutes les images (au format GIF) utilisÃ©es par l'interface. Dans toutes les installations standard de Greenstone ce sera httpprefix/images, et vous n'interviendrez pas sur cette ligne.</Text>
+<Text id="258">gwcgi est l'adresse web du programme CGI library. La plupart des serveurs web (dont Apache) n'en ont pas besoin, et cette ligne doit alors rester commentÃ©e, donc inactive. N'ÃŽtez le commentaire que si vous Ãªtes sÃ»r de vous, car cela peut poser certains problÃšmes.</Text>
+<Text id="259">maxrequests n'est utilisÃ© que par les versions de Greenstone qui ont activÃ© l'option Â«Fast-CGIÂ» lors de la compilation. La distribution binaire standard n'inclut pas cette option, car tous les serveurs web ne sont pas configurÃ©s de maniÃšre compatible. L'option Â«Fast-CGIÂ» accÃ©lÃšre l'exÃ©cution des scripts CGI en gardant l'exÃ©cutable principal en mÃ©moire entre deux invocations du logiciel, au lieu de le charger depuis le disque dur Ã  chaque requÃªte d'une page web depuis le logiciel Greenstone. Le compromis Ã  trouver est un Ã©quilibre avec la quantitÃ© de mÃ©moire utilisÃ©e, qui peut augmenter si le programme demeure longtemps en mÃ©moire. AprÃšs la gÃ©nÃ©ration de maxrequests pages web, le programme CGI rend la main, libÃ©rant ainsi toute la mÃ©moire accumulÃ©e. Pour rÃ©pondre Ã  la prochaine requÃªte provoquÃ©e par une page web, le programme CGI est alors relu depuis le disque dur, et un nouveau cycle de requÃªtes de pages dÃ©marre. La plupart des installations utilisent le protocole standard CGI, ce qui signifie qu'on peut ignorer sans crainte le paramÃštre maxrequests.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="personalizing">
+<Title>
+<Text id="260">Personnaliser son installation</Text>
+</Title>
+<Content>
+<Text id="261">La premiÃšre chose que vous aurez probablement envie de faire aprÃšs l'installation de Greenstone et la vÃ©rification de son bon fonctionnement, c'est de personnaliser la page d'accueil. Le fichier qui engendre la page d'accueil de Greenstone s'appelle home.dm, et se situe dans le sous-rÃ©pertoire macros du rÃ©pertoire oÃ¹ vous avez installÃ© Greenstone. Pour les systÃšmes Windows, la valeur par dÃ©faut est donc CProgram Filesgsdlmacroshome.dm. C'est un fichier texte qu'il faudra Ã©diter pour crÃ©er une nouvelle page d'accueil. Au lieu de l'Ã©diter, nous recommandons de crÃ©er un nouveau fichier, disons yourhome.dm (chez moi). Ce fichier ressemblera au fichier home.dm mais dÃ©finira le Â«paquetage homeÂ»Â --Â la portion activeÂ --Â un peu diffÃ©remment.</Text>
+<Text id="262">Quand on met en place une autre page d'accueil, il faut pouvoir la relier d'une faÃ§on ou d'une autre aux pages de la bibliothÃšque numÃ©rique de maniÃšre Ã  pouvoir effectuer des recherches et naviguer dans les collections sur votre systÃšme. La solution adoptÃ©e par Greenstone est d'utiliser des Â«macrosÂ». C'est la raison pour laquelle le fichier correspondant Ã  la page d'accueil a un nom qui se termine en Â«.dmÂ» et non pas en Â«.htmlÂ»Â --Â c'est un fichier Â«de macrosÂ», et non pas un fichier HTML habituel. Pas d'inquiÃ©tude cependant: le fichier de macros ne contient que de l'HTML, entremÃªlÃ© de quelques incantations mystiques expliquÃ©es ci-dessous. Le langage de macros regorge de potentialitÃ©s puissantes, et nous n'en dÃ©crivons ici qu'une faible portion (reportez-vous au Guide du dÃ©veloppeur de la bibliothÃšque numÃ©rique Greenstone pour obtenir plus d'informations Ã  son sujet).</Text>
+<Section id="example">
+<Title>
+<Text id="263">Exemple</Text>
+</Title>
+<Content>
+<Figure id="your_own_greenstone_home_page">
+<Title>
+<Text id="264">Votre propre page d'accueil de Greenstone</Text>
+</Title>
+<File width="395" height="227" url="images/Install_Fig_3.png"/>
+</Figure>
+<Text id="265">La figureÂ <CrossRef target="Figure" ref="your_own_greenstone_home_page"/> montre un exemple d'une nouvelle page d'accueil pour la bibliothÃšque numÃ©rique. Chacun des liens mentionnant Â«Cliquez iciÂ» vous emmÃšnera sur la portion correspondante de Greenstone. Cette page fut engendrÃ©e par le fichier yourhome.dm, prÃ©sentÃ© en figureÂ <CrossRef target="Figure" ref="yourhome_dm"/>.</Text>
+<Figure id="yourhome_dm">
+<Title>
+<Text id="266">Fichier yourhome.dm utilisÃ© pour crÃ©er la figureÂ <CrossRef target="Figure" ref="your_own_greenstone_home_page"/></Text>
+</Title>
+<CodeLine>package home</CodeLine>
+<CodeLine>_content_ {</CodeLine>
+<CodeLine>&lt;h2&gt;Your own Greenstone home page&lt;/h2&gt;</CodeLine>
+<CodeLine>&lt;ul&gt;</CodeLine>
+<CodeLine>&lt;table&gt;</CodeLine>
+<CodeLine>&lt;tr valign=top&gt;&lt;td&gt;Search page for the demo collection&lt;br&gt;&lt;/td&gt;</CodeLine>
+<CodeLine>      &lt;td&gt;&lt;a href="_httpquery_&amp;c=demo"&gt;Click here&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;tr&gt;&lt;td&gt;"About" page for the demo collection&lt;/td&gt;</CodeLine>
+<CodeLine>      &lt;td&gt;&lt;a href="_httppageabout_&amp;c=demo"&gt;Click here&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;tr&gt;&lt;td&gt;Preferences page for the demo collection&lt;/td&gt;</CodeLine>
+<CodeLine>      &lt;td&gt;&lt;a href="_httppagepref_&amp;c=demo"&gt;Click here&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;tr&gt;&lt;td&gt;Home page&lt;/td&gt;</CodeLine>
+<CodeLine>      &lt;td&gt;&lt;a href="_httppagehome_"&gt;Click here&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;tr&gt;&lt;td&gt;Help page&lt;/td&gt;</CodeLine>
+<CodeLine>      &lt;td&gt;&lt;a href="_httppagehelp_"&gt;Click here&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;tr&gt;&lt;td&gt;Administration page&lt;/td&gt;</CodeLine>
+<CodeLine>      &lt;td&gt;&lt;a href="_httppagestatus_"&gt;Click here&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;tr&gt;&lt;td&gt;The Collector&lt;/td&gt;</CodeLine>
+<CodeLine>      &lt;td&gt;&lt;a href="_httppagecollector_"&gt;Click here&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</CodeLine>
+<CodeLine>&lt;/table&gt;</CodeLine>
+<CodeLine>&lt;/ul&gt;</CodeLine>
+<CodeLine>}</CodeLine>
+<CodeLine># if you hate the squirly green bar down the left-hand side of the</CodeLine>
+<CodeLine># page, uncomment these lines:</CodeLine>
+<CodeLine># _header_ {</CodeLine>
+<CodeLine># }</CodeLine>
+</Figure>
+<Text id="267">Vous pouvez utiliser la figureÂ <CrossRef target="Figure" ref="yourhome_dm"/> comme un patron pour crÃ©er votre propre page d'accueil de Greenstone. Pour simplifier, il dÃ©finit une macro Â«contentÂ», et les accolades renferment de l'HTML ordinaire, ainsi que toute commande de mise en forme HTML, pour inclure le contenu que vous souhaitez voir apparaÃ®tre sur la page. Le texte Ã©tant de l'HTML standard, vous pouvez si vous le souhaitez inclure des liens hypertexte et utiliser toutes les autres fonctionnalitÃ©s du HTML.</Text>
+<Text id="268">Pour relier votre nouvelle page d'accueil Ã  d'autres pages de la bibliothÃšque numÃ©rique, vous devrez utilisez une formule magique appropriÃ©e. Dans ce langage de macros, les formules magiques sont entourÃ©es de caractÃšres de soulignementÂ --Â vous pouvez en voir dans la figureÂ <CrossRef target="Figure" ref="yourhome_dm"/>. Par exemple,<i>_httppagehome_</i>vous emmÃšne sur la page d'accueil,<i>_httppagehelp_</i>vers la page d'aide, etc. Dans certains cas il vous faudra prÃ©ciser le nom d'une collection. La chaÃ®ne qui suit,<i>_httpquery_&amp;c=demo</i>, donne la page de recherche pour la collection Â«DemoÂ»; dans le cas d'autres collections vous remplacerez la chaÃ®ne Â«<i>demo</i>Â» par le nom de la collection dÃ©sirÃ©e.</Text>
+<Text id="269">La macro<i>_content_</i>contient directement du HTML. On peut placer n'importe quel code HTML dans une dÃ©finition de macro. Cependant, les caractÃšres spÃ©ciaux<i>{</i>,<i>}</i>,<i>\</i>, et<i>_</i>devront Ãªtre prÃ©cÃ©dÃ©s d'une barre oblique inversÃ©e (backslash, c'est-Ã -dire Â«Â») pour leur Ã©viter d'Ãªtre interprÃ©tÃ©s par l'interprÃ©teur du langage de macros.</Text>
+<Text id="270">Vous remarquerez que la dÃ©finition de macro<i>_content_</i>ne contient ni en-tÃªte ni pied de page HTML. Si vous souhaitez intervenir sur ces Ã©lÃ©ments dans votre page d'accueil, ce sont les macros<i>_header_</i>et/ou<i>_footer_</i>qu'il vous faudra personnaliser respectivement, en les ajoutant Ã  votre fichier yourhome.dm sous la forme</Text>
+<CodeLine>_macroname_ {</CodeLine>
+<CodeLine>...</CodeLine>
+<CodeLine>}</CodeLine>
+<Text id="271">Par exemple, la barre verte ondulante sur la gauche des pages Greenstone est dÃ©finie dans la macro<i>_header_</i>, et elle disparaÃ®tra si on dÃ©clare cette macro comme Ã©tant vide, comme indiquÃ© Ã  la fin de la figureÂ <CrossRef target="Figure" ref="yourhome_dm"/>.</Text>
+</Content>
+</Section>
+<Section id="how_to_make_it_work">
+<Title>
+<Text id="272">Mise en place</Text>
+</Title>
+<Content>
+<Text id="273">Il faut informer Greenstone de l'existence de la nouvelle page d'accueil, de nom yourhome.dm. Le systÃšme charge les fichiers de macros spÃ©cifiÃ©s dans le fichier de configuration principal main.cfg, c'est pourquoi il faut y indiquer tout nouveau fichier crÃ©Ã©. Les collisions de noms sont gÃ©rÃ©es comme on pourrait s'y attendre: les dÃ©finitions les plus rÃ©centes ont la prioritÃ©.</Text>
+<Text id="274">Ainsi, pour faire en sorte que le logiciel de bibliothÃšque numÃ©rique Greenstone utilise la page d'accueil de la figureÂ <CrossRef target="Figure" ref="your_own_greenstone_home_page"/> en lieu et place de la page par dÃ©faut, il faut commencer par placer le fichier yourhome.dm de la figureÂ <CrossRef target="Figure" ref="yourhome_dm"/> dans le rÃ©pertoire macros. Il faut ensuite Ã©diter le fichier de configuration main.cfg et y remplacer home.dm par yourhome.dm dans la liste des fichiers de macros chargÃ©s au dÃ©marrage.</Text>
+</Content>
+</Section>
+<Section id="redirecting_a_url_to_greenstone">
+<Title>
+<Text id="275">Renvoyer une URL vers Greenstone</Text>
+</Title>
+<Content>
+<Text id="276">Vous Ã©prouverez peut-Ãªtre l'envie de rediriger une URL plus pratique vers le CGI de Greenstone. Sur notre systÃšme, par exemple, l'URLhttp://nzdl.org(qui est un raccourci pourhttp://nzdl.org/index.html) est renvoyÃ©e vershttp://nzdl.org/cgi-bin/library. C'est la directive Redirect qui s'occupe de cela pour le serveur web Apache. Comme les autres directives, elle prend place dans le fichier de configuration CProgram FilesApache GroupApacheconfhttpd.conf. Pour renvoyer l'URLhttp://www.monserveur.comvershttp://www.monserveur.com/cgi-bin/library, ajoutez la ligne suivante dans le fichier httpd.conf:</Text>
+<CodeLine>Redirect /index.html http://www.yourserver.com/cgi-bin/library</CodeLine>
+<Text id="277">Vous pourrez ensuite atteindre votre systÃšme de bibliothÃšque numÃ©rique directement depuis l'URLhttp://www.monserveur.com. Si vous souhaitez plutÃŽt que ce soit l'URLhttp://www.monserveur.com/greenstonequi soit renvoyÃ©e vershttp://www.monserveur.com/cgi-bin/library, c'est la ligne suivante qu'il faudra inclure dans le fichier httpd.conf:</Text>
+<CodeLine>Redirect /greenstone http://www.yourserver.com/cgi-bin/library</CodeLine>
+<Text id="278">Si votre ordinateur ne dispose pas de nom dans le DNS (ou systÃšme de noms), tel que Â«www.monserveur.comÂ» dans l'exemple donnÃ© ci-dessus, il suffit de remplacerwww.monserveur.compar localhostdans toutes les lignes d'exemple. Tant que le navigateur et le serveur web fonctionnent sur la mÃªme machineÂ --Â ce qui est sÃ»rement le cas si votre ordinateur ne dispose pas de nom dans le DNSÂ --Â l'effet obtenu sera exactement le mÃªme.</Text>
+<Text id="279">Au lieu de placer les directives de redirection dans le fichier httpd.conf, on peut tout aussi bien les placer dans un fichier appelÃ© .htaccess, et placÃ© dans le rÃ©pertoire racine des documents du serveur web. Cette solution prÃ©sente mÃªme deux avantages sur la prÃ©cÃ©dente. D'abord, les modifications apportÃ©es au fichier .htaccess sont immÃ©diatement actives, alors qu'il faut redÃ©marrer le serveur web Apache pour observer les effets de changements apportÃ©s au fichier httpd.conf. Ensuite, il faut gÃ©nÃ©ralement Ãªtre connectÃ© en tant que l'utilisateur Â«rootÂ» sur les systÃšmes Unix pour pouvoir Ã©diter le fichier httpd.conf, mais ce n'est souvent pas le cas du fichier .htaccess.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="appendix_associated_software">
+<Title>
+<Text id="280">Logiciels associÃ©s</Text>
+</Title>
+<Content>
+<Text id="281">Voici comment obtenir les paquetages logiciels mentionnÃ©s dans ce document.</Text>
+<Section id="apache_webserver">
+<Title>
+<Text id="282">Le serveur web Apache</Text>
+</Title>
+<Content>
+<Text id="283">Toutes les versions de Greenstone, Ã  l'exception de la version bibliothÃšque locale pour Windows, requiÃšrent un serveur web externe. De nombreuses installations, et en particulier les plus volumineuses, disposeront dÃ©jÃ  d'un serveur web. Si vous utilisez Linux, Apache se trouve peut-Ãªtre sur votre cÃ©dÃ©rom sans avoir Ã©tÃ© sÃ©lectionnÃ© lors de la procÃ©dure d'installation. Le serveur web Apache, disponible Ã  l'URLwww.apache.org, est libre et facile Ã  installer.</Text>
+</Content>
+</Section>
+<Section id="perl">
+<Title>
+<Text id="284">Perl</Text>
+</Title>
+<Content>
+<Text id="285">Pour construire des collections avec Greenstone il faut disposer du langage Perl, version 5 ou ultÃ©rieure. Dans le cas des systÃšmes Windows, nous recommandons ActivePerl, disponible surwww.activestate.com. La plupart des systÃšmes Unix disposeront dÃ©jÃ  d'une installation de Perl mais dans le cas contraire, vous en trouverez le code source ainsi que des binaires pour de nombreuses plates-formes Unix, le tout librement tÃ©lÃ©chargeable, Ã  l'URLwww.perl.com.</Text>
+</Content>
+</Section>
+<Section id="gcc">
+<Title>
+<Text id="286">GCC</Text>
+</Title>
+<Content>
+<Text id="287">La version Unix de Greenstone se compile avec le compilateur C++ de GNU, GCC. Greenstone utilise intensivement la bibliothÃšque standard de patrons pour C++, STL (nous avons remarquÃ© qu'elle Ã©tait cassÃ©e sur d'anciennes versions GCC; veuillez nous signaler tout problÃšme relatif Ã  STL que vous rencontreriez). Prenez note du fait que cette version de Greenstone ne compilera pas avec la version 3.0 de GCC.</Text>
+</Content>
+</Section>
+<Section id="gdbm">
+<Title>
+<Text id="288">GDBM</Text>
+</Title>
+<Content>
+<Text id="289">Toutes les versions de Greenstone utilisent GDBM, le gestionnaire de bases de donnÃ©es de GNU. Il est fourni avec toutes les versions Windows de Greenstone et installÃ© automatiquement pendant la procÃ©dure d'installation. Les systÃšmes Linux en disposant dÃ©jÃ , nous ne le fournissons pas pour ces derniers. La plupart des autres systÃšmes Unix en disposent, mais si nÃ©cessaire vous pourrez le tÃ©lÃ©charger depuis l'URLwww.gnu.org.</Text>
+</Content>
+</Section>
+<Section id="java_runtime_environment">
+<Title>
+<Text id="290">Environnement Java Runtime</Text>
+</Title>
+<Content>
+<Text id="291">Pour utiliser "Greenstone Librarian Interface" (l'Interface BibliothÃ©caire de Greenstone), il est nÃ©cessaire de disposer d'une version appropriÃ©e de Java Runtine Environment. Si on n'en dispose pas, une version appropriÃ©e est incluse dans le CD-ROM; le cas Ã©chÃ©ant, le tÃ©lÃ©chargement de la derniÃšre version est possible Ã  partir dehttp://java.sun.com/j2se/downloads.html. La version 1.4.0 ou supÃ©rieure est requise.</Text>
+</Content>
+</Section>
+<Section id="java_compiler">
+<Title>
+<Text id="292">Compilateur Java</Text>
+</Title>
+<Content>
+<Text id="293">Pour compiler le code source de l'Interface du BibliothÃ©caire Greenstone, vous devez d'abord installer un Java Development Toolkit. Vous pouvez tÃ©lÃ©charger J2SE (Software Development Kit) de l'URL http://java.sun.com/j2se/downloads.html. La version 1.4.0 or supÃ©rieur est nÃ©cessaire.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+</Manual>
Index: /tags/start/gsdl-documentation/manuals/xml-source/fr/Paper_fr.xml
===================================================================
--- /tags/start/gsdl-documentation/manuals/xml-source/fr/Paper_fr.xml	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/xml-source/fr/Paper_fr.xml	(revision 13666)
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Manual>
+<Heading>
+<Text id="1"/>
+</Heading>
+<Title>
+<Text id="2">BibliothÃšque numÃ©rique Greenstone: du papier Ã  la collection</Text>
+</Title>
+<Author>
+<Text id="3">Dr Michel Loots, Dan Camarzan et Ian H. Witten</Text>
+</Author>
+<Affiliation>
+<Text id="4">ONG Human Info, Belgique<br/>Simple Words, Roumanie<br/>UniversitÃ© de Waikato, Nouvelle-ZÃ©lande</Text>
+</Affiliation>
+<Comment>
+<Text id="5">Greenstone est une suite logicielle destinÃ©e Ã  la construction et Ã  la distribution de collections de bibliothÃšques numÃ©riques. Cette suite fournit une nouvelle maniÃšre d'organiser l'information et de la publier sur l'Internet ou sur un cÃ©dÃ©rom. Greenstone est produit par le projet de bibliothÃšque numÃ©rique de Nouvelle-ZÃ©lande (dÃ©pendant de l'universitÃ© de Waikato), et dÃ©veloppÃ© et distribuÃ© en coopÃ©ration avec l'UNESCO et l'ONG Human Info.C'est un logiciel Open Source, diffusÃ© selon les termes de la licence publique gÃ©nÃ©rale de GNU, et qu'on peut obtenir Ã  l'URLhttp://greenstone.org.</Text>
+<Text id="6">Nous souhaitons nous assurer que ce logiciel fonctionne bien pour vous. Faites-nous part, en anglais, de tout problÃšme Ã  l'adresse Ã©lectronique.</Text>
+</Comment>
+<Version>
+<Text id="7">Greenstone gsdl-2.50</Text>
+</Version>
+<Date>
+<Text id="8">Mars 2004</Text>
+</Date>
+<Section id="about_this_manual">
+<Title>
+<Text id="9">Ã propos de ce manuel</Text>
+</Title>
+<Content>
+<Text id="10">Ce document explique comment crÃ©er des collections de cÃ©dÃ©roms Ã  partir de documents papier. Il dÃ©crit en dÃ©tail les procÃ©dures et les coÃ»ts relatifs Ã  la numÃ©risation et aux processus de reconnaissance optique de caractÃšres (ROC, ou OCR), de maniÃšre Ã  obtenir des textes dans un format que Greenstone puisse accepter. Il dÃ©crit aussi comment crÃ©er et Ã©diter le matÃ©riel associÃ© Ã  une collection.</Text>
+<Text id="11">Nous nous sommes efforcÃ©s d'Ãªtre aussi clairs et complets que possible dans nos explication. Toute marque commerciale mentionnÃ©e ne l'est que dans un but d'illustration, et cela ne signifie en rien que nous conseillions, favorisions ou recommandions ce produit d'une quelconque maniÃšre.</Text>
+</Content>
+</Section>
+<Section id="companion_documents">
+<Title>
+<Text id="12">Documents d'accompagnement</Text>
+</Title>
+<Content>
+<Text id="13">L'ensemble des documents de Greenstone comprend cinq volumes:</Text>
+<BulletList>
+<Bullet>
+<Text id="14">Guide d'installation de la bibliothÃšque numÃ©rique Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="15">Guide de l'utilisateur de la bibliothÃšque numÃ©rique Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="16">Guide du dÃ©veloppeur de la bibliothÃšque numÃ©rique Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="17">BibliothÃšque numÃ©rique Greenstone: du papier Ã  la collection (<i>ce document-ci</i>)</Text>
+</Bullet>
+<Bullet>
+<Text id="18">BibliothÃšque numÃ©rique Greenstone: Utilisation de "L'organizer"</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Section>
+<Section id="acknowledgements">
+<Title>
+<Text id="19">Remerciements</Text>
+</Title>
+<Content>
+<Text id="20">L'opÃ©ration de numÃ©risation, l'Organizer et tout le savoir-faire relatif Ã  la crÃ©ation de collections Ã  but non lucratif par le fruit d'un travail de collaboration furent dÃ©veloppÃ©s par Michel Loots, docteur en mÃ©decine, membre des projets Human Info NGO et HumanityCD, et par Dan Camarzan de Simple Words, ainsi que par leurs collaborateurs de Brasov, en Roumanie.</Text>
+<Text id="21">Le logiciel Greenstone a vu le jour grÃ¢ce Ã  un effort de collaboration entre de nombreuses personnes. Rodger McNab et Stefan Boddie en sont les principaux architectes et dÃ©veloppeurs. Des contributions ont Ã©tÃ© faites par David Bainbridge, George Buchanan, Hong Chen, Michael Dewsnip, Katherine Don, Elke Duncker, Carl Gutwin, Geoff Holmes, Dana McKay, John McPherson, Craig Nevill-Manning, Dynal Patel, Gordon Paynter, Bernhard Pfahringer, Todd Reed, Bill Rogers, John Thompson, et Stuart Yeates. D'autres membres du Projet de bibliothÃšque numÃ©rique de Nouvelle-ZÃ©lande ont Ã©galement donnÃ© des conseils et inspirÃ© les concepteurs du systÃšme: Mark Apperley, Sally Jo Cunningham, Steve Jones, Te Taka Keegan, Michel Loots, Malika Mahoui, et Lloyd Smith. Nous remercions aussi tous ceux qui ont contribuÃ© au dÃ©veloppement des modules sous licence GNU GPL qui font partie de cette distribution: MG, GDBM, PDFTOHTML, PERL, WGET, WVWARE, XLHTML.</Text>
+</Content>
+</Section>
+<Chapter id="introduction">
+<Title>
+<Text id="22">Introduction</Text>
+</Title>
+<Content>
+<Text id="23">L'un des objectifs du logiciel de bibliothÃšque numÃ©rique Greenstone est de permettre Ã  des entitÃ©s telles que des universitÃ©s, des agences des Nations Unies, des organisations non gouvernementales, des associations Ã  but non lucratif, ou des gouvernements, de crÃ©er des collections variÃ©es d'informations qui pourront Ãªtre diffusÃ©es en ligne ou sur cÃ©dÃ©rom.</Text>
+<Text id="24">Les Ã©tapes Ã  suivre seront typiquement:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="25">SÃ©lection des documents Ã  inclure</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="26">S'assurer des atorisations d'utilisation de ces documents (droits d'auteurs et copyrights) dans la bibliothÃšque numÃ©rique</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="27">NumÃ©risation et ROC des documents papier non disponibles sous forme numÃ©rique de maniÃšre Ã  disposer d'un format numÃ©rique parfait</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="28">Conversion de tous les documents dans un format (comprenant texte et images) qu'il est possible d'importer dans Greenstone (de prÃ©fÃ©rence HTML ou Microsoft Word, mais d'autres formats sont Ã©galement possibles, et traitÃ©s plus ou moins prÃ©cisÃ©ment par un Â«greffonÂ» (plugin) qui leur est propre (voir Ã  ce sujet le Guide de l'utilisateur de la bibliothÃšque numÃ©rique Greenstone))</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="29">Ãtiquetage des chapitres, paragraphes et images des documents numÃ©riques</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="30">Organisation de la collection sous forme d'une bibliothÃšque numÃ©rique structurÃ©e de maniÃšre optimale</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="31">Construction de la bibliothÃšque numÃ©rique Ã  l'aide du logiciel Greenstone</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="32">Pressage et distribution de la collection sur cÃ©dÃ©rom et/ou distribution sur l'Internet</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="33">Pour crÃ©er une collection numÃ©rique, les publications doivent Ãªtre disponibles dans un format numÃ©rique. Si des livres, revues ou d'autres documents ne sont disponibles que sous forme de papier, il faudra les numÃ©riser et les traiter sous un format lisible par ordinateur (Ã©tape iii). GÃ©nÃ©ralement on procÃšde par reconnaissance optique de caractÃšres (ROC, ou OCR), mais parfois on saisit les documents Ã  nouveau, au clavier. Ce processus est dÃ©crit dans les sectionsÂ 2Ã Â 4du prÃ©sent manuel.</Text>
+<Text id="34">L'Ã©tape v active les diffÃ©rentes portions d'un document qui pourront Ãªtre sÃ©lectionnÃ©es indÃ©pendamment et affichÃ©es par les lecteurs dans la bibliothÃšque rÃ©sultante, alors que l'Ã©tape vi correspond Ã  l'affectation d'attributs Ã  des documents tels que les catÃ©gories de thÃšmes, de mots-clefs, et les donnÃ©es bibliographiques, utilisÃ©es pour le classement et la recherche dans la bibliothÃšque. Ces Ã©tapes sont traitÃ©es au chapitreÂ 5de ce manuel.</Text>
+<Text id="35">Ce manuel prÃ©sente les nombreux problÃšmes qui se posent lors du processus d'Ã©dition et de crÃ©ation d'une collection Ã  partir de documents papier. Avant de poursuivre la lecture, posez-vous les questions suivantes:</Text>
+<BulletList>
+<Bullet>
+<Text id="36">Quel but poursuit la collection?</Text>
+</Bullet>
+<Bullet>
+<Text id="37">Quel public est ciblÃ©?</Text>
+</Bullet>
+<Bullet>
+<Text id="38">Quelle couverture gÃ©ographiqueÂ --Â locale, rÃ©gionale, mondiale?</Text>
+</Bullet>
+<Bullet>
+<Text id="39">Combien de documents seront rendus disponibles?</Text>
+</Bullet>
+<Bullet>
+<Text id="40">Combien de pages?</Text>
+</Bullet>
+<Bullet>
+<Text id="41">Quelle quantitÃ© de contenus graphiques?</Text>
+</Bullet>
+<Bullet>
+<Text id="42">Le contenu se divise-t-il en portions que seul un public limitÃ© consultera et en portions Ã  dissÃ©miner plus largement?</Text>
+</Bullet>
+<Bullet>
+<Text id="43">Les documents sont-ils dÃ©jÃ  disponibles sous forme Ã©lectronique?</Text>
+</Bullet>
+<Bullet>
+<Text id="44">Si tel est le cas, sous quels formats? (remarquez au passage que des fichiers au format PDF ne sont pas toujours Ã©quivalents Ã  leur contenu textuel sous forme numÃ©rique, puisqu'ils ne contiennent souvent que des images, une par page)</Text>
+</Bullet>
+<Bullet>
+<Text id="45">Quels sont les droits qui s'appliquent aux documents?</Text>
+</Bullet>
+<Bullet>
+<Text id="46">Qui possÃšde des droits?</Text>
+</Bullet>
+<Bullet>
+<Text id="47">Existe-t-il d'autres organisations ciblant le mÃªme public?</Text>
+</Bullet>
+<Bullet>
+<Text id="48">Souhaitez-vous collaborer avec d'autres groupes?</Text>
+</Bullet>
+<Bullet>
+<Text id="49">Quel est le budget global du projet?</Text>
+</Bullet>
+<Bullet>
+<Text id="50">De quelles ressources humaines (en hommes-mois) disposez-vous pour la coordination, l'Ã©dition, la numÃ©risation et la programmation?</Text>
+</Bullet>
+<Bullet>
+<Text id="51">De combien d'ordinateurs disposez-vous pour ce projet?</Text>
+</Bullet>
+<Bullet>
+<Text id="52">Combien de cÃ©dÃ©roms souhaitez-vous distribuer? </Text>
+</Bullet>
+<Bullet>
+<Text id="53">Seront-ils gratuits ou payants? </Text>
+</Bullet>
+</BulletList>
+</Content>
+</Chapter>
+<Chapter id="scanners_and_scanning">
+<Title>
+<Text id="54">Les scanners et la numÃ©risation</Text>
+</Title>
+<Content>
+<Text id="55">La premiÃšre Ã©tape dans la conversion de documents papier en une collection pour bibliothÃšque numÃ©rique est d'obtenir des images de toutes les pages de toutes les publications sous forme numÃ©rique. L'Ã©tape suivante consiste Ã  appliquer une reconnaissance optique de caractÃšres (ROC, ou OCR), pour la rÃ©ussite de laquelle il est essentiel de disposer d'images propres et de bonne qualitÃ©. Le processus de numÃ©risation utilise un scanner qui travaille Ã  une rÃ©solution minimale de 300 dpi (points par pouce, ou dots per inch). La plupart des numÃ©risations peuvent se faire en noir et blanc, mais en prÃ©sence d'illustrations en couleurs il faut utiliser un scanner couleur. Dans la plupart des cas les couvertures des livres sont en couleurs et il faudra les numÃ©riser en tant que photographie couleur.</Text>
+<Section id="scanners">
+<Title>
+<Text id="56">Les scanners</Text>
+</Title>
+<Content>
+<Text id="57">On trouve des scanners Ã  tous les prix, de toutes tailles et de toutes formes. Ils coÃ»tent de 100$ pour les scanners Ã  plat Ã  50Â 000$ pour de gros scanners industriels de fabricants tels que Bell &amp; Howell<FootnoteRef id="1"/>. On trouve de nombreux sites web qui proposent de nombreux scanners Ã  vendre. Vous les trouverez facilement en tapant le mot-clef Â«scannerÂ» dans des moteurs de recherche tels que Google, Altavista, ou Yahoo. </Text>
+<Text id="58">Le format de sortie des scanners est un fichier informatique dont le format est souvent TIFF ou bitmap. Le meilleur format est le TIFF IV compressÃ©: une page numÃ©risÃ©e et convertie en ce format n'occupe en moyenne que 50 kilo-octets, Ã  comparer aux 2 mÃ©ga-octets qu'elle occuperait sous forme bitmap non compressÃ©e.</Text>
+<Subsection id="low-cost_flat-bed_scanner">
+<Title>
+<Text id="59">Scanners Ã  plat de bas de gamme</Text>
+</Title>
+<Content>
+<Text id="60">Les scanners Ã  plat sont les moins onÃ©reux et les plus communs. De nombreuses marques en proposent: HP, Agfa, Acer, etc. Les prix s'Ã©talent de 100 Ã  300$. On peut numÃ©riser Ã  la fois des images en noir et blanc ou en couleurs. Le faible prix permet d'Ã©quiper chaque ordinateur de son propre scanner.</Text>
+<Text id="61">Ces scanners ont pour inconvÃ©nients une qualitÃ© moyenne du rÃ©sultat, une faible vitesse de numÃ©risation, une fiabilitÃ© rÃ©duite quand la tempÃ©rature s'Ã©lÃšve, et des pannes frÃ©quentes. Il faut numÃ©riser les pages manuellement, une Ã  une. Chaque page doit Ãªtre placÃ©e avec attention sur la vitre de numÃ©risation de maniÃšre Ã  obtenir un alignement correct. Ces scanners ont une faible productivitÃ©. Bien que les fabricants prÃ©tendent qu'on peut scanner une page en moins d'une minute, il est rare dans la pratique de pouvoir scanner plus de douze pages en une heure. Le processus de numÃ©risation monopolise l'ordinateur utilisÃ©.</Text>
+<Text id="62">C'est pourquoi de tels scanners ne sont utiles que pour des petits travaux de numÃ©risation, avec de 200 Ã  400 pages par mois de maniÃšre rÃ©guliÃšre, ou de 1000 Ã  2000 pages de maniÃšre exceptionnelle.</Text>
+</Content>
+</Subsection>
+<Subsection id="low-end_scanner_with_sheet_feeder">
+<Title>
+<Text id="63">Scanners de bas de gamme avec chargeur</Text>
+</Title>
+<Content>
+<Text id="64">Ces scanners coÃ»tent de 500 Ã  1200$. On peut insÃ©rer, scanner et traiter de 10 Ã  50 pages d'un coup: l'opÃ©rateur ne doit pas rester constamment aux cÃŽtÃ©s de la machine. Cela permet d'atteindre une productivitÃ© de 150 Ã  200 pages par jour. Ces scanners sont plus robustes et tombent en panne moins souventÂ --Â ils permettent gÃ©nÃ©ralement de traiter de 30 Ã  50Â 000 pages avant de nÃ©cessiter une rÃ©paration.</Text>
+<Text id="65">Ils ont pour inconvÃ©nient de ne numÃ©riser qu'une face de chaque feuille Ã  la foisÂ --Â il faut retourner la pile de feuilles et la numÃ©riser de nouveau pour obtenir les versos. Ceci crÃ©e des problÃšmes car les chargeurs causent souvent des ennuis des bourrages papier.</Text>
+<Text id="66">Ces scanners sont utiles pour des volumes de 1500 Ã  3000 pages par mois.</Text>
+</Content>
+</Subsection>
+<Subsection id="color_scanners">
+<Title>
+<Text id="67">Scanners couleur</Text>
+</Title>
+<Content>
+<Text id="68">Toute opÃ©ration de numÃ©risation se heurte tÃŽt ou tard au problÃšme des images couleur, c'est pourquoi il faudra toujours disposer d'un scanner couleur. De maniÃšre gÃ©nÃ©rale, moins de 5% de toute publication contient des images couleur, sans compter la couverture. C'est pourquoi un scanner Ã  plat tel que dÃ©crit ci-dessus suffira. Nous conseillons de choisir un scanner capable d'une rÃ©solution de 600 dpi.</Text>
+</Content>
+</Subsection>
+<Subsection id="professional_duplex_scanners">
+<Title>
+<Text id="69">Scanners professionnels bi-faces</Text>
+</Title>
+<Content>
+<Text id="70">Les scanners professionnels sont des machines fiables et industrielles, capables de traiter un grand volumeÂ --Â de 2 Ã  10Â 000 pages par jour. Ils disposent d'un systÃšme de chargeur automatique Ã  plateau qui peut recevoir des paquets de 50 Ã  200 pages. Les meilleurs et les plus rapides sont des machines duplex qui peuvent numÃ©riser les deux faces d'une feuille d'un coup.</Text>
+<Text id="71">Les scanners professionnels duplex ont besoin d'un ordinateur puissant Ã©quipÃ© d'un disque dur de 10 Ã  20 giga-octets. Les prix s'Ã©talent de 5 Ã  50Â 000$. Par exemple, le scanner duplex Canon DR-6020 coÃ»te 5000$ et peut traiter des documents recto-verso. Il a une capacitÃ© d'environ 2000 pages par jour et une durÃ©e de vie de 600 Ã  800Â 000 pages. Les scanners Bell &amp; Howell et Fujitsu coÃ»tent de 10 Ã  50Â 000$ et ont une durÃ©e de vie de plusieurs millions de pages.</Text>
+<Text id="72">Les scanners Ã  micro-fiches coÃ»tent de 15Â 000$ pour une unitÃ© semi-automatique Ã  80Â 000$ pour une unitÃ© entiÃšrement automatisÃ©e.</Text>
+</Content>
+</Subsection>
+<Subsection id="scanning_programs">
+<Title>
+<Text id="73">Logiciels de numÃ©risation</Text>
+</Title>
+<Content>
+<Text id="74">Tous les scanners sont fournis avec leur propre logiciel, qui doit donc Ãªtre installÃ© sur l'ordinateur qui pilote le scanner. Certains scanners disposent d'une carte Ã  enficher sur l'ordinateur pour accÃ©lÃ©rer l'opÃ©ration de numÃ©risation.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="preparing_the_documents">
+<Title>
+<Text id="75">La prÃ©paration des documents</Text>
+</Title>
+<Content>
+<Text id="76">Avant d'Ãªtre numÃ©risÃ©s, les documents doivent Ãªtre correctement prÃ©parÃ©s. Il faut dÃ©poussiÃ©rer, sÃ©cher, enlever les agrafes, et aplanir les pages pliÃ©es.</Text>
+<Text id="77">Il faut ÃŽter la reliure des livres par une coupure nette, droite et prÃ©cise. Les livres des bibliothÃšques devront souvent Ãªtre reliÃ©s Ã  nouveau, auquel cas la plus grande attention est nÃ©cessaire lors de cette opÃ©ration, ce qui facilitera la mise en place de la nouvelle reliure.</Text>
+<Text id="78">Pour un nombre limitÃ© de documents, la coupe peut se faire Ã  la rÃšgle et au cutter. Faites attention Ã  vos mains! Pour des plus gros volumes, il existe des machines Ã  couper faites pour.</Text>
+<Text id="79">Pour des gros volumes (Ã  partir de 20 documents) nous recommandons de demander Ã  un imprimeur ou une boÃ®te Ã  copies l'autorisation d'utiliser leur massicot professionnel. N'oubliez pas d'ÃŽter toute agrafe ou trombone; ils pourraient endommager les lames.</Text>
+</Content>
+</Section>
+<Section id="the_scanning_process">
+<Title>
+<Text id="80">L'opÃ©ration de numÃ©risation</Text>
+</Title>
+<Content>
+<Text id="81">Quand on utilise le logiciel fourni avec le scanner, chaque page est numÃ©risÃ©e et transformÃ©e en image numÃ©rique au format TIFF ou bitmap. Ces images doivent alors Ãªtre stockÃ©es sur le disque dur sous des noms de fichiers habituels. La reconnaissance optique de caractÃšres dÃ©bute Ã  la fin de la numÃ©risation de tout ou partie d'un lot de documents.</Text>
+<Text id="82">Il faudra une rÃ©solution de 300 dpi pour la numÃ©risation, mÃªme si parfois 200 dpi peuvent suffire.</Text>
+<Subsection id="quality_control">
+<Title>
+<Text id="83">ContrÃŽle qualitÃ©</Text>
+</Title>
+<Content>
+<Text id="84">La numÃ©risation a pour but de passer les pages Ã  la ROC pour produire des versions traitement de texte ou HTML des publications, ou de produire des fichiers image de bonne qualitÃ© tels que des fichiers image PDF. Dans tous les cas, la qualitÃ© de la numÃ©risation est cruciale: une mauvaise qualitÃ© produira des images peu jolies, qui occuperont plus de mÃ©moire. La nettetÃ© des images affecte Ã©normÃ©ment le processus de ROC: la productivitÃ© peut chuter jusqu'Ã  40% si la qualitÃ© n'est pas au rendez-vous. Sachant que l'opÃ©ration de ROC reprÃ©sente plus de 90% du coÃ»t total de la transformation du papier en collection, on constate que la qualitÃ© de la numÃ©risation peut avoir des effets trÃšs marquÃ©s sur le coÃ»t global.</Text>
+<Text id="85">On peut amÃ©liorer la qualitÃ© du fichier TIFF en ajustant le processus de numÃ©risation Ã  chaque type de papier, en utilisant les rÃ©glages fournis par le logiciel de numÃ©risation. Les papiers relativement transparents requerront des rÃ©glages plus clairs; il faut ajuster le contraste en fonction de la qualitÃ© d'impression, etc.</Text>
+<Text id="86">Commencez par diviser les feuilles en lots de texture de papier et de qualitÃ© d'impression comparables. Faites des tests de ROC sur un Ã©chantillon du premier lot pour dÃ©terminer les rÃ©glages optimaux. NumÃ©risez ensuite tout ce lot avant de passer au suivant.</Text>
+</Content>
+</Subsection>
+<Subsection id="filename_conventions">
+<Title>
+<Text id="87">Conventions sur les noms de fichier</Text>
+</Title>
+<Content>
+<Text id="88">Attribuez Ã  chaque livre ou document un numÃ©ro de traitement ou un code unique, qui sera utilisÃ© en tant que nom du rÃ©pertoire contenant tous les fichiers TIFF relatifs au document. Selon votre systÃšme d'exploitation (DOS, Windows, Unix, Linux, etc.), vous pourrez utiliser de 8 Ã  128 caractÃšres pour les noms de fichiers. Nous vous recommandons de vous limiter Ã  8 ou 16 caractÃšres pour cet identifiant de document. Les 5 premiers caractÃšres pourront par exemple identifier le document, la lettre suivante pourra contenir un code de langue de rÃ©daction du document, et les caractÃšres restants pourront identifier la page. Par exemple, l'identifiant u7548f12.tif pourra reprÃ©senter l'image TIFF de la page 12 d'un livre Ã©crit en franÃ§ais, de code u7548.</Text>
+<Text id="89">RÃ©servez un rÃ©pertoire du disque dur aux opÃ©rations de numÃ©risation (appelons-le par exemple scanjobs). Puis crÃ©ez un sous-rÃ©pertoire pour chaque lot. CrÃ©ez Ã  nouveau un sous-rÃ©pertoire pour chaque publication, comme par exemple u7548f pour le document ci-dessus Ã©voquÃ©. Stockez toutes les images TIFF de la publication, y compris les images couleur, dans ce rÃ©pertoire.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="productivity_and_resources">
+<Title>
+<Text id="90">De la productivitÃ© et des ressources nÃ©cessaires</Text>
+</Title>
+<Content>
+<Text id="91">Ne sous-estimez pas l'ampleur de l'opÃ©ration de numÃ©risationÂ --Â et en particulier celle de la ROC qui la suivra. Il vaut mieux considÃ©rer la numÃ©risation et la ROC comme deux activitÃ©s complÃštement sÃ©parÃ©es. Les choix optimaux, tant Ã©conomiques que pratiques, seront faits indÃ©pendamment.</Text>
+<Text id="92">Les aspects auxquels rÃ©flÃ©chir incluent les investissements nÃ©cessaires en matÃ©riel (scanners et ordinateurs); la disponibilitÃ© d'un espace disque suffisant ainsi que d'assez de ressources humaines; la formation des agents; les coÃ»ts salariaux; les nombres de pages initial et final Ã  numÃ©riser, les dates maximales de fin de travaux; et les possibilitÃ©s de sous-traitance.</Text>
+<Subsection id="scanning_costs">
+<Title>
+<Text id="93">CoÃ»ts de numÃ©risation</Text>
+</Title>
+<Content>
+<Text id="94">Une dÃ©cision importante consiste Ã  trancher entre investir en achat d'Ã©quipement de numÃ©risation et effectuer toute la numÃ©risation soi-mÃªme, ou sous-traiter cette tÃ¢che Ã  une sociÃ©tÃ© spÃ©cialisÃ©e. Les critÃšres principaux sont:</Text>
+<BulletList>
+<Bullet>
+<Text id="95">urgence du travail de numÃ©risation;</Text>
+</Bullet>
+<Bullet>
+<Text id="96">nombre total de pages;</Text>
+</Bullet>
+<Bullet>
+<Text id="97">coÃ»ts salariaux des opÃ©rateurs de numÃ©risation.</Text>
+</Bullet>
+</BulletList>
+<Text id="98">Les opÃ©rateurs doivent Ãªtre extrÃªmement motivÃ©s, douÃ©s techniquement, et soucieux de qualitÃ©. </Text>
+<Text id="99">Une sociÃ©tÃ© spÃ©cialisÃ©e rÃ©clamera en moyenne 0.06$ par page. Il faut ajouter Ã  cela le coÃ»t du transfert des documents, qui peut s'Ã©lever Ã  0.03$ pour un envoi d'un pays en voie de dÃ©veloppement vers un pays dÃ©veloppÃ©, et 0.015$ pour un envoi entre pays dÃ©veloppÃ©s.</Text>
+<Text id="100">Le tableauÂ <CrossRef target="Table" ref="table_scanning_cost"/> donne une estimation du coÃ»t du processus de numÃ©risation s'il est effectuÃ© par vos soins, en utilisant diffÃ©rents types de scanners. Vous remarquerez que ces chiffres sont des estimations, et ne sont fournis qu'en tant que rÃ©fÃ©rence approximative en se fondant sur l'expÃ©rience des auteurs. Les trois premiÃšres colonnes traitent des coÃ»ts salariaux. La premiÃšre prÃ©sente la capacitÃ© en pages par mois, sur la base d'un temps plein. On trouve les ressources nÃ©cessaires en homme-mois par page en divisant le nombre mensuel d'heures travaillÃ©es par la capacitÃ© en pages par mois de la deuxiÃšme colonne. Il est prÃ©sentÃ© dans la troisiÃšme colonne, sur la base de 180 heures travaillÃ©es par mois.</Text>
+<Table id="table_scanning_cost">
+<Title>
+<Text id="101">CoÃ»t de la numÃ©risation</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="90"/>
+<th width="71">
+<Text id="102">CapacitÃ© (pages/mois)</Text>
+</th>
+<th width="75">
+<Text id="103">Heures/page (180 h/mois)</Text>
+</th>
+<th width="83">
+<Text id="104">CoÃ»t/page (4$/h)</Text>
+</th>
+<th width="60">
+<Text id="105">Achat du scanner</Text>
+</th>
+<th width="66">
+<Text id="106">DurÃ©e de vie du scanner (en pages)</Text>
+</th>
+<th width="85">
+<Text id="107">CoÃ»t du scanner (0.06$/p.)</Text>
+</th>
+</tr>
+<tr>
+<th width="90">
+<Text id="108">Scanner Ã  plat</Text>
+</th>
+<th width="71">
+<Text id="109">2 500</Text>
+</th>
+<th width="75">
+<Text id="110">0.072</Text>
+</th>
+<th width="83">
+<Text id="111">0.288$</Text>
+</th>
+<th width="60">
+<Text id="112">300$</Text>
+</th>
+<th width="66">
+<Text id="113">7 000</Text>
+</th>
+<th width="85">
+<Text id="114">5 000</Text>
+</th>
+</tr>
+<tr>
+<th width="90">
+<Text id="115">Scanner Ã  chargeur</Text>
+</th>
+<th width="71">
+<Text id="116">8 000</Text>
+</th>
+<th width="75">
+<Text id="117">0.0225</Text>
+</th>
+<th width="83">
+<Text id="118">0.09$</Text>
+</th>
+<th width="60">
+<Text id="119">800$</Text>
+</th>
+<th width="66">
+<Text id="120">30 000</Text>
+</th>
+<th width="85">
+<Text id="121">13 000</Text>
+</th>
+</tr>
+<tr>
+<th width="90">
+<Text id="122">Scanner pro. bas de gamme</Text>
+</th>
+<th width="71">
+<Text id="123">40 000</Text>
+</th>
+<th width="75">
+<Text id="124">0.0045</Text>
+</th>
+<th width="83">
+<Text id="125">0.018$</Text>
+</th>
+<th width="60">
+<Text id="126">6 000$</Text>
+</th>
+<th width="66">
+<Text id="127">600 000</Text>
+</th>
+<th width="85">
+<Text id="128">100 000</Text>
+</th>
+</tr>
+<tr>
+<th width="90">
+<Text id="129">Scanner pro. haut de gamme</Text>
+</th>
+<th width="71">
+<Text id="130">150 000</Text>
+</th>
+<th width="75">
+<Text id="131">0.0012</Text>
+</th>
+<th width="83">
+<Text id="132">0.0048$</Text>
+</th>
+<th width="60">
+<Text id="133">50 000$</Text>
+</th>
+<th width="66">
+<Text id="134">8 000 000</Text>
+</th>
+<th width="85">
+<Text id="135">833 000</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<br/>
+<Text id="136">Le prix par page s'obtient en multipliant le coÃ»t salarial horaire global dans votre cas par la deuxiÃšme colonne du tableauÂ <CrossRef target="Table" ref="table_scanning_cost"/>. Nous avons donnÃ© en exemple, dans la troisiÃšme colonne, le prix d'une numÃ©risation faite sur place avec un coÃ»t salarial de 4$ par heureÂ --Â ce qui ne comprend pas le coÃ»t des investissements.</Text>
+<Text id="137">Ces calculs supposent que le scanner est utilisÃ© pour un volume suffisant, justifiant l'investissement. Les trois derniÃšres colonnes du tableau <CrossRef target="Table" ref="table_scanning_cost"/>Â fournissent plus d'informations sur le coÃ»t du scanner Ã  proprement parler. La premiÃšre montre le coÃ»t d'achat du scanner, et la deuxiÃšme fournit sa durÃ©e de vie moyenne. La derniÃšre colonne montre le nombre de pages qu'on pourrait faire numÃ©riser par un sous-traitant, au prix de 0.06$ par page, pour le prix du scanner seul.</Text>
+<Text id="138">Bien sÃ»r, de nombreux autres facteurs guident le choix du scanner: disponibilitÃ© des fonds, souhait d'indÃ©pendance, volontÃ© de dÃ©velopper un pÃŽle de compÃ©tences local, rÃšgles des bibliothÃšques imposant une numÃ©risation locale sans possibilitÃ© de transport des livres, etc.</Text>
+<Text id="139">Ces chiffres donnent une idÃ©e du volume de pages Ã  traiter pour justifier diffÃ©rents niveaux d'investissement. Un institut ou une organisation aura rarement besoin de numÃ©riser plus de 800Â 000 pages. Ã de tels niveaux, des paramÃštres plus complexes entrent en ligne de compteÂ --Â tels que la maintenance et la possibilitÃ© de rentabiliser l'investissement en revendant des services de numÃ©risationÂ --Â paramÃštres dont nous ne traiterons pas ici.</Text>
+<Text id="140">On peut Ãªtre sÃ©duit par l'idÃ©e de dÃ©velopper une activitÃ© commerciale de numÃ©risation, surtout dans les pays en voie de dÃ©veloppement. Mais gardez Ã  l'esprit que la numÃ©risation est une activitÃ© non rÃ©currente: une fois les documents numÃ©risÃ©s, les clients ne passeront jamais une autre commande pour la numÃ©risation des mÃªmes documents, mÃªme si les relations sont excellentes. D'un point de vue commercial, il faut prÃ©voir d'intenses efforts de mercatique. Nous dÃ©conseillons aux ONG et aux autres organisations Ã  but non lucratif de s'aventurer dans un tel projet sans essais liminaires trÃšs complets et un projet financier extrÃªmement rÃ©flÃ©chi.</Text>
+<Text id="141">En conclusion, on peut dire qu'il vaut mieux sous-traiter si la quantitÃ© de pages Ã  numÃ©riser s'Ã©tale de 10 Ã  50Â 000 pages. Un scanner professionnel de bas de gamme, coÃ»tant environ 6000$, ne se justifie que s'il faut numÃ©riser plus de 100Â 000 pages. On peut aussi envisager une association de plusieurs institutions (telles que des ONG ou des bibliothÃšques) pour l'achat groupÃ© d'une telle machine.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="ocr">
+<Title>
+<Text id="142">ROC: reconnaissance optique de caractÃšres</Text>
+</Title>
+<Content>
+<Text id="143">Un systÃšme de reconnaissance optique de caractÃšres, ou ROC, transforme une image numÃ©risÃ©e en texte. Il accepte en entrÃ©e une image numÃ©rique au format TIFF ou bitmap, de prÃ©fÃ©rence propre et de bonne qualitÃ©. Il fournit en sortie un fichier de traitement de texte ou pour le web, aux formats RTF, Word, ou HTML.</Text>
+<Text id="144">La conversion de documents papier sous forme Ã©lectronique est un processus en quatre Ã©tapes:</Text>
+<BulletList>
+<Bullet>
+<Text id="145">numÃ©risation; </Text>
+</Bullet>
+<Bullet>
+<Text id="146">analyse de la mise en page;</Text>
+</Bullet>
+<Bullet>
+<Text id="147">reconnaissance;</Text>
+</Bullet>
+<Bullet>
+<Text id="148">numÃ©risation des images et des tableaux.</Text>
+</Bullet>
+</BulletList>
+<Text id="149">En suivant ces Ã©tapes, il faut effectuer des contrÃŽles qualitÃ© sur les fichiers produits, et les sauvegarder dans le format appropriÃ©.</Text>
+<Text id="150">On trouve beaucoup de bons programmes de ROC sur le marchÃ©, et leurs prix varient de 100 Ã  400$<FootnoteRef id="2"/>. On trouve par exemple, entre (nombreux) autres:</Text>
+
+<BulletList>
+<Bullet>
+<Text id="151">Read-Iris (http://www.readiris.com/)</Text>
+</Bullet>
+<Bullet>
+<Text id="152">Omnipage (http://www.omnipage.com/)</Text>
+</Bullet>
+<Bullet>
+<Text id="153">Fine-Reader (http://www.finereader.com/) </Text>
+</Bullet>
+</BulletList>
+<Text id="154">Les sites web des Ã©diteurs vous fourniront toutes les informations nÃ©cessaires, y compris la liste des revendeurs dans votre rÃ©gion. L'expÃ©rience des auteurs les amÃšne Ã  recommander pour leur bonne ergonomie les programmes Fine-Reader et Omnipage. Fine-Reader est le moins cher, Ã  environ 100$. Il est trÃšs souple, et a les options de langue les plus variÃ©es.</Text>
+<Text id="155">Il faut choisir entre effectuer la numÃ©risation et la ROC sur place, ou sous-traiter ces opÃ©rations Ã  une organisation spÃ©cialisÃ©e. Un travail sur place nÃ©cessite un scanner, un logiciel de ROC, des compÃ©tences en ROC (donc des formations), et des opÃ©rateurs soucieux de qualitÃ© et extrÃªmement motivÃ©s.</Text>
+<Section id="the_ocr_process">
+<Title>
+<Text id="156">Le processus de ROC</Text>
+</Title>
+<Content>
+<Text id="157">Le processus de ROC change d'un programme Ã  l'autre, et chacun est trÃšs long Ã  apprendre et Ã  maÃ®triser. Le manuel du logiciel expliquera ce processus en dÃ©tail. Quatre aspects mÃ©ritent qu'on leur accorde une attention particuliÃšre: le contrÃŽle qualitÃ©, les tableaux, les images, et les contenus spÃ©cialisÃ©s tels que formules, caractÃšres d'autres alphabets ou langues, etc.</Text>
+<Subsection id="quality_control_1">
+<Title>
+<Text id="158">ContrÃŽle qualitÃ©</Text>
+</Title>
+<Content>
+<Text id="159">On n'insistera jamais assez sur ce point. Il vaut mieux faire mener ces contrÃŽles qualitÃ© par des locuteurs dont la langue traitÃ©e est la langue maternelle, ou des gens maÃ®trisant parfaitement cette langue. Les meilleurs candidats se recruteront Ã  l'universitÃ© ou au lycÃ©e. Remarquons que des relecteurs plus jeunes seront capables d'une concentration plus soutenue pour ce type de travail.</Text>
+<Text id="160">On compte normalement quatre contrÃŽles qualitÃ©.</Text>
+<Text id="161">Le premier est effectuÃ© au moment de la ROC. Tout programme de ROC dispose d'un vÃ©rificateur orthographique intÃ©grÃ© qui met en valeur toutes les lettres suspectes. Il affiche en mÃªme temps l'image du mot concernÃ©, ce qui facilite le travail de vÃ©rification et de correction de l'erreur.</Text>
+<Text id="162">Le deuxiÃšme est une vÃ©rification globale du texte Ã  la fin du processus de ROC. Il arrive souvent d'oublier une page, un paragraphe, un titre de chapitre, etc. Un examen global est nÃ©cessaire pour dÃ©tecter d'Ã©ventuelles pages manquantes. Il est essentiel de vÃ©rifier les titres, les en-tÃªtes de chapitres, les paragraphes, et les tableaux.</Text>
+<Text id="163">Le troisiÃšme est une vÃ©rification orthographique utilisant Microsoft Word: ce programme dispose en effet d'un dictionnaire souvent plus sophistiquÃ© que ceux qui sont embarquÃ©s dans les programmes de ROC. En important le livre dans Word et en y effectuant une vÃ©rification orthographique, on peut trouver et corriger des erreurs supplÃ©mentaires. Veillez Ã  enseigner au vÃ©rificateur orthographique tous les mots particuliÃšrement difficiles ou sujets Ã  erreurs, ou encore les termes scientifiques et techniques communs dans le type de publication considÃ©rÃ©.</Text>
+<Text id="164">Enfin, le document complet devrait Ãªtre vÃ©rifiÃ© par un relecteur indÃ©pendant, qui en extrait des Ã©chantillons et contrÃŽle l'absence d'erreurs, de problÃšmes avec les tableaux et les images, la typographie, et l'aspect gÃ©nÃ©ral du texte rÃ©sultant. Ce n'est qu'aprÃšs cette Ã©tape qu'un livre peut Ãªtre dÃ©clarÃ© apte Ã  la dissÃ©mination numÃ©rique.</Text>
+</Content>
+</Subsection>
+<Subsection id="tables">
+<Title>
+<Text id="165">Tableaux</Text>
+</Title>
+<Content>
+<Text id="166">Les programmes de ROC peinent Ã  traiter les tableaux. De plus, il est difficile de les vÃ©rifier: ils contiennent de nombreux chiffres, souvent avec des espaces, points ou virgules, et il est aisÃ© de dÃ©caler des cellules d'une ligne ou d'une colonne. Il leur faut un effort de concentration particulier et une relecture obstinÃ©e et intense, une vÃ©rification soigneuse, et un bon contrÃŽle qualitÃ©. On peut les traiter de trois maniÃšres extrÃªmement diffÃ©rentes.</Text>
+<Text id="167">D'abord, les tableaux peuvent Ãªtre traitÃ©s en tant qu'images. Cela implique de les numÃ©riser sous forme d'image noir et blanc et de les placer au bon endroit dans le document rÃ©sultant. C'est la solution la plus facile: aucun risque d'erreur, et le temps nÃ©cessaire est uniquement celui de la crÃ©ation de l'image. Cependant, cette solution est plus gourmande en mÃ©moire. Un autre problÃšme concerne la rÃ©solution, pas toujours suffisante lorsqu'il faut afficher de grands tableaux sur un Ã©cran d'ordinateur: si on affiche tout le tableau, il est illisible, et si on agrandit l'image (en la faisant sortir de l'Ã©cran) pour la rendre lisible, l'utilisateur doit s'y dÃ©placer pour pouvoir en lire toutes les lignes et colonnes, et manque d'une vue d'ensemble.</Text>
+<Text id="168">Ensuite, les tableaux peuvent Ãªtre recrÃ©Ã©s manuellement en crÃ©ant une table comptant le mÃªme nombre de lignes et de colonnes et en tapant les cellules une Ã  une, caractÃšre par caractÃšre.</Text>
+<Text id="169">Enfin, le tableau peut passer Ã  la ROC. C'est plus rapide que la saisie manuelle, mais prÃ©sente un plus grand risque d'erreurs. Les colonnes sont parfois fusionnÃ©es, et les points et les virgules ne sont pas bien reconnus.</Text>
+</Content>
+</Subsection>
+<Subsection id="images">
+<Title>
+<Text id="170">Images</Text>
+</Title>
+<Content>
+<Text id="171">Les publications contiennent trois grands types d'images diffÃ©rents:</Text>
+<BulletList>
+<Bullet>
+<Text id="172">croquis en noir et blanc;</Text>
+</Bullet>
+<Bullet>
+<Text id="173">photographies en noir et blanc;</Text>
+</Bullet>
+<Bullet>
+<Text id="174">photographies en couleurs.</Text>
+</Bullet>
+</BulletList>
+<Text id="175">Les croquis noir et blanc se numÃ©risent en mode Â«croquisÂ» et seront sauvegardÃ©s au format GIF ou PNG. Les photographies noir et blanc se numÃ©risent en mode Â«niveaux de grisÂ» et seront sauvegardÃ©es au format GIF ou JPEG. Les photographies couleur se numÃ©risent en mode Â«couleurÂ» et seront sauvegardÃ©es au format JPEG. Dans la plupart des cas, le JPEG de qualitÃ© moyenne fournit une rÃ©solution suffisante.</Text>
+<Text id="176">Pour la plupart des collections, ce sont les images qui consomment le plus de place sur le disque dur ou sur le cÃ©dÃ©rom. C'est pourquoi il est important d'optimiser chaque image du point de vue de la clartÃ© et de la lisibilitÃ©, tout en minimisant sa taille. Vous Ã©conomiserez de l'espace disque en nÃ©gligeant de reprendre tout ou partie des images, de prÃ©fÃ©rence celles qui ne sont pas pertinentes par rapport au texte.</Text>
+<Text id="177">Il faut numÃ©riser les images sÃ©parÃ©ment, une Ã  une. Nous vous recommandons de donner aux fichiers image un nom consistant en les 5 ou 6 premiers caractÃšres utilisÃ©s pour identifier le document, suivis du numÃ©ro de page oÃ¹ apparaÃ®t l'image. Une autre solution, dans l'hypothÃšse oÃ¹ chaque document dispose de son propre rÃ©pertoire, est de se contenter d'utiliser la lettre p, suivie du numÃ©ro de page de l'image. Si plusieurs images apparaissent sur la mÃªme page, on ajoutera au nom de fichier une lettre supplÃ©mentaire: a, b, c... Si par exemple une image JPEG apparaÃ®t page 36 de la publication u7548f ci-dessus Ã©voquÃ©e, elle sera placÃ©e dans un fichier appelÃ© u7548e36.jpg ou p36.jpg.</Text>
+<Text id="178">AprÃšs la numÃ©risation des images, on peut mettre au travail les programmes de traitement par lots (batch), afin de changer les tailles ou d'amÃ©liorer la qualitÃ© de toutes les images en une seule passe.</Text>
+</Content>
+</Subsection>
+<Subsection id="specialized_material">
+<Title>
+<Text id="179">Contenus spÃ©cialisÃ©s</Text>
+</Title>
+<Content>
+<Text id="180">De nombreux documents renferment des contenus spÃ©cialisÃ©s tels que des caractÃšres spÃ©ciaux, des formules, ou des pages difficiles. Les caractÃšres spÃ©ciaux sont souvent issus de langues Ã©trangÃšres ou pourvus de signes diacritiques. Il faut alors utiliser l'option de langue du programme de ROC utilisÃ© et lui indiquer la langue Ã  reconnaÃ®tre. Les formules devront Ãªtre recrÃ©Ã©es manuellement. Parfois cette opÃ©ration n'est pas possible dans le programme de ROC, et uniquement faisable dans un traitement de texte tel que Microsoft Word. Les pages difficiles, au contenu complexe ou si endommagÃ©es qu'on n'a pas pu en obtenir une image nette lors du processus de numÃ©risation, devront parfois Ãªtre retapÃ©es.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="productivity_and_resources_1">
+<Title>
+<Text id="181">De la productivitÃ© et des ressources nÃ©cessaires</Text>
+</Title>
+<Content>
+<Text id="182">Comme on l'a dÃ©jÃ  signalÃ©, il ne faut pas sous-estimer la difficultÃ© du processus de ROC. MÃªme si ses aspects Ã©conomiques et pratiques doivent Ãªtre traitÃ©s indÃ©pendamment de ceux relevant de la numÃ©risation, on trouve des points communs: le nÃ©cessaire investissement en ordinateurs; la disponibilitÃ© en ressources humaines et leur encadrement; la formation des opÃ©rateurs; les coÃ»ts salariaux; le nombre total de pages Ã  traiter; et la possibilitÃ© de sous-traiter des documents.</Text>
+<Text id="183">Dans cette section, nous faisons partager notre expÃ©rience d'opÃ©rations de ROC en Belgique, en Roumanie et en Inde. Toutes les Ã©tudes de cas, les calculs et les chiffres prÃ©sentÃ©s font les hypothÃšses implicites de situations moyennes et de documents de difficultÃ© standard (incluant images et tableaux) tels qu'on en trouve dans la plupart des archives et des bibliothÃšques, des rÃ©sultats de trÃšs bonne qualitÃ©, et une opÃ©ration Ã  moyen ou long terme.</Text>
+<Subsection id="intensive_ocr">
+<Title>
+<Text id="184">La ROC intensive</Text>
+</Title>
+<Content>
+<Text id="185">La ROC est une activitÃ© difficile, qui requiert une grande concentration et beaucoup de compÃ©tences. Avant d'atteindre une productivitÃ© et une qualitÃ© de croisiÃšre, il faut prÃ©voir une pÃ©riode d'apprentissage d'environ six semaines.</Text>
+<Text id="186">Les premiÃšres heures de chaque jour sont souvent les plus fructueuses en matiÃšre de rÃ©sultats et de productivitÃ©. AprÃšs trois heures de travail de ROC, la productivitÃ© dÃ©croÃ®t trÃšs rapidement, jusqu'Ã  50% du niveau initial. AprÃšs six heures de travail, la plupart des gens sont trÃšs fatiguÃ©s.</Text>
+<Text id="187">La mÃªme courbe se dessine au niveau supÃ©rieur, celui des semaines. Les premiÃšres semaines, tout le monde travaille vite et bien, mais vient un moment oÃ¹ les deux tiers des agents s'ennuient et deviennent frustrÃ©s. Ces personnes abandonnent le projet ou se mettent Ã  travailler de faÃ§on mÃ©diocre, en quantitÃ© comme en qualitÃ©. MÃªme ceux qui passent le cap critique des 3 ou 5 semaines de travail et intÃšgrent l'Ã©quipe, partent souvent aprÃšs 6 Ã  12 mois, Ã  la recherche d'un meilleur poste.</Text>
+<Text id="188">Les remarques de la sectionÂ Section <CrossRef target="Section" ref="the_ocr_process"/> concernant le personnel sont particuliÃšrement avÃ©rÃ©es dans le cadre d'un travail de ROC intensif. Il vaut mieux faire mener les contrÃŽles qualitÃ© par des locuteurs dont la langue traitÃ©e est la langue maternelle, ou des gens maÃ®trisant parfaitement cette langue. Des relecteurs plus jeunes seront capables d'une concentration plus soutenue pour des tÃ¢ches de ROC. Empiriquement, on a constatÃ© que des personnes Ã¢gÃ©es de 18 Ã  23 ans convenaient mieux que des personnes de plus de 25 ans.</Text>
+<Text id="189">Enfin, la ROC peut Ãªtre un travail fastidieux, ce qui donne une importance exceptionnelle aux questions de motivation et de goÃ»t du travail bien fait.</Text>
+<Text id="190">Ces remarques sur la ROC mÃšnent aux prÃ©ceptes suivants:</Text>
+<BulletList>
+<Bullet>
+<Text id="191">Les jeunes gens Ã¢gÃ©s de 18 Ã  25 ans sont les plus indiquÃ©s pour ce travail.</Text>
+</Bullet>
+<Bullet>
+<Text id="192">Les premiÃšres heures Ã©tant toujours les plus productives, il faut organiser le travail Ã  temps partiel ou ne retenir que les gens les plus motivÃ©s et concentrÃ©s pour un travail Ã  temps plein.</Text>
+</Bullet>
+<Bullet>
+<Text id="193">Les deux tiers des gens abandonnent ou s'ennuient aprÃšs trois Ã  cinq semaines, ce qui se traduit par une qualitÃ© et une productivitÃ© en baisse les derniÃšres semaines.</Text>
+</Bullet>
+<Bullet>
+<Text id="194">Il faut veiller Ã  fournir un travail rÃ©gulier pour justifier la formation nÃ©cessaire, pour maintenir la concentration, et pour que restent hauts les c3#3urs.</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Subsection>
+<Subsection id="achievable_productivity">
+<Title>
+<Text id="195">ProductivitÃ© possible</Text>
+</Title>
+<Content>
+<Table id="table_ocr_productivity">
+<Title>
+<Text id="196">ProductivitÃ© de l'OCR</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="161"/>
+<th width="142">
+<Text id="197">Heures travaillÃ©es par jour</Text>
+</th>
+<th width="123">
+<Text id="198">Pages par jour</Text>
+</th>
+<th width="104">
+<Text id="199">Pages par mois</Text>
+</th>
+</tr>
+<tr>
+<th width="161">
+<Text id="200">Formation initiale (6 semaines)</Text>
+</th>
+<th width="142">
+<Text id="201">3</Text>
+</th>
+<th width="123">
+<Text id="202">6</Text>
+</th>
+<th width="104">
+<Text id="203">120</Text>
+</th>
+</tr>
+<tr>
+<th width="161">
+<Text id="204">Niveau de productivitÃ© optimale</Text>
+</th>
+<th width="142">
+<Text id="205">3</Text>
+</th>
+<th width="123">
+<Text id="206">9</Text>
+</th>
+<th width="104">
+<Text id="207">150 Ã  200</Text>
+</th>
+</tr>
+<tr>
+<th width="161"/>
+<th width="142">
+<Text id="208">7</Text>
+</th>
+<th width="123">
+<Text id="209">28</Text>
+</th>
+<th width="104">
+<Text id="210">500 Ã  600</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="211">Le tableauÂ <CrossRef target="Table" ref="table_ocr_productivity"/> donne les statistiques moyennes de productivitÃ© pour la ROC. Les documents sont de toutes tailles et de toutes qualitÃ©s, et ces chiffres supposent que le lot de documents contient un nombre moyen d'images et de tableauxÂ --Â disons une image et une tableau de 5 lignes par 5 colonnes toutes les 8 pages. Ils supposent aussi que les images des pages sont de qualitÃ© moyenne Ã  bonne (comme on l'a dÃ©jÃ  signalÃ©, ceci dÃ©pend de la numÃ©risation) et que les opÃ©rateurs maÃ®trisent bien la langue.</Text>
+<Text id="212">Le tableauÂ <CrossRef target="Table" ref="table_ocr_productivity"/> distingue les cas des opÃ©rateurs en formation et celui des opÃ©rateurs ayant atteint leur niveau de productivitÃ© optimal. Si un agent administratif devait passer 3 heures par jour Ã  des activitÃ©s de ROC, il pourrait produire 180 Ã  200 pages par mois. Dans le cas de personnel employÃ© Ã  temps plein, ayant reÃ§u une formation adÃ©quate, avec une concentration Ã©levÃ©e et un goÃ»t du travail bien fait, on peut obtenir de 500 Ã  600 pages par mois.</Text>
+<Text id="213">Cependant, les taux obtenus sur des pages difficiles, de qualitÃ© mÃ©diocre, contenant beaucoup d'images ou de tableaux, sont bien plus faiblesÂ --Â peut-Ãªtre de 300 Ã  400 pages par mois pour un travail Ã  temps plein.</Text>
+<Text id="214">Supposons que les coÃ»ts salariaux d'opÃ©rateurs de ROC motivÃ©s et soucieux de qualitÃ© travaillant Ã  temps plein s'Ã©lÃšvent Ã  400$ par mois, et que les frais d'infrastructure (comprenant les coÃ»ts d'encadrement, les ordinateurs, les bureaux, les fournitures, etc.) s'Ã©lÃšvent Ã  300 Ã  400$ par personne et par mois. Alors le coÃ»t de la ROC est de 1.2$ Ã  1.6$ par page. Si on prend en compte le temps de formation, le volume total, la durÃ©e de l'opÃ©ration, et les coÃ»ts de licenciement si l'opÃ©ration devait prendre fin par manque de travail, ces coÃ»ts atteignent 1.5$ Ã  2.5$ par page.</Text>
+<Text id="215">Il faut comparer le coÃ»t d'une ROC menÃ©e sur place Ã  celui d'une ROC sous-traitÃ©e Ã  un professionnel. De telles sociÃ©tÃ©s demandent en gÃ©nÃ©ral de 1.5$ Ã  4$ par page, en comptant les images et les tableaux. L'ONG Human Info/Simple Words dispose d'une telle unitÃ© en Roumanie, et pratique un tarif spÃ©cial pour les organisations humanitaires ou Ã  but non lucratifs: de 1.2$ Ã  2$ par page. Contactez-nous Ã  l'adresse Ã©lectronique si vous souhaitez obtenir des informations ou des conseils complÃ©mentaires.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="alternatives_to_ocr">
+<Title>
+<Text id="216">Pour Ã©viter la ROC</Text>
+</Title>
+<Content>
+<Text id="217">Il existe deux solutions qui permettent d'Ã©viter la ROC, et nous les prÃ©sentons toutes deux ici.</Text>
+<Subsection id="manual_retyping">
+<Title>
+<Text id="218">Saisie manuelle</Text>
+</Title>
+<Content>
+<Text id="219">La premiÃšre, qui Ã©limine Ã©galement la plupart des opÃ©rations de numÃ©risation, consiste Ã  retaper les documents Ã  la main, en utilisant un traitement de texte. Il faut quand mÃªme numÃ©riser la couverture et les images, mais les autres pages n'ont pas besoin d'Ãªtre numÃ©risÃ©es, ce qui Ã©vite l'achat d'un scanner puissant et de logiciels de ROC.</Text>
+<Text id="220">Les opÃ©rateurs n'ont pas besoin de comprendre le texte: il leur suffit d'Ãªtre des dactylographes prÃ©cis, qui tapent exactement ce qu'ils voient. La saisie gÃ©nÃšre des erreurs, qu'on trouve et dÃ©tecte par la mÃ©thode dite de double saisie. Elle consiste Ã  demander Ã  deux personnes de saisir le mÃªme document indÃ©pendamment, suite Ã  quoi on comparer les deux versions numÃ©riques mot Ã  mot Ã  l'aide d'un logiciel spÃ©cial manipulÃ© par un opÃ©rateur disposant du document original. On suppose implicitement qu'un mot tapÃ© indÃ©pendamment deux fois de la mÃªme maniÃšre est nÃ©cessairement correct. Mais cela ne suffit pas toujours, et on peut avoir recours Ã  de la triple saisie pour obtenir une prÃ©cision extrÃªmement Ã©levÃ©e.</Text>
+<Text id="221">L'avantage de la saisie est l'Ã©conomie effectuÃ©e: nul besoin d'un programme de ROC (qui nÃ©cessite des ordinateurs puissants), aussi des ordinateurs plus anciens, ou d'occasion peuvent suffire. De plus, ce travail peut Ãªtre menÃ© par des personnes moins qualifiÃ©es. L'inconvÃ©nient est la durÃ©e de la pÃ©riode de formation (d'un minimum de deux mois). Une simple saisie induisant souvent trop d'erreurs, il faut procÃ©der Ã  une double ou Ã  une triple saisie.</Text>
+<Text id="222">Le coÃ»t dÃ©pend entiÃšrement du salaire. Les dactylos sont gÃ©nÃ©ralement payÃ©es environ 150$ par mois dans les pays en voie de dÃ©veloppement. La productivitÃ© est de 20 Ã  30 pages par jour, pour un total de 400 pages par mois, en comptant les images. Avec une double saisie, cela donne un coÃ»t de revient salarial d'environ 300$ par mois, plus les Ã  cÃŽtÃ©s.</Text>
+</Content>
+</Subsection>
+<Subsection id="image_files">
+<Title>
+<Text id="223">Fichiers image</Text>
+</Title>
+<Content>
+<Text id="224">Une solution de remplacement Ã  la ROC trÃšs peu onÃ©reuse est de se contenter d'utiliser une version image PDF des pages du document. Le coÃ»t est nÃ©gligeable devant celui de la ROCÂ --Â environ 0.1$ par page.</Text>
+<Text id="225">Ã l'issue du processus de numÃ©risation et une fois que les fichiers TIFF sont disponibles, un convertisseur automatique (on utilise en gÃ©nÃ©ral Adobe Acrobat ou Adobe Photoshop) transforme tous les fichiers TIFF des pages du livre en fichiers PDF.</Text>
+<Text id="226">Le revers de la mÃ©daille est l'impossibilitÃ© de mener des recherches textuelles dans de tels fichiers. De plus, ils sont trÃšs lourds: environ 50 kilo-octets par page, plus ou moins 20% selon la qualitÃ© du fichier TIFF original.</Text>
+<Text id="227">Les fichiers image PDF sont lents Ã  tÃ©lÃ©charger (parfois, dans les pays en voie de dÃ©veloppement, cette opÃ©ration est impossible ou a un coÃ»t prohibitif). Ils tiennent rarement sur une disquette, et il est impossible de manipuler leur texte, ne serait-ce que pour effectuer des copier-coller.</Text>
+<Text id="228">Il faut rÃ©server cette mÃ©thode aux situations oÃ¹ aucun budget ne peut Ãªtre dÃ©bloquÃ© pour la ROC, et pour les documents susceptibles d'Ãªtre utilisÃ©s par un petit nombre de personnes, disposant d'une connexion Internet Ã  haut dÃ©bit.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="combining_scanning_and_ocr">
+<Title>
+<Text id="229">Mettre bout Ã  bout numÃ©risation et ROC</Text>
+</Title>
+<Content>
+<Text id="230">Si un scanner est directement reliÃ© Ã  l'ordinateur qui hÃ©berge le logiciel de ROC, la plupart des programmes de ROC peuvent numÃ©riser une page et effectuer immÃ©diatement la reconnaissance de caractÃšres. ProcÃ©der une page Ã  la fois, en enchaÃ®nant numÃ©risation puis ROC, est une stratÃ©gie raisonnable pour des petits volumes, mais s'avÃ©rera coÃ»teux en temps pour des tÃ¢ches plus importantes et plus continues.</Text>
+<Text id="231">Cette solution peut suffire pour 100 Ã  150 pages par mois. Pour des volumes plus Ã©levÃ©s il est plus rapide et plus efficace de commencer par numÃ©riser le document, puis de dÃ©marrer en deuxiÃšme lieu une opÃ©ration de ROC sur toutes ses pages Ã  la fois.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="three_examples">
+<Title>
+<Text id="232">Trois exemples: de 1000 Ã  100 000 pages</Text>
+</Title>
+<Content>
+<Section id="typical_small_collection">
+<Title>
+<Text id="233">Cas d'une petite collection: de 500 Ã  1000 pages</Text>
+</Title>
+<Content>
+<Text id="234">La plupart des ONG ont un volume de 500 Ã  1000 pages Ã  numÃ©riser. Un tel volume peut Ãªtre traitÃ© sur place si on trouve des volontaires motivÃ©s.</Text>
+<Subsection id="scanning">
+<Title>
+<Text id="235">NumÃ©risation</Text>
+</Title>
+<Content>
+<Text id="236">La premiÃšre Ã©tape consiste Ã  numÃ©riser les publications pour produire un fichier TIFF de bonne qualitÃ© de chaque page, et une image sÃ©parÃ©e pour chaque illustration (croquis, image en niveaux de gris ou en couleurs). Si on fait l'hypothÃšse que 1000 pages doivent Ãªtre numÃ©risÃ©es, ceci peut reprÃ©senter un travail Ã  temps partiel d'environ un moisÂ --Â pour la numÃ©risation seule. Les fichiers TIFF occuperont de 60 Ã  80 mÃ©ga-octets d'espace disque, et c'est une bonne idÃ©e que de graver un cÃ©dÃ©rom rÃ©inscriptible contenant ces fichiers. Un scanner Ã  plat de bas de gamme de 100 Ã  300$ suffira Ã  mener cette tÃ¢che de numÃ©risation Ã  bien. La numÃ©risation peut Ãªtre prise en charge par un volontaire, aprÃšs les heures de bureau ou les jours non ouvrÃ©s, au bureau ou Ã  la maison.</Text>
+</Content>
+</Subsection>
+<Subsection id="ocr">
+<Title>
+<Text id="237">ROC</Text>
+</Title>
+<Content>
+<Text id="238">La ROC, menÃ©e par un autre volontaire ou par une Ã©quipe de volontaires, douÃ©s en langue et en correction, vient ensuite. Les fichiers TIFF peuvent Ãªtre partagÃ©s entre ordinateurs, ou bien on peut utiliser un seul ordinateur pour l'ensemble du travail. Il faudra en moyenne de 5 Ã  6 mois Ã  temps partiel (par exemple, environ 20 heures par semaine) pour convertir 1000 pages en bons documents Word ou HTML.</Text>
+</Content>
+</Subsection>
+<Subsection id="outsourcing">
+<Title>
+<Text id="239">Sous-traiter</Text>
+</Title>
+<Content>
+<Text id="240">On peut aussi envisager de sous-traiter les opÃ©rations de numÃ©risation et de ROC. Il en coÃ»tera probablement de 1500 Ã  2000$ pour tout convertir en bons fichiers Word ou HTML.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="all_publications_from_an_organization">
+<Title>
+<Text id="241">Toutes les publications d'une organisation: 5000 pages</Text>
+</Title>
+<Content>
+<Text id="242">De nombreuses organisations plus importantes disposent d'environ 5000 pages d'archives de livres, journaux, revues, et autres documents, actuels ou Ã©puisÃ©s.</Text>
+<Subsection id="scanning_1">
+<Title>
+<Text id="243">NumÃ©risation</Text>
+</Title>
+<Content>
+<Text id="244">VoilÃ  un volume trop important pour un scanner Ã  plat. La numÃ©risation doit donc Ãªtre sous-traitÃ©e (ce qui coÃ»tera environ 400$ pour 5000 pages) ou confiÃ©e Ã  un scanner Ã  chargeur (qui coÃ»te environ 900$). On peut aussi envisager l'achat groupÃ© d'un scanner plus performant, avec d'autres institutions ou ONG (il en coÃ»tera 6000$, Ã  diviser par le nombre de participants). Les 5000 pages converties au format TIFF occuperont 300 Ã  400 mÃ©ga-octets d'espace disque. LÃ  encore, c'est une bonne idÃ©e de graver un cÃ©dÃ©rom rÃ©inscriptible contenant ces fichiers.</Text>
+</Content>
+</Subsection>
+<Subsection id="ocr_1">
+<Title>
+<Text id="245">ROC</Text>
+</Title>
+<Content>
+<Text id="246">La ROC, menÃ©e par un volontaire ou par une Ã©quipe de volontaires, douÃ©s en langue et en correction, vient ensuite. Ici encore, les fichiers TIFF peuvent Ãªtre partagÃ©s entre ordinateurs, ou bien on peut utiliser un seul ordinateur pour l'ensemble du travail. Il faudra en moyenne de 25 Ã  30 mois Ã  temps partiel (par exemple, environ 20 heures par semaine) pour convertir 5000 pages en bons documents Word ou HTML. En pratique, c'est lÃ  une tÃ¢che trop longue et gourmande en ressources informatiques pour pouvoir fonctionner sur la base du volontariat. Il faudrait rÃ©munÃ©rer les volontaires, surveiller leurs performances et la qualitÃ© de leur travail, fournir l'espace adÃ©quat, etc., pour obtenir un travail finalisÃ© de bonne qualitÃ© dans des dÃ©lais raisonnables.</Text>
+<Text id="247">On peut aussi crÃ©er des fichiers image PDF, ce qui occupera de 300 Ã  400 mÃ©ga-octets d'espace disque, et sera plus difficile Ã  tÃ©lÃ©charger depuis l'Internet.</Text>
+</Content>
+</Subsection>
+<Subsection id="outsourcing_1">
+<Title>
+<Text id="248">Sous-traiter</Text>
+</Title>
+<Content>
+<Text id="249">On peut aussi envisager de sous-traiter les opÃ©rations de numÃ©risation et de ROC. Il en coÃ»tera probablement de 7500 Ã  10Â 000$ pour tout convertir en bons fichiers Word ou HTML.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="a_small_library">
+<Title>
+<Text id="250">Une petite bibliothÃšques: 100 000 pages</Text>
+</Title>
+<Content>
+<Text id="251">Des organisations plus importantes, des universitÃ©s, des gouvernements, et des bibliothÃšques spÃ©cialisÃ©es disposeront peut-Ãªtre de toute une bibliothÃšque Ã  numÃ©riserÂ --Â disons, 100Â 000 pages. La premiÃšre question Ã  se poser est celle des droits attachÃ©s aux publications: si elles ne sont pas placÃ©es ou tombÃ©es dans le domaine public, il faut obtenir des dÃ©tenteurs des droits l'autorisation explicite de les numÃ©riser. Pensez aussi Ã  vÃ©rifier si les fichiers ne sont pas dÃ©jÃ  disponibles sous forme numÃ©rique.</Text>
+<Subsection id="scanning_2">
+<Title>
+<Text id="252">NumÃ©risation</Text>
+</Title>
+<Content>
+<Text id="253">Le volume est trop important pour un scanner Ã  chargeur. Il faut donc sous-traiter la numÃ©risation (il en coÃ»tera 8000$ pour 100Â 000 pages) ou acheter un scanner plus performant en commun avec quelques autres institutions ou ONG (il en coÃ»tera 6000$, Ã  diviser par le nombre de participants). Les 100Â 000 pages converties au format TIFF occuperont 6 Ã  8 giga-octets d'espace disque. La meilleure idÃ©e est de graver une sÃ©rie de copies de ces fichiers sur cÃ©dÃ©rom rÃ©inscriptible.</Text>
+</Content>
+</Subsection>
+<Subsection id="ocr_2">
+<Title>
+<Text id="254">ROC</Text>
+</Title>
+<Content>
+<Text id="255">La ROC vient ensuite (on peut aussi penser Ã  crÃ©er des fichiers PDF pour des documents moins largement utilisÃ©s). Il faudra en moyenne de 500 Ã  700 mois Ã  temps partiel pour convertir 5000 pages en documents Word ou HTML. C'est une opÃ©ration impossible Ã  mener sur la base du volontariat, et il faut avoir une approche professionnelle.</Text>
+<Text id="256">On peut rÃ©duire les coÃ»ts en transformant les pages les moins frÃ©quemment utilisÃ©es (par exemple, les 80% les moins utilisÃ©s, ce qui reprÃ©sente 80Â 000 pages) en PDF, et ne transformer que les 20Â 000 pages restantes en Word et en HTML. Les fichiers PDF occuperont 6 Ã  8 giga-octets d'espace disque et seront plus difficiles Ã  tÃ©lÃ©charger sur l'Internet, mais ils ne coÃ»teront que 0.2$ par page Ã  faire produire par des professionnels (pour un coÃ»t total de 16Â 000$). S'il fallait faire crÃ©er 80Â 000 fichiers PDF Ã  partir de fichiers TIFF par des volontaires utilisant des programmes de conversion vers PDF tels qu'Adobe Acrobat, il faudrait prÃ©voir 10 Ã  20 mois de travail Ã  temps partiel sur un ordinateur puissant.</Text>
+</Content>
+</Subsection>
+<Subsection id="outsourcing_2">
+<Title>
+<Text id="257">Sous-traiter</Text>
+</Title>
+<Content>
+<Text id="258">On peut aussi envisager de sous-traiter le travail. Si on reste sur l'hypothÃšse de 80% des pages converties en PDF et les 20% les plus frÃ©quents en HTML, le coÃ»t du PDF s'Ã©lÃ©vera Ã  environ 16Â 000$ et celui du HTML de 30 Ã  40Â 000$, pour un budget global d'environ 50Â 000$. Si toutes les pages passaient Ã  la ROC, il en coÃ»terait de 150 Ã  200Â 000$ pour convertir toute la collection en fichiers Word et HTML. </Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="creating_an_electronic_collection">
+<Title>
+<Text id="259">CrÃ©er une collection Ã©lectronique</Text>
+</Title>
+<Content>
+<Text id="260">Quand on dÃ©cide de crÃ©er une collection, il faut garder Ã  l'esprit trois aspects importants. D'abord, il faut organiser la collection. Plus dense et complet sera le contenu, plus le besoin d'indexation et de systÃšmes de recherche puissants se fera sentir. De tels outils sont indispensables pour des collections de 3000 Ã  5000 pages ou plus. Ensuite, il faut donner la prioritÃ© aux besoins des utilisateurs finals. Identifiez le public ciblÃ© par la collection, et consultez-le rÃ©guliÃšrement. Enfin, le budget disponible tranchera tous les choix en matiÃšre de dÃ©veloppement ou raffinement.</Text>
+<Section id="methods_of_collection_building">
+<Title>
+<Text id="261">MÃ©thodes de construction de collections</Text>
+</Title>
+<Content>
+<Text id="262">On trouve de nombreux exemples d'excellents cÃ©dÃ©roms crÃ©Ã©s sur le modÃšle de la page web. Les documents HTML, PDF ou Word peuvent Ãªtre ajoutÃ©s et reliÃ©s au reste de la collection grÃ¢ce Ã  des liens hypertexte. La navigation est simple et attrayante grÃ¢ce aux liens hypertexte, aux cadres, aux mots-clefs, aux index, etc. De tels systÃšmes peuvent convenir pour des volumes de quelques milliers de pages, mais Ã  partir de 3000 ou 5000 pages ils atteindront leurs limites et il deviendra important de disposer d'une collection bien structurÃ©e et de fonctionnalitÃ©s de recherche puissantes. C'est lÃ  que Greenstone peut rendre service.</Text>
+<Text id="263">Le logiciel de bibliothÃšque numÃ©rique Greenstone crÃ©e une bibliothÃšque numÃ©rique structurÃ©e disposant d'un moteur de recherche trÃšs puissant. On peut indexer jusqu'Ã  150Â 000 pages sur un simple cÃ©dÃ©rom, et chaque cÃ©dÃ©rom peut se transformer en serveur web. Greenstone est un logiciel libre, disponible selon les termes de la licence publique gÃ©nÃ©rale de GNU.</Text>
+<Text id="264">Les manuels fournis dÃ©crivent la maniÃšre de confectionner des collections Greenstone. Il y a essentiellement trois faÃ§ons de crÃ©er des collections.</Text>
+
+<BulletList>
+<Bullet>
+<Text id="265">Le "Librarian Interface" (l'Interface BibliothÃ©caire)</Text>
+</Bullet>
+<Bullet>
+<Text id="266">Le "Collector" (Le collectionneur)</Text>
+</Bullet>
+<Bullet>
+<Text id="267">La crÃ©ation Ã  partir de la ligne de commande.</Text>
+</Bullet>
+</BulletList>
+<Text id="268">La premiÃšre est le "Librarian Interface" (l'Interface BibliothÃ©caire) dÃ©crit dans le "Guide de l'utilisateur de la bibliothÃšque numÃ©rique Greenstone" (Chapitre 3, "RÃ©aliser des collections Greenstone"). C'est un outil interactif fonctionnel dans la crÃ©ation des collections. Avec lui, on peut collecter des groupes de documents, importer ou assigner des mÃ©ta-donnÃ©es, et confectionner une collection Greenstone. La deuxiÃšme mÃ©thode est le sous-systÃšme "collectionneur", dÃ©crit au chapitre 4 du guide de l'utilisateur. C'est un outil plus ancien qui fournit une maniÃšre alternative de crÃ©er des collections de pages Web et autres documents. Il vous guide Ã  travers une sÃ©quence de pages Web conventionnelles qui exigent l'information requise. Il ne fournit cependant aucun moyen d'ajouter une mÃ©tadata aux documents et, parce que c'est une interface Web, il n'est vraiment pas adaptÃ© aux collections qui prennent plus que quelques minutes pour Ãªtre crÃ©Ã©es. La troisiÃšme mÃ©thode consiste Ã  exÃ©cuter directement, Ã  partir de la ligne de commande, les programmes de crÃ©ation de collections; elle figure dans le "Guide du dÃ©veloppeur de la collection Greenstone" (Chapitre 1). Elle offre plus de flexibilitÃ© dans l'exÃ©cution individuelle des programmes et dans la sauvegarde des rÃ©sultats intermÃ©diaires, hautement souhaitable pour les collections qui prennent des heures Ã  Ãªtre crÃ©Ã©es. La lecture du chapitre 2 du Developer's Guide s'avÃšre aussi nÃ©cessaire pour exploiter de faÃ§on optimale la puissance de Greenstone dans la confection des collections de pointe.</Text>
+<Text id="269">Une quatriÃšme mÃ©thode de crÃ©ation et d'Ã©dition du matÃ©riel associÃ© Ã  la collection existe; c'est un programme appelÃ© "The Collection Organizer" (Organisateur de la Collection). Cependant, sa fonctionnalitÃ© a Ã©tÃ© dÃ©passÃ©e par le "Librarian Interface" (l'Interface BibliothÃ©caire) mentionnÃ© ci-dessus. Ce document est dÃ©crit comme un leg sous le titre "Using the Organizer" (Utiliser l'organisateur).</Text>
+</Content>
+</Section>
+<Section id="getting_started_in_seven_steps_and_15_minutes">
+<Title>
+<Text id="270">Commencer en sept Ã©tapes et en 15 minutes</Text>
+</Title>
+<Content>
+<Text id="271">La meilleure faÃ§on d'apprÃ©hender et de sentir l'Interface BibliothÃ©caire est en fait de crÃ©er une bibliothÃšque par un petit test. Si vous disposez de 15 minutes on vous conseille de suivre ces Ã©tapes pour une meilleure comprÃ©hension de ces programmes.</Text>
+<Text id="272">Avant tout, vous installez Greenstone (Voir Le Guide d'installation de Greenstone) "The Greenstone intaller's Guide" qui comprend la collection de dÃ©monstration "Demo Collection" dans un format DLS et ses fichiers sources. Noter que si vous souhaitez ajouter Ã  la collection l'un quelconque des 140 documents de la collection DLS (au lieu seulement des 11 de la collection Demo de Greenstone), vous devez installer DLS comme un des modÃšles des bibliothÃšques Greenstone. Dans CProgram Filesgsdlcollect, comme d'ailleurs Demo, dans les sous-repertoires respectifs DLS et Demo. Si Greenstone avait dÃ©jÃ  Ã©tÃ© installÃ© sans la collection DLS et que vous souhaitez installer celle-ci, vous devez rÃ©insÃ©rer le Cd-rom de Greenstone et procÃ©der Ã  l'ajout de DLS. La dÃ©sinstallation de Greenstone n'est en aucun cas nÃ©cessaire.</Text>
+<Text id="273">Nous vous conseillons d'imprimer les instructions ci-dessous et de les suivre pas Ã  pas:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="274">DÃ©marrer le "Librarian Interface" (l'Interface BibliothÃ©caire) sous Windows en sÃ©lectionnant Greenstone Digital Library Ã  partir de la section Programmes du menu de DÃ©marrage et en sÃ©lectionnant "Librarian interface". Si vous utilisez Unix Ã  la place, il faut taper:</Text>
+<CodeLine>cd ~/gsdl cd gli ./gli.sh</CodeLine>
+<Text id="275">oÃ¹Â /gsdl est le rÃ©pertoire contenant votre systÃšme Greenstone.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="276">SÃ©lectionner "Nouveau" Ã  partir du menu "Fichier" dans la barre de menu horizontale placÃ©e en haut de la fenÃªtre. Lui donner un titre, par exemple "Ma premiÃšre collection" et mettre votre adresse Ã©lectronique et une description sommaire de la collection. Dans le menu "Baser cette collection sur", choisir "greenstone demo" (dÃ©monstration de greenstone) ou "Developement Library Subset" (le rÃ©sultat est le mÃªme parce que ces deux collections ont la mÃªme structure).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="277">Ajouter des documents Ã  partir de la collection Demo (ou la collection DLS si elle est installÃ©e) Ã  votre nouvelle collection. Pour ce faire, double-cliquer sur le rÃ©pertoire des Collections Greenstone Ã  gauche du panneau, et double-cliquer sur la collection dÃ©sirÃ©e. Les documents qui s'y trouvent sont affichÃ©s en dessous. SÃ©lectionnez-en un, le faire glisser et le dÃ©poser dans le panneau de droite ("glisser-coller"). Celle-ci reprÃ©sente la collection en cours de crÃ©ation. Choisir plusieurs documents, les faire glisser un Ã  un Ã  l'intÃ©rieur, ou utiliser une sÃ©lection multiple de faÃ§on standard.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="278">Ajouter vos propres documents qui ne sont pas dans la collection Demo ou DLS. Fermer le rÃ©pertoire des collections Greenstone du panneau de gauche et double-cliquer sur le rÃ©pertoire "Local filespace". Naviguer vers le rÃ©pertoire qui contient des documents(c'est Ã  dire de petits fichiers Word et HTML). En faire glisser quelques-uns dans le panneau de droite pour les inclure dans votre collection.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="279">Ajouter des mÃ©ta-donnÃ©es aux documents de votre collection. Jusqu'Ã  prÃ©sent, l'exÃ©cution se dÃ©roulait sous le panneau "Gather", indiquÃ© par l'onglet "Gather" en-dessous de la barre de menu horizontale en haut de Windows. Cliquer sur l'onglet "Enrich" qui se trouve Ã  cÃŽtÃ©. Les documents dans votre collection apparaissent maintenant dans le panneau de gauche : cliquer sur l'un et examiner la mÃ©ta-donnÃ©e qui lui est associÃ©e dans la liste "ElÃ©ment ... Valeurs" en haut Ã  droite. Utiliser le panneau en-dessous pour changer les valeurs individuelles en sÃ©lectionnant l'Ã©lÃ©ment dÃ©sirÃ© et, soit choisir une valeur existante sur la liste, ou taper une nouvelle valeur dans la boÃ®te situÃ©e en bas. Ajouter les meta-donnÃ©es Titre, Organisation et Mot-clÃ© Ã  chacun de vos propres documents figurant sur la collection. AprÃšs la saisie de chaque valeur, il est nÃ©cessaire de cliquer sur "Ajouter" pour ajouter cette valeur Ã  la mÃ©ta-donnÃ©e.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="280">Cliquez l'onglet "CrÃ©er" pour quitter le mode "Enrich" et crÃ©er votre nouvelle collection. Cliquer sur l'onglet "CrÃ©er la Collection" en bas. Pendant que l'ordinateur Ã©labore la collection, vous recevrez en feedback un compte rendu sur ce qui est en cours d'exÃ©cution.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="281">En fin d'exÃ©cution, cliquer sur l'onglet Preview pour visualiser la collection Ã  partir du "Librarian Interface" (l'Interface BibliothÃ©caire). VÃ©rifier les titres a-z, organisations et comment lister pour vous assurer que vos documents ont Ã©tÃ© inclus dans la collection. En visitant votre page Web Greenstone, le constat est fait aussi que la collection a Ã©tÃ© installÃ©e parmi les collections de Greenstone.</Text>
+</NumberedItem>
+</NumberedList>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<FootnoteList>
+<Footnote id="1">
+<Text id="282">Tous les prix mentionnÃ©s reprÃ©sentent des dollars amÃ©ricains (USD) et sont donnÃ©s sur la base du marchÃ© en 2001.</Text>
+</Footnote>
+<Footnote id="2">
+<Text id="283">Rappel: tous les prix mentionnÃ©s reprÃ©sentent des dollars amÃ©ricains (USD) et sont donnÃ©s sur la base du marchÃ© en 2001.</Text>
+</Footnote>
+</FootnoteList>
+</Manual>
Index: /tags/start/gsdl-documentation/manuals/xml-source/fr/User_fr.xml
===================================================================
--- /tags/start/gsdl-documentation/manuals/xml-source/fr/User_fr.xml	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/xml-source/fr/User_fr.xml	(revision 13666)
@@ -0,0 +1,2474 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Manual>
+<Heading>
+<Text id="1"/>
+</Heading>
+<Title>
+<Text id="2">Guide de l'utilisateur de la bibliothÃšque numÃ©rique Greenstone</Text>
+</Title>
+<Author>
+<Text id="3">Ian H. Witten, Stefan Boddie et John Thompson</Text>
+</Author>
+<Affiliation>
+<Text id="4">DÃ©partement d'informatique,<br/>UniversitÃ© de Waikato, Nouvelle-ZÃ©lande</Text>
+</Affiliation>
+<Comment>
+<Text id="5">Greenstone est une suite logicielle destinÃ©e Ã  la construction et Ã  la distribution de collections de bibliothÃšques numÃ©riques. Cette suite fournit une nouvelle maniÃšre d'organiser l'information et de la publier sur l'Internet ou sur un cÃ©dÃ©rom. Greenstone est produit par le projet de bibliothÃšque numÃ©rique de Nouvelle-ZÃ©lande (dÃ©pendant de l'universitÃ© de Waikato), et distribuÃ© en coopÃ©ration avec l'UNESCO et le projet de bibliothÃšques pour l'humanitÃ©. C'est un logiciel Open Source, qu'on peut obtenir Ã  l'URLhttp://greenstone.org, et qui est diffusÃ© selon les termes de la licence publique gÃ©nÃ©rale de GNU.</Text>
+<Text id="6">Nous souhaitons nous assurer que ce logiciel fonctionne bien pour vous.<br/>Faites-nous part, en anglais, de tout problÃšme Ã  l'adresse Ã©lectronique<br/>.</Text>
+</Comment>
+<Version>
+<Text id="7">Greenstone gsdl-2.70</Text>
+</Version>
+<Date>
+<Text id="8">Mars 2006</Text>
+</Date>
+<Section id="about_this_manual">
+<Title>
+<Text id="9">Ã propos de ce manuel</Text>
+</Title>
+<Content>
+<Text id="10">Ce manuel fournit une description complÃšte de la maniÃšre d'utiliser le logiciel Greenstone pour accÃ©der Ã  et construire des collections de bibliothÃšques numÃ©riques.</Text>
+<Text id="11">La sectionÂ <CrossRef target="Chapter" ref="overview_of_greenstone"/> donne une vue d'ensemble des possibilitÃ©s du logiciel. La sectionÂ <CrossRef target="Chapter" ref="using_greenstone_collections"/> explique comment utiliser les collections de Greenstone. L'interface parle d'elle-mÃªmeÂ --Â la meilleure faÃ§on d'apprendre est d'essayerÂ --Â et cette section correspond aux informations d'aide en ligne fournies pour une collection typique. La sectionÂ <CrossRef target="Chapter" ref="making_greenstone_collections"/> explique la procÃ©dure de crÃ©ation d'une bibliothÃšque propre de collections en utilisant le "Greenstone Librarian Interface" (l'Interface BibliothÃ©caire de Greenstone). La sectionÂ <CrossRef target="Chapter" ref="administration"/> introduit l'outil d'administration, qui permet Ã  l'administrateur systÃšme de surveiller ce qui se passe, et de contrÃŽler les droits de construction de collections.</Text>
+<Text id="12">Les annexes listent les fonctionnalitÃ©s du logiciel Greenstone, et donnent un glossaire des termes utilisÃ©s dans la documentation de Greenstone.</Text>
+</Content>
+</Section>
+<Section id="companion_documents">
+<Title>
+<Text id="13">Documents d'accompagnement</Text>
+</Title>
+<Content>
+<Text id="14">L'ensemble des documents de Greenstone comprend quatre volumes:</Text>
+<BulletList>
+<Bullet>
+<Text id="15">Guide d'installation de la bibliothÃšque numÃ©rique Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="16">Guide de l'utilisateur de la bibliothÃšque numÃ©rique Greenstone (<i>ce document-ci</i>)</Text>
+</Bullet>
+<Bullet>
+<Text id="17">Guide du dÃ©veloppeur de la bibliothÃšque numÃ©rique Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="18">BibliothÃšque numÃ©rique Greenstone: du papier Ã  la collection</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Section>
+<Section id="acknowledgements">
+<Title>
+<Text id="19">Remerciements</Text>
+</Title>
+<Content>
+<Text id="20">Le logiciel Greenstone a vu le jour grÃ¢ce Ã  un effort de collaboration entre de nombreuses personnes. Rodger McNab et Stefan Boddie en sont les principaux architectes et dÃ©veloppeurs. Des contributions ont Ã©tÃ© faites par David Bainbridge, George Buchanan, Hong Chen, Michael Dewsnip, Katherine Don, Elke Duncker, Carl Gutwin, Geoff Holmes, Dana McKay, John McPherson, Craig Nevill-Manning, Dynal Patel, Gordon Paynter, Bernhard Pfahringer, Todd Reed, Bill Rogers, John Thompson, et Stuart Yeates. D'autres membres du Projet de bibliothÃšque numÃ©rique de Nouvelle-ZÃ©lande ont Ã©galement donnÃ© des conseils et inspirÃ© les concepteurs du systÃšme: Mark Apperley, Sally Jo Cunningham, Steve Jones, Te Taka Keegan, Michel Loots, Malika Mahoui, et Lloyd Smith. Nous remercions aussi tous ceux qui ont contribuÃ© au dÃ©veloppement des modules sous licence GNU GPL qui font partie de cette distribution: MG, GDBM, PDFTOHTML, PERL, WGET, WVWARE, XLHTML.</Text>
+</Content>
+</Section>
+<Chapter id="overview_of_greenstone">
+<Title>
+<Text id="21">Vue d'ensemble de Greenstone</Text>
+</Title>
+<Content>
+<Text id="22">Greenstone est un systÃšme complet pour construire et prÃ©senter des collections de milliers ou de millions de documents, comprenant du texte, des images, des contenus audio et vidÃ©o.</Text>
+<Section id="collections">
+<Title>
+<Text id="23">Les collections</Text>
+</Title>
+<Content>
+<Text id="24">La bibliothÃšque numÃ©rique typique construite avec Greenstone contient de nombreuses collections, organisÃ©es individuellementÂ --Â mÃªme si elles ont un air de famille prononcÃ©. Elles sont faciles Ã  maintenir, et on peut facilement y ajouter du contenu et les reconstruire automatiquement.</Text>
+<Text id="25">Il existe plusieurs maniÃšres de retrouver de l'information dans la plupart des collections Greenstone. On peut par exemple<i>rechercher des mots particuliers</i>apparaissant dans le corps du texte ou dans une section du document. On peut aussi<i>consulter des documents par leur titre</i>: il suffit alors de cliquer sur un livre pour le lire. On peut encore<i>consulter des documents par thÃšme</i>. Les thÃšmes reprÃ©sentent les Ã©tagÃšres de la bibliothÃšque: il suffit de cliquer sur une Ã©tagÃšre pour en voir les livres. Quand cela a un sens, les documents sont fournis avec une table des matiÃšres: on peut alors cliquer sur un chapitre ou sur une sous-section pour en lire le contenu, on peut dÃ©velopper toute la table des matiÃšres, ou encore dÃ©velopper tout le document dans la fenÃªtre de son navigateur (ce qui est utile pour imprimer). Le site web de la bibliothÃšque numÃ©rique de Nouvelle-ZÃ©lande (nzdl.org) propose de nombreux exemples de collections.</Text>
+<Text id="26">La page de garde de chaque collection prÃ©sente l'objectif et la couverture de la collection, et en explique l'organisation. On peut consulter la plupart des collections en y <i>recherchant</i>des mots-clefs ou en y<i>naviguant</i>. Lors de recherches, le logiciel Greenstone examine l'ensemble du texte de tous les documents de la collection (ce qui s'appelle une Â«recherche dans le corps du texteÂ»). Dans la plupart des collections l'utilisateur peut choisir entre plusieurs index, construits Ã  partir de diffÃ©rentes portions des documents. Certaines collections disposent d'un index des documents complets, d'un index des paragraphes, et d'un index des titres, dans lesquels on peut rechercher des mots ou des groupes de mots particuliers. On peut de cette maniÃšre retrouver tous les documents contenant un ensemble de mots prÃ©cis (les mots pouvant s'Ã©taler sur tout le document), tous les paragraphes qui contiennent ce mÃªme ensemble de mots (les mots doivent alors tous apparaÃ®tre dans le mÃªme paragraphe), ou tous les documents dont les titres contiennent les mots recherchÃ©s (les mots doivent alors se trouver dans les titres du document). On peut rencontrer d'autres index, comme par exemple un index des sections, ou encore un index des en-tÃªtes de sections. Lors de navigations, l'utilisateur examine des listes: liste des auteurs, liste des titres, liste des dates, structures de classification hiÃ©rarchiques, etc. DiffÃ©rentes collections proposeront diffÃ©rentes maniÃšres de naviguer.</Text>
+</Content>
+</Section>
+<Section id="finding_information">
+<Title>
+<Text id="27">Trouver l'information</Text>
+</Title>
+<Content>
+<Text id="28">Greenstone construit des index portant sur le corps du texte Ã  partir des contenus textuels du documentÂ --Â ce sont des index qui permettent de rechercher tout mot apparaissant dans le texte du document. On peut rechercher dans les index des mots particuliers, des ensembles ou des groupes de mots, et les rÃ©sultats sont ordonnÃ©s en fonction de leur pertinence par rapport Ã  la requÃªte.</Text>
+<Text id="29">Dans la plupart des collections, des donnÃ©es descriptives telles que l'auteur, la date, des mots-clefs, etc., sont associÃ©es Ã  chaque document. On appelle ces informations Â«mÃ©ta-donnÃ©esÂ». De nombreuses collections de documents contiennent Ã©galement des index portant sur le texte de certains types de mÃ©ta-donnÃ©es. De nombreuses collections proposent par exemple un index de recherche dans les titres des documents.</Text>
+<Text id="30">Les utilisateurs peuvent naviguer de maniÃšre interactive Ã  travers des listes et des structures hiÃ©rarchiques qui sont engendrÃ©es Ã  partir des mÃ©ta-donnÃ©es associÃ©es Ã  chaque document de la collection. Les mÃ©ta-donnÃ©es forment la matiÃšre premiÃšre de la navigation: elles doivent Ãªtre explicitement fournies, ou bien il doit Ãªtre possible de les obtenir automatiquement Ã  partir des documents eux-mÃªmes. DiffÃ©rentes collections proposeront diffÃ©rentes maniÃšres de naviguer. Les index de recherche et de navigation sont crÃ©Ã©s lors d'un processus de Â«constructionÂ», en se basant sur les informations fournies dans le fichier de configuration de la collection.</Text>
+<Text id="31">Greenstone crÃ©e toutes ses structures d'index automatiquement Ã  partir des documents et des fichiers qui les accompagnent: rien n'est fait manuellement. Si de nouveaux documents du mÃªme format sont disponibles, ils peuvent Ãªtre automatiquement fusionnÃ©s au reste de la collection. En fait, pour la plupart des collections, tout ceci est pris en charge par des processus qui s'exÃ©cutent rÃ©guliÃšrement, partent Ã  la recherche de nouveaux contenus, et reconstruisent les indexÂ --Â le tout sans aucune intervention manuelle.</Text>
+</Content>
+</Section>
+<Section id="document_formats">
+<Title>
+<Text id="32">Les formats de documents</Text>
+</Title>
+<Content>
+<Text id="33">Les documents originaux sont dans un grand nombre de formats, et sont traduits sous une forme XML standard Ã  l'aide de Â«greffonsÂ» (plugins). Les greffons distribuÃ©s avec Greenstone sont capables de traiter des documents aux formats texte brut, HTML, Word, PDF, et les messages Ã©lectroniques (de courrier ou de groupes de discussion). On peut Ã©crire de nouveaux greffons pour de nouveaux types de documents (pour ce faire, il faudra prÃ©alablement Ã©tudier le Guide du dÃ©veloppeur de la bibliothÃšque numÃ©rique Greenstone). Pour construire des structures de navigation Ã  partir de mÃ©ta-donnÃ©es, on utilise de mÃªme un systÃšme de Â«classificateursÂ». Ces derniers crÃ©ent des index de navigation de divers types: listes dÃ©roulantes, sÃ©lecteurs alphabÃ©tiques, dates et autres hiÃ©rarchies arbitraires. Ici encore, des programmeurs Greenstone peuvent crÃ©er de nouvelles structures de navigation.</Text>
+</Content>
+</Section>
+<Section id="multimedia_and_multilingual_documents">
+<Title>
+<Text id="34">Documents multimÃ©dia et multilingues</Text>
+</Title>
+<Content>
+<Text id="35">Les collections peuvent comprendre du texte, des images, des contenus audio et vidÃ©o. Les contenus non textuels peuvent Ãªtre reliÃ©s aux documents textuels ou accompagnÃ©s de descriptions textuelles (telles que les lÃ©gendes des figures) pour pouvoir Ãªtre accessibles depuis une recherche dans le corps du texte ou la navigation.</Text>
+<Text id="36">Greenstone utilise partout Unicode, qui est un systÃšme standard pour reprÃ©senter les jeux de caractÃšres des langues du monde. Ceci permet de traiter et de reprÃ©senter toutes les langues de maniÃšre consistante. On a construit des collections avec de l'anglais, de l'arabe, du chinois, de l'espagnol, du franÃ§ais, et du maori. Les collections multilingues intÃšgrent une reconnaissance automatique de la langue, et l'interface est disponible dans toutes les langues mentionnÃ©es ci-dessus (entre autres).</Text>
+</Content>
+</Section>
+<Section id="distributing_greenstone">
+<Title>
+<Text id="37">Distribuer Greenstone</Text>
+</Title>
+<Content>
+<Text id="38">Les collections sont mises Ã  disposition sur l'Internet ou publiÃ©es, sous une forme exactement semblable, sur un cÃ©dÃ©rom qui s'installe automatiquement sous Windows. Les textes et les index sont compactÃ©s, et un protocole CORBA permet de gÃ©rer les collections distribuÃ©es et les interfaces de requÃªtes graphiques.</Text>
+<Text id="39">La bibliothÃšque numÃ©rique de Nouvelle-ZÃ©lande (nzdl.org) fournit de nombreux exemples de collections, y compris des documents historiques, des informations humanitaires et de dÃ©veloppement, des rapports techniques et des bibliographies, des 1#1uvres littÃ©raires, et des magazines.</Text>
+<Text id="40">Sa nature Open Source fait de Greenstone un logiciel facile Ã  complÃ©ter, et il bÃ©nÃ©ficie de l'inclusion de modules sous licence publique gÃ©nÃ©rale de GNU pour la recherche dans le corps du texte, la gestion des bases de donnÃ©es, et l'extraction de texte depuis des formats de documents propriÃ©taires. Seule une coopÃ©ration internationale permettra aux logiciels de bibliothÃšque numÃ©rique de devenir suffisamment complets et de satisfaire les besoins des utilisateurs en richesse comme en souplesse.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="using_greenstone_collections">
+<Title>
+<Text id="41">Utilisation des collections Greenstone</Text>
+</Title>
+<Content>
+<Text id="42">Le logiciel Greenstone a Ã©tÃ© conÃ§u dans un souci d'ergonomie. Les interfaces des collections sont identiques, sur le web comme sur des cÃ©dÃ©roms. L'installation de Greenstone Ã  partir du cÃ©dÃ©rom est une opÃ©ration trÃšs simple, sur tout ordinateur Ã©quipÃ© de Windows ou de Linux: un programme d'installation standard complÃšte des binaires prÃ©-compilÃ©s. On peut utiliser une collection localement, sur l'ordinateur oÃ¹ elle est installÃ©e; on peut aussi, si cet ordinateur est reliÃ© Ã  un rÃ©seau, autoriser de maniÃšre automatique et transparente l'accÃšs Ã  cette collection depuis tous les autres ordinateurs du rÃ©seau.</Text>
+<Text id="43">La section suivante dÃ©crit l'installation d'un cÃ©dÃ©rom de Greenstone. Nous examinerons ensuite les possibilitÃ©s de recherche et de navigation offertes par une collection Greenstone reprÃ©sentative: la collection Â«DemoÂ», fournie avec Greenstone. D'autres collections prÃ©senteront des fonctionnalitÃ©s semblables: savoir en manipuler une, c'est savoir les manipuler toutes. Vient ensuite une explication sur la maniÃšre d'adapter l'interface Ã  vos propres besoins Ã  l'aide de la page de prÃ©fÃ©rences.</Text>
+<Section id="utilisation_d'using_a_greenstone_cd-rom">
+<Title>
+<Text id="44">Utilisation d'un cÃ©dÃ©rom de Greenstone</Text>
+</Title>
+<Content>
+<Text id="45">Le logiciel de bibliothÃšque numÃ©rique Greenstone lui-mÃªme est distribuÃ© sur un cÃ©dÃ©rom, et votre administrateur systÃšme ou vous l'avez dÃ©jÃ  installÃ© sur votre systÃšme, en suivant les instructions du Guide d'installation de la bibliothÃšque numÃ©rique Greenstone. Si telle est bien votre situation, Greenstone est dÃ©jÃ  installÃ© sur votre ordinateur et vous pouvez nÃ©gliger de lire le reste de la prÃ©sente section et passer directement Ã  la suivante.</Text>
+<Text id="46">Certaines collections Greenstone sont distribuÃ©es sur un cÃ©dÃ©rom minimal, qui contient juste assez du logiciel pour n'utiliser que cette collection. Pour utiliser un tel cÃ©dÃ©rom, il suffit de l'insÃ©rer dans le lecteur de cÃ©dÃ©rom sur tout ordinateur personnel Ã©quipÃ© de Windows. Dans la plupart des cas (si le programme autorun est activÃ©), une fenÃªtre apparaÃ®tra, qui vous invitera Ã  installer le logiciel Greenstone. Dans le cas contraire, trouvez le lecteur de cÃ©dÃ©rom (sur les systÃšmes Windows actuels, on y parvient en double-cliquant sur l'icone Mon ordinateur, situÃ©e sur le bureau), et double-cliquez dessus, puis sur le fichier Setup.exe qu'elle contient. Le programme Setup de Greenstone sera alors exÃ©cutÃ© et vous guidera tout au long de la procÃ©dure d'installation. La plupart des gens se contentent de rÃ©pondre oui (yes) Ã  toutes les questions.</Text>
+<Text id="47">Ã la fin de la procÃ©dure d'installation, vous trouverez la bibliothÃšque dans le sous-menu Programmes du menu DÃ©marrer de Windows, et elle portera le nom de la collection, comme par exemple, Humanity Libraries (Â«bibliothÃšques pour l'humanitÃ©) ou United Nations University (Â«universitÃ© des Nations-UniesÂ»).</Text>
+<Text id="48">Une fois que le logiciel a Ã©tÃ© installÃ©, vous entrerez automatiquement dans la bibliothÃšque Ã  chaque insertion du cÃ©dÃ©rom, si le programme autorun est activÃ©.</Text>
+</Content>
+</Section>
+<Section id="finding_information_1">
+<Title>
+<Text id="49">Trouver l'information</Text>
+</Title>
+<Content>
+<Text id="50">La meilleure maniÃšre d'apprendre Ã  utiliser une collection Greenstone est de pratiquer. Pas d'inquiÃ©tudeÂ --Â vous ne pouvez rien casser. Cliquez partout et sans crainte: la plupart des images qui apparaÃ®tront sur votre Ã©cran rÃ©agissent aux clics. Si vous maintenez le pointeur de la souris au-dessus d'une image, la plupart des navigateurs afficheront un message qui vous expliquera ce qui se passera si vous cliquez.</Text>
+<Text id="51">Faites l'expÃ©rience! Choisissez des mots communs tels que Â«leÂ» (the) ou Â«etÂ» (and) en tant que critÃšres de rechercheÂ --Â voilÃ  qui devrait fournir des rÃ©ponses, et vous ne pourrez rien casser.</Text>
+<Text id="52">Les bibliothÃšques numÃ©riques Greenstone comprennent souvent plusieurs collections distinctesÂ --Â par exemple, des rapports scientifiques et techniques, des 1#1uvres littÃ©raires, des FAQ de l'Internet, des magazines. Le systÃšme de bibliothÃšque numÃ©rique disposera d'une page d'accueil qui vous permettra d'accÃ©der Ã  toute collection publiquement accessible; de plus, chaque collection dispose de sa propre page Â«Ã  proposÂ» qui vous fournira toutes les informations relatives Ã  l'organisation de la collection et aux principes guidant ce qui y est inclus. Pour retrouver cette page Ã  tout moment, cliquez simplement sur l'icone de Â«collectionÂ» qui apparaÃ®t dans le coin supÃ©rieur gauche de toutes les pages de recherche et de navigation.</Text>
+<Text id="53">La figureÂ 1 prÃ©sente une copie d'Ã©cran de la collection Â«DemoÂ», fournie avec le logiciel Greenstone, et qui reprÃ©sente un tout petit sous-ensemble de la collection de bibliothÃšque de dÃ©veloppement pour l'humanitÃ©; nous l'utiliserons comme rÃ©fÃ©rence pour la description des diffÃ©rentes maniÃšres de trouver de l'information. Si vous ne trouvez pas la collection Â«DemoÂ», utilisez Ã  la place la bibliothÃšque de dÃ©veloppement pour l'humanitÃ©: elle lui ressemble en tous points. D'abord, on peut cliquer sur presque toutes les icones. Plusieurs icones apparaissent au sommet de la plupart des pages; le tableauÂ 1explique leur signification.</Text>
+<Figure id="using_the_demo_collection">
+<Title>
+<Text id="54">Utilisation de la collection Â«DemoÂ»</Text>
+</Title>
+<File url="images/User_Fig_1.png"/>
+</Figure>
+<Table id="what_the_icons_at_the_top_of_each_page_mean">
+<Title>
+<Text id="55">Signification des icones situÃ©es au sommet de chaque page</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="">
+<File url="images/User_Icon_1.png" height="32"/>
+</th>
+<th width="255">
+<Text id="56">Vous emmÃšne sur la page Â«Ã  proposÂ»</Text>
+</th>
+</tr>
+<tr>
+<th width="">
+<File url="images/User_Icon_2.png" height="16"/>
+</th>
+<th width="255">
+<Text id="57">Vous emmÃšne sur la page d'accueil de la bibliothÃšque numÃ©rique, depuis laquelle vous pourrez choisir une autre collection</Text>
+</th>
+</tr>
+<tr>
+<th width="">
+<File url="images/User_Icon_3.png" height="16"/>
+</th>
+<th width="255">
+<Text id="58">Fournit un texte d'aide similaire au prÃ©sent </Text>
+</th>
+</tr>
+<tr>
+<th width="">
+<File url="images/User_Icon_4.png" height="16"/>
+</th>
+<th width="255">
+<Text id="59">Vous permet de mettre en place des options d'interface utilisateur et de recherche qui seront dÃšs lors sÃ©lectionnÃ©es</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="60">La barre situÃ©e juste dessous, intitulÃ©e Â«recherche ... thÃšmes ... titres a-z ... organisation ... comment faireÂ» vous donne accÃšs aux fonctionnalitÃ©s de recherche et de navigation. Le bouton le plus Ã  gauche sert aux recherches, et les autres boutonsÂ --Â au nombre de quatre dans la cette collectionÂ --Â Ã©voquent plusieurs types de navigation. Ces quatre derniers boutons peuvent varier d'une collection Ã  l'autre.</Text>
+<Subsection id="how_to_find_information">
+<Title>
+<Text id="61">Comment trouver de l'information</Text>
+</Title>
+<Content>
+<Text id="62">Le tableauÂ 2montre les cinq maniÃšres de trouver de l'information dans la collection Â«DemoÂ».</Text>
+<Table id="table_icons_on_the_search_browse_bar">
+<Title>
+<Text id="63">Signification des icones de la barre de recherche/navigation</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="">
+<File url="images/User_Icon_5.png" height="12"/>
+</th>
+<th width="">
+<Text id="64">Recherche de mots-clefs particuliers</Text>
+</th>
+</tr>
+<tr>
+<th width="">
+<File url="images/User_Icon_6.png" height="12"/>
+</th>
+<th width="">
+<Text id="65">AccÃšs aux publications par thÃšme</Text>
+</th>
+</tr>
+<tr>
+<th width="">
+<File url="images/User_Icon_7.png" height="12"/>
+</th>
+<th width="">
+<Text id="66">AccÃšs aux publications par titre</Text>
+</th>
+</tr>
+<tr>
+<th width="">
+<File url="images/User_Icon_8.png" height="12"/>
+</th>
+<th width="">
+<Text id="67">AccÃšs aux publications par organisation</Text>
+</th>
+</tr>
+<tr>
+<th width="">
+<File url="images/User_Icon_9.png" height="12"/>
+</th>
+<th width="">
+<Text id="68">AccÃšs aux publications par listes de Â«comment faireÂ»</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="69">Vous pouvez <i>rechercher des mots-clefs particuliers</i>dans le corps du texte Ã  partir de la page de Â«rechercheÂ» (semblable en tous points Ã  la page Â«Ã  proposÂ» prÃ©sentÃ©e dans la figure 1, Ã  ceci prÃšs qu'elle ne contient pas la mention Ã  propos de cette collection). On atteint la page de recherche en cliquant sur le bouton Rechercher. Vous pouvez<i>accÃ©der aux publications par thÃšme</i>en cliquant sur le bouton ThÃšmes. Ceci affiche une liste de thÃšmes, reprÃ©sentÃ©s par des Ã©tagÃšres qu'on peut ensuite dÃ©velopper en cliquant dessus. Vous pouvez<i>accÃ©der aux publications par titre</i>en cliquant sur le bouton titres a-z. Ceci affiche une liste de livres par ordre alphabÃ©tique. Vous pouvez<i>accÃ©der aux publications par organisation</i>en cliquant sur le bouton organisation. Ceci affiche une liste d'organisations. Vous pouvez<i>accÃ©der aux publications par liste de Â«comment faireÂ»</i>en cliquant sur le bouton comment faire. Ceci affiche une liste de Â«comment faireÂ». Tous ces boutons sont visibles dans la figureÂ 1.</Text>
+</Content>
+</Subsection>
+<Subsection id="how_to_read_the_documents">
+<Title>
+<Text id="70">Comment lire les documents</Text>
+</Title>
+<Content>
+<Figure id="a_book_in_the_demo_collection">
+<Title>
+<Text id="71">Un livre de la collection Â«DemoÂ»</Text>
+</Title>
+<File url="images/User_Fig_2.png"/>
+</Figure>
+<Text id="72">Dans la collection Â«DemoÂ», on sait qu'on est arrivÃ© Ã  un livre particulier quand on voit apparaÃ®tre la photographie de sa couverture (comme sur la figureÂ 2). Une table des matiÃšres jouxte cette image: la ligne en gras marque l'endroit courant, qui est dans le cas prÃ©sent Introduction and Summary (Â«introduction et rÃ©sumÃ©Â»), c'est-Ã -dire la premiÃšre section du livre considÃ©rÃ©. On peut dÃ©velopper cette table des matiÃšres: cliquer sur les dossiers aura pour effet de les ouvrir ou de les fermer. Cliquer sur le livre ouvert au sommet le fermera.</Text>
+<Text id="73">Vient ensuite le texte de la section courante (The international demand for tropical butterflies...Â --Â Â«la demande internationale en papillons tropicaux...Â» dans l'exemple citÃ©, juste sous l'illustration). Ã la fin de la lecture, des flÃšches vous proposeront de passer Ã  la section suivante ou de revenir sur la section prÃ©cÃ©dente.</Text>
+<Text id="74">Sous la photographie, on trouve quatre boutons. Cliquer sur DÃ©tacher crÃ©era une nouvelle fenÃªtre de navigateur pour ce seul livre (ce qui est utile si on souhaite comparer des livres, ou en lire plusieurs Ã  la fois). Si vous avez atteint ce livre suite Ã  une opÃ©ration de recherche, les termes de la recherche seront mis en valeur: le bouton Supprimer la mise en Ã©vidence dÃ©sactive cette fonctionnalitÃ©. Cliquer sur DÃ©velopper le texte dÃ©veloppera tout le texte de la section ou du livre en cours. Cliquer sur DÃ©velopper le contenu prÃ©sentera toute la table des matiÃšres du livre, de sorte que vous pourrez voir les titres de tous les chapitres et sous-sections.</Text>
+<Text id="75">Dans certaines collections, les documents ne disposent pas d'une telle structure hiÃ©rarchique. Dans ce cas, aucune table des matiÃšres n'est affichÃ©e lorsque l'on parvient sur un document particulierÂ --Â on ne dispose alors que du texte du document. Dans certains cas, le document est divisÃ© en pages, qu'on peut alors lire dans l'ordre, ou passer d'une page Ã  une autre.</Text>
+</Content>
+</Subsection>
+<Subsection id="what_the_icons_mean">
+<Title>
+<Text id="76">Signification des icones</Text>
+</Title>
+<Content>
+<Text id="77">Lorsque vous naviguerez dans la collection, vous trouverez les Ã©lÃ©ments prÃ©sentÃ©s au tableauÂ 3.</Text>
+</Content>
+</Subsection>
+<Subsection id="how_to_search_for_particular_words">
+<Title>
+<Text id="78">Comment rechercher des mots-clefs particuliers</Text>
+</Title>
+<Content>
+<Text id="79">Ã partir de la page de recherche, suivez les Ã©tapes suivantes pour effectuer une requÃªte:</Text>
+<BulletList>
+<Bullet>
+<Text id="80">SpÃ©cifiez les unitÃ©s concernÃ©es par la recherche: dans la collection Â«DemoÂ» vous pouvez effectuer des recherches dans les titres des sections ou dans le corps du texte des livres.</Text>
+</Bullet>
+<Bullet>
+<Text id="81">PrÃ©cisez si vous souhaitez rechercher tout ou partie des mots-clefs indiquÃ©s.</Text>
+</Bullet>
+<Bullet>
+<Text id="82">Tapez les mots que vous souhaitez rechercher dans la boÃ®te de requÃªte.</Text>
+</Bullet>
+<Bullet>
+<Text id="83">Cliquez sur le bouton DÃ©buter la recherche.</Text>
+</Bullet>
+</BulletList>
+<Text id="84">Lorsque vous effectuez une requÃªte, les titres des documents correspondants seront prÃ©sentÃ©s par paquets de 20 au maximum. Un bouton situÃ© Ã  la fin vous emmÃ©nera aux 20 suivants, d'oÃ¹ d'autres boutons vous emmÃ©neront aux 20 suivants, ou vous permettront de revenir 20 premiers, et ainsi de suite. Cependant, des soucis d'efficacitÃ© ont dictÃ© le choix d'un maximum de 100 documents renvoyÃ©s pour toute requÃªte. Vous pourrez changer ces nombres en cliquant sur le bouton prÃ©fÃ©rences situÃ© au sommet de la page.</Text>
+<Table id="table_icons_that_you_will_encounter_when_browsing">
+<Title>
+<Text id="85">Icones que vous rencontrerez lors de la navigation</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="">
+<File url="images/User_Icon_10.png" height="16"/>
+</th>
+<th width="283">
+<Text id="86">Cliquez sur l'icone d'un livre pour lire le livre correspondant</Text>
+</th>
+</tr>
+<tr>
+<th width="">
+<File url="images/User_Icon_11.png" height="16"/>
+</th>
+<th width="283">
+<Text id="87">Cliquez sur une Ã©tagÃšre pour examiner les livres relatifs Ã  ce thÃšme</Text>
+</th>
+</tr>
+<tr>
+<th width="">
+<File url="images/User_Icon_12.png" height="16"/>
+</th>
+<th width="283">
+<Text id="88">Visualiser ce document</Text>
+</th>
+</tr>
+<tr>
+<th width="">
+<File url="images/User_Icon_13.png" height="16"/>
+</th>
+<th width="283">
+<Text id="89">Ouvrir ce dossier et visualiser son contenu</Text>
+</th>
+</tr>
+<tr>
+<th width="">
+<File url="images/User_Icon_14.png" height="16"/>
+</th>
+<th width="283">
+<Text id="90">Cliquez sur cette icone pour fermer le livre</Text>
+</th>
+</tr>
+<tr>
+<th width="">
+<File url="images/User_Icon_15.png" height="16"/>
+</th>
+<th width="283">
+<Text id="91">Cliquez sur cette icone pour fermer le dossier</Text>
+</th>
+</tr>
+<tr>
+<th width="">
+<File url="images/User_Icon_16.png" height="16"/>
+</th>
+<th width="283">
+<Text id="92">Cliquez sur la flÃšche pour continuer vers la prochaine section...</Text>
+</th>
+</tr>
+<tr>
+<th width="">
+<File url="images/User_Icon_17.png" height="16"/>
+</th>
+<th width="283">
+<Text id="93">...ou pour revenir Ã  la section prÃ©cÃ©dente</Text>
+</th>
+</tr>
+<tr>
+<th width="">
+<File url="images/User_Icon_18.png" height="16"/>
+</th>
+<th width="283">
+<Text id="94">Ouvrir cette page dans une nouvelle fenÃªtre</Text>
+</th>
+</tr>
+<tr>
+<th width="">
+<File url="images/User_Icon_19.png" height="16"/>
+</th>
+<th width="283">
+<Text id="95">DÃ©velopper la table des matiÃšres</Text>
+</th>
+</tr>
+<tr>
+<th width="">
+<File url="images/User_Icon_20.png" height="16"/>
+</th>
+<th width="283">
+<Text id="96">Afficher tout le texte</Text>
+</th>
+</tr>
+<tr>
+<th width="">
+<File url="images/User_Icon_21.png" height="16"/>
+</th>
+<th width="283">
+<Text id="97">Mettre en valeur les termes de la recherche</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="98">Cliquer sur le titre de tout document ou sur la petite icone qui le jouxte aura pour effet de l'ouvrir. L'icone peut reprÃ©senter un livre, un dossier, ou une page: ce sera un livre si vous recherchez parmi des livres; dans le cas contraire, si vous recherchez parmi des sections, ce sera une icone de dossier ou de page selon que la section trouvÃ©e dispose ou non de sous-sections.</Text>
+<Part id="search_terms">
+<Title>
+<Text id="99"><i>Termes de la recherche</i></Text>
+</Title>
+<Content>
+<Text id="100">Ce que vous taperez dans la boÃ®te de requÃªte sera interprÃ©tÃ© comme une liste de mots appelÃ©e Â«termes de la rechercheÂ». Chaque terme de la recherche ne peut contenir que des lettres de l'alphabet ou des chiffres, et les termes sont sÃ©parÃ©s par des blancs. Tous les autres caractÃšres apparaissant, tels que des signes de ponctuation, seront interprÃ©tÃ©s comme des sÃ©parateurs de termes, exactement comme les blancs. Ils ne seront donc pas pris en compte: vous ne pouvez pas rechercher des mots incluant des signes de ponctuation.</Text>
+<Text id="101">Par exemple, la requÃªte:</Text>
+<Text type="code" id="102">Agro-forestry in the Pacific Islands: Systems for Sustainability (1993)<br/>(Â«agriculture-et-forÃªt dans les Ã®les du Pacifique: systÃšmes de durabilitÃ© (1993)Â»)</Text>
+<Text id="103">sera traitÃ©e exactement comme:</Text>
+<Text type="code" id="104">Agro forestry in the Pacific Islands Systems for Sustainability 1993<br/>(Â«agriculture et forÃªt dans les Ã®les du Pacifique systÃšmes de durabilitÃ© 1993Â»)</Text>
+</Content>
+</Part>
+<Part id="query_type">
+<Title>
+<Text id="105"><i>Types de requÃªtes</i></Text>
+</Title>
+<Content>
+<Text id="106">On trouve deux types de requÃªtes:</Text>
+<BulletList>
+<Bullet>
+<Text id="107">Des requÃªtes sur tous les termes. Ces requÃªtes recherchent des documents (ou des chapitres, ou des titres) qui contiennent tous les termes spÃ©cifiÃ©s. Les documents qui satisfont la requÃªte sont affichÃ©s.</Text>
+</Bullet>
+<Bullet>
+<Text id="108">Des requÃªtes sur certains termes. Contentez-vous de lister des termes susceptibles d'apparaÃ®tre dans les documents que vous recherchez. Les documents sont affichÃ©s par ordre de degrÃ© de satisfaction de la requÃªte. Lors du calcul du degrÃ© de satisfaction d'une requÃªte:</Text>
+<BulletList>
+<Bullet>
+<Text id="109">plus un document contient de termes de recherche, mieux il correspond;</Text>
+</Bullet>
+<Bullet>
+<Text id="110">les termes rares sont plus importants que les termes communs;</Text>
+</Bullet>
+<Bullet>
+<Text id="111">les documents courts reÃ§oivent un score plus Ã©levÃ© que les documents volumineux.</Text>
+</Bullet>
+</BulletList>
+</Bullet>
+</BulletList>
+</Content>
+</Part>
+<Text id="112">Utilisez autant de termes de recherche que vous le dÃ©sirezÂ --Â une phrase complÃšte, ou mÃªme un paragraphe complet. Si vous ne spÃ©cifiez qu'un seul terme, le choix d'une requÃªte sur tous les termes ou sur certains termes n'aura que peu d'importance, Ã  ceci prÃšs que dans le second cas, les rÃ©sultats seront triÃ©s en fonction de la frÃ©quence d'apparition du terme de la recherche.</Text>
+</Content>
+</Subsection>
+<Subsection id="scope_of_queries">
+<Title>
+<Text id="113">PortÃ©e des requÃªtes</Text>
+</Title>
+<Content>
+<Text id="114">Dans la plupart des collections vous pourrez choisir parmi diffÃ©rents index de recherche. On peut trouver par exemple des index des auteurs ou des titres, ou bien des chapitres ou des paragraphes. En gÃ©nÃ©ral, tout le document correspondant est renvoyÃ©, quel que soit l'index de recherche utilisÃ©.</Text>
+<Text id="115">Si les documents sont des livres, ils seront ouverts Ã  l'endroit appropriÃ©.</Text>
+</Content>
+</Subsection>
+<Subsection id="advanced_search_features">
+<Title>
+<Text id="116">FonctionnalitÃ©s de recherche avancÃ©e</Text>
+</Title>
+<Content>
+<Text id="117">MÃªme si la plupart des besoins de recherche sont satisfaits par ce qui est dÃ©crit ci-dessus, Greenstone propose des fonctionnalitÃ©s de recherche avancÃ©e. On les active Ã  partir de la page de prÃ©fÃ©rences, qu'on atteint en cliquant sur le bouton prÃ©fÃ©rences, situÃ© au sommet de la page. AprÃšs avoir modifiÃ© vos prÃ©fÃ©rences, ne revenez pas Â«en arriÃšreÂ» dans votre navigateurÂ --Â cela aurait pour effet d'annuler les modifications. Cliquez plutÃŽt sur n'importe lequel des boutons de la barre de recherche/navigation.</Text>
+<Part id="case_sensitivity_and_stemming">
+<Title>
+<Text id="118"><i>DÃ©pendance Ã  la casse et troncature</i></Text>
+</Title>
+<Content>
+<Text id="119">Lors de la spÃ©cification de termes de recherche, on peut dÃ©cider si les majuscules et minuscules doivent correspondre entre la requÃªte et le document: c'est la Â«dÃ©pendance Ã  la casseÂ». On peut aussi choisir de ne prendre en compte que les racines des mots et d'ignorer les terminaisons: c'est la Â«troncatureÂ».</Text>
+<Text id="120">Sous Options de recherche dans la page prÃ©fÃ©rences, vous trouverez deux boutons libellÃ©s ignorer la casse et les majuscules et les minuscules doivent correspondre; ces boutons contrÃŽlent la dÃ©pendance Ã  la casse. Suivent deux boutons libellÃ©s ignorer la fin des mots et le mot entier doit correspondre: ils contrÃŽlent la troncature.</Text>
+<Text id="121">Si on sÃ©lectionne par exemple les boutons ignorer la casse et ignorer la fin des mots, la requÃªte:</Text>
+<Text type="code" id="122">African building<br/>(Â«Africaine constructionÂ»)</Text>
+<Text id="123">sera traitÃ©e de la mÃªme maniÃšre que:</Text>
+<Text type="code" id="124">africa builds<br/>(Â«afrique construitÂ»)</Text>
+<Text id="125">car la majuscule du mot Â«AfricanÂ» sera transformÃ©e en minuscule, et car les suffixes Â«nÂ» et Â«ingÂ» seront respectivement ÃŽtÃ©s des mots Â«AfricanÂ» et Â«buildingÂ» (de mÃªme, le suffixe Â«sÂ» serait ÃŽtÃ© du mot Â«buildsÂ»).</Text>
+<Text id="126">On conseille en gÃ©nÃ©ral d'ignorer la casse et les terminaisons sauf dans le cadre de recherches de mots ou d'acronymes particuliers.</Text>
+</Content>
+</Part>
+<Part id="phrase_searching">
+<Title>
+<Text id="127"><i>Recherche de groupes de mots</i></Text>
+</Title>
+<Content>
+<Text id="128">Si votre requÃªte comprend un groupe de mots entre apostrophes doubles (""), seuls les documents contenant ce groupe de mots, exactement tel que saisi par vous, seront renvoyÃ©s.</Text>
+<Text id="129">Si vous souhaitez utiliser la recherche de groupes de mots, il vous faut apprendre un peu son fonctionnement. Les groupes de mots sont traitÃ©s par un examen post-recherche. D'abord, la requÃªte est effectuÃ©e de la maniÃšre habituelleÂ --Â tous les mots du groupe de mots sont inclus dans les termes de la rechercheÂ --Â puis les documents renvoyÃ©s sont examinÃ©s pour Ã©liminer ceux oÃ¹ le groupe de mots prÃ©cisÃ© n'apparaÃ®t pas.</Text>
+<Text id="130">Lors de l'examen post-recherche, les groupes de mots sont pris tels qu'ils sont, et ceci inclut tout signe de ponctuation. Par exemple, la requÃªte:</Text>
+<Text type="code" id="131">what's a "post-retrieval scan?"<br/>(qu'est-ce qu'un Â«examen post-rechercheÂ»?)</Text>
+<Text id="132">rapatriera d'abord tous les documents correspondant aux mots:</Text>
+<CodeLine>what s a post retrieval scan</CodeLine>
+<Text id="133">puis les documents renvoyÃ©s seront examinÃ©s Ã  la recherche du groupe de mots:</Text>
+<Text type="code" id="134">post-retrieval scan?<br/>(examen post-recherche?)</Text>
+<Text id="135">Les recherches de groupes de mots sont indÃ©pendantes de la casse si on a sÃ©lectionnÃ© le bouton ignorer la casse sur la page prÃ©fÃ©rences.</Text>
+</Content>
+</Part>
+<Part id="advanced_query_mode">
+<Title>
+<Text id="136"><i>Mode de requÃªte avancÃ©</i></Text>
+</Title>
+<Content>
+<Text id="137">Dans le mode de requÃªte avancÃ©, qu'on peut sÃ©lectionner sur la page de prÃ©fÃ©rences, les requÃªtes pour tous les mots, telles que dÃ©crites ci-dessus, sont en rÃ©alitÃ© des requÃªtes boolÃ©ennes. Elles consistent en une liste de termes reliÃ©s par des opÃ©rateurs logiques Â«<i>&amp;</i>Â» (et), Â«<i>|</i>Â» (ou), et Â«<i>!</i>Â» (non). Toute absence d'opÃ©rateur entre des termes de recherche sera interprÃ©tÃ©e comme un Â«<i>&amp;</i>Â» (et): c'est pourquoi une recherche ne prÃ©cisant aucun opÃ©rateur renvoie des documents contenant tous les termes de la requÃªte.</Text>
+<Text id="138">Si les mots Â«ANDÂ», Â«ORÂ», et Â«NOTÂ»<FootnoteRef id="1"/>apparaissent dans votre requÃªte, ils sont traitÃ©s comme des termes de recherche ordinaires, et non pas comme des opÃ©rateurs. Pour utiliser les opÃ©rateurs il faut prÃ©ciser Â«<i>&amp;</i>Â», Â«<i>|</i>Â», et Â«<i>!</i>Â». On peut de plus utiliser des parenthÃšses pour prÃ©ciser les prioritÃ©s.</Text>
+</Content>
+</Part>
+<Part id="using_search_history">
+<Title>
+<Text id="139"><i>Utiliser l'historique de recherche</i></Text>
+</Title>
+<Content>
+<Text id="140">En activant la fonctionnalitÃ© d'Historique de la recherche dans la page de prÃ©fÃ©rences, vous aurez accÃšs Ã  vos derniÃšres recherches, ainsi qu'une vue synthÃ©tique du nombre de rÃ©sultats qu'elles ont fourni. Cliquez sur le bouton jouxtant l'une des recherches antÃ©rieures pour copier le texte de cette recherche dans la boÃ®te de requÃªte. Ceci facilite la rÃ©pÃ©tition de versions lÃ©gÃšrement modifiÃ©es de requÃªtes prÃ©cÃ©dentes. </Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="changing_the_preferences">
+<Title>
+<Text id="141">Changer les prÃ©fÃ©rences</Text>
+</Title>
+<Content>
+<Figure id="the_preferences_page">
+<Title>
+<Text id="142">La page de Â«prÃ©fÃ©rencesÂ»</Text>
+</Title>
+<File url="images/User_Fig_3.png"/>
+</Figure>
+<Text id="143">Cliquer sur le bouton prÃ©fÃ©rences situÃ© en haut de la page vous permettra de modifier certains aspects de l'interface pour qu'elle corresponde mieux Ã  vos propres souhaits. Les prÃ©fÃ©rences sont propres Ã  la collection; vous en trouverez un exemple dans la figureÂ 3. Lors de l'ajustement des prÃ©fÃ©rences de recherche, il vaut mieux cliquer sur le bouton Appliquer (illustrÃ© figure 3Â ). AprÃšs le positionnement des prÃ©fÃ©rences, ne revenez pas Â«en arriÃšreÂ» dans votre navigateurÂ --Â cela aurait pour effet d'annuler les modifications. Cliquez plutÃŽt sur n'importe lequel des boutons de la barre d'accÃšs, vers le haut de la page.</Text>
+<Subsection id="collection_preferences">
+<Title>
+<Text id="144">PrÃ©fÃ©rences de collection</Text>
+</Title>
+<Content>
+<Text id="145">Certaines collections comprennent plusieurs sous-collections, dans lesquelles on peut mener des recherches indÃ©pendantes ou groupÃ©es, comme si elles ne formaient qu'une unitÃ©. Si c'est le cas, vous pouvez choisir quelles sous-collections inclure dans vos recherches dans la page de prÃ©fÃ©rences.</Text>
+</Content>
+</Subsection>
+<Subsection id="language_preferences">
+<Title>
+<Text id="146">PrÃ©fÃ©rences de langue</Text>
+</Title>
+<Content>
+<Text id="147">Chaque collection dispose d'une langue de prÃ©sentation par dÃ©faut, mais vous pouvez choisir une autre langue si tel est votre dÃ©sir. Vous pouvez aussi modifier l'encodage utilisÃ© par Greenstone en alimentation de votre navigateurÂ --Â le logiciel a des valeurs par dÃ©faut raisonnables, mais un autre encodage fournit de meilleurs rÃ©sultats sur certains navigateurs. Toutes les collections permettent de passer d'une interface graphique standard Ã  une interface textuelle. Ceci est particuliÃšrement utile pour les mal voyants utilisant de grosses polices Ã  l'Ã©cran, ou pour les personnes utilisant un synthÃ©tiseur vocal sur leur ordinateur.</Text>
+</Content>
+</Subsection>
+<Subsection id="presentation_preferences">
+<Title>
+<Text id="148">PrÃ©fÃ©rences de prÃ©sentation</Text>
+</Title>
+<Content>
+<Text id="149">Selon les collections, on peut trouver d'autres options pour contrÃŽler la prÃ©sentation. Les collections de pages web vous permettront de supprimer la barre de navigation de Greenstone au sommet de chaque page de document, de telle sorte qu'une recherche vous mÃšne directement Ã  la page web correspondante, sans en-tÃªte Greenstone. Pour mener une autre recherche il vous faudra revenir Â«en arriÃšreÂ» dans votre navigateur. Ces collections vous permettront Ã©galement de supprimer le message d'avertissement de Greenstone lorsque vous cliquerez sur un lien qui vous mÃ©nera hors de la collection de bibliothÃšques numÃ©riques, vers le web. Enfin, certaines collections web vous permettront de dÃ©cider si les liens de la page de RÃ©sultats de la recherche doivent vous mener directement vers l'URL concernÃ©e, ou vers une copie de la page au niveau de la bibliothÃšque numÃ©rique.</Text>
+</Content>
+</Subsection>
+<Subsection id="search_preferences">
+<Title>
+<Text id="150">PrÃ©fÃ©rences de recherche</Text>
+</Title>
+<Content>
+<Text id="151">Sous PrÃ©fÃ©rences de recherche dans la figureÂ 3, les deux premiers boutons vous permettent d'obtenir une grosse boÃ®te de requÃªte, de maniÃšre Ã  effectuer facilement des recherches de la taille d'un paragraphe. Dans Greenstone, il est Ã©tonnamment rapide de rechercher des portions importantes de texte. Les deux paires de boutons suivantes contrÃŽlent le type de texte trouvÃ© par les recherches effectuÃ©es. Le premier groupe (libellÃ© Respecter la casse:) contrÃŽle la distinction majuscules/minuscules. Le second groupe, La fin des mots:, contrÃŽle la prise en compte ou non des fins de mots.</Text>
+<Text id="152">Le prochain couple de boutons vous fera passer en mode de recherche Â«avancÃ©eÂ», tel que dÃ©crit ci-dessus, ce qui vous permettra de spÃ©cifier des requÃªtes plus prÃ©cises en combinant des termes par les opÃ©rations Â«etÂ» (<i>&amp;</i>), Â«ouÂ» (<i>|</i>), et Â«nonÂ» (<i>!</i>). Vous pouvez activer ou dÃ©sactiver la fonctionnalitÃ© d'historique de recherche, mentionnÃ©e prÃ©cÃ©demment. Enfin, vous pouvez contrÃŽler le nombre de rÃ©sultats renvoyÃ©s, ainsi que le nombre de rÃ©sultats prÃ©sentÃ©s sur chaque Ã©cran, grÃ¢ce Ã  la derniÃšre entrÃ©e de la figureÂ 3.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="making_greenstone_collections">
+<Title>
+<Text id="153">CrÃ©er une collection Greenstone</Text>
+</Title>
+<Content>
+<Text id="154">La voie la plus simple pour crÃ©er de nouvelles bibliothÃšques est d'utiliser "Greenstone Librarian Interface" (l'Interface BibliothÃ©caire de Greenstone), GLI. Cela vous permet de rassembler une sÃ©rie de documents, importer ou assigner des mÃ©ta-donnÃ©es, de les intÃ©grer dans une collection Greenstone. Elle permet cinq activitÃ©s de base qui peuvent Ãªtre interpolÃ©es mais qui sont normalement entreprises dans cet ordre:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="155">Copier le document de l'espace fichiers de l'ordinateur, y compris les collections existantes, vers la nouvelle collection. Toute mÃ©ta-donnÃ© existante reste "attachÃ©e" Ã  ces documents. Des documents peuvent Ãªtre collectÃ©s Ã  partir du web par le biais d'une fonctionnalitÃ© de mirroring incorporÃ©e.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="156">Enrichir les documents en ajoutant des mÃ©tadatas supplÃ©mentaires Ã  des documents individuels ou des groupes de documents.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="157">Concevoir la bibliothÃšque en dÃ©terminant son aspect et les fonctionnalitÃ©s d'accÃšs qu'elle permet.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="158">Mettre sur pied la bibliothÃšque en utilisant Greenstone. </Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="159">PrÃ©visualiser la bibliothÃšque nouvellement crÃ©Ã©e, qui aura Ã©tÃ© installÃ©e dans votre page Greenstone en tant que collection ordinaire.</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="160">"Librarian Interface" (l'Interface BibliothÃ©caire) vous permet d'ajouter aux documents ce qu'on appelle mÃ©ta-donnÃ©es "externes", des mÃ©ta-donnÃ©es rattachÃ©es au document dans son ensemble. Mais les documents ont souvent besoin d'Ãªtre structurÃ©s en sections et sous sections, et des mÃ©ta-donnÃ©es "internes" peuvent Ãªtre associÃ©es Ã  chaque partie. Dans Greenstone, des documents sources peuvent Ãªtre "marquÃ©s" avec cette information, ce qui sera expliquÃ© dans la sectionÂ 3.3.</Text>
+<Text id="161">Enfin, une autre alternative pour la crÃ©ation de collections est fournie par le Collecteur "Collector" qui aide Ã  confectionner de nouvelles collections, de modifier ou d'ajouter des Ã©lÃ©ments Ã  des collections existantes, ou de supprimer des collections. Dans la plupart des cas, le "Librarian Interface" (l'Interface BibliothÃ©caire), plus recent, devrait Ãªtre utilisÃ© en lieu et place du collecteur. Ceci sera dÃ©crit dans la sectionÂ 3.4.</Text>
+<Text id="162">Pour utiliser la puissance entiÃšre de Greenstone pour construire des collections avancÃ©es il faut aussi lire chapitre 2 du Guide de dÃ©veloppeur.</Text>
+<Section id="the_librarian_interface">
+<Title>
+<Text id="163">l'Interface du BibliothÃ©caire</Text>
+</Title>
+<Content>
+<Text id="164">Examinons un exemple simple pour expliquer le fonctionnement de l'Interface du BibliothÃ©caire de greenstone. Les figures de 4 Ã  15 sont des captures d'Ã©cran en divers points durant l'interaction. Cet exemple utilise les documents de la collection DLS "Development Library subset" qui est distribuÃ©e avec Greenstone. Pour des besoins de l'exposÃ©, la procÃ©dure prend la forme d'un passage simple Ã  travers les Ã©tapes Ã©numÃ©rÃ©es ci-dessus. Un modÃšle d'utilisation plus rÃ©aliste pour les utilisateurs est de passer successivement de l'avant Ã  l'arriiÃšre Ã  travers les diffÃ©rentes Ã©tapes au fur et Ã  mesure que l'exÃ©cution se poursuit.</Text>
+<Text id="165">L'interface bibliothÃ©caire peut fonctionner dans un de 4 mode: Assistant BibliothÃ©caire, BibliothÃ©caire, SpÃ©cialiste des Systemes BibliothÃ©caires, et Expert. Ces modes cotrolent les niveaux de dÃ©tails dans l'interface, et peut etre changÃ© Ã  travers 'PrÃ©fÃ©rences' par le menu 'Fichier'. Pour consulter cette partie, il faut que l'interface soit dans le mode prÃ©-construit, BibliothÃ©caire.</Text>
+<Subsection id="getting_started">
+<Title>
+<Text id="166">DÃ©marrage</Text>
+</Title>
+<Content>
+<Text id="167">Lancer le "Librarian Interface" (l'Interface BibliothÃ©caire) sous Windows en sÃ©lectionnant "Greenstone Digital Library" (BibliothÃšque numÃ©rique de Greenstone) dans la section des Programmes du menu "DÃ©marrer" et en choisissant "Librarian Interface". SI vous utilisez Unix, taper plutÃŽt:</Text>
+<CodeLine>cd ~/gsdl cd gli ./gli.sh</CodeLine>
+<Text id="168">oÃ¹Â /gsdl est le rÃ©pertoire contenant le systÃšme Greenstone. Pour commencer, on peut soit ouvrir une collection existante, soit en dÃ©buter une nouvelle. La figureÂ 4montre l'utilisateur en train de dÃ©buter une nouvelle collection. Il a sÃ©lectionnÃ© "Nouveau" dans le menu Fichier et a commencÃ© Ã  fournir les informations gÃ©nÃ©rales sur la collectionÂ --Â son titre, l'adresse Ã©lectronique de la personne responsable et une description sommaire du contenu, dans une fenÃªtre pop up. Le titre de la collection est une courte expression utilisÃ©e dans la bibliothÃšque numÃ©rique pour identifier le contenu de la collection : les collections existantes ont des noms tels que BibliothÃšque de la nourriture et de l'alimentation, BibliothÃšque de l'environnement Mondial et ainsi de suite. Lorsque vous tapez le titre, le systÃšme attribue un identificateur mnÃ©motechnique unique, le "nom" de la collection, pour un usage interne (Vous pouvez le changer si vous voulez). L'adresse Ã©lectronique prÃ©cise le premier point de contact pour tout problÃšme rencontrÃ© avec la collection.</Text>
+<Text id="169">La description sommaire est une dÃ©claration qui dÃ©crit les principes qui gouvernent ce qui est inclus dans la collection. Il apparaÃ®t sous le titre "Ã propos de cette collection" sur la page initiale de la collection.</Text>
+<Figure id="starting_a_new_collection">
+<Title>
+<Text id="170">CrÃ©ation d'une nouvelle collection</Text>
+</Title>
+<File url="images/User_Fig_4.png"/>
+</Figure>
+<Figure id="exploring_the_local_file_space">
+<Title>
+<Text id="171">Exploration de l'espace de fichiers local</Text>
+</Title>
+<File url="images/User_Fig_5.png"/>
+</Figure>
+<Text id="172">A ce point, l'utilisateur dÃ©cide soit de baser la nouvelle collection sur la structure d'une collection existante, soit de crÃ©er une collection d'un type totalement nouveau. Dans la figureÂ 4, il a choisi de la baser sur la collection DLS " Development Library Subset ". Cela implique que la sÃ©rie de mÃ©ta-donnÃ©es "DLS" qui est utilisÃ©e dans cette collection sera utilisÃ©e dans la nouvelle collection. (En fait, cette sÃ©rie de mÃ©ta-donnÃ©es a Ã©tÃ© utilisÃ©e pour mettre sur pied plusieurs collections Greenstone qui partagent une structure et une organisation communes mais avec un contenu diffÃ©rent, comme les collections DLS "Development Library Subset" et la collection de dÃ©monstration fournies comme modÃšles avec Greenstone.</Text>
+<Text id="173">Le jeu de mÃ©ta-donnÃ©es de DLS contient les Ã©lÃ©ments suivants:</Text>
+<BulletList>
+<Bullet>
+<Text id="174">Titre</Text>
+</Bullet>
+<Bullet>
+<Text id="175">Sujet</Text>
+</Bullet>
+<Bullet>
+<Text id="176">Langue</Text>
+</Bullet>
+<Bullet>
+<Text id="177">Organisation</Text>
+</Bullet>
+<Bullet>
+<Text id="178">Mot-clÃ© (c.-Ã -d. "Howto")</Text>
+</Bullet>
+</BulletList>
+<Text id="179">(En plus, il y a un Ã©lÃ©ment de mÃ©ta-donnÃ©e appelÃ© "AZList" qui est utilisÃ© pour dÃ©terminer la case de la liste alphabÃ©tique qui contient le titre du document, avec des valeurs comme "A-B" ou "C-D-E". Ceci est utilisÃ© pour avoir un contrÃŽle prÃ©cis sur les divisons Ã  l'intÃ©rieur de la liste. Pour la plupart des autres collections il est absent, et Greenstone attribue lui-mÃªme les rÃ©cipients.)</Text>
+<Text id="180">Si, au contraire, l'utilisateur avait choisi utilise "Nouvelle collection" Ã  ce stade, il lui est demandÃ© de sÃ©lectionner jeux de mÃ©ta-donnÃ©es qui doivent Ãªtre utilisÃ©s dans la nouvelle collection. Trois jeux standard sont prÃ©-fournis: "Dublin Core", le jeu de mÃ©ta-donnÃ©es DLS mentionnÃ©e ci-dessus et un jeu qui comprend les Ã©lÃ©ments de mÃ©ta-donnÃ©es extraits automatiquement par Greenstone Ã  partir des documents de la collection. L'utilisateur peut aussi crÃ©er de nouveaux jeux de mÃ©ta-donnÃ©es en utilisant un paneau popup activÃ© Ã  travers le menu "metadata" (mÃ©ta-donnÃ©es).</Text>
+<Text id="181">Plusieurs jeux de mÃ©ta-donnÃ©es diffÃ©rents peuvent Ãªtre associÃ©s Ã  la mÃªme collection; le systÃšme les maintient distinctes (si bien que par exemple, des documents peuvent avoir Ã  la fois un titre "Dublin Core" et un titre DLS). Les diffÃ©rents jeux sont clairement distinguÃ©es dans l'interface. Dans les coulisses, les jeux de mÃ©ta-donnÃ©es sont reprÃ©sentÃ©s en XML.</Text>
+</Content>
+</Subsection>
+<Subsection id="assembling_the_source_material">
+<Title>
+<Text id="182">Assemblage du matÃ©riel source</Text>
+</Title>
+<Content>
+<Text id="183">AprÃšs avoir cliquÃ© sur le bouton "OK" du popup "Nouvelle collection", les parties restantes de l'interface, qui Ã©taient grises avant, deviennent actives. Le panneau "Rassembler", sÃ©lectionnÃ© par l'onglet Ã©ponyme en haut de la figureÂ 4, est initialement affichÃ©. Ceci permet Ã  l'utilisateur d'explorer l'espace de fichiers local et les collections existantes tout en rassemblant les documents choisis pour la nouvelle collection. Le panneau est divisÃ© en deux sections, celle de gauche pour naviguer parmi les structures existantes et celle de droite pour les documents dans la collection.</Text>
+<Text id="184">Les opÃ©rations disponibles Ã  cette Ã©tape sont:</Text>
+<BulletList>
+<Bullet>
+<Text id="185">Navigation dans la hiÃ©rarchie de la structure existante des fichiers, et dans celle qui est en cours de crÃ©ation, de la maniÃšre usuelle.</Text>
+</Bullet>
+<Bullet>
+<Text id="186">"Glisser-coller" de fichiers dans la nouvelle collection.</Text>
+</Bullet>
+<Bullet>
+<Text id="187">SÃ©lection multiple de fichiers.</Text>
+</Bullet>
+<Bullet>
+<Text id="188">"Glisser-coller" de sous-hiÃ©rarchies entiÃšres.</Text>
+</Bullet>
+<Bullet>
+<Text id="189">Suppression de documents de la collection naissante.</Text>
+</Bullet>
+<Bullet>
+<Text id="190">CrÃ©ation de nouvelles sous-hiÃ©rarchies Ã  l'intÃ©rieur de la collection.</Text>
+</Bullet>
+<Bullet>
+<Text id="191">Filtrage des fichiers visibles aussi bien dans le systÃšme de fichiers local que dans la collection; filtrage basÃ© sur des groupes prÃ©dÃ©terminÃ©s ou sur des termes contenus dans des fichiers.</Text>
+</Bullet>
+<Bullet>
+<Text id="192">Invocation du programme appropriÃ© pour afficher les contenus du fichier sÃ©lectionnÃ© en le double-cliquant.</Text>
+</Bullet>
+</BulletList>
+<Text id="193">Une attention particuliÃšre est prise pour traiter les collisions de noms identiques quand des fichiers de mÃªme nom dans diffÃ©rentes parties de la structure de rÃ©pertoires de l'ordinateur sont copiÃ©s dans le mÃªme rÃ©pertoire de la collection.</Text>
+<Text id="194">Dans la figure 5, l'utilisateur utilise l'affichage interactif de l'arborescence des fichiers pour explorer le systÃšme local de fichiers. A ce stade, la collection sur la droite est vide; l'utilisateur la remplit en opÃ©rant un "glisser-coller" des fichiers d'intÃ©rÃªt du panneau de gauche vers le panneau de droite. De tels fichiers sont "copiÃ©s" plutÃŽt que "dÃ©places": de cette faÃ§on, le systÃšme de fichiers original n'est pas perturbÃ©. Les techniques usuelles de sÃ©lection multiple, de "glisser-coller", de structuration de la nouvelle collection en crÃ©ant des sous-rÃ©pertoires et de suppression de fichiers en les dÃ©plaÃ§ant vers la corbeille, sont toutes disponibles.</Text>
+<Text id="195">Les collections existantes sont reprÃ©sentÃ©es par un sous-rÃ©pertoire Ã  gauche appelÃ© "Collections Greenstone", qui peut Ãªtre ouvert et explorÃ© comme tout autre rÃ©pertoire. Cependant, les documents qui s'y trouvent diffÃšrent des fichiers ordinaires parce qu'ils ont des mÃ©ta-donnÃ©es qui leurs sont attachÃ©es et ceci est conservÃ© quand ils sont dÃ©placÃ©s vers une nouvelle collection. Des conflits peuvent arriver lorsque des mÃ©ta-donnÃ©es ont Ã©tÃ© assignÃ©es en utilisant un jeu de mÃ©ta-donnÃ©es diffÃ©rent de celui en cours d'utilisation, et il revient Ã  l'utilisateur de les rÃ©soudre. Dans la figure 6, l'utilisateur a sÃ©lectionnÃ© des documents Ã  partir de la collection existante et les a ajoutÃ©s Ã  la nouvelle collection. La fenÃªtre pop up explique que l'organisation des Ã©lÃ©ments de mÃ©ta-donnÃ©es ne peut pas Ãªtre automatiquement importÃ©e, et demande Ã  l'utilisateur soit de sÃ©lectionner un jeu de mÃ©ta-donnÃ©es et de cliquer sur "Ajouter" pour ajouter l'Ã©lÃ©ment de mÃ©ta-donnÃ©es Ã  ce jeu<FootnoteRef id="2"/>, soit de choisir un jeu de mÃ©ta-donnÃ©es, puis un Ã©lÃ©ment et ensuite cliquer sur "Fusionner" pour renommer l'ancien Ã©lÃ©ment de mÃ©ta-donnÃ©e en l'Ã©lÃ©ment nouveau en fusionnant les deux. Les mÃ©ta-donnÃ©es dans les documents suivants de la mÃªme collection subiront la mÃªme manipulation.</Text>
+<Text id="196">Lorsque des ensembles importants de fichiers sont sÃ©lectionnÃ©s, dÃ©posÃ©s par un "glisser-coller" dans la nouvelle collection, l'opÃ©ration de copie peut prendre quelque temps surtout quand il y a conversion de mÃ©ta-donnÃ©es. Pour indiquer la progression de l'opÃ©ration, l'interface montre le fichier qui est en train d'Ãªtre copiÃ© et le pourcentage de fichiers dÃ©jÃ  traitÃ©s.</Text>
+<Text id="197">Des fonctionnalitÃ©s spÃ©ciales sont fournies pour le traitement de gros jeux de fichiers. Par exemple, l'utilisateur peut choisir de filtrer l'arborescence des fichiers pour afficher seulement certains fichiers, en utilisant un menu dÃ©roulant de types de fichier affichÃ© en dessous des arborescences. Dans la figure 7, on montre seulement les fichiers HTM et HTML (et seuls ces fichiers seront copiÃ©s par l'opÃ©ration "glisser-coller".</Text>
+</Content>
+</Subsection>
+<Subsection id="enriching_the_documents">
+<Title>
+<Text id="198">Enrichir les documents</Text>
+</Title>
+<Content>
+<Text id="199">La prochaine Ã©tape dans la construction d'une collection consiste Ã  enrichir les documents en y ajoutant des mÃ©ta-donnÃ©es. L'onglet "Enrichir" affiche un nouveau panneau d'information (figureÂ 8), qui montre l'arborescence de documents reprÃ©sentant la collection sur la gauche, et permet, sur la droite, l'ajout de mÃ©ta-donnÃ©es datas Ã  des documents individuels ou des groupes de documents.</Text>
+<Text id="200">Les documents qui sont copiÃ©s durant la premiÃšre Ã©tape viennent avec des mÃ©ta-donnÃ©es quelcoques qui leurs sont associÃ©es. Si un document est une partie de la collection Greenstone, des mÃ©ta-donnÃ©es prÃ©cÃ©demment dÃ©finies sont transfÃ©rÃ©es vers la nouvelle collection. Il est Ã©vident que la nouvelle collection peut avoir un jeu diffÃ©rente de mÃ©ta-donnÃ©es ou, peut Ãªtre tout juste un sous-ensemble des mÃ©ta-donnÃ©es dÃ©finies, et seules les mÃ©ta-donnÃ©es qui appartiennent au jeu de la nouvelle collection sont transfÃ©rÃ©es. La rÃ©solution de tels conflits peut nÃ©cessiter l'intervention de l'utilisateur par le biais d'un dialogue supplÃ©mentaire (figureÂ 6). Tous les choix faits sont enregistrÃ©s et appliquÃ©s pour des copies de fichiers ultÃ©rieures.</Text>
+<Text id="201">Le panneau Enrich permet l'assignation de valeurs de meta-donnÃ©es aux documents de la collection. Par exemple, de nouvelles valeurs peuvent Ãªtre ajoutÃ©es au jeu de valeurs dÃ©jÃ  existantes pour un Ã©lÃ©ment. Si les valeurs de l'Ã©lÃ©ment ont une structure hiÃ©rarchique, la structure peut Ãªtre Ã©tendue de la mÃªme maniÃšre.</Text>
+<Figure id="importing_existing_metadata">
+<Title>
+<Text id="202">Importation de mÃ©ta-donnÃ©es existantes</Text>
+</Title>
+<File url="images/User_Fig_6.png"/>
+</Figure>
+<Figure id="filtering_the_file_trees">
+<Title>
+<Text id="203">Filtrage des arborescences de fichiers</Text>
+</Title>
+<File url="images/User_Fig_7.png"/>
+</Figure>
+<Figure id="assigning_metadata_using_enrich_view">
+<Title>
+<Text id="204">Assignation de mÃ©ta-donnÃ©es en utilisant "Enrich"</Text>
+</Title>
+<File url="images/User_Fig_8.png"/>
+</Figure>
+<Figure id="viewing_all_metadata_for_selected_files">
+<Title>
+<Text id="205">Affichage de toutes les mÃ©ta-donnÃ©es pour des fichiers sÃ©lectionnÃ©s</Text>
+</Title>
+<File url="images/User_Fig_9.png"/>
+</Figure>
+<Text id="206">Des valeurs de mÃ©ta-donnÃ©e peuvent aussi Ãªtre assignÃ©s Ã  des rÃ©pertoires, exactement de la mÃªme maniÃšre. Les documents dans ces rÃ©pertoires pour lesquels cette mÃ©ta-donnÃ©e n'est pas spÃ©cifiÃ©e, hÃ©ritent les valeurs de la mÃ©ta-donnÃ©e. Cependant, elles peuvent Ãªtre Ã©crasÃ©es par la suite en fournissant des valeurs diffÃ©rentes pour ces documents.</Text>
+<Text id="207">Les opÃ©rations Ã  ce stade comprennent:</Text>
+<BulletList>
+<Bullet>
+<Text id="208">Assignation de valeurs de mÃ©ta-donnÃ©es nouvelles ou existente aux documents.</Text>
+</Bullet>
+<Bullet>
+<Text id="209">Assignation de mÃ©ta-donnÃ©e Ã  un document individuel.</Text>
+</Bullet>
+<Bullet>
+<Text id="210">Assignation de mÃ©ta-donnÃ©e Ã  un rÃ©pertoire ( ceci est hÃ©ritÃ© par tous les documents dans le rÃ©pertoire, y compris ceux qui sont des sous-rÃ©pertoires.</Text>
+</Bullet>
+<Bullet>
+<Text id="211">Assignation de mÃ©ta-donnÃ©e hiÃ©rarchique dont la structure peut Ãªtre mise Ã  jour de faÃ§on dynamique si cela est nÃ©cessaire.</Text>
+</Bullet>
+<Bullet>
+<Text id="212">Edition et mise Ã  jour de mÃ©ta-donnÃ©e assignÃ©e.</Text>
+</Bullet>
+<Bullet>
+<Text id="213">Revue de mÃ©ta-donnÃ©es assignÃ©es Ã  une sÃ©lection de fichiers et rÃ©pertoires.</Text>
+</Bullet>
+</BulletList>
+<Text id="214">Pour notre exemple, dans la figureÂ 8l'utilisateur a sÃ©lectionnÃ© le dossier ec121e et a assignÃ© "Ec courier" comme son organisation de mÃ©ta-donnÃ©es. Les boutons pour mettre Ã  jour et supprimer les mÃ©ta-donnÃ©es sont activÃ©es suivant les sÃ©lections effectuÃ©es.</Text>
+<Text id="215">Durant cette phase d'enrichissement, en fait Ã  n'importe quel autre moment, l'utilisateur peut choisir d'afficher toutes les mÃ©ta-donnÃ©es qui ont Ã©tÃ© assignÃ©es aux documents de la collection. Ceci est fait en sÃ©lectionnant une sÃ©rie de documents et en choisissant "MÃ©ta-donnÃ©es assignÃ©es" Ã  partir du menu des jeux de mÃ©ta-donnÃ©es, ce qui ouvre une fenÃªtre popup comme celle de la figureÂ 9qui montre les mÃ©ta-donnÃ©es sous forme d'un tableau. Pour les grandes collections, il est utile de pouvoir afficher les mÃ©ta-donnÃ©es associÃ©es Ã  certains types de documents seulement, et quand l'utilisateur a spÃ©cifiÃ© un filtre de fichiers comme mentionnÃ© ci-dessus, seuls les documents sÃ©lectionnÃ©s sont visibles dans l'affichage des mÃ©ta-donnÃ©es.</Text>
+<Text id="216">Le panneau dans la figureÂ 10permet Ã  l'utilisateur d'Ã©diter les jeux de mÃ©ta-donnÃ©es. Ici, l'utilisateur regarde l'Ã©lÃ©ment "Subject" du jeu DLS. Les valeurs de cet Ã©lÃ©ment forment une hiÃ©rarchie, et l'utilisateur est en train d'examiner et peut Ãªtre de changer la liste des valeurs qui lui sont assignÃ©es. Le mÃªme panneau permet de changer le "profil" pour la mise en correspondance des Ã©lÃ©ments d'un jeu de mÃ©ta-donnÃ©es l'autre. Ce profil est crÃ©Ã© au cours de l'importation de documents Ã  partir de collections qui ont des mÃ©ta-donnÃ©es prÃ©-assignÃ©es.</Text>
+<Figure id="editing_the_metadata_set">
+<Title>
+<Text id="217">Edition deu jeu de mÃ©ta-donnÃ©es</Text>
+</Title>
+<File url="images/User_Fig_10.png"/>
+</Figure>
+<Figure id="designing_the_collection_1">
+<Title>
+<Text id="218">Conception de la collection</Text>
+</Title>
+<File url="images/User_Fig_11.png"/>
+</Figure>
+<Figure id="specifying_which_plug-ins_to_use">
+<Title>
+<Text id="219">SpÃ©cification des plugins Ã  utiliser</Text>
+</Title>
+<File url="images/User_Fig_12.png"/>
+</Figure>
+<Figure id="configuring_arguments_to_a_plug-in">
+<Title>
+<Text id="220">Configuration des arguments de plugin</Text>
+</Title>
+<File url="images/User_Fig_13.png"/>
+</Figure>
+</Content>
+</Subsection>
+<Subsection id="conception_de_la_collection">
+<Title>
+<Text id="221">Conception de la collection</Text>
+</Title>
+<Content>
+<Text id="222">Le panneau de conception (figureÂ 11Â --Â 18) permet la spÃ©cification de la structure, l'organisation et la prÃ©sentation de la collection qui est en train d'Ãªtre crÃ©Ã©e. Comme dÃ©jÃ  notÃ©, le rÃ©sultat de ce processus est enregistrÃ© dans le fichier de configuration de la collection "collection configuration file", qui est le moyen pour Greenstone d'exprimer les fonctionnalitÃ©s requises par une collection. Cette Ã©tape comprend une sÃ©rie d'Ã©crans d'interaction sÃ©parÃ©s, chacun traitant un aspect de la conception de la collection. En effet, il sert d'Ã©quivalent graphique Ã  l'opÃ©ration usuelle d'Ã©dition manuelle du fichier de configuration.</Text>
+<Text id="223">Les opÃ©rations comprennent:</Text>
+<BulletList>
+<Bullet>
+<Text id="224">Revue et Ã©dition de mÃ©ta-donnÃ©es de niveau collection, telles que titre, auteur et accÃšs public Ã  la collection.</Text>
+</Bullet>
+<Bullet>
+<Text id="225">DÃ©finition des indexes de texte complet Ã  construire.</Text>
+</Bullet>
+<Bullet>
+<Text id="226">CrÃ©ation de sous-collections et construction d'indexes Ã  leur allouer. </Text>
+</Bullet>
+<Bullet>
+<Text id="227">Ajout ou suppression de support de langues d'interface prÃ©dÃ©finies.</Text>
+</Bullet>
+<Bullet>
+<Text id="228">Construction d'une liste de plugins Ã  utiliser, et leurs arguments.</Text>
+</Bullet>
+<Bullet>
+<Text id="229">PrÃ©sentation de la liste Ã  l'utilisateur pour revue et modification.</Text>
+</Bullet>
+<Bullet>
+<Text id="230">Configuration de plugins individuels.</Text>
+</Bullet>
+<Bullet>
+<Text id="231">Construction d'une liste de "classificateurs", leurs arguments, affectation et configuration.</Text>
+</Bullet>
+<Bullet>
+<Text id="232">Affectation de chaÃ®nes de formatage Ã  divers contrÃŽles de la collection, en vue de changer son apparence.</Text>
+</Bullet>
+<Bullet>
+<Text id="233">Revue des jeux de mÃ©ta-donnÃ©es utilisÃ©s dans la collection ainsi que leurs Ã©lÃ©ments.</Text>
+</Bullet>
+</BulletList>
+<Text id="234">Dans la figureÂ 11, l'utilisateur a cliquÃ© sur l'onglet "Conception" et Ã©tudie les informations gÃ©nÃ©rales sur la collection, entrÃ©es lors de la crÃ©ation de la nouvelle collection. A gauche, sont listÃ©s les diffÃ©rentes facettes que l'utilisateur peut configurer : GÃ©nÃ©ral, Plug-ins de document , Type de recherche, Indexes de recherche, Indexes de partition, Recherche inter-collection, Classificateurs de navigation, FonctionnalitÃ©s de formatage, Traduction de texte, Jeux de mÃ©ta-donnÃ©es. L'apparence et la fonctionnalitÃ© varient entre celles-ci. Par exemple, en cliquant sur Plug-in, on a l'Ã©cran de la figureÂ 12qui vous permet d'ajouter, de supprimer ou de configurer des plugins, et de changer l'ordre dans lequel les plugins sont appliquÃ©s aux documents.</Text>
+<Text id="235">Les plugins et les classificateurs disposent de plusieurs arguments ou "Options" que l'utilisateur peut fournir. La boÃ®te de dialogue dans la figureÂ 13montre l'utilisateur prÃ©cisant des arguments Ã  certains plugins. Les champs grisÃ©s deviennent actifs quand l'utilisateur ajoute l'option en cliquant sur la case Ã  cocher se trouvant Ã  cÃŽtÃ©. Puisque Greenstone est un systÃšme open-source en croissance continuelle, le nombre d'options tend Ã  augmenter au fur et Ã  mesure que les dÃ©veloppeurs ajoutent de nouvelles fonctionnalitÃ©s. Pour aider Ã  y faire face, Greenstone a un programme fonctionnel "Plug-in information " qui liste les options disponibles pour chaque plugin, et le "Librarian Interface" (l'Interface BibliothÃ©caire) l'invoque automatiquement pour dÃ©terminer quelle option montrer. Ceci permet Ã  l'interface interactive de l'utilisateur de suivre automatiquement les dÃ©veloppements dans le logiciel.</Text>
+<Figure id="getting_ready_to_create_new_collection">
+<Title>
+<Text id="236">PrÃªt pour crÃ©er la nouvelle collection</Text>
+</Title>
+<File url="images/User_Fig_14.png"/>
+</Figure>
+<Figure id="previewing_the_newly_built_collection">
+<Title>
+<Text id="237">AperÃ§u de la collection nouvellement crÃ©Ã©e</Text>
+</Title>
+<File url="images/User_Fig_15.png"/>
+</Figure>
+</Content>
+</Subsection>
+<Subsection id="building_the_collection">
+<Title>
+<Text id="238">Construction de la collection</Text>
+</Title>
+<Content>
+<Text id="239">Le panneau "CrÃ©er" (figureÂ 14) est utilisÃ© pour construire une collection basÃ©e sur les documents et d'assigner des mÃ©ta-donnÃ©es. Le plus gros du travail est fait par le code Greenstone lui-mÃªme. L'utilisateur contrÃŽle le dÃ©roulement externe Ã  travers une sÃ©rie d'Ã©crans interactifs, chacun traitant les arguments fournis Ã  une certaine Ã©tape du processus de crÃ©ation.</Text>
+<Text id="240">L'utilisateur observe la construction en cours Ã  travers une fenÃªtre qui montre non seulement le texte gÃ©nÃšrÃ© par les scripts d'importation et de construction d'index, mais aussi par les barres de progression qui indiquent le degrÃ© global d'exÃ©cution de chaque script.</Text>
+<Text id="241">La figureÂ 14montre le "Create View" (Affichage CrÃ©er). Des options, pouvant Ãªtre appliquÃ©es pendant la crÃ©ation de ce processus, sont montrÃ©es en haut. L'utilisateur sÃ©lectionne les valeurs appropriÃ©es pour les options. La figure illustre un popup "tool tip" (boÃ®te Ã  outils) qui est disponible Ã  travers l'interface pour expliquer la fonction de chaque argument.</Text>
+<Text id="242">Lorsqu'il est satisfait avec ces arguments, l'utilisateur clique "Construire collection". Greenstone affiche continuellement un texte qui indique le dÃ©roulement et ceci est montrÃ© par le biais d'une barre de progression plus informative.</Text>
+</Content>
+</Subsection>
+<Subsection id="previewing">
+<Title>
+<Text id="243">AperÃ§u</Text>
+</Title>
+<Content>
+<Text id="244">Le bouton "PrÃ©visualiser la Collection" (figureÂ 14) est utilisÃ© pour visualiser la collection qui a Ã©tÃ© crÃ©Ã©e. L'appui sur ce bouton initiera la page web hebergeant cette collection (figureÂ 15). En pratique, l'aperÃ§u montre souvent des dÃ©fauts dans la conception de la collection ou sur les valeurs individuelles de mÃ©ta-donnÃ©es, et l'utilisateur retourne souvent aux Ã©tapes prÃ©cÃ©dentes pour les corriger. Ce bouton devient actif une fois que la collection a Ã©tÃ© crÃ©Ã©e. La collection nouvellement crÃ©Ã©e sera aussi installÃ©e dans votre page d'accueil Greenstone comme une des collections normales.</Text>
+</Content>
+</Subsection>
+<Subsection id="help">
+<Title>
+<Text id="245">Aide</Text>
+</Title>
+<Content>
+<Text id="246">L'aide en ligne est toujours disponible et elle est obtenue en utilisant l'Ã©lÃ©ment "Aide" situÃ© Ã  droite de la principale barre de menu, en haut de chacune des figures. Ceci ouvre un fichier hiÃ©rarchiquement structurÃ© du texte d'aide, et il est tenu compte du contexte courant de l'utilisateur pour mettre en relief la section qui est appropriÃ©e Ã  l'Ã©tape actuelle de l'interaction. En plus, comme notÃ© ci-dessus, Ã  chaque fois que la souris est maintenue sur tout objet interactif, une petite fenÃªtre popup apparaÃ®t afin de donner un "tool tip" textuel comme illustrÃ© vers le bas de la figureÂ 14.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="librarian_interface_user_guide">
+<Title>
+<Text id="247">L'interface bibliothÃ©caire du Guide d'Utilisateur</Text>
+</Title>
+<Content>
+<Subsection id="starting_off">
+<Title>
+<Text id="248">DÃ©marrage</Text>
+</Title>
+<Content>
+<Text id="249">Cette section explique comment crÃ©er, charger, enregistrer et supprimer des collections.</Text>
+<Part id="creating_a_new_collection">
+<Title>
+<Text id="250">CrÃ©er une nouvelle collection</Text>
+</Title>
+<Content>
+<Text id="251">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="252">"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="253">"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="254">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="255">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="256">Le clic sur "Annuler" ramÃšne immÃ©diatement lâÃ©cran principal.</Text>
+</Content>
+</Part>
+<Part id="saving_the_collection">
+<Title>
+<Text id="257">Ouvrir une collection existante</Text>
+</Title>
+<Content>
+<Text id="258">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 (see Confectionner votre Collection).</Text>
+<Text id="259">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="260">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>
+</Content>
+</Part>
+<Part id="opening_an_existing_collection">
+<Title>
+<Text id="261">Ouvrir une collection existante</Text>
+</Title>
+<Content>
+<Text id="262">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="263">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="264">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 Importation de MÃ©ta-donnÃ©es PrÃ©cÃ©demment AssignÃ©es.</Text>
+</Content>
+</Part>
+<Part id="deleting_collections">
+<Title>
+<Text id="265">Suppression des collections</Text>
+</Title>
+<Content>
+<Text id="266">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>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="downloading_files_from_the_internet">
+<Title>
+<Text id="267">TÃ©lÃ©chargement de fichiers de lIinternet</Text>
+</Title>
+<Content>
+<Text id="268">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>
+<Part id="the_download_view">
+<Title>
+<Text id="269">La vue TÃ©lÃ©chargement</Text>
+</Title>
+<Content>
+<Text id="270">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="271">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="272">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="273">La liste de tÃ©lÃ©chargement a une entrÃ©e pour chaque tÃ©lÃ©chargement de pageWeb. 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="274">La section PrÃ©fÃ©rences 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>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="collecting_files_for_your_collection">
+<Title>
+<Text id="275">Collecter les fichiers pour la Collection</Text>
+</Title>
+<Content>
+<Text id="276">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>
+<Part id="the_gather_view">
+<Title>
+<Text id="277">Lâaffichage Rassembler</Text>
+</Title>
+<Content>
+<Text id="278">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 Ã  celuici, cliquer directement sur lâonglet "Rassembler" au bas de la barre des menus.</Text>
+<Text id="279">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="280">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 Association de fichiers).</Text>
+<Text id="281">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="282">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="283">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="284">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="285">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 CrÃ©ation de dossiers). "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="286">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="287">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>
+</Content>
+</Part>
+<Part id="creating_folders">
+<Title>
+<Text id="288">CrÃ©er des dossiers</Text>
+</Title>
+<Content>
+<Text id="289">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="290">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="291">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>
+</Content>
+</Part>
+<Part id="adding_files">
+<Title>
+<Text id="292">Ajouter des fichiers</Text>
+</Title>
+<Content>
+<Text id="293">Les fichiers peuvent Ãªtre copiÃ©s dans la collection par glisserdÃ©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="294">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="295">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="296">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 Importer des mÃ©tadonnÃ©es originellement assignÃ©es . 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>
+</Content>
+</Part>
+<Part id="removing_files">
+<Title>
+<Text id="297">Supprimer des Fichiers</Text>
+</Title>
+<Content>
+<Text id="298">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 LâAffichage Rassembler (The Gather view).</Text>
+<Text id="299">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 glisserdÃ©placer de la collection vers le bouton "Supprimer" et les y dÃ©poser.</Text>
+</Content>
+</Part>
+<Part id="filtering_the_tree">
+<Title>
+<Text id="300">Filtrer lâarborescence</Text>
+</Title>
+<Content>
+<Text id="301">Le "Filtrage" de lâarborescence de la collection permet de rÃ©duire la recherche de fichiers particuliers.</Text>
+<Text id="302">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="303">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>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="enriching_the_collection_with_metadata">
+<Title>
+<Text id="304">Enrichir la Collection avec des mÃ©ta-donnÃ©es</Text>
+</Title>
+<Content>
+<Text id="305">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>
+<Part id="the_enrich_view">
+<Title>
+<Text id="306">Lâaffichage Enrichir</Text>
+</Title>
+<Content>
+<Text id="307">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="308">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="309">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="310">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="311">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="312">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>
+</Content>
+</Part>
+<Part id="selecting_metadata_sets">
+<Title>
+<Text id="313">SÃ©lectionner les jeux de mÃ©ta-donnÃ©es</Text>
+</Title>
+<Content>
+<Text id="314">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="315">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>
+</Content>
+</Part>
+<Part id="appending_new_metadata">
+<Title>
+<Text id="316">Ajout de Nouvelles MÃ©ta-donnÃ©es</Text>
+</Title>
+<Content>
+<Text id="317">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="318">SÃ©lectionner ensuite lâÃ©lÃ©ment mÃ©ta-donnÃ©e Ã  ajouter en cliquant sur sa rangÃ©e dans le tableau.</Text>
+<Text id="319">Taper la valeur dans le champ valeur. Utilisez le charactÃšre "|" pour rapporter une structure, comme dÃ©crit dans The Enrich View. 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="320">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>
+</Content>
+</Part>
+<Part id="adding_previously_defined_metadata">
+<Title>
+<Text id="321">Ajouter des MÃ©ta-donnÃ©es prÃ©dÃ©finies</Text>
+</Title>
+<Content>
+<Text id="322">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="323">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>
+</Content>
+</Part>
+<Part id="editing_or_removing_metadata">
+<Title>
+<Text id="324">Editant ou Ãliminant MÃ©ta-donnÃ©es</Text>
+</Title>
+<Content>
+<Text id="325">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="326">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="327">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>
+</Content>
+</Part>
+<Part id="reviewing_assigned_metadata">
+<Title>
+<Text id="328">Passer en revue les MÃ©ta-donnÃ©es assignÃ©es</Text>
+</Title>
+<Content>
+<Text id="329">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="330">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="331">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="332">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="333">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="334">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>
+</Content>
+</Part>
+<Part id="importing_previously_assigned_metadata">
+<Title>
+<Text id="335">Importer des MÃ©ta-donnÃ©es PrÃ©-assignÃ©es</Text>
+</Title>
+<Content>
+<Text id="336">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="337">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="338">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="339">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Ã©tadonnÃ©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="340">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>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="designing_your_collection_appearance">
+<Title>
+<Text id="341">DÃ©coration de lâapparence de votre collection</Text>
+</Title>
+<Content>
+<Text id="342">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>
+<Part id="the_design_view">
+<Title>
+<Text id="343">LâAffichage conception</Text>
+</Title>
+<Content>
+<Text id="344">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="345">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="346">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="347">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>
+</Content>
+</Part>
+<Part id="general">
+<Title>
+<Text id="348">GÃ©nÃ©ral</Text>
+</Title>
+<Content>
+<Text id="349">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="350">Les valeurs fournies ici peuvent Ãªtre modifiÃ©es au cours de la crÃ©ation de la collection.</Text>
+<Text id="351">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 CrÃ©er une nouvelle collection.</Text>
+</Content>
+</Part>
+<Part id="document_plugins">
+<Title>
+<Text id="352">Plugiciels de Document</Text>
+</Title>
+<Content>
+<Text id="353">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="354">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="355">Pour enlever un plugiciel, sÃ©lectionner-le sur la liste et cliquer sur "Enlever plugiciel".</Text>
+<Text id="356">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="357">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="358">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="359">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 PrÃ©fÃ©rences).</Text>
+</Content>
+</Part>
+<Part id="search_types">
+<Title>
+<Text id="360">Types de recherche</Text>
+</Title>
+<Content>
+<Text id="361">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="362">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="363">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="364">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>
+</Content>
+</Part>
+<Part id="search_indexes">
+<Title>
+<Text id="365">Index de recherche</Text>
+</Title>
+<Content>
+<Text id="366">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="367">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="368">Pour Ã©diter un index, sÃ©lectionnez-le et changez les dÃ©tails de lâindex, puis clicquez sur "Remplacer lâindex".</Text>
+<Text id="369">Pour enlever un index, il faut le sÃ©lectionner sur la liste dâindex assignÃ©s et cliquer "Enlever index".</Text>
+<Text id="370">Pour crÃ©er un indexe couvrant texte et toute metadata, cliquez sur "Ajouter Tout".</Text>
+<Text id="371">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="372">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="373">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>
+</Content>
+</Part>
+<Part id="partition_indexes">
+<Title>
+<Text id="374">Index de Partition</Text>
+</Title>
+<Content>
+<Text id="375">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="376">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="377">La fenÃªtre des Indexes de Partition est seulement Ã©tablie dans la Librairie de SystÃšmes SpÃ©cialistes et modes Experts (voir PrÃ©fÃ©rences). 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>
+</Content>
+</Part>
+<Part id="define_filters">
+<Title>
+<Text id="378">DÃ©finir les Filtres</Text>
+</Title>
+<Content>
+<Text id="379">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="380">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="381">Pour enlever un filtre, sÃ©lectionner-le sur la liste et cliquer sur "Enlever Filtre".</Text>
+<Text id="382">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>
+</Content>
+</Part>
+<Part id="assign_partitions">
+<Title>
+<Text id="383">Assigner des Partitions</Text>
+</Title>
+<Content>
+<Text id="384">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="385">Pour supprimer une partition, sÃ©lectionner-la Ã  partir de la liste et cliquer sur "Enlever Partition".</Text>
+<Text id="386">Pour faire dâune partition celle par dÃ©faut, sÃ©lectionner-la Ã  partir de la liste et cliquer sur "Par DÃ©faut".</Text>
+</Content>
+</Part>
+<Part id="assign_languages">
+<Title>
+<Text id="387">Assigner Langages</Text>
+</Title>
+<Content>
+<Text id="388">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="389">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="390">Pour supprimer une langue, sÃ©lectionner-la Ã  partir de la liste "SÃ©lection de Langage" et cliquer sur "Enlever Langage".</Text>
+<Text id="391">Pour installer un language par dÃ©faut, sÃ©lectionner-la dans la liste et cliquez sur "Par dÃ©faut".</Text>
+</Content>
+</Part>
+<Part id="cross-collection_search">
+<Title>
+<Text id="392">Recherches Ã  travers collections</Text>
+</Title>
+<Content>
+<Text id="393">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="394">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="395">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="396">Pour plus de dÃ©tails, voir Chapitre 1 du Guide du DÃ©veloppeur Greenstone.</Text>
+</Content>
+</Part>
+<Part id="browsing_classifiers">
+<Title>
+<Text id="397">Classificateurs de navigation</Text>
+</Title>
+<Content>
+<Text id="398">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="399">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 plugiciels de Documents). Une fois le nouveau classificateur configurÃ©, il sâajoute Ã  la fin de la liste des "Classificateurs couramment AssignÃ©s".</Text>
+<Text id="400">Pour supprimer un classificateur, sÃ©lectionner-le dans la liste et cliquez sur "Supprimer Classificateur".</Text>
+<Text id="401">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="402">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="403">Pour plus dâinformations sur les classificateurs lisez le chapitre 2 du Guide du DÃ©veloppeur Greenstone â Exploitez vos documents au maximum.</Text>
+</Content>
+</Part>
+<Part id="format_features">
+<Title>
+<Text id="404">CaractÃ©ristiques de Format</Text>
+</Title>
+<Content>
+<Text id="405">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="406">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="407">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="408">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="409">Pour enlever une commande de format, sÃ©lectionner-la sur la liste et cliquer "Enlever Format".</Text>
+<Text id="410">Pour modifier une commande de format, sÃ©lectionner-la sur la liste et cliquer sur "Remplacer Format".</Text>
+<Text id="411">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="412">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>
+</Content>
+</Part>
+<Part id="translate_text">
+<Title>
+<Text id="413">Traduire Texte</Text>
+</Title>
+<Content>
+<Text id="414">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="415">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="416">Pour supprimer une traduction existante, sÃ©lectionner-la Ã  partir du tableau "Traduction AssignÃ©e" et cliquer sur "Enlever Traduction".</Text>
+<Text id="417">Pour Ã©diter une traduction, sÃ©lectionner-la et Ã©diter-la dans la zone de texte "Texte Traduit", et cliquer sur "Remplacer Traduction".</Text>
+</Content>
+</Part>
+<Part id="metadata_sets">
+<Title>
+<Text id="418">jeux de MÃ©ta-donnÃ©es</Text>
+</Title>
+<Content>
+<Text id="419">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="420">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="421">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="422">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="423">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Ã©tadonnÃ©es aux Ã©lÃ©ments du jeu supprimÃ©, on vous demandera ce que vous voulez en faire lorsque vous allez ouvrir Ã  nouveau cette collection.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="producing_your_collection">
+<Title>
+<Text id="424">Pour produire votre collection</Text>
+</Title>
+<Content>
+<Text id="425">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>
+<Part id="the_create_view">
+<Title>
+<Text id="426">LâAffichage CrÃ©er</Text>
+</Title>
+<Content>
+<Text id="427">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="428">Quand la collection est construite, appuyant "Preview Collection" initiera la page web hebergeant la collection.</Text>
+<Text id="429">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>
+</Content>
+</Part>
+<Part id="import_and_build_settings">
+<Title>
+<Text id="430">ParamÃštres dâImportation et de Construction</Text>
+</Title>
+<Content>
+<Text id="431">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="432">Le contrÃŽle des diffÃ©rents paramÃštres se fait de faÃ§on identique Ã  la fenÃªtre "Configurer Arguments" dÃ©crit dans la section Plugiciels de documents. 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>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="miscellaneous">
+<Title>
+<Text id="433">Miscellaneous</Text>
+</Title>
+<Content>
+<Text id="434">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>
+<Part id="preferences">
+<Title>
+<Text id="435">PrÃ©fÃ©rences</Text>
+</Title>
+<Content>
+<Text id="436">Cette section explique le dialogue des prÃ©fÃ©rences, auquel on accÃšde en ouvrant "Fichier" -&gt; "PrÃ©fÃ©rences".</Text>
+<Text id="437">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="438">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="439">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="440">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="441">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 TÃ©lÃ©charger les fichiers de lâInternet 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="442">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>
+</Content>
+</Part>
+<Part id="file_associations">
+<Title>
+<Text id="443">Associations de fichiers</Text>
+</Title>
+<Content>
+<Text id="444">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="445">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". "</Text>
+<Text id="446">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="447">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="448">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>
+</Content>
+</Part>
+<Part id="exporting_collections_to_cddvd">
+<Title>
+<Text id="449">Exportation de collections vers CD/DVD</Text>
+</Title>
+<Content>
+<Text id="450">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="451">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="452">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>
+</Content>
+</Part>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="tagging_document_files">
+<Title>
+<Text id="453">Le balisage des fichiers de documents</Text>
+</Title>
+<Content>
+<Text id="454">Les documents source ont souvent besoin d'Ãªtre structurÃ©s en sections et sous-sections, et il faut communiquer cette information Ã  Greenstone de sorte qu'il puisse puisse conserver la structure hiÃ©rarchique des documents. On peut Ã©galement associer des mÃ©ta-donnÃ©es -- telles que son titre -- Ã  chaque section et sous-section.</Text>
+<Text id="455">Les documents source d'un processus de reconnaissance optique de caractÃšres (ROC) sont typiquement un ensemble de fichiers de traitement de texte, y compris des images. S'ils sont reprÃ©sentÃ©s sous la forme de fichiers Microsoft Word, on peut les importer dans Greenstone en utilisant le greffon Word. On peut aussi les convertir en HTML et les importer dans Greenstone en utilisant le greffon HTML.</Text>
+<Text id="456">Dans les deux cas, on peut indiquer la structure hiÃ©rarchique d'un document en insÃ©rant des balises dans le texte comme suit:</Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>&lt;Description&gt;</CodeLine>
+<Text type="code" id="457">&lt;Metadata name="Title"&gt; Assurer le respect des droits de l'homme pour les pauvres: stratÃ©gies pour atteindre les cibles de dÃ©veloppement international &lt;/Metadata&gt;</Text>
+<CodeLine>&lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="458"><i>(texte de la section)</i></Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="459">On utilise les marqueurs<i>&lt;!-- ... --&gt;</i>car ils dÃ©notent des commentaires en HTML; ces balises de section n'auront donc aucun impact sur la mise en forme du document. Il faut inclure ces autour des balises de sections, mÃªme si le document sur lequel on travaille n'est pas de l'HTML (si par exemple il s'agit d'un fichier de type Microsoft Word).</Text>
+<Text id="460">On peut spÃ©cifier d'autres types de mÃ©ta-donnÃ©es dans la portion Description (situÃ©e entre les balises<i>&lt;Description&gt;</i>et<i>&lt;/Description&gt;</i>), mais ce n'est pas le cas du style de collection dÃ©crit ici.</Text>
+<Text id="461">Il est important de se rappeler que l'on crÃ©e une table des matiÃšres hiÃ©rarchique lorsque l'on insÃšre des balises de sections dans le document. Cela signifie qu'on peut imbriquer des sections dans d'autres sections. En fait, il faut imbriquer toutes les sections dans une grande section qui recouvre l'ensemble du document.</Text>
+<Text id="462">L'exemple suivant illustre le cas d'un document composÃ© de deux chapitres, dont le second contient deux sous-sections. Vous trouverez des exemples concrets de documents source balisÃ©s de cette maniÃšre dans les documents source des collections Demo et DLS. </Text>
+<CodeLine>&lt;!-- &lt;Section&gt; &lt;Description&gt; &lt;Metadata name="Title"&gt;Mon document&lt;/Metadata&gt; &lt;/Description&gt; &lt;Section&gt; &lt;Description&gt; &lt;Metadata name="Title"&gt;Chapitre 1&lt;/Metadata&gt; &lt;/Description&gt; --&gt;</CodeLine>
+<Text type="code" id="463">(text du chapitre 1)</Text>
+<CodeLine>&lt;!-- &lt;/Section&gt; &lt;Section&gt; &lt;Description&gt; &lt;Metadata name="Title"&gt;Chapitre 2&lt;/Metadata&gt; &lt;/Description&gt; &lt;Section&gt; &lt;Description&gt; &lt;Metadata name="Title"&gt;Sous-section 1&lt;/Metadata&gt; &lt;/Description&gt; --&gt;</CodeLine>
+<Text type="code" id="464">(texte de la sous-section 1)</Text>
+<CodeLine>&lt;!-- &lt;/Section&gt; &lt;Section&gt; &lt;Description&gt; &lt;Metadata name="Title"&gt;Sous-section 2&lt;/Metadata&gt; &lt;/Description&gt; --&gt;</CodeLine>
+<Text type="code" id="465">(texte de la sous-section 2)</Text>
+<CodeLine>&lt;!-- &lt;/Section&gt; &lt;/Section&gt; &lt;/Section&gt; --&gt;</CodeLine>
+<Text id="466">Il faut noter que des mÃ©ta-donnÃ©es assignÃ©es Ã  partir dun onglet de section dans un document source prend le pas sur celle assignÃ©e au document tout entier. Ceci signifie que vous ne devez pas spÃ©cifier explicitement la mÃ©ta-donnÃ©e "Title" ("Titre") pour la section de plus haut niveau Ã  l'intÃ©rieur d'un document source Ã  moins que vous ne veuilliez Ã©craser le titre que vous lui avez donnÃ© en spÃ©cifiant la mÃ©ta-donnÃ©e. Dans l'exemple ci-dessus, Ã  moins de vouloir Ã©craser le titre du document existant, vous devriez omettre la ligne oÃ¹ on peut lire:</Text>
+<CodeLine>&lt;Metadata name="Title"&gt;Mon document&lt;/Metadata&gt;</CodeLine>
+</Content>
+</Section>
+<Section id="the_collector">
+<Title>
+<Text id="467">Le Collector</Text>
+</Title>
+<Content>
+<Text id="468">Le Collector est un outil d'assistance qui vous aidera Ã  crÃ©er de nouvelles collections, Ã  modifier ou ajouter Ã  des collections existantes, ou Ã  effacer des collections. Pour ce faire vous serez guidÃ©s Ã  travers un ensemble de pages web qui vous demanderont les informations nÃ©cessaires. Ces pages web parlent d'elles-mÃªmes, et la prÃ©sente section vous les dÃ©crira. Au lieu d'utiliser le Collector, on peut aussi construire des collections depuis la ligne de commandeÂ --Â les premiÃšres pages du Guide du dÃ©veloppeur dÃ©taillent ce processus pas Ã  pas.</Text>
+<Text id="469">Avant de construire et de distribuer des collections d'informations numÃ©riques, il faut rÃ©flÃ©chir aux consÃ©quences et aux responsabilitÃ©s que cela implique. On trouve des aspects lÃ©gaux relatifs aux droits: pouvoir accÃ©der Ã  des documents n'implique pas forcÃ©ment qu'on puisse les distribuer Ã  des tiers. On trouve aussi des aspects sociaux: les collections devraient respecter les coutumes de la communautÃ© dont leurs documents proviennent. Enfin, on trouve des aspects Ã©thiques: il existe des documents qu'il vaut mieux ne pas communiquer. La plume est plus puissante que l'Ã©pÃ©e! Soyez sensible au pouvoir de l'information, et faites-en sage usage.</Text>
+<Text id="470">Pour accÃ©der au Collector, cliquez sur le lien appropriÃ© depuis la page d'accueil de la bibliothÃšque numÃ©rique. </Text>
+<Text id="471">Dans Greenstone, la structure d'une collection est dÃ©terminÃ©e lors de sa mise en place. Cela comprend aussi bien le format des documents source, la maniÃšre de les reprÃ©senter Ã  l'Ã©cran, les sources de mÃ©ta-donnÃ©es, quelles possibilitÃ©s de navigation offrir, quels index de recherche dans le corps du texte fournir, et comment afficher les rÃ©sultats des recherches. AprÃšs la mise en place de la collection, il est facile d'y inclure de nouveaux documentsÂ --Â pour peu qu'ils soient dans le mÃªme format que les documents existants, et que les mÃªmes mÃ©ta-donnÃ©es soient fournies, exactement de la mÃªme maniÃšre.</Text>
+<Text id="472">Le Collector dispose des fonctions de base suivantes:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="473">crÃ©er une nouvelle collection de mÃªme structure qu'une collection existante;</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="474">crÃ©er une nouvelle collection d'une structure diffÃ©rente de celle des collections existantes;</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="475">ajouter du contenu Ã  une collection existante;</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="476">modifier la structure d'une collection existante;</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="477">effacer une collection; et</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="478">exporter une collection existante sur un cÃ©dÃ©rom autonome et auto-installable.</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="479">Les figuresÂ 16aa et suivantes illustrent l'utilisation du Collector pour la crÃ©ation d'une nouvelle collection, Ã  partir d'un ensemble de fichiers HTML stockÃ©s localement dans le cas de cet exemple. Il faut d'abord dÃ©cider de travailler sur une collection existante ou d'en construire une nouvelle. Dans le premier cas, vous vous trouverez dans les deux premiers points de la liste numÃ©rotÃ©e ci-dessus; dans le second, ce seront les quatre derniers points qui vous concerneront. Dans la figureÂ 16aa, l'utilisateur opte pour la crÃ©ation d'une nouvelle collection.</Text>
+<Figure id="using_the_collector_to_build_a_new_collection">
+<Title>
+<Text id="480">Utiliser le Collector pour construire une nouvelle collection (Ã  suivre)</Text>
+<SubTitle>
+<Text id="481">(a)</Text>
+</SubTitle>
+</Title>
+<File url="images/User_Fig_16a.png"/>
+</Figure>
+<Subsection id="logging_in">
+<Title>
+<Text id="482">Se connecter</Text>
+</Title>
+<Content>
+<Text id="483">Dans tous les cas, il est nÃ©cessaire de se connecter avant de pouvoir faire quoi que ce soit. En gÃ©nÃ©ral, on utilise un navigateur web pour accÃ©der Ã  l'outil de construction de collection sur un ordinateur distant, afin de construire une collection sur ce serveur. Il est bien sÃ»r hors de question d'autoriser n'importe qui Ã  construire des collections (ne serait-ce que pour des raisons de droits), c'est pourquoi Greenstone renferme un systÃšme de sÃ©curitÃ© qui oblige qui veut construire des collections Ã  se connecter avant toute autre chose. Ceci permet Ã  un systÃšme central d'offrir un service Ã  ceux qui souhaitent construire des collections d'informations et utiliser le serveur pour les rendre disponibles Ã  d'autres. D'autre part, mÃªme si vous utilisez Greenstone sur votre ordinateur local et y construisez des collections, il est nÃ©cessaire de vous connecter car il ne faut pas autoriser des tiers utilisant Greenstone sur votre ordinateur Ã  construire des collections sans autorisation prÃ©alable.</Text>
+</Content>
+</Subsection>
+<Subsection id="dialog_structure">
+<Title>
+<Text id="484">Structure de dialogue</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_1">
+<Title>
+<Text id="485">Utiliser le Collector pour construire une nouvelle collection (Suite)</Text>
+<SubTitle>
+<Text id="486">(b)</Text>
+</SubTitle>
+</Title>
+<File url="images/User_Fig_16b.png"/>
+</Figure>
+<Text id="487">Suite Ã  la connexion, on voit apparaÃ®tre la page prÃ©sentÃ©e figureÂ 16bb. Elle montre la suite d'Ã©tapes impliquÃ©es dans la construction d'une collection, c'est-Ã -dire:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="488">Informations sur la collection</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="489">DonnÃ©es source</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="490">Configurer la collection </Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="491">Construire la collection</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="492">Afficher la collection.</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="493">La premiÃšre Ã©tape consiste Ã  spÃ©cifier le nom de la collection et les informations associÃ©es. La deuxiÃšme Ã©tape est de prÃ©ciser d'oÃ¹ proviendront les donnÃ©es source. La troisiÃšme permet d'ajuster les options de configuration, une Ã©tape que vous trouverez de plus en plus utile Ã  mesure que vous serez plus expÃ©rimentÃ© avec Greenstone. La quatriÃšme Ã©tape indique oÃ¹ se fera tout le travail (de l'ordinateur). Durant le processus de Â«constructionÂ» le systÃšme construit tous les index et rassemble toutes les autres informations nÃ©cessaires au bon fonctionnement de la collection. La cinquiÃšme Ã©tape vous permettra de visualiser la collection nouvellement crÃ©Ã©e.</Text>
+<Text id="494">Ces cinq Ã©tapes sont reprÃ©sentÃ©es sous forme d'une suite de boutons gris au bas de l'Ã©cran figureÂ 16bb, ainsi qu'au bas de toutes les autres pages gÃ©nÃ©rÃ©es par le Collector. Cet affichage aide les utilisateurs Ã  se rappeler oÃ¹ ils en sont dans le processus. Le bouton Ã  cliquer pour passer Ã  la suite est affichÃ© en vert (informations sur la collection sur la figureÂ 16bb). Les boutons gris (tous les autres, sur la figureÂ 16bb) sont inactifs. Les boutons deviennent jaunes au fur et Ã  mesure de la progression dans les Ã©tapes, et l'utilisateur peut revenir Ã  une Ã©tape antÃ©rieure en cliquant sur le bouton jaune correspondant. Cet affichage est inspirÃ© des Â«assistantsÂ» largement utilisÃ©s dans les logiciels propriÃ©taires pour guider les utilisateurs tout au long des diffÃ©rentes Ã©tapes de l'installation de nouveaux logiciels.</Text>
+</Content>
+</Subsection>
+<Subsection id="collection_information">
+<Title>
+<Text id="495">Informations sur la collection</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_2">
+<Title>
+<Text id="496">Utiliser le Collector pour construire une nouvelle collection (Suite)</Text>
+<SubTitle>
+<Text id="497">(c)</Text>
+</SubTitle>
+</Title>
+<File url="images/User_Fig_16c.png"/>
+</Figure>
+<Text id="498">La prochaine Ã©tape, celle des informations de collection, est illustrÃ©e figureÂ 16cc. Lorsqu'on crÃ©e une nouvelle collection, il est nÃ©cessaire de donner certaines informations la concernant:</Text>
+<BulletList>
+<Bullet>
+<Text id="499">titre,</Text>
+</Bullet>
+<Bullet>
+<Text id="500">adresse de courrier Ã©lectronique de contact, et</Text>
+</Bullet>
+<Bullet>
+<Text id="501">une brÃšve description.</Text>
+</Bullet>
+</BulletList>
+<Text id="502">Le titre de la collection est une petite phrase utilisÃ©e Ã  travers la bibliothÃšque numÃ©rique pour identifier le contenu de la collection. On peut citer comme exemples de titres Â«BibliothÃšque de la nourriture et de la nutritionÂ», Â«BibliothÃšque environnementale mondialeÂ», Â«BibliothÃšque de dÃ©veloppement pour l'humanitÃ©Â», etc. L'adresse Ã©lectronique spÃ©cifie qui contacter pour tout problÃšme rencontrÃ© avec la collection. Si le logiciel Greenstone dÃ©tecte un problÃšme, il est possible qu'il y envoie un rapport dÃ©crivant l'erreur. Enfin, la brÃšve description est une phrase dÃ©crivant les critÃšres d'inclusion dans la collection. Elle apparaÃ®t sous l'en-tÃªte Ã  propos de la premiÃšre page, lors de la prÃ©sentation de la collection.</Text>
+<Text id="503">La position actuelle dans les Ã©tapes de construction de la collection est dÃ©notÃ©e par une flÃšche qui apparaÃ®t au bas de chaque pageÂ --Â dans ce cas, comme illustrÃ© par la figureÂ 16cc, nous nous trouvons Ã  l'Ã©tape des informations de la collection. On continue vers la figureÂ 16dd en cliquant sur le bouton vert donnÃ©es source.</Text>
+</Content>
+</Subsection>
+<Subsection id="source_data">
+<Title>
+<Text id="504">DonnÃ©es source</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_3">
+<Title>
+<Text id="505">Utiliser le Collector pour construire une nouvelle collection (Suite) </Text>
+<SubTitle>
+<Text id="506">(d)</Text>
+</SubTitle>
+</Title>
+<File url="images/User_Fig_16d.png"/>
+</Figure>
+<Text id="507">La figureÂ 16dd est le moment oÃ¹ l'utilisateur spÃ©cifie le texte source qui constituera la collection. On peut soit baser sa collection sur l'une des structures par dÃ©faut fournies, soit sur la structure d'une collection existante.</Text>
+<Text id="508">Si vous optez pour la structure par dÃ©faut, la nouvelle collection pourra contenir des documents HTML (fichiers d'extensions .htm ou .html), des fichiers texte (fichiers d'extensions .txt ou .text), des fichiers au format Microsoft Word (fichiers d'extensions .doc), des documents PDF (fichiers d'extensions .pdf), ou des courriers Ã©lectroniques (fichiers d'extensions .email). Vous trouverez plus d'informations sur les diffÃ©rents formats de documents qu'on peut inclure dans la sectionÂ 3.4.9.</Text>
+<Text id="509">Si vous basez votre nouvelle collection sur une collection existante, les fichiers de la nouvelle collection devront avoir exactement le mÃªme type que ceux utilisÃ©s pour construire la collection existante. Vous remarquerez que certaines collections utilisent des formats de fichiers en entrÃ©e non standard, et que d'autres utilisent des mÃ©ta-donnÃ©es stockÃ©es dans des fichiers auxiliaires. Si ces informations sont absentes de vos nouvelles donnÃ©es, certaines fonctionnalitÃ©s de navigation pourront mal fonctionner. Si par exemple vous clonez la collection Â«DemoÂ», vous remarquerez peut-Ãªtre que les boutons thÃšmes, organisation, et comment faire ne fonctionnent pas bien.</Text>
+<Text id="510">La page web propose des boÃ®tes pour indiquer la localisation des documents source: on peut spÃ©cifier jusqu'Ã  trois sources diffÃ©rentes en entrÃ©e dans la figureÂ 16dd. Si cela ne vous suffit pas, cliquez sur le bouton intitulÃ© More sources (Â«davantage de sourcesÂ»).</Text>
+<Text id="511">Il existe trois types de spÃ©cifications:</Text>
+<BulletList>
+<Bullet>
+<Text id="512">un nom de rÃ©pertoire dans le systÃšme du serveur Greenstone (commenÃ§ant par Â«file://Â»);</Text>
+</Bullet>
+<Bullet>
+<Text id="513">une adresse commenÃ§ant par Â«http://Â», pour les fichiers Ã  tÃ©lÃ©charger depuis le web;</Text>
+</Bullet>
+<Bullet>
+<Text id="514">une adresse commenÃ§ant par Â«ftp://Â», pour les fichiers Ã  tÃ©lÃ©charger en FTP anonyme.</Text>
+</Bullet>
+</BulletList>
+<Text id="515">Si vous utilisezfile://ouftp://pour spÃ©cifier un fichier, ce fichier sera rapatriÃ©.</Text>
+<Text id="516">Si vous utilisezhttp://, tout dÃ©pend si l'URL correspondante fournit dans le navigateur une page web normale ou une liste de fichiers. Si elle fournit une page web normale, cette page sera tÃ©lÃ©chargÃ©eÂ --Â ainsi que toutes les pages vers lesquelles elle pointe, et les pages vers lesquelles pointent ces derniÃšres, etc., pourvu que toutes rÃ©sident sur le mÃªme site, sous cette URL.</Text>
+<Text id="517">Si vous utilisezfile://ouftp://pour spÃ©cifier un dossier ou un rÃ©pertoire, ou si vous donnez une URL enhttp://qui mÃšne vers une liste de fichiers, tout le dossier et tous ses sous-dossiers seront inclus dans la collection.</Text>
+<Text id="518">Vous pouvez spÃ©cifier des sources de plusieurs types.</Text>
+<Text id="519">Dans le cas de la figureÂ 16dd, la nouvelle collection contiendra des documents copiÃ©s depuis un systÃšme de fichiers local ainsi que depuis un site web externe, qui sera copiÃ© localement (une copie Â«miroirÂ» en sera faite) pendant le processus de construction.</Text>
+<Text id="520">Quand on clique sur le bouton configurer la collection pour passer Ã  la prochaine Ã©tape de la construction, le Collector vÃ©rifie que toutes les sources de donnÃ©es spÃ©cifiÃ©es sont joignables. Ceci peut prendre quelques secondes, ou mÃªme quelques minutes si vous avez spÃ©cifiÃ© plusieurs sources. Si l'une ou l'autre des sources spÃ©cifiÃ©es ne sont pas disponibles, on obtient une page comme celle de la figureÂ 16ee, marquant d'une croix les sources non disponibles (dans le cas prÃ©sent, c'est le cas de toutes deux).</Text>
+<Figure id="using_the_collector_to_build_a_new_collection_4">
+<Title>
+<Text id="521">Utiliser le Collector pour construire une nouvelle collection (Suite)</Text>
+<SubTitle>
+<Text id="522">(e)</Text>
+</SubTitle>
+</Title>
+<File url="images/User_Fig_16e.png"/>
+</Figure>
+<Text id="523">Plusieurs raisons peuvent expliquer le fait que des sources soient non disponibles: </Text>
+<BulletList>
+<Bullet>
+<Text id="524">le fichier, le site FTP ou l'URL indiquÃ© n'existe pas;</Text>
+</Bullet>
+<Bullet>
+<Text id="525">il vous faut d'abord vous connecter Ã  votre FAI; </Text>
+</Bullet>
+<Bullet>
+<Text id="526">vous tentez d'accÃ©der Ã  une URL alors que vous vous trouvez derriÃšre un pare-feu.</Text>
+</Bullet>
+</BulletList>
+<Text id="527">Le dernier cas est potentiellement celui qui a l'air le plus mystÃ©rieux. Il se produit si en temps normal il vous faut fournir un nom d'utilisateur et un mot de passe pour accÃ©der Ã  l'Internet. Parfois, il est possible que votre navigateur web affiche correctement la page si on y en entre l'URL, alors que le Collector prÃ©tend que cette source n'est pas disponible. L'explication est que la version affichÃ©e dans votre navigateur provient peut-Ãªtre d'une copie tampon (cache). Malheureusement, les copies tampon locales sont invisibles au Collector. Dans un tel cas de figure, nous vous recommandons de tÃ©lÃ©charger d'abord les pages Ã  l'aide de votre navigateur.</Text>
+</Content>
+</Subsection>
+<Subsection id="configuring_the_collection">
+<Title>
+<Text id="528">Configurer la collection</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_5">
+<Title>
+<Text id="529">Utiliser le Collector pour construire une nouvelle collection (Suite)</Text>
+<SubTitle>
+<Text id="530">(f)</Text>
+</SubTitle>
+</Title>
+<File url="images/User_Fig_16f.png"/>
+</Figure>
+<Text id="531">La figureÂ 16ff prÃ©sente l'Ã©tape suivante. La construction et la prÃ©sentation de toutes les collections sont contrÃŽlÃ©es par des spÃ©cifications enregistrÃ©es dans un fichier de configuration de collection spÃ©cial (voir ci-dessous). Les utilisateurs expÃ©rimentÃ©s pourront utiliser cette page pour modifier les rÃ©glages de configuration, mais la plupart passeront directement Ã  la derniÃšre Ã©tape. En fait, dans la figureÂ 16dd, les boutons configurer la collection et construire la collection sont tous les deux affichÃ©s en vert, ce qui signifie bien que l'on peut complÃštement court-circuiter la troisiÃšme Ã©tape du processus.</Text>
+<Text id="532">Dans notre exemple, l'utilisateur a fait une petite modification au fichier de configuration par dÃ©faut en incluant le drapeau file_is_url Ã  l'aide du greffon (plugin) HTML. Ce drapeau provoque l'insertion des mÃ©ta-donnÃ©es d'URL dans chaque document, en se fondant sur la convention de nom de fichier adoptÃ©e par l'outil qui crÃ©e le miroir. Ces mÃ©ta-donnÃ©es sont utilisÃ©es dans la collection pour permettre aux utilisateurs de se rÃ©fÃ©rer Ã  la version originale du document, plutÃŽt qu'Ã  une copie locale.</Text>
+</Content>
+</Subsection>
+<Subsection id="building_the_collection_1">
+<Title>
+<Text id="533">Construire la collection</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_6">
+<Title>
+<Text id="534">Utiliser le Collector pour construire une nouvelle collection (Suite)</Text>
+<SubTitle>
+<Text id="535">(g)</Text>
+</SubTitle>
+</Title>
+<File url="images/User_Fig_16g.png"/>
+</Figure>
+<Text id="536">La figureÂ 16gg illustre l'Ã©tape de Â«constructionÂ». Jusqu'Ã  prÃ©sent, les rÃ©ponses fournies dans l'interface ont simplement Ã©tÃ© enregistrÃ©es dans un fichier temporaire. L'Ã©tape de construction est celle oÃ¹ tout le travail est rÃ©ellement effectuÃ©.</Text>
+<Text id="537">Lors de la construction, les index de navigation et de recherche sont construits en suivant les instructions du fichier de configuration de collection. Le processus de construction peut prendre de quelques minutes Ã  quelques heures, selon la taille de la collection et la puissance de l'ordinateur. Certaines collections trÃšs consÃ©quentes peuvent prendre plus d'un jour Ã  construire.</Text>
+<Text id="538">Lorsque vous atteindrez cette Ã©tape, une ligne d'Ã©tat situÃ©e au bas de la page web vous donnera un suivi de la progression de l'opÃ©ration, suivi mis Ã  jour toutes les 5 secondes. Le message visible dans la figureÂ 16gg indique que lors de la capture d'Ã©cran, Greenstone effectuait une conversion de format de document de PDF vers HTML.</Text>
+<Text id="539">Des avertissements seront affichÃ©s si certains fichiers ou URL requis en entrÃ©e n'existent pas, ou existent mais qu'aucun greffon (plugin) ne peut les traiter, ou que le greffon ne peut pas trouver un fichier associÃ©, telle qu'une image incrustÃ©e dans un document HTML. L'objectif est que vous suiviez cette progression en laissant cette fenÃªtre ouverte dans votre navigateur. Si des erreurs provoquent la fin prÃ©maturÃ©e du processus, elles seront enregistrÃ©e dans cette zone d'Ã©tat.</Text>
+<Text id="540">Vous pouvez arrÃªter le processus de construction Ã  tout instant en cliquant sur le bouton ArrÃªt de la construction, visible figureÂ 16gg. Si vous quittez la page web (sans avoir annulÃ© le processus de construction Ã  l'aide du bouton ArrÃªt de la construction), la construction continuera Ã  s'effectuer, et la nouvelle collection sera installÃ©e Ã  la fin de l'opÃ©ration. </Text>
+</Content>
+</Subsection>
+<Subsection id="viewing_the_collection">
+<Title>
+<Text id="541">Afficher la collection</Text>
+</Title>
+<Content>
+<Text id="542">Quand la collection est construite et installÃ©e, la suite de boutons visibles aux bas des figuresÂ 16bb Ã Â 16ff apparaÃ®t au bas de la figureÂ 16gg, avec le bouton afficher la collection activÃ©. Ce bouton emmÃšne directement l'utilisateur vers la collection nouvellement construite.</Text>
+<Text id="543">Enfin, il existe une fonctionnalitÃ© d'envoi de courrier d'Ã©lectronique Ã  l'adresse Ã©lectronique de contact de la collection ainsi qu'Ã  l'administrateur systÃšme, Ã  chaque crÃ©ation (ou modification) d'une collection. Ceci permet aux responsables de vÃ©rifier tout changement prenant place et de surveiller ce qui se passe sur le systÃšme. Cette fonctionnalitÃ© est dÃ©sactivÃ©e par dÃ©faut mais elle peut Ãªtre activÃ©e en Ã©ditant le fichier de configuration main.cfg (voir Ã  ce sujet le Guide du dÃ©veloppeur de la bibliothÃšque numÃ©rique Greenstone, sectionÂ <CrossRef target="Chapter" external="Develop" lang="fr" ref="configuring_your_greenstone_site"/>).</Text>
+</Content>
+</Subsection>
+<Subsection id="working_with_existing_collections">
+<Title>
+<Text id="544">Travailler avec des collections existantes</Text>
+</Title>
+<Content>
+<Text id="545">Lorsque l'on dÃ©marre le Collector, il faut spÃ©cifier si on souhaite crÃ©er une collection entiÃšrement nouvelle, ou travailler avec une collection existante, en y ajoutant ou en en effaÃ§ant des donnÃ©es. Ãtant donnÃ© qu'il crÃ©e automatiquement toutes les structures de recherche et de navigation Ã  partir des documents eux-mÃªmes, Greenstone facilite l'ajout de nouvelles informations Ã  des collections existantes. Aucun lien n'Ã©tant insÃ©rÃ© manuellement, il est possible de fusionner automatiquement au reste de la collection de nouveaux documents disponibles, s'ils sont au mÃªme format.</Text>
+<Text id="546">Pour travailler avec une collection existante, il faut d'abord sÃ©lectionner la collection au sein d'une liste fournie par le logiciel. Certaines collections sont Â«protÃ©gÃ©es en Ã©critureÂ» et ne peuvent pas Ãªtre modifiÃ©es: de telles collections n'apparaÃ®tront pas dans la liste de sÃ©lections. Avec la collection retenue, vous pourrez:</Text>
+<BulletList>
+<Bullet>
+<Text id="547">Ajouter de nouvelles donnÃ©es et reconstruire la collection;</Text>
+</Bullet>
+<Bullet>
+<Text id="548">Ãditer le fichier de configuration de la collection;</Text>
+</Bullet>
+<Bullet>
+<Text id="549">Effacer entiÃšrement la collection;</Text>
+</Bullet>
+<Bullet>
+<Text id="550">Exporter la collection sur un cÃ©dÃ©rom.</Text>
+</Bullet>
+</BulletList>
+<Part id="add_new_data">
+<Title>
+<Text id="551">Ajouter de nouvelles donnÃ©es</Text>
+</Title>
+<Content>
+<Text id="552">Les fichiers spÃ©cifiÃ©s par vous seront ajoutÃ©s Ã  la collection. Assurez-vous de ne pas spÃ©cifier Ã  nouveau des fichiers dÃ©jÃ  prÃ©sents dans la collection, sans quoi deux copies en seraient incluses. Les fichiers sont identifiÃ©s par leur chemin d'accÃšs complet, et les pages web par leur adresse web absolue. On peut spÃ©cifier des rÃ©pertoires et des fichiers de la mÃªme maniÃšre que lors de la construction d'une nouvelle collection.</Text>
+<Text id="553">Si vous souhaitez ajouter des donnÃ©es Ã  une collection et que pour l'une ou l'autre raison, le processus de construction Ã©choue, l'ancienne version de la collection demeurera inchangÃ©e.</Text>
+</Content>
+</Part>
+<Part id="edit_configuration_file">
+<Title>
+<Text id="554">Ãditer le fichier de configuration</Text>
+</Title>
+<Content>
+<Text id="555">Les utilisateurs expÃ©rimentÃ©s peuvent Ã©diter le fichier de configuration de la collection, de la mÃªme maniÃšre que lors de la construction d'une nouvelle collection. La sectionÂ 4explique les rÃ©glages de configuration.</Text>
+</Content>
+</Part>
+<Part id="delete_the_collection">
+<Title>
+<Text id="556">Effacer la collection</Text>
+</Title>
+<Content>
+<Text id="557">On vous demandera de confirmer le fait que vous souhaitez vraiment effacer la collection. Une fois la collection effacÃ©e, Greenstone ne pourra pas la rÃ©cupÃ©rer!</Text>
+</Content>
+</Part>
+<Part id="export_the_collection">
+<Title>
+<Text id="558">Exporter la collection</Text>
+</Title>
+<Content>
+<Text id="559">Vous pouvez exporter la collection sous une forme qui lui permette d'Ãªtre Ã©crite sur un cÃ©dÃ©rom Windows autonome et auto-installable. Les logiciels propriÃ©taires crÃ©ant des cÃ©dÃ©roms auto-installables Ã©tant onÃ©reux, cette fonctionnalitÃ© comprend un module d'installation maison.</Text>
+<Text id="560">Lors de l'export de la collection, la boÃ®te de dialogue vous informe du nom du rÃ©pertoire oÃ¹ se trouve le rÃ©sultat de l'opÃ©ration. Ce rÃ©pertoire doit intÃ©gralement Ãªtre gravÃ© sur le cÃ©dÃ©rom en utilisant un logiciel standard de gravage.</Text>
+<Text id="561">L'immense variÃ©tÃ© des diffÃ©rentes configurations Windows possibles nous a empÃªchÃ© de tester et de dÃ©boguer l'installeur de Greenstone dans toutes les conditions possibles. Bien qu'il produise des cÃ©dÃ©roms qui fonctionneront sur la plupart des systÃšmes Windows, il est toujours en cours de dÃ©veloppement. Si vous rencontrez des problÃšmes et que vous disposez d'un logiciel d'installation propriÃ©taire (tel qu'InstallShield, par exemple), vous pouvez utiliser ce dernier pour crÃ©er des cÃ©dÃ©roms Ã  partir des informations fournies par Greenstone. Le rÃ©pertoire d'export mentionnÃ© ci-dessus contient quatre fichiers relatifs au processus d'installation, et trois sous-rÃ©pertoires qui contiennent la collection et le logiciel au complet. Ãtez les quatre fichiers et utilisez InstallShield pour crÃ©er une image de cÃ©dÃ©rom qui installera ces rÃ©pertoires et crÃ©era un raccourci vers le programme gsdlserver.exe.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="document_formats_1">
+<Title>
+<Text id="562">Formats de documents</Text>
+</Title>
+<Content>
+<Text id="563">Lors de la construction de collections, Greenstone traite chaque format de document source en recherchant un Â«greffonÂ» (plugin) qui est capable de le traiter. Les greffons sont spÃ©cifiÃ©s dans le fichier de configuration de la collection. Greenstone utilise en gÃ©nÃ©ral le nom de fichier pour dÃ©terminer le format de documentÂ --Â par exemple, toto.txt sera traitÃ© comme un fichier texte, toto.html comme un fichier HTML, et toto.doc comme un fichier Word.</Text>
+<Text id="564">Voici un rÃ©sumÃ© des greffons disponibles pour les formats de documents les plus courants. Vous trouverez plus de dÃ©tails sur ces greffons ainsi que des greffons supplÃ©mentaires, capables de traiter des formats moins courants, dans le Guide du dÃ©veloppeur de la bibliothÃšque numÃ©rique Greenstone.</Text>
+<Part id="textplug">
+<Title>
+<Text id="565">TEXTPlug (*.txt, *.text)</Text>
+</Title>
+<Content>
+<Text id="566">TEXTPlug interprÃšte un fichier texte comme un simple document. Il ajoute des mÃ©ta-donnÃ©es de titre en se fondant sur la premiÃšre ligne du fichier.</Text>
+</Content>
+</Part>
+<Part id="htmlplug">
+<Title>
+<Text id="567"><i>HTMLPlug (*.htm, *.html; et aussi .shtml, .shm, .asp, .php, .cgi)</i></Text>
+</Title>
+<Content>
+<Text id="568">HTMLPlug traite les fichiers HTML. Il extrait les mÃ©ta-donnÃ©es de titre en se fondant sur la balise<i>&lt;title&gt;</i>, et peut aussi extraire toute autre mÃ©ta-donnÃ©e exprimÃ©e dans la syntaxe de la balise<i>&lt;meta&gt;</i>de HTML. Ce greffon dispose de nombreuses options, documentÃ©es dans le Guide du dÃ©veloppeur de la bibliothÃšque numÃ©rique Greenstone.</Text>
+</Content>
+</Part>
+<Part id="wordplug">
+<Title>
+<Text id="569"><i>WORDPlug (*.doc)</i></Text>
+</Title>
+<Content>
+<Text id="570">WORDPlug importe des fichiers au format Microsoft Word. Il en existe de nombreuses variantes diffÃ©rentesÂ --Â et mÃªme les programmes de Microsoft sont coutumiers d'erreurs de conversion. Greenstone utilise des programmes indÃ©pendants pour convertir les fichiers Word en HTML. Pour certains anciens formats Word, le systÃšme utilise un simple algorithme d'extraction qui trouve toutes les portions de texte incluses dans le fichier en entrÃ©e.</Text>
+</Content>
+</Part>
+<Part id="pdfplug">
+<Title>
+<Text id="571"><i>PDFPlug (*.pdf)</i></Text>
+</Title>
+<Content>
+<Text id="572">PDFPlug importe des documents au format PDF d'Adobe (Â«format de document portableÂ»). Comme WORDPlug, il utilise un programme indÃ©pendant, qui s'appelle pdftohtml dans le cas prÃ©sent, pour convertir des fichiers PDF en HTML.</Text>
+<Text id="573">Comme dans le cas de WORDPlug, les collections afficheront par dÃ©faut l'Ã©quivalent HTML du fichier lorsque l'utilisateur cliquera sur l'icone document; cependant, on peut modifier les chaÃ®nes de format dans le fichier de configuration de la collection pour donner plutÃŽt accÃšs Ã  l'utilisateur au fichier PDF original, et nous vous recommandons de procÃ©der ainsi. Contentez-vous de remplacer les balises<i>&lt;link&gt; ... &lt;/link&gt;</i>par des balises<i>&lt;srclink&gt; ... &lt;/srclink&gt;</i>.</Text>
+<Text id="574">Le programme pdftohtml ne parvient pas Ã  traiter certains fichiers PDF. Le processus de conversion prend un temps exponentiellement long, et on voit souvent apparaÃ®tre Ã  l'Ã©cran un message traitant de ce processus. Si cela se produit, la seule solution que nous puissions proposer est d'ÃŽter le document concernÃ© de la collection. PDFPlug ne peut pas non plus traiter les fichiers PDF chiffrÃ©s.</Text>
+</Content>
+</Part>
+<Part id="psplug">
+<Title>
+<Text id="575"><i>PSPlug (*.ps)</i></Text>
+</Title>
+<Content>
+<Text id="576">PSPlug importe des documents au format PostScript. Il fonctionne au mieux si votre ordinateur dispose dÃ©jÃ  d'un programme standard sous Linux et appelÃ© ps2ascii. Ce programme est disponible sur la plupart des installations Linux, mais pas sous Windows. Si ce programme n'est pas disponible, PSPlug se limite Ã  un simple algorithme d'extraction de texte.</Text>
+</Content>
+</Part>
+<Part id="emailplug">
+<Title>
+<Text id="577"><i>EMAILPlug (*.email)</i></Text>
+</Title>
+<Content>
+<Text id="578">EMAILPlug importe des fichiers contenant du courrier Ã©lectronique, et traite les formats de courrier Ã©lectronique courants tels que ceux utilisÃ©s par Netscape, Eudora, et les lecteurs de courrier Ã©lectronique sous Unix. Chaque document source est examinÃ© Ã  la recherche d'un ou de plusieurs courriers Ã©lectroniques mis bout Ã  bout, et si cette recherche aboutit le contenu du document est traitÃ©. Le greffon extrait les mÃ©ta-donnÃ©es des champs Subject (Â«objetÂ»), To (Â«destinataireÂ»), From (Â«expÃ©diteurÂ»), et Date. Cependant, ce greffon ne traite pas encore correctement les courriers Ã©lectroniques encodÃ©s au format MIMEÂ --Â bien que lisibles, ils ont souvent un aspect Ã©trange.</Text>
+</Content>
+</Part>
+<Part id="zipplug">
+<Title>
+<Text id="579"><i>ZIPPlug (.gz, .z, .tgz, .taz, .bz, .zip, .tar)</i></Text>
+</Title>
+<Content>
+<Text id="580">Le greffon ZIPPlug traite les formats d'entrÃ©e compactÃ©s et/ou d'archives suivants: gzip (.gz, .z, .tgz, .taz), bzip (.bz), zip (.zip .jar), et tar (.tar). Il repose sur les programmes gunzip, bunzip, unzip, et tar, qui sont des outils standard sous Linux. ZIPPlug est dÃ©sactivÃ© sur les ordinateurs employant Windows.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="administration">
+<Title>
+<Text id="581">Administration</Text>
+</Title>
+<Content>
+<Text id="582">Chaque installation de Greenstone comprend un outil d'Â«administrationÂ», auquel on accÃšde en cliquant sur le lien appropriÃ© de la page d'accueil.</Text>
+<Text id="583">La premiÃšre page, prÃ©sentÃ©e figureÂ 17, donne des informations sur chacune des collections proposÃ©es par le systÃšme. Remarquez qu'il est possible que certaines collections Â«privÃ©esÂ» n'apparaissant pas sur la page d'accueil de Greenstone soient listÃ©es ici:<i>toutes</i>les collections sont ici prÃ©sentes. Chaque collection est accompagnÃ©e de son nom court, de son nom complet, du fait qu'elle est ou non publique, et du fait qu'elle est ou non en fonctionnement. Cliquer sur l'abrÃ©viation (abbrev.) d'une collection (la premiÃšre colonne de liens dans la figureÂ 17) fournira des informations sur cette collection, informations synthÃ©tisÃ©es Ã  partir du fichier de configuration de cette collection ainsi qu'Ã  partir d'autres structures internes crÃ©Ã©es pour elle. Si la collection est publique et en cours de fonctionnement, cliquer sur le nom complet de la collection (le deuxiÃšme lien) vous emmÃ©nera sur la collection Ã  proprement parler. </Text>
+<Text id="584">Une collection appelÃ©e wohiex, pour women's history excerpt, est visible prÃšs du bas de la figureÂ 17. FigureÂ 18montre l'information qui est affichÃ©e quand on appuie sur ce lien. Quand on choisit une collection, la premiÃšre section donne des informations sur le fichier de configuration et sur la taille de la collection (dans le cas prÃ©sent, elle comprend environ 1000 documents, un million de mots, et plus de 6 mÃ©ga-octets de donnÃ©es). Les sections suivantes contiennent des informations internes relatives au protocole de communication utilisÃ© pour accÃ©der aux collections. Par exemple, les options de filtre pour Â«QueryFilterÂ» montrent les options et les valeurs possibles qu'on peut utiliser lors de l'interrogation de la collection par requÃªtes.</Text>
+<Text id="585">L'outil d'administration prÃ©sente Ã©galement des informations de configuration relatives Ã  l'installation et permet de modifier cette derniÃšre. Il facilite l'examen du journal d'erreurs (qui enregistre les erreurs internes) et du journal utilisateur (qui consigne l'utilisation de la collection). Il permet Ã  un ou plusieurs utilisateurs spÃ©cifiÃ©s d'en autoriser d'autres Ã  construire des collections et Ã  ajouter du contenu Ã  des collections existantes. On accÃšde Ã  toutes ces fonctionnalitÃ©s de maniÃšre interactive Ã  partir d'Ã©lÃ©ments du menu situÃ© Ã  gauche sur la figureÂ 17.</Text>
+<Figure id="greenstone_administration_facility">
+<Title>
+<Text id="586">Outil d'administration de Greenstone</Text>
+</Title>
+<File url="images/User_Fig_17.png"/>
+</Figure>
+<Figure id="information_about_the_womens_history_excerpt_collection">
+<Title>
+<Text id="587">Informations relatives Ã  une collection particuliÃšre</Text>
+</Title>
+<File url="images/User_Fig_18a.png"/>
+<File url="images/User_Fig_18b.png"/>
+</Figure>
+<Section id="configuration_files">
+<Title>
+<Text id="588">Fichiers de configuration</Text>
+</Title>
+<Content>
+<Text id="589">Deux fichiers de configuration contrÃŽlent le fonctionnement de Greenstone: le fichier de configuration de site gsdlsite.cfg et le fichier de configuration principal main.cfg.</Text>
+<Text id="590">Le fichier gsdlsite.cfg sert Ã  configurer Greenstone pour le site particulier sur lequel il est installÃ©. Il est conÃ§u pour enregistrer les options de configuration propres Ã  un site donnÃ©, comme par exemple le nom du rÃ©pertoire abritant le logiciel, l'adresse HTTP du systÃšme Greenstone, et si l'option Â«Fast-CGIÂ» est utilisÃ©e ou non. Les entrÃ©es de ce fichier sont dÃ©crites dans le Guide d'installation de la bibliothÃšque numÃ©rique Greenstone</Text>
+<Text id="591">Le fichier main.cfg contient des informations communes Ã  l'interface et Ã  toutes les collections servies sur un site Greenstone. Il comprend l'adresse Ã©lectronique du mainteneur du systÃšme, le fait que les pages d'Ã©tat et de Collector sont activÃ©es ou non, le fait qu'on conserve ou non des journaux de l'activitÃ© utilisateur, et si l'on utilise ou non des Â«cookiesÂ» web pour identifier les utilisateurs.</Text>
+</Content>
+</Section>
+<Section id="logs">
+<Title>
+<Text id="592">Journaux</Text>
+</Title>
+<Content>
+<Text id="593">On peut examiner trois types de journaux: journaux d'utilisation, d'erreur, et d'initialisation. Les deux derniers types de journaux ne prÃ©senteront rÃ©ellement d'intÃ©rÃªt qu'aux yeux des mainteneurs du logiciel.</Text>
+<Text id="594">Le logiciel Greenstone peut consigner toute l'activitÃ© utilisateur, c'est-Ã -dire toutes les pages visitÃ©es par chaque utilisateur, bien qu'aucune information nominative ne soit stockÃ©e dans les journaux. On active la journalisation (qui est dÃ©sactivÃ©e par dÃ©faut) en incluant les lignes suivantes:</Text>
+<CodeLine>logcgiargs true usecookies true</CodeLine>
+<Text id="595">dans le fichier de configuration principal du systÃšme. Ces deux options ayant par dÃ©faut la valeur fausse false, aucune journalisation n'a lieu tant qu'elles ne reÃ§oivent pas la valeur vraie true. C'est la ligne logcgiargs qui a pour effet d'activer ou de dÃ©sactiver la journalisation. En activant usecookies, on affecte Ã  chaque utilisateur un code d'identification unique, ce qui permet de suivre dans le journal les interactions de chaque utilisateur.</Text>
+<Text id="596">Chaque ligne du journal utilisateur reprÃ©sente une page visitÃ©eÂ --Â mÃªme les pages gÃ©nÃ©rÃ©es pour la consultation des journaux sont ainsi consignÃ©es! Elle comprend (a) l'adresse IP de l'ordinateur de l'utilisateur, (b) une estampille temporelle entre crochets, (c) les arguments CGI entre parenthÃšses, et (d) le nom du navigateur de l'utilisateur (sachant que le navigateur de Netscape s'appelle Â«MozillaÂ»). Voici un exemple d'une telle ligne, Ã©chantillon ventilÃ© et annotÃ© pour en faciliter la lecture:</Text>
+<CodeLine>/fast-cgi-bin/niupepalibrary (a) its-www1.massey.ac.nz (b) [Thu Dec 07 23:47:00 NZDT 2000] (c) (a=p, b=0, bcp=, beu=, c=niupepa, cc=, ccp=0, ccs=0, cl=, cm=, cq2=, d=, e=, er=, f=0, fc=1, gc=0, gg=text, gt=0, h=, h2=, hl=1, hp=, il=l, j=, j2=, k=1, ky=, l=en, m=50, n=, n2=, o=20, p=home, pw=, q=, q2=, r=1, s=0, sp=frameset, t=1, ua=, uan=, ug=, uma=listusers, umc=, umnpw1=, umnpw2=, umpw=, umug=, umun=, umus=, un=, us=invalid, v=0, w=w, x=0, z=130.123.128.4-950647871) (d) "Mozilla/4.08 [en] (Win95; I ;Nav)" </CodeLine>
+<Text id="597">Le dernier argument CGI, Â«zÂ», est un code d'identification ou Â«cookieÂ» engendrÃ© par le navigateur de l'utilisateur: il comprend le numÃ©ro IP suivi d'une estampille temporelle portant la date de la premiÃšre visite de cet utilisateur Ã  la bibliothÃšque numÃ©rique.</Text>
+<Text id="598">Le journal usage.txt est placÃ© dans le rÃ©pertoire etc de la structure de fichiers de Greenstone (voir Ã  ce sujet le Guide du dÃ©veloppeur de la bibliothÃšque numÃ©rique Greenstone). Lorsque la journalisation est activÃ©e, chaque action de chaque utilisateur est consignÃ©e. Cependant, seules les 100 derniÃšres entrÃ©es du journal sont affichÃ©es par le lien Journal de l'utilisation visible figureÂ 17.</Text>
+</Content>
+</Section>
+<Section id="user_management">
+<Title>
+<Text id="599">Gestion des utilisateurs</Text>
+</Title>
+<Content>
+<Text id="600">Greenstone incorpore un systÃšme d'authentification qu'on peut utiliser pour contrÃŽler l'accÃšs Ã  certaines fonctionnalitÃ©s. Pour le moment, il ne sert qu'Ã  restreindre l'accÃšs au Collector et Ã  certaines fonctions d'administration. Si pour une collection particuliÃšre il s'avÃ©rait nÃ©cessaire d'authentifier les utilisateurs avant de leur renvoyer des informations, cela serait Ã©galement possible. On pourrait par exemple protÃ©ger individuellement des documents de telle sorte que seuls des utilisateurs enregistrÃ©s puissent y accÃ©der en tapant un mot de passe. Cependant, aucune collection n'utilise cette possibilitÃ© actuellement. L'authentification se fait en requÃ©rant un nom d'utilisateur et un mot de passe, comme illustrÃ© figureÂ 16aa.</Text>
+<Text id="601">La page d'administration permet de lister les utilisateurs, d'en ajouter de nouveaux, et d'en effacer d'anciens. Ãvidemment, ce pouvoir est lui aussi protÃ©gÃ©: seuls les utilisateurs disposant de privilÃšges d'administration peuvent ajouter de nouveaux utilisateurs. Il est Ã©galement possible Ã  chaque utilisateur d'appartenir Ã  diffÃ©rents Â«groupesÂ». Actuellement, il n'existe que deux groupes, qui sont Â«administratorÂ» (administrateur) et Â«colbuilderÂ» (constructeur de collection). Les membres du premier groupe peuvent ajouter et effacer des utilisateurs, et modifier leurs groupes. Les membres du second peuvent accÃ©der aux fonctionnalitÃ©s dÃ©crites plus haut pour construire de nouvelles collections et modifier (ou effacer) des collections existantes. </Text>
+<Text id="602">Lors de l'installation de Greenstone, il existe un utilisateur, appelÃ© admin, qui appartient aux deux groupes. Son mot de passe est mis en place pendant le processus d'installation. Cet utilisateur peut crÃ©er de nouveaux identifiants et mots de passe associÃ©s pour des utilisateurs qui n'appartiendraient qu'au groupe colbuilder, ce qui est la mÃ©thode conseillÃ©e pour donner Ã  d'autres utilisateurs la possibilitÃ© de construire des collections. Les informations utilisateur sont stockÃ©es dans deux bases de donnÃ©es placÃ©es dans la structure de fichiers de Greenstone (voir Ã  ce sujet le Guide du dÃ©veloppeur de la bibliothÃšque numÃ©rique Greenstone).</Text>
+</Content>
+</Section>
+<Section id="technical_information">
+<Title>
+<Text id="603">Informations techniques</Text>
+</Title>
+<Content>
+<Text id="604">Les liens situÃ©s sous l'en-tÃªte Informations techniques fournissent davantage d'informations sur l'installation. Le lien GÃ©nÃ©ral donne accÃšs aux informations techniques, y compris les rÃ©pertoires de stockage. L'Ã©lÃ©ment de menu Protocoles donne, pour chaque type de protocole, des informations sur les collections accessibles par ce protocole.</Text>
+<Text id="605">Enfin, le code de l'interface utilisateur (appelÃ© le Â«rÃ©ceptionnisteÂ») utilise des<i>actions</i>pour communiquer les souhaits de l'utilisateur au systÃšme. Ces actions correspondent Ã  l'argument CGI libellÃ© Â«aÂ». Si par exemple<i>a=status</i>, le rÃ©ceptionniste invoque l'action status, qui affiche la page d'Ã©tats. Un Ã©lÃ©ment de menu donne accÃšs aux listes de toutes les actions proposÃ©es par le systÃšme, et un autre mÃšne aux arguments acceptÃ©s par ces actions.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="appendix_a_software_features">
+<Title>
+<Text id="606">FonctionnalitÃ©s du logiciel</Text>
+</Title>
+<Content>
+<Table class="hidden" id="table_appendixa">
+<Title/>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="607"><i>Accessible Ã  travers un navigateur web</i></Text>
+</th>
+<th width="397">
+<Text id="608">On accÃšde aux collections Ã  travers un navigateur web standard (tel que Netscape ou Internet Explorer), ce qui fournit Ã  la fois une navigation facile et des fonctionnalitÃ©s de recherche puissantes. </Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="609"><i>FonctionnalitÃ©s du logiciel</i></Text>
+</th>
+<th width="397">
+<Text id="610">L'utilisateur peut effectuer des recherches dans le corps du texte des documents, ou choisir parmi plusieurs index construits Ã  partir de diffÃ©rentes portions des documents. Certaines collections proposent par exemple un index des documents complets, un index des sections, un index des titres, et un index des auteurs, qu'on peut tous sÃ©lectionner pour rechercher certains mots ou groupes de mots. Les rÃ©sultats peuvent Ãªtre ordonnÃ©s par leur pertinence ou en utilisant une mÃ©ta-donnÃ©e.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="611"><i>Souplesse de la navigation</i></Text>
+</th>
+<th width="397">
+<Text id="612">L'utilisateur peut naviguer dans les listes des auteurs, des titres, des dates, des structures de classification, etc. Des collections diffÃ©rentes pourront proposer des fonctionnalitÃ©s de navigation diffÃ©rentes et mÃªme au sein d'une collection, on trouvera un large spectre d'interfaces de navigation. Les interfaces de recherche et de navigation sont prÃ©parÃ©es pendant le processus de construction, en se fondant sur les informations de configuration de la collection.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="613"><i>CrÃ©ation automatique de structures d'accÃšs</i></Text>
+</th>
+<th width="397">
+<Text id="614">Le logiciel Greenstone crÃ©e des collections d'informations trÃšs faciles Ã  maintenir. Toutes les structures de recherche et de navigation sont directement construites Ã  partir des documents eux-mÃªmes. Aucun lien n'est insÃ©rÃ© manuellement, mais tous les liens existant dans les originaux sont conservÃ©s. Cela signifie que si de nouveaux documents du mÃªme format sont disponibles, ils peuvent Ãªtre automatiquement fusionnÃ©s au reste de la collection. En fait, pour la plupart des collections, tout ceci est pris en charge par des processus qui s'exÃ©cutent rÃ©guliÃšrement, partent Ã  la recherche de nouveaux contenus, et reconstruisent les index~---~le tout sans aucune intervention manuelle. </Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="615"><i>Utilisation des mÃ©ta-donnÃ©es disponibles</i></Text>
+</th>
+<th width="397">
+<Text id="616">On peut associer Ã  chaque document ou Ã  chaque section de document des mÃ©ta-donnÃ©es, c'est-Ã -dire des informations de description telles que l'auteur, le titre, la date, des mots-clefs, etc. Les mÃ©ta-donnÃ©es forment la matiÃšre premiÃšre des index de navigation. Elles doivent Ãªtre explicitement fournies, ou bien il doit Ãªtre possible de les obtenir automatiquement Ã  partir des documents eux-mÃªmes. La plupart des documents Ã©lectroniques utilisent le schÃ©ma de mÃ©ta-donnÃ©es<i>Dublin Core</i>, mais il est Ã©galement possible d'utiliser d'autres schÃ©mas.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="617"><i>Extension des possibilitÃ©s du systÃšme par greffons (Â«pluginsÂ»)</i></Text>
+</th>
+<th width="397">
+<Text id="618">Pour pouvoir utiliser plusieurs types de documents source, le logiciel est organisÃ© d'une maniÃšre telle qu'on peut Ã©crire des Â«greffonsÂ» (plugins) pour de nouveaux formats de documents. Il existe actuellement des greffons pour les formats texte brut, HTML, Word, PDF, PostScript, courrier Ã©lectronique, certains formats propriÃ©taires, et pour l'exploration rÃ©cursive de structures de fichiers arborescentes et d'archives compactÃ©es contenant de telles structures. Une collection peut proposer des documents de plusieurs formats source. On utilise un schÃ©ma semblable de Â«classificateursÂ» pour construire des index de navigation Ã  partir des mÃ©ta-donnÃ©es: les classificateurs crÃ©ent des index de navigation de divers types en se fondant sur les mÃ©ta-donnÃ©es.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="619"><i>ConÃ§u pour gÃ©rer des collections de plusieurs mÃ©ga-octets</i></Text>
+</th>
+<th width="397">
+<Text id="620">Les collections peuvent contenir plusieurs millions de documents, ce qui fait du systÃšme Greenstone un logiciel adaptÃ© aux collections de taille allant jusqu'Ã  plusieurs giga-octets.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="621"><i>Les documents peuvent Ãªtre Ã©crits dans n'importe quelle langue</i></Text>
+</th>
+<th width="397">
+<Text id="622">Le logiciel utilise Unicode partout, ce qui permet de traiter tous les langages d'une maniÃšre consistante. Ã l'heure actuelle, on a construit des collections contenant du franÃ§ais, de l'espagnol, du maori, du chinois, de l'arabe, et de l'anglais. C'est une conversion Ã  la volÃ©e qui traduit le format Unicode utilisÃ© en interne en un alphabet reconnu par le navigateur web de l'utilisateur.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="623"><i>L'interface utilisateur est disponible dans de nombreuses langues</i></Text>
+</th>
+<th width="397">
+<Text id="624">L'interface peut Ãªtre affichÃ©e en de nombreuses langues. Elle est actuellement disponible en allemand, anglais, arabe, chinois, espagnol, franÃ§ais, hollandais, maori, et portugais. On peut facilement ajouter de nouvelles langues Ã  cette liste de traductions.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="625"><i>Les collections peuvent contenir du texte, des images, du son, et de la vidÃ©o</i></Text>
+</th>
+<th width="397">
+<Text id="626">Les collections Greenstone peuvent comprendre du texte, des images, des contenus audio et vidÃ©o. La plupart des contenus non textuels sont reliÃ©s aux documents textuels ou accompagnÃ©s de descriptions textuelles (telles que les lÃ©gendes des figures) pour pouvoir Ãªtre accessibles depuis une recherche dans le corps du texte ou la navigation. Cependant, l'architecture du logiciel rend possible l'implÃ©mentation de greffons (plugins) et de classificateurs pour des donnÃ©es non textuelles.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="627"><i>Utilisation de techniques de compression avancÃ©es</i></Text>
+</th>
+<th width="397">
+<Text id="628">Greenstone utilise des techniques de compression pour rÃ©duire la taille des index et du texte. La rÃ©duction de taille des index par voie de compression a de plus l'avantage d'accÃ©lÃ©rer la vitesse de rapatriement du texte.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="629"><i>Fourniture d'une fonction d'administration</i></Text>
+</th>
+<th width="397">
+<Text id="630">Une fonction d'Â«administrationÂ» permet Ã  des utilisateurs spÃ©cifiÃ©s d'en autoriser de nouveaux Ã  construire des collections, Ã  protÃ©ger des documents de telle sorte que seuls des utilisateurs enregistrÃ©s puissent y accÃ©der en tapant un mot de passe, Ã  examiner la composition de toutes les collections, etc. Les journaux d'activitÃ© utilisateur peuvent enregistrer toutes les requÃªtes effectuÃ©es vers chaque collection Greenstone.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="631"><i>Les nouvelles collections apparaissent dynamiquement</i></Text>
+</th>
+<th width="397">
+<Text id="632">On peut mettre des collections Ã  jour et en proposer de nouvelles Ã  tout moment, sans devoir arrÃªter le systÃšme: le processus en charge de l'interface utilisateur remarquera (grÃ¢ce Ã  un systÃšme de sondages rÃ©guliers) que de nouvelles collections sont apparues et les ajoutera Ã  la liste proposÃ©e Ã  l'utilisateur.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="633"><i>Les collections peuvent Ãªtre publiÃ©es sur l'Internet ou sur un cÃ©dÃ©rom</i></Text>
+</th>
+<th width="397">
+<Text id="634">On peut utiliser le logiciel pour servir des collections sur le web. Mais les collections Greenstone peuvent Ãªtre diffusÃ©es, sous une forme exactement semblable, sur cÃ©dÃ©rom. L'interface utilisateur utilisera un navigateur web standard (Netscape est inclus sur chaque disque), et l'interaction se dÃ©roulera de la mÃªme maniÃšre que sur le web, Ã  ceci prÃšs que les temps de rÃ©ponse seront plus faciles Ã  prÃ©dire, et plus reproductibles car moins soumis aux alÃ©as du rÃ©seau. Les cÃ©dÃ©roms fonctionnent sous toutes les versions du systÃšme d'exploitation Windows.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="635"><i>Les collections peuvent Ãªtre distribuÃ©es sur plusieurs ordinateurs</i></Text>
+</th>
+<th width="397">
+<Text id="636">Une structure de processus souple permet de faire servir diffÃ©rentes collections par des ordinateurs diffÃ©rents, bien que tout soit prÃ©sentÃ© Ã  l'utilisateur de maniÃšre unifiÃ©e, sur la mÃªme page web, comme faisant partie de la mÃªme bibliothÃšque numÃ©rique.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="637"><i>Fonctionne sous Windows comme sous Unix</i></Text>
+</th>
+<th width="397">
+<Text id="638">Greenstone fonctionne Ã  la fois sous Windows (versions 3.1/3.11, 95/98/Me, NT/2000) et sous Unix (Linux et SunOS). On peut utiliser n'importe lequel de ces systÃšmes comme serveur web. On ne peut pas construire des collections sur des systÃšmes Windows de bas de gamme, mais on peut y transfÃ©rer des collections prÃ©-construites ailleurs.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="639"><i>Ce que Greenstone apporte</i></Text>
+</th>
+<th width="397">
+<Text id="640">La bibliothÃšque numÃ©rique Greenstone est un logiciel libre, disponible depuis le site web de la bibliothÃšque numÃ©rique de Nouvelle-ZÃ©lande (<u>nzdl.org</u>) sous les termes de la licence publique gÃ©nÃ©rale de GNU. le logiciel comprend tout ce qui est dÃ©crit ci-dessus: service web, crÃ©ation de cÃ©dÃ©roms, construction de collection, possibilitÃ©s multilingues, greffons (plugins) et classificateurs permettant d'accepter un grand nombre de formats de documents source. Il comprend une fonctionnalitÃ© d'installation automatique pour faciliter cette opÃ©ration sur les systÃšmes Windows comme Unix. Dans l'esprit du logiciel libre, les utilisateurs sont encouragÃ©s Ã  nous communiquer tout rapport de bogue, correction, modification ou amÃ©lioration.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Chapter>
+<Chapter id="appendix_b_glossary_of_terms">
+<Title>
+<Text id="641">Glossaire des termes</Text>
+</Title>
+<Content>
+<Table class="hidden" id="appendixb">
+<Title/>
+<TableContent>
+<tr>
+<th width="123">
+<Text id="642"><b>Terme</b></Text>
+</th>
+<th width="406">
+<Text id="643"><b>Signification</b></Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="644"><i>autoconf</i></Text>
+</th>
+<th width="406">
+<Text id="645">Programme Unix utilisÃ© pour configurer le paquetage d'installation du logiciel Greenstone et l'adapter Ã  votre systÃšme</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="646"><i>Autorun</i></Text>
+</th>
+<th width="406">
+<Text id="647">FonctionnalitÃ© de Windows qui dÃ©marre un programme automatiquement lors de l'insertion d'un cÃ©dÃ©rom</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="648">BoolÃ©enne, requÃªte</Text>
+</th>
+<th width="406">
+<Text id="649">RequÃªte dans un systÃšme de rapatriement d'informations qui peut contenir des ET, OU, et NON boolÃ©ens </Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="650">Navigation</Text>
+</th>
+<th width="406">
+<Text id="651">AccÃšs Ã  une collection en parcourant une liste organisÃ©e de valeurs de mÃ©ta-donnÃ©es associÃ©es aux documents (telles que l'auteur, le titre, la date, des mots-clefs)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="652"><i>buildcol.pl</i></Text>
+</th>
+<th width="406">
+<Text id="653">Programme de Greenstone utilisÃ© pour construire des collections</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="654">Construction</Text>
+</th>
+<th width="406">
+<Text id="655">Processus de crÃ©ation des structures d'indexation et de navigation utilisÃ©es pour accÃ©der Ã  une collection</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="656">C++</Text>
+</th>
+<th width="406">
+<Text id="657">Langage de programmation dans lequel est Ã©crit la majoritÃ© des logiciels Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="658">Casse, ignorer la</Text>
+</th>
+<th width="406">
+<Text id="659">Faire en sorte que les opÃ©rations de recherche ne distinguent pas les majuscules des minuscules</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="660">CGI</Text>
+</th>
+<th width="406">
+<Text id="661">Common Gateway Interface (interface commune de passerelle), systÃšme qui permet Ã  des utilisateurs d'activer des programmes sur l'ordinateur hÃŽte (ou serveur) en cliquant sur des pages web</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="662">CGI, script</Text>
+</th>
+<th width="406">
+<Text id="663">Code associÃ© Ã  un bouton, un menu, ou Ã  un lien sur une page web qui spÃ©cifie ce que l'ordinateur hÃŽte (ou serveur) doit faire lorsque l'utilisateur clique sur cet objet</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="664"><i>cgi-bin</i></Text>
+</th>
+<th width="406">
+<Text id="665">RÃ©pertoire de stockage des scripts CGI</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="666">Classificateur</Text>
+</th>
+<th width="406">
+<Text id="667">Module de code de Greenstone qui examine les mÃ©ta-donnÃ©es d'un document et crÃ©e un index de navigation</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="668">Collection</Text>
+</th>
+<th width="406">
+<Text id="669">Ensemble de documents rassemblÃ©s sous une interface de recherche et de navigation homogÃšne</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="670">Collection, fichier de configuration</Text>
+</th>
+<th width="406">
+<Text id="671">Fichier qui spÃ©cifie comment importer et construire une collection, quels index et quelles interfaces de langue fournir, etc.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="672">Collection, serveur de</Text>
+</th>
+<th width="406">
+<Text id="673">Programme fournissant l'accÃšs Ã  une collection en cours d'utilisation</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="674">Configuration, fichier de</Text>
+</th>
+<th width="406">
+<Text id="675">Voir Â«Collection, fichier de configurationÂ», Â«Principal, fichier de configurationÂ», et Â«Site, fichier de configuration deÂ»</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="676">CVS</Text>
+</th>
+<th width="406">
+<Text id="677">Concurrent Versioning System (systÃšme de versions concurrentes), systÃšme permettant de maintenir le code source utilisÃ© par Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="678"><i>db2txt</i></Text>
+</th>
+<th width="406">
+<Text id="679">Outil Greenstone permettant de visualiser une base de donnÃ©es GDBM sous forme textuelle (voir Â«GDBMÂ»)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="680">Â«DemoÂ», collection</Text>
+</th>
+<th width="406">
+<Text id="681">Sous-ensemble de la bibliothÃšque de dÃ©veloppement pour l'humanitÃ©, distribuÃ© avec le logiciel Greenstone Ã  des fins d'illustration et de didacticiel</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="682">BibliothÃšque numÃ©rique</Text>
+</th>
+<th width="406">
+<Text id="683">Collection d'objets numÃ©riques (textes, extraits audio ou vidÃ©o) ainsi que de mÃ©thodes d'accÃšs et de rapatriement, de sÃ©lection, d'organisation, et de maintenance</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="684"><i>HDL</i></Text>
+</th>
+<th width="406">
+<Text id="685">Humanity Development Library (bibliothÃšque de dÃ©veloppement pour l'humanitÃ©), collection Greenstone d'informations humanitaires pour les pays en voie de dÃ©veloppement</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="686">Document</Text>
+</th>
+<th width="406">
+<Text id="687">UnitÃ© de base servant Ã  construire des collections de bibliothÃšques numÃ©riques; elle peut contenir du texte, des graphiques, du son, de la vidÃ©o, etc.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="688">Dublin core</Text>
+</th>
+<th width="406">
+<Text id="689">ManiÃšre standardisÃ©e de dÃ©crire les mÃ©ta-donnÃ©es</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="690">Fast CGI</Text>
+</th>
+<th width="406">
+<Text id="691">Outil qui permet aux scripts CGI de demeurer actifs en permanence, de maniÃšre Ã  Ã©viter de les redÃ©marrer de zÃ©ro Ã  chacune de leurs invocations</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="692">Filtre, programme de</Text>
+</th>
+<th width="406">
+<Text id="693">La portion d'un serveur de collection Greenstone qui implÃ©mente les opÃ©rations de requÃªte et de navigation</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="694">Format, chaÃ®ne de</Text>
+</th>
+<th width="406">
+<Text id="695">ChaÃ®ne qui spÃ©cifie comment afficher les documents et autres listes dans Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="696">GB, encodage</Text>
+</th>
+<th width="406">
+<Text id="697">ManiÃšre standardisÃ©e d'encoder le chinois</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="698">GDBM</Text>
+</th>
+<th width="406">
+<Text id="699">GNU DataBase Manager (gestionnaire de bases de donnÃ©es de GNU), programme utilisÃ© par le logiciel Greenstone pour stocker les mÃ©ta-donnÃ©es de chaque document</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="700">GIMP</Text>
+</th>
+<th width="406">
+<Text id="701">GNU Image-Manipulation Program (programme de manipulation d'images de GNU), utilisÃ© (sur Unix) pour crÃ©er les icones de Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="702">GML</Text>
+</th>
+<th width="406">
+<Text id="703">Greenstone Markup Language (langage de balisage de Greenstone), un format compatible XML utilisÃ© pour stocker les documents de maniÃšre interne</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="704">GNU, licence publique gÃ©nÃ©rale (GPL)</Text>
+</th>
+<th width="406">
+<Text id="705">licence de logiciels qui permet aux utilisateurs de copier et de distribuer librement les programmes d'ordinateurs qu'elle couvre, ainsi que de les modifier, pour peu que toutes les modifications soient rendues publiques</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="706">Greenstone</Text>
+</th>
+<th width="406">
+<Text id="707">Nom de ce logiciel de bibliothÃšque numÃ©rique </Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="708">GSDL</Text>
+</th>
+<th width="406">
+<Text id="709">AbrÃ©viation de \lang{Greenstone Digital Library} (bibliothÃšque numÃ©rique Greenstone)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="710"><i>%GSDLHOME%</i></Text>
+</th>
+<th width="406">
+<Text id="711">Variable pour le systÃšme d'exploitation (Windows) reprÃ©sentant le rÃ©pertoire racine oÃ¹ tous les programmes et collections Greenstone sont stockÃ©s (<i>$GSDLHOME</i>sur des systÃšmes Unix)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="712"><i>%GSDLOS%</i></Text>
+</th>
+<th width="406">
+<Text id="713">Variable pour le systÃšme d'exploitation (Windows) reprÃ©sentant le systÃšme d'exploitation en cours d'utilisation (<i>$GSDLOS</i>sur des systÃšmes Unix)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="714"><i>hashfile</i>DL</Text>
+</th>
+<th width="406">
+<Text id="715">Programme Greenstone utilisÃ© au moment de l'import ou de la construction pour gÃ©nÃ©rer l'OID de chaque document</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="716">HTML</Text>
+</th>
+<th width="406">
+<Text id="717">HyperText Markup Language (langage de balisage pour l'hypertexte), le langage dans lequel la plupart des documents web sont Ã©crits</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="718"><i>import.pl</i></Text>
+</th>
+<th width="406">
+<Text id="719">Programme Greenstone utilisÃ© pour importer des documents</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="720">Importing</Text>
+</th>
+<th width="406">
+<Text id="721">Processus de rassemblement de collections de documents dans le systÃšme Greenstone </Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="722">Index</Text>
+</th>
+<th width="406">
+<Text id="723">Structure d'information utilisÃ©e pour la recherche ou la navigation au sein d'une collection</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="724">InstallShield</Text>
+</th>
+<th width="406">
+<Text id="725">Programme Windows, utilisÃ© par les cÃ©dÃ©roms Greenstone, qui permet Ã  un systÃšme d'Ãªtre installÃ© Ã  partir d'un cÃ©dÃ©rom</Text>
+</th>
+</tr>
+<tr>
+<tr>
+<th width="123">
+<Text id="726">Principal, fichier de configuration</Text>
+</th>
+<th width="406">
+<Text id="727">Fichier contenant les spÃ©cifications communes Ã  toutes les collections servies par un site</Text>
+</th>
+</tr>
+<th width="123">
+<Text id="728">MÃ©ta-donnÃ©es</Text>
+</th>
+<th width="406">
+<Text id="729">Informations de description telles que l'auteur, le titre, la date, des mots-clefs, etc., associÃ©es Ã  un document (ou Ã  une collection de documents)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="730">MG</Text>
+</th>
+<th width="406">
+<Text id="731">Managing Gigabytes (gÃ©rer les giga-octets), programme utilisÃ© par le systÃšme Greenstone pour l'indexation du corps du texte, embarquant des techniques de compression (voir Ã  ce sujet le livre de Witten, I.H., Moffat, A., et Bell, T. intitulÃ© \mytitle{Managing Gigabytes: compressing and indexing documents and images} (gÃ©rer les giga-octets: compression et indexation des documents et des images), Morgan Kaufmann, deuxiÃšme Ã©dition, 1999)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="732"><i>mgbuild</i></Text>
+</th>
+<th width="406">
+<Text id="733">Programme MG utilisÃ© pour construire un index de corps du texte</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="734"><i>mgquery</i></Text>
+</th>
+<th width="406">
+<Text id="735">Programme MG utilisÃ© pour effectuer des requÃªtes dans un index compressÃ© de corps du texte</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="736"><i>mkcol.pl</i></Text>
+</th>
+<th width="406">
+<Text id="737">Programme Greenstone qui crÃ©e et initialise la structure de rÃ©pertoire d'une nouvelle collection</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="738">Nouvelle-ZÃ©lande, projet de bibliothÃšque numÃ©rique de</Text>
+</th>
+<th width="406">
+<Text id="739">Projet de recherche du dÃ©partement d'informatique de l'universitÃ© de Waikato en Nouvelle-ZÃ©lande, qui a crÃ©Ã© le logiciel Greenstone (<u>nzdl.org</u>)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="740">OID</Text>
+</th>
+<th width="406">
+<Text id="741">Object Identifier (identifiant d'objet), code d'identification unique associÃ© Ã  un document</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="742">Perl</Text>
+</th>
+<th width="406">
+<Text id="743">Langage de programmation utilisÃ© pour une grande partie des opÃ©rations de manipulation de texte se dÃ©roulant lors du processus de construction</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="744">Ping</Text>
+</th>
+<th width="406">
+<Text id="745">Message envoyÃ© Ã  un systÃšme pour dÃ©terminer s'il est en fonctionnement ou non</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="746">Greffon (Â«pluginÂ»)</Text>
+</th>
+<th width="406">
+<Text id="747">Module de code qui gÃšre des documents de divers formats, utilisÃ© lors des processus d'import et de construction</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="748">Protocole</Text>
+</th>
+<th width="406">
+<Text id="749">Ensemble de conventions par lesquelles le rÃ©ceptionniste de Greenstone communique avec un serveur de collection</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="750">OrdonnÃ©e, requÃªte</Text>
+</th>
+<th width="406">
+<Text id="751">RequÃªte Ã  un systÃšme de rapatriement d'informations effectuÃ©e en langage naturel, et ordonnant les documents trouvÃ©s par ordre de pertinence</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="752">RÃ©ceptionniste</Text>
+</th>
+<th width="406">
+<Text id="753">Programme qui organise l'interface utilisateur de Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="754">RTF</Text>
+</th>
+<th width="406">
+<Text id="755">Rich Text Format (format de texte enrichi), format standard pour l'Ã©change de documents texte</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="756">Recherche</Text>
+</th>
+<th width="406">
+<Text id="757">AccÃšs Ã  une collection Ã  travers une recherche dans le corps du texte de ses contenus (ou d'une partie de ses contenus, telle que les titres de sections)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="758">Serveur</Text>
+</th>
+<th width="406">
+<Text id="759">Voir Â«Collection, serveur deÂ» et Â«Web, serveurÂ»</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="760"><i>setup.bat, setup.sh, setup.csh</i></Text>
+</th>
+<th width="406">
+<Text id="761">Script utilisÃ© pour mettre en place l'environnement nÃ©cessaire Ã  la reconnaissance du logiciel Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="762">Site, fichier de configuration de</Text>
+</th>
+<th width="406">
+<Text id="763">Fichier contenant les spÃ©cifications utilisÃ©es pour configurer le logiciel Greenstone pour le site particulier sur lequel il est installÃ©. </Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="764">Troncature</Text>
+</th>
+<th width="406">
+<Text id="765">Ãter la terminaison d'un mot dans un terme de requÃªte pour gÃ©nÃ©raliser la requÃªte</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="766">STL</Text>
+</th>
+<th width="406">
+<Text id="767">Standard template library} (bibliothÃšque standard de patrons), bibliothÃšque trÃšs rÃ©pandue de code C++, dÃ©veloppÃ©e par Silicon Graphics</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="768">txt2db</Text>
+</th>
+<th width="406">
+<Text id="769">Programme Greenstone utilisÃ© au moment de la construction pour crÃ©er la base de donnÃ©es GDBM</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="770">Unicode</Text>
+</th>
+<th width="406">
+<Text id="771">SystÃšme standard de reprÃ©sentation des ensembles de caractÃšres utilisÃ©s dans les langues du monde</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="772">UNU</Text>
+</th>
+<th width="406">
+<Text id="773">L'universitÃ© des Nations-Unies; on utilise Ã©galement ce sigle pour Ã©voquer une collection Greenstone crÃ©Ã©e pour cette organisation</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="774">Web, serveur</Text>
+</th>
+<th width="406">
+<Text id="775">Programme standard utilisÃ© par les ordinateurs pour publier de l'information sur le web</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="776">XML</Text>
+</th>
+<th width="406">
+<Text id="777">Format standard pour les documents et les donnÃ©es structurÃ©s sur le web (le langage de balisage de Greenstoneâvoir Ã  ce sujet Â«GMLÂ»âest un format compatible XML)</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Chapter>
+<FootnoteList>
+<Footnote id="1">
+<Text id="778">N.D.T. : Respectivement Â«etÂ», Â«ouÂ», et Â«nonÂ» en anglais.</Text>
+</Footnote>
+</FootnoteList>
+</Manual>
Index: /tags/start/gsdl-documentation/manuals/xml-source/manual.dtd
===================================================================
--- /tags/start/gsdl-documentation/manuals/xml-source/manual.dtd	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/xml-source/manual.dtd	(revision 13666)
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--DTD generated by XMLSpy v2006 rel. 3 sp2 (http://www.altova.com)-->
+<!ELEMENT Affiliation (Text)>
+<!ELEMENT Author (Text)>
+<!ELEMENT BulletItem (Text, BulletList?)>
+<!ELEMENT BulletList (BulletItem+)>
+<!ELEMENT Chapter (Title, Content)>
+<!ATTLIST Chapter
+	id CDATA #REQUIRED
+>
+<!ELEMENT CodeLine (#PCDATA | i | br)*>
+<!ELEMENT Comment (Text)>
+<!ELEMENT Content (Text | BulletList | Section | Subsection | CodeLine | Figure | Indented | Table | NumberedList | Part)+>
+<!ELEMENT Date (Text)>
+<!ELEMENT Figure (Title, CodeLine*, File?)>
+<!ATTLIST Figure
+	id CDATA #REQUIRED
+	class CDATA #IMPLIED
+>
+<!ELEMENT File EMPTY>
+<!ATTLIST File
+	url CDATA #REQUIRED
+	height CDATA #REQUIRED
+	width CDATA #REQUIRED
+>
+<!ELEMENT Footnote (Text)>
+<!ATTLIST Footnote
+	id CDATA #REQUIRED
+>
+<!ELEMENT FootnoteList (Footnote+)>
+<!ELEMENT FootnoteRef EMPTY>
+<!ATTLIST FootnoteRef
+	id CDATA #REQUIRED
+>
+<!ELEMENT Heading (Text)>
+<!ELEMENT Indented (Text)>
+<!ELEMENT Manual (Heading, Title, Author, Affiliation, Text, Comment, Version, Date, Section+, Chapter+, FootnoteList)>
+<!ELEMENT NumberedItem (Text)>
+<!ELEMENT NumberedList (NumberedItem+)>
+<!ELEMENT Part (Title, Content)>
+<!ATTLIST Part
+	id CDATA #REQUIRED
+>
+<!ELEMENT Section (Title, Content)>
+<!ATTLIST Section
+	id CDATA #REQUIRED
+>
+<!ELEMENT Subsection (Title, Content)>
+<!ATTLIST Subsection
+	id CDATA #REQUIRED
+>
+<!ELEMENT Table (Title, TableContent)>
+<!ATTLIST Table
+	id CDATA #REQUIRED
+	class CDATA #IMPLIED
+>
+<!ELEMENT TableContent (tr+)>
+<!ELEMENT Text (#PCDATA | b | i | FootnoteRef | br | File)*>
+<!ATTLIST Text
+	id CDATA #REQUIRED
+>
+<!ELEMENT Title (Text*)>
+<!ELEMENT Version (Text)>
+<!ELEMENT b (#PCDATA | b | br)*>
+<!ELEMENT br EMPTY>
+<!ELEMENT i (#PCDATA | br)*>
+<!ELEMENT th (Text | CodeLine)+>
+<!ATTLIST th
+	width CDATA #REQUIRED
+>
+<!ELEMENT tr (th+)>
Index: /tags/start/gsdl-documentation/manuals/xml-source/ru/Develop_ru.xml
===================================================================
--- /tags/start/gsdl-documentation/manuals/xml-source/ru/Develop_ru.xml	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/xml-source/ru/Develop_ru.xml	(revision 13666)
@@ -0,0 +1,6233 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Manual>
+<Heading>
+<Text id="1">ÐŠÐÐ€Ð ÐÐÐÐ¯ ÐÐÐÐÐÐÐ¢ÐÐÐ GREENSTONE</Text>
+</Heading>
+<Title>
+<Text id="2">Ð Ð£ÐÐÐÐÐÐ¡Ð¢ÐÐ</Text>
+</Title>
+<Author>
+<Text id="3">David Bainbridge, Dana McKay and Ian H. Witten</Text>
+</Author>
+<Affiliation>
+<Text id="4">Ð€Ð°ÐºÑÐ»ÑÑÐµÑ ÐÐŸÐŒÐ¿ÑÑÑÐµÑÐœÑÑ
+ ÐÐ°ÑÐº<br/> Ð£ÐœÐžÐ²ÐµÑÑÐžÑÐµÑ ÐÐ°Ð¹ÐºÐ°ÑÐŸ, ÐÐŸÐ²Ð°Ñ ÐÐµÐ»Ð°ÐœÐŽÐžÑ</Text>
+</Affiliation>
+<Text id="5">Greenstone - Ð¿Ð°ÐºÐµÑ Ð¿ÑÐžÐºÐ»Ð°ÐŽÐœÑÑ
+ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒ, Ð¿ÑÐµÐŽÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÐ¹ ÐŽÐ»Ñ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ Ðž ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÐµÐœÐžÑ ÑÐžÑÑÐŸÐ²ÑÑ
+ ÑÐŸÐœÐŽÐŸÐ² Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐº. Ð­ÑÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑÑÑ ÐœÐŸÐ²ÑÐŒ ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐŒ ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐž ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž Ðž Ð¿ÑÐ±Ð»ÐžÐºÐ°ÑÐžÐž ÐµÐµ Ð² ÑÐµÑÐž ÐÐœÑÐµÑÐœÐµÑ ÐžÐ»Ðž ÐœÐ° CD-ROM. ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ Greenstone ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÐ°ÐœÐŸ Ð² ÐÐŸÐ²ÐŸÐ·ÐµÐ»Ð°ÐœÐŽÑÐºÐŸÐŒ ÑÐœÐžÐ²ÐµÑÑÐžÑÐµÑÐµ ÐÐ°Ð¹ÐºÐ°ÑÐŸ, Ð² ÑÐ°ÐŒÐºÐ°Ñ
+ ÐÑÐŸÐµÐºÑÐ° ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÑÐžÑÑÐŸÐ²ÑÑ
+ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐº Ð² ÑÐŸÑÑÑÐŽÐœÐžÑÐµÑÑÐ²Ðµ Ñ Ð®ÐÐÐ¡ÐÐ Ðž ÐÐÐ Human Info. ÐÑÑ
+ÐŸÐŽÐœÑÐ¹ Ð¿ÑÐŸÐŽÑÐºÑ - ÑÑÐŸ ÑÐ²ÐŸÐ±ÐŸÐŽÐœÐŸ ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÑÐµÐŒÐŸÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ ÐŒÐŸÐ¶ÐœÐŸ Ð¿ÐŸÐ»ÑÑÐžÑÑ Ð¿ÐŸ Ð°ÐŽÑÐµÑÑ http://greenstone.org. ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÐŽÐ°ÐœÐœÐŸÐ³ÐŸ Ð¿ÑÐŸÐŽÑÐºÑÐ° ÐŸÐ³ÐŸÐ²Ð°ÑÐžÐ²Ð°ÐµÑÑÑ Ð² ÐÐžÑÐµÐœÐ·ÐžÐŸÐœÐœÐŸÐŒ ÑÐŸÐ³Ð»Ð°ÑÐµÐœÐžÐž ÐŸ ÑÐ²ÐŸÐ±ÐŸÐŽÐœÐŸÐŒ ÐŽÐŸÑÑÑÐ¿Ðµ GNU.</Text>
+<Comment>
+<Text id="6">ÐÑ ÐœÐ°ÐŽÐµÐµÐŒÑÑ, ÑÑÐŸ ÑÑÐŸ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ Ñ
+ÐŸÑÐŸÑÐŸ. ÐÐŸÐ¶Ð°Ð»ÑÐ¹ÑÑÐ°, ÑÐŸÐŸÐ±ÑÐžÑÐµ ÐŸ Ð»ÑÐ±ÑÑ
+ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÐ°Ñ
+ Ð¿ÐŸ Ð°ÐŽÑÐµÑÑ: greenstone@cs.waikato.ac.nz</Text>
+</Comment>
+<Version>
+<Text id="7">Greenstone gsdl-2.50</Text>
+</Version>
+<Date>
+<Text id="8">ÐÐ°ÑÑ 2004</Text>
+</Date>
+<Section id="about_this_manual">
+<Title>
+<Text id="9">ÐÐ± ÑÑÐŸÐ¹ ÐžÐœÑÑÑÑÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="10">ÐÐ°ÑÑÐŸÑÑÐµÐµ ÑÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ Ð¿ÑÐžÐœÑÐžÐ¿Ñ ÑÐ°Ð±ÐŸÑÑ Greenstone. ÐÐœÐŸ Ð¿ÑÐµÐŽÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐŸ ÐŽÐ»Ñ ÑÐµÑ
+, ÐºÑÐŸ Ñ
+ÐŸÑÐµÑ ÑÐ°ÐŒÐŸÑÑÐŸÑÑÐµÐ»ÑÐœÐŸ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ Ðž ÐºÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ.</Text>
+<Text id="11">Ð Ð°Ð·ÐŽÐµÐ» <CrossRef target="Chapter" ref="understanding_the_collection-building_process"/> ÐŽÐ°ÐµÑ ÑÑÐµÑÐœÑÑ Ð·Ð°Ð¿ÐžÑÑ Ð»ÐžÑÑ, ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ ÑÑÐ°ÑÑÐ²ÑÑÑÐµÐŒÑ Ð² Ð¿ÑÐŸÑÐµÑÑÐµ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, Ð²ÐºÐ»ÑÑÐ°Ñ ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÐºÑ ÑÑÑÑÐºÑÑÑÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐ¹, Ð²ÐœÑÑÑÐµÐœÐœÐµÐ³ÐŸ ÑÐŸÑÐŒÐ°ÑÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ðž ÑÐ°Ð¹Ð»Ð° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐ¿ÑÐ°Ð²Ð»ÑÐµÑ ÑÑÑÑÐºÑÑÑÐŸÐ¹ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð Ð°Ð·ÐŽÐµÐ» <CrossRef target="Chapter" ref="getting_the_most_out_of_your_documents"/> ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ ÑÐ°ÑÑÐž GreenÂ¬stone, ÐºÐŸÑÐŸÑÑÐµ ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÑÑ ÐžÑÑ
+ÐŸÐŽÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ (Ðž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ) Ðž ÑÐµÐ³Ð»Ð°ÐŒÐµÐœÑÐžÑÑÑÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž ÑÐµÑÐµÐ· ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ. ÐÐŽÐµÑÑ ÑÐ°ÐºÐ¶Ðµ ÐŸÐ¿ÐžÑÑÐ²Ð°ÑÑÑÑ "Ð²ÐœÐµÑÐœÐžÐµ" Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐµ ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑÑ, ÐºÐŸÑÐŸÑÑÐµ ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÑÑÑÑÑ Ð²ÐŒÐµÑÑÐµ Ñ Greenstone. Ð ÑÐ°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Chapter" ref="the_greenstone_runtime_system"/> Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐŸ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÑÑÑÑÐºÑÑÑÑ ÑÐžÑÑÐµÐŒÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐž Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ Greenstone, Ð° ÑÐ°ÐºÐ¶Ðµ ÐŽÐ°ÐœÐŸ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ, Ð¿ÑÐžÐ·Ð²Ð°ÐœÐœÐŸÐµ Ð¿ÐŸÐŒÐŸÑÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð»ÑÑÑÐµ Ð¿ÐŸÐœÑÑÑ, ÐºÐ°Ðº ÐŸÐœÐŸ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ Ðž ÐºÐ°Ðº ÐŒÐŸÐ¶ÐœÐŸ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÑÐžÑÑÐµÐŒÑ, ÑÑÐŸÐ±Ñ ÐŸÐœÐ° ÑÐŽÐŸÐ²Ð»ÐµÑÐ²ÐŸÑÑÐ»Ð° ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒ Ð¿ÐŸÑÑÐµÐ±ÐœÐŸÑÑÑÐŒ. Ð Ð°Ð·ÐŽÐµÐ» <CrossRef target="Chapter" ref="configuring_your_greenstone_site"/> ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ ÑÐ°Ð¹Ð»Ñ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž Greenstone, Ð° Ð² ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐ° Ð¡ÑÐ°ÐœÐŽÐ°ÑÑÐœÐ°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° ÑÐ°Ð±Ð»ÐŸÐœÐŸÐ² C++.</Text>
+<Text id="12">ÐÑÐž ÑÐ°Ð±ÐŸÑÐµ Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐŒ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµÐŒ GreenÂ¬stone ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÑÐŸÐ»ÐºÐœÑÑÑÑÑ ÑÐŸ ÑÑÑÐ»ÐºÐ°ÐŒÐž ÐœÐ° ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž ÑÐžÑÑÐµÐŒÑ, ÐºÐŸÑÐŸÑÑÐµ ÐœÐµ ÐŸÐ¿ÐžÑÐ°ÐœÑ Ð² ÐœÐ°ÑÑÐŸÑÑÐµÐŒ ÑÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ðµ. Ð­ÑÐŸ ÑÐ²ÑÐ·Ð°ÐœÐŸ Ñ ÑÐµÐŒ, ÑÑÐŸ Greenstone ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² Ð¿ÐŸÑÑÐŸÑÐœÐœÐŸÐŒ ÑÐ°Ð·Ð²ÐžÑÐžÐž. Ð§ÑÐŸÐ±Ñ Ð±ÑÑÑ Ð² ÐºÑÑÑÐµ ÑÐµÐºÑÑÐµÐ¹ ÑÐ°Ð±ÐŸÑÑ, Ð¿ÐŸÐŽÐ¿ÐžÑÐžÑÐµÑÑ ÐœÐ° ÑÐ°ÑÑÑÐ»ÐºÑ Greenstone (ÐžÐœÑÑÑÑÐºÑÐžÐž ÐœÐ° ÑÐ°Ð¹ÑÐµ greenstone.org).</Text>
+</Content>
+</Section>
+<Section id="companion_documents">
+<Title>
+<Text id="13">Ð¡ÐŸÐ¿ÑÑÑÑÐ²ÑÑÑÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ</Text>
+</Title>
+<Content>
+<Text id="14">ÐÐŸÐ»ÐœÑÐ¹ ÐºÐŸÐŒÐ¿Ð»ÐµÐºÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÑÐžÐž Ðº Greenstone ÑÐŸÑÑÐŸÐžÑ ÐžÐ· Ð¿ÑÑÐž ÑÐŸÐŒÐŸÐ²:</Text>
+<BulletList>
+<Bullet>
+<Text id="15">Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ Ð¿ÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐµ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="16">ÐÐœÑÑÑÑÐºÑÐžÑ ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ (ÑÑÐŸÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ) ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="17">Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐº Ð° ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="18">ÐŠÐžÑÑÐŸÐ²Ð°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Greenstone: ÐŸÑ ÐÑÐŒÐ°Ð³Ðž ÐŽÐŸ ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Bullet>
+<Bullet>
+<Text id="19">ÐŠÐžÑÑÐŸÐ²Ð°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Greenstone: ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÐÑÐ³Ð°ÐœÐ°Ð¹Ð·ÐµÑÐ°</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Section>
+<Section id="acknowledgements">
+<Title>
+<Text id="20">ÐÐ»Ð°Ð³ÐŸÐŽÐ°ÑÐœÐŸÑÑÑ</Text>
+</Title>
+<Content>
+<Text id="21">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ Greenstone - Ð¿ÑÐŸÐŽÑÐºÑ ÑÐŸÐ²ÐŒÐµÑÑÐœÐŸÐ³ÐŸ ÑÑÑÐŽÐ° ÐŒÐœÐŸÐ¶ÐµÑÑÐ²Ð° Ð»ÑÐŽÐµÐ¹. Rodger McNab Ðž Stefan Boddie Ð¿ÑÐžÐœÑÐžÐ¿ÐžÐ°Ð»ÑÐœÑÐµ ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐž ÑÐžÑÑÐµÐŒÑ. ÐÐµÐŸÑÐµÐœÐžÐŒÑÐ¹ Ð²ÐºÐ»Ð°ÐŽ Ð²ÐœÐµÑÐ»Ðž David Bainbridge, George Buchanan, Hong Chen, Michael Dewsnip, Katherine Don, Elke Duncker, Carl Gutwin, Geoff Holmes, Dana McKay, John McPherson, Craig Nevill-Manning, Dynal Patel, Gordon Paynter, Bernhard Pfahringer, Todd Reed, Bill Rogers, John Thompson, Ðž Stuart Yeates. ÐÑÑÐ°Ð»ÑÐœÑÐµ ÑÐ»ÐµÐœÑ ÐÑÐŸÐµÐºÑÐ° ÐÐŸÐ²ÐŸÐ·ÐµÐ»Ð°ÐœÐŽÑÐºÐŸÐ¹ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž  ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÐ°Ð»Ðž Ð²ÐŽÐŸÑ
+ÐœÐŸÐ²ÐµÐœÐœÑÐ¹ ÐŽÐžÐ·Ð°Ð¹Ðœ Ð²ÑÐµÐ¹ ÑÐžÑÑÐµÐŒÑ: Mark Apperley, Sally Jo Cunningham, Matt Jones, Steve Jones, Te Taka Keegan, Michel Loots, Malika Mahoui, Gary Marsden, Dave Nichols Ðž Lloyd Smith. ÐÑ ÑÐ°ÐºÐ¶Ðµ Ð²ÑÑÐ°Ð¶Ð°ÐµÐŒ ÑÐ²ÐŸÑ Ð¿ÑÐžÐ·ÐœÐ°ÑÐµÐ»ÑÐœÐŸÑÑÑ Ð²ÑÐµÐŒ ÑÐµÐŒ, ÐºÑÐŸ ÑÑÑÐŽÐžÐ»ÑÑ ÐœÐ°ÐŽ ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµÐŒ Ð¿Ð°ÐºÐµÑÐŸÐ², Ð¿ÐŸÐ¿Ð°ÐŽÐ°ÑÑÐžÑ
+ Ð¿ÐŸÐŽ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ Ð»ÐžÑÐµÐœÐ·ÐžÐž  GNU, Ðž Ð²ÐºÐ»ÑÑÐµÐœÐœÑÑ
+ Ð² ÐŽÐžÑÑÑÐžÐ±ÑÑÐžÐ²: MG, GDBM, PDFTOHTML, PERL, WGET, WVWARE Ðž XLHTML.</Text>
+</Content>
+</Section>
+<Chapter id="understanding_the_collection-building_process">
+<Title>
+<Text id="22">ÐÐŸÐœÑÑÐžÐµ Ð¿ÑÐŸÑÐµÑÑÐ° ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹</Text>
+</Title>
+<Content>
+<Text id="23">ÐÐŸÐœÐµÑÐœÑÐ¹ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Greenstone ÐŒÐŸÐ¶ÐµÑ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑ (Collector), ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÐ¹ Ð² ÐŽÐŸÐºÑÐŒÐµÐœÑÐµ <i>ÐŠÐžÑÑÐŸÐ²Ð°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Greenstone: Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ</i> (Ð Ð°Ð·ÐŽÐµÐ» 3). ÐÐœ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐŸÑÐµÐœÑ Ð¿ÑÐŸÑÑÐŸ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐœÐ° Ð±Ð°Ð·Ðµ ÑÐ¶Ðµ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÑ
+, ÐœÐŸ Ñ ÐœÐŸÐ²ÑÐŒ ÐœÐ°Ð¿ÐŸÐ»ÐœÐµÐœÐžÐµÐŒ. ÐÐŽÐœÐ°ÐºÐŸ ÐœÐµÐ²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑÐŸÐŒ Ð¿ÑÐž ÑÐŸÐ·ÐŽÐ°ÐœÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ñ Ð°Ð±ÑÐŸÐ»ÑÑÐœÐŸ ÐœÐŸÐ²ÐŸÐ¹ ÑÑÑÑÐºÑÑÑÐŸÐ¹. Ð ÑÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ Ð¿ÑÐžÐŽÐµÑÑÑ Ð²ÐœÐŸÑÐžÑÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð² ÑÐ°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐ¹, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐ¿ÑÐ°Ð²Ð»ÑÐµÑ ÑÑÑÑÐºÑÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð²ÐµÐŽÑ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÑÐ°ÐŽÐžÐºÐ°Ð»ÑÐœÑÐµ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð²ÐŸÐ·ÑÐŒÐµÐ»Ðž ÑÑÑÐµÐºÑ, ÐÐ°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð·ÐœÐ°ÑÑ Ð³ÐŸÑÐ°Ð·ÐŽÐŸ Ð±ÐŸÐ»ÑÑÐµ ÐŸ ÑÐžÑÑÐµÐŒÐµ Greenstone. ÐÐ°ÐœÐœÑÐ¹ ÑÐ°Ð·ÐŽÐµÐ» ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ð²ÑÐµ, ÑÑÐŸ ÐÐ°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð·ÐœÐ°ÑÑ ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ. Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÑÐ°ÐºÐ¶Ðµ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑÑÑ ÑÑÑÑÐºÑÑÑÐ° ÐŽÐžÑÐµÐºÑÐŸÑÐžÐ¹ Greenstone Ðž ÑÐŸÑÐŒÐ°Ñ Ð²ÐœÑÑÑÐµÐœÐœÐµÐ³ÐŸ Ñ
+ÑÐ°ÐœÐµÐœÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ².</Text>
+<Text id="24">ÐÑ Ð¿ÐŸÐŽÑÐ°Ð·ÑÐŒÐµÐ²Ð°ÐµÐŒ, ÑÑÐŸ ÐœÐ° Ð²Ð°ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° ÑÐžÑÑÐµÐŒÐ° Greenstone, ÑÐºÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÐœÐœÐ°Ñ Ð¿ÐŸÐŽ ÐŸÐ±ÐŸÐ»ÐŸÑÐºÑ Windows ÐžÐ»Ðž Unix. ÐÑÐ»Ðž  Ð²Ñ   ÐµÑÐµ  ÐœÐµ  ÑÑÑÐ°ÐœÐŸÐ²ÐžÐ»Ðž  ÑÐžÑÑÐµÐŒÑ, ÑÐŸ   ÑÐŽÐµÐ»Ð°Ð¹ÑÐµ  ÑÑÐŸ, Ð²ÐŸÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ð²ÑÐžÑÑ ÐºÐŸÐŒÐ¿Ð»ÐµÐºÑÐŸÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÑÐžÐž <i>ÐŠÐžÑÑÐŸÐ²Ð°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Greenstone: Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ Ð¿ÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐµ</i>. ÐÐ»Ñ ÐŸÐ±ÑÐ°ÑÐµÐœÐžÑ Ðº ÐŸÑÐœÐŸÐ²ÐœÐŸÐŒÑ ÐºÐ°ÑÐ°Ð»ÐŸÐ³Ñ Greenstone Ð¿ÐŸÐ²ÑÐµÐŒÐµÑÑÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐžÐŒÑ <i>GSDLHOME</i>, ÐºÐŸÑÐŸÑÐŸÐµ ÐŽÐ»Ñ ÑÐžÑÑÐµÐŒÑ Windows Ð²ÑÐ³Ð»ÑÐŽÐžÑ ÐºÐ°Ðº <i>%GSDLHOME%</i>, Ð° ÐŽÐ»Ñ Unix - <i>$GSDLHOME</i>. ÐÑ ÑÐŸÐ·ÐŽÐ°ÐµÑÐµ ÑÑÐŸÑ ÐºÐ°ÑÐ°Ð»ÐŸÐ³ Ð² Ð¿ÑÐŸÑÐµÑÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Greenstone ÐœÐ° Ð²Ð°Ñ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑ.</Text>
+<Section id="building_collections_from_the_command_line">
+<Title>
+<Text id="25">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐžÐ· ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐž</Text>
+</Title>
+<Content>
+<Text id="26">ÐÐ°ÑÐ°Ð² ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐžÐ· ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐž, Ð²Ñ Ð¿ÑÐŸÐ¹ÐŽÐµÑÐµ Ð¿ÐŸ Ð²ÑÐµÐ¹ ÐŸÐ¿ÐµÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÐµÐ¿ÐŸÑÐºÐµ, ÑÑÐŸ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÐžÑ Ð²Ð°ÐŒ Ð»ÑÑÑÐµ Ð¿ÐŸÐœÑÑÑ ÑÑÐŸÑ Ð¿ÑÐŸÑÐµÑÑ. Ð Ð°Ð·ÑÐŒÐµÐµÑÑÑ, ÐŽÐ»Ñ ÐœÐ°ÐžÐ±ÐŸÐ»ÑÑÐµÐ³ÐŸ ÑÐžÑÐ»Ð° ÑÑ
+ÐŸÐ¶ÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ð²Ñ Ð±ÑÐŽÐµÑÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑÐŸÐŒ. ÐÐ»Ñ Ð¿ÑÐžÐŒÐµÑÐ° ÐŒÑ Ð²ÐŸÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹, ÐœÐ°Ñ
+ÐŸÐŽÑÑÐµÐ¹ÑÑ ÐœÐ° ÑÑÑÐ°ÐœÐŸÐ²ÐŸÑÐœÐŸÐŒ CD-ROM Ðž ÑÐŸÑÑÐŸÑÑÐµÐ¹ ÐžÐ· ÐŽÐŸÐŒÐ°ÑÐœÐžÑ
+ WWW-ÑÑÑÐ°ÐœÐžÑ ÐŒÐœÐŸÐ¶ÐµÑÑÐ²Ð° Ð»ÐžÑ, ÑÐ°Ð±ÐŸÑÐ°Ð²ÑÐžÑ
+ ÐœÐ°ÐŽ Ð¿ÑÐŸÐµÐºÑÐŸÐŒ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐÐŸÐ²ÐŸÐ·ÐµÐ»Ð°ÐœÐŽÑÐºÐŸÐ¹ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Ðž ÑÐžÑÑÐµÐŒÐŸÐ¹ Greenstone.</Text>
+<Text id="27">ÐÑÐŽÐµÐ»ÑÐœÑÐµ Ð¿ÐŸÐŽÑÐ°Ð·ÐŽÐµÐ»Ñ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐž ÐœÐµ ÐŸÑÐ»ÐžÑÐ°ÑÑÑÑ ÐŽÑÑÐ³ ÐŸÑ ÐŽÑÑÐ³Ð°, ÐŸÐŽÐœÐ°ÐºÐŸ ÐŸÐœÐž Ð±ÑÐ»Ðž ÑÐŸÐ·ÐŽÐ°ÐœÑ ÐŽÐ»Ñ ÑÐ°Ð±ÐŸÑÑ Ñ Greenstone Ð² ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÐŸÐ¿ÐµÑÐ°ÑÐžÐŸÐœÐœÑÑ
+ ÑÑÐµÐŽÐ°Ñ
+, ÑÐ°ÐºÐžÑ
+ ÐºÐ°Ðº Windows Ðž Unix. ÐÐ°ÐŒ ÐŸÑÑÐ°ÐµÑÑÑ ÑÐŸÐ»ÑÐºÐŸ Ð²ÑÐ±ÑÐ°ÑÑ. ÐœÐ° Ð±Ð°Ð·Ðµ ÐŸÐ¿ÐµÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÑ Ð²Ð°ÑÐµÐ³ÐŸ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐ°. ÐÑÐž Ð±ÐµÐ³Ð»ÐŸÐŒ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµ ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÐŸÐ¿ÐµÑÐ°ÑÐžÐž ÐŒÐŸÐ³ÑÑ Ð²Ð°ÐŒ Ð¿ÐŸÐºÐ°Ð·Ð°ÑÑÑÑ ÐœÐµÐ¿ÐŸÐœÑÑÐœÑÐŒÐž Ðž ÑÐ°ÐžÐœÑÑÐ²ÐµÐœÐœÑÐŒÐž, ÐŸÐŽÐœÐ°ÐºÐŸ Ð²ÑÐ¿ÐŸÐ»ÐœÐžÑÐµ ÐžÑ
+, Ð±Ð»ÐžÐ·ÐºÐŸ Ð¿ÑÐžÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑÑ Ðº ÐžÐœÑÑÑÑÐºÑÐžÑÐŒ - Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÑÑÐžÑ
+ ÐŸÐ¿ÐµÑÐ°ÑÐžÐ¹ Ð±ÑÐŽÐµÑ ÐŽÐ°ÐœÐŸ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ Ð¿ÐŸÐ·Ð¶Ðµ. Ð ÐºÐŸÐœÑÐµ Ð¿ÐŸÐŽÑÐ°Ð·ÐŽÐµÐ»Ð° ÐŽÐ°ÐœÐŸ ÐºÑÐ°ÑÐºÐŸÐµ ÑÐµÐ·ÑÐŒÐµ ÐŸ ÑÐ°Ð·Ð»ÐžÑÐžÑÑ
+ ÐŒÐµÐ¶ÐŽÑ Ð¿ÑÐŸÑÐµÑÑÐ°ÐŒÐž ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐœÐ° Ð±Ð°Ð·Ðµ Widows Ðž Unix.</Text>
+<Subsection id="collection_building_under_windows">
+<Title>
+<Text id="28">Ð€ÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ð¿ÐŸÐŽ Windows</Text>
+</Title>
+<Content>
+<Text id="29">ÐÑÐž ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Greenstone Ð² ÑÑÐµÐŽÐµ Windows ÑÐµÑÐµÐ· ÐºÐŸÐŒÐ°ÐœÐŽÐœÑÑ ÑÑÑÐŸÐºÑ ÐžÐ·ÐœÐ°ÑÐ°Ð»ÑÐœÐŸ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð·Ð°Ð¿ÑÑÑÐžÑÑ "command prompt" - Ð¿ÑÐžÐ³Ð»Ð°ÑÐµÐœÐžÐµ ÐŽÐ»Ñ Ð²Ð²ÐŸÐŽÐ° Ð²Ð°ÑÐžÑ
+ ÐºÐŸÐŒÐ°ÐœÐŽ. ÐÐŸÐ¿ÑÐŸÐ±ÑÐ¹ÑÐµ Ð¿ÐŸÑÐŒÐŸÑÑÐµÑÑ ÑÐµÑÐµÐ· ÐŸÑÐœÐŸÐ²ÐœÐŸÐµ ÐŒÐµÐœÑ Start -^Programs, ÐœÐ°Ð¹ÐŽÐžÑÐµ MS-DOS Prompt, DOS Prompt, ÐžÐ»Ðž Command Prompt. ÐÑÐ»Ðž Ð²Ñ ÐœÐµ ÐœÐ°ÑÐ»Ðž ÐœÐžÑÐµÐ³ÐŸ ÐžÐ· ÐŸÐ¿ÐžÑÐ°ÐœÐœÐŸÐ³ÐŸ Ð²ÑÑÐµ, Ð·Ð°Ð¿ÑÑÑÐžÑÐµ Start ~$Run Ðž Ð² ÐŽÐžÐ°Ð»ÐŸÐ³ÐŸÐ²ÐŸÐŒ ÐŸÐºÐœÐµ ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ command (or cmd). ÐÑÐ»Ðž Ð·Ð°Ð¿ÑÑÐº ÐºÐŸÐŒÐ°ÐœÐŽÑ ÐŸÐºÐŸÐœÑÐžÐ»ÑÑ Ð±ÐµÐ·ÑÑÐ¿ÐµÑÐœÐŸ, ÑÐŸ ÐŸÐ±ÑÐ°ÑÐžÑÐµÑÑ Ðº ÑÐ²ÐŸÐµÐŒÑ ÑÐžÑÑÐµÐŒÐœÐŸÐŒÑ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐ°ÑÐŸÑÑ.</Text>
+<Text id="30">ÐÐœÐµÑÐžÑÐµ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð² ÐºÐ°ÑÐ°Ð»ÐŸÐ³, Ð² ÐºÐŸÑÐŸÑÑÐ¹ Ð±ÑÐ»Ð° ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° ÑÐžÑÑÐµÐŒÐ° Greenstone. ÐÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ Greenstone ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑÑÑ Ð² ÐºÐ°ÑÐ°Ð»ÐŸÐ³, Ð² ÐºÐŸÑÐŸÑÑÐ¹ ÐŒÐŸÐ¶ÐœÐŸ Ð¿ÐŸÐ¿Ð°ÑÑÑ ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð²</Text>
+<CodeLine>cd "C:\Program Files\gsdl "</CodeLine>
+<Text id="31">(ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐºÐ°Ð²ÑÑÐºÐž ÐžÐ·-Ð·Ð° Ð¿ÑÐŸÐ±ÐµÐ»Ð° Ð² ÐžÐŒÐµÐœÐž ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž Program Files). ÐÐ°Ð»ÐµÐµ, Ð² ÑÐ»ÐµÐŽÑÑÑÐµÐŒ ÐŸÐºÐœÐµ ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ</Text>
+<CodeLine>setup.bat</CodeLine>
+<Text id="32">Ð­ÑÐŸÑ ÑÐ°Ð¹Ð» (ÐºÐŸÑÐŸÑÑÐ¹ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ) ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÑÐžÑÑÐµÐŒÐµ, Ð³ÐŽÐµ ÐžÑÐºÐ°ÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Greenstone<FootnoteRef id="1"/>. ÐÑÐ»Ðž Ð¿ÑÐž ÑÐ°Ð±ÐŸÑÐµ Ð² ÐžÐœÑÐµÑÐ°ÐºÑÐžÐ²ÐœÐŸÐŒ ÑÐµÐ°ÐœÑÐµ DOS prompt Ð²Ñ Ð·Ð°Ñ
+ÐŸÑÐžÑÐµ Ð²ÐµÑÐœÑÑÑÑÑ ÐœÐ° Ð²ÐµÑÑ
+ÐœÐžÐ¹ ÑÑÐŸÐ²ÐµÐœÑ ÐºÐ°ÑÐ°Ð»ÐŸÐ³Ð° Greenstone Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐŽÐµÐ»Ð°ÑÑ ÑÑÐŸ, ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð² cd "%GSDLHOME%" (ÐœÐµÐ¿ÑÐµÐŒÐµÐœÐœÐŸ Ð² ÐºÐ°Ð²ÑÑÐºÐ°Ñ
+). ÐÑÐ»Ðž Ð²Ñ Ð·Ð°ÐºÐŸÐœÑÐžÐ»Ðž ÑÐ°Ð±ÐŸÑÑ Ð² ÐŸÐºÐœÐµ DOS, Ð° Ð¿ÐŸÑÐŸÐŒ Ð·Ð°Ð¿ÑÑÑÐžÐ»Ðž ÐœÐŸÐ²ÑÑ ÑÐµÑÑÐžÑ, ÑÐŸ Ð²Ñ ÐŽÐŸÐ»Ð¶ÐœÑ Ð·Ð°Ð¿ÑÑÑÐžÑÑ Ð·Ð°ÐœÐŸÐ²ÐŸ setup.bat.</Text>
+<Text id="33">Ð¢ÐµÐ¿ÐµÑÑ Ð²Ñ ÐžÐŒÐµÐµÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÑÑ ÐžÐ»Ðž Ð¿ÐµÑÐµÑÐŸÑÐŒÐžÑÐŸÐ²ÑÐ²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð¡ÐœÐ°ÑÐ°Ð»Ð° ÐŒÑ ÑÐ°ÑÑÐŒÐŸÑÑÐžÐŒ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ mkcol.pl, ÐœÐ°Ð¿ÐžÑÐ°ÐœÐœÑÑ ÐœÐ° Perl, ÐžÐŒÑ ÐºÐŸÑÐŸÑÐŸÐ¹ ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ "make a collection" (ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž). ÐÐµÑÐ²ÑÐ¹ Ð·Ð°Ð¿ÑÑÐº ÑÑÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐŒÐŸÐ¶ÐœÐŸ ÐŸÑÑÑÐµÑÑÐ²ÐžÑÑ, ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð² perl -S mkcol.pl, Ð¿ÑÐž ÑÑÐŸÐŒ ÐœÐ° ÑÐºÑÐ°ÐœÐµ Ð¿ÐŸÑÐ²ÐžÑÑÑ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ Ðž ÑÐ¿ÐžÑÐŸÐº Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ². ÐÑÐ»Ðž ÐŸÐºÑÑÐ¶ÐµÐœÐžÐµ Ð²Ð°ÑÐµÐ¹ ÐŸÐ¿ÐµÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÑ Windows ÐœÐ°ÑÑÑÐŸÐµÐœÐŸ ÐœÐ° ÑÐ°Ð±ÐŸÑÑ Ñ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑÐŒÐž Perl, ÑÐ°Ð¹Ð»Ð°ÐŒÐž Ñ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµÐŒ .pi, ÑÐŸ ÑÑÐ° Ð¿ÑÐŸÑÐµÐŽÑÑÐ° ÐœÐµ Ð·Ð°Ð¹ÐŒÐµÑ ÐŒÐœÐŸÐ³ÐŸ Ð²ÑÐµÐŒÐµÐœÐž. ÐÐ°Ðº Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÐžÐŽÐµÑÑ Ð² Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÐµÐœÐœÐŸÐŒ Ð¿ÑÐžÐŒÐµÑÐµ, ÐµÐŽÐžÐœÑÑÐ²ÐµÐœÐœÑÐ¹ ÐŸÐ±ÑÐ·Ð°ÑÐµÐ»ÑÐœÑÐ¹ Ð°ÑÐ³ÑÐŒÐµÐœÑ - ÑÑÐŸ creator (ÑÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ), ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»Ð·ÑÐµÑÑÑ ÐŽÐ»Ñ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ Ð»ÐžÑÐ°, ÑÐŸÑÐŒÐžÑÑÑÑÐµÐ³ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ.</Text>
+<Text id="34">Ð¢ÐµÐ¿ÐµÑÑ ÐŒÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒ ÑÑÑ ÐºÐŸÐŒÐ°ÐœÐŽÑ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐœÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐŸÑÑÐŸÑÑÐµÐ¹ ÐžÐ· ÐŽÐŸÐŒÐ°ÑÐœÐžÑ
+ WWW-ÑÑÑÐ°ÐœÐžÑ ÑÑÐ°ÑÑÐœÐžÐºÐŸÐ² Ð¿ÑÐŸÐµÐºÑÐ° ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐŠÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone. ÐÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ Ð¿ÑÐžÑÐ²ÐŸÐžÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐžÐŒÑ, Ñ ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð»</Text>
+<CodeLine>perl âS mkcol.pl âcreator me@cs.waikato.ac.nz dlpeople</CodeLine>
+<Text id="35">(ÐžÐ»Ðž mkcol.pl âcreator me@cs. waikato. ac. nz dlpeople ÐµÑÐ»Ðž Perl ÑÐ²ÑÐ·Ð°Ðœ Ñ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµÐŒ ÑÐ°Ð¹Ð»Ð° .ÑÐ). ÐÐŸÐ¶Ð°Ð»ÑÐ¹ÑÑÐ°, Ð·Ð°ÐŒÐµÐœÐžÑÐµ ÐŒÐŸÐ¹ email Ð°ÐŽÑÐµÑ ÐœÐ° ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÑÐ¹!</Text>
+<Text id="36">ÐÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° Ð²ÐœÐŸÐ²Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² Ð¿ÐµÑÐµÐ¹ÐŽÐµÐŒ Ð² ÑÐŸÐ»ÑÐºÐŸ-ÑÑÐŸ ÑÐŸÐ·ÐŽÐ°ÐœÐœÑÐ¹ ÐºÐ°ÑÐ°Ð»ÐŸÐ³ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ»Ñ ÑÑÐŸÑ Ð¿ÐµÑÐ°ÑÐ°ÐµÐŒ:</Text>
+<CodeLine>cd "%GSDLHOME%\collect\dlpeople "</CodeLine>
+<Figure id="collection_configuration_file_created_by_mkcol">
+<Title>
+<Text id="37">Collection configuration file created by <i>mkcol.pl</i></Text>
+</Title>
+<CodeLine>creatorÂ Â Â Â Â Â Â Â Â Â Â Â Â me@cs.waikato.ac.nz</CodeLine>
+<CodeLine>maintainerÂ Â Â Â Â Â Â Â Â Â me@cs.waikato.ac.nz</CodeLine>
+<CodeLine>publicÂ Â Â Â Â Â Â Â Â Â Â Â Â Â true</CodeLine>
+<CodeLine>betaÂ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â true</CodeLine>
+<CodeLine>indexesÂ Â Â Â Â Â Â Â Â Â Â Â Â document:text</CodeLine>
+<CodeLine>defaultindexÂ Â Â Â Â Â Â Â document:text</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â ZIPPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â GAPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â TEXTPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â HTMLPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â EMAILPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â ArcPlug</CodeLine>
+<CodeLine>pluginÂ Â Â Â Â Â Â Â Â Â Â Â Â Â RecPlug</CodeLine>
+<CodeLine>classifyÂ Â Â Â Â Â Â Â Â Â Â Â AZList -metadata "Title"</CodeLine>
+<CodeLine>collectionmetaÂ collectionnameÂ Â Â Â "dlpeople"</CodeLine>
+<CodeLine>collectionmetaÂ iconcollectionÂ Â Â Â ""</CodeLine>
+<CodeLine>collectionmetaÂ collectionextraÂ Â Â ""</CodeLine>
+<CodeLine>collectionmetaÂ .document:textÂ Â Â Â "documents "</CodeLine>
+</Figure>
+<Text id="38">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž, ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð²   dir.   Ð ÐœÐµÐ¹ ÐŽÐŸÐ»Ð¶ÐœÐŸ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑÑ 7 Ð¿ÐŸÐŽÐŽÐžÑÐµÐºÑÐŸÑÐžÐ¹: archives, building, etc, images, import, index Ðž perllib.</Text>
+<Text id="39">Ð¢ÐµÐ¿ÐµÑÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð·Ð°Ð¿ÐŸÐ»ÐœÐžÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒÐž. ÐÑÑÐŸÑÐœÐžÐº ÐŒÐ°ÑÐµÑÐžÐ°Ð»ÐŸÐ² ÐŽÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž dlpeople ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÐœÐ° ÑÑÑÐ°ÐœÐŸÐ²ÐŸÑÐœÐŸÐŒ CD-ROM Greenstone Ð² ÐºÐ°ÑÐ°Ð»ÐŸÐ³Ðµ collect\dlpeople. Ð¡ÐœÐ°ÑÐ°Ð»Ð° Ð²ÑÑÐ°Ð²ÑÑÐµ CD-ROM Ð² ÑÐžÑÐ°ÑÑÐµÐµ ÑÑÑÑÐŸÐ¹ÑÑÐ²ÐŸ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, D:\). ÐÐ°Ð»ÐµÐµ ÑÐºÐŸÐ¿ÐžÑÑÐ¹ÑÐµ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ ÐºÐ°ÑÐ°Ð»ÐŸÐ³Ð°D:\collect\dlpeople Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ import ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž dlpeople. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐŽÐµÐ»Ð°ÑÑ ÑÑÐŸ Ð² ÑÐ»ÐµÐŽÑÑÑÐµÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ:</Text>
+<Indented>
+<Text id="40">Ð²ÑÐŽÐµÐ»ÐžÑÐµ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ ÐºÐ°ÑÐ°Ð»ÐŸÐ³Ð° dlpeople Ðž Ð¿ÐµÑÐµÐŒÐµÑÑÐžÑÐµ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ import ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž dlpeople.</Text>
+</Indented>
+<Text id="41">Ð ÐºÐ°ÑÐµÑÑÐ²Ðµ Ð°Ð»ÑÑÐµÑÐœÐ°ÑÐžÐ²Ñ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°ÑÑ ÑÐ»ÐµÐŽÑÑÑÑÑ ÐºÐŸÐŒÐ°ÐœÐŽÑ:</Text>
+<CodeLine>xcopy /s d:\collect\dlpeople\* import</CodeLine>
+<Text id="42">Ð ÐºÐ°ÑÐ°Ð»ÐŸÐ³Ðµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž etc ÑÑÑÐµÑÑÐ²ÑÐµÑ ÑÐ°Ð¹Ð» Ñ ÐžÐŒÐµÐœÐµÐŒ collect, cfg. ÐÑÐºÑÐŸÐ¹ÑÐµ ÐµÐ³ÐŸ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Ð»ÑÐ±ÐŸÐ¹ ÑÐµÐºÑÑÐŸÐ²ÑÐ¹ ÑÐµÐŽÐ°ÐºÑÐŸÑ, Ð»ÐžÐ±ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÑÐµÐŽÐ°ÐºÑÐŸÑ, ÐœÐ°ÑÑÑÐŸÐµÐœÐœÑÐ¹ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ. Ð ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐµ Ð²Ñ ÑÐ²ÐžÐŽÐžÑÐµ ÐŸÐºÐœÐŸ, ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ Ð²ÑÐ³Ð»ÑÐŽÐžÑ ÑÐ°Ðº, ÐºÐ°Ðº Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐŸ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="collection_configuration_file_created_by_mkcol"/>, Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°Ñ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ ÑÐ°Ð¹Ð»Ð° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐŸÐ·ÐŽÐ°ÐœÐœÐŸÐ³ÐŸ Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ ÐºÐŸÐŒÐ°ÐœÐŽÑ perl-S mkcol.pl -creator me@cs.waikato.ac.nz dlpeople.</Text>
+<Text id="43">Ð¢ÐµÐ¿ÐµÑÑ Ð²Ñ Ð³ÐŸÑÐŸÐ²Ñ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. Ð­ÑÐŸ Ð¿ÑÐŸÑÐµÑÑ Ð¿ÐµÑÐµÐœÐŸÑÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð² ÑÐžÑÑÐµÐŒÑ Greenstone, ÑÑÐ°ÐœÐŽÐ°ÑÑÐžÐ·Ð°ÑÐžÐž ÑÐŸÑÐŒÐ°ÑÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², Ð¿ÑÑÐž ÑÐ¿ÐµÑÐžÑÐžÐºÐ°ÑÐžÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðž ÑÑÑÑÐºÑÑÑÑ ÑÐ°Ð¹Ð»Ð°, Ð² ÐºÐŸÑÐŸÑÐŸÐŒ Ð±ÑÐŽÑÑ Ñ
+ÑÐ°ÐœÐžÑÑÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ. ÐÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ perl -Simport.pl Ðž Ð² ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐµ Ð²Ñ Ð¿ÐŸÐ»ÑÑÐžÑÐµ ÑÐ¿ÐžÑÐŸÐº ÐŸÐ¿ÑÐžÐ¹ ÐŽÐ»Ñ ÐŸÐ¿ÐµÑÐ°ÑÐžÐž ÐžÐŒÐ¿ÐŸÑÑÐ°. ÐÐ»Ñ ÑÐ¿ÑÐŸÑÐµÐœÐžÑ Ð¿ÑÐŸÑÐµÑÑÐ° Ð²ÐŸÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµÑÑ Ð±Ð°Ð·ÐŸÐ²ÐŸÐ¹ ÐºÐŸÐŒÐ°ÐœÐŽÐŸÐ¹:</Text>
+<CodeLine>perl âS import.pl -removeold dlpeople</CodeLine>
+<Text id="44">ÐÐµ Ð±ÐµÑÐ¿ÐŸÐºÐŸÐ¹ÑÐµÑÑ Ð¿ÐŸ Ð¿ÐŸÐ²ÐŸÐŽÑ Ð±ÑÑÑÑÐŸ Ð±ÐµÐ³ÑÑÐµÐ³ÐŸ Ð¿ÐŸ ÑÐºÑÐ°ÐœÑ ÑÐµÐºÑÑÐ° - ÑÑÐŸ ÐŸÑÑÐµÑ ÐŸ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐž Ð¿ÑÐŸÑÐµÐŽÑÑÑ ÐžÐŒÐ¿ÐŸÑÑÐ°. Ð ÑÐ²ÐµÐŽÐµÐœÐžÑ, Ð¿ÑÐŸÑÐµÑÑ ÐžÐŒÐ¿ÐŸÑÑÐ° ÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð·Ð°ÐœÐžÐŒÐ°ÐµÑ ÐŸÐºÐŸÐ»ÐŸ 5 ÐŒÐžÐœÑÑ ÐœÐ° 1 ÐÐ¢Ñ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ Ðž ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐŽÐŸÐ»ÑÑÐµ ÐœÐ° Ð±ÐŸÐ»ÐµÐµ ÐŒÐµÐŽÐ»ÐµÐœÐœÑÑ
+ ÐŒÐ°ÑÐžÐœÐ°Ñ
+. ÐÐ±ÑÐ°ÑÐžÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ ÐœÐ° ÑÐŸ, ÑÑÐŸ Ð²Ñ ÐœÐµ ÐŽÐŸÐ»Ð¶ÐœÑ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑÑ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÑÑ
+ collect ÐžÐ»Ðž dlpeople Ð¿ÑÐž Ð·Ð°Ð¿ÑÑÐºÐµ ÑÑÐŸÐ¹ ÐºÐŸÐŒÐ°ÐœÐŽÑ; T.K.GSDLHOME ÑÐ¶Ðµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÐ» ÐŽÐ»Ñ ÑÐ°Ð±ÐŸÑÑ ÑÐžÑÑÐµÐŒÑ Greenstone ÐŒÐµÑÑÐŸÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÐµ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ².</Text>
+<Text id="45">Ð¢ÐµÐ¿ÐµÑÑ ÐŽÐ°Ð²Ð°Ð¹ÑÐµ Ð²ÐœÐµÑÐµÐŒ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð² ÑÐ°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŽÐ»Ñ ÐŒÐŸÐŽÐžÑÐžÐºÐ°ÑÐžÐž ÐµÐ³ÐŸ Ð²ÐžÐŽÐ°. Ð¡ÐœÐ°ÑÐ°Ð»Ð° Ð¿ÑÐžÑÐ²ÐŸÐžÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐžÐŒÑ. ÐÐœÐŸ Ð±ÑÐŽÐµÑ Ð²ÐŸÑÐ¿ÑÐžÐœÑÑÐŸ Ð²ÐµÐ±-Ð±ÑÐŸÑÐ·ÐµÑÐŸÐŒ, ÐºÐ°Ðº Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº ÐŽÐ»Ñ ÑÐžÑÑÐ»ÑÐœÐŸÐ³ÐŸ Ð»ÐžÑÑÐ° WWW-ÑÑÑÐ°ÐœÐžÑÑ, Ðž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐžÐºÐŸÐœÐºÐž Ð¿ÑÐž ÐŸÑÑÑÑÑÑÐ²ÐžÐž ÑÐžÑÑÐœÐºÐ°. ÐÐ·ÐŒÐµÐœÐžÐŒ ÑÑÑÐŸÐºÑ collectionmeta collectionname "dlpeople" ÐœÐ° ÑÑÑÐŸÐºÑ Ð²ÐžÐŽÐ° collectionmeta collectionname "The People of the NZDL project".</Text>
+<Text id="46">ÐÐŸÐ±Ð°Ð²ÐžÐŒ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐµÐ¶ÐŽÑ ÐºÐ°Ð²ÑÑÐºÐ°ÐŒÐž: <i>collectionmeta collectionextra ""</i>. ÐÐœÐŸ Ð±ÑÐŽÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐŸ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐŒÐ°ÑÐµÑÐžÐ°Ð»Ð° ÐŽÐ»Ñ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐž ÑÐ°Ð·ÐŽÐµÐ»Ð° "About" (ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž) ÐœÐ° ÐŽÐŸÐŒÐ°ÑÐœÐµÐ¹ WWW-ÑÑÑÐ°ÐœÐžÑÐµ. Ð¯ ÐŽÐŸÐ±Ð°Ð²ÐžÐ» "This collection is made up of the homepages of some of the people who have worked on the NZDL project." ÐÐ°Ð¶ÐœÐŸ Ð²Ð²ÐŸÐŽÐžÑÑ ÑÑÐŸ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÐŸÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐŸÐ¹ - ÐœÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐŽÐ»Ñ ÐŸÑÐ±ÐžÐ²ÐºÐž ÐºÐ»Ð°Ð²ÐžÑÑ Enter/ÐÐ²ÐŸÐŽ. ÐÑÐ»Ðž Ð²Ñ Ñ
+ÐŸÑÐžÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð² Ð²Ð°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐœÐŸÐ³ÐŸÑÐ·ÑÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ, ÑÐŸ ÑÑÑÐµÑÑÐ²ÑÐµÑ ÑÐ¿ÐŸÑÐŸÐ± Ð²ÑÐ²ÐŸÐŽÐ° ÐŽÐ°ÐœÐœÐŸÐ³ÐŸ ÑÐµÐºÑÑÐ° Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐž Ñ Ð²ÑÐ±ÑÐ°ÐœÐœÑÐŒ ÑÐ·ÑÐºÐŸÐŒ. Ð­ÑÐŸ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ Ð±ÑÐŽÐµÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐŸ ÐŽÐ°Ð»ÐµÐµ Ð² ÑÐ°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Section" ref="configuration_file"/>.</Text>
+<Text id="47">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ, ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐŽÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÑ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐžÐºÐŸÐœÐŸÐº ÐœÐ° WWW-ÑÑÑÐ°ÐœÐžÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž; ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ, ÑÐŸÐ·ÐŽÐ°ÐœÐœÐŸÐµ ÐŒÐœÐŸÑ, Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÐžÐŽÐµÑÑ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="collection_icon"/>. Ð£ÐºÐ°Ð¶ÐžÑÐµ Ð¿ÑÑÑ ÐœÐ°Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÑ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ Ð² ÐºÐ°Ð²ÑÑÐºÐ°Ñ
+ Ð² ÑÑÑÐŸÐºÐµ collectionmeta iconcollection "" ÑÐ°Ð¹Ð»Ð° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž. ÐÐ»Ñ ÐºÑÐ°ÑÐºÐŸÑÑÐž Ðž ÐŒÐŸÐ±ÐžÐ»ÑÐœÐŸÑÑÐž _httpprefix_ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ðœ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÑÑÐ°ÑÑÐŸÐ²ÐŸÐ³ÐŸ URL ÑÐºÐ°Ð·ÑÐ²Ð°ÑÑÐµÐ³ÐŸ ÐœÐ° ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ, ÐœÐ°Ñ
+ÐŸÐŽÑÑÐµÐµÑÑ Ð² ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ¹ ÐŸÐ±Ð»Ð°ÑÑÐž Greenstone. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð²Ð²ÐµÑÑÐž: _httppreflx_/collect/dlpeople/images/icon.gif ÐµÑÐ»Ðž Ð²Ñ Ð¿ÐŸÐŒÐµÑÑÐžÐ»Ðž Ð¿ÐŸÐŽÑ
+ÐŸÐŽÑÑÐµÐµ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÑÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (Ð² ÐœÐ°ÑÐµÐŒ Ð¿ÑÐžÐŒÐµÑÐµ ÑÑÐŸ: collect\dlpeople\images ).</Text>
+<Text id="48">Ð¡ÐŸÑ
+ÑÐ°ÐœÐžÑÐµ ÑÐ°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð·Ð°ÐºÑÐŸÐ¹ÑÐµ ÐµÐ³ÐŸ - ÐŸÐœ Ð²Ð°ÐŒ Ð±ÐŸÐ»ÑÑÐµ ÐœÐµ Ð¿ÐŸÐœÐ°ÐŽÐŸÐ±ÐžÑÑÑ ÐœÐ° ÐŽÐ°ÐœÐœÐŸÐŒ ÑÑÐ°Ð¿Ðµ ÐŸÐ±ÑÑÐµÐœÐžÑ.</Text>
+<Text id="49">Ð¡Ð»ÐµÐŽÑÑÑÐ°Ñ ÑÐ°Ð·Ð° - "Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÐµ" ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð² ÐºÐŸÑÐŸÑÐŸÐ¹ Ð±ÑÐŽÑÑ ÑÐŸÐ·ÐŽÐ°ÐœÑ Ð²ÑÐµ ÐžÐœÐŽÐµÐºÑÑ Ðž ÑÐ°Ð¹Ð»Ñ, ÐŸÑÐ²ÐµÑÐ°ÑÑÐžÐµ Ð·Ð° ÑÐ°Ð±ÐŸÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ Ð² ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐµ perl âS buildcol.pl Ðž Ð¿ÐŸÐ»ÑÑÐžÑÐµ ÑÐ¿ÐžÑÐŸÐº ÐŸÐ¿ÑÐžÐ¹ ÐŽÐ»Ñ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐŸÐŽÑÐŸÐ±ÐœÐŸÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÑÑÐžÑ
+ ÐŸÐ¿ÑÐžÐ¹ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐŸ Ð² Ð Ð°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Section" ref="import_and_build_processes"/>. ÐÐŸÐºÐ° Ð¶Ðµ Ð¿ÑÐžÐŽÐµÑÐ¶ÐžÐ²Ð°Ð¹ÑÐµÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ "Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ", ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð²:</Text>
+<CodeLine>perl âS buildcol.pl dlpeople</CodeLine>
+<Text id="50">Ð ÑÐœÐŸÐ²Ð° ÐœÐµ Ð±ÐµÑÐ¿ÐŸÐºÐŸÐ¹ÑÐµÑÑ ÐŸ Ð±ÑÑÑÑÐŸ Ð±ÐµÐ³ÑÑÐµÐŒ Ð¿ÐŸ ÑÐºÑÐ°ÐœÑ ÑÐµÐºÑÑÐµ - ÑÑÐŸ ÐŸÑÑÐµÑ ÐŸ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐž ÐºÐŸÐŒÐ°ÐœÐŽÑ.</Text>
+<Text id="51">Ð¢ÐµÐ¿ÐµÑÑ "ÐŸÐ¶ÐžÐ²ÐžÐŒ" ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ:</Text>
+<Text id="52">Ð²ÑÐŽÐµÐ»ÐžÑÐµ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ ÐºÐ°ÑÐ°Ð»ÐŸÐ³Ð° building ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž dlpeople Ðž Ð¿ÐµÑÐµÐœÐµÑÐžÑÐµ ÐµÐ³ÐŸ Ð² ÐºÐ°ÑÐ°Ð»ÐŸÐ³ index.</Text>
+<Text id="53">Ð¢Ð°Ðº Ð¶Ðµ Ð²Ð² ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÐŽÐµÐ»Ð°ÑÑ ÑÑÑ ÐŸÐ¿ÐµÑÐ°ÑÐžÑ, ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð² ÐºÐŸÐŒÐ°ÐœÐŽÑ:</Text>
+<CodeLine>rd /s index                 # on Windows NT/2000</CodeLine>
+<CodeLine>deltree /Y index       # on Windows 95/98</CodeLine>
+<Text id="54">Ðž ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐžÐŒÑ ÐºÐ°ÑÐ°Ð»ÐŸÐ³Ð° building ÐœÐ° index ÐºÐŸÐŒÐ°ÐœÐŽÐŸÐ¹</Text>
+<CodeLine>ren building index</CodeLine>
+<Text id="55">Ð Ð·Ð°ÐºÐ»ÑÑÐµÐœÐžÐµ ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ:</Text>
+<CodeLine>mkdir building</CodeLine>
+<Text id="56">Ð¿ÐŸÐŽÐ³ÐŸÑÐŸÐ²ÐžÐ² ÑÐžÑÑÐµÐŒÑ ÐŽÐ»Ñ Ð±ÑÐŽÑÑÐžÑ
+ Ð¿ÐµÑÐµÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÐ¹. ÐÐ°Ð¶ÐœÐŸ, ÑÑÐŸÐ±Ñ Ð²ÑÐµ ÑÑÐž ÐºÐŸÐŒÐ°ÐœÐŽÑ Ð±ÑÐ»Ðž Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÑ ÐžÐ· ÑÑÐµÐ±ÑÐµÐŒÐŸÐ¹ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž (Ð² ÐŸÑÐ»ÐžÑÐžÐµ ÐŸÑ ÐºÐŸÐŒÐ°ÐœÐŽ Greenstone mkcol.pl, import.pl and buildcol.pl); ÐµÑÐ»Ðž ÑÐµÐºÑÑÐ°Ñ ÑÐ°Ð±ÐŸÑÐ°Ñ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ ÐœÐµ ÑÐ²Ð»ÑÐµÑÑÑ dlpeople, ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ: cd "%GSDLHOME%\collect\dlpeople" ÐŽÐŸ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº Ð²Ñ Ð·Ð°Ð¿ÑÑÑÐžÑÐµ ÐœÐ° ÐžÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ ÐºÐŸÐŒÐ°ÐœÐŽÑ rd, ren Ðž mkdir.</Text>
+<Text id="57">ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ ÑÐŒÐµÑÑ ÐŸÐ±ÑÐ°ÑÐ°ÑÑÑÑ Ðº Ð²ÐœÐŸÐ²Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ñ Ð²Ð°ÑÐµÐ¹ ÐŽÐŸÐŒÐ°ÑÐœÐµÐ¹ ÑÑÑÐ°ÐœÐžÑÑ Greenstone. ÐÑÐ»Ðž ÑÑÐ° ÑÑÑÐ°ÐœÐžÑÐ° ÐŸÑÐºÑÑÑÐ° Ð² Ð²Ð°ÑÐµÐŒ Ð±ÑÐŸÑÐ·ÐµÑÐµ, Ð²Ñ ÐŽÐŸÐ»Ð¶ÐœÑ ÐµÐµ ÐŸÐ±ÐœÐŸÐ²ÐžÑÑ ÐžÐ»Ðž Ð·Ð°ÐºÑÑÑÑ ÐŸÐºÐœÐŸ Ð±ÑÐŸÑÐ·ÐµÑÐ° Ðž Ð¿ÐµÑÐµÐ·Ð°Ð¿ÑÑÑÐžÑÑ ÐµÐ³ÐŸ (ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÐžÐ·Ð±ÐµÐ¶Ð°ÑÑ Ð¿ÑÐŸÐ±Ð»ÐµÐŒ ÐºÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ). ÐÑÐ»Ðž Ð²Ñ Ð¿ÐŸÐ»ÑÐ·ÑÐµÑÐµÑÑ "Ð»ÐŸÐºÐ°Ð»ÑÐœÐŸÐ¹ Ð²ÐµÑÑÐžÐµÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž" Greenstone, ÑÐŸ ÐŽÐŸÐ»Ð¶ÐœÑ Ð¿ÐµÑÐµÐ·Ð°Ð¿ÑÑÑÐžÑÑ Ð²ÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ. ÐÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐµÐ»ÐºÐœÐžÑÐµ ÐºÐœÐŸÐ¿ÐºÐŸÐ¹ ÐŒÑÑÐž Ð¿ÐŸ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ. ÐÐŸÐ»ÑÑÐµÐœÐœÑÐ¹ ÑÐµÐ·ÑÐ»ÑÑÐ°Ñ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐ²ÐžÐŽÐµÑÑ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="about_page_for_the_new_collection"/>.</Text>
+<Figure id="collection_icon">
+<Title>
+<Text id="58">ÐÐºÐŸÐœÐºÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<File width="156" height="120" url="images/Dev_Fig_006.png"/>
+</Figure>
+<Text id="59">Ð Ð·Ð°ÐºÐ»ÑÑÐµÐœÐžÐµ Ð¿ÑÐžÐ²ÐµÐŽÐµÐŒ ÐºÐŸÐŒÐ°ÐœÐŽÑ, ÑÐŸÐ·ÐŽÐ°ÑÑÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ:</Text>
+<CodeLine>cd "C:\Program Files\gsdl " # assuming default location</CodeLine>
+<CodeLine>setup.bat</CodeLine>
+<CodeLine>perl âS mkcol.pl âcreator me@cs.waikato.ac.nz dlpeople</CodeLine>
+<CodeLine>cd "%GSDLHOME%\collect\dlpeople "</CodeLine>
+<CodeLine>xcopy   /s   d:\collect\dlpeople\*   import # assuming D drive</CodeLine>
+<CodeLine>perl âS import.pl dlpeople</CodeLine>
+<CodeLine>perl âS buildcol.pl dlpeople</CodeLine>
+<CodeLine>rd /s index           # on Windows NT/2000</CodeLine>
+<CodeLine>deltree /Y index # on Windows 95/98</CodeLine>
+<CodeLine>ren building index</CodeLine>
+<CodeLine>mkdir building</CodeLine>
+</Content>
+</Subsection>
+<Subsection id="collection_building_under_unix">
+<Title>
+<Text id="60">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÐŸÐŽ Unix</Text>
+</Title>
+<Content>
+<Text id="61">Ð¡ÐœÐ°ÑÐ°Ð»Ð° Ð²ÐœÐŸÑÐžÐŒ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ, Ð² ÐºÐŸÑÐŸÑÑÑ Ð±ÑÐ»Ð° ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° ÑÐžÑÑÐµÐŒÐ° Greenstone. Ð Ð¿ÑÐžÐŒÐµÑÑ, ÐµÑÐ»Ðž Greenstone Ð±ÑÐ»Ð° ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° Ñ ÐžÐŒÐµÐœÐµÐŒ "Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ, ÑÐŸ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ Ð²ÐµÑÑ
+ÐœÐµÐ³ÐŸ ÑÑÐŸÐ²ÐœÑ ÐŒÐŸÐ¶ÐœÐŸ Ð¿ÐŸÐ¿Ð°ÑÑÑ, ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð²:</Text>
+<CodeLine>cd ~/gsdl</CodeLine>
+<Text id="62">ÐÐ°ÑÐµÐŒ ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°ÑÑ:</Text>
+<CodeLine>source setup.bash     # if you're running the BASH shell</CodeLine>
+<CodeLine>source setup.csh       # if you're running the C shell</CodeLine>
+<Text id="63">Ð­ÑÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ñ (ÐºÐŸÑÐŸÑÑÐµ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ) ÑÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÑÐžÑÑÐµÐŒÐµ, Ð³ÐŽÐµ ÐžÑÐºÐ°ÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Greenstone. ÐÑÐ»Ðž Ð¿ÐŸÐ·Ð¶Ðµ Ð²Ñ Ð·Ð°Ñ
+ÐŸÑÐžÑÐµ Ð²ÐµÑÐœÑÑÑÑÑ ÐœÐ° Ð²ÐµÑÑ
+ÐœÐžÐ¹ ÑÑÐŸÐ²ÐµÐœÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž GreenÂ¬stone, ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ Ð² ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐµ cd $GSDLHOME.</Text>
+<Text id="64">ÐÑÐ»Ðž Ð²Ñ ÐœÐµ ÑÐ²ÐµÑÐµÐœÑ Ð² ÑÐžÐ¿Ðµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐœÐŸÐ¹ ÐœÐ° Ð²Ð°ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ ÐŸÐ±ÐŸÐ»ÐŸÑÐºÐž, ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ Ð² ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐµ $0, Ð² ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐµ ÑÐµÐ³ÐŸ Ð²Ñ Ð¿ÐŸÐ»ÑÑÐžÑÐµ Ð¿ÐŸÐ»ÐœÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ. ÐÑÐ»Ðž Ð¿ÑÐž ÑÐ°Ð±ÐŸÑÐµ Ð²Ñ Ð¿ÐŸÐ»ÑÐ·ÑÐµÑÐµÑÑ ÐžÐœÐŸÐ¹ ÐŸÐ±ÐŸÐ»ÐŸÑÐºÐŸÐ¹, ÑÐŸ Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ Ð±ÑÐŽÐµÑ ÐŸÐ±ÑÐ°ÑÐžÑÑÑÑ Ð·Ð° ÑÐŸÐ²ÐµÑÐŸÐŒ Ðº Ð²Ð°ÑÐµÐŒÑ ÑÐžÑÑÐµÐŒÐœÐŸÐŒÑ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐ°ÑÐŸÑÑ.</Text>
+<Text id="65">Ð¢ÐµÐ¿ÐµÑÑ Ð²Ñ ÐžÐŒÐµÐµÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÑÑ ÐžÐ»Ðž Ð¿ÐµÑÐµÑÐŸÑÐŒÐžÑÐŸÐ²ÑÐ²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð¡ÐœÐ°ÑÐ°Ð»Ð° ÐŒÑ ÑÐ°ÑÑÐŒÐŸÑÑÐžÐŒ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ mkcol.pl, ÐœÐ°Ð¿ÐžÑÐ°ÐœÐœÑÑ ÐœÐ° Perl, ÐžÐŒÑ ÐºÐŸÑÐŸÑÐŸÐ¹ ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ "make a collection" (ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž). ÐÐµÑÐ²ÑÐ¹ Ð·Ð°Ð¿ÑÑÐº ÑÑÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐŒÐŸÐ¶ÐœÐŸ ÐŸÑÑÑÐµÑÑÐ²ÐžÑÑ, ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð² mkcol.pl, Ð¿ÑÐž ÑÑÐŸÐŒ ÐœÐ°  ÑÐºÑÐ°ÐœÐµ Ð¿ÐŸÑÐ²ÐžÑÑÑ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ Ðž ÑÐ¿ÐžÑÐŸÐº Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ². ÐÐ°Ðº Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÐžÐŽÐµÑÑ Ð² Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐœÐŸÐŒ Ð¿ÑÐžÐŒÐµÑÐµ, ÐµÐŽÐžÐœÑÑÐ²ÐµÐœÐœÑÐ¹ ÐŸÐ±ÑÐ·Ð°ÑÐµÐ»ÑÐœÑÐ¹ Ð°ÑÐ³ÑÐŒÐµÐœÑ - ÑÑÐŸ creator (ÑÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ), ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»Ð·ÑÑÐµÑÑÑ ÐŽÐ»Ñ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ Ð»ÐžÑÐ°, ÑÐŸÑÐŒÐžÑÑÑÑÐµÐ³ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ.</Text>
+<Figure id="about_page_for_the_new_collection">
+<Title>
+<Text id="66">Ð¡ÑÑÐ°ÐœÐžÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž "About" (ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž)</Text>
+</Title>
+<File width="389" height="409" url="images/Dev_Fig_008.png"/>
+</Figure>
+<Text id="67">Ð¢ÐµÐ¿ÐµÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒ ÐºÐŸÐŒÐ°ÐœÐŽÑ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐœÐ°ÑÐ°Ð»ÑÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² Ðž ÐŽÐžÑÐµÐºÑÐŸÑÐžÐ¹, ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÑÑ
+ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐŽÐŸÐŒÐ°ÑÐœÐµÐ¹ ÑÑÑÐ°ÐœÐžÑÑ ÑÑÐ°ÑÑÐœÐžÐºÐŸÐ² Ð¿ÑÐŸÐµÐºÑÐ° ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐŠÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone. ÐÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ Ð¿ÑÐžÑÐ²ÐŸÐžÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐžÐŒÑ dlpeople, Ñ Ð¿ÐµÑÐ°ÑÐ°Ñ:</Text>
+<CodeLine>mkcol.pl âcreator me@cs.waikato.ac.nz dlpeople</CodeLine>
+<Text id="68">ÐÐŸÐ¶Ð°Ð»ÑÐ¹ÑÑÐ°, ÐžÐ·ÐŒÐµÐœÐžÑÐµ ÐŒÐŸÐ¹ email Ð°ÐŽÑÐµÑ ÐœÐ° ÑÐ²ÐŸÐ¹ ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÑÐ¹!</Text>
+<Text id="69">ÐÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° Ð²ÐœÐŸÐ²Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² Ð¿ÐµÑÐµÐ¹ÐŽÐµÐŒ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ ÑÐŸÐ·ÐŽÐ°ÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ»Ñ ÑÑÐŸÐ³ÐŸ ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°ÐµÐŒ:</Text>
+<CodeLine>cd $GSDLHOME/collect/dlpeople</CodeLine>
+<Text id="70">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ ÑÑÐŸÐ¹ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž, ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð² Is. ÐÐŽÐµÑÑ ÐŽÐŸÐ»Ð¶ÐœÐŸ Ð±ÑÑÑ 7 ÐŽÐžÑÐµÐºÑÐŸÑÐžÐ¹: archives, building, etc, images, import, index Ðž perllib.</Text>
+<Text id="71">Ð¢ÐµÐ¿ÐµÑÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð·Ð°Ð¿ÐŸÐ»ÐœÐžÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒÐž. ÐÑÑÐŸÑÐœÐžÐº ÐŒÐ°ÑÐµÑÐžÐ°Ð»ÐŸÐ² ÐŽÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž dlpeople ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÐœÐ° ÑÑÑÐ°ÐœÐŸÐ²ÐŸÑÐœÐŸÐŒ CD-ROM Greenstone Ð² ÐºÐ°ÑÐ°Ð»ÐŸÐ³Ðµ collect/dlpeople. ÐÐ»Ñ Ð¿ÐŸÐ»ÑÑÐµÐœÐžÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž Ñ CD-ROM Ð¿ÐŸÐŽ Linux Ð²ÑÑÐ°Ð²ÑÑÐµ ÐŽÐžÑÐº Ð² ÑÐžÑÐ°ÑÑÐµÐµ ÑÑÑÑÐŸÐ¹ÑÑÐ²ÐŸ Ðž ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ ÐºÐŸÐŒÐ°ÐœÐŽÑ:</Text>
+<CodeLine>mount /cdrom</CodeLine>
+<Text id="72">(ÑÑÐ° ÐºÐŸÐŒÐ°ÐœÐŽÐ° ÐŒÐŸÐ¶ÐµÑ ÐŸÑÐ»ÐžÑÐ°ÑÑÑÑ ÐŸÑ ÑÐžÑÑÐµÐŒÑ Ðº ÑÐžÑÑÐµÐŒÐµ). ÐÐŸÑÐ»Ðµ ÑÑÑÐ°ÐœÐŸÐºÐž CD-ROM ÐŒÐŸÐ¶ÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ, ÐºÐ°Ðº Ð»ÑÐ±Ð°Ñ ÐŽÑÑÐ³Ð°Ñ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ, Ðž ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð² Is /cdrom/collect, ÐŒÐŸÐ¶ÐœÐŸ Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž Ñ ÐžÐŒÐµÐœÐµÐŒ dlpeople ÐœÐ° CD-ROM.</Text>
+<Text id="73">ÐÐ°ÑÐµÐŒ ÑÐºÐŸÐ¿ÐžÑÑÐ¹ÑÐµ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž /cdrom/collect/dlpeople  Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ $GSDLHOME/collect/dlpeople/import. ÐÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÑÐŽÐµÐ»Ð°ÑÑ ÑÑÐŸ, ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ ÐºÐŸÐŒÐ°ÐœÐŽÑ:</Text>
+<CodeLine>cp âr /cdrom/collect/dlpeople/*   import/</CodeLine>
+<Text id="74">ÐÐ°ÑÐµÐŒ ÐœÐ°Ð±ÐµÑÐžÑÐµ:</Text>
+<CodeLine>umount /cdrom</CodeLine>
+<Text id="75">ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ Ð·Ð°ÐºÑÑÑÑ CD-ROM ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ</Text>
+<Text id="76">Ð ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž etc ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÑÐ°Ð¹Ð» collect.ucfg. ÐÑÐºÑÐŸÐ¹ÑÐµ ÐµÐ³ÐŸ, Ð²ÐŸÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ð²ÑÐžÑÑ Ð»ÑÐ±ÑÐŒ ÑÐµÐºÑÑÐŸÐ²ÑÐŒ ÑÐµÐŽÐ°ÐºÑÐŸÑÐŸÐŒ ÐžÐ»Ðž ÐœÐ°ÐžÐ±ÐŸÐ»ÐµÐµ Ð¿ÐŸÐ¿ÑÐ»ÑÑÐœÑÐŒ Ð² Linux ÑÐµÐºÑÑÐŸÐ²ÑÐŒ ÑÐµÐŽÐ°ÐºÑÐŸÑÐŸÐŒ - emacs. Ð ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐµ Ð²Ñ ÑÐ²ÐžÐŽÐžÑÐµ ÐŸÐºÐœÐŸ, ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ Ð²ÑÐ³Ð»ÑÐŽÐžÑ, ÐºÐ°Ðº ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="collection_configuration_file_created_by_mkcol"/>, Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°Ñ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ ÑÐ°Ð¹Ð»Ð° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐŸÐ·ÐŽÐ°ÐœÐœÐŸÐ³ÐŸ Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ ÐºÐŸÐŒÐ°ÐœÐŽÑ mkcol.pl -creator me@cs.waikato.ac.nz dlpeople.</Text>
+<Text id="77">Ð¢ÐµÐ¿ÐµÑÑ Ð²Ñ Ð³ÐŸÑÐŸÐ²Ñ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. Ð­ÑÐŸ Ð¿ÑÐŸÑÐµÑÑ Ð¿ÐµÑÐµÐœÐŸÑÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð² ÑÐžÑÑÐµÐŒÑ Greenstone, ÑÑÐ°ÐœÐŽÐ°ÑÑÐžÐ·Ð°ÑÐžÐž ÑÐŸÑÐŒÐ°ÑÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², Ð¿ÑÑÐž ÑÐ¿ÐµÑÐžÑÐžÐºÐ°ÑÐžÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðž ÑÑÑÑÐºÑÑÑÑ ÑÐ°Ð¹Ð»Ð°, Ð² ÐºÐŸÑÐŸÑÐŸÐŒ Ð±ÑÐŽÑÑ Ñ
+ÑÐ°ÐœÐžÑÑÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ. ÐÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ ÐºÐŸÐŒÐ°ÐœÐŽÑ import.pl Ðž Ð¿ÐŸÐ»ÑÑÐžÑÐµ Ð¿ÐŸÐ»ÐœÑÐ¹ ÑÐ¿ÐžÑÐŸÐº ÐŸÐ¿ÑÐžÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐžÐŒÐ¿ÐŸÑÑÐ°. ÐÐ»Ñ ÑÐ¿ÑÐŸÑÐµÐœÐžÑ Ð¿ÑÐŸÑÐµÐŽÑÑÑ Ð²ÐŸÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµÑÑ Ð±Ð°Ð·ÐŸÐ²ÐŸÐ¹ ÐºÐŸÐŒÐ°ÐœÐŽÐŸÐ¹</Text>
+<CodeLine>import.pl   dlpeople</CodeLine>
+<Text id="78">ÐÐµ Ð±ÐµÑÐ¿ÐŸÐºÐŸÐ¹ÑÐµÑÑ Ð¿ÐŸ Ð¿ÐŸÐ²ÐŸÐŽÑ Ð±ÑÑÑÑÐŸ Ð±ÐµÐ³ÑÑÐµÐ³ÐŸ Ð¿ÐŸ ÑÐºÑÐ°ÐœÑ ÑÐµÐºÑÑÐ° - ÑÑÐŸ ÐŸÑÑÐµÑ ÐŸ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐž Ð¿ÑÐŸÑÐµÐŽÑÑÑ ÐžÐŒÐ¿ÐŸÑÑÐ°. Ð ÑÐ²ÐµÐŽÐµÐœÐžÑ, Ð¿ÑÐŸÑÐµÑÑ ÐžÐŒÐ¿ÐŸÑÑÐ° ÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð·Ð°ÐœÐžÐŒÐ°ÐµÑ ÐŸÐºÐŸÐ»ÐŸ 5 ÐŒÐžÐœÑÑ ÐœÐ° 1 ÐÐÑ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ Ðž ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐŽÐŸÐ»ÑÑÐµ ÐœÐ° Ð±ÐŸÐ»ÐµÐµ ÐŒÐµÐŽÐ»ÐµÐœÐœÑÑ
+ ÐŒÐ°ÑÐžÐœÐ°Ñ
+. ÐÐ±ÑÐ°ÑÐžÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ ÐœÐ° ÑÐŸ, ÑÑÐŸ Ð²Ñ ÐœÐµ ÐŽÐŸÐ»Ð¶ÐœÑ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑÑ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÑÑ
+ collect ÐžÐ»Ðž dlpeople Ð¿ÑÐž Ð·Ð°Ð¿ÑÑÐºÐµ ÑÑÐŸÐ¹ ÐºÐŸÐŒÐ°ÐœÐŽÑ, Ñ.Ðº. GSDLHOME ÑÐ¶Ðµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÐ» ÐŽÐ»Ñ ÑÐ°Ð±ÐŸÑÑ ÑÐžÑÑÐµÐŒÑ Greenstone ÐŒÐµÑÑÐŸÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÐµ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ².</Text>
+<Text id="79">Ð¢ÐµÐ¿ÐµÑÑ ÐŽÐ°Ð²Ð°Ð¹ÑÐµ Ð²ÐœÐµÑÐµÐŒ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð² ÑÐ°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŽÐ»Ñ ÐŒÐŸÐŽÐžÑÐžÐºÐ°ÑÐžÐž ÐµÐµ Ð²ÐžÐŽÐ°. Ð¡ÐœÐ°ÑÐ°Ð»Ð° Ð¿ÑÐžÑÐ²ÐŸÐžÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐžÐŒÑ. ÐÐœÐŸ Ð±ÑÐŽÐµÑ Ð²ÐŸÑÐ¿ÑÐžÐœÑÑÐŸ Ð²ÐµÐ±-Ð±ÑÐŸÑÐ·ÐµÑÐŸÐŒ ÐºÐ°Ðº Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº ÐŽÐ»Ñ ÑÐžÑÑÐ»ÑÐœÐŸÐ³ÐŸ Ð»ÐžÑÑÐ° WWW-ÑÑÑÐ°ÐœÐžÑÑ, Ðž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐžÐºÐŸÐœÐºÐž Ð¿ÑÐž ÐŸÑÑÑÑÑÑÐ²ÐžÐž ÑÐžÑÑÐœÐºÐ°. ÐÐ·ÐŒÐµÐœÐžÐŒ ÑÑÑÐŸÐºÑ collectionmeta collectionname "dlpeople" ÐœÐ° ÑÑÑÐŸÐºÑ Ð²ÐžÐŽÐ°: collectionmeta collectionname "The People of the NZDL project".</Text>
+<Text id="80">ÐÐŸÐ±Ð°Ð²ÐžÐŒ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐµÐ¶ÐŽÑ ÐºÐ°Ð²ÑÑÐºÐ°ÐŒÐž: <i>collectionmeta collectionextra ""</i>. ÐÐœÐŸ Ð±ÑÐŽÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐŸ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐŒÐ°ÑÐµÑÐžÐ°Ð»Ð° ÐŽÐ»Ñ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ ÑÐ°Ð·ÐŽÐµÐ»Ð° "About" (ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž) ÐœÐ° ÐŽÐŸÐŒÐ°ÑÐœÐµÐ¹ WWW-ÑÑÑÐ°ÐœÐžÑÐµ. Ð¯ ÐŽÐŸÐ±Ð°Ð²ÐžÐ» "This collection is made up of the homepages of some of the people who have worked on the NZDL project." ÐÐ°Ð¶ÐœÐŸ Ð²Ð²ÐŸÐŽÐžÑÑ ÑÑÐŸ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÐŸÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐŸÐ¹ - ÐœÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐŽÐ»Ñ ÐŸÑÐ±ÐžÐ²ÐºÐž ÐºÐ»Ð°Ð²ÐžÑÑ Enter/ÐÐ²ÐŸÐŽ. ÐÑÐ»Ðž Ð²Ñ Ñ
+ÐŸÑÐžÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð² Ð²Ð°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐœÐŸÐ³ÐŸÑÐ·ÑÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ, ÑÐŸ ÑÑÑÐµÑÑÐ²ÑÐµÑ ÑÐ¿ÐŸÑÐŸÐ± Ð²ÑÐ²ÐŸÐŽÐ° ÐŽÐ°ÐœÐœÐŸÐ³ÐŸ ÑÐµÐºÑÑÐ° Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐž Ñ Ð²ÑÐ±ÑÐ°ÐœÐœÑÐŒ ÑÐ·ÑÐºÐŸÐŒ. Ð­ÑÐŸ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ Ð±ÑÐŽÐµÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐŸ ÐŽÐ°Ð»ÐµÐµ Ð² ÑÐ°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Section" ref="configuration_file"/>.</Text>
+<Text id="81">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ, ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐŽÑÑ ÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÑÑ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐžÐºÐŸÐœÐŸÐº ÐœÐ° WWW-ÑÑÑÐ°ÐœÐžÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ, ÑÐŸÐ·ÐŽÐ°ÐœÐœÐŸÐµ ÐŒÐœÐŸÑ, Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÐžÐŽÐµÑÑ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="collection_icon"/>. Ð£ÐºÐ°Ð¶ÐžÑÐµ Ð¿ÑÑÑ ÐœÐ°Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÑ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ Ð² ÐºÐ°Ð²ÑÑÐºÐ°Ñ
+ Ð² ÑÑÑÐŸÐºÐµ collectionmeta iconcollection "" ÑÐ°Ð¹Ð»Ð° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž. ÐÐ»Ñ ÐºÑÐ°ÑÐºÐŸÑÑÐž Ðž ÐŒÐŸÐ±ÐžÐ»ÑÐœÐŸÑÑÐž _httpprefix_ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ðœ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÑÑÐ°ÑÑÐŸÐ²ÐŸÐ³ÐŸ URL, ÑÐºÐ°Ð·ÑÐ²Ð°ÑÑÐµÐ³ÐŸ ÐœÐ° ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ, ÐœÐ°Ñ
+ÐŸÐŽÑÑÐµÐµÑÑ Ð² ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ¹ ÐŸÐ±Ð»Ð°ÑÑÐž Greenstone. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð²Ð²ÐµÑÑÐž: httpprefix_/collect/dlpeople/images/icon.gif ÐµÑÐ»Ðž Ð²Ñ Ð¿ÐŸÐŒÐµÑÑÐžÐ»Ðž Ð¿ÐŸÐŽÑ
+ÐŸÐŽÑÑÐµÐµ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÑÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (Ð² ÐœÐ°ÑÐµÐŒ Ð¿ÑÐžÐŒÐµÑÐµ ÑÑÐŸ: collect\dlpeople\images ).</Text>
+<Text id="82">Ð¡ÐŸÑ
+ÑÐ°ÐœÐžÑÐµ ÑÐ°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð·Ð°ÐºÑÐŸÐ¹ÑÐµ ÐµÐ³ÐŸ - ÐŸÐœ Ð²Ð°ÐŒ Ð±ÐŸÐ»ÑÑÐµ ÐœÐµ Ð¿ÐŸÐœÐ°ÐŽÐŸÐ±ÐžÑÑÑ ÐœÐ° ÐŽÐ°ÐœÐœÐŸÐŒ ÑÑÐ°Ð¿Ðµ ÐŸÐ±ÑÑÐµÐœÐžÑ.</Text>
+<Text id="83">Ð¡Ð»ÐµÐŽÑÑÑÐ°Ñ ÑÐ°Ð·Ð° - "Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÐµ" ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð² ÐºÐŸÑÐŸÑÐŸÐ¹ Ð±ÑÐŽÑÑ ÑÐŸÐ·ÐŽÐ°ÐœÑ Ð²ÑÐµ ÐžÐœÐŽÐµÐºÑÑ Ðž ÑÐ°Ð¹Ð»Ñ, ÐŸÑÐ²ÐµÑÐ°ÑÑÐžÐµ Ð·Ð° ÑÐ°Ð±ÐŸÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ Ð² ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐµ buildcol.pl Ðž Ð¿ÐŸÐ»ÑÑÐžÑÐµ ÑÐ¿ÐžÑÐŸÐº ÐŸÐ¿ÑÐžÐ¹ ÐŽÐ»Ñ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐŸÐŽÑÐŸÐ±ÐœÐŸÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÑÑÐžÑ
+ ÐŸÐ¿ÑÐžÐ¹ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐŸ Ð² Ð Ð°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Section" ref="import_and_build_processes"/>. ÐÐŸÐºÐ° Ð¶Ðµ Ð¿ÑÐžÐŽÐµÑÐ¶ÐžÐ²Ð°Ð¹ÑÐµÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ "Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ", ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð²:</Text>
+<CodeLine>buildcol.pl dlpeople</CodeLine>
+<Text id="84">Ð ÑÐœÐŸÐ²Ð° ÐœÐµ Ð±ÐµÑÐ¿ÐŸÐºÐŸÐ¹ÑÐµÑÑ ÐŸ Ð±ÑÑÑÑÐŸ Ð±ÐµÐ³ÑÑÐµÐŒ Ð¿ÐŸ ÑÐºÑÐ°ÐœÑ ÑÐµÐºÑÑÐµ - ÑÑÐŸ ÐŸÑÑÐµÑ ÐŸ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐž ÐºÐŸÐŒÐ°ÐœÐŽÑ.</Text>
+<Text id="85">Ð¡ÐŽÐµÐ»Ð°Ð¹ÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ "ÐŸÐ¿ÐµÑÐ°ÑÐžÐ²ÐœÐŸÐ¹", ÐºÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐŒÐ°ÑÐµÑÐžÐ°Ð»Ñ Ð¿ÐŸÐŒÐµÑÐµÐœÑ Ð² ÐºÐ°ÑÐ°Ð»ÐŸÐ³ building, Ð¿ÐµÑÐµÑÐ»ÐžÑÐµ ÐžÑ
+ Ð² ÐºÐ°ÑÐ°Ð»ÐŸÐ³ index. ÐÑÐ»Ðž Ñ Ð²Ð°Ñ Ð¿ÑÐµÐ¶ÐŽÐµ Ð±ÑÐ»Ð° ÑÐ¶Ðµ ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÑÐœÐ°ÑÐ°Ð»Ð° ÑÐŽÐ°Ð»ÐžÑÐµ ÑÑÐ°ÑÑÐµ ÐžÐœÐŽÐµÑÑ, ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð² Ð² ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐµ:</Text>
+<CodeLine>rm âr index/*</CodeLine>
+<Text id="86">(Ð¿ÑÐµÐŽÐ¿ÐŸÐ»Ð°Ð³Ð°ÐµÑÑÑ, ÑÑÐŸ Ð²Ñ ÑÐ°Ð±ÐŸÑÐ°ÐµÑÐµ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž dlpeople). ÐÐ°ÑÐµÐŒ Ð²Ð²ÐµÐŽÐžÑÐµ:</Text>
+<CodeLine>mv building/* index/</CodeLine>
+<Table id="collection-building_differences_between_windows_and_linux">
+<Title>
+<Text id="87">Ð Ð°Ð·Ð»ÐžÑÐžÑ Ð² Ð¿ÑÐŸÑÐµÑÑÐ°Ñ
+ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐŽÐ»Ñ Windows Ðž Linux Windows</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="265">
+<Text id="88"><b>Windows</b></Text>
+</th>
+<th width="265">
+<Text id="89"><b>Linux</b></Text>
+</th>
+</tr>
+<tr>
+<th width="265">
+<Text id="90">Linux ÐÐ°Ð¿ÑÑÑÐžÑÐµ setup, bat, ÑÑÐŸÐ±Ñ ÑÐŽÐµÐ»Ð°ÑÑ  Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Greenstone ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž</Text>
+</th>
+<th width="265">
+<Text id="91">ÐÐ°Ð¿ÑÑÑÐžÑÐµ setup, bat, ÑÑÐŸÐ±Ñ ÑÐŽÐµÐ»Ð°ÑÑ                                       ÐÐ°Ð¿ÑÑÑÐžÑÐµ setup, bash ÐžÐ»Ðž setup, csh, ÑÑÐŸÐ±Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Greenstone ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž</Text>
+</th>
+</tr>
+<tr>
+<th width="265">
+<Text id="92">Ð¡ÐºÐŸÐ¿ÐžÑÑÐ¹ÑÐµ ÑÐ°Ð¹Ð»Ñ Ñ CD-ROM, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐŒÐµÐœÐµÐŽÐ¶ÐµÑ ÑÐ°Ð¹Ð»ÐŸÐ² ÐžÐ»Ðž Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐºÐŸÐŒÐ°ÐœÐŽ Windows</Text>
+</th>
+<th width="265">
+<Text id="93">Ð¡ÐºÐŸÐ¿ÐžÑÑÐ¹ÑÐµ ÑÐ°Ð¹Ð»Ñ Ñ CD-ROM, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ mount Ðž ÐºÐŸÐŒÐ°ÐœÐŽÑ Unix</Text>
+</th>
+</tr>
+<tr>
+<th width="265">
+<Text id="94">ÐÐ°ÐŒÐµÐœÐžÑÐµ ÐžÐœÐŽÐµÐºÑÑ ÑÑÐ°ÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð² rd /s index, Ð¿ÐŸÑÐŸÐŒ ren building index Ð·Ð°ÑÐµÐŒ mkdir building, ÐžÐ»Ðž Ð²ÐŸÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµÑÑ ÐŒÐµÐœÐµÐŽÐ¶ÐµÑÐŸÐŒ ÑÐ°Ð¹Ð»ÐŸÐ²</Text>
+</th>
+<th width="265">
+<Text id="95">ÐÐ°ÐŒÐµÐœÐžÑÐµ ÐžÐœÐŽÐµÐºÑÑ ÑÑÐ°ÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð² rm âr index/* , Ð° Ð·Ð°ÑÐµÐŒ mv building/* index</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="96">ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ ÑÐŒÐµÑÑ ÐŸÐ±ÑÐ°ÑÐ°ÑÑÑÑ Ðº Ð²ÐœÐŸÐ²Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ñ Ð²Ð°ÑÐµÐ¹ ÐŽÐŸÐŒÐ°ÑÐœÐµÐ¹ ÑÑÑÐ°ÐœÐžÑÑ Greenstone. ÐÑÐ»Ðž ÑÑÐ° ÑÑÑÐ°ÐœÐžÑÐ° ÐŸÑÐºÑÑÑÐ° Ð² Ð²Ð°ÑÐµÐŒ Ð±ÑÐŸÑÐ·ÐµÑÐµ, Ð²Ñ ÐŽÐŸÐ»Ð¶ÐœÑ ÐµÐµ ÐŸÐ±ÐœÐŸÐ²ÐžÑÑ ÐžÐ»Ðž Ð·Ð°ÐºÑÑÑÑ ÐŸÐºÐœÐŸ Ð±ÑÐŸÑÐ·ÐµÑÐ° Ðž Ð¿ÐµÑÐµÐ·Ð°Ð¿ÑÑÑÐžÑÑ ÐµÐ³ÐŸ (ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÐžÐ·Ð±ÐµÐ¶Ð°ÑÑ Ð¿ÑÐŸÐ±Ð»ÐµÐŒ ÐºÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ). ÐÑÐ»Ðž Ð²Ñ Ð¿ÐŸÐ»ÑÐ·ÑÐµÑÐµÑÑ "Ð»ÐŸÐºÐ°Ð»ÑÐœÐŸÐ¹ Ð²ÐµÑÑÐžÐµÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž" Greenstone, ÑÐŸ ÐŽÐŸÐ»Ð¶ÐœÑ Ð¿ÐµÑÐµÐ·Ð°Ð¿ÑÑÑÐžÑÑ Ð²ÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ. ÐÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐµÐ»ÐºÐœÐžÑÐµ ÐºÐœÐŸÐ¿ÐºÐŸÐ¹ ÐŒÑÑÐž Ð¿ÐŸ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ. ÐÐŸÐ»ÑÑÐµÐœÐœÑÐ¹ ÑÐµÐ·ÑÐ»ÑÑÐ°Ñ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐ²ÐžÐŽÐµÑÑ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="about_page_for_the_new_collection"/>.</Text>
+<Text id="97">Ð Ð² Ð·Ð°ÐºÐ»ÑÑÐµÐœÐžÐµ Ð¿ÑÐžÐ²ÐµÐŽÐµÐŒ ÑÐ°ÑÐ¿ÐµÑÐ°ÑÐºÑ ÐºÐŸÐŒÐ°ÐœÐŽ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž dlpeople:</Text>
+<CodeLine>cd ~/gsdl # assuming default Greenstone in home directory</CodeLine>
+<CodeLine>source setup.bash     # if you're running the BASH shell</CodeLine>
+<CodeLine>source setup.csh       # if you're running the C shell</CodeLine>
+<CodeLine>mkcol.pl âcreator me@cs.waikato.ac.nz dlpeople</CodeLine>
+<CodeLine>cd $GSDLHOME/collect/dlpeople</CodeLine>
+<CodeLine>mount /cdrom # assuming this is where CD-ROM is mapped to</CodeLine>
+<CodeLine>cp âr /cdrom/collect/dlpeople/* import/</CodeLine>
+<CodeLine>umount /cdrom</CodeLine>
+<CodeLine>import.pl dlpeople</CodeLine>
+<CodeLine>buildcol.pl dlpeople</CodeLine>
+<CodeLine>rm -r index/*</CodeLine>
+<CodeLine>mv building/* index</CodeLine>
+</Content>
+</Subsection>
+<Subsection id="differences_between_windows_and_unix">
+<Title>
+<Text id="98">Ð Ð°Ð·Ð»ÐžÑÐžÑ ÐŒÐµÐ¶ÐŽÑ Windows Ðž Unix</Text>
+</Title>
+<Content>
+<Text id="99">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ð² ÑÑÐµÐŽÐµ Unix Ðž ÑÑÐµÐŽÐµ Windows ÐŸÑÐµÐœÑ Ð¿ÐŸÑ
+ÐŸÐ¶Ðž, Ð·Ð° ÐžÑÐºÐ»ÑÑÐµÐœÐžÐµÐŒ ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÐœÐµÐ±ÐŸÐ»ÑÑÐžÑ
+ ÑÐ°ÑÑ
+ÐŸÐ¶ÐŽÐµÐœÐžÐ¹, ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐ»Ðž ÑÐ²ÐµÐŽÐµÐœÑ Ð² Ð¢Ð°Ð±Ð»ÐžÑÑ <CrossRef target="Table" ref="collection-building_differences_between_windows_and_linux"/>.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="greenstone_directories">
+<Title>
+<Text id="100">ÐÐžÑÐµÐºÑÐŸÑÐžÐž Greenstone</Text>
+</Title>
+<Content>
+<Text id="101">ÐÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="structure_of_the_gsdlhome_directory"/> Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐ° ÑÑÑÑÐºÑÑÑÐ° ÐŽÐžÑÐµÐºÑÐŸÑÐžÐ¹ GSDLHOME. Ð Ð¢Ð°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="where_to_find_information_about_directories"/> ÐŽÐ°ÐœÐŸ ÐºÑÐ°ÑÐºÐŸÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐ³ÐŸ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž, Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐœÐŸÐ¹ ÐœÐ° ÐŽÐžÐ°Ð³ÑÐ°ÐŒÐŒÐµ. ÐÐµÐºÐŸÑÐŸÑÑÐµ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž Ð±ÑÐŽÑÑ Ð±ÐŸÐ»ÐµÐµ ÐŽÐµÑÐ°Ð»ÑÐœÐŸ ÑÐ°ÑÑÐŒÐŸÑÑÐµÐœÑ Ð² Ð¿ÐŸÑÐ»ÐµÐŽÑÑÑÐžÑ
+ ÑÐ°Ð·ÐŽÐµÐ»Ð°Ñ
+ ÐœÐ°ÑÑÐŸÑÑÐµÐ³ÐŸ ÑÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° - ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÑÐ°Ð·ÐŽÐµÐ»Ð°Ñ
+ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐ° Ð² Ð¢Ð°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="where_to_find_information_about_directories"/>.</Text>
+<Figure id="structure_of_the_gsdlhome_directory">
+<Title>
+<Text id="102">Ð¡ÑÑÑÐºÑÑÐ° ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž GSDLHOME</Text>
+</Title>
+<File width="415" height="143" url="images/Dev_Fig_010.png"/>
+</Figure>
+<Table id="where_to_find_information_about_directories">
+<Title>
+<Text id="103">Ð¡ÑÑÑÐºÑÑÑÐ° ÐŽÐžÑÐµÐºÑÐŸÑÐžÐ¹</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="331">
+<Text id="104">ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ</Text>
+</th>
+<th width="66">
+<Text id="105">ÑÐ°Ð·ÐŽÐµÐ»</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="106"><i>bin</i></Text>
+</th>
+<th width="331">
+<Text id="107">ÐÑÐ¿ÐŸÐ»ÐœÑÐµÐŒÑÐ¹ ÐŽÐ²ÐŸÐžÑÐœÑÐ¹ ÐºÐŸÐŽ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž Ñ ÐžÐŒÐµÐœÐµÐŒ Ð²Ð°ÑÐµÐ¹ ÐÐ¡.</Text>
+</th>
+<th width="66">
+<Text id="108">â</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="109"><i>bin/script</i></Text>
+</th>
+<th width="331">
+<Text id="110">Ð¡ÐºÑÐžÐ¿ÑÑ ÑÐ·ÑÐºÐ° Perl, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ Ðž Ð²ÐµÐŽÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, import.pl and buildcol.pl). ÐÐ»Ñ Ð¿ÐŸÐ»ÑÑÐµÐœÐžÑ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ ÑÑÐžÑ
+ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒ ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ ÐžÑ
+ ÐžÐŒÑ Ð² ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐµ.</Text>
+</th>
+<th width="66">
+<Text id="111">1.3</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="112"><i>perllib</i></Text>
+</th>
+<th width="331">
+<Text id="113">ÐÐŸÐŽÑÐ»Ñ ÑÐ·ÑÐºÐ° Perl, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð²ÐŸ Ð²ÑÐµÐŒÑ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ Ðž ÐžÐŒÐ¿ÐŸÑÑÐ°.</Text>
+</th>
+<th width="66">
+<Text id="114">2.1</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="115"><i>perllib/plugins</i></Text>
+</th>
+<th width="331">
+<Text id="116">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐœÐ° ÑÐ·ÑÐºÐµ Perl - Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ ÐŽÐ»Ñ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ².</Text>
+</th>
+<th width="66">
+<Text id="117">2.1</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="118"><i>perllib/classify</i></Text>
+</th>
+<th width="331">
+<Text id="119">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° - ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ ÐœÐ° ÑÐ·ÑÐºÐµ Perl (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐºÐŸÐŽ AZList, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐŸÐ·ÐŽÐ°ÐµÑ ÑÐ¿ÐžÑÐŸÐº ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð² Ð°Ð»ÑÐ°Ð²ÐžÑÐœÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ Ð¿ÐŸ ÐœÐµÐºÐŸÑÐŸÑÐŸÐŒÑ Ð°ÑÑÐžÐ±ÑÑÑ).</Text>
+</th>
+<th width="66">
+<Text id="120">2.2</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="121"><i>cgi-bin</i></Text>
+</th>
+<th width="331">
+<Text id="122">ÐÑÐµ CGI -ÑÐºÑÐžÐ¿ÑÑ ÑÐžÑÑÐµÐŒÑ Greenstone, ÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐŒÐµÑÐµÐœÑ Ð² cgi-bin ÐºÐ°ÑÐ°Ð»ÐŸÐ³.</Text>
+</th>
+<th width="66">
+<Text id="123">â</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="124"><i>tmp</i></Text>
+</th>
+<th width="331">
+<Text id="125">ÐÐžÑÐµÐºÑÐŸÑÐžÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ Greenstone ÐŽÐ»Ñ Ð²ÑÐµÐŒÐµÐœÐœÐŸÐ³ÐŸ Ñ
+ÑÐ°ÐœÐµÐœÐžÑ ÑÐ°Ð¹Ð»ÐŸÐ².</Text>
+</th>
+<th width="66">
+<Text id="126">â</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="127"><i>etc</i></Text>
+</th>
+<th width="331">
+<Text id="128">Ð€Ð°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐ¹, ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÐž Ðž ÐŸÑÑÐµÑÐ° ÐŸÐ± ÐŸÑÐžÐ±ÐºÐ°Ñ
+, Ð±Ð°Ð·Ð° Ð°Ð²ÑÐŸÑÐžÐ·Ð°ÑÐžÐž Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹.</Text>
+</th>
+<th width="66">
+<Text id="129">â</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="130"><i>src</i></Text>
+</th>
+<th width="331">
+<Text id="131">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐœÐ° C++, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÐŸÐ±ÑÐ»ÑÐ¶ÐžÐ²Ð°ÐœÐžÑ
+ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÑÐµÑÐµÐ·   web-ÑÐµÑÐ²ÐµÑ.</Text>
+</th>
+<th width="66">
+<Text id="132">3</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="133"><i>src/colservr</i></Text>
+</th>
+<th width="331">
+<Text id="134">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐœÐ° C++, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÐŸÐ±ÑÐ»ÑÐ¶ÐžÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž âÐŸÑÐ²ÐµÑÑ ÐœÐ° Ð·Ð°Ð¿ÑÐŸÑÑ Ðž Ñ.Ð¿.</Text>
+</th>
+<th width="66">
+<Text id="135"><CrossRef target="Section" ref="protocol"/></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="136"><i>src/recpt</i></Text>
+</th>
+<th width="331">
+<Text id="137">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐœÐ° C++, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ Ð¿ÐµÑÐµÐŽÐ°ÑÐž Ð·Ð°Ð¿ÑÐŸÑÐ° ÑÐµÑÐµÐ· ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ðž ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐŸÑÐ²ÐµÑÐ° ÐœÐ° Ð·Ð°Ð¿ÑÐŸÑ.</Text>
+</th>
+<th width="66">
+<Text id="138">3.9</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="139"><i>packages</i></Text>
+</th>
+<th width="331">
+<Text id="140">ÐÐ°ÐºÐµÑ ÐžÑÑ
+ÐŸÐŽÐœÑÑ
+ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒ, ÐœÐµ Ð²Ñ
+ÐŸÐŽÑÑÐžÑ
+ Ð² ÑÐŸÑÑÐ°Ð² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ Greenstone, ÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÑ
+ ÐžÐŒ </Text>
+</th>
+<th width="66">
+<Text id="141">2.5</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="142"><i>packages/mg</i></Text>
+</th>
+<th width="331">
+<Text id="143">ÐÑÑ
+ÐŸÐŽÐœÐ°Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° MG, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Greenstone ÐŽÐ»Ñ ÑÐ¶Ð°ÑÐžÑ Ðž ÐžÐœÐŽÐµÐºÑÐ°ÑÐžÐž.</Text>
+</th>
+<th width="66">
+<Text id="144">2.5</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="145"><i>mappings</i></Text>
+</th>
+<th width="331">
+<Text id="146">ÐŸÐ²Ð°ÐœÐžÑ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ² Unicode (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐŽÐ»Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐºÐžÑÐ°Ð¹ÑÐºÐŸÐ¹ ÑÐ°ÑÐºÐ»Ð°ÐŽÐºÐž ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ²).</Text>
+</th>
+<th width="66">
+<Text id="147">â</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="148"><i>macros</i></Text>
+</th>
+<th width="331">
+<Text id="149">ÐÐ°ÐºÑÐŸÑÐ°Ð¹Ð»Ñ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÑÐºÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°.</Text>
+</th>
+<th width="66">
+<Text id="150">2.4</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="151"><i>collect</i></Text>
+</th>
+<th width="331">
+<Text id="152">Collections being served from this copy of Greenstone</Text>
+</th>
+<th width="66">
+<Text id="153">1.1</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="154"><i>lib</i></Text>
+</th>
+<th width="331">
+<Text id="155">ÐžÑÑ
+ÐŸÐŽÐœÐ°Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐœÐ° C++, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ ÐºÐ°Ðº ÑÐµÑÐ²ÐµÑÐŸÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐ°Ðº Ðž ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÐŸÐŒ</Text>
+</th>
+<th width="66">
+<Text id="156">3.1</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="157"><i>images</i></Text>
+</th>
+<th width="331">
+<Text id="158">ÐÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÑÐºÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°.</Text>
+</th>
+<th width="66">
+<Text id="159">â</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="160"><i>docs</i></Text>
+</th>
+<th width="331">
+<Text id="161">ÐÐŸÐºÑÐŒÐµÐœÑÐ°ÑÐžÑ</Text>
+</th>
+<th width="66">
+<Text id="162">â</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Section>
+<Section id="import_and_build_processes">
+<Title>
+<Text id="163">ÐÑÐŸÑÐµÑÑÑ import Ðž build</Text>
+</Title>
+<Content>
+<Text id="164">ÐÑÐž ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐž ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÐµÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹ ÐžÐ· ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ Ð»ÐžÐœÐžÐž (ÑÐŒ. Ð Ð°Ð·ÐŽÐµÐ» <CrossRef target="Section" ref="building_collections_from_the_command_line"/>) Ð±ÑÐ»Ðž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÑ ÐºÐŸÐŒÐ°ÐœÐŽÑ import.pl ÐŽÐ»Ñ ÐžÐŒÐ¿ÐŸÑÑÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ðž buildcol.pl ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐŽÐµÑÑ ÐŒÑ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐµÐµ ÑÐ°ÑÑÐŒÐŸÑÑÐžÐŒ, ÑÑÐŸ ÐŽÐµÐ»Ð°ÑÑ ÑÐ°ÐŒÐž ÑÑÐž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Ðž ÐŸÐ¿ÑÐžÐž, ÐºÐŸÑÐŸÑÑÐµ ÐžÑ
+ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑ. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒ Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÑ col_name ÐŽÐ»Ñ ÐŸÐ±ÑÐ°ÑÐµÐœÐžÑ Ðº Ð²ÐœÐŸÐ²Ñ ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐœÐŸÐ¹ ÐžÐ»Ðž ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="165">ÐÑÐŸÑÐµÑÑÑ ÐžÐŒÐ¿ÐŸÑÑÐ° Ðž ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ Ð²ÐŸ ÐŒÐœÐŸÐ³ÐŸÐŒ ÑÑ
+ÐŸÐ¶Ðž, Ð² ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐµ ÑÐµÐ³ÐŸ ÐžÐŒÐµÑÑ ÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÑÐžÑ
+ ÐŸÐ¿ÑÐžÐ¹, ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÑ
+ Ð² Ð¢Ð°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="options_for_the_import_and_build_processes"/>. (ÐÐŸÐŒÐœÐžÑÐµ, ÑÑÐŸ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ ÑÑÐŸÐ±Ñ ÑÐ²ÐžÐŽÐµÑÑ ÐŸÐ¿ÑÐžÐž ÐŽÐ»Ñ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÑÐºÑÐžÐ¿ÑÐŸÐ² Greenstone, ÐŽÐŸÑÑÐ°ÑÐŸÑÐœÐŸ ÐœÐ°Ð±ÑÐ°ÑÑ Ð² ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐµ ÐµÐ³ÐŸ ÐžÐŒÑ Ð±ÐµÐ· ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ ÐŸÐ¿ÑÐžÐ¹).</Text>
+<Table id="options_for_the_import_and_build_processes">
+<Title>
+<Text id="166">ÐÐ¿ÑÐžÐž ÐŽÐ»Ñ Ð¿ÑÐŸÑÐµÑÑÐŸÐ² import Ðž build</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="104">
+<Text id="167"><b>ÐÑÐ³ÑÐŒÐµÐœÑ</b></Text>
+</th>
+<th width="293">
+<Text id="168"><b>Ð€ÑÐœÐºÑÐžÑ</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="169"><i>-verbosity</i></Text>
+</th>
+<th width="104">
+<Text id="170">Ð§ÐžÑÐ»ÐŸ 0-3</Text>
+</th>
+<th width="293">
+<Text id="171">ÐÐŸÐœÑÑÐŸÐ»Ñ Ð·Ð° ÑÐµÐŒ, ÑÐºÐŸÐ»ÑÐºÐŸ ÐŽÐ°ÐœÐœÑÑ
+ ÐŸ Ð¿ÑÐŸÑÐµÑÑÐµ Ð·ÐœÐ°ÑÐžÑÑÑ ÐºÐ°Ðº ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÐ°Ñ ÐŸÑÐžÐ±ÐºÐ°; 0 - ÐŒÐ°Ð»ÐŸ, 3 - ÐŒÐœÐŸÐ³ÐŸ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="172"><i>-archivedir</i></Text>
+</th>
+<th width="104">
+<Text id="173">ÐÐŒÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž</Text>
+</th>
+<th width="293">
+<Text id="174">Ð£ÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐœÐ° ÐŒÐµÑÑÐŸ Ñ
+ÑÐ°ÐœÐµÐœÐžÑ Ð°ÑÑ
+ÐžÐ²ÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² Greenstone, ÐœÐ° ÑÐŸ, ÐºÑÐŽÐ° import.pl ÐŒÐŸÐ¶ÐµÑ ÐžÑ
+ Ð¿ÐŸÐŒÐµÑÑÐžÑÑ Ðž Ð³ÐŽÐµ buildcol.pl ÐŒÐŸÐ¶ÐµÑ ÐžÑ
+ ÐœÐ°Ð¹ÑÐž. ÐÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ GSDLHOME/collect/col name/archives</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="175"><i>-maxdocs</i></Text>
+</th>
+<th width="104">
+<Text id="176">Ð§ÐžÑÐ»ÐŸ &gt;0</Text>
+</th>
+<th width="293">
+<Text id="177">ÐÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐŒÐ°ÐºÑÐžÐŒÐ°Ð»ÑÐœÐŸÐµ ÑÐžÑÐ»ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÐŸÐ±ÑÐ°Ð±ÐŸÑÐ°ÐœÐœÑÑ
+ ÐŸÐ¿ÑÐžÑÐŒÐž import ÐžÐ»Ðž built. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð²ÐŸ Ð²ÑÐµÐŒÑ ÑÐµÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ ÑÐ°Ð¹Ð»Ð° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐžÐ»Ðž ÐœÐŸÐ²ÑÑ
+ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐ¹.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="178"><i>-collectdir</i></Text>
+</th>
+<th width="104">
+<Text id="179">ÐÐŒÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž</Text>
+</th>
+<th width="293">
+<Text id="180">Ð£ÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐœÐ° ÐŒÐµÑÑÐŸ ÐœÐ°Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ GSDLHOME/collect</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="181"><i>-out</i></Text>
+</th>
+<th width="104">
+<Text id="182">ÐÐŒÑ ÑÐ°Ð¹Ð»Ð°</Text>
+</th>
+<th width="293">
+<Text id="183">Ð£ÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐœÐ° ÑÐ°Ð¹Ð», Ð² ÐºÐŸÑÐŸÑÐŸÐŒ Ð·Ð°Ð¿ÐžÑÑÐ²Ð°ÑÑÑÑ Ð²ÑÐµ ÐžÑÑ
+ÐŸÐŽÑÑÐžÐµ ÑÐŸÐŸÐ±ÑÐµÐœÐžÑ, ÐŸÐ±ÑÑÐœÐŸ ÐŽÐ»Ñ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÑ
+ ÐŸÑÐžÐ±ÐŸÐº. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð² ÑÐ°Ð±ÐŸÑÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐ¹ ÐŸÑÐ»Ð°ÐŽÐºÐž ÐœÐ°Ð¹ÐŽÐµÐœÐœÑÑ
+ ÐŸÑÐžÐ±ÐŸÐº.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="184"><i>-keepold</i></Text>
+</th>
+<th width="104">
+<Text id="185">ÐÑÑÑÑÑÑÐ²ÑÐµÑ</Text>
+</th>
+<th width="293">
+<Text id="186">ÐÐµ ÑÐŽÐ°Ð»ÑÐµÑ ÑÐµÐ·ÑÐ»ÑÑÐ°Ñ Ð¿ÑÐµÐŽÑÐŽÑÑÐžÑ
+ Ð·Ð°Ð¿ÑÑÐºÐŸÐ² Ð¿ÑÐŸÑÐµÑÑÐŸÐ² import ÐžÐ»Ðž build; Ð² Ð¿ÑÐŸÑÐµÑÑÐµ ÐžÐŒÐ¿ÐŸÑÑÐ° ÐœÐµ ÑÐŽÐ°Ð»ÑÐµÑ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž archives', Ð² Ð¿ÑÐŸÑÐµÑÑÐµ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐœÐµ ÐŸÑÐžÑÐ°ÐµÑ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž building.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="187"><i>âdebug</i></Text>
+</th>
+<th width="104">
+<Text id="188">ÐÑÑÑÑÑÑÐ²ÑÐµÑ</Text>
+</th>
+<th width="293">
+<Text id="189"> ÐÐµÑÐ°ÑÑ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐŸÐ² ÑÐ°Ð±ÐŸÑÑ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐ¹ ÐŸÑÐ»Ð°ÐŽÐºÐž.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Subsection id="the_import_process">
+<Title>
+<Text id="190">ÐÑÐŸÑÐµÑÑ import</Text>
+</Title>
+<Content>
+<Text id="191">ÐÑÐŸÑÐµÑÑ ÐžÐŒÐ¿ÐŸÑÑÐ° ÑÐ»ÑÐ¶ÐžÑ ÐŽÐ»Ñ ÐºÐŸÐœÐ²ÐµÑÑÐ°ÑÐžÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐžÐ· ÐžÑ
+ Ð¿ÐµÑÐ²ÐžÑÐœÑÑ
+ ÑÐŸÑÐŒÐ°ÑÐŸÐ² Ð² Ð€ÐŸÑÐŒÐ°Ñ ÐÑÑ
+ÐžÐ²Ð° Greenstone, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐ¹ ÑÐžÑÑÐµÐŒÐŸÐ¹ Greenstone, Ðž Ð·Ð°Ð¿ÐžÑÐž Ð² ÐºÐŸÐœÐµÑÐœÑÐ¹ ÑÐ°Ð¹Ð» (Ñ ÐžÐŒÐµÐœÐµÐŒ archives, inf), ÐºÐŸÑÐŸÑÑÐ¹ Ð±ÑÐŽÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ ÑÐŸÐ³ÐŽÐ°, ÐºÐŸÐ³ÐŽÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÐ¶Ðµ Ð±ÑÐŽÐµÑ ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐ°. Import.pl ÐŽÐŸÐ»Ð¶ÐµÐœ Ð·ÐœÐ°ÑÑ, ÐºÐ°ÐºÐŸÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ ÐŽÐŸÐ»Ð¶ÐœÐŸ Ð±ÑÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐŸ Ðž Ð³ÐŽÐµ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÑÐ°Ð¹Ð»-ÐŸÑÐžÐ³ÐžÐœÐ°Ð» ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. Ð Ð¢Ð°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="options_for_the_import_and_build_processes"/> Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÑ ÐŸÐ¿ÑÐžÐž ÐŽÐ»Ñ Ð¿ÑÐŸÑÐµÑÑÐŸÐ² ÐžÐŒÐ¿ÐŸÑÑÐ° Ðž ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ; Ð² Ð¢Ð°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="additional_options_for_the_import_process"/> ÐŽÐ°ÐœÑ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÑÐµ ÐŸÐ¿ÑÐžÐž, ÐºÐ°ÑÐ°ÑÑÐžÐµÑÑ ÑÐŸÐ»ÑÐºÐŸ Ð¿ÑÐŸÑÐµÑÑÐ° ÐžÐŒÐ¿ÐŸÑÑÐ°. ÐÐ¿ÑÐžÐž OIDtype Ð·Ð°ÑÐ»ÑÐ¶ÐžÐ²Ð°ÑÑ Ð±ÐŸÐ»ÐµÐµ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸÐ³ÐŸ ÑÐ°ÑÑÐŒÐŸÑÑÐµÐœÐžÑ. ÐÐ°Ð¶ÐŽÑÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ ÐžÐŒÐµÐµÑ ÑÐ²ÑÐ·Ð°ÐœÐœÑÐ¹ Object IdentiÂ¬fier (ÐÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑ ÐÐ±ÑÐµÐºÑÐ°) ÐžÐ»Ðž OID. Ð­ÑÐŸ ÐœÐ°ÐžÐ»ÑÑÑÐžÐ¹ ÑÐ¿ÐŸÑÐŸÐ± ÐŽÐ»Ñ Ñ
+ÐµÑÐžÑÐŸÐ²Ð°ÐœÐžÑ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° (hash/Ñ
+ÐµÑ). Ð¥ÐŸÑÑ ÐŸÐœ Ðž ÐŸÑÐµÐœÑ ÐŒÐµÐŽÐ»ÐµÐœÐœÑÐ¹, ÐœÐŸ Ð²ÑÐµ Ð¶Ðµ ÑÐ²Ð»ÑÐµÑÑÑ ÐŽÐŸÑÑÐ°ÑÐŸÑÐœÐŸ Ð¿ÑÐŸÑÑÐŸÐ¹ Ð°Ð»ÑÑÐµÑÐœÐ°ÑÐžÐ²ÐŸÐ¹ ÐœÐ°ÐºÐŸÐ¿Ð»ÐµÐœÐžÑ, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð² ÑÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ, Ð² ÐºÐŸÑÐŸÑÐŸÐŒ ÐŸÐœÐž Ð±ÑÐ»Ðž ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÑ. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐœÐ°ÐºÐŸÐ¿Ð»ÐµÐœÐžÐµ ÐŽÐ»Ñ ÑÑÐºÐŸÑÐµÐœÐžÑ ÑÐ°Ð±ÐŸÑÑ, ÐœÐŸ Ð²ÑÐµ Ð¶Ðµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ Ñ
+ÐµÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð² ÑÐ»ÑÑÐ°Ðµ, ÐµÑÐ»Ðž Ð¿ÐŸÐ·Ð¶Ðµ Ð·Ð°Ñ
+ÐŸÑÐžÑÐµ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ðº Ð²Ð°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (Ð±ÐµÐ· Ð¿ÐŸÐ²ÑÐŸÑÐœÐŸÐ¹ Ð¿ÑÐŸÑÐµÐŽÑÑÑ ÐžÐŒÐ¿ÐŸÑÑÐ°).</Text>
+<Table id="additional_options_for_the_import_process">
+<Title>
+<Text id="192">ÐÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÑÐµ ÐŸÐ¿ÑÐžÐž ÐŽÐ»Ñ Ð¿ÑÐŸÑÐµÑÑÐ°</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="104">
+<Text id="193"><b>ÐÑÐ³ÑÐŒÐµÐœÑ</b></Text>
+</th>
+<th width="293">
+<Text id="194"><b>Ð€ÑÐœÐºÑÐžÑ</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="195"><i>-importdir</i></Text>
+</th>
+<th width="104">
+<Text id="196">ÐÐŒÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž</Text>
+</th>
+<th width="293">
+<Text id="197">Ð£ÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐœÐ° ÑÐŸ, Ð³ÐŽÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐœÐ°Ð¹ÐŽÐµÐœÑ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ. ÐÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ: GSDLHOME/collect/coljiame/import.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="198"><i>-removeold</i></Text>
+</th>
+<th width="104">
+<Text id="199">ÐÑÑÑÑÑÑÐ²ÑÐµÑ</Text>
+</th>
+<th width="293">
+<Text id="200">ÐÑÐžÑÐ°ÐµÑ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž archives Ð¿ÐµÑÐµÐŽ Ð¿ÑÐŸÑÐµÑÑÐŸÐŒ ÐžÐŒÐ¿ÐŸÑÑÐ°.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="201"><i>-gzip</i></Text>
+</th>
+<th width="104">
+<Text id="202">ÐÑÑÑÑÑÑÐ²ÑÐµÑ          </Text>
+</th>
+<th width="293">
+<Text id="203">Zip Ð°ÑÑ
+ÐžÐ²ÐžÑÑÐµÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Greenstone, Ð¿ÐŸÐ»ÑÑÐµÐœÐœÑÐµ Ð² ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐµ Ð¿ÑÐŸÑÐµÑÑÐ° ÐžÐŒÐ¿ÐŸÑÑÐ° (ZIPPlug ÐŽÐŸÐ»Ð¶ÐµÐœ Ð±ÑÑÑ Ð²ÐºÐ»ÑÑÐµÐœ Ð² ÑÐ¿ÐžÑÐŸÐº Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐ¹, a gzip ÐŽÐŸÐ»Ð¶ÐµÐœ Ð±ÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ ÐœÐ° Ð²Ð°ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="204"><i>-groupsize</i></Text>
+</th>
+<th width="104">
+<Text id="205">Ð§ÐžÑÐ»ÐŸ Ð¥</Text>
+</th>
+<th width="293">
+<Text id="206">ÐÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², Ð³ÑÑÐ¿Ð¿ÐžÑÑÐµÐŒÑÑ
+ Ð² ÐŸÐŽÐžÐœ Ð°ÑÑ
+ÐžÐ²ÐœÑÐ¹ ÑÐ°Ð¹Ð» Greenstone, Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ 1 (ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ 1 ÐŽÐŸÐºÑÐŒÐµÐœÑÐµ 1 ÑÐ°Ð¹Ð»).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="207"><i>âsortmeta</i></Text>
+</th>
+<th width="104">
+<Text id="208">ÐÐŒÑ ÑÑÐ³Ð°</Text>
+</th>
+<th width="293">
+<Text id="209">Ð¡ÐŸÑÑÐžÑÑÐµÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð² Ð°Ð»ÑÐ°Ð²ÐžÑÐœÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ Ð¿ÐŸ ÐžÐŒÐµÐœÐž ÑÑÐ³Ð° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+          ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. ÐÐŽÐœÐ°ÐºÐŸ, ÐµÑÐ»Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐžÐŒÐµÐµÑ Ð±ÐŸÐ»ÐµÐµ 1 Ð³ÑÑÐ¿Ð¿Ñ Ð² ÐŸÐŽÐœÐŸÐŒ Ð°ÑÑ
+ÐžÐ²ÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ (Ñ.Ðµ. groupsize >1), ÑÑÐ° ÑÑÐœÐºÑÐžÑ Ð±ÑÐŽÐµÑ Ð·Ð°Ð±Ð»ÐŸÐºÐžÑÐŸÐ²Ð°ÐœÐ°.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="210"><i>-OIDtype</i></Text>
+</th>
+<th width="104">
+<Text id="211">Ð¥ÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ</Text>
+</th>
+<th width="293">
+<Text id="212">ÐÐµÑÐŸÐŽ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐÐš ÐŽÐ»Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²: Ñ
+ÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ, ÐŸÑÐµÐœÑ ÐžÐ»Ðž ÐœÐ°Ð¿ÐŸÐ»ÐœÐµÐœÐžÐµ     ÐŒÐµÐŽÐ»ÐµÐœÐœÑÐ¹ ÐŒÐµÑÐŸÐŽ; ÐŒÐµÑÐŸÐŽ ÐœÐ°Ð¿ÐŸÐ»ÐœÐµÐœÐžÑ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ Ð³ÐŸÑÐ°Ð·ÐŽÐŸ Ð±ÑÑÑÑÐµÐµ Ðž Ð·Ð°ÐºÐ»ÑÑÐ°ÐµÑÑÑ Ð² Ð¿ÑÐŸÑÑÐŸÐŒ Ð¿ÑÐžÑÐ²Ð°ÐžÐ²Ð°ÐœÐžÐž Ð²Ñ
+ÐŸÐŽÑÑÐžÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ Ð¿ÐŸÑÐ»ÐµÐŽÐŸÐ²Ð°ÑÐµÐ»ÑÐœÐŸÐ³ÐŸ ÐœÐŸÐŒÐµÑÐ°</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Figure id="steps_in_the_import_process">
+<Title>
+<Text id="213">ÐÐŸÑÐ°Ð³ÐŸÐ²ÐŸÐµ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ Ð¿ÑÐŸÑÐµÑÑÐ° import</Text>
+</Title>
+<File width="402" height="379" url="images/Dev_Fig_012.png"/>
+</Figure>
+<Text id="214">ÐÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="steps_in_the_import_process"/> Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœ Ð¿ÑÐŸÑÐµÑÑ ÐžÐŒÐ¿ÐŸÑÑÐ°, ÐžÐœÐžÑÐžÐžÑÐŸÐ²Ð°ÐœÐœÑÐ¹ Ð¿ÑÐŸÑÐµÐŽÑÑÐŸÐ¹ ÑÐ°Ð±ÐŸÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ import.pl. ÐÐ°Ð¶ÐŽÑÐ¹ ÐŸÐ²Ð°Ð» Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÑÑÐŸÐ±ÐŸÐ¹ ÐŒÐŸÐŽÑÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÐœÑÑÑÐžÐ¹ Ð·Ð°ÐŽÐ°ÑÐž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÐŸÐ¹ ÑÐ°ÑÑÐž ÑÐžÑÑÐµÐŒÑ Greenstone. ÐÑÐµ ÑÑÐž ÐŒÐŸÐŽÑÐ»Ðž ÐœÐ°Ñ
+ÐŸÐŽÑÑÑÑ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž GSDLHOME/perllib.</Text>
+<Text id="215">ÐÐ»Ñ ÑÐ°Ð³Ð° 3. ÐÐ±ÑÐ°ÑÐžÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ, ÑÑÐŸ Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÐµ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ, ÑÐ°ÐºÐžÐµ ÐºÐ°Ðº importdir Ðž archivedir ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð·Ð°Ð¿ÑÑÐµÐœÑ ÐžÐ· ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐž ÐžÐ»Ðž ÐžÐ· ÑÐ°Ð¹Ð»Ð° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.ÐÑÐ»Ðž Ð·Ð°Ð¿ÑÑÐº Ð¿ÑÐŸÐžÐ·Ð²ÐµÐŽÐµÐœ ÐžÐ· ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐž, ÑÐŸ Ð²ÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž, ÑÐŽÐµÐ»Ð°ÐœÐœÑÐµ ÑÐµÑÐµÐ· ÑÐ°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž, ÐžÐ³ÐœÐŸÑÐžÑÑÑÑÑÑ.</Text>
+<Text id="216">ÐÐ° 6 ÑÐ°Ð³Ðµ Ð±ÑÐ» ÑÐŸÐ·ÐŽÐ°Ðœ ÑÐ°Ð¹Ð» ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐŸÐœÐœÐŸÐ³ÐŸ Ð°ÑÑ
+ÐžÐ²Ð° (archives.ini).</Text>
+<Text id="217">ÐÐ° 7 ÑÐ°Ð³Ðµ Ð±ÑÐ» ÑÐŸÐ·ÐŽÐ°Ðœ ÐŸÐ±ÑÐµÐºÑ, ÐºÐŸÑÐŸÑÑÐ¹ Ñ
+ÑÐ°ÐœÐžÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÑÐŸÐŒ, ÐºÑÐŽÐ° Ð±ÑÐ»Ðž Ð·Ð°Ð¿ÐžÑÐ°ÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ, Ðž Ð¿ÐŸÐŽÑÐžÐœÑÐµÑÑÑ ÑÐ¿ÐµÑÐžÐ°Ð»ÑÐœÑÐŒ ÐžÐœÑÑÑÑÐºÑÐžÑÐŒ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐµÑÑÐ° ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐžÑ (ÑÐ°ÐºÐžÐŒ ÐºÐ°Ðº sortmeta, ÐºÐŸÑÐŸÑÐ°Ñ ÑÐŸÑÑÐžÑÑÐµÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐž ÑÐŸ ÑÐ¿ÐµÑÐžÑÐžÐºÐŸÐ¹ ÑÑÐ³ÐŸÐ² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+).</Text>
+<Text id="218">ÐÐŸÐ»ÑÑÐ°Ñ ÑÐ°ÑÑÑ ÑÐ°Ð±ÐŸÑÑ Ð² Ð¿ÑÐŸÑÐµÑÑÐµ ÐžÐŒÐ¿ÐŸÑÑÐ° ÐŽÐµÐ»Ð°ÐµÑÑÑ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑÐŒÐž, Ð²ÑÐ·ÑÐ²Ð°ÐµÐŒÑÐŒÐž ÐŒÐŸÐŽÑÐ»ÐµÐŒ plugin. Ð­ÑÐŸÑ ÐŒÐŸÐŽÑÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐµÑ ÐºÐŸÐœÐ²ÐµÐ¹ÐµÑ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐ¹, ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÑ
+ Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐœ ÑÐ°ÐºÐ¶Ðµ ÐŸÐ±ÑÐ»ÑÐ¶ÐžÐ²Ð°ÐµÑ Ð·Ð°Ð¿ÐžÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð°ÑÑ
+ÐžÐ²Ð° Greenstone, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐŸÐ±ÑÐµÐºÑ document.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_build_process">
+<Title>
+<Text id="219">ÐÑÐŸÑÐµÑÑ build</Text>
+</Title>
+<Content>
+<Text id="220">Ð ÑÐµÑÐµÐœÐžÐµ Ð¿ÑÐŸÑÐµÑÑÐ° ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ ÑÐ¶Ð°ÑÐžÐµ ÑÐµÐºÑÑÐ°, Ð¿ÐŸ Ð¿ÐŸÐ»ÐœÐŸÐŒÑ ÑÐµÐºÑÑÑ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑÑ ÐžÐœÐŽÐµÐºÑÐ°ÑÐžÑ, ÐŸÐ¿ÐžÑÐ°ÐœÐœÐ°Ñ Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÐŸÐŒÐµ ÑÐŸÐ³ÐŸ, ÐœÐ° ÑÑÐŸÐŒ ÑÑÐ°Ð¿Ðµ ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²ÐµÑÑÑ Ðž Ð¿ÐŸÐŽÐºÐ»ÑÑÐ°ÐµÑÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÑÐŸÐŒ, ÐºÐ°Ðº ÑÐ¶Ðµ ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐœÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð±ÑÐŽÐµÑ Ð²ÑÐ³Ð»ÑÐŽÐµÑÑ Ð²ÐŸ Ð²ÑÐµÐŒÐžÑÐœÐŸÐ¹ Ð¿Ð°ÑÑÐžÐœÐµ -ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐŽÐ°ÐœÐœÑÐµ ÐŸ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ°Ñ
+ Ðž ÐžÐºÐŸÐœÐºÐ°Ñ
+, ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÑÐµ ÐŽÐ°ÐœÐœÑÐµ Ðž Ñ.ÐŽ. Buildcol.pl ÐžÐŒÐµÐµÑ ÐŒÐœÐŸÐ³ÐŸ ÐŸÐ¿ÑÐžÐ¹, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÑ
+ ÑÐŸÐ²ÐŒÐµÑÑÐœÐŸ Ñ import.pl, ÑÐŒ. Ð¢Ð°Ð±Ð»ÐžÑÑ <CrossRef target="Table" ref="options_for_the_import_and_build_processes"/>, Ðž ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÐœÐžÐºÐ°Ð»ÑÐœÑÑ
+, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐœÑÑ
+ Ð² Ð¢Ð°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="additional_options_for_the_build_process"/>.</Text>
+<Table id="additional_options_for_the_build_process">
+<Title>
+<Text id="221">ÐÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÑÐµ ÐŸÐ¿ÑÐžÐž ÐŽÐ»Ñ Ð¿ÑÐŸÑÐµÑÑÐ°</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="104">
+<Text id="222"><b>ÐÑÐ³ÑÐŒÐµÐœÑ</b></Text>
+</th>
+<th width="293">
+<Text id="223"><b>Ð€ÑÐœÐºÑÐžÑ</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="224"><i>-builddir</i></Text>
+</th>
+<th width="104">
+<Text id="225">ÐÐŒÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž</Text>
+</th>
+<th width="293">
+<Text id="226">ÐÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ, Ð³ÐŽÐµ Ð±ÑÐŽÐµÑ Ñ
+ÑÐ°ÐœÐžÑÑÑÑ ÑÐµÐ·ÑÐ»ÑÑÐ°Ñ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ (Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ: <i>GSDLHOME/collect/col_name/building</i>).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="227"><i>-index</i></Text>
+</th>
+<th width="104">
+<Text id="228">ÐÐœÐŽÐµÐºÑÐœÐŸÐµ ÐžÐŒÑ</Text>
+</th>
+<th width="293">
+<Text id="229">ÐÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÐžÐœÐŽÐµÐºÑÑ Ð¿ÑÐŸÑÐµÑÑÐ° ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ. ÐÐ°ÐœÐœÐ°Ñ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ '.Title) Ð¿ÑÐŸÑÐµÐŽÑÑÐ° Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ Ð¿ÑÐžÑÐ²Ð°ÐžÐ²Ð°ÐµÑ ÐžÐœÐŽÐµÐºÑÑ, ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÐœÑÐµ Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="230"><i>-allclassifications</i></Text>
+</th>
+<th width="104">
+<Text id="231">ÐÑÑÑÑÑÑÐ²ÑÐµÑ</Text>
+</th>
+<th width="293">
+<Text id="232">Ð Ð¿ÑÐŸÑÐµÑÑÐµ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ Ð¿ÑÐµÐŽÑÐ¿ÑÐµÐ¶ÐŽÐ°ÐµÑ ÑÐŽÐ°Ð»ÐµÐœÐžÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐ¹, ÐœÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐžÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÑ Ð¿ÐŸ Ð»ÐžÑÐµÑÐµ "X" Ð² Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐµ, Ð² ÑÐ»ÑÑÐ°Ðµ, ÐµÑÐ»Ðž ÑÐ°ÐŒ ÐœÐµÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÑÐµÐ¹ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº ÐœÐ°ÑÐžÐœÐ°ÐµÑÑÑ Ñ Ð»ÐžÑÐµÑÑ "X").</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="233"><i>-create_images</i></Text>
+</th>
+<th width="104">
+<Text id="234">ÐÑÑÑÑÑÑÐ²ÑÐµÑ</Text>
+</th>
+<th width="293">
+<Text id="235">ÐÐ²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÑÐŸÐ·ÐŽÐ°ÐµÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐžÐºÐŸÐœÐŸÐº (ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÑÐŸÐ¹ ÐŸÐ¿ÑÐžÐµÐ¹ Ñ Ð²Ð°Ñ ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ GIMP Ðž ÐŒÐŸÐŽÑÐ»Ñ Gimp Perl).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="236"><i>-mode</i></Text>
+</th>
+<th width="104">
+<Text id="237"><i>all</i>, <br/><i>compress_text</i>, <br/><i>infodb</i>, ÐžÐ»Ðž <br/><i>build index</i></Text>
+</th>
+<th width="293">
+<Text id="238">ÐÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ, ÑÑÐŸ ÐŽÐŸÐ»Ð¶ÐµÐœ ÑÐŽÐµÐ»Ð°ÑÑ Ð¿ÑÐŸÑÐµÑÑ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ (Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ all). All Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑ Ð¿ÐŸÐ»ÐœÐŸÐµ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÐµ, compress_text ÑÐŸÐ»ÑÐºÐŸ ÑÐ¶Ð°ÑÐžÐµ ÑÐµÐºÑÑÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, infodb ÑÐŸÐ·ÐŽÐ°ÐµÑ Ð±Ð°Ð·Ñ ÐŽÐ°ÐœÐœÑÑ
+ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž, ÐŸÑÐœÐŸÑÑÑÐµÐ¹ÑÑ Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž - ÐžÐŒÑ, ÑÐ°Ð¹Ð»Ñ, ÑÐ²ÑÐ·ÐœÑÐµ ÑÐ°Ð¹Ð»Ñ, ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÐ°Ñ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ Ðž Ñ.Ð¿., - build index -ÑÐŸÑÐŒÐžÑÑÐµÑ ÐžÐœÐŽÐµÐºÑÑ, ÑÐºÐ°Ð·Ð°ÐœÐœÑÐµ Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»ÐµÐºÑÐžÐž ÐžÐ»Ðž Ð² ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐµ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="239"><i>âno_text</i></Text>
+</th>
+<th width="104"/>
+<th width="293">
+<Text id="240">ÐÐµ Ñ
+ÑÐ°ÐœÐžÑ ÑÐ¶Ð°ÑÑÐ¹ ÑÐµÐºÑÑ. ÐÐ°ÐœÐœÐ°Ñ ÐŸÐ¿ÑÐžÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð² ÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ, ÐµÑÐ»Ðž Ð²Ñ Ñ
+ÐŸÑÐžÑÐµ ÐŒÐžÐœÐžÐŒÐžÐ·ÐžÑÐŸÐ²Ð°ÑÑ ÑÐ°Ð·ÐŒÐµÑ ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐœÑÑ
+ ÐžÐœÐŽÐµÐºÑÐŸÐ², Ð² ÑÐ»ÑÑÐ°Ðµ, ÐµÑÐ»Ðž Ð²Ñ ÐœÐ°ÐŒÐµÑÐµÐœÑ Ð²ÐŸ Ð²ÑÐµÐŒÑ Ð·Ð°Ð¿ÑÑÐºÐ° Ð²ÑÐµÐ³ÐŽÐ° Ð²ÑÐ²ÐŸÐŽÐžÑÑ ÐœÐ° ÑÐºÑÐ°Ðœ ÐŸÑÐžÐ³ÐžÐœÐ°Ð» ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Figure id="steps_in_the_build_process">
+<Title>
+<Text id="241">ÐÐŸÑÐ°Ð³ÐŸÐ²ÐŸÐµ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ Ð¿ÑÐŸÑÐµÑÑÐ° <i>build</i></Text>
+</Title>
+<File width="308" height="234" url="images/Dev_Fig_014.png"/>
+</Figure>
+<Text id="242">ÐÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="steps_in_the_build_process"/> Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐ° ÐŽÐžÐ°Ð³ÑÐ°ÐŒÐŒÐ° Ð¿ÐŸÑÐ°Ð³ÐŸÐ²ÐŸÐ³ÐŸ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ Ð¿ÑÐŸÑÐµÑÑÐ° buildcol.pl. ÐÐœÐŸÐ³ÐžÐµ ÐžÐ· ÑÐ°Ð³ÐŸÐ² ÐŸÑÐœÐŸÑÑÑÑÑ Ðž Ðº Ð¿ÑÐŸÑÐµÑÑÑ ÐžÐŒÐ¿ÐŸÑÑÐ°. ÐÐµÑÐ²ÑÐ¹ ÐŸÑÐ»ÐžÑÐžÑÐµÐ»ÑÐœÑÐ¹ ÑÐ°Ð³ - 4. ÐÐœ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑÑ ÑÐŸÐ»ÑÐºÐŸ Ð² ÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ, ÐµÑÐ»Ðž ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° ÐŸÐ¿ÑÐžÑ create_images. ÐÐ°ÑÐµÐŒ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ ÑÐŸÐ·ÐŽÐ°ÑÑÑÑ Ðž ÑÐµÐ³ÐžÑÑÑÐžÑÑÑÑÑÑ Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÑÐœÐºÑÐžÐµÐ¹ ÑÐºÑÐžÐ¿ÑÐ° buildcol.pl. ÐÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÑÑÐŸ ÑÑÐ°Ð±ÐŸÑÐ°Ð»ÐŸ, ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ Ðž ÑÐºÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÐœÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° GIMP (GNU Image Manipulation Program) Ðž ÐŒÐŸÐŽÑÐ»Ñ Gimp Perl. ÐÐŸÐŒÐžÐŒÐŸ ÑÑÐŸÐ³ÐŸ, Ð²Ñ ÐŽÐŸÐ»Ð¶ÐœÑ ÐžÐŒÐµÑÑ ÐŽÐŸÑÑÑÐ¿ Ñ Ð¿ÑÐ°Ð²ÐŸÐŒ Ð·Ð°Ð¿ÐžÑÐž (ÑÐ°Ðº Ð¶Ðµ, ÐºÐ°Ðº Ðž ÑÑÐµÐœÐžÑ) Ð² ÑÐ°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="243">ÐšÐ°Ð³ 5 ÑÐœÐ°ÑÐ°Ð»Ð° Ð¿ÑÐŸÐ²ÐµÑÑÐµÑ ÐœÐ°Ð»ÐžÑÐžÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð¿ÑÐŸÑÐµÐŽÑÑÑ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ. ÐÐµÐºÐŸÑÐŸÑÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÑÐµÐ±ÑÑÑ ÑÐ¿ÐµÑÐžÐ°Ð»ÑÐœÐŸÐ¹ ÑÐ°Ð·ÐŸÐ²ÐŸÐ¹ Ð¿ÑÐŸÑÐµÐŽÑÑÑ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ, Ð¿ÑÐž ÐºÐŸÑÐŸÑÐŸÐ¹ ÑÐºÐ°Ð·Ð°ÐœÐœÑÐ¹ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐŸÑÑÐ°Ð²ÐžÑÐµÐ»Ñ ÐŽÐŸÐ»Ð¶ÐµÐœ Ð±ÑÑÑ ÐŸÐ¿ÐžÑÐ°Ðœ, Ðž ÑÑÐ° Ð·Ð°Ð¿ÐžÑÑ (ÐžÐŒÑ ÑÐ°Ð¹Ð»Ð° ÐŽÐŸÐ»Ð¶ÐœÐŸ Ð²ÐºÐ»ÑÑÐ°ÑÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð¿ÑÐžÑÑÐ°Ð²ÐºÑ "builder") Ð¿ÐŸÐŒÐµÑÐµÐœÐ° Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž perllib. Mgbuilder, Ð² ÑÐ²ÐŸÑ ÐŸÑÐµÑÐµÐŽÑ, Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÐµÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ Ð·Ð°ÑÐ²Ð»ÐµÐœÐœÑÑ
+ ÑÐŸÑÑÐ°Ð²ÐžÑÐµÐ»ÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ° 5 ÑÐ°Ð³Ðµ ÑÐŸÑÑÐ°Ð²ÐžÑÐµÐ»Ñ (Ð»ÐžÐ±ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ, Ð»ÐžÐ±ÐŸ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž) ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑ ÐžÑÑ
+ÐŸÐŽÐœÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ, ÑÐ°ÐºÐžÐµ ÐºÐ°Ðº ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², Ð²ÐºÐ»ÑÑÐ°ÐµÐŒÑÑ
+ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐŽÐŸÐ»Ð¶ÐœÐ° Ð»Ðž Ð±ÑÑÑ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐ° Ð¿ÑÐµÐŽÑÐŽÑÑÐ°ÑÑ Ð²ÐµÑÑÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð³ÐŽÐµ ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž building Ðž archive.</Text>
+<Text id="244">ÐÐ° 6 ÑÐ°Ð³Ðµ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐºÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÑÐ¶Ð°Ñ Ðž Ð¿ÑÐŸÐžÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°Ðœ, ÐžÐºÐŸÐœÐºÐž Ðž Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐž Ð¿ÐŸÐŒÐµÑÐµÐœÑ Ð² ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐŸÐœÐœÑÑ Ð±Ð°Ð·Ñ ÐŽÐ°ÐœÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐŽÐ°ÐœÐœÑÐµ ÑÑÑÑÐºÑÑÑÐžÑÐŸÐ²Ð°ÐœÑ Ð¿ÑÐž Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ², Ð²Ð¿ÐŸÑÐ»ÐµÐŽÑÑÐ²ÐžÐž Ð²ÑÐ·ÑÐ²Ð°ÐµÐŒÑÑ
+ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑÐŒÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÐµÐŒÐž ÑÑÐžÐŒÐž ÑÐ°Ð³Ð°ÐŒÐž ÑÐ¿ÑÐ°Ð²Ð»ÑÐµÑ mgbuilder (ÐžÐ»Ðž ÑÐ¿ÐŸÐ»ÐœÐŸÐŒÐŸÑÐµÐœÐœÑÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹ ÐºÐŸÐŒÐ¿Ð°ÐœÐŸÐ²ÑÐžÐº), ÐºÐŸÑÐŸÑÑÐ¹, Ð² ÑÐ²ÐŸÑ ÐŸÑÐµÑÐµÐŽÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÐŽÐ»Ñ ÑÐ¶Ð°ÑÐžÑ Ðž ÐžÐœÐŽÐµÐºÑÐ°ÑÐžÐž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ MG ("ManÂ¬aging Gigabytes," ÑÐŒ. Witten et al., 1999).</Text>
+<Text id="245">Ð§Ð°ÑÑÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÑ ÐŸÐ¿ÑÐžÐµÐ¹ mode, ÐŸÐŽÐœÐ°ÐºÐŸ ÐŒÐŸÐ¶ÐœÐŸ ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÑÑ Ð²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÑÐµÐ¶ÐžÐŒ "Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ" - ÑÐ¶Ð°ÑÑ ÑÐµÐºÑÑ, Ð¿ÑÐŸÐžÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐµÐ³ÐŸ, ÑÐŸÐŽÐ°ÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐŸÐœÐœÑÑ Ð±Ð°Ð·Ñ ÐŽÐ°ÐœÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="246">ÐÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐŽÐŸÑÑÑÐ¿Ð° Ðº ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐµÑÐµÐ· ÑÐµÑÑ ÐÐœÑÐµÑÐœÐµÑ Ð²Ñ ÐŽÐŸÐ»Ð¶ÐœÑ Ð¿ÐµÑÐµÐŒÐµÑÑÐžÑÑ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž building Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ index. ÐÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐœÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐ° ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž inÂ¬dex, ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð±ÐŸÐ»ÑÑÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐŒÐŸÐ¶ÐµÑ ÐŽÐ»ÐžÑÑÑÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÐ°ÑÐŸÐ², Ð° ÑÐŸ Ðž ÐŽÐœÐµÐ¹. ÐÐ°Ð¶ÐœÐŸÐ¹ ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÑÑ Ð¿ÑÐŸÑÐµÑÑÐ° ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÑÐ²Ð»ÑÐµÑÑÑ ÑÐŸ, ÑÑÐŸ ÐŸÐœ ÐœÐµ Ð²ÐœÐŸÑÐžÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÐ¹ Ð² ÑÑÑÐµÑÑÐ²ÑÑÑÑÑ ÐºÐŸÐ¿ÐžÑ ÐŽÐŸ ÑÐµÑ
+ Ð¿ÐŸÑ, Ð¿ÐŸÐºÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐœÐµ Ð±ÑÐŽÐµÑ ÐŸÐºÐŸÐœÑÐ°ÑÐµÐ»ÑÐœÐŸ ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐ°.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="greenstone_archive_documents">
+<Title>
+<Text id="247">ÐÑÑ
+ÐžÐ² ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Greenstone</Text>
+</Title>
+<Content>
+<Text id="248">ÐÑÐµ ÐžÑÑ
+ÐŸÐŽÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ, Ð²ÐœÐŸÑÐžÐŒÑÐµ Ð² ÑÐžÑÑÐµÐŒÑ Greenstone ÐºÐŸÐœÐ²ÐµÑÑÐžÑÑÑÑÑÑ Ð² ÑÐŸÑÐŒÐ°Ñ, ÐžÐ·Ð²ÐµÑÑÐœÑÐ¹ ÐºÐ°Ðº Greenstone Archive Format (Ð€ÐŸÑÐŒÐ°Ñ ÐÑÑ
+ÐžÐ²Ð° Greenstone). Ð­ÑÐŸ ÑÐŸÑÐŒÐ°Ñ XML, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐ°Ð·ÐŒÐµÑÐ°ÐµÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð¿ÐŸ ÑÐ°Ð·ÐŽÐµÐ»Ð°ÐŒ Ðž Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÑ ÑÐµÐ¶ÐžÐŒ ÑÐ°Ð±ÐŸÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐœÐ° ÑÑÐŸÐ²ÐœÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÐžÐ»Ðž ÑÐ°Ð·ÐŽÐµÐ»Ð°. ÐÐ°ÐŒ ÐœÐµ Ð¿ÑÐžÐŽÐµÑÑÑ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ ÑÐ°Ð¹Ð»Ñ Ð°ÑÑ
+ÐžÐ²Ð° Greenstone Ð²ÑÑÑÐœÑÑ, Ñ.Ðº. ÑÑÐŸÐ¹ ÑÐ°Ð±ÐŸÑÐŸÐ¹ Ð·Ð°ÐœÐžÐŒÐ°ÐµÑÑÑ ÑÐ¿ÐµÑÐžÐ°Ð»ÑÐœÐŸÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÐŸÐ¿ÐžÑÐ°ÐœÐœÐŸÐµ Ð² ÑÐ»ÐµÐŽÑÑÑÐµÐ¹ Ð³Ð»Ð°Ð²Ðµ. ÐÐŽÐœÐ°ÐºÐŸ, Ñ.Ðº. ÑÑÐŸ ÐŒÐŸÐ¶ÐµÑ Ð¿ÐŸÐŒÐŸÑÑ Ð² Ð¿ÐŸÐœÐžÐŒÐ°ÐœÐžÐž ÑÐŸÑÐŒÐ°ÑÐ° ÑÐ°Ð¹Ð»ÐŸÐ² ÑÐžÑÑÐµÐŒÑ Greenstone, ÐŒÑ ÑÐµÑÐžÐ»Ðž Ð¿ÐŸÐŒÐµÑÑÐžÑÑ ÑÑÐŸ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÐœÐžÐ¶Ðµ.</Text>
+<Text id="249">Ð XML ÑÑÐ³Ðž ÑÐ°Ð·ÐŒÐµÑÐºÐž Ð·Ð°ÐºÐ»ÑÑÐµÐœÑ Ð² Ð·ÐœÐ°ÐºÐž ÐŸ. Ð€ÐŸÑÐŒÐ°Ñ Ð°ÑÑ
+ÐžÐ²Ð° Greenstone Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÑÐµÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ, ÐœÐ°Ñ
+ÐŸÐŽÑÑÐžÐµÑÑ Ð² ÑÐŸÑÐŒÐ°ÑÐµ HTML Ðž ÐŽÑ. Ð²ÑÑÐ°Ð²Ð»ÑÑ ÑÐžÐŒÐ²ÐŸÐ»Ñ &lt;, &gt;, ÐžÐ»Ðž " Ð² ÐžÑÑ
+ÐŸÐŽÐœÑÐ¹ ÑÐµÐºÑÑ Ðž ÐžÐ·Ð±ÐµÐ³Ð°Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÑ
+ ÑÑÐ»ÐŸÐ²ÐžÐ¹ &amp;lt;, &amp;gt; Ðž &amp;quot;.</Text>
+<Figure id="greenstone_archive_format">
+<Title>
+<Text id="250">Ð€ÐŸÑÐŒÐ°Ñ Ð°ÑÑ
+ÐžÐ²Ð° Greenstone: Ð°) Document Type DefiniÂ¬tion /ÐÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐµ ÑÐžÐ¿Ð°
+ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° (DTD); Ð±)  ÐÑÐžÐŒÐµÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°</Text>
+<SubTitle>
+<Text id="251">(a)</Text>
+</SubTitle>
+</Title>
+<CodeLine>&lt;!DOCTYPE GreenstoneArchive [</CodeLine>
+<CodeLine>Â Â Â &lt;!ELEMENT Section (Description,Content,Section*)&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;!ELEMENT Description (Metadata*)&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;!ELEMENT Content (#PCDATA)&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;!ELEMENT Metadata (#PCDATA)&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;ATTLIST Metadata name CDATA #REQUIRED&gt;</CodeLine>
+<CodeLine>]&gt;</CodeLine>
+</Figure>
+<Figure id="greenstone_archive_format_1">
+<Title>
+<Text id="252"/>
+<SubTitle>
+<Text id="253">(b)</Text>
+</SubTitle>
+</Title>
+<CodeLine>&lt;?xml version="1.0"?&gt;</CodeLine>
+<CodeLine>&lt;!DOCTYPE GreenstoneArchive SYSTEM</CodeLine>
+<CodeLine>"http://greenstone.org/dtd/GreenstoneArchive/1.0/GreenstoneArchive.dtd" &gt;</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Metadata name= "gsdlsourcefilename"&gt;ec158e.txt&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Metadata name= "Title"&gt;Freshwater Resources in Arid Lands&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Metadata name= "Identifier"&gt;HASH0158f56086efffe592636058&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Metadata name= "gsdlassocfile"&gt;cover.jpg:image/jpeg:&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Metadata name= "gsdlassocfile"&gt;p07a.png:image/png:&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â &lt;Metadata name= "Title"&gt;Preface&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Content&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <i>This is the text of the preface</i>
+</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;/Content&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;/Section&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â &lt;Metadata name= "Title"&gt;First and only chapter&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &lt;Metadata name= "Title"&gt;Part 1&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â &lt;Content&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <i>This is the first part of the first and only chapter</i>
+</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â &lt;/Content&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;/Section&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;Section&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â &lt;Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â &lt;Metadata name= "Title"&gt;Part 2&lt;/Metadata&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â &lt;/Description&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â &lt;Content&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <i>This is the second part of the first and only chapter</i>
+</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â Â Â &lt;/Content&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â Â &lt;/Section&gt;</CodeLine>
+<CodeLine>Â Â Â &lt;/Section&gt;</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+</Figure>
+<Text id="254">ÐÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="greenstone_archive_format"/> Ð²Ð°ÑÐµÐŒÑ Ð²ÐœÐžÐŒÐ°ÐœÑ Ð¿ÑÐµÐŽÐ»ÐŸÐ¶ÐµÐœ Document Type Definition/ ÐÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐµ ÑÐžÐ¿Ð° ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° (DTD) ÑÐ·ÑÐºÐ° XML ÐŽÐ»Ñ ÑÐŸÑÐŒÐ°ÑÐ° Ð°ÑÑ
+ÐžÐ²Ð° GreenÂ¬stone. ÐÐ·ÐœÐ°ÑÐ°Ð»ÑÐœÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑ ÑÐ°Ð·Ð±ÐžÐ²Ð°ÐµÑÑÑ ÐœÐ° Sections (ÑÐµÐºÑÐžÐž ÐžÐ»Ðž ÑÐ°Ð·ÐŽÐµÐ»Ñ), ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð²Ð»ÐŸÐ¶ÐµÐœÐœÑÐŒÐž. ÐÐ°Ð¶ÐŽÐ°Ñ Section ÐžÐŒÐµÐµÑ Description (ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ) ÐºÐŸÑÐŸÑÐŸÐµ ÑÐŸÐŽÐµÑÐ¶ÐžÑ 0 ÐžÐ»Ðž Ð±ÐŸÐ»ÐµÐµ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² Metadata, Ð° ÑÐ°ÐºÐ¶Ðµ ConÂ¬tent (ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐµÐ»ÑÐœÑÑ ÑÐ°ÑÑÑ), ÐºÐŸÑÐŸÑÐ°Ñ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÑÐ°Ð²ÐœÐ° ÐœÑÐ»Ñ, Ð° ÑÐ°ÐºÑÐžÑÐµÑÐºÐž ÑÑÐŸ ÑÐ° ÑÐ°ÑÑÑ, Ð³ÐŽÐµ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. ÐÐ°Ð¶ÐŽÐŸÐŒÑ ÑÐ»ÐµÐŒÐµÐœÑÑ Metadata ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ ÐžÐŒÑ Ð°ÑÑÐžÐ±ÑÑÐ° Ðž ÑÐµÐºÑÑÐŸÐ²ÑÐµ ÐŽÐ°ÐœÐœÑÐµ. Ð XML, PCDATA ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ "parsed character ÑÐ«:Ð°"(Ð°ÐœÐ°Ð»ÐžÐ·ÐžÑÑÐµÐŒÑÐµ ÑÐžÐŒÐ²ÐŸÐ»ÑÐœÑÐµ ÐŽÐ°ÐœÐœÑÐµ): Ð² ÐŸÑÐœÐŸÐ²ÐœÐŸÐŒ ÑÐµÐºÑÑ.</Text>
+<Text id="255">Ð ÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="greenstone_archive_format_1"/> ÐŽÐµÐŒÐŸÐœÑÑÑÐžÑÑÐµÑ Ð¿ÑÐžÐŒÐµÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ð² ÑÑÐŸÐŒ ÑÐŸÑÐŒÐ°ÑÐµ, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÑÑÐžÐ¹ ÑÐŸÐ±ÐŸÐ¹ ÐœÐµÐ±ÐŸÐ»ÑÑÑÑ ÐºÐœÐžÐ³Ñ Ñ ÐŽÐ²ÑÐŒÑ ÑÐ²ÑÐ·ÐœÑÐŒÐž ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑÐŒÐž. Ð­ÑÐ° ÐºÐœÐžÐ³Ð° ÑÐŸÑÑÐŸÐžÑ ÐžÐ· ÐŽÐ²ÑÑ
+ ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐ², ÐœÐ°Ð·Ð²Ð°ÐœÐœÑÑ
+ Preface Ðž First and only chapter, ÐºÐŸÑÐŸÑÐ°Ñ ÑÐŸÑÑÐŸÐžÑ ÐžÐ· ÐŽÐ²ÑÑ
+ Ð¿ÐŸÐŽÑÐ°Ð·ÐŽÐµÐ»ÐŸÐ². ÐÐ±ÑÐ°ÑÐžÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ ÐœÐ° ÑÐŸ, ÑÑÐŸ ÐœÐµÑ ÐœÐžÐºÐ°ÐºÐŸÐ³ÐŸ Ð¿ÐŸÐœÑÑÐžÑ "chapter": ÐŽÐ°ÐœÐœÑÐ¹ ÑÐ°Ð·ÐŽÐµÐ» Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœ Ð¿ÑÐŸÑÑÐŸ ÐºÐ°Ðº ÑÐ°Ð·ÐŽÐµÐ» Ð²ÐµÑÑ
+ÐœÐµÐ³ÐŸ ÑÑÐŸÐ²ÐœÑ.</Text>
+<Table id="greenstone_archive_format_values">
+<Title>
+<Text id="256">Ð€ÐŸÑÐŒÐ°Ñ Ð°ÑÑ
+ÐžÐ²Ð° Greenstone: ÐÐœÐ°ÑÐµÐœÐžÑ ÐŽÐ»Ñ Ð°ÑÑÐžÐ±ÑÑÐ° <i>name</i> ÑÑÐ³Ð° <i>Metadata</i></Text>
+</Title>
+<TableContent>
+<tr>
+<th width="130">
+<Text id="257"><i>gsdlsourcefilename</i></Text>
+</th>
+<th width="400">
+<Text id="258">ÐÑÑ
+ÐŸÐŽÐœÑÐ¹ ÑÐ°Ð¹Ð», ÐžÐ· ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»ÐŸÐŒ Ð°ÑÑ
+ÐžÐ²Ð° Greenstone Ð±ÑÐ» ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°Ðœ</Text>
+</th>
+</tr>
+<tr>
+<th width="130">
+<Text id="259"><i>gsdlassocfile</i></Text>
+</th>
+<th width="400">
+<Text id="260">Ð€Ð°Ð¹Ð», ÑÐ²ÑÐ·Ð°ÐœÐœÑÐ¹ Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐŒ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÐ°Ð¹Ð» ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ)</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="261">ÐÑÐºÑÑÐ²Ð°ÑÑÐžÐ¹ ÑÑÐ³ <i>&lt;Section&gt;</i> ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ ÐœÐ°ÑÐ°Ð»ÐŸ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÐ°Ð·ÐŽÐµÐ»Ð° ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, Ð°Ð° Ð·Ð°ÐºÑÑÐ²Ð°ÑÑÐžÐ¹ ÑÑÐ³ <i>&lt;/Section&gt;</i> - ÐºÐŸÐœÐµÑ ÑÐ°Ð·ÐŽÐµÐ»Ð°. ÐÐ° ÐºÐ°Ð¶ÐŽÑÐŒ ÑÑÐ³ÐŸÐŒ <i>&lt;Section&gt;</i> ÑÐ»ÐµÐŽÑÐµÑ ÑÐ°Ð·ÐŽÐµÐ» <i>&lt;Description&gt;</i>. Ð Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐŽÐ°ÐœÐœÐŸÐ³ÐŸ ÑÐ°Ð·ÐŽÐµÐ»Ð° ÐœÐ°Ñ
+ÐŸÐŽÑÑÑÑ ÑÐ»ÐµÐŒÐµÐœÑÑ <i>&lt;Metadata&gt;</i>. Ð¢Ð°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ, ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐ²ÑÐ·Ð°ÐœÑ Ñ ÐžÐœÐŽÐžÐ²ÐžÐŽÑÐ°Ð»ÑÐœÑÐŒÐž ÑÐ°Ð·ÐŽÐµÐ»Ð°ÐŒÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. ÐÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ ÐžÐ· ÐœÐžÑ
+ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐžÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÐ°ÐºÐžÑ
+ ÐºÐ°Ðº <i>&lt;Ð¢ÐšÐµ&gt;</i>. ÐÐ²Ð° Ð·ÐœÐ°ÑÐµÐœÐžÑ Ð°ÑÑÐžÐ±ÑÑÐ° name Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÑ Ð² Ð¢Ð°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="greenstone_archive_format_values"/> Ðž ÑÐ¿ÐµÑÐžÐ°Ð»ÑÐœÐŸ ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÐ°ÐœÑ Greenstone; Ð²ÑÐµ ÐŸÑÑÐ°Ð»ÑÐœÑÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÑÑ ÑÐŸÐ±ÐŸÐ¹ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, Ð¿ÑÐžÐ»Ð°Ð³Ð°ÐµÐŒÑÐµ Ðº ÐŽÐ°ÐœÐœÐŸÐŒÑ ÑÐ°Ð·ÐŽÐµÐ»Ñ. </Text>
+<Text id="262">Ð ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÑÐ°Ð·Ð±ÐžÑÑ ÐœÐ° ÐŸÑÐŽÐµÐ»ÑÐœÑÐµ ÑÑÑÐ°ÐœÐžÑÑ. ÐÐœÐž ÐŸÐ·ÐœÐ°ÑÐµÐœÑ ÐºÐ°Ðº ÑÐ°Ð·ÐŽÐµÐ»Ñ. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÐºÐœÐžÐ³Ð° ÐŒÐŸÐ¶ÐµÑ ÐžÐŒÐµÑÑ ÑÐ°Ð·ÐŽÐµÐ»Ñ Ð¿ÐµÑÐ²ÐŸÐ³ÐŸ ÑÑÐŸÐ²ÐœÑ, ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑ Ð³Ð»Ð°Ð²Ð°ÐŒ, Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÐžÐ· ÐºÐŸÑÐŸÑÑÑ
+ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐŸ ÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐŸ "ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐ²", ÐºÐŸÑÐŸÑÑÐµ ÑÐ°ÐºÑÐžÑÐµÑÐºÐž ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑ ÐŸÑÐŽÐµÐ»ÑÐœÑÐŒ ÑÑÑÐ°ÐœÐžÑÐ°ÐŒ Ð³Ð»Ð°Ð²Ñ.</Text>
+<Subsection id="document_metadata">
+<Title>
+<Text id="263">ÐÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°</Text>
+</Title>
+<Content>
+<Text id="264">ÐÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐŸÐŽÐµÑÐ¶Ð°Ñ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸÐ¿ÐžÑÐ°ÑÐµÐ»ÑÐœÐŸÐ³ÐŸ Ñ
+Ð°ÑÐ°ÐºÑÐµÑÐ°, ÑÐ°ÐºÑÑ ÐºÐ°Ðº ÐŽÐ°ÐœÐœÑÐµ ÐŸÐ± Ð°Ð²ÑÐŸÑÐµ, Ð·Ð°Ð³Ð»Ð°Ð²ÐžÐµ, ÐŽÐ°ÑÑ, ÐºÐ»ÑÑÐµÐ²ÑÐµ ÑÐ»ÐŸÐ²Ð° Ðž Ñ.ÐŽ., ÐºÐ°ÑÐ°ÑÑÑÑÑÑ ÐºÐŸÐœÐºÑÐµÑÐœÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. Ð, ÐºÐ°Ðº Ð±ÑÐ»ÐŸ ÑÐ¶Ðµ ÑÐºÐ°Ð·Ð°ÐœÐŸ Ð²ÑÑÐµ, ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ñ
+ÑÐ°ÐœÑÑÑÑ Ð²ÐŒÐµÑÑÐµ Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐŒ. ÐÐŸÑÐŒÐŸÑÑÐµÐ² ÐœÐ° ÑÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="greenstone_archive_format"/>, Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐ²ÐžÐŽÐµÑÑ, ÑÑÐŸ ÑÑÐ³ &lt;ÐÐµÐ³Ð°Ð¹?Ð°Ð³Ð°&gt; ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÑÐžÐ¿Ð° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðž Ð¿ÑÐžÑÐ²Ð°ÐžÐ²Ð°ÐµÑ ÐžÐŒ Ð·ÐœÐ°ÑÐµÐœÐžÐµ. ÐÐ±ÑÐ°ÑÐžÐŒÑÑ ÐŽÐ»Ñ Ð¿ÑÐžÐŒÐµÑÐ° Ðº ÑÑÑÐŸÐºÐµ &lt;Metadataname='"Etle "&gt;First and only chap-ter&lt;/Metadata&gt; ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="greenstone_archive_format_1"/> - Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÑÐ²Ð»ÑÐµÑÑÑ ÑÐ°ÑÑÑÑ ÑÐ²ÑÐ·Ð°ÐœÐœÑÑ
+ Ñ ÐœÐžÐŒ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. ÐÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÑÐžÐ¿ÐŸÐ² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð±ÑÐ» ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ðœ Dublin Core metadata standard (Dublin Core, 2001, Weibel, 1999; Thiele, 1997).</Text>
+<Text id="265">Ð¢Ð°Ð±Ð»ÐžÑÐ° <CrossRef target="Table" ref="dublin_core_metadata_standard"/> ÐŽÐµÐŒÐŸÐœÑÑÑÐžÑÑÐµÑ, ÐºÐ°ÐºÐžÐµ ÐžÐ· ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÑ
+ ÑÐžÐ¿ÐŸÐ², ÐŸÑÐŒÐµÑÐµÐœÐœÑÐµ Ð·Ð²ÐµÐ·ÐŽÐŸÑÐºÐ°ÐŒÐž, ÐŽÐŸÑÑÑÐ¿ÐœÑ ÑÐµÐ³ÐŸÐŽÐœÑ Ðº ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÐœÐ° Ð²ÐµÐ±-ÑÐ°Ð¹ÑÐµ New Zealand Digital Library. ÐÑÐ»Ðž ÐœÐµÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž Ð¿ÐŸÐŽÐŸÐ±ÑÐ°ÑÑ ÑÐžÐ¿, ÑÐŸÑÐœÐŸ ÐŸÐ¿ÐžÑÑÐ²Ð°ÑÑÐžÐ¹ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, ÑÐŸ ÐŒÐŸÐ¶ÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŽÑÑÐ³ÐŸÐ¹ ÑÐžÐ¿, ÐœÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÐ¹ Ð² Dublin Core metadata standard. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, Ð² ÐŽÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐŸÐŽÐµÑÐ¶ÐžÑÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ how to Ðž Magazine.</Text>
+<Table id="dublin_core_metadata_standard">
+<Title>
+<Text id="266">Dublin Core metadata standard</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="133">
+<Text id="267"><b>ÐÐŒÑ</b></Text>
+</th>
+<th width="94">
+<Text id="268"><b>ÐÐŸÐŽÑÑÐ³ <br/> ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</b></Text>
+</th>
+<th width="305">
+<Text id="269"><b>ÐÐ¿ÐžÑÐ°ÐœÐžÐµ</b></Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="270">*Title</Text>
+</th>
+<th width="94">
+<Text id="271">Title</Text>
+</th>
+<th width="305">
+<Text id="272">ÐÐŒÑ ÑÐµÑÑÑÑÐ°</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="273">*Creator</Text>
+</th>
+<th width="94">
+<Text id="274"><i>Creator</i></Text>
+</th>
+<th width="305">
+<Text id="275">ÐÐžÑÐŸ, ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸÐµ Ð·Ð° ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐ³ÐŸ ÑÐµÑÑÑÑÐ°</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="276">*Subject and keywords</Text>
+</th>
+<th width="94">
+<Text id="277"><i>Subject</i></Text>
+</th>
+<th width="305">
+<Text id="278">Ð¢ÐµÐŒÐ° ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐ³ÐŸ ÑÐµÑÑÑÑÐ°</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="279">*Description</Text>
+</th>
+<th width="94">
+<Text id="280"><i>Description</i></Text>
+</th>
+<th width="305">
+<Text id="281">ÐÐ¿ÐžÑÐ°ÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÐµÑÑÑÑÐ°</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="282">*Publisher</Text>
+</th>
+<th width="94">
+<Text id="283"><i>Publisher</i></Text>
+</th>
+<th width="305">
+<Text id="284">ÐÐžÑÐŸ, ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸÐµ Ð·Ð° ÐŽÐŸÑÑÑÐ¿ Ðº ÑÐµÑÑÑÑÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="285">Contributor</Text>
+</th>
+<th width="94">
+<Text id="286"><i>Contributor</i></Text>
+</th>
+<th width="305">
+<Text id="287">ÐÐžÑÐŸ, ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸÐµ Ð·Ð° Ð¿ÐŸÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐ³ÐŸ ÑÐµÑÑÑÑÐ°</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="288">*Date</Text>
+</th>
+<th width="94">
+<Text id="289"><i>Date</i></Text>
+</th>
+<th width="305">
+<Text id="290">ÐÐ°ÑÐ° Ð¿ÑÐ±Ð»ÐžÐºÐ°ÑÐžÐž ÑÐµÑÑÑÑÐ°, Ð»ÐžÐ±ÐŸ ÐŽÑÑÐ³Ð°Ñ Ð²Ð°Ð¶ÐœÐ°Ñ ÐŽÐ°ÑÐ°, ÑÐ²ÑÐ·Ð°ÐœÐœÐ°Ñ Ñ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÑÐŒ ÑÐµÑÑÑÑÐ°</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="291">Resource type</Text>
+</th>
+<th width="94">
+<Text id="292"><i>Type</i></Text>
+</th>
+<th width="305">
+<Text id="293">Ð¥Ð°ÑÐ°ÐºÑÐµÑ ÐžÐ»Ðž Ð¶Ð°ÐœÑ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐ³ÐŸ ÑÐµÑÑÑÑÐ°</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="294">Format</Text>
+</th>
+<th width="94">
+<Text id="295"><i>Format</i></Text>
+</th>
+<th width="305">
+<Text id="296">Ð€ÐžÐ·ÐžÑÐµÑÐºÐŸÐµ ÐžÐ»Ðž ÑÐžÑÑÐŸÐ²ÐŸÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÑÐµÑÑÑÑÐ°</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="297">*Resource identifier</Text>
+</th>
+<th width="94">
+<Text id="298"><i>Identifier</i></Text>
+</th>
+<th width="305">
+<Text id="299">ÐÐŽÐœÐŸÐ·ÐœÐ°ÑÐœÐ°Ñ ÑÑÑÐ»ÐºÐ° ÐœÐ° ÑÐµÑÑÑÑ ÑÑÐŸ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑ ÐŸÐ±ÑÐµÐºÑÐ° ÐžÐ»Ðž OID</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="300">*Source</Text>
+</th>
+<th width="94">
+<Text id="301"><i>Source</i></Text>
+</th>
+<th width="305">
+<Text id="302">Ð¡ÑÑÐ»ÐºÐ° ÐœÐ° ÐžÑÑÐŸÑÐœÐžÐº, ÐžÐ· ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ Ð±ÑÐ» Ð¿ÐŸÐ»ÑÑÐµÐœ ÑÐµÑÑÑÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="303">*Language</Text>
+</th>
+<th width="94">
+<Text id="304"><i>Language</i></Text>
+</th>
+<th width="305">
+<Text id="305">Ð¯Ð·ÑÐº ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐ³ÐŸ ÑÐµÑÑÑÑÐ°</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="306">Relation</Text>
+</th>
+<th width="94">
+<Text id="307"><i>Relation</i></Text>
+</th>
+<th width="305">
+<Text id="308">Ð¡ÑÑÐ»ÐºÐ° ÐœÐ° ÑÐ²ÑÐ·ÐœÑÐ¹ ÑÐµÑÑÑÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="309">*Coverage</Text>
+</th>
+<th width="94">
+<Text id="310"><i>Coverage</i></Text>
+</th>
+<th width="305">
+<Text id="311">ÐÐ±Ð»Ð°ÑÑÑ ÐŸÑ
+Ð²Ð°ÑÐ° ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐ³ÐŸ ÑÐµÑÑÑÑÐ°</Text>
+</th>
+</tr>
+<tr>
+<th width="133">
+<Text id="312">Rights</Text>
+</th>
+<th width="94">
+<Text id="313"><i>Rights</i></Text>
+</th>
+<th width="305">
+<Text id="314">ÐÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ Ð¿ÑÐ°Ð²Ðµ Ð²Ð»Ð°ÐŽÐµÐœÐžÑÐž ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÐµÐœÐžÑ ÑÐµÑÑÑÑÐ° management</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+<Subsection id="inside_greenstone_archive_documents">
+<Title>
+<Text id="315">Inside Greenstone archive documents</Text>
+</Title>
+<Content>
+<Text id="316">Within a single document, the Greenstone archive format imposes a limited amount of structure. Documents are divided into paragraphs. They can be split hierarchically into sections and subsections; these may be nested to any depth. Each document has an associated Object Identifier or OIDâthese are extended to identify sections and subsections by appending section and subsection numbers, separated by periods, to the document's OID. For example, subsection 3 of section 2 of document HASHa7 is referred to as HASHa7.2.3.</Text>
+<Text id="317">When you read a book in a Greenstone collection, the section hierarchy is manifested in the table of contents of the book. For example, books in the Demo collection have a hierarchical table of contents showing chapters, sections, and subsections, as illustrated in Figure <CrossRef target="Figure" ref="hierarchical_structure_in_the_demo_collection"/>. Documents in the Computer Science Technical Reports collection do not have a hierarchical subsection structure, but each document is split into pages and you can browse around the pages of a retrieved document. Chapters, sections, subsections, and pages are all implemented simply as âsectionsâ within the document.</Text>
+<Figure id="hierarchical_structure_in_the_demo_collection">
+<Title>
+<Text id="318">ÐÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐ°Ñ ÑÑÑÑÐºÑÑÑÐ° ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+<SubTitle>
+<Text id="318a">(a)</Text>
+</SubTitle>
+</Title>
+<File width="373" height="251" url="images/Dev_Fig_015a.gif"/>
+</Figure>
+<Figure id="hierarchical_structure_in_the_demo_collection_1">
+<Title>
+<Text id="318b">ÐÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐ°Ñ ÑÑÑÑÐºÑÑÑÐ° ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+<SubTitle>
+<Text id="318c">(b)</Text>
+</SubTitle>
+</Title>
+<File width="373" height="251" url="images/Dev_Fig_015b.gif"/>
+</Figure>
+<Text id="319">Ð¡ÑÑÑÐºÑÑÑÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÑÐ°ÐºÐ¶Ðµ ÐžÐœÐŽÐµÐºÑÐžÑÑÐµÑÑÑ Ðž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ Ð¿ÐŸÐžÑÐºÐ°. ÐÐŽÐµÑÑ ÑÑÑÐµÑÑÐ²ÑÐµÑ 3 ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÑ
+ ÑÑÐŸÐ²ÐœÑ ÐžÐœÐŽÐµÐºÑÐ°ÑÐžÐž: <i>document</i>, <i>section</i> <i>^paragraph</i>, Ñ
+ÐŸÑÑ Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ðž ÐœÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑ Ð²ÑÐµ ÑÑÐž ÑÑÐŸÐ²ÐœÑ ÐŽÐ»Ñ ÐžÐœÐŽÐµÐºÑÐ°ÑÐžÐž. ÐÐœÐŽÐµÐºÑ document ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ð¿ÐŸÐ»ÐœÑÐ¹ ÑÐµÐºÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° - Ð²Ñ Ð¿ÐŸÐ»ÑÐ·ÑÐµÑÐµÑÑ ÐžÐŒ ÐŽÐ»Ñ Ð¿ÐŸÐžÑÐºÐ° Ð²ÑÐµÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŽÐµÑÐ¶Ð°Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐ¹ ÐœÐ°Ð±ÐŸÑ ÑÐ»ÐŸÐ² (ÑÐ»ÐŸÐ²Ð° ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐ°ÑÑÐµÑÐœÑ Ð¿ÐŸ Ð²ÑÐµÐŒÑ ÑÐµÐºÑÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°). ÐÑÐž ÑÐŸÐ·ÐŽÐ°ÐœÐžÐž ÐžÐœÐŽÐµÐºÑÐ° secÂ¬tion ÐžÐœÐŽÐµÐºÑÐžÑÑÐµÑÑÑ ÐºÐ°Ð¶ÐŽÐ°Ñ Ð¿ÐŸÑÑÐžÑ ÑÐµÐºÑÑÐ° ÐŸÑ ÐŸÐŽÐœÐŸÐ³ÐŸ ÑÑÐ³Ð° &lt;Section&gt; ÐŽÐŸ Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÑ ÑÐ»ÐµÐŽÑÑÑÐµÐ³ÐŸ ÑÑÐ³Ð° &lt;Section&gt;. Ð¢Ð°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ, Ð³Ð»Ð°Ð²Ð°, ÑÑÐ°Ð·Ñ Ð¶Ðµ ÐœÐ°ÑÐžÐœÐ°ÑÑÐ°ÑÑÑ Ñ ÐœÐŸÐ²ÐŸÐ³ÐŸ ÑÐ°Ð·ÐŽÐµÐ»Ð°, ÑÐŸÐ·ÐŽÐ°ÑÑ Ð¿ÑÑÑÐŸÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ Ð¿ÑÐž ÐžÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐž. Ð Ð°Ð·ÐŽÐµÐ»Ñ Ðž Ð¿ÐŸÐŽÑÐ°Ð·ÐŽÐµÐ»Ñ ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÑÑÑÑ Ð¿ÐŸÐŽÐŸÐ±ÐœÑÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ: ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐ°Ñ ÑÑÑÑÐºÑÑÑÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÑÐ³Ð»Ð°Ð¶ÐžÐ²Ð°ÐµÑÑÑ Ñ ÑÐµÐ»ÑÑ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ Ð¿ÐŸÐžÑÐºÐŸÐ²ÑÑ
+ ÐžÐœÐŽÐµÐºÑÐŸÐ². ÐÑÐž ÐžÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐž ÐœÐ° ÑÑÐŸÐ²ÐœÐµ Ð¿Ð°ÑÐ°Ð³ÑÐ°ÑÐŸÐ² ÐºÐ°Ð¶ÐŽÑÐ¹ Ð¿Ð°ÑÐ°Ð³ÑÐ°Ñ ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°ÐµÑÑÑ ÐºÐ°Ðº ÑÐ°ÐŒÐŸÑÑÐŸÑÑÐµÐ»ÑÐœÑÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ, ÑÑÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð² ÐŽÐ°Ð»ÑÐœÐµÐ¹ÑÐµÐŒ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ Ð¿ÑÐŸÐ²ÐµÐŽÐµÐœÐžÑ Ð±ÐŸÐ»ÐµÐµ ÑÑÐŸÐºÑÑÐžÑÐŸÐ²Ð°ÐœÐœÐŸÐ³ÐŸ Ð¿ÐŸÐžÑÐºÐ°. </Text>
+<Text id="320">ÐÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐµ ÐŒÐµÐœÑ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="hierarchical_structure_in_the_demo_collection_1"/> ÐœÐ°Ð³Ð»ÑÐŽÐœÐŸ ÐŽÐµÐŒÐŸÐœÑÑÑÐžÑÑÐµÑ Ð¿ÐŸÐžÑÐºÐŸÐ²ÑÐµ ÐžÐœÐŽÐµÐºÑÑ ÐŽÐ»Ñ ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. "Chapters" Ðž "section titles" -Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÑÑ ÑÐŸÐ±ÐŸÐ¹ ÐžÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐœÐ° ÑÑÐŸÐ²ÐœÐµ ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐ², ÑÐŸÐ³ÐŽÐ° ÐºÐ°Ðº "entire books" - ÐžÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐœÐ° ÑÑÐŸÐ²ÐœÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. ÐÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð»ÑÐ±ÐŸÐ³ÐŸ Ð²ÐžÐŽÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐŸÑÑÑÐµÑÑÐ²Ð»ÐµÐœÐŸ ÑÐ°Ðº Ð¶Ðµ, ÐºÐ°Ðº ÐžÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐµÐºÑÑÐ°. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÑÐµÐŽÐ»Ð°Ð³Ð°ÑÑ ÐŽÐ»Ñ Ð¿ÐŸÐžÑÐºÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐžÐœÐŽÐµÐºÑÑ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐŸÐ² ÑÐ°Ð·ÐŽÐµÐ»Ð°, ÑÑÐŸ Ðž Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐŸ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="hierarchical_structure_in_the_demo_collection_1"/>.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="configuration_file">
+<Title>
+<Text id="321">Ð€Ð°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="322">Ð€Ð°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐ¿ÑÐ°Ð²Ð»ÑÐµÑ ÑÑÑÑÐºÑÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐœÐ°ÑÑÑÐŸÐžÑÑ ÐµÐµ Ð²ÐœÐµÑÐœÐžÐ¹ Ð²ÐžÐŽ, Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ðž ÐžÑ
+ Ð¿ÑÐ±Ð»ÐžÐºÐ°ÑÐžÐž. ÐÑÐŸÑÑÐŸÐž ÑÐ°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐŸÐ·ÐŽÐ°ÐµÑÑÑ, ÐºÐŸÐ³ÐŽÐ° Ð²Ñ Ð·Ð°Ð¿ÑÑÐºÐ°ÐµÑÐµ mkcol.pl, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐŸÐ·ÐŽÐ°ÐµÑ Ð·Ð°Ð¿ÐžÑÑ ÐŽÐ»Ñ Ð°ÐŽÑÐµÑÐŸÐ² E-mail Ð»ÐžÑ, ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÑÑ
+ Ð·Ð° ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ Ðž Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð¡Ð»ÐµÐŽÑÐµÑ Ð¿ÐŸÐŒÐœÐžÑÑ, ÑÑÐŸ ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ Ð°ÑÐ³ÑÐŒÐµÐœÑÐ° creator ÑÐ²Ð»ÑÐµÑÑÑ Ð¿ÑÐžÐœÑÐŽÐžÑÐµÐ»ÑÐœÑÐŒ, ÐœÐŸ ÐµÑÐ»Ðž Ð²Ñ ÐŸÑÐŽÐµÐ»ÑÐœÐŸ ÐœÐµ ÐŸÐ³ÐŸÐ²Ð°ÑÐžÐ²Ð°ÐµÑÐµ, ÑÐŸ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐžÐ· ÑÑÐŸÐ³ÐŸ Ð°ÑÐ³ÑÐŒÐµÐœÑÐ° Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž Ð±ÑÐŽÐµÑ Ð¿ÐµÑÐµÐœÐµÑÐµÐœÐ° Ð² Ð¿ÐŸÐ»Ðµ Ð°ÑÐ³ÑÐŒÐµÐœÑÐ° maintainer.</Text>
+<Table id="items_in_the_collection_configuration_file">
+<Title>
+<Text id="323">Ð­Ð»ÐµÐŒÐµÐœÑÑ ÑÐ°Ð¹Ð»Ð° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<CodeLine>creator</CodeLine>
+</th>
+<th width="397">
+<Text id="324">E-mail ÑÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>maintainer</i></CodeLine>
+</th>
+<th width="397">
+<Text id="325">E-mail ÑÐ»ÑÐ¶Ð±Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>public</i></CodeLine>
+</th>
+<th width="397">
+<Text id="326">ÐÐŸÐ»Ð¶ÐœÐ° Ð»Ðž Ð±ÑÑÑ ÐŸÐ¿ÑÐ±Ð»ÐžÐºÐŸÐ²Ð°ÐœÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>beta</i></CodeLine>
+</th>
+<th width="397">
+<Text id="327">Ð¯Ð²Ð»ÑÐµÑÑÑ Ð»Ðž ÐœÐ°ÑÑÐŸÑÑÐ°Ñ Ð¿ÑÐ±Ð»ÐžÐºÐ°ÑÐžÑ beta-Ð²ÐµÑÑÐžÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>indexes</i></CodeLine>
+</th>
+<th width="397">
+<Text id="328">Ð¡Ð¿ÐžÑÐŸÐº ÐžÐœÐŽÐµÐºÑÐŸÐ² ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>defaultindex</i></CodeLine>
+</th>
+<th width="397">
+<Text id="329">ÐÐœÐŽÐµÐºÑÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>subcollection</i></CodeLine>
+</th>
+<th width="397">
+<Text id="330">ÐÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐŸÑÐœÐŸÐ²Ð°ÐœÐœÑÑ ÐœÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>indexsubcollections</i></CodeLine>
+</th>
+<th width="397">
+<Text id="331">Ð£ÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐœÐ° Ð¿ÐŸÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐŽÐ»Ñ ÐžÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>defaultsubcollection</i></CodeLine>
+</th>
+<th width="397">
+<Text id="332">ÐÐœÐŽÐµÐºÑÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÐŽÐ»Ñ Ð¿ÐŸÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>languages</i></CodeLine>
+</th>
+<th width="397">
+<Text id="333">Ð¡Ð¿ÐžÑÐŸÐº ÑÐ·ÑÐºÐŸÐ² ÐŽÐ»Ñ ÐžÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>defaultlanguage</i></CodeLine>
+</th>
+<th width="397">
+<Text id="334">Ð¯Ð·ÑÐº ÐŽÐ»Ñ ÐžÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÑ, ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐœÑÐ¹ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>collectionmeta</i></CodeLine>
+</th>
+<th width="397">
+<Text id="335">ÐÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐœÐ° ÑÑÐŸÐ²ÐœÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>plugin</i></CodeLine>
+</th>
+<th width="397">
+<Text id="336">ÐÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ, ÑÑÐ°ÑÑÐ²ÑÑÑÐžÐµ Ð² Ð¿ÑÐŸÑÐµÑÑÐµ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>format</i></CodeLine>
+</th>
+<th width="397">
+<Text id="337">Ð¡ÑÑÐŸÐºÐŸÐ²ÑÐ¹ ÑÐŸÑÐŒÐ°Ñ (ÐŸÐ±ÑÑÑÐœÐµÐœÐžÐµ ÑÐ»ÐµÐŽÑÐµÑ)</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>classify</i></CodeLine>
+</th>
+<th width="397">
+<Text id="338">ÐÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐ¹ Ð² Ð¿ÑÐŸÑÐµÑÑÐµ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="339">ÐÐ°Ð¶ÐŽÐ°Ñ ÑÑÑÐŸÐºÐ° ÑÐ°Ð¹Ð»Ð° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÐŸ ÑÑÑÐµÑÑÐ²Ñ ÑÐ²Ð»ÑÐµÑÑÑ Ð¿Ð°ÑÐŸÐ¹ "Ð°ÑÑÐžÐ±ÑÑ, Ð·ÐœÐ°ÑÐµÐœÐžÐµ". ÐÐ°Ð¶ÐŽÑÐ¹ Ð°ÑÑÐžÐ±ÑÑ ÐœÐµÑÐµÑ ÑÐ°ÑÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐºÐŸÑÐŸÑÐ°Ñ ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐœÐ° ÑÐŸ, ÐºÐ°Ðº ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÐŽÐŸÐ»Ð¶ÐœÑ Ð²ÑÐ³Ð»ÑÐŽÐµÑÑ ÐžÐ»Ðž ÐºÐ°Ðº ÐŸÐœÐž ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐ°ÐœÑ. Ð ÑÐ°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="items_in_the_collection_configuration_file"/> Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÑ ÑÐ»ÐµÐŒÐµÐœÑÑ, ÐºÐŸÑÐŸÑÑÐµ ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ Ð²ÐºÐ»ÑÑÐµÐœÑ Ð² ÑÐ°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ðž ÐŽÐ»Ñ ÑÐµÐ³ÐŸ ÐŸÐœÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ. Ð¢Ð°ÐºÐžÐŒ Ð¶Ðµ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÑ Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð²ÑÐµ ÐŸÐ¿ÑÐžÐž ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐž ÐŽÐ»Ñ import.pl Ðž buildcol.pl - ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, Ð¿ÑÐž Ð¿ÑÐŸÑÑÐµÐœÐžÐž no_text true ÐŽÐ»Ñ ÐŸÐ¿ÑÐžÐž buildcol.pl Ð±ÑÐŽÐµÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ Ð°ÑÑÐžÐ±ÑÑ no_text.</Text>
+<Text id="340">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÑÐ°Ð¹Ð»Ð° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÑÐºÑÐžÐ¿ÑÐ° mkcol.pl, Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐœÐŸÐ³ÐŸ Ð² Ð¢Ð°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="collection_configuration_file_created_by_mkcd"/>, ÑÐ²Ð»ÑÐµÑÑÑ ÐŸÑÐµÐœÑ Ð¿ÑÐŸÑÑÑÐŒ Ðž ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÑÐ¹ ÐŒÐžÐœÐžÐŒÑÐŒ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž. Ð¡ÑÑÐŸÐºÐž 1 Ðž 2 ÑÐ²Ð»ÑÑÑÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÑÐŒÐž Ð°ÑÑÐžÐ±ÑÑÐ° creator, ÑÐŸÐ·ÐŽÐ°ÐœÐœÑÐŒÐž Ð² ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐµ ÑÐ°Ð±ÐŸÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ mkcol.pl, Ðž ÑÐŸÐŽÐµÑÐ¶Ð°Ñ Ð°ÐŽÑÐµÑÐ° ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ Ð¿ÐŸÑÑÑ Ð»ÐžÑ, ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÑÑ
+ Ð·Ð° ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ Ðž ÐœÐ°Ð¿ÐŸÐ»ÐœÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (ÐœÐµ ÐŸÐ±ÑÐ·Ð°ÑÐµÐ»ÑÐœÐŸ ÐŸÐŽÐžÐœ Ðž ÑÐŸÑ Ð¶Ðµ ÑÐµÐ»ÐŸÐ²ÐµÐº).</Text>
+<Table id="collection_configuration_file_created_by_mkcd">
+<Title>
+<Text id="341">Ð€Ð°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»ÐµÐºÑÐžÐž, ÑÐŸÐ·ÐŽÐ°ÐœÐœÑÐ¹ <i>mkcd.pl</i></Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="342"><b>ÐÑÑÐžÐ±ÑÑ</b></Text>
+</th>
+<th width="265">
+<Text id="343"><b>ÐÐœÐ°ÑÐµÐœÐžÐµ</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>1</CodeLine>
+</th>
+<th width="132">
+<CodeLine>creator</CodeLine>
+</th>
+<th width="265">
+<Text id="344">username@email.com</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>2</CodeLine>
+</th>
+<th width="132">
+<CodeLine>maintainer</CodeLine>
+</th>
+<th width="265">
+<Text id="345">username@email.com</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>3</CodeLine>
+</th>
+<th width="132">
+<CodeLine>public</CodeLine>
+</th>
+<th width="265">
+<Text id="346">True</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>4</CodeLine>
+</th>
+<th width="132">
+<CodeLine>beta</CodeLine>
+</th>
+<th width="265">
+<Text id="347">True</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>5</CodeLine>
+</th>
+<th width="132">
+<CodeLine>indexes</CodeLine>
+</th>
+<th width="265">
+<Text id="348">document:text</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>6</CodeLine>
+</th>
+<th width="132">
+<CodeLine>defaultindex</CodeLine>
+</th>
+<th width="265">
+<Text id="349">document:text</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>7</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="350">ZIPPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>8</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="351">GAPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>9</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="352">TextPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>10</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="353">HTMLPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>11</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="354">EMAILPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>12</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="355">ArcPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>13</CodeLine>
+</th>
+<th width="132">
+<CodeLine>plugin</CodeLine>
+</th>
+<th width="265">
+<Text id="356">RecPlug</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>14</CodeLine>
+</th>
+<th width="132">
+<CodeLine>classify</CodeLine>
+</th>
+<th width="265">
+<Text id="357">AZList metadata Title</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>15</CodeLine>
+</th>
+<th width="132">
+<CodeLine>collectionmeta</CodeLine>
+</th>
+<th width="265">
+<Text id="358">collectionname       "sample collection"</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>16</CodeLine>
+</th>
+<th width="132">
+<CodeLine>collectionmeta</CodeLine>
+</th>
+<th width="265">
+<Text id="359">iconcollection       ""</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>17</CodeLine>
+</th>
+<th width="132">
+<CodeLine>collectionmeta</CodeLine>
+</th>
+<th width="265">
+<Text id="360">collectionextra     ""</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine>18</CodeLine>
+</th>
+<th width="132">
+<CodeLine>collectionmeta</CodeLine>
+</th>
+<th width="265">
+<Text id="361">.document:text     "documents"</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="362">Ð¡ÑÑÐŸÐºÐ° 3 ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐœÐ° ÑÐŸÑ ÑÐ°ÐºÑ, Ð±ÑÐŽÐµÑ Ð»Ðž ÐŽÐ°ÐœÐœÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð¿ÐŸÑÐ»Ðµ ÐµÐµ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐŽÐŸÑÑÑÐ¿ÐœÐ° ÑÐžÑÐŸÐºÐŸÐŒÑ ÐºÑÑÐ³Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹, Ðž Ð¿ÑÐžÐœÐžÐŒÐ°ÐµÑ 2 Ð·ÐœÐ°ÑÐµÐœÐžÑ: true (Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ, ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ, ÑÑÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð±ÑÐŽÐµÑ ÐŽÐŸÑÑÑÐ¿ÐœÐ° ÐŽÐ»Ñ Ð¿ÑÐ±Ð»ÐžÑÐœÐŸÐ³ÐŸ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ) ÐžÐ»Ðž false (ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ, ÑÑÐŸ ÐœÐµ Ð±ÑÐŽÐµÑ). ÐÐŸÑÐ»ÐµÐŽÐœÐµÐµ ÐŸÐ±ÑÑÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð²ÐŸ Ð²ÑÐµÐŒÑ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÑÐµÑÑÐŸÐ²ÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐžÐ»Ðž ÐŽÐ»Ñ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐŽÐ»Ñ ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ.</Text>
+<Text id="363">Line 5 determines what collection indexes are created at build time: in this example only the document text is to be indexed. Indexes can be constructed at the <i>document</i>, <i>section</i>, and <i>paragraph</i> levels. They can contain the material in <i>text</i>, or in any metadataâmost commonly <i>Title</i>. The form used to specify an index is <i>level:data</i>. For example, to include an index of section titles as well, you should change line 5 to <i>indexes document:text section:Title</i>. More than one type of data can be included in the same index by separating the data types with commas. For example, to create a section-level index of titles, text and dates, the line should read <i>indexes section:text,Title,Date.</i> The default index defined in line 6 is the default to be used on the collection's search page.</Text>
+<Text id="364">Lines 7â13 specify which plugins to use when converting documents to the Greenstone archive format and when building collections from archive files. Section <CrossRef target="Section" ref="plugins"/> gives information about what plugins are available. The order in which plugins are listed is the order in which they are tried on each document, and once a plugin that is able to process a document is found, no more are tried.</Text>
+<Text id="365">Line 14 specifies that an alphabetic list of titles is to be created for browsing purposes. Browsing structures are constructed by âclassifiersâ. Section <CrossRef target="Section" ref="classifiers"/> gives information about classifiers and what they can do.</Text>
+<Text id="366">Lines 15â18 are used to specify collection-level metadata. Specified through <i>collectionname</i>, the long form of the name is used as the collection's âtitleâ for the web browser. The <i>collectionicon</i> entry gives the URL of the collection's icon. If an index is specified (as in line 18), the string following is displayed as the name of that index on the collection's search page. ÐÐ°ÐžÐ±ÐŸÐ»ÐµÐµ Ð²Ð°Ð¶ÐœÐŸÐ¹ ÑÐ°ÑÑÑÑ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐœÐ° ÑÑÐŸÐ²ÐœÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÑÐ²Ð»ÑÐµÑÑÑ collectionextra, ÐºÐŸÑÐŸÑÐ°Ñ ÐŽÐ°ÐµÑ ÑÐµÐºÑÑ ÑÐ°Ð·Ð²ÐµÑÐœÑÑÐŸÐ³ÐŸ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð·Ð°ÐºÐ»ÑÑÐµÐœÐœÑÐ¹ Ð² ÐŽÐ²ÐŸÐ¹ÐœÑÐµ ÐºÐ°Ð²ÑÑÐºÐž. Ð­ÑÐŸÑ ÑÐµÐºÑÑ Ð±ÑÐŽÐµÑ ÐŸÑÐŸÐ±ÑÐ°Ð¶Ð°ÑÑÑÑ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ ÐŽÐ»Ñ ÑÑÑÐ°ÐœÐžÑÑ "About this collection" (Ð ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž). ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ Ð²Ð°ÑÐžÐ°ÐœÑÑ collectionextra ÐŽÐ»Ñ ÐŒÑÐ»ÑÑÐžÑÐ·ÑÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°, Ð¿ÑÑÐµÐŒ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ ÑÐ·ÑÐºÐŸÐ²ÐŸÐ³ÐŸ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ Ð² ÐºÐ²Ð°ÐŽÑÐ°ÑÐœÑÑ
+ ÑÐºÐŸÐ±ÐºÐ°Ñ
+. ÐÐ°Ð¿ÑÐžÐŒÐµÑ,</Text>
+<Indented>
+<Text id="367">collectionmeta collectionextra "collection description"</Text>
+</Indented>
+<Indented>
+<Text id="368">collectionmeta collectionextra [l=fr] "description in French"</Text>
+</Indented>
+<Indented>
+<Text id="369">collectionmeta collectionextra [l=mi] "description in Maori"</Text>
+</Indented>
+<Text id="370">ÐÑÐ»Ðž ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ ÑÐ·ÑÐº ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° "fr" ÐžÐ»Ðž "mi", ÑÐŸ Ð±ÑÐŽÐµÑ ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐ° ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐ°Ñ Ð²ÐµÑÑÐžÑ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ. ÐÐ»Ñ ÐŽÑÑÐ³ÐžÑ
+ ÑÐ·ÑÐºÐŸÐ² Ð¿ÐŸÑÐ²ÐžÑÑÑ Ð²ÐµÑÑÐžÑ, Ð·Ð°ÐŽÐ°ÐœÐœÐ°Ñ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ.</Text>
+<Text id="371">Ð­ÑÐŸÑ Ð¿ÑÐŸÑÑÐŸÐ¹ ÑÐ°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐœÐµ Ð²ÐºÐ»ÑÑÐ°ÑÑÐžÐ¹ ÐœÐž Ð¿ÑÐžÐŒÐµÑÐŸÐ² ÑÑÑÐŸÐº ÑÐŸÑÐŒÐ°ÑÐ°, ÐœÐž Ð¿ÐŸÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐœÐž ÑÑÐµÐŽÑÑÐ² ÑÐ·ÑÐºÐ°, Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÐµÐŒÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐŒ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž. Ð¡ÑÑÐŸÐºÐŸÐ²ÑÐ¹ ÑÐŸÑÐŒÐ°Ñ Ð±ÑÐŽÐµÑ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐµÐµ ÑÐ°ÑÑÐŒÐŸÑÑÐµÐœ Ð² Ð Ð°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Section" ref="formatting_greenstone_output"/>, Ð° Ð·ÐŽÐµÑÑ ÐŒÑ ÑÐ°ÑÑÐŒÐŸÑÑÐžÐŒ ÑÐžÑÑÐ°ÑÐžÑ Ñ Ð¿ÐŸÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒÐž Ðž ÑÐ·ÑÐºÐ°ÐŒÐž.</Text>
+<Subsection id="subcollections">
+<Title>
+<Text id="372">ÐÐŸÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="373">Greenstone Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ Ð¿ÐŸÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÐžÐ· ÐœÐžÑ
+ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÑÑ ÐŸÑÐŽÐµÐ»ÑÐœÑÐµ ÐžÐœÐŽÐµÐºÑÑ. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, Ð² ÐŸÐŽÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐžÐŒÐµÐµÑÑÑ Ð±ÐŸÐ»ÑÑÐŸÐµ Ð¿ÐŸÐŽÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÐžÐŒÐµÐœÑÐµÐŒÑÑ
+ <i>Food and Nutrition Bulletin</i>. ÐÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒ ÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ Ð¿ÑÐžÐŒÐµÑÐ°.</Text>
+<Text id="374">Ð ÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐžÐŒÐµÑÑÑÑ 3 ÐžÐœÐŽÐµÐºÑÐ° Ðž Ð²ÑÐµ ÐœÐ° ÑÑÐŸÐ²ÐœÐµ ÑÐ°Ð·ÐŽÐµÐ»Ð°: ÐŸÐŽÐžÐœ - ÐŽÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð²ÑÐŸÑÐŸÐ¹ - ÐŽÐ»Ñ  <i>Food and Nutrition Bulletin</i> Ðž ÑÑÐµÑÐžÐ¹ - ÐŽÐ»Ñ ÐŸÑÑÐ°Ð»ÑÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². ÐÐžÐ¶Ðµ Ð¿ÑÐžÐ²ÐµÐŽÐµÐœÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐµ ÑÑÑÐŸÐºÐž ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<CodeLine>indexes                           section:text</CodeLine>
+<CodeLine>subcollection               fn "Title/^Food and Nutrition Bulletin/i "</CodeLine>
+<CodeLine>subcollection               other "!Title/^Food and Nutrition Bulletin/i "</CodeLine>
+<CodeLine>indexsubcollections fn   other   fn,other</CodeLine>
+<Text id="375">ÐÑÐŸÑÐ°Ñ Ðž ÑÑÐµÑÑÑ ÑÑÑÐŸÐºÐž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ ÑÐ»ÐµÐŽÑÑÑÐžÐµ Ð¿ÐŸÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž: Ñ ÐžÐŒÐµÐœÐµÐŒ fn, ÐºÐŸÑÐŸÑÐ°Ñ ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Food and Nutrition Bulletin, Ðž Ñ ÐžÐŒÐµÐœÐµÐŒ other, Ð² ÐºÐŸÑÐŸÑÐŸÐ¹ ÐœÐ°Ñ
+ÐŸÐŽÑÑÑÑ ÐŸÑÑÐ°Ð»ÑÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ. Ð¢ÑÐµÑÑÐµ Ð¿ÐŸÐ»Ðµ ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÐµ ÐœÐ° ÑÐ·ÑÐºÐµ Perl, ÐºÐŸÑÐŸÑÐŸÐµ ÐžÐŽÐµÐœÑÐžÑÐžÑÐžÑÑÐµÑ ÑÑÐž Ð¿ÐŸÐŽÐŒÐœÐŸÐ¶ÐµÑÑÐ²Ð°, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐžÐ¿Ð° Title: Ð² Ð¿ÐµÑÐ²ÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ ÐžÑÐµÐŒ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐž, ÐºÐŸÑÐŸÑÑÐµ ÐœÐ°ÑÐžÐœÐ°ÑÑÑÑ Ñ Food and Nutrition Bulletin , Ð° Ð²ÐŸ Ð²ÑÐŸÑÐŸÐŒ - Ð² ÐºÐŸÑÐŸÑÑÑ
+ ÐŽÐ°ÐœÐœÐŸÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÐŸÑÑÑÑÑÑÐ²ÑÐµÑ (ÐŸÐ±ÑÐ°ÑÐžÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ ÐœÐ° Ð·ÐœÐ°Ðº "!"). ÐÐœÐ°Ðº i Ð² ÐºÐŸÐœÑÐµ ÑÑÑÐŸÐºÐž ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ, ÑÑÐŸ Ð¿ÑÐž ÑÐ°Ð±ÐŸÑÐµ ÑÑÐžÑ
+ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐ¹ ÑÐµÐ³ÐžÑÑÑ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ² ÐœÐµ ÑÑÐžÑÑÐ²Ð°ÐµÑÑÑ. ÐÐŸÐ»Ðµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, Ð² ÐœÐ°ÑÐµÐŒ ÑÐ»ÑÑÐ°Ðµ Title, ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð»ÑÐ±ÑÐŒ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÐŒ Ð¿ÐŸÐ»ÐµÐŒ, ÐžÐ»Ðž Filename, ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÐžÐŒ Ð¿ÐµÑÐ²ÐŸÐœÐ°ÑÐ°Ð»ÑÐœÐŸÐŒÑ ÐžÐŒÐµÐœÐž ÑÐ°Ð¹Ð»Ð° ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. Ð ÑÐµÑÐ²ÐµÑÑÐŸÐ¹ ÑÑÑÐŸÐºÐµ, indexsubcollections, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑÑÑ ÑÑÐž ÐžÐœÐŽÐµÐºÑÐ°: ÐŸÐŽÐžÐœ - ÐŽÐ»Ñ Ð¿ÐŸÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž fn, Ð²ÑÐŸÑÐŸÐ¹ - ÐŽÐ»Ñ Ð¿ÐŸÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž other Ðž ÑÑÐµÑÐžÐ¹ - ÐŽÐ»Ñ ÐŸÐ±ÐµÐžÑ
+ Ð¿ÐŸÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (Ñ.Ðµ. ÐŽÐ»Ñ Ð²ÑÐµÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²). ÐÐ±ÑÐ°ÑÐžÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ ÐœÐ° ÑÐŸ, ÑÑÐŸ ÐµÑÐ»Ðž Ð±Ñ ÐŽÐ²Ð° Ð²Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÑ Ð±ÑÐ»Ðž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÑ Ð² ÑÑÑÐŸÐºÐµ indexes, ÑÐŸ ÐŸÐ±ÑÐµÐµ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐœÑÑ
+ ÐžÐœÐŽÐµÐºÑÐŸÐ² Ð±ÑÐ»ÐŸ Ð±Ñ ÑÐµÑÑÑ, Ð° ÐœÐµ ÑÑÐž.</Text>
+<Text id="376">ÐÑÐ»Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÐœÐ° ÑÐ°Ð·ÐœÑÑ
+ ÑÐ·ÑÐºÐ°Ñ
+, ÑÐŸ ÐžÐœÐŽÐµÐºÑÑ ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÑ ÐŸÑÐŽÐµÐ»ÑÐœÐŸ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÐ·ÑÐºÐ°. Ð¯Ð·ÑÐº ÑÐ²Ð»ÑÐµÑÑÑ ÐžÐœÑÑÑÑÐºÑÐžÐµÐ¹ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+; Language is a metadata statement; Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑÑÑ Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐž ÑÐŸ ÑÑÐ°ÐœÐŽÐ°ÑÑÐŸÐŒ ISO 639 ÐŽÐ²ÑÑ
+Ð±ÑÐºÐ²ÐµÐœÐœÑÐŒ ÐºÐŸÐŽÐŸÐŒ, ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐ°ÑÑÐžÐŒ ÑÐ·ÑÐº - ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐµÐ¿ - ÑÑÐŸ English (Ð°Ð³Ð»ÐžÐ¹ÑÐºÐžÐ¹), zh - Chinese (ÐºÐžÑÐ°Ð¹ÑÐºÐžÐ¹), Ðž mi - ÑÑÐŸ Maori (ÐŒÐ°ÐŸÑÐž). Ð¢Ð°Ðº ÐºÐ°Ðº Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÑ ÐœÐ° ÑÑÐŸÐ²ÐœÐµ ÑÐ°Ð·ÐŽÐµÐ»Ð°, ÐŸÑÐŽÐµÐ»ÑÐœÑÐµ ÑÐ°ÑÑÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÑ ÐœÐ° ÑÐ°Ð·ÐœÑÑ
+ ÑÐ·ÑÐºÐ°Ñ
+.</Text>
+<Text id="377">ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÐµÑÐ»Ðž ÑÐ°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÑÐŸÐŽÐµÑÐ¶ÐžÑ: ÑÐµÐºÑÑ ÑÐ°Ð·ÐŽÐµÐ»Ð°, Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº ÑÐ°Ð·ÐŽÐµÐ»Ð°, ÑÐµÐºÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ðž ÐžÐœÐŽÐµÐºÑÑ ÑÐµÐºÑÑÐ° Ð¿Ð°ÑÐ°Ð³ÑÐ°ÑÐ°, ÑÐŸ ÐŽÐ»Ñ Ð°ÐœÐ³Ð»ÐžÐ¹ÑÐºÐŸÐ³ÐŸ, ÐºÐžÑÐ°Ð¹ÑÐºÐŸÐ³ÐŸ Ðž ÑÐ·ÑÐºÐ° ÐŒÐ°ÐŸÑÐž Ð±ÑÐ»Ðž </Text>
+<CodeLine>indexes section:text section:Title document:text paragraph:text</CodeLine>
+<CodeLine>languages en zh mi</CodeLine>
+<Text id="378">Ð±ÑÐ»Ðž Ð±Ñ ÑÐŸÐ·ÐŽÐ°ÐœÑ ÐŽÐ²ÐµÐœÐ°ÐŽÑÐ°ÑÑ ÐžÐœÐŽÐµÐºÑÐŸÐ² Ð² ÑÐµÐ»ÐŸÐŒ. ÐÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÐµ ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ Ð¿ÐŸÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÑÐŒÐœÐŸÐ¶Ð°ÐµÑ ÑÐžÑÐ»ÐŸ ÐžÐœÐŽÐµÐºÑÐŸÐ². ÐÐŽÐœÐ°ÐºÐŸ, ÑÐ»ÐµÐŽÑÐµÑ Ñ ÐŸÑÑÐŸÑÐŸÐ¶ÐœÐŸÑÑÑÑ ÐŸÑÐœÐŸÑÐžÑÑÑÑ Ðº ÑÐ°Ð·ÐŽÑÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²Ð° ÐžÐœÐŽÐµÐºÑÐŸÐ².</Text>
+<Text id="379">(Ð­ÑÐ° ÐžÐœÐŽÐµÐºÑÐœÐ°Ñ ÑÐ¿ÐµÑÐžÑÐžÐºÐ°ÑÐžÑ ÐŒÐŸÐ³Ð»Ð° Ð±Ñ Ð±ÑÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐ° Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ ÑÑÐµÐŽÑÑÐ² subcollection, Ð° ÐœÐµ ÑÑÐµÐŽÑÑÐ²ÐŸ languages. ÐÐŽÐœÐ°ÐºÐŸ, Ð² ÑÐ²ÑÐ·Ðž Ñ ÑÐµÐŒ, ÑÑÐŸ ÑÐžÐœÑÐ°ÐºÑÐžÑ Ð¿ÑÐµÐ¿ÑÑÑÑÐ²ÑÐµÑ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ "Ð¿ÐŸÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ð¿ÐŸÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹", ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ ÐœÐµÐ²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÐŒ ÐŸÑÐŽÐµÐ»ÑÐœÐŸ ÐžÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐºÐ°Ð¶ÐŽÑÐ¹ ÑÐ·ÑÐº Ð² Ð¿ÐŸÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+).</Text>
+</Content>
+</Subsection>
+<Subsection id="cross-collection_searching">
+<Title>
+<Text id="380">ÐÐµÑÐµÐºÑÐµÑÑÐœÑÐ¹ Ð¿ÐŸÐžÑÐº Ð¿ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="381">Greenstone ÐžÐŒÐµÐµÑ ÑÑÐµÐŽÑÑÐ²ÐŸ ÐŽÐ»Ñ "Ð¿ÐµÑÐµÐºÑÐµÑÑÐœÐŸÐ³ÐŸ Ð¿ÐŸÐžÑÐºÐ° Ð¿ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž", ÐºÐŸÑÐŸÑÐŸÐµÐ¹ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑ Ð¿ÐŸÐžÑÐº Ð¿ÐŸ ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒ ÑÑÐ°Ð·Ñ Ñ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÐµÐœÐžÐµÐŒ ÐŸÐ±ÑÐµÐŽÐžÐœÐµÐœÐœÑÑ
+ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐŸÐ², ÑÐ°Ðº, ÐºÐ°Ðº ÐµÑÐ»Ðž Ð±Ñ Ð²Ñ ÐžÑÐºÐ°Ð»Ðž Ð¿ÐŸ ÐŸÐŽÐœÐŸÐ¹ ÐŸÐ±ÑÐµÐŽÐžÐœÐµÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÐœÐŸ Ð»ÑÐ±ÐŸÐµ Ð¿ÐŸÐŽÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹: Preferences page (ÑÑÑÐ°ÐœÐžÑÐ° ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÐ¹) Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐÐ°ÐŒ Ð²ÑÐ±ÐžÑÐ°ÑÑ, ÐºÐ°ÐºÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ Ð²ÐºÐ»ÑÑÐµÐœÑ Ð² Ð¿ÐŸÐžÑÐº.</Text>
+<Text id="382">ÐÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ Ð¿ÐµÑÐµÐºÑÐµÑÑÐœÐŸÐ³ÐŸ Ð¿ÐŸÐžÑÐºÐ° ÐŸÐ³ÐŸÐ²Ð°ÑÐžÐ²Ð°ÐµÑÑÑ ÑÑÑÐŸÐºÐŸÐ¹:</Text>
+<CodeLine>supercollection col _1 col _2 âŠ.</CodeLine>
+<Text id="383">Ð³ÐŽÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð²ÐŸÐ²Ð»ÐµÑÐµÐœÐœÑÐµ Ð² Ð¿ÐŸÐžÑÐº, ÐžÐŒÐµÐœÑÑÑÑÑ col_l, col_2,... Ð¢ÐŸÑÐœÐŸ ÑÐ°ÐºÐ°Ñ Ð¶Ðµ ÑÑÑÐŸÐºÐ° ÐŽÐŸÐ»Ð¶ÐœÐ° Ð±ÑÑÑ Ðž Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÑÐµÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÐºÐŸÑÐŸÑÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐ»Ñ Ð¿ÐµÑÐµÐºÑÐµÑÑÐœÐŸÐ³ÐŸ Ð¿ÐŸÐžÑÐºÐ°.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="getting_the_most_out_of_your_documents">
+<Title>
+<Text id="384">ÐÐŸÐ»ÑÑÐµÐœÐžÐµ Ð±ÐŸÐ»ÑÑÐµÐ³ÐŸ ÐŸÑ Ð²Ð°ÑÐžÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²</Text>
+</Title>
+<Content>
+<Text id="385">ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐžÐœÐŽÐžÐ²ÐžÐŽÑÐ°Ð»ÐžÐ·ÐžÑÐŸÐ²Ð°ÐœÑ ÑÐ°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ, ÑÑÐŸÐ±Ñ ÑÐ°Ð·Ð³ÑÐ°ÐœÐžÑÐžÑÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑÑÑÑ Ð² ÐœÐžÑ
+ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒÐž ÑÐ¿ÐŸÑÐŸÐ±Ð°ÐŒÐž ÐŽÐŸÑÑÑÐ¿Ð°. ÐÐ°ÑÑÐŸÑÑÐ°Ñ Ð³Ð»Ð°Ð²Ð° ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ, ÐºÐ°Ðº Greenstone ÐžÐ·Ð²Ð»ÐµÐºÐ°ÐµÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ðž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÑ ÐµÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ: Ð Ð°Ð·ÐŽÐµÐ» <CrossRef target="Section" ref="plugins"/> - ÐÐ±ÑÐ°Ð±ÐŸÑÐºÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², Ð Ð°Ð·ÐŽÐµÐ» <CrossRef target="Section" ref="classifiers"/> - ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ, Ð Ð°Ð·ÐŽÐµÐ»Ñ <CrossRef target="Section" ref="formatting_greenstone_output"/> Ðž <CrossRef target="Section" ref="controlling_the_greenstone_user_interface"/> -ÐžÐœÑÑÑÑÐŒÐµÐœÑÐ°Ð»ÑÐœÑÐµ ÑÑÐµÐŽÑÑÐ²Ð° ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ.</Text>
+<Section id="plugins">
+<Title>
+<Text id="386">ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ</Text>
+</Title>
+<Content>
+<Text id="387">ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ Ð°ÐœÐ°Ð»ÐžÐ·ÐžÑÑÑÑ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ðž ÐžÐ·Ð²Ð»ÐµÐºÐ°ÑÑ ÐžÐ· ÐœÐžÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, HTML-Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ ÐºÐŸÐœÐ²ÐµÑÑÐžÑÑÐµÑ HTML-ÑÑÑÐ°ÐœÐžÑÑ Ð² ÑÐŸÑÐŒÐ°Ñ Ð°ÑÑ
+ÐžÐ²Ð° Greenstone Ðž ÐžÐ·Ð²Ð»ÐµÐºÐ°ÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, ÐºÐŸÑÐŸÑÑÐµ ÑÐ²Ð»ÑÑÑÑÑ ÑÐ²ÐœÑÐŒ Ð² ÑÐŸÑÐŒÐ°ÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° - ÑÐ°ÐºÐžÐµ, ÐºÐ°Ðº Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐž, Ð·Ð°ÐºÐ»ÑÑÐµÐœÐœÑÐµ ÑÐµÐ³Ð°ÐŒÐž <i>&lt;title&gt;&lt;/title&gt;</i>.</Text>
+<Text id="388">ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ ÐœÐ°Ð¿ÐžÑÐ°ÐœÑ ÐœÐ° ÑÐ·ÑÐºÐµ Perl. ÐÑÐµ ÐŸÐœÐž Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÑÑ ÐŸÑ ÐŸÑÐœÐŸÐ²ÐœÐŸÐ³ÐŸ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ BasPlug, ÐºÐŸÑÐŸÑÐŸÐµ Ð²ÑÐ¿ÐŸÐ»ÐœÑÐµÑ ÐºÐœÐžÐ²ÐµÑÑÐ°Ð»ÑÐœÑÐµ ÐŸÐ¿ÐµÑÐ°ÑÐžÐž, ÑÐ°ÐºÐžÐµ ÐºÐ°Ðº ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐœÐŸÐ²ÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°Ð»ÑÐœÐŸÐ³ÐŸ Ð°ÑÑ
+ÐžÐ²Ð° Greenstone ÐŽÐ»Ñ Ð¿ÐŸÑÐ»ÐµÐŽÑÑÑÐµÐ¹ ÑÐ°Ð±ÐŸÑÑ Ñ ÐœÐžÐŒ, ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑÐ° ÐŸÐ±ÑÐµÐºÑÐ° (OID), ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐ° ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐ² ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ Ñ
+ÑÐ°ÐœÑÑÑÑ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž perllib/plugins.</Text>
+<Text id="389">Ð§ÑÐŸÐ±Ñ ÑÐ·ÐœÐ°ÑÑ Ð±ÐŸÐ»ÑÑÐµ ÐŸ Ð»ÑÐ±ÐŸÐŒ ÐžÐ· Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐ¹, ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ <i>pluginfo.pl plugin-name</i> Ð² ÐŸÐ±Ð»Ð°ÑÑÐž ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐž. (Ð¡ÐœÐ°ÑÐ°Ð»Ð°, Ð²Ñ ÐŽÐŸÐ»Ð¶ÐœÑ Ð²ÑÐ·Ð²Ð°ÑÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐ¹ ÑÐºÑÐžÐ¿ÑÑ <i>setup</i>, ÐµÑÐ»Ðž Ð²Ñ ÑÑÐŸÐ³ÐŸ ÐœÐµ ÐŽÐµÐ»Ð°Ð»Ðž ÑÐ°ÐœÐµÐµ. ÐÑÐ»Ðž Ð²Ð°ÑÐ° ÐŸÐ¿ÐµÑÐ°ÑÐžÐŸÐœÐœÐ°Ñ ÑÐžÑÑÐµÐŒÐ° ÐœÐµ ÐœÐ°ÑÑÑÐŸÐµÐœÐ° ÐœÐ° ÑÐŸ, ÑÑÐŸÐ±Ñ Ð²ÐŸÑÐ¿ÑÐžÐœÐžÐŒÐ°ÑÑ ÑÐ°Ð¹Ð»Ñ Ñ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµÐŒ .Ñl ÐºÐ°Ðº Ð²ÑÐ¿ÐŸÐ»ÐœÐžÐŒÑÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐœÐ° ÑÐ·ÑÐºÐµ Perl, ÑÐŸ Ð² Windows Ð²Ñ ÐŽÐŸÐ»Ð¶ÐœÑ ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°ÑÑ <i>perl âS pluginfo.pl plugin-name</i>). Ð ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐµ ÐœÐ° ÑÐºÑÐ°ÐœÐµ Ð¿ÐŸÑÐ²ÐžÑÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸÐ± ÐžÐœÑÐµÑÐµÑÑÑÑÐµÐŒ Ð²Ð°Ñ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐž - ÐºÐ°ÐºÐžÐµ ÐŽÐ°ÐœÐœÐŸÐŒÑ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ ÑÑÐµÐ±ÑÑÑÑÑ ÑÐ¿ÐµÑÐžÑÐžÑÐœÑÐµ ÐŸÐ¿ÑÐžÐž Ðž ÐºÐ°ÐºÐžÐµ ÐŸÐ±ÑÐžÐµ.</Text>
+<Text id="390">ÐÑ Ð»ÐµÐ³ÐºÐŸ ÐŒÐŸÐ¶ÐµÑÐµ ÐœÐ°Ð¿ÐžÑÐ°ÑÑ ÐœÐŸÐ²ÑÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ ÐŽÐ»Ñ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž ÑÐŸÑÐŒÐ°ÑÐŸÐ² ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÐœÐµ Ð¿ÑÐµÐŽÑÑÐŒÐŸÑÑÐµÐœÐœÑÑ
+ Ð² ÑÑÑÐµÑÑÐ²ÑÑÑÐžÑ
+ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑÑ
+, ÑÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐŸÑÐŸÐ±ÑÐŒÐž ÑÐ¿ÐŸÑÐŸÐ±Ð°ÐŒÐž ÐžÐ»Ðž ÐžÐ·Ð²Ð»ÐµÑÐµÐœÐžÑ ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐœÐŸÐ²ÑÑ
+ Ð²ÐžÐŽÐŸÐ² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+.</Text>
+<Subsection id="general_options">
+<Title>
+<Text id="391">ÐÐ±ÑÐžÐµ ÐŸÐ¿ÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="392">Ð Ð¢Ð°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="options_applicable_to_all_plugins"/> Ð¿ÑÐžÐ²ÐµÐŽÐµÐœÑ ÐŸÐ¿ÑÐžÐž, Ð¿ÑÐžÐœÐžÐŒÐ°ÐµÐŒÑÐµ Ð»ÑÐ±ÑÐŒ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐŒ, Ð¿ÐŸÐ»ÑÑÐµÐœÐœÑÐŒ ÐŸÑ BasPlug.</Text>
+<Table id="options_applicable_to_all_plugins">
+<Title>
+<Text id="393">ÐÐ¿ÑÐžÐž, Ð¿ÑÐžÐŒÐµÐœÑÐµÐŒÑÐµ ÐŽÐ»Ñ Ð²ÑÐµÑ
+ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐ¹</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<CodeLine><i>input_encoding</i></CodeLine>
+</th>
+<th width="397">
+<Text id="394">ÐÐŸÐŽÐžÑÐŸÐ²ÐºÐ° ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ² ÐžÑÑ
+ÐŸÐŽÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². ÐÐœÐ°ÑÐµÐœÐžÐµ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÐŽÐŸÐ»Ð¶ÐœÐŸ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÑÐµÑÐžÑÑ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÑ ÐºÐŸÐŽÐžÑÐŸÐ²ÐºÐž ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÐžÐœÐŽÐžÐ²ÐžÐŽÑÐ°Ð»ÑÐœÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. ÐÐœÐŸÐ³ÐŽÐ° Ð¿ÐŸÐ»ÐµÐ·ÐœÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÑÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ, Ñ
+ÐŸÑÑ, ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐµÑÐ»Ðž Ð²Ñ ÑÐŸÑÐœÐŸ Ð·ÐœÐ°ÐµÑÐµ, ÑÑÐŸ Ð²ÑÐµ Ð²Ð°ÑÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÐœÐ°Ñ
+ÐŸÐŽÑÑÑÑ Ð² ASCII, ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ° Ð²Ñ
+ÐŸÐŽÐœÐŸÐ¹ ÐºÐŸÐŽÐžÑÐŸÐ²ÐºÐž  ascii Ð·ÐœÐ°ÑÐžÑÐµÐ»ÑÐœÐŸ ÑÐ²ÐµÐ»ÐžÑÐžÐ²Ð°ÐµÑ ÑÐºÐŸÑÐŸÑÑÑ ÐžÐŒÐ¿ÐŸÑÑÐ° Ðž ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ Ð²Ð°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð¡ÑÑÐµÑÑÐ²ÑÐµÑ ÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐŸ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÑ
+ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹. ÐÐ»Ñ Ð¿ÐŸÐ»ÑÑÐµÐœÐžÑ ÐžÑ
+ Ð¿ÐŸÐ»ÐœÐŸÐ³ÐŸ ÑÐ¿ÐžÑÐºÐ° Ð²ÐŸÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµÑÑ pluginfo.pl BasPlug.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>default_encoding</i></CodeLine>
+</th>
+<th width="397">
+<Text id="395">ÐÐŸÐŽÐžÑÐŸÐ²ÐºÐ°, ÐºÐŸÑÐŸÑÐ°Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð² ÑÐ»ÑÑÐ°Ðµ, ÐµÑÐ»Ðž ÐŽÐ»Ñ ÐŸÐ¿ÑÐžÐž input encoding ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ auto ÐžÐ»Ðž ÐŸÐ±ÐœÐ°ÑÑÐ¶ÐµÐœÑ ÑÐ±ÐŸÐž Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐºÐŸÐŽÐžÑÐŸÐ²Ð°ÐœÐžÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>process_exp</i></CodeLine>
+</th>
+<th width="397">
+<Text id="396">ÐÐ±ÑÑÐœÐŸÐµ Perl-Ð²ÑÑÐ°Ð¶ÐµÐœÐžÐµ ÐŽÐ»Ñ ÑÐŸÐ³Ð»Ð°ÑÐŸÐ²Ð°ÐœÐžÑ ÐžÐŒÐµÐœ ÑÐ°Ð¹Ð»ÐŸÐ² (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐŽÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÐŒÐµÑÑÐŸÐœÐ°Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÑ ÑÐ°Ð¹Ð»ÐŸÐ² Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐŒ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµÐŒ). ÐÐœÐŸ ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐœÐ° ÑÐ°Ð¹Ð», ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑÑÑ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµÐŒ . ÐÐ°Ð¶ÐŽÐŸÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ ÐžÐŒÐµÐµÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ (Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ HTMLPlug - (? i) .html? - Ñ.Ðµ. ÑÐ°Ð¹Ð» Ñ ÑÐ°ÑÐžÑÐµÐœÐžÐµÐŒ .htm ÐžÐ»Ðž .html).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>block_exp</i></CodeLine>
+</th>
+<th width="397">
+<Text id="397">ÐÐ±ÑÑÐœÐŸÐµ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÐµ ÐŽÐ»Ñ ÑÐŸÐ³Ð»Ð°ÑÐŸÐ²Ð°ÐœÐžÑ ÐžÐŒÐµÐœ ÑÐ°Ð¹Ð»ÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÐœÐµ ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ Ð¿ÐµÑÐµÐŽÐ°ÐœÑ Ð¿ÐŸÑÐ»ÐµÐŽÑÑÑÐžÐŒ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑÐŒ. Ð­ÑÐŸ ÐŒÐŸÐ¶ÐµÑ Ð¿ÑÐµÐŽÐŸÑÐ²ÑÐ°ÑÐžÑÑ Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÐµ ÑÐŸÐŸÐ±ÑÐµÐœÐžÐ¹ ÐŸÐ± ÐŸÑÐžÐ±ÐºÐ°Ñ
+ Ð² ÑÐ°Ð¹Ð»Ð°Ñ
+, ÐºÐŸÑÐŸÑÑÐŒÐž Ð²Ñ ÐœÐµ ÐžÐœÑÐµÑÐµÑÑÐµÑÐµÑÑ. ÐÐµÐºÐŸÑÐŸÑÑÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÐžÐŒÐµÑÑ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÑ Ð±Ð»ÐŸÐºÐžÑÐŸÐ²Ð°ÐœÐžÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ, ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, HTMLPlug Ð±Ð»ÐŸÐºÐžÑÑÐµÑ ÑÐ°Ð¹Ð»Ñ Ñ ÑÐ°ÑÑÐžÑÐµÐœÐžÑÐŒÐž .gif .jpg .jpeg .png .rtf Ðž .css ÑÐ°ÑÑÐžÑÐµÐœÐžÑÐŒÐž.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>cover_image</i></CodeLine>
+</th>
+<th width="397">
+<Text id="398">ÐÑÐµÑ jpg ÑÐ°Ð¹Ð» (Ñ ÑÐ°ÐºÐžÐŒ Ð¶Ðµ ÐžÐŒÐµÐœÐµÐŒ, ÑÑÐŸ Ðž ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÐŒÑÐ¹ ÑÐ°Ð¹Ð») Ðž ÑÐ²ÑÐ·ÑÐ²Ð°ÐµÑ ÐµÐ³ÐŸ Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐŒ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐŸÐ±Ð»ÐŸÐ¶ÐºÐž.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>extract_acronyms</i></CodeLine>
+</th>
+<th width="397">
+<Text id="399">Extract acronyms from documents and add them as metadata to the corresponding Greenstone archive documents.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>markup_acronyms</i></CodeLine>
+</th>
+<th width="397">
+<Text id="400">ÐÐŸÐ±Ð°Ð²Ð»ÑÐµÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸÐ± Ð°Ð±Ð±ÑÐµÐ²ÐžÐ°ÑÑÑÐµ Ð² ÑÐµÐºÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>extract_language</i></CodeLine>
+</th>
+<th width="397">
+<Text id="401">Identify each document's language and associate it as metadata. Note that this is done automatically if <i>input_encoding</i> is <i>auto</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>default_language</i></CodeLine>
+</th>
+<th width="397">
+<Text id="402">Ð ÑÐ»ÑÑÐ°Ðµ ÑÐ±ÐŸÑ Ð¿ÑÐž Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐŸÐŒ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐž ÑÐ·ÑÐºÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÑÑ ÑÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>first</i></CodeLine>
+</th>
+<th width="397">
+<Text id="403">ÐÐ·Ð²Ð»ÐµÐºÐ°ÐµÑ ÑÑÐ°ÑÑÐŸÐº ÑÐµÐºÑÑÐ°, Ð·Ð°ÐºÐ»ÑÑÐµÐœÐœÑÐ¹ ÐŒÐµÐ¶ÐŽÑ Ð·Ð°Ð¿ÑÑÑÐŒÐž, ÐºÐ°Ðº ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ FirstNNN (ÑÐ°ÑÑÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ Ð·Ð°ÐŒÐµÐœÑ ÐŽÐ»Ñ Title).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>extract_email</i></CodeLine>
+</th>
+<th width="397">
+<Text id="404">ÐÐ·Ð²Ð»ÐµÐºÐ°ÐµÑ Ð°ÐŽÑÐµÑ ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ Ð¿ÐŸÑÑÑ Ðž ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑ ÐµÐ³ÐŸ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<CodeLine><i>extract_date</i></CodeLine>
+</th>
+<th width="397">
+<Text id="405">ÐÐ·Ð²Ð»ÐµÐºÐ°ÐµÑ ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐŽÐ°ÑÑ, ÐºÐ°ÑÐ°ÑÑÐžÐµÑÑ ÐžÑÑÐŸÑÐžÑÐµÑÐºÐžÑ
+ ÑÐŸÐ±ÑÑÐžÐ¹, Ðž ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑ ÐžÑ
+ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Coverage.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+<Subsection id="document_processing_plugins">
+<Title>
+<Text id="406">ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ Greenstone</Text>
+</Title>
+<Content>
+<Table id="greenstone_plugins">
+<Title>
+<Text id="407">Greenstone plugins</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="60"/>
+<th width="72"/>
+<th width="236">
+<Text id="408"><b>ÐŠÐµÐ»Ñ</b></Text>
+</th>
+<th width="85">
+<Text id="409"><b>Ð¢ÐžÐ¿Ñ ÑÐ°Ð¹Ð»ÐŸÐ²</b></Text>
+</th>
+<th width="76">
+<Text id="410"><b>ÐÐ³ÐœÐŸÑÐžÑÑÐµÐŒÑÐµ ÑÐ°Ð¹Ð»Ñ</b></Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="411"><b>ÐÐ±ÑÐžÐµ</b></Text>
+</th>
+<th width="72">
+<Text id="412"><i>ArcPlug</i></Text>
+</th>
+<th width="236">
+<Text id="413">ÐÐ±ÑÐ°Ð±ÐŸÑÐºÐ° ÑÐ°Ð¹Ð»ÐŸÐ² ÑÐºÐ°Ð·Ð°ÐœÐœÑÑ
+ Ð² ÑÐ°Ð¹Ð»Ðµ archives.inf ÐºÐŸÑÐŸÑÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐ»Ñ  ÑÐ²ÑÐ·Ðž Ð¿ÑÐŸÑÐµÑÑÐŸÐ² ÐžÐŒÐ¿ÐŸÑÑÐ° Ðž ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ. ÐÐŸÐ»Ð¶ÐµÐœ Ð±ÑÑÑ Ð²ÐºÐ»ÑÑÐµÐœ(ÐµÑÐ»Ðž import.pl ÐœÐµ Ð±ÑÐŽÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ).</Text>
+</th>
+<th width="85">
+<Text id="414"><i>â</i></Text>
+</th>
+<th width="76">
+<Text id="415"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="416"><i>RecPlug</i></Text>
+</th>
+<th width="236">
+<Text id="417">ÐÐ±ÑÐ°ÑÐ°ÑÑÑ ÑÐµÑÐµÐ· ÐŽÐžÑÐµÐºÑÐžÐ²ÐœÑÑ ÑÑÑÑÐºÑÑÑÑ, Ð¿ÑÐŸÐ²ÐµÑÑÐµÑ, ÑÐ²Ð»ÑÐµÑÑÑ Ð»Ðž ÐžÐŒÑ ÑÐ°Ð¹Ð»Ð° ÐŽÐžÑÐµÐºÑÐŸÑÐžÐµÐ¹, Ðž ÐµÑÐ»Ðž ÑÐ²Ð»ÑÐµÑÑÑ, ÑÐŸ Ð²ÑÐµ ÑÐ°Ð¹Ð»Ñ ÑÑÐŸÐ¹ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž Ð²ÑÑÑÐ°ÐžÐ²Ð°ÑÑÑÑ Ð²ÐœÑÑÑÑ ÐºÐŸÐœÐ²ÐµÐ¹ÐµÑÐœÐŸÐ³ÐŸ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ. ÐÐ°Ð·ÐœÐ°ÑÐ°ÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐµÑÐ»Ðž ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° ÐŸÐ¿ÑÐžÑ use_metadata_files Ðž Ð¿ÑÐžÑÑÑÑÑÐ²ÑÑÑ ÑÐ°Ð¹Ð»Ñ metadata.xml.</Text>
+</th>
+<th width="85">
+<Text id="418"><i>â</i></Text>
+</th>
+<th width="76">
+<Text id="419"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="420"><i>GAPlug</i></Text>
+</th>
+<th width="236">
+<Text id="421">ÐÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑ ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ import.plÑÐ°Ð¹Ð»Ñ Ð°ÑÑ
+ÐžÐ²Ð° Greenstone. ÐÐŸÐ»Ð¶ÐµÐœ Ð±ÑÑÑ Ð²ÐºÐ»ÑÑÐµÐœ (ÐµÑÐ»Ðž import.pl ÐœÐµ Ð±ÑÐŽÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ðœ).</Text>
+</th>
+<th width="85">
+<Text id="422"><i>.xml</i></Text>
+</th>
+<th width="76">
+<Text id="423"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="424">TEXTPlug</Text>
+</th>
+<th width="236">
+<Text id="425">ÐÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑ ÑÐµÐºÑÑ, Ð¿ÐŸÐŒÐµÑÐ°Ñ ÐµÐ³ÐŸ ÐŒÐµÐ¶ÐŽÑ ÑÑÐ³Ð°ÐŒÐž (Ð¿ÑÐµÐŽÑÐŸÑÐŒÐ°ÑÐœÐ°Ñ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐ°).</Text>
+</th>
+<th width="85">
+<Text id="426"><i>.txt, .text</i></Text>
+</th>
+<th width="76">
+<Text id="427"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="428"><i>HTMLPlug</i></Text>
+</th>
+<th width="236">
+<Text id="429">ÐÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑ HTML, ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸ Ð¿ÐµÑÐµÐŒÐµÑÐ°Ñ Ð³ÐžÐ¿ÐµÑÑÑÑÐ»ÐºÐž. ÐÑÐ»Ðž ÑÐ²ÑÐ·Ð°ÐœÐœÐ°Ñ Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐŒ ÑÑÑÐ°ÐœÐžÑÐ° ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð²ÐœÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐŸ Ð²ÑÑÐ°Ð²Ð»ÑÐµÑÑÑ Ð¿ÑÐŸÐŒÐµÐ¶ÑÑÐŸÑÐœÐ°Ñ ÑÑÑÐ°ÐœÐžÑÐ°, Ð¿ÑÐµÐŽÑÐ¿ÑÐµÐ¶ÐŽÐ°ÑÑÐ°Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐŸ ÑÐŸÐŒ, ÑÑÐŸ Ð¿ÑÐž Ð¿ÐµÑÐµÑ
+ÐŸÐŽÐµ Ð¿ÐŸ ÑÑÑÐ»ÐºÐµ ÐŸÐœ Ð¿ÐŸÐºÐžÐœÐµÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÐ·Ð²Ð»ÐµÐºÐ°ÐµÑ Ð¿ÐŸÐŽÐ³ÐŸÑÐŸÐ²Ð»ÐµÐœÐœÑÐµ ÐŽÐ»Ñ ÐŽÐŸÑÑÑÐ¿Ð° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐ°ÐºÐžÐµ ÐºÐ°Ðº Title</Text>
+</th>
+<th width="85">
+<Text id="430"><i>.htm, .html, .cgi, .php, .asp, .shm, .shtml</i></Text>
+</th>
+<th width="76">
+<Text id="431"><i>.gif, .jpeg, .jpg, .png, .css, .rtf</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="432"><i>WordPlug</i></Text>
+</th>
+<th width="236">
+<Text id="433">ÐÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Microsoft Word, ÐžÐ·Ð²Ð»ÐµÐºÐ°ÐµÑ ÐŽÐ°ÐœÐœÑÐµ ÐŸÐ± Ð°Ð²ÑÐŸÑÐµ Ðž Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐµ Ðž ÑÐŸÑ
+ÑÐ°ÐœÑÐµÑ ÐŽÐžÐ°Ð³ÑÐ°ÐŒÐŒÑ Ðž ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ Ð² ÐœÐ°ÐŽÐ»ÐµÐ¶Ð°ÑÐžÑ
+ ÐŒÐµÑÑÐ°Ñ
+. ÐÐŸÐœÐ²ÐµÑÑÐžÐŸÐœÐœÑÐµ ÑÑÐžÐ»ÐžÑÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐµ ÑÑÐžÐŒ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµÐŒ, ÐžÐœÐŸÐ³ÐŽÐ° ÑÐŸÐ·ÐŽÐ°ÑÑ HTML, ÐºÐŸÑÐŸÑÑÐ¹ Ð¿Ð»ÐŸÑ
+ÐŸ ÐŸÑÑÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°Ðœ. ÐÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÐŒ, ÑÑÐŸÐ±Ñ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐÑ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÐ»Ðž ÐŸÑÐžÐ³ÐžÐœÐ°Ð»Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, ÐµÑÐ»Ðž ÑÐŸÑÐŒÐžÑÑÐµÑÐµ ÑÐ²ÐŸÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐžÐ· ÑÐ°Ð¹Ð»ÐŸÐ² WORD. Ð¢ÐµÐºÑÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÐ·Ð²Ð»ÐµÐºÐ°ÐµÑÑÑ ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÑÐ°, ÑÐ²Ð»ÑÐµÑÑÑ Ð°ÐŽÐµÐºÐ²Ð°ÑÐœÑÐŒ ÐŽÐ»Ñ Ð¿ÐŸÐžÑÐºÐ° Ðž ÑÐµÐ»ÐµÐ²ÐŸÐ³ÐŸ ÐžÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÑ.</Text>
+</th>
+<th width="85">
+<Text id="434"><i>.doc</i></Text>
+</th>
+<th width="76">
+<Text id="435"><i>.gif, .jpeg, .jpg, .png, .css, .rtf</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="436"><i>PDFPlug</i></Text>
+</th>
+<th width="236">
+<Text id="437">Processes PDF documents, extracting the first line of text as a title. The <i>pdftohtml</i> program fails on some PDF files. What happens is that the conversion process takes an exceptionally long time, and often an error message relating to the conversion process appears on the screen. If this occurs, the only solution that we can offer is to remove the offending document from the collection and re-import.</Text>
+</th>
+<th width="85">
+<Text id="438"><i>.pdf</i></Text>
+</th>
+<th width="76">
+<Text id="439"><i>.gif, .jpeg, .jpg, .png, .css, .rtf</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="440"><i>PSPlug</i></Text>
+</th>
+<th width="236">
+<Text id="441">ÐÐ±ÑÐ°Ð±ÐŸÑÐºÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² PostScript, Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑÑ ÐžÐ·Ð²Ð»ÐµÑÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+: ÐŽÐ°ÑÑ, Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ° Ðž ÐœÐŸÐŒÐµÑÐ° ÑÑÑÐ°ÐœÐžÑ.</Text>
+</th>
+<th width="85">
+<Text id="442"><i>.ps</i></Text>
+</th>
+<th width="76">
+<Text id="443"><i>.eps</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="444"><i>EMAILPlug</i></Text>
+</th>
+<th width="236">
+<Text id="445">ÐÐ±ÑÐ°Ð±ÐŸÑÐºÐ° E-mail ÑÐŸÐŸÐ±ÑÐµÐœÐžÐ¹ Ð¿ÑÑÐµÐŒ ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°ÐœÐžÑ Ð°Ð²ÑÐŸÑÐ°, ÑÐµÐŒÑ, ÐŽÐ°ÑÑ Ðž Ñ.ÐŽ. ÐÐ°ÐœÐœÐŸÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ Ð¿ÐŸÐºÐ° ÐœÐµ ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑ ÐŽÐŸÐ»Ð¶ÐœÑÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ ÑÐŸÐŸÐ±ÑÐµÐœÐžÑ Ð² ÐºÐŸÐŽÐžÑÐŸÐ²ÐºÐµ MIME - Ð·Ð°ÑÐ°ÑÑÑÑ ÐŸÐœÐž Ð²ÑÐ³Ð»ÑÐŽÑÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÑÑÐ°ÐœÐœÐŸ.</Text>
+</th>
+<th width="85">
+<Text id="446">Must end in digits or digits followed by <i>.Email</i></Text>
+</th>
+<th width="76">
+<Text id="447"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="448"><i>BibTexPlug</i></Text>
+</th>
+<th width="236">
+<Text id="449">ÐÐ±ÑÐ°Ð±ÐŸÑÐºÐ° ÑÐ°Ð¹Ð»ÐŸÐ² Ð±ÐžÐ±Ð»ÐžÐŸÐ³ÑÐ°ÑÐžÐž Ð² ÑÐŸÑÐŒÐ°ÑÐµ BibText </Text>
+</th>
+<th width="85">
+<Text id="450"><i>.bib</i></Text>
+</th>
+<th width="76">
+<Text id="451"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="452"><i>ReferPlug</i></Text>
+</th>
+<th width="236">
+<Text id="453">ÐÐ±ÑÐ°Ð±ÐŸÑÐºÐ° ÑÐ°Ð¹Ð»ÐŸÐ² Ð±ÐžÐ±Ð»ÐžÐŸÐ³ÑÐ°ÑÐžÐž Ð² ÑÐŸÑÐŒÐ°ÑÐµ refer</Text>
+</th>
+<th width="85">
+<Text id="454"><i>.bib</i></Text>
+</th>
+<th width="76">
+<Text id="455"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="456"><i>SRCPlug</i></Text>
+</th>
+<th width="236">
+<Text id="457">ÐÐ±ÑÐ°Ð±ÐŸÑÐºÐ° ÐžÑÑ
+ÐŸÐŽÐœÑÑ
+ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒ</Text>
+</th>
+<th width="85">
+<Text id="458"><i>Makefile, Readme, .c, .cc, .cpp, .h, .hpp, .pl, .pm, .sh</i></Text>
+</th>
+<th width="76">
+<Text id="459"><i>.o, .obj, .a, .so, .dll</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="460"><i>ImagePlug</i></Text>
+</th>
+<th width="236">
+<Text id="461">ÐÐ±ÑÐ°Ð±ÐŸÑÐºÐ° ÑÐ°Ð¹Ð»ÐŸÐ² ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐ¹ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐ¹. Ð Ð°Ð±ÐŸÑÐ°ÐµÑ ÑÐŸÐ»ÑÐºÐŸ Ð² UNIX.</Text>
+</th>
+<th width="85">
+<Text id="462"><i>.jpeg, .jpg, .gif, .png, .bmp, .xbm, .tif, .tiff</i></Text>
+</th>
+<th width="76">
+<Text id="463"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="464"><i>SplitPlug</i></Text>
+</th>
+<th width="236">
+<Text id="465">ÐÐŸÐŽÐŸÐ±ÐœÐŸ BasPlug Ðž ConvertToPlug, ÐŽÐ°ÐœÐœÐŸÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ ÐœÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð²ÑÐ·Ð²Ð°ÐœÐŸ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ, ÐŸÐŽÐœÐ°ÐºÐŸ ÐŸÐœÐŸ ÐŒÐŸÐ¶ÐµÑ Ð¿ÐŸÑÐ»ÐµÐŽÐŸÐ²Ð°ÑÑ Ð·Ð° byplugins Ð² ÑÐ»ÑÑÐ°Ðµ, ÐµÑÐ»Ðž ÑÑÐµÐ±ÑÐµÑÑÑ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐ° ÑÐ°Ð¹Ð»Ð°, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐµÐ³ÐŸ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ².</Text>
+</th>
+<th width="85">
+<Text id="466"><i>â</i></Text>
+</th>
+<th width="76">
+<Text id="467"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="468"><i>FOXPlug</i></Text>
+</th>
+<th width="236">
+<Text id="469">ÐÐ±ÑÐ°Ð±ÐŸÑÐºÐ° ÑÐ°Ð¹Ð»ÐŸÐ² dbt FoxBASE</Text>
+</th>
+<th width="85">
+<Text id="470"><i>.dbt, .dbf</i></Text>
+</th>
+<th width="76">
+<Text id="471"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="472"><i>ZIPPlug</i></Text>
+</th>
+<th width="236">
+<Text id="473">Ð Ð°Ð·Ð°ÑÑ
+ÐžÐ²Ð°ÑÐžÑ gzip, bzip, zip Ðž tar ÑÐ°Ð¹Ð»ÐŸÐ², ÐµÑÐ»Ðž ÐŽÐŸÑÑÑÐ¿ÐœÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐµ ÑÑÐµÐŽÑÑÐ²Ð° GNU.</Text>
+</th>
+<th width="85">
+<Text id="474"><i>.gzip, .bzip, .zip, .tar, .gz, .bz, .tgz, .taz</i></Text>
+</th>
+<th width="76">
+<Text id="475"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60">
+<Text id="476"><b>ÐÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž <br/> ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</b></Text>
+</th>
+<th width="72">
+<Text id="477"><i>PrePlug</i></Text>
+</th>
+<th width="236">
+<Text id="478">ÐÐ±ÑÐ°Ð±ÐŸÑÐºÐ° ÐºÐŸÐœÐµÑÐœÐŸÐ¹ HTML, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ PRESCRIPT, ÑÐ°Ð·Ð±ÐžÐµÐœÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐ°Ñ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Computer Science Technical Reports.</Text>
+</th>
+<th width="85">
+<Text id="479"><i>.html, .html.gz</i></Text>
+</th>
+<th width="76">
+<Text id="480"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="481"><i>GBPlug</i></Text>
+</th>
+<th width="236">
+<Text id="482">ÐÐ±ÑÐ°Ð±ÐŸÑÐºÐ° E-text (ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ³ÐŸ ÑÐµÐºÑÑÐ°) Project Gutenberg (ÐÑÐŸÐµÐºÑÐ° ÐÑÑÐµÐœÐ±ÐµÑÐ³), Ð²ÐºÐ»ÑÑÐ°ÑÑÐ°Ñ ÑÑÑÐœÐŸÐ¹ Ð²Ð²ÐŸÐŽ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž ÐŸ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ°Ñ
+.</Text>
+</th>
+<th width="85">
+<Text id="483"><i>.txt.gz, .html, .htm</i></Text>
+</th>
+<th width="76">
+<Text id="484"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="60"/>
+<th width="72">
+<Text id="485"><i>TCCPlug</i></Text>
+</th>
+<th width="236">
+<Text id="486">ÐÐ±ÑÐ°Ð±ÐŸÑÐºÐ° E-mail ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², Ð¿ÐŸÑÑÑÐ¿ÐžÐ²ÑÐžÑ
+ ÐŸÑ ÐµÐ¶ÐµÐœÐµÐŽÐµÐ»ÑÐœÐžÐºÐ° Computistsâ Weekly</Text>
+</th>
+<th width="85">
+<Text id="487">ÐÐ±ÑÐ·Ð°ÐœÐ° ÐœÐ°ÑÐžÐœÐ°ÑÑÑÑ Ñ tcc ÐžÐ»Ðž cw</Text>
+</th>
+<th width="76">
+<Text id="488"><i>â</i></Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="489">ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ ÐŽÐ»Ñ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐŒ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµÐŒ, ÑÐŸÑÐŒÐžÑÑÑÑÐžÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐŽÐ»Ñ Ð°ÐœÐ°Ð»ÐžÐ·Ð° ÐžÑÑ
+ÐŸÐŽÐœÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐž Ñ ÐµÐ³ÐŸ ÑÐŸÑÐŒÐ°ÑÐŸÐŒ. Ð€Ð°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÐµÑÐµÑÐžÑÐ»ÑÐµÑ Ð²ÑÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐµ Ð¿ÑÐž ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÐž ÑÐ°ÐŒÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð Ð¿ÑÐŸÑÐµÑÑÐµ ÐžÐŒÐ¿ÐŸÑÑÐ° ÐºÐ°Ð¶ÐŽÑÐ¹ ÑÐ°Ð¹Ð» ÐžÐ»Ðž ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ Ð°ÐœÐ°Ð»ÐžÐ·ÐžÑÑÑÑÑÑ ÐºÐ°Ð¶ÐŽÑÐŒ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµÐŒ ÐŽÐŸ ÑÐµÑ
+ Ð¿ÐŸÑ, Ð¿ÐŸÐºÐ° ÑÑÐµÐ±ÑÐµÐŒÑÐµ ÐœÐµ Ð±ÑÐŽÑÑ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐ°ÐœÑ - Ð±ÐŸÐ»ÐµÐµ ÑÐ°ÐœÐœÐžÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ ÐžÐŒÐµÑÑ Ð¿ÑÐžÐŸÑÐžÑÐµÑ Ð¿ÐµÑÐµÐŽ Ð±ÐŸÐ»ÐµÐµ Ð¿ÐŸÐ·ÐŽÐœÐžÐŒÐž. ÐÑÐ»Ðž ÐœÐµÑ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐ¹, ÐºÐŸÑÐŸÑÑÐµ ÑÐŒÐŸÐ³Ð»Ðž Ð±Ñ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐ°ÑÑ ÐœÐµÐºÐžÐ¹ ÑÐ°Ð¹Ð», Ð±ÑÐŽÐµÑ Ð²ÑÐŽÐ°ÐœÐŸ Ð¿ÑÐµÐŽÑÐ¿ÑÐµÐ¶ÐŽÐµÐœÐžÐµ (ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÐŸÐµ ÑÐŸÐŸÐ±ÑÐµÐœÐžÐµ ÐŸÐ± ÐŸÑÐžÐ±ÐºÐµ) Ðž Ð¿ÑÐŸÑÐµÑÑ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž Ð¿ÐµÑÐµÐ¹ÐŽÐµÑ Ðº ÑÐ»ÐµÐŽÑÑÑÐµÐŒÑ ÑÐ°Ð¹Ð»Ñ. (Ð­ÑÐŸ ÑÐŸÑ ÑÐ»ÑÑÐ°Ð¹, Ð³ÐŽÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐ° ÐŸÐ¿ÑÐžÑ block_exp - Ð¿ÑÐµÐŽÐŸÑÐ²ÑÐ°ÑÐµÐœÐžÐµ Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÑ ÑÐŸÐŸÐ±ÑÐµÐœÐžÐ¹ ÐŸÐ± ÐŸÑÐžÐ±ÐºÐµ ÐŽÐ»Ñ ÑÐµÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ², Ð¿ÑÐžÑÑÑÑÑÐ²ÐžÐµ ÐºÐŸÑÐŸÑÑÑ
+ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð±ÐµÐ· ÐžÑ
+ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž). Ð Ð¿ÑÐŸÑÐµÑÑÐµ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÑÐ° Ð¶Ðµ ÑÐ°ÐŒÐ°Ñ Ð¿ÑÐŸÑÐµÐŽÑÑÐ°, ÑÐŸÐ»ÑÐºÐŸ Ð²ÐŒÐµÑÑÐŸ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž archives ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ import.</Text>
+<Text id="490">Ð¡Ð¿ÐžÑÐŸÐº ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÑ
+ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐ¹ Greenstone Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœ Ð² Ð¢Ð°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="greenstone_plugins"/>. ÐÐ»Ñ Ð¿ÑÐŸÑ
+ÐŸÐ¶ÐŽÐµÐœÐžÑ Ð¿ÐŸ ÐŽÐµÑÐµÐ²Ñ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐ¹ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐ° ÑÐµÐºÑÑÑÐžÑ. Ð¥ÐŸÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐžÐŒÐ¿ÐŸÑÑÐ° Ðž ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐœÐµ Ð²ÑÐ¿ÐŸÐ»ÐœÑÑÑ ÑÐ²ÐœÑÑ ÑÐµÐºÑÑÑÐžÑ, ÐœÐµÐºÐŸÑÐŸÑÑÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ Ð¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐºÐŸÑÐ²ÐµÐœÐœÐŸÐ¹ ÑÐµÐºÑÑÑÐžÐµÐ¹ Ð¿ÑÐž Ð¿ÑÐŸÑ
+ÐŸÐ¶ÐŽÐµÐœÐžÐž ÐžÐŒÐµÐœ ÑÐ°Ð¹Ð»ÐŸÐ² ÐžÐ»Ðž ÐŽÐžÑÐµÐºÑÐŸÑÐžÐ¹ ÑÐµÑÐµÐ· ÐºÐŸÐœÐ²ÐµÐ¹ÐµÑ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐ¹. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÐŸÐµ Ð¿ÑÐŸÑ
+ÐŸÐ¶ÐŽÐµÐœÐžÐµ ÑÐµÐºÑÑÑÐžÐž Ð¿ÐŸ ÐŽÐµÑÐµÐ²Ñ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐ¹ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑÑÑ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµÐŒ RecPlug, Ð¿ÑÐµÐŽÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÐŒÐž ÐžÐŒÐµÐœÐœÐŸ ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ, ÐµÑÐ»Ðž, ÐºÐŸÐœÐµÑÐœÐŸ, ÐŸÐœÐŸ Ð±ÑÐŽÐµÑ Ð¿ÐŸÑÐ»ÐµÐŽÐœÐžÐŒ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐŒ Ð² ÐºÐŸÐœÐ²ÐµÐ¹ÐµÑÐµ. ÐÐŸÑÐ²ÐµÐœÐœÑÑ Ð¶Ðµ ÑÐµÐºÑÑÑÐžÑ Ð²ÑÐ·ÑÐ²Ð°ÑÑ ÑÐŸÐ»ÑÐºÐŸ ÐŽÐ²Ð° Ð¿ÐµÑÐ²ÑÑ
+ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ ÐžÐ· Ð¢Ð°Ð±Ð»ÐžÑÑ <CrossRef target="Table" ref="greenstone_plugins"/>.</Text>
+<Text id="491">ÐÐµÐºÐŸÑÐŸÑÑÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ Ð±ÑÐ»Ðž ÐœÐ°Ð¿ÐžÑÐ°ÐœÑ ÐŽÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÐžÐŒÐµÑÑÐžÑ
+ ÐŸÑÐŸÐ±ÑÐ¹ ÑÐŸÑÐŒÐ°Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², Ð¿ÐŸÐŽÐŸÐ±ÐœÐŸ E-text (ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐŒÑ ÑÐµÐºÑÑÑ), ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐŸÐŒÑ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Gutenberg. Ð­ÑÐž ÑÐ¿ÐµÑÐžÑÐžÑÐœÑÐµ ÐŽÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ ÐœÐ°Ñ
+ÐŸÐŽÑÑÑÑ Ð² ÐºÐ°ÑÐ°Ð»ÐŸÐ³Ðµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž perllib/plugins. ÐÐ°ÐœÐœÑÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÑ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÐŸÑÐŒÐµÐœÐžÑÑ ÐŸÐ±ÑÐžÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ Ñ ÑÐ°ÐºÐžÐŒ Ð¶Ðµ ÐžÐŒÐµÐœÐµÐŒ.</Text>
+<Text id="492">ÐÐµÐºÐŸÑÐŸÑÑÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑ Ð²ÐœÐµÑÐœÐžÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, ÐºÐŸÑÐŸÑÑÐµ Ð°ÐœÐ°Ð»ÐžÐ·ÐžÑÑÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐµ ÑÐ°ÑÑÐœÑÐµ ÑÐŸÑÐŒÐ°ÑÑ, ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐŽÐ»Ñ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž ÑÐµÐºÑÑÐ° - Microsoft Word ÐžÐ»Ðž HTML. ÐÐ±ÑÐµÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ ConvertToPlug Ð²ÑÐ·ÑÐ²Ð°ÐµÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐºÐŸÐœÐ²ÐµÑÑÐ°ÑÐžÐž Ðž Ð¿ÐµÑÐµÐŽÐ°ÐµÑ ÑÐµÐ·ÑÐ»ÑÑÐ°Ñ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž Ð»ÐžÐ±ÐŸ TEXTPlug, Ð»ÐžÐ±ÐŸ HTMLPlug. ÐÐ°Ð»ÐµÐµ ÐŒÑ ÐŸÑÑÐ°ÐœÐŸÐ²ÐžÐŒÑÑ ÐœÐ° ÑÑÐŸÐŒ Ð±ÐŸÐ»ÐµÐµ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸ.</Text>
+<Text id="493">ÐÐµÐºÐŸÑÐŸÑÑÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ ÐžÐŒÐµÑÑ ÐžÐœÐŽÐžÐ²ÐžÐŽÑÐ°Ð»ÑÐœÑÐµ ÐŸÐ¿ÑÐžÐž, ÐºÐŸÑÐŸÑÑÐµ ÑÐ¿ÑÐ°Ð²Ð»ÑÑÑ Ð¿ÑÐŸÑÐµÑÑÐ°ÐŒÐž Ð±ÐŸÐ»ÐµÐµ ÐŽÐµÑÐ°Ð»ÑÐœÐŸ, ÑÐµÐŒ ÑÑÐŸ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ ÐŸÐ±ÑÐžÐµ ÐŸÐ¿ÑÐžÐž. ÐÐœÐž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÑ Ð² Ð¢Ð°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="plugin-specific_options"/>.</Text>
+<Table id="plugin-specific_options">
+<Title>
+<Text id="494">ÐÐ¿ÑÐžÐž, ÑÐ¿ÐµÑÐžÑÐžÑÐœÑÐµ ÐŽÐ»Ñ Ð¿ÑÐžÐŸÐ¶ÐµÐœÐžÐ¹</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="495"><b>ÐÐ¿ÑÐžÑ</b></Text>
+</th>
+<th width="265">
+<Text id="496"><b>ÐŠÐµÐ»Ñ</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="497"><i>HTMLPlug</i></Text>
+</th>
+<th width="132">
+<Text id="498"><i>nolinks</i></Text>
+</th>
+<th width="265">
+<Text id="499">ÐÐµ ÐŸÐ±ÑÑÐ²Ð°ÑÑ ÑÑÑÐ»ÐºÐž Ð²ÐœÑÑÑÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð­ÑÐŸ ÑÑÐºÐŸÑÑÐµÑ Ð¿ÑÐŸÑÐµÑÑÑ ÐžÐŒÐ¿ÐŸÑÑÐ°/ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ, ÐŸÐŽÐœÐ°ÐºÐŸ ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÑÑÑÐ»ÐºÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŸÐ±ÐŸÑÐ²Ð°ÐœÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="500"><i>description_tags</i></Text>
+</th>
+<th width="265">
+<Text id="501">ÐÐœÑÐµÑÐ¿ÑÐµÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐ°Ð¹Ð»Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, ÐºÐ°Ðº ÐŸÐ¿ÐžÑÐ°ÐœÐŸ ÐœÐžÐ¶Ðµ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="502"><i>keep_head</i></Text>
+</th>
+<th width="265">
+<Text id="503">ÐÐµ ÐŸÑÐ±ÑÐ°ÑÑÐ²Ð°ÑÑ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐž HTML.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="504"><i>no_metadata</i></Text>
+</th>
+<th width="265">
+<Text id="505">ÐÐµ ÐžÑÐºÐ°ÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ (ÑÑÐŸ ÐŒÐŸÐ¶ÐµÑ ÑÐ²ÐµÐ»ÐžÑÐžÑÑ ÑÐºÐŸÑÐŸÑÑÑ Ð¿ÑÐŸÑÐµÑÑÐŸÐ² ÐžÐŒÐ¿ÐŸÑÑÐ°/ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ).</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="506"><i>metadata_fields</i></Text>
+</th>
+<th width="265">
+<Text id="507">ÐÑÐŸÐ±ÑÐ°ÑÑ ÐŽÐ»Ñ Ð¿ÐŸÑÐ»ÐµÐŽÑÑÑÐµÐ³ÐŸ ÐžÐ·Ð²Ð»ÐµÑÐµÐœÐžÑ ÐŸÑÐŽÐµÐ»ÐµÐœÐœÑÐµ Ð·Ð°Ð¿ÑÑÑÐŒÐž ÑÐžÐ¿Ñ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ (Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ Title). ÐÐµÑÐµÐžÐŒÐµÐœÐŸÐ²Ð°ÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŽÐ»Ñ ÑÐ°Ð¹Ð»Ð° Ð°ÑÑ
+ÐžÐ²Ð° Greenstone, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ tag, Ð³ÐŽÐµ tag-ÑÑÐŸ HTML-ÑÑÐ³, Ð° newname-ÑÑÐŸ ÐœÐŸÐ²ÐŸÐµ ÐžÐŒÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="508"><i>hunt_creator_metadata</i></Text>
+</th>
+<th width="265">
+<Text id="509">ÐÐ±ÐœÐ°ÑÑÐ¶ÐžÑÑ Ð²ÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŸÐ± Ð°Ð²ÑÐŸÑÑÑÐ²Ðµ Ðž Ð¿ÐŸÐŒÐµÑÑÐžÑÑ ÐžÑ
+ Ð² Ð°ÑÑ
+ÐžÐ² ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Greenstone Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÑÐžÐ¿Ð° Creator. Ð¢Ð°ÐºÐ¶Ðµ Ð²Ð°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð²ÐºÐ»ÑÑÐžÑÑ Creator, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐŸÐ¿ÑÐžÑ metadata_fields.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="510"><i>file_is_url</i></Text>
+</th>
+<th width="265">
+<Text id="511">ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÑÑÑ ÐŸÐ¿ÑÐžÑ, ÐµÑÐ»Ðž ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÑÑÑÑÐºÑÑÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐŽÑÑ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ð»Ð°ÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° web-Ð·ÐµÑÐºÐ°Ð»ÐžÑÐŸÐ²Ð°ÐœÐžÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="512"><i>assoc_files</i></Text>
+</th>
+<th width="265">
+<Text id="513">ÐÑÐµÐŽÑÑÐ°Ð²ÐžÑÑ ÐŸÐ±ÑÑÐœÐŸÐµ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÐµ ÐœÐ° ÑÐ·ÑÐºÐµ Perl, ÐŸÐ¿ÐžÑÑÐ²Ð°ÑÑÐµÐµ ÑÐžÐ¿Ñ ÑÐ°Ð¹Ð»ÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐŽÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÑ ÐºÐ°Ðº ÑÐ²ÑÐ·ÐœÑÐµ ÑÐ°Ð¹Ð»Ñ. ÐÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÑÑÐŸ .jpg, .jpeg, .gif, .png, .css</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="514"><i>rename_assoc_files</i></Text>
+</th>
+<th width="265">
+<Text id="515">ÐÐµÑÐµÐžÐŒÐµÐœÐŸÐ²Ð°ÑÑ ÑÐ²ÑÐ·Ð°ÐœÐœÑÐµ Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐŒ ÑÐ°Ð¹Ð»Ñ. ÐÐ° Ð²ÑÐµÐŒÑ ÑÑÐŸÐ³ÐŸ Ð¿ÑÐŸÑÐµÑÑÐ° ÐŽÐžÑÐµÐºÑÐžÐ²ÐœÐ°Ñ ÑÑÑÑÐºÑÑÑÐ° Ð»ÑÐ±ÑÑ
+ ÑÐ²ÑÐ·ÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² ÑÑÐ°Ð»Ð° Ð±Ñ ÐœÐ°ÐŒÐœÐŸÐ³ÐŸ Ð±ÐŸÐ»ÐµÐµ Ð¿ÐŸÐ²ÐµÑÑ
+ÐœÐŸÑÑÐœÐŸÐ¹ (ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð² ÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ, ÐºÐŸÐ³ÐŽÐ° Ð¿ÐŸÐŽ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐŸÑÐ²ÐµÐŽÐµÐœÐŸ ÐŸÐ³ÑÐ°ÐœÐžÑÐµÐœÐœÐŸÐµ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²ÐŸ).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="516"><i>HTMLPlug</i> and <br/><i>TEXTPlug</i></Text>
+</th>
+<th width="132">
+<Text id="517"><i>title_sub</i></Text>
+</th>
+<th width="265">
+<Text id="518">ÐÑÑÐ°Ð¶ÐµÐœÐžÐµ Ð·Ð°ÐŒÐµÐœÑ ÐœÐ° ÑÐ·ÑÐºÐµ Perl ÐŽÐ»Ñ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐŸÐ².</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="519"><i>PSPlug</i></Text>
+</th>
+<th width="132">
+<Text id="520"><i>extract_date</i></Text>
+</th>
+<th width="265">
+<Text id="521">ÐÐ·Ð²Ð»ÐµÑÑ ÐŽÐ°ÑÑ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐžÐ· Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ° PostScript Ðž ÑÐŸÑ
+ÑÐ°ÐœÐžÑÑ ÐºÐ°Ðº ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="522"><i>extract_title</i></Text>
+</th>
+<th width="265">
+<Text id="523">ÐÐ·Ð²Ð»ÐµÑÑ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÐžÐ· Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ° PostScript Ðž ÑÐŸÑ
+ÑÐ°ÐœÐžÑÑ ÐºÐ°Ðº ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ°.</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="132">
+<Text id="524"><i>extract_pages</i></Text>
+</th>
+<th width="265">
+<Text id="525">ÐÐ·Ð²Ð»ÐµÑÑ ÐœÐŸÐŒÐµÑÐ° ÑÑÑÐ°ÐœÐžÑ ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° PostScript Ðž ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐžÑ
+ Ðº ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ð°ÐŒ ÐºÐ°Ðº ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ñ ÑÑÐ³ÐŸÐŒ Pages.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="526"><i>RecPlug</i></Text>
+</th>
+<th width="132">
+<Text id="527"><i>use_metadata_files</i></Text>
+</th>
+<th width="265">
+<Text id="528">ÐÐ°Ð·ÐœÐ°ÑÐžÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŽÐ»Ñ ÑÐ°Ð¹Ð»Ð°, ÐºÐ°Ðº ÐŸÐ¿ÐžÑÐ°ÐœÐŸ ÐœÐžÐ¶Ðµ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="529"><i>ImagePlug</i></Text>
+</th>
+<th width="132">
+<Text id="530">Various options</Text>
+</th>
+<th width="265">
+<Text id="531">Ð¡ÐŒ. ImagePlug.pm.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="532"><i>SRCPlug</i></Text>
+</th>
+<th width="132">
+<Text id="533"><i>remove_prefix</i></Text>
+</th>
+<th width="265">
+<Text id="534">Ð¡ÐŸÐ·ÐŽÐ°ÑÑ ÐŸÐ±ÑÑÐœÐŸÐµ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÐµ ÐœÐ° ÑÐ·ÑÐºÐµ Perl ÐŽÐ»Ñ ÑÐ°Ð±Ð»ÐŸÐœÐ°, ÐºÐŸÑÐŸÑÑÐ¹ ÐŽÐŸÐ»Ð¶ÐµÐœ Ð±ÑÑÑ ÑÐŽÐ°Ð»ÐµÐœ ÐžÐ· ÐžÐŒÐµÐœÐž ÑÐ°Ð¹Ð»Ð°. Ð ÑÐµÐ¶ÐžÐŒÐµ Ð¿ÐŸ
+ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÑÐµÐ»ÐžÐºÐŸÐŒ ÑÐŽÐ°Ð»ÑÐµÑÑÑ Ð¿ÑÑÑ.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+<Subsection id="plugins_to_import_proprietary_formats">
+<Title>
+<Text id="535">ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ ÐŽÐ»Ñ ÐžÐŒÐ¿ÐŸÑÑÐ° ÑÐ°ÑÑÐœÑÑ
+ ÑÐŸÑÐŒÐ°ÑÐŸÐ²</Text>
+</Title>
+<Content>
+<Text id="536">ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÐœÐµÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÑ
+ ÑÐŸÑÐŒÐ°ÑÐŸÐ² ÑÐ²Ð»ÑÐµÑÑÑ ÑÑÑÐŽÐœÐŸÑÐ°Ð·ÑÐµÑÐžÐŒÐŸÐ¹ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÐŸÐ¹ ÐŽÐ»Ñ Ð²ÑÐµÑ
+ ÑÐžÑÑÐŸÐ²ÑÑ
+ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÑ
+ ÑÐžÑÑÐµÐŒ. Ð Ñ
+ÐŸÑÑ ÑÐ°Ð±ÐŸÑÐ°Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÑÐžÑ Ð¿ÐŸ ÑÑÐžÐŒ ÑÐŸÑÐŒÐ°ÑÐ°ÐŒ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð²Ð¿ÐŸÐ»ÐœÐµ ÐŽÐŸÑÑÑÐ¿ÐœÐŸÐ¹, ÐŸÐŽÐœÐ°ÐºÐŸ ÑÐ°ÐŒ Ð¿ÑÐµÐŽÐŒÐµÑ Ð²ÐœÐµÑÐµÐœÐžÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÐ¹ ÐŸÑÑÐ°ÐµÑÑÑ Ð² ÐœÐµÐ¹ Ð±ÐµÐ· ÐŸÑÑÐ°Ð¶ÐµÐœÐžÑ, ÑÑÐŸ ÐŸÑÑÐ°Ð²Ð»ÑÐµÑ ÑÑÑÐŽÐœÐŸÑÑÐž Ð¿ÑÐž Ð²ÐœÐµÑÐµÐœÐžÐž ÐžÐ·ÐŒÐµÐœÐµÐœÐžÐ¹. Ð¡ÐžÑÑÐµÐŒÐ° Greenstone Ð¿ÐŸÑÐ»Ð° Ð¿ÐŸ Ð¿ÑÑÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ GPL (GNU Public License) ÑÐ¿ÐµÑÐžÐ°Ð»ÑÐœÑÑ
+ ÑÑÐžÐ»ÐžÑ ÐŽÐ»Ñ ÐºÐŸÐœÐ²ÐµÑÑÐ°ÑÐžÐž, ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐ»Ðž ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÐ°ÐœÑ Ð»ÑÐŽÑÐŒÐž, ÑÐ¿ÐµÑÐžÐ°Ð»ÐžÐ·ÐžÑÑÑÑÐžÐŒÐžÑÑ ÐžÐŒÐµÐœÐœÐŸ ÐœÐ° ÑÐ°ÐºÐžÑ
+ ÑÐ°Ð±ÐŸÑÐ°Ñ
+. Ð£ÑÐžÐ»ÐžÑÑ ÐºÐŸÐœÐ²ÐµÑÑÐ°ÑÐžÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÑÐŸÑÐŒÐ°ÑÐŸÐ² Word Ðž PDF Ð²ÐºÐ»ÑÑÐµÐœÑ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ packages. ÐÐœÐž ÐºÐŸÐœÐ²ÐµÑÑÐžÑÑÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð² ÑÐµÐºÑÑ ÐžÐ»Ðž HTML. ÐÐ°ÑÐµÐŒ HTMLPlug Ðž TEXTPlug Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÑÑÑ ÐžÑ
+ Ð² ÑÐŸÑÐŒÐ°Ñ Ð°ÑÑ
+ÐžÐ²Ð° Greenstone. ConvertToPlug ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ Ð²ÐºÐ»ÑÑÐµÐœÐžÑ ÑÑÐžÑ
+ ÑÑÐžÐ»ÐžÑ. Ð ÑÐ°Ðº Ð¶Ðµ ÐºÐ°Ðº BasPlug, ÐœÐžÐºÐŸÐ³ÐŽÐ° ÐœÐµ Ð²ÑÐ·ÑÐ²Ð°ÐµÑÑÑ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ. ÐÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="plugin_inheritance_hierarchy"/> Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÑ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ, ÐœÐ°Ð¿ÐžÑÐ°ÐœÐœÑÐµ ÐŽÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ ÑÐŸÑÐŒÐ°ÑÐŸÐ². ConvertToPlug, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÑÑ
+ÐµÐŒÑ ÐŽÐžÐœÐ°ÐŒÐžÑÐµÑÐºÐŸÐ³ÐŸ ÑÐ°ÑÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ Perl Ð·Ð°Ð¿ÑÑÐºÐ°ÐµÑ TEXTPlug ÐžÐ»Ðž HTMLPlug Ð² Ð·Ð°Ð²ÐžÑÐžÐŒÐŸÑÑÐž ÐŸÑ ÑÐŸÑÐŒÐ°ÑÐ°, Ð² ÐºÐŸÑÐŸÑÑÐ¹ Ð±ÑÐ»Ðž ÐºÐŸÐœÐ²ÐµÑÑÐžÑÐŸÐ²Ð°ÐœÑ ÐžÑÑ
+ÐŸÐŽÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ.</Text>
+<Figure id="plugin_inheritance_hierarchy">
+<Title>
+<Text id="537">ÐÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐ°Ñ ÑÑÑÑÐºÑÑÑÐ° ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐžÑ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐ¹</Text>
+</Title>
+<File width="229" height="193" url="images/Dev_Fig_024.jpg"/>
+</Figure>
+<Text id="538">ÐÐŸÐ³ÐŽÐ° ConvertToPlug Ð¿ÐŸÐ»ÑÑÐ°ÐµÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ, ÐŸÐœ Ð²ÑÐ·ÑÐ²Ð°ÐµÑ gsConvert.pl (ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž GSDLHOME/bin/script) ÐŽÐ»Ñ Ð·Ð°Ð¿ÑÑÐºÐ° ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐ¹ ÑÑÐžÐ»ÐžÑÑ. ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑ Ð±ÑÐŽÐµÑ Ð¿ÑÐŸÐºÐŸÐœÐ²ÐµÑÑÐžÑÐŸÐ²Ð°Ðœ, ÐŸÐœ Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑÑÑ Ðº ConvertToPlug, ÐºÐŸÑÐŸÑÑÐ¹ Ð²ÑÐ·ÑÐ²Ð°ÐµÑ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž ÑÐµÐºÑÑÐ° ÐžÐ»Ðž HTML. ÐÑÐ±ÐŸÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ, Ð²ÑÐ·Ð²Ð°ÐœÐœÐŸÐµ ConvertToPlug, ÐžÐŒÐµÐµÑ ÐŸÐ¿ÑÐžÑ convertjto, ÐºÐŸÑÐŸÑÐ°Ñ ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ð°ÑÐ³ÑÐŒÐµÐœÑ textvum html, ÐŽÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ Ð¿ÑÐµÐŽÐŸÑÑÐžÑÐµÐ»ÑÐœÐŸÐ³ÐŸ ÑÐŸÑÐŒÐ°ÑÐ°. Ð Ð°Ð±ÐŸÑÐ° Ñ ÑÐµÐºÑÑÐŸÐŒ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ Ð·ÐœÐ°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð±ÑÑÑÑÐµÐµ, ÐŸÐŽÐœÐ°ÐºÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑ, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐœÑÐ¹ Ð² ÑÐŸÑÐŒÐ°ÑÐµ HTML, Ð²ÑÐ³Ð»ÑÐŽÐžÑ ÐœÐ°ÐŒÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÐµÑÐœÐµÐµ Ðž ÐŒÐŸÐ¶ÐµÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑ ÐžÐ»Ð»ÑÑÑÑÐ°ÑÐžÐž.</Text>
+<Text id="539">ÐÐœÐŸÐ³ÐŽÐ° ÐŽÐ»Ñ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÑÐŸÑÐŒÐ°ÑÐ° ÑÑÑÐµÑÑÐ²ÑÐµÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÑÐžÐ»ÐžÑ, Ðž gsConvert ÐŒÐŸÐ¶ÐµÑ Ð¿ÑÑÐ°ÑÑÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐžÑ
+. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÐŽÐ»Ñ ÐºÐŸÐœÐ²ÐµÑÑÐ°ÑÐžÐž Word Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐžÑÐµÐ»ÑÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÑÑÐžÐ»ÐžÑÑ wvWare, ÐŸÐŽÐœÐ°ÐºÐŸ ÐŸÐœÐ° ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ, ÑÐŸÐ·ÐŽÐ°ÐœÐœÑÐµ Ð² ÑÐµÐŽÐ°ÐºÑÐŸÑÐµ Word ÐœÐµ ÐœÐžÐ¶Ðµ 6 Ð²ÐµÑÑÐžÐž, Ð° Ð²ÐŸÑ ÑÑÐžÐ»ÐžÑÑ AnyToHTML, ÐºÐŸÑÐŸÑÐ°Ñ no-ÑÑÑÐµÑÑÐ²Ñ ÐžÐ·Ð²Ð»ÐµÐºÐ°ÐµÑ ÑÐŸÐ»ÑÐºÐŸ ÑÐµÐºÑÑÐŸÐ²ÑÐµ ÑÑÑÐŸÐºÐž, which essentially just extracts whatever text strings can be found, Ð²Ð¿ÐŸÐ»ÐœÐµ ÐŒÐŸÐ¶ÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŽÐ»Ñ ÐºÐŸÐœÐ²ÐµÑÑÐ°ÑÐžÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐžÐ· Word 5.</Text>
+<Text id="540">ÐšÐ°Ð³Ðž Ð·Ð°Ð³ÑÑÐ·ÐºÐž ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐœÐ²ÐµÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÑÐžÐ»ÐžÑÑ ÐŽÐ»Ñ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ Ð²ÐœÐµÑÐœÐžÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="541">Ð£ÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐœÐŸÐ²ÑÑ ÑÑÐžÐ»ÐžÑÑ Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐž Ñ ÑÑÐµÐ±ÐŸÐ²Ð°ÐœÐžÑÐŒÐž Greenstone (Ð¿ÐŸÐŒÐµÑÑÐžÑÑ ÐµÐµ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ <i>packages</i>).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="542">ÐÐœÐµÑÑÐž   ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð² gsConvert.pl ÐŽÐ»Ñ Ð¿ÐŸÑÐ»ÐµÐŽÑÑÑÐµÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÑÑÐžÐ»ÐžÑÑ. ÐÐœÐž Ð·Ð°ÐºÐ»ÑÑÐ°ÑÑÑÑ Ð² ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÐž ÐœÐŸÐ²ÐŸÐ³ÐŸ Ð¿ÑÐµÐŽÐ»ÐŸÐ¶ÐµÐœÐžÑ Ñ ÐŸÐ¿ÐµÑÐ°ÑÐŸÑÐŸÐŒ if Ð² ÑÑÐœÐºÑÐžÑ main, Ðž ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÐž ÑÑÐœÐºÑÐžÐž, Ð²ÑÐ·ÑÐ²Ð°ÑÑÐµÐ¹ ÐœÐŸÐ²ÑÑ ÑÑÐžÐ»ÐžÑÑ.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="543">W3.	ÐÐ°Ð¿ÐžÑÐ°ÑÑ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ ÐœÐ° ÑÑÐŸÐ²ÐµÐœÑ, ÑÐ»ÐµÐŽÑÑÐžÐ¹ Ð·Ð°  <i>ConvertToPlug</i>, ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ ÑÑÐŸÐ±Ñ Ð¿ÐµÑÐµÑ
+Ð²Ð°ÑÐžÑÑ ÐºÐŸÐœÐ²ÐµÑÑÐ°ÑÐžÑ Ð² ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐ¹ ÑÐŸÑÐŒÐ°Ñ, Ð¿ÐŸÐŽÐŒÐµÐœÐžÐ² ÐµÐ³ÐŸ ÐœÐ° ÐœÑÐ¶ÐœÑÐ¹.</Text>
+</NumberedItem>
+</NumberedList>
+</Content>
+</Subsection>
+<Subsection id="assigning_metadata_from_a_file">
+<Title>
+<Text id="544">ÐÐ°Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐžÐ· ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐ³ÐŸ ÑÐ°Ð¹Ð»Ð°</Text>
+</Title>
+<Content>
+<Text id="545">Ð¡ÑÐ°ÐœÐŽÐ°ÑÑÐœÐŸÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ RecPlug Ð¿ÐŸÐŒÐžÐŒÐŸ Ð²ÑÐµÐ³ÐŸ, ÐžÐŒÐµÐµÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ ÐœÐ°Ð·ÐœÐ°ÑÐ°ÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð²ÑÑÑÐœÑÑ (ÐžÐ»Ðž Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž), ÑÐŸÐ·ÐŽÐ°Ð²Ð°Ñ XML-ÑÐ°Ð¹Ð»Ñ. ÐÑÑÐ°ÐœÐŸÐ²ÐžÐŒÑÑ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐµÐµ ÐœÐ° ÑÑÐŸÐŒ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ Ð²Ñ ÑÐ°ÐŒÐž ÑÐŒÐŸÐ³Ð»Ðž ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ ÑÐ°Ð¹Ð»Ñ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐ»Ñ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ Ð²Ð°ÑÐžÑ
+ ÑÐŸÑÐŒÐ°ÑÐŸÐ². ÐÑÐ»Ðž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐ° ÐŸÐ¿ÑÐžÑ usejnetadatajiles, ÑÐŸ RecPlug ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ Ð²ÑÐ¿ÐŸÐŒÐŸÐ³Ð°ÑÐµÐ»ÑÐœÑÐ¹ ÑÐ°Ð¹Ð» ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ - metadata.xml. ÐÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="xml_format"/> Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœ XML Document Type Definition (DTD) ÐŽÐ»Ñ ÑÐŸÑÐŒÐ°ÑÐ° ÑÐ°Ð¹Ð»Ð° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, Ð° ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="xml_format_1"/> Ð¿ÑÐžÐ²ÐµÐŽÐµÐœ Ð¿ÑÐžÐŒÐµÑ ÑÐ°Ð¹Ð»Ð° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ metadata.xml.</Text>
+<Figure id="xml_format">
+<Title>
+<Text id="546">Ð€ÐŸÑÐŒÐ°Ñ XML. a) Document Type Definition (DTD); Ð±) Ð¿ÑÐžÐŒÐµÑ ÑÐ°Ð¹Ð»Ð°</Text>
+<SubTitle>
+<Text id="547">(a)</Text>
+</SubTitle>
+</Title>
+<CodeLine>&lt;!DOCTYPE GreenstoneDirectoryMetadata [</CodeLine>
+<CodeLine>   &lt;!ELEMENT DirectoryMetadata (FileSet*)&gt;</CodeLine>
+<CodeLine>   &lt;!ELEMENT FileSet (FileName+,Description)&gt;</CodeLine>
+<CodeLine>   &lt;!ELEMENT FileName (#PCDATA)&gt;</CodeLine>
+<CodeLine>   &lt;!ELEMENT Description (Metadata*)&gt;</CodeLine>
+<CodeLine>   &lt;!ELEMENT Metadata (#PCDATA)&gt;</CodeLine>
+<CodeLine>   &lt;ATTLIST Metadata name CDATA #REQUIRED&gt;</CodeLine>
+<CodeLine>   &lt;ATTLIST Metadata mode (accumulate|override) "override"&gt;</CodeLine>
+<CodeLine>]&gt;</CodeLine>
+</Figure>
+<Figure id="xml_format_1">
+<Title>
+<Text id="548"/>
+<SubTitle>
+<Text id="549">(b)</Text>
+</SubTitle>
+</Title>
+<CodeLine>&lt;?xml version="1.0" ?&gt;</CodeLine>
+<CodeLine>&lt;!DOCTYPE GreenstoneDirectoryMetadata SYSTEM</CodeLine>
+<CodeLine>"http://greenstone.org/dtd/GreenstoneDirectoryMetadata/<br/>1.0/GreenstoneDirectoryMetadata.dtd"&gt;</CodeLine>
+<CodeLine>&lt;DirectoryMetadata&gt;</CodeLine>
+<CodeLine>   &lt;FileSet&gt;</CodeLine>
+<CodeLine>       &lt;FileName&gt;nugget.*&lt;/FileName&gt;</CodeLine>
+<CodeLine>       &lt;Description&gt;</CodeLine>
+<CodeLine>       &lt;Metadata name="Title"&gt;Nugget Point Lighthouse&lt;/Metadata&gt;</CodeLine>
+<CodeLine>           &lt;Metadata name="Place" mode="accumulate"&gt;Nugget Point&lt;/Metadata&gt;</CodeLine>
+<CodeLine>       &lt;/Description&gt;</CodeLine>
+<CodeLine>   &lt;/FileSet&gt;</CodeLine>
+<CodeLine>   &lt;FileSet&gt;</CodeLine>
+<CodeLine>       &lt;FileName&gt;nugget-point-1.jpg&lt;/FileName&gt;</CodeLine>
+<CodeLine>       &lt;Description&gt;</CodeLine>
+<CodeLine>           &lt;Metadata name="Title"&gt;Nugget Point Lighthouse , The Catlins &lt;/Metadata&gt;</CodeLine>
+<CodeLine>           &lt;Metadata name="Subject"&gt;Lighthouse&lt;/Metadata&gt;</CodeLine>
+<CodeLine>       &lt;/Description&gt;</CodeLine>
+<CodeLine>   &lt;/FileSet&gt;</CodeLine>
+<CodeLine>&lt;/DirectoryMetadata&gt;</CodeLine>
+</Figure>
+<Text id="550">Ð Ð¿ÑÐžÐŒÐµÑÐµ Ð¿ÐŸÐºÐ°Ð·Ð°Ðœ ÑÐ°Ð¹Ð», ÐºÐŸÑÐŸÑÑÐ¹ ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐŽÐ²Ðµ ÑÑÑÑÐºÑÑÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. Ð ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÐžÐ· ÐºÐŸÑÐŸÑÑÑ
+, ÑÐ»ÐµÐŒÐµÐœÑ filename ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ ÑÐ°Ð¹Ð», Ðº ÐºÐŸÑÐŸÑÐŸÐŒÑ ÐŸÑÐœÐŸÑÑÑÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, Ð² Ð²ÐžÐŽÐµ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÐŸÐ³ÐŸ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÑ. Ð¢Ð°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ, <FileName>nugget. *</FileName> ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐœÐ° ÑÐŸ, ÑÑÐŸ Ð¿ÐµÑÐ²Ð°Ñ Ð·Ð°Ð¿ÐžÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŸÑÐœÐŸÑÐžÑÑÑ ÐºÐŸ Ð²ÑÐµÐŒ ÑÐ°Ð¹Ð»Ð°ÐŒ, ÑÑÐµ ÐžÐŒÑ ÐœÐ°ÑÐžÐœÐ°ÐµÑÑÑ Ñ "nugget"<FootnoteRef id="2"/>. ÐÐ»Ñ ÑÑÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐžÐ¿Ð° Title ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ ÐºÐ°Ðº "Nugget Point Lighthouse".</Text>
+<Text id="551">Ð­Ð»ÐµÐŒÐµÐœÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŸÑÑÐ°Ð±Ð°ÑÑÐ²Ð°ÑÑÑÑ Ð² ÑÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ, Ð² ÐºÐŸÑÐŸÑÐŸÐŒ ÐŸÐœÐž Ð¿ÐŸÑÐ²Ð»ÑÑÑÑÑ. ÐÑÐŸÑÐ°Ñ Ð·Ð°Ð¿ÐžÑÑ ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐžÐ¿Ð° Title ÐŽÐ»Ñ ÑÐ°Ð¹Ð»Ð° nuggetpoint- l.jpg ÐºÐ°Ðº "Nugget Point Lighthouse, The Catlins", ÑÐµÐŒ ÑÐ°ÐŒÑÐŒ ÐŸÑÐŒÐµÐœÑÑ Ð¿ÑÐµÐŽÑÐŽÑÑÐžÐµ ÑÐºÐ°Ð·Ð°ÐœÐžÑ. ÐÐŽÐµÑÑ ÑÐ°ÐºÐ¶Ðµ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐŸ Ð¿ÐŸÐ»Ðµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Subject.</Text>
+<Text id="552">ÐÐœÐŸÐ³ÐŽÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, ÐžÐŒÐµÑÑÐžÐµ ÑÐ¶Ðµ ÐœÐµÐºÐŸÑÐŸÑÐŸÐµ ÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ Ðž Ð¿ÐŸÐ»ÑÑÐ°Ñ ÐœÐŸÐ²ÑÐµ, ÐŽÐŸÐ»Ð¶ÐœÑ ÐžÑ
+ ÐœÐ°ÐºÐ°Ð¿Ð»ÐžÐ²Ð°ÑÑ, Ð²ÐŒÐµÑÑÐŸ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÐŸÑÐŒÐµÐœÑÑÑ Ð¿ÑÐµÐŽÑÐŽÑÑÐžÐµ. Ð­ÑÐŸ ÐŽÐµÐ»Ð°ÐµÑÑÑ Ð²Ð²ÐµÐŽÐµÐœÐžÐµÐŒ Ð°ÑÑÐžÐ±ÑÑÐ° mode=accumulate. Ð ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐµ ÐŸÐ¿ÑÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Place Ð¿ÐµÑÐµÐŒÐµÑÐ°ÐµÑÑÑ ÐœÐ° Ð¿ÐŸÐ·ÐžÑÐžÑ Ð²ÑÑÐµ Ðž ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ ÑÐ¿ÐŸÑÐŸÐ±ÐœÐŸÐ¹ ÐœÐ°ÐºÐ°Ð¿Ð»ÐžÐ²Ð°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ. ÐÐ»Ñ Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ° Ðº ÐµÐŽÐžÐœÑÑÐ²ÐµÐœÐœÐŸÑÑÐž Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ ÐŽÐ»Ñ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐœÐ°Ð¿ÐžÑÐžÑÐµ: <i>&lt;Metadata name=âPlaceâ mode=âoverrideâ&gt;New Zealand&lt;/Metadata&gt;</i>. Ð€Ð°ÐºÑÐžÑÐµÑÐºÐž, Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÐŸÐ¿ÑÑÑÐžÑÑ ÑÑÑ ÑÐ¿ÐµÑÐžÑÐžÐºÐ°ÑÐžÑ ÑÐµÐ¶ÐžÐŒÐ°, Ð¿ÐŸÑÐºÐŸÐ»ÑÐºÑ ÐºÐ°Ð¶ÐŽÑÐ¹ Ð¿ÐŸÑÐ»ÐµÐŽÑÑÑÐžÐ¹ ÑÐ»ÐµÐŒÐµÐœÑ ÐŸÑÐŒÐµÐœÑÐµÑ Ð¿ÑÐµÐŽÑÐŽÑÑÐžÐ¹, ÐµÑÐ»Ðž ÑÑÐŸ Ð·Ð°ÑÐ°ÐœÐµÐµ ÐœÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐŸ. ÐÐ»Ñ ÐœÐ°ÐºÐŸÐ¿Ð»ÐµÐœÐžÑ Ð² ÐœÐµÐºÐŸÑÐŸÑÐŸÐŒ Ð¿ÐŸÐ»Ðµ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð¿ÑÐž ÐºÐ°Ð¶ÐŽÐŸÐŒ Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÐž ÐºÐŸÑÐŸÑÑÑ
+ ÐŽÐŸÐ»Ð¶ÐœÐŸ Ð±ÑÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐœÐŸ: mode=accumulate.</Text>
+<Text id="553">ÐÐŸÐ³ÐŽÐ° ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° ÐŸÐ¿ÑÐžÑ usejnetadatajiles, RecPlug Ð¿ÑÐŸÐ²ÐµÑÑÐµÑ ÐºÐ°Ð¶ÐŽÑÑ Ð²Ð²ÐŸÐŽÐžÐŒÑÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ ÐŽÐ»Ñ XML ÑÐ°Ð¹Ð»Ð° metadata.xml Ðž Ð¿ÑÐžÐŒÐµÐœÑÐµÑ ÐµÐ³ÐŸ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ ÐºÐŸ Ð²ÑÐµÐŒ ÑÐ°Ð¹Ð»Ð°ÐŒ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž Ðž Ð¿ÐŸÐŽÐŽÐžÑÐµÐºÑÐŸÑÐžÐ¹.</Text>
+<Text id="554">ÐÐµÑ
+Ð°ÐœÐžÐ·ÐŒ ÑÐ°Ð±ÐŸÑÑ metadata.xml, ÐºÐŸÑÐŸÑÑÐ¹ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ Ð² RecPlug, ÑÐ²Ð»ÑÐµÑÑÑ ÐµÐŽÐžÐœÑÑÐ²ÐµÐœÐœÑÐŒ ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐŒ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð² ÐŽÐŸÐºÑÐŒÐµÐœÑÐµ. ÐÑÐµÐœÑ Ð¿ÑÐŸÑÑÐŸ ÐœÐ°Ð¿ÐžÑÐ°ÑÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ, ÐºÐŸÑÐŸÑÑÐµ ÑÐŒÐŸÐ³ÑÑ Ð¿ÑÐžÐœÐžÐŒÐ°ÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, ÑÐ¿ÐµÑÐžÑÐžÑÐœÑÐµ ÐŽÐ»Ñ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÑÐŸÑÐŒÐ°ÑÐŸÐ².</Text>
+</Content>
+</Subsection>
+<Subsection id="tagging_document_files">
+<Title>
+<Text id="555">ÐÐ°ÑÐºÐžÑÐŸÐ²ÐºÐ° ÑÐ°Ð¹Ð»Ð° ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÑÑÐ³Ð°ÐŒÐž</Text>
+</Title>
+<Content>
+<Text id="556">Ð§Ð°ÑÑÐŸ Ð²ÐŸÐ·ÐœÐžÐºÐ°ÐµÑ Ð¿ÐŸÑÑÐµÐ±ÐœÐŸÑÑÑ ÑÑÑÑÐºÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐžÑÑ
+ÐŸÐŽÐœÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÐœÐ° ÑÐ°Ð·ÐŽÐµÐ»Ñ Ðž Ð¿ÐŸÐŽÑÐ°Ð·ÐŽÐµÐ»Ñ. Ð¡ ÑÐµÐ»ÑÑ Ð¿ÑÐµÐŽÐŸÑÐ²ÑÐ°ÑÐµÐœÐžÑ ÐœÐ°ÑÑÑÐµÐœÐžÐ¹ Ð² ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐŸÐ¹ ÑÑÑÑÐºÑÑÑÐµ ÑÑÐ° ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŽÐŸÐ»Ð¶ÐœÐ° Ð±ÑÑÑ ÑÐŸÐŸÐ±ÑÐµÐœÐ° ÑÐžÑÑÐµÐŒÐµ Greenstone. ÐÐŸÐŒÐžÐŒÐŸ ÑÑÐŸÐ³ÐŸ, ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, ÐŸÐ±ÑÑÐœÐŸ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐž, ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÑÐ²ÑÐ·Ð°ÐœÑ Ñ ÐºÐ°Ð¶ÐŽÑÐŒ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐŒ ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐŒ ÐžÐ»Ðž Ð¿ÐŸÐŽÑÐ°Ð·ÐŽÐµÐ»ÐŸÐŒ.</Text>
+<Text id="557">Ð¡Ð°ÐŒÑÐ¹ Ð¿ÑÐŸÑÑÐŸÐ¹ ÑÐ¿ÐŸÑÐŸÐ± ÑÐŽÐµÐ»Ð°ÑÑ ÑÑÐŸ Ð·Ð°ÐºÐ»ÑÑÐ°ÐµÑÑÑ Ð² Ð¿ÑÐŸÑÑÐŸÐŒ ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐž ÐžÑÑ
+ÐŸÐŽÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ². HTML-Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ ÐžÐŒÐµÐµÑ ÐŸÐ¿ÑÐžÑ description_tags, ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑ ÑÑÐ³Ðž Ð² ÑÐµÐºÑÑÐµ:</Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>   &lt;Description&gt;</CodeLine>
+<CodeLine>       &lt;Metadata name="Title"&gt; Realizing human rights for poor people: Strategies for achieving the international development targets&lt;/Metadata&gt;</CodeLine>
+<CodeLine>   &lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="558"><i>(text of section goes here)</i></Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="559">ÐÐ°ÑÐºÐµÑÑ &lt;!-- âŠ --&gt; ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ Ð² HTML ÐŽÐ»Ñ Ð²ÑÑÐ°Ð²ÐºÐž ÐºÐŸÐŒÐŒÐµÐœÑÐ°ÑÐžÐµÐ²; ÑÐ°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ, ÑÑÐž ÑÑÐ³Ðž ÐœÐµ Ð±ÑÐŽÑÑ Ð²Ð»ÐžÑÑÑ ÐœÐ° ÐŸÐ±ÑÐµÐµ ÑÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. Ð ÑÐ°ÑÑÐž Description ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÑ ÐŽÑÑÐ³ÐžÐµ Ð²ÐžÐŽÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÐœÐŸ Ð² ÐœÐ°ÑÐµÐŒ ÑÐ»ÑÑÐ°Ðµ ÑÑÐŸ ÑÐŽÐµÐ»Ð°ÐœÐŸ ÐœÐµ Ð±ÑÐ»ÐŸ. ÐÐŸÐŒÐžÐŒÐŸ ÑÑÐŸÐ³ÐŸ, ÑÑÐ³Ðž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ -Ð²Ð»ÐŸÐ¶ÐµÐœÐœÑÐŒÐž. Ð¢Ð°Ðº ÑÑÑÐŸÐºÐ° Ð¿ÐŸÐŒÐµÑÐµÐœÐœÐ°Ñ text of section goes here (ÑÐµÐºÑÑ ÑÐ°Ð·ÐŽÐµÐ»Ð°), Ð² ÐŽÐ°Ð»ÑÐœÐµÐ¹ÑÐµÐŒ ÐŒÐŸÐ¶ÐµÑ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð² ÑÐµÐ±Ñ Ð¿ÐŸÐŽÑÐ°Ð·ÐŽÐµÐ»Ñ, ÐœÐ°Ð¿ÑÐžÐŒÐµÑ,</Text>
+<Text id="560"><i>(text of first part of section goes here)</i></Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>   &lt;Description&gt;</CodeLine>
+<CodeLine>       &lt;Metadata name="Title"&gt; The international development targets&lt;/Metadata&gt;</CodeLine>
+<CodeLine>   &lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="561"><i>(text of subsection goes here)</i></Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="562"><i>(text of last part of section goes here)</i></Text>
+<Text id="563">Ð­ÑÐžÐŒÐž ÑÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÑÐŒÐž Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑÐŒÐž ÐŸÐ±Ð»Ð°ÐŽÐ°ÐµÑ Ð»ÑÐ±ÐŸÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÐµÐµ HTMLPlug. Ð ÑÐ°ÑÑÐœÐŸÑÑÐž, Word-Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ ÐºÐŸÐœÐ²ÐµÑÑÐžÑÑÑÑ ÐžÑÑ
+ÐŸÐŽÑÐ¹ ÑÐ°Ð¹Ð» Ð² HTML, ÑÐ°Ðº ÑÑÐŸ Ð² ÑÐ»ÑÑÐ°Ðµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÑÐŸÑÐŒÐ°ÑÐ° Word (Ðž RTF), ÐžÐ·Ð²Ð»ÐµÑÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ Ð¿ÐŸ ÑÑÐµÐœÐ°ÑÐžÑ ÐžÐ·Ð²Ð»ÐµÑÐµÐœÐžÑ ÐžÑ
+ ÐžÐ· ÑÐŸÑÐŒÐ°ÑÐ° HTML. (Ð ÑÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ Ð¿ÑÐžÐŽÐµÑÑÑ ÐœÐµÐŒÐœÐŸÐ³ÐŸ Ð¿ÐŸÑÐ°Ð±ÐŸÑÐ°ÑÑ, Ñ.Ðº. ÐŽÐ»Ñ ÐœÐŸÑÐŒÐ°Ð»ÑÐœÐŸÐ¹ ÐºÐŸÐœÐ²ÐµÑÑÐ°ÑÐžÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Word Ð² ÑÐŸÑÐŒÐ°Ñ HTML ÑÑÐµÐ±ÑÐµÑÑÑ ÑÐŽÐ°Ð»ÐžÑÑ Ð¿ÐŸÐ±ÐŸÑÐœÑÐµ ÑÐžÐŒÐ²ÐŸÐ»Ñ "&lt;" Ðž "&gt;"; ÐŒÑ Ð¿ÑÐŸÐžÐ·Ð²ÐµÐ»Ðž ÐžÑ
+ ÑÐ¿ÐŸÑÑÐŽÐŸÑÐµÐœÐžÐµ, ÐœÐµ Ð¿ÑÐžÐœÐžÐŒÐ°Ñ Ð²ÐŸ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ Ð¿ÑÐžÐ²ÐµÐŽÐµÐœÐœÑÐµ Ð²ÑÑÐµ ÑÐ¿ÐµÑÐžÑÐžÐºÐ°ÑÐžÐž). ÐÐ±ÑÐ°ÑÐžÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ ÐœÐ° ÑÐŸ, ÑÑÐŸ ÑÐŸÑÐœÐŸ ÑÐ°ÐºÐŸÐ¹ Ð¶Ðµ ÑÐŸÑÐŒÐ°Ñ, ÐºÐ°Ðº ÐŸÐ¿ÐžÑÐ°ÐœÐŸ Ð²ÑÑÐµ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ðž Ð² ÑÐ»ÑÑÐ°Ðµ Word - ÑÐ°Ð¹Ð»ÐŸÐ², ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐžÑ
+ "&lt;!â" Ðž"~&gt;". ÐšÑÐžÑÑ Ðž ÐžÐœÑÐµÑÐ²Ð°Ð» ÐžÐ³ÐœÐŸÑÐžÑÑÑÑÑÑ.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="classifiers">
+<Title>
+<Text id="564">ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ</Text>
+</Title>
+<Content>
+<Text id="565">ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐžÐœÐŽÐµÐºÑÐŸÐ² Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÐžÐŒÐµÑÐ°ÐŒÐž ÑÐ²Ð»ÑÑÑÑÑ ÐžÐœÐŽÐµÐºÑÑ Titles A-Z ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž dlpeople, Ð° ÑÐ°ÐºÐ¶Ðµ ÐžÐœÐŽÐµÐºÑÑ Subject, How to, Organisation Ðž Titles A-Z Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Humanity Development Library - ÐŸÐŽÐœÐŸÐ¹ ÐžÐ· Ð¿ÐŸÐŽÐŒÐœÐŸÐ¶ÐµÑÑÐ²Ð° ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹. ÐÐ°Ð²ÐžÐ³Ð°ÑÐžÐŸÐœÐœÐŸÐµ ÐŒÐµÐœÑ Ð² Ð²ÐµÑÑ
+ÐœÐµÐ¹ ÑÐ°ÑÑÐž ÑÐºÑÐ°ÐœÐ° ÐœÐ° ÑÐžÑÑÐœÐºÐ°Ñ
+ 3 Ðž 8Ð° ÐžÐŒÐµÐµÑ ÑÑÐœÐºÑÐžÑ search, ÐºÐŸÑÐŸÑÐ°Ñ Ð²ÑÐµÐ³ÐŽÐ° ÑÐœÐ°Ð±Ð¶ÐµÐœÐ° ÐºÐœÐŸÐ¿ÐºÐ°ÐŒÐž ÐŽÐ»Ñ Ð²ÑÐµÑ
+ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐ»Ðž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÑ. ÐÐœÑÐŸÑÐŒÐ°ÑÐžÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ ÐŽÐ»Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐž Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°, ÑÐŸÑ
+ÑÐ°ÐœÑÐµÑÑÑ Ð² ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ Ð±Ð°Ð·Ðµ ÐŽÐ°ÐœÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐºÑÐŽÐ° ÐŸÐœÐ° Ð¿ÐŸÐŒÐµÑÐ°ÐµÑÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ°ÐŒÐž, Ð²ÑÐ·ÑÐ²Ð°ÐµÐŒÑÐŒÐž ÐœÐ° ÐºÐŸÐœÐµÑÐœÐŸÐ¹ ÑÑÐ°ÐŽÐžÐž ÑÐ°Ð±ÐŸÑÑ buildcol.pl.</Text>
+<Figure id="azlist_classifier">
+<Title>
+<Text id="566">ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ <i>AZList</i></Text>
+</Title>
+<File width="390" height="182" url="images/Dev_Fig_026.png"/>
+</Figure>
+<Text id="567">ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ, Ð¿ÐŸÐŽÐŸÐ±ÐœÐŸ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑÐŒ, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑÑÑ Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÑÑÐµÑÑÐ²ÑÐµÑ ÑÑÑÐŸÐºÐ°, ÐœÐ°ÑÐžÐœÐ°ÑÑÐ°ÑÑÑ Ñ ÐºÐ»ÑÑÐµÐ²ÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð° classify Ðž ÑÐŸÐ¿ÑÐŸÐ²ÐŸÐ¶ÐŽÐ°ÐµÐŒÐ°Ñ ÐžÐŒÐµÐœÐµÐŒ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ° Ðž ÑÑÐµÐ±ÑÐµÐŒÑÑ
+ ÐŸÐ¿ÑÐžÐ¹. ÐÑÐœÐŸÐ²ÐœÐŸÐ¹ ÑÐ°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐŸÐ±ÑÑÐ¶ÐŽÐµÐœÐœÑÐ¹ Ð² Ð Ð°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Section" ref="configuration_file"/>, Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÑÑÑÐŸÐºÑ classify AZList âmetadata Title, ÐºÐŸÑÐŸÑÐ°Ñ ÑÐŸÐ·ÐŽÐ°ÐµÑ Ð°Ð»ÑÐ°Ð²ÐžÑÐœÑÐ¹ ÑÐ¿ÐžÑÐŸÐº Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐŸÐ², ÐžÐ·Ð²Ð»ÐµÐºÐ°Ñ ÐžÑ
+ ÐžÐ· Ð¿ÐŸÐ»Ñ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Title, Ð·Ð°ÑÐµÐŒ ÑÐŸÑÑÐžÑÑÐµÑ ÐžÑ
+ Ðž ÑÐ°Ð·Ð±ÐžÐ²Ð°ÐµÑ Ð¿ÐŸ Ð°Ð»ÑÐ°Ð²ÐžÑÐœÑÐŒ ÐŽÐžÐ°Ð¿Ð°Ð·ÐŸÐœÐ°ÐŒ. ÐÑÐžÐŒÐµÑ Ð¿ÐŸÐºÐ°Ð·Ð°Ðœ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="azlist_classifier"/>.</Text>
+<Figure id="list_classifier">
+<Title>
+<Text id="568">ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ <i>List</i></Text>
+</Title>
+<File width="394" height="143" url="images/Dev_Fig_028.png"/>
+</Figure>
+<Text id="569">ÐÑÐŸÑÑÐµÐ¹ÑÐžÐ¹ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ, ÐœÐ°Ð·Ð²Ð°ÐœÐœÑÐ¹ List, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="list_classifier"/>. ÐÐœ ÑÐŸÐ·ÐŽÐ°ÐµÑ ÐŸÑÑÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐ¹ ÑÐ¿ÐžÑÐŸÐº ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÐŸÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðž ÐŸÑÐŸÐ±ÑÐ°Ð¶Ð°ÐµÑ ÐµÐ³ÐŸ Ð±ÐµÐ· ÐºÐ°ÐºÐžÑ
+-Ð»ÐžÐ±ÐŸ Ð°Ð»ÑÐ°Ð²ÐžÑÐœÑÑ
+ Ð¿ÐŸÐŽÑÐ°Ð·ÐŽÐµÐ»ÐŸÐ². ÐÑÐžÐŒÐµÑÐŸÐŒ ÐŒÐŸÐ³ÑÑ Ð¿ÐŸÑÐ»ÑÐ¶ÐžÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ how to ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐ·ÐŽÐ°ÐœÑ ÑÑÑÐŸÐºÐŸÐ¹ classify List âmetadata Howto Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž<FootnoteRef id="3"/>. ÐÑÑÐ³ÐŸÐ¹ ÑÐœÐžÐ²ÐµÑÑÐ°Ð»ÑÐœÐŸÐ¹ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ ÑÐ¿ÐžÑÐºÐ° DateList, ÐºÐŸÑÐŸÑÑÐ¹ Ð³ÐµÐœÐµÑÐžÑÑÐµÑ ÑÐ¿ÐžÑÐŸÐº ÐŽÐ°Ñ, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="datelist_classifier"/>. (ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ DateList ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Greenstone Archives).</Text>
+<Figure id="datelist_classifier">
+<Title>
+<Text id="570">ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ <i>DateList</i></Text>
+</Title>
+<File width="390" height="159" url="images/Dev_Fig_030.png"/>
+</Figure>
+<Text id="571">ÐÑÑÐ³ÐžÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ Ð³ÐµÐœÐµÑÐžÑÑÑÑ ÑÑÑÑÐºÑÑÑÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°, ÐºÐŸÑÐŸÑÑÐµ ÑÐ²Ð»ÑÑÑÑÑ ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐžÐŒÐž. ÐÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐžÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ Ð² ÑÐ»ÑÑÐ°Ðµ Ð¿ÑÐµÐŽÐŒÐµÑÐœÑÑ
+ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐ¹ Ðž Ð¿ÐŸÐŽÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐ¹, Ð° ÑÐ°ÐºÐ¶Ðµ ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐŸÐœÐœÑÑ
+ ÐžÐµÑÐ°ÑÑ
+ÐžÐ¹. Ð€Ð°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÑÑÑÐŸÐºÑ classify Hierarchy âhflle sub.txt âmetadata Subject âsort Title, Ðž ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="hierarchy_classifier"/> Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÐžÐŽÐµÑÑ Ð¿ÑÐµÐŽÐŒÐµÑÐœÑÑ ÐžÐµÑÐ°ÑÑ
+ÐžÑ, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐœÑÑ Ð² Ð±ÑÐŸÑÐ·ÐµÑÐµ. ÐÐºÐŸÐœÐºÐ° "ÐºÐœÐžÐ¶ÐœÐ°Ñ Ð¿ÐŸÐ»ÐºÐ°" Ñ Ð²ÑÐŽÐµÐ»ÐµÐœÐœÑÐŒ Ð¶ÐžÑÐœÑÐŒ ÑÑÐžÑÑÐŸÐŒ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐŸÐŒ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÑ Ð¿ÐµÑÐ²ÑÐ¹ ÑÑÐŸÐ²ÐµÐœÑ; Ð²ÑÑÐµ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÐžÐŽÐµÑÑ Ð¿ÑÐµÐŽÐŒÐµÑÐœÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÑ, Ðº ÐºÐŸÑÐŸÑÐŸÐ¹ Ð¿ÑÐžÐœÐ°ÐŽÐ»ÐµÐ¶ÐžÑ ÑÐ¿ÐŸÐŒÑÐœÑÑÑÐ¹ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº. Ð ÑÑÐŸÐŒ Ð¿ÑÐžÐŒÐµÑÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÐ°Ñ ÐžÐµÑÐ°ÑÑ
+ÐžÑ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² Ð¿ÑÐŸÑÑÐŸÐŒ ÑÐµÐºÑÑÐŸÐ²ÐŸÐŒ ÑÐŸÑÐŒÐ°ÑÐµ Ð² ÑÐ°Ð¹Ð»Ðµ sub.txt.</Text>
+<Figure id="hierarchy_classifier">
+<Title>
+<Text id="572">ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ <i>Hierarchy</i></Text>
+</Title>
+<File width="394" height="198" url="images/Dev_Fig_032.png"/>
+</Figure>
+<Text id="573">ÐÑÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ Ð³ÐµÐœÐµÑÐžÑÑÑÑ ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÑÑ ÑÑÑÑÐºÑÑÑÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ ÐžÐœÐŽÐµÐºÑÐ° Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°. ÐÐ° ÑÐ°ÐŒÐŸÐŒ ÐœÐžÐ¶ÐœÐµÐŒ ÑÑÐŸÐ²ÐœÐµ ÐžÐµÑÐ°ÑÑ
+ÐžÐž (Ñ.Ðµ. Ð»ÐžÑÑÐµ) ÐŸÐ±ÑÑÐœÐŸ ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ, ÐœÐŸ Ð² ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ°Ñ
+ - ÑÑÐŸ ÑÐ°Ð·ÐŽÐµÐ»Ñ. ÐÐœÑÑÑÐµÐœÐœÐžÐµ ÑÐ·Ð»Ñ ÐžÐµÑÐ°ÑÑ
+ÐžÐž - ÑÑÐŸ Vlist, Hlist, ÐžÐ»Ðž Datelist. Vlist - ÑÑÐŸ ÑÐ¿ÐžÑÐŸÐº ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ², Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÑÑ
+ Ð²ÐµÑÑÐžÐºÐ°Ð»ÑÐœÐŸ, Ð²ÐœÐžÐ·Ñ ÑÑÑÐ°ÐœÐžÑÑ, Ð¿ÐŸÐŽÐŸÐ±ÐœÐŸ ÐžÐœÐŽÐµÐºÑÑ "how to" Ð² ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (ÑÐŒ.ÑÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="list_classifier"/>). Hlist ÑÐ°ÑÐ¿ÐŸÐ»Ð°Ð³Ð°ÐµÑÑÑ Ð³ÐŸÑÐžÐ·ÐŸÐœÑÐ°Ð»ÑÐœÐŸ. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, AZList, Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐœÑÐ¹ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="azlist_classifier"/>,- ÑÑÐŸ ÐžÐµÑÐ°ÑÑ
+ÐžÑ Ñ ÐŽÐ²ÑÐŒÑ ÑÑÐŸÐ²ÐœÑÐŒÐž Ð²ÐœÑÑÑÐµÐœÐœÐžÑ
+ ÑÐ·Ð»ÐŸÐ², ÑÐŸÑÑÐŸÑÑÐžÑ
+ ÐžÐ· Hlist (Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœ ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐŒ A-Z ) Ñ ÐŽÐŸÑÐµÑÐœÐžÐŒÐž Ð·Ð°Ð¿ÐžÑÑÐŒÐž Vlists. Ð­ÑÐž ÐŽÐŸÑÐµÑÐœÐžÐµ Ð·Ð°Ð¿ÐžÑÐž ÑÐ²Ð»ÑÑÑÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒÐž. Datelist (ÑÐŒ. ÑÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="datelist_classifier"/>) ÑÐ²Ð»ÑÐµÑÑÑ ÐŸÑÐŸÐ±ÑÐŒ Ð²ÐžÐŽÐŸÐŒ Vlist, Ðž Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑ Ð²ÑÐ±ÐŸÑÐºÑ Ð¿ÐŸ Ð³ÐŸÐŽÑ Ðž  ÐŒÐµÑÑÑÑ.</Text>
+<Text id="574">Ð¡ÑÑÐŸÐºÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑ ÐŽÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ² Ð² ÑÐ°Ð¹Ð»Ð°Ñ
+ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐžÑ
+ Ð°ÑÐ³ÑÐŒÐµÐœÑ metadata, ÐžÐŽÐµÐœÑÐžÑÐžÑÐžÑÑÑÑÐžÐ¹ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, Ð¿ÐŸ ÐºÐŸÑÐŸÑÑÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÑÐžÑÐŸÐ²Ð°ÐœÑ Ðž ÐŸÑÑÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÑ. ÐÑÐ±ÐŸÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐºÐŸÑÐŸÑÐ°Ñ ÐœÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž, Ð±ÑÐŽÐµÑ ÐžÐ·Ð±Ð°Ð²Ð»ÐµÐœ ÐŸÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ° (ÐœÐŸ ÐŸÐœ Ð²ÑÐµ Ð¶Ðµ ÐžÐœÐŽÐµÐºÑÐžÑÑÐµÑÑÑ, Ðž ÑÐ»ÐµÐŽÐŸÐ²Ð°ÑÐµÐ»ÑÐœÐŸ, ÐŽÐŸÑÑÑÐ¿ÐµÐœ ÐŽÐ»Ñ Ð¿ÐŸÐžÑÐºÐ°). ÐÑÐ»Ðž ÐœÐžÐºÐ°ÐºÐŸÐ¹ Ð¿Ð°ÑÐ°ÐŒÐµÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐœÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœ, Ð²ÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð²ÐºÐ»ÑÑÐ°ÑÑÑÑ Ð² ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ Ð² ÑÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ, Ð² ÐºÐŸÑÐŸÑÐŸÐŒ ÐŸÐœÐž Ð¿ÐŸÑÑÑÐ¿Ð°ÑÑ Ð² Ñ
+ÐŸÐŽÐµ Ð¿ÑÐŸÑÐµÑÑÐ° ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ. Ð­ÑÐŸ ÐŒÐŸÐ¶ÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð² ÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ, ÐµÑÐ»Ðž Ð²Ñ Ñ
+ÐŸÑÐžÑÐµ Ð¿ÐŸÐ»ÑÑÐžÑÑ ÑÐ¿ÐžÑÐŸÐº Ð²ÑÐµÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð² Ð²Ð°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Table id="greenstone_classifiers">
+<Title>
+<Text id="575">ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ Greenstone</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="576"><b>ÐÑÐ³ÑÐŒÐµÐœÑ</b></Text>
+</th>
+<th width="305">
+<Text id="577"><b>ÐÐµÐ¹ÑÑÐ²ÐžÐµ</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="578"><i>Hierarchy</i></Text>
+</th>
+<th width="92"/>
+<th width="305">
+<Text id="579">ÐÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐ°Ñ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="580"><i>hfile</i></Text>
+</th>
+<th width="305">
+<Text id="581">Ð€Ð°Ð¹Ð» ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐž</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="582"><i>metadata</i></Text>
+</th>
+<th width="305">
+<Text id="583">Ð­Ð»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐ»Ñ ÑÐµÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ Ð²ÐŸÐ¿ÑÐµÐºÐž ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑÑ hfile</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="584"><i>sort</i></Text>
+</th>
+<th width="305">
+<Text id="585">Ð­Ð»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÐŸÑÑÐžÑÑÑÑÐžÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ Ð»ÐžÑÑÐ° (Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ - Title)</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="586"><i>buttonname</i></Text>
+</th>
+<th width="305">
+<Text id="587">ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐºÐœÐŸÐ¿ÐºÐž, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐŸÐ¹ ÐŽÐ»Ñ ÐŸÐ±ÑÐ°ÑÐµÐœÐžÑ Ðº ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ (Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ - Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ð°ÑÐ³ÑÐŒÐµÐœÑÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+) </Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="588"><i>List</i></Text>
+</th>
+<th width="92"/>
+<th width="305">
+<Text id="589">ÐÐ»ÑÐ°Ð²ÐžÑÐœÑÐ¹ ÑÐ¿ÐžÑÐŸÐº ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="590"><i>metadata</i></Text>
+</th>
+<th width="305">
+<Text id="591">ÐÐºÐ»ÑÑÐµÐœÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐžÑ
+ ÑÑÐŸÑ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="592"><i>buttonname</i></Text>
+</th>
+<th width="305">
+<Text id="593">ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐºÐœÐŸÐ¿ÐºÐž, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐŸÐ¹ ÐŽÐ»Ñ ÐŸÐ±ÑÐ°ÑÐµÐœÐžÑ Ðº ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ (Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ - Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ð°ÑÐ³ÑÐŒÐµÐœÑÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+)</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="594"><i>SectionList</i></Text>
+</th>
+<th width="92"/>
+<th width="305">
+<Text id="595">Ð¡Ð¿ÐžÑÐŸÐº ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐ² ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² </Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="596"><i>AZList</i></Text>
+</th>
+<th width="92"/>
+<th width="305">
+<Text id="597">Ð¡Ð¿ÐžÑÐŸÐº ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÑÐ°Ð·Ð±ÐžÑÑÑ
+ ÐœÐ° Ð°Ð»ÑÐ°Ð²ÐžÑÐœÑÐµ ÐŽÐžÐ°Ð¿Ð°Ð·ÐŸÐœÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="598"><i>metadata</i></Text>
+</th>
+<th width="305">
+<Text id="599">ÐÐºÐ»ÑÑÐµÐœÐžÐµ Ð²ÑÐµÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐžÑ
+ ÑÑÐŸÑ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Text>
+</th>
+</tr>
+<tr>
+<th width="132"/>
+<th width="92">
+<Text id="600"><i>buttonname</i></Text>
+</th>
+<th width="305">
+<Text id="601">ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐºÐœÐŸÐ¿ÐºÐž, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐŸÐ¹ ÐŽÐ»Ñ ÐŸÐ±ÑÐ°ÑÐµÐœÐžÑ Ðº ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ (Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ - Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ð°ÑÐ³ÑÐŒÐµÐœÑÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+) ÐÐŸÐŽÐŸÐ±ÐœÐŸ AZList,ÐœÐŸ Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð²ÑÐµ ÑÐ°Ð·ÐŽÐµÐ»Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐÐŸÐŽÐŸÐ±ÐœÐŸ AZList, ÐœÐŸ ÑÐŸÑÑÐžÑÑÐµÑ Ð¿ÐŸ ÐŽÐ°ÑÐµ</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="602"><i>AZSectionList</i></Text>
+</th>
+<th width="92"/>
+<th width="305">
+<Text id="603">ÐÐŸÐŽÐŸÐ±ÐœÐŸ AZList,ÐœÐŸ Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð²ÑÐµ ÑÐ°Ð·ÐŽÐµÐ»Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="604"><i>DateList</i></Text>
+</th>
+<th width="92"/>
+<th width="305">
+<Text id="605">ÐÐŸÐŽÐŸÐ±ÐœÐŸ AZList, ÐœÐŸ ÑÐŸÑÑÐžÑÑÐµÑ Ð¿ÐŸ ÐŽÐ°ÑÐµ</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="606">Ð¢ÐµÐºÑÑÐžÐ¹ ÐœÐ°Ð±ÐŸÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ² Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœ Ð² Ð¢Ð°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="greenstone_classifiers"/>. ÐÐ°Ðº Ð±ÑÐ»ÐŸ ÑÐ°ÑÑÐŒÐŸÑÑÐµÐœÐŸ ÑÐ°ÐœÐµÐµ, ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ Ð»ÑÐ±ÐŸÐŒ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐž, Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ pluginfo.pl. Ð¢Ð°ÐºÐ¶Ðµ Ð² ÑÐ»ÑÑÐ°Ðµ Ñ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ°ÐŒÐž ÑÑÑÐµÑÑÐ²ÑÐµÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° classinfo.pl, ÐºÐŸÑÐŸÑÐ°Ñ ÐŽÐ°ÐµÑ Ð²Ð°ÐŒ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ Ð»ÑÐ±ÐŸÐŒ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐµ Ðž ÐŽÐŸÑÑÑÐ¿ÐœÑÑ
+ ÐµÐŒÑ ÐŸÐ¿ÑÐžÑÑ
+.</Text>
+<Text id="607">ÐÑÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ Ð¿ÑÐžÐœÐžÐŒÐ°ÑÑ Ð°ÑÐ³ÑÐŒÐµÐœÑ buttonname, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑÐžÐ¹ ÐœÐ°ÐŽÐ¿ÐžÑÑ ÐœÐ° ÐœÐ°Ð²ÐžÐ³Ð°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐºÐœÐŸÐ¿ÐºÐµ Greenstone, ÐºÐŸÑÐŸÑÐ°Ñ Ð²ÑÐ·ÑÐ²Ð°ÐµÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ (Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ð°ÑÐ³ÑÐŒÐµÐœÑÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+). ÐÐœÐŸÐ¿ÐºÐž ÑÑÑÐµÑÑÐ²ÑÑÑ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÐžÐ¿Ð° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Dublin Core Ðž ÐŽÐ»Ñ ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÐŽÑÑÐ³ÐžÑ
+ ÑÐžÐ¿ÐŸÐ² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+.</Text>
+<Text id="608">ÐÐ°Ð¶ÐŽÑÐ¹ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ Ð¿ÐŸÐ»ÑÑÐ°ÐµÑ ÐœÐµÑÐ²ÐœÐŸÐµ ÐžÐŒÑ, Ð·Ð°Ð²ÐžÑÑÑÐµÐµ ÐŸÑ ÐµÐ³ÐŸ Ð¿ÐŸÐ·ÐžÑÐžÐž Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÑÐµÑÐžÐ¹ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ, ÑÐºÐ°Ð·Ð°ÐœÐœÑÐ¹ Ð² ÑÐ°Ð¹Ð»Ðµ, ÐœÐ°Ð·ÑÐ²Ð°ÑÑ CL3. Ð­ÑÐž ÐžÐŒÐµÐœÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹ Ð¿ÐŸÐ»ÐµÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ Ð±Ð°Ð·Ñ ÐŽÐ°ÐœÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŽÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÐžÐµÑÐ°ÑÑ
+ÐžÐž ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ°.</Text>
+<Text id="609">ÐÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐœÐ°Ð¿ÐžÑÐ°ÐœÑ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÑ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž perllib/classify. Development Library ÐžÐŒÐµÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ Ð¿ÐŸ ÐžÐŒÐµÐœÐž HDLList, ÐºÐŸÑÐŸÑÑ ÑÐ²Ð»ÑÐµÑÑÑ ÑÐŒÐµÐœÑÑÐµÐœÐœÑÐŒ Ð²Ð°ÑÐžÐ°ÐœÑÐŸÐŒ AZList.</Text>
+<Subsection id="list_classifiers">
+<Title>
+<Text id="610">Ð¡Ð¿ÐžÑÐŸÐº ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ²</Text>
+</Title>
+<Content>
+<Text id="611">ÐÐžÐ¶Ðµ Ð¿ÑÐžÐ²ÐµÐŽÐµÐœ ÑÐ¿ÐžÑÐŸÐº ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ²:</Text>
+<BulletList>
+<Bullet>
+<Text id="612"><i>SectionList</i>âÐ¿ÐŸÑ
+ÐŸÐ¶ ÐœÐ° List, ÐœÐŸ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐ² Ð²ÑÑÑÑÐ¿Ð°ÑÑ Ð»ÐžÑÑÑ, Ð° Ðº ÐŽÐŸÐºÑÐŒÐµÐœÑÑ. ÐÐºÐ»ÑÑÐ°ÐµÑ Ð²ÑÐµ ÑÐ°Ð·ÐŽÐµÐ»Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, ÐºÑÐŸÐŒÐµ Ð²ÐµÑÑ
+ÐœÐµÐ³ÐŸ ÑÑÐŸÐ²ÐœÐµ ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ  ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÑÐ¿ÐžÑÐºÐ° ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐ²   (ÑÑÐ°ÑÐµÐ¹, Ð³Ð»Ð°Ð² Ðž Ñ.ÐŽ.), ÐºÐ°ÐºÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Computists' Weekly   (ÐŽÐŸÑÑÑÐ¿ÐœÐ° ÐœÐ° ÑÐ°Ð¹ÑÐµ nzdl.org), Ð³ÐŽÐµ ÐºÐ°Ð¶ÐŽÑÐ¹ Ð²ÑÐ¿ÑÑÐº - ÑÑÐŸ ÐŸÑÐŽÐµÐ»ÑÐœÑÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐœÐµÐ·Ð°Ð²ÐžÑÐžÐŒÑ ÑÑÐ°ÑÐµÐ¹, ÐœÐ°Ñ
+ÐŸÐŽÑÑÐžÑ
+ÑÑ Ð² ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÑÑ
+ ÑÐ°Ð·ÐŽÐµÐ»Ð°Ñ
+.</Text>
+</Bullet>
+<Bullet>
+<Text id="613"><i>AZList</i>âÐ³ÐµÐœÐµÑÐžÑÑÐµÑ ÐžÐµÑÐ°ÑÑ
+ÐžÑ Ñ ÐŽÐ²ÑÐŒÑ ÑÑÐŸÐ²ÐœÑÐŒÐž, Ð²ÐºÐ»ÑÑÐ°ÑÑÑÑ HLis ÐŽÐŸÑÐµÑÐœÐžÐµ Ð·Ð°Ð¿ÐžÑÐž ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ.</Text>
+</Bullet>
+<Bullet>
+<Text id="614"><i>AZSectionList</i>âÐ¿ÐŸÑ
+ÐŸÐ¶ ÐœÐ° AZList, ÐœÐŸ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐ² Ð²ÑÑÑÑÐ¿Ð°ÑÑ Ð»ÐžÑÑÑ Ð° ÐœÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ.</Text>
+</Bullet>
+<Bullet>
+<Text id="615"><i>DateList</i>âÐ¿ÐŸÑ
+ÐŸÐ¶ ÐœÐ° AZList, Ð·Ð° ÐžÑÐºÐ»ÑÑÐµÐœÐžÐµÐŒ ÑÐŸÐ³ÐŸ, ÑÑÐŸ Ð²ÐµÑÑ
+ÐœÐžÐ¹ ÑÑÐŸÐ²ÐµÐœÑ HLL Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐŽÐµÐ»Ð°ÑÑ Ð²ÑÐ±ÐŸÑÐºÑ Ð¿ÐŸ Ð³ÐŸÐŽÑ, Ð° ÐµÐ³ÐŸ ÐŽÐŸÑÐµÑÐœÐžÐµ Ð·Ð°Ð¿ÐžÑÐž - DateLists, Ð° Ðº VLists. ÐÐœÐ°ÑÐµÐœÐžÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ Ð°ÑÐ³ÑÐŒÐµÐœÑÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ - Date.</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Subsection>
+<Subsection id="the_hierarchy_classifier">
+<Title>
+<Text id="616">ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ ÐžÐµÑÐ°ÑÑ
+ÐžÐž</Text>
+</Title>
+<Content>
+<Text id="617">ÐÑÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ ÑÐ²Ð»ÑÑÑÑÑ ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐžÐŒÐž. ÐÐŽÐœÐ°ÐºÐŸ, ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ: ÑÐ¿ÐžÑÐºÐ°, ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÐµ Ð²ÑÑÐµ, ÐžÐŒÐµÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐœÐŸÐµ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ ÑÑÐŸÐ²ÐœÐµÐ¹, ÑÐŸÑÑ ÐºÐ°Ðº ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ "ÐžÐµÑÐ°ÑÑ
+ÐžÐž", ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÐµ Ð² ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ, ÐžÐŒÐµÑ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐ»ÑÐœÐŸÐµ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ ÑÑÐŸÐ²ÐœÐµÐ¹. ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ ÐžÐµÑÐ°ÑÑ
+ÐžÐž Ð±ÐŸÐ»ÐµÐµ ÑÐ»ÐŸÐ¶Ðž ÐŽÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ, ÑÐµÐŒ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ ÑÐ¿ÐžÑÐºÐ°.</Text>
+<Figure id="part_of_the_file_sub">
+<Title>
+<Text id="618">Part of the file <i>sub.txt</i></Text>
+</Title>
+<CodeLine>1           1       "General reference"</CodeLine>
+<CodeLine>1.2       1.2       "Dictionaries, glossaries, language courses, terminology</CodeLine>
+<CodeLine>2           2       "Sustainable Development, International cooperation, Pro</CodeLine>
+<CodeLine>2.1       2.1       "Development policy and theory, international cooperatio</CodeLine>
+<CodeLine>2.2       2.2       "Development, national planning, national plans"</CodeLine>
+<CodeLine>2.3       2.3       "Project planning and evaluation (incl. project managem</CodeLine>
+<CodeLine>2.4       2.4       "Regional development and planning incl. regional profil</CodeLine>
+<CodeLine>2.5       2.5       "Nongovernmental organisations (NGOs) in general, self-</CodeLine>
+<CodeLine>2.6       2.6       "Organisations, institutions, United Nations (general, d</CodeLine>
+<CodeLine>2.6.1   2.6.1       "United Nations"</CodeLine>
+<CodeLine>2.6.2   2.6.2       "International organisations"</CodeLine>
+<CodeLine>2.6.3   2.6.3       "Regional organisations"</CodeLine>
+<CodeLine>2.6.5   2.6.5       "European Community - European Union"</CodeLine>
+<CodeLine>2.7       2.7       "Sustainable Development, Development models and example</CodeLine>
+<CodeLine>2.8       2.8       "Basic Human Needs"</CodeLine>
+<CodeLine>2.9       2.9       "Hunger and Poverty Alleviation"</CodeLine>
+</Figure>
+<Text id="619">ÐÑÐ³ÑÐŒÐµÐœÑ hflle ÐŽÐ°ÐµÑ ÐžÐŒÑ ÑÐ°Ð¹Ð»Ð°, ÐºÐ°Ðº Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐŸ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="part_of_the_file_sub"/>, ÐºÐŸÑÐŸÑÐŸÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÐžÐµÑÐ°ÑÑ
+ÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. ÐÐ°Ð¶ÐŽÐ°Ñ ÑÑÑÐŸÐºÐ° ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ ÐŸÐŽÐœÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÑ, Ð° ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ ÑÐŸÑÑÐŸÑÑ ÐžÐ· ÑÑÐµÑ
+ ÑÐ°ÑÑÐµÐ¹:</Text>
+<BulletList>
+<Bullet>
+<Text id="620">ÐÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ (Ð·Ð°ÐŽÐ°ÐœÐœÐŸÐ³ÐŸ Ð°ÑÐ³ÑÐŒÐµÐœÑÐŸÐŒ metadata) Ð¿ÐŸ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐž.</Text>
+</Bullet>
+<Bullet>
+<Text id="621">ÐÐ°ÑÐºÐµÑ Ð¿ÐŸÐ·ÐžÑÐžÐž-Ð²-ÐžÐµÑÐ°ÑÑ
+ÐžÐž, Ð² ÐŒÐœÐŸÐ³Ð¿ÐµÑÐžÐŸÐŽÐœÐŸÐ¹ ÑÐžÑÐ»ÐŸÐ²ÐŸÐ¹ ÑÐŸÑÐŒÐµ, ÐœÐ°Ð¿ÑÐžÐŒÐµÑ 2,2.12,2.12.6.</Text>
+</Bullet>
+<Bullet>
+<Text id="622">ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐž (ÐµÑÐ»Ðž ÐŸÐœÐŸ ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ð¿ÑÐŸÐ±ÐµÐ»Ñ, ÑÐŸ ÐŽÐŸÐ»Ð¶ÐœÐŸ Ð±ÑÑÑ Ð·Ð°ÐºÐ»ÑÑÐµÐœÐŸ Ð² ÐºÐ°Ð²ÑÑÐºÐž).</Text>
+</Bullet>
+</BulletList>
+<Text id="623">ÐÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="part_of_the_file_sub"/> Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐ° ÑÐ°ÑÑÑ ÑÐ°Ð¹Ð»Ð° sub.txt, ÑÐŸÐ·ÐŽÐ°ÑÑÐµÐ³ÐŸ Ð¿ÐŸÐŽÑÐžÐœÐµÐœÐœÑÑ ÐžÐµÑÐ°ÑÑ
+ÐžÑ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Development Library (Ðž Ð² ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž). Ð­ÑÐŸÑ Ð¿ÑÐžÐŒÐµÑ - ÐœÐµÐŒÐœÐŸÐ³ÐŸ Ð·Ð°Ð¿ÑÑÐ°ÐœÐœÑÐ¹, Ñ.Ðº. ÐœÐŸÐŒÐµÑ, ÑÐºÐ°Ð·ÑÐ²Ð°ÑÑÐžÐ¹ ÐœÐ° ÐžÐµÑÐ°ÑÑ
+ÐžÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ²Ð°Ð¶ÐŽÑ ÐœÐ° ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÑÑÑÐŸÐºÐµ. Ð¢ÐžÐ¿ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Hierarchy Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœ Ð² ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°Ñ
+ ÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑÐŒÐž Ð² ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐŸÐ¹ ÑÐžÑÐ»ÐŸÐ²ÐŸÐ¹ ÑÐŸÑÐŒÐµ, ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÐ±ÑÑÑÐœÑÐµÑ Ð¿ÐµÑÐ²ÐŸÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ. ÐÑÐŸÑÐŸÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÐœÐŸÐŒÐµÑÐ° ÑÑÐµÐ±ÑÐµÑÑÑ ÐŽÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÐžÐµÑÐ°ÑÑ
+ÐžÐž, ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÐµÑÑÑ Ð±ÑÐŸÑÐ·ÐµÑÐŸÐŒ ÐžÐµÑÐ°ÑÑ
+ÐžÐž.</Text>
+<Text id="624">ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ hierarchy ÐžÐŒÐµÐµÑ ÐŸÐ¿ÑÐžÐŸÐœÐ°Ð»ÑÐœÑÐ¹ Ð°ÑÐ³ÑÐŒÐµÐœÑ sort, ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ, ÐºÐ°Ðº ÑÐ¿ÐŸÑÑÐŽÐŸÑÐžÐ²Ð°ÑÑÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð² Ð»ÐžÑÑÐ°Ñ
+. ÐÑÐ±ÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÑ ÐºÐ°Ðº ÐºÐ»ÑÑ ÑÐŸÑÑÐžÑÐŸÐ²ÐºÐž. ÐÐœÐ°ÑÐµÐœÐžÐµ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÐŽÐŸÐ»Ð¶ÐœÐŸ ÑÐŸÐ·ÐŽÐ°ÑÑ ÑÐ¿ÐžÑÐŸÐº Ð² ÑÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ, Ð² ÐºÐŸÑÐŸÑÐŸÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð¿ÑÐŸÑ
+ÐŸÐŽÐžÐ»Ðž Ð¿ÑÐŸÑÐµÑÑ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ. Ð£Ð¿ÐŸÑÑÐŽÐŸÑÐµÐœÐžÐµ Ð²ÐŸ Ð²ÐœÑÑÑÐµÐœÐœÐžÑ
+ ÑÐ·Ð»Ð°Ñ
+ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐŸ Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐž Ñ Ð¿ÐŸÑÑÐŽÐºÐŸÐŒ, Ð² ÐºÐŸÑÐŸÑÐŸÐŒ ÑÐ»ÐµÐŒÐµÐœÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÑ Ð² Ð°ÑÐ³ÑÐŒÐµÐœÑÐµ hfile.</Text>
+</Content>
+</Subsection>
+<Subsection id="how_classifiers_work">
+<Title>
+<Text id="625">ÐÐ°Ðº ÑÐ°Ð±ÐŸÑÐ°ÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ</Text>
+</Title>
+<Content>
+<Text id="626">ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ ÑÐ²Ð»ÑÑÑÑÑ ÐŸÐ±ÑÐµÐºÑÐ°ÐŒÐž ÑÐ·ÑÐºÐ° Perl, Ð¿ÐŸÐ»ÑÑÐµÐœÐœÑÐŒÐž ÐŸÑ BasClas.pm Ðž Ñ
+ÑÐ°ÐœÐžÐŒÑÐŒÐž Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž perllib/classijy. ÐÐœÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÑÐŸÐ³ÐŽÐ°, ÐºÐŸÐ³ÐŽÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÐ¶Ðµ ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐ°. ÐÑÐž Ð·Ð°Ð¿ÑÑÐºÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ² Ð²ÑÐ¿ÐŸÐ»ÐœÑÑÑÑÑ ÑÐ»ÐµÐŽÑÑÑÐžÐµ ÑÐ°Ð³Ðž.</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="627">ÐÐµÑÐŸÐŽ new ÑÐŸÐ·ÐŽÐ°ÐµÑ ÐŸÐ±ÑÐµÐºÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ°.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="628">ÐÐµÑÐŸÐŽ init ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·ÐžÑÑÐµÑ ÐŸÐ±ÑÐµÐºÑ Ð¿ÐŸ ÑÐ°ÐºÐžÐŒ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐ°ÐŒ, ÐºÐ°Ðº ÑÐžÐ¿ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐºÐœÐŸÐ¿ÐºÐž Ðž ÐºÑÐžÑÐµÑÐžÐž ÑÐŸÑÑÐžÑÐŸÐ²ÐºÐž.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="629">ÐÐµÑÐŸÐŽ classify ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŸÐŽÐžÐœ ÑÐ°Ð· ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ðž Ñ
+ÑÐ°ÐœÐžÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐž, Ð¿ÑÐŸÐžÐ·Ð²ÐµÐŽÐµÐœÐœÐŸÐ¹ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐŒ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐŸÐ±ÑÐµÐºÑÐ°.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="630">ÐÐµÑÐŸÐŽ get_classijy_info Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑ Ð»ÐŸÐºÐ°Ð»ÑÐœÐŸ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐœÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐž   Ð¿ÑÐŸÑÐµÑÑÑ ÐºÐŸÐŒÐ¿ÐŸÐœÐŸÐ²ÐºÐž, ÐºÐŸÑÐŸÑÑÐ¹ Ð·Ð°Ð¿ÐžÑÑÐ²Ð°ÐµÑ ÐµÐµ Ð² ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐŸÐœÐœÑÑ Ð±Ð°Ð·Ñ ÐŽÐ°ÐœÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŽÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ, Ð²ÐŸ Ð²ÑÐµÐŒÑ ÑÐ°Ð±ÐŸÑÑ Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹.</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="631">ÐÐµÑÐŸÐŽ classify ÐŸÑÑÑÐºÐžÐ²Ð°ÐµÑ OID ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐ»Ñ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, Ðž Ð² ÑÐ»ÑÑÐ°Ðµ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÐž, Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐ»Ñ ÑÐŸÑÑÐžÑÐŸÐ²ÐºÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². ÐÐµÑÐŸÐŽ get_classify_info Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑ Ð²ÑÑ ÑÐŸÑÑÐžÑÐŸÐ²ÐºÑ Ðž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐŒ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÑ. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, Ð² ÑÐ»ÑÑÐ°Ðµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ° AZList, ÐŸÐœ ÑÐ°Ð·Ð±ÐžÐ²Ð°ÐµÑ ÑÐ¿ÐžÑÐŸÐº ÐœÐ° Ð°Ð»ÑÐ°Ð²ÐžÑÐœÑÐµ ÐŽÐžÐ°Ð¿Ð°Ð·ÐŸÐœÑ.</Text>
+<Text id="632">ÐÑÐŸÑÐµÑÑ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·ÐžÑÑÐµÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ, ÐºÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐŸÐ±ÑÐµÐºÑ builder Ð±ÑÐŽÐµÑ ÑÐŸÐ·ÐŽÐ°Ðœ. ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐž ÑÐŸÐ·ÐŽÐ°ÑÑÑÑ Ð² Ð¿ÑÐŸÑÐµÑÑÐµ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ, ÐºÐŸÐ³ÐŽÐ° classify.pm, Ð¿ÐŸÑÑÐŸÑÐœÐœÐŸ ÐœÐ°Ñ
+ÐŸÐŽÑÑÐžÐ¹ÑÑ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž perllib Greenstone, ÑÐŸÐ·ÐŽÐ°ÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐŸÐœÐœÑÑ Ð±Ð°Ð·Ñ ÐŽÐ°ÐœÐœÑÑ
+.</Text>
+<Table id="items_appearing_in_format_strings">
+<Title>
+<Text id="633">Ð­Ð»ÐµÐŒÐµÐœÑÑ âÑÐŸÑÐŒÐ°ÑÐ° ÑÑÑÐŸÐºÐžâ</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="634"><i>[Text]</i></Text>
+</th>
+<th width="397">
+<Text id="635">Ð¢ÐµÐºÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="636"><i>[link] âŠ [/link]</i></Text>
+</th>
+<th width="397">
+<Text id="637">HTML ÐŽÐ»Ñ ÑÐ²ÑÐ·Ðž ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐŒ</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="638"><i>[icon]</i></Text>
+</th>
+<th width="397">
+<Text id="639">Ð¡ÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐ°Ñ ÐžÐºÐŸÐœÐºÐ° (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐœÐµÐ±ÐŸÐ»ÑÑÐ°Ñ ÑÐµÐºÑÑÐŸÐ²Ð°Ñ ÐžÐºÐŸÐœÐºÐ° Ð² ÑÑÑÐŸÐºÐµ Search Results)</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="640"><i>[num]</i></Text>
+</th>
+<th width="397">
+<Text id="641">ÐÐŸÐŒÐµÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° (ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÐŸÑÐ»Ð°ÐŽÐºÐž).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="642"><i>[metadata-name]</i></Text>
+</th>
+<th width="397">
+<Text id="643">ÐÐœÐ°ÑÐµÐœÐžÐµ ÑÑÐŸÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐ»Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, ÐœÐ°Ð¿ÑÐžÐŒÐµÑ <i>[Title]</i></Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="formatting_greenstone_output">
+<Title>
+<Text id="644">ÐÑÑ
+ÐŸÐŽÐœÐŸÐ¹ ÑÐŸÑÐŒÐ°Ñ Greenstone</Text>
+</Title>
+<Content>
+<Text id="645">Web-ÑÑÑÐ°ÐœÐžÑÑ, ÐºÐŸÑÐŸÑÑÐµ Ð²Ñ Ð²ÐžÐŽÐžÑÐµ Ð¿ÑÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž Greenstone, ÐœÐµ ÑÐŸÐ·ÐŽÐ°Ð²Ð°Ð»ÐžÑÑ Ð·Ð°ÑÐ°ÐœÐµÐµ, Ð° Ð±ÑÐ»Ðž ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÑ "ÐœÐ° Ð»ÐµÑÑ", Ð¿ÐŸ ÐŒÐµÑÐµ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÐž. ÐÐ°ÑÑÑÐŸÐ¹ÐºÐ° Ð²ÐœÐµÑÐœÐµÐ³ÐŸ Ð²ÐžÐŽÐ° ÐŒÐœÐŸÐ³ÐžÑ
+ Ð°ÑÐ¿ÐµÐºÑÐŸÐ² ÑÑÑÐ°ÐœÐžÑ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑÑ Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ "ÑÐŸÑÐŒÐ°ÑÐ° ÑÑÑÐŸÐº". Ð¡ÑÑÐŸÐºÐž ÑÐŸÑÐŒÐ°ÑÐ° ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑÑ Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð²Ð²ÐŸÐŽÑÑÑÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÑÐŸÑÐŒÐ°Ñ ÐºÐ»ÑÑÐµÐ²ÑÑ
+ ÑÐ»ÐŸÐ², ÑÐŸÐ¿ÑÐŸÐ²ÐŸÐ¶ÐŽÐ°ÐµÐŒÑÐ¹ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµÐŒ ÑÐ»ÐµÐŒÐµÐœÑÐ°, Ðº ÐºÐŸÑÐŸÑÐŸÐŒÑ ÑÐŸÑÐŒÐ°Ñ ÐŸÐ±ÑÐ°ÑÐ°ÐµÑÑÑ. ÐÑÑÑ ÐŽÐ²Ð° ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ Ð²ÐžÐŽÐ° ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÑÐ¿ÑÐ°Ð²Ð»ÑÑÑÑÑ ÑÑÑÐŸÐºÐ°ÐŒÐž ÑÐŸÑÐŒÐ°ÑÐ°. ÐÐµÑÐ²ÑÐ¹ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÐžÐœÑÑÑÑÐŒÐµÐœÑÑ ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ, ÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ ÐžÐ»Ðž ÑÐ°ÑÑÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². ÐÑÐŸÑÐŸÐ¹ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÑÐ¿ÐžÑÐºÐž, Ð¿ÑÐŸÐžÐ·Ð²ÐµÐŽÐµÐœÐœÑÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ°ÐŒÐž ÐžÐ»Ðž Ð¿ÐŸÐžÑÐºÐŸÐ²ÑÐµ ÑÐ¿ÐžÑÐºÐž. ÐÑÐµ ÑÑÑÐŸÐºÐž ÑÐŸÑÐŒÐ°ÑÐ° ÐžÐœÑÐµÑÐ¿ÑÐµÑÐžÑÑÑÑÑÑ Ð²ÐŸ Ð²ÑÐµÐŒÑ ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ ÑÑÑÐ°ÐœÐžÑÑ. Ð ÑÐ²ÑÐ·Ðž Ñ ÑÐµÐŒ, ÑÑÐŸ Ð²ÐœÐµÑÐµÐœÐœÑÐµ Ð²Ð°ÐŒÐž ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð²ÑÑÑÐ¿Ð°ÑÑ Ð² ÑÐžÐ»Ñ Ñ ÐŒÐŸÐŒÐµÐœÑÐ° ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐžÑ ÐžÑ
+ Ð² collect.cfg, ÑÐºÑÐ¿ÐµÑÐžÐŒÐµÐœÑ ÑÐŸ ÑÑÑÐŸÐºÐ°ÐŒÐž ÑÐŸÑÐŒÐ°ÑÐ° ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ Ð±ÑÑÑÑÑÐŒ Ðž Ð¿ÑÐŸÑÑÑÐŒ.</Text>
+<Text id="646">Ð Ð¢Ð°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="items_appearing_in_format_strings"/> Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÑ ÐŸÐ¿ÐµÑÐ°ÑÐŸÑÑ, Ð·Ð°ÐŽÐ°ÑÑÐžÐµ ÑÐŸÑÐŒÐ°Ñ, ÐºÐŸÑÐŸÑÑÐµ Ð·Ð°ÑÑÐ°Ð³ÐžÐ²Ð°ÑÑ Ð¿ÑÑÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². ÐÐ¿ÑÐžÑ DocumentButtons ÑÐ¿ÑÐ°Ð²Ð»ÑÐµÑ ÑÐµÐŒ, ÐºÐ°ÐºÐžÐµ ÐºÐœÐŸÐ¿ÐºÐž ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÑ ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. ÐÐŽÐµÑÑ string - ÑÐ¿ÐžÑÐŸÐº ÐºÐœÐŸÐ¿ÐŸÐº (ÐŸÑÐŽÐµÐ»ÐµÐœÐœÑÑ
+ ÐŽÑÑÐ³ ÐŸÑ ÐŽÑÑÐ³Ð° |), ÑÑÐŸ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Detach, Highlight, Expand Text Ðž Expand Contents (ÐÑÐŽÐµÐ»ÐžÑÑ, ÐÐŸÐŽÑÐ²ÐµÑÐžÑÑ, Ð Ð°Ð·Ð²ÐµÑÐœÑÑÑ Ð¢ÐµÐºÑÑ Ðž Ð Ð°Ð·Ð²ÐµÑÐœÑÑÑ Ð¡ÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ).ÐÐµÑÐµÑÐ¿ÐŸÑÑÐŽÐŸÑÐµÐœÐžÐµ ÑÐ¿ÐžÑÐºÐ° Ð¿ÐµÑÐµÑÐ¿ÐŸÑÑÐŽÐŸÑÐžÐ²Ð°ÐµÑ Ðž ÐºÐœÐŸÐ¿ÐºÐž.</Text>
+<Table id="the_format_options">
+<Title>
+<Text id="647">ÐÐ¿ÑÐžÐž format</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="246">
+<Text id="648"><i>format DocumentImages true/false</i></Text>
+</th>
+<th width="283">
+<Text id="649">ÐÑÐ»Ðž true, ÐŸÑÐŸÐ±ÑÐ°Ð¶Ð°ÐµÑ ÑÐžÑÑÐœÐŸÐº ÐŸÐ±Ð»ÐŸÐ¶ÐºÐž Ð² Ð²ÐµÑÑ
+ÐœÐµÐŒ Ð»ÐµÐ²ÐŸÐŒ ÑÐ³Ð»Ñ ÑÑÑÐ°ÐœÐžÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° (Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ -false)</Text>
+</th>
+</tr>
+<tr>
+<th width="246">
+<Text id="650"><i>format DocumentHeading formatstring</i></Text>
+</th>
+<th width="283">
+<Text id="651">formatstring       ÐÑÐ»Ðž Documentlmages   - false, ÑÐŸÑÐŒÐ°Ñ ÑÑÑÐŸÐºÐž ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÑÐµÑ ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ° Ð² Ð²ÐµÑÑ
+ÐœÐµÐ¹ Ð»ÐµÐ²ÐŸÐ¹ ÑÐ°ÑÑÐž ÑÑÑÐ°ÐœÐžÑÑ  (Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ [Title]).</Text>
+</th>
+</tr>
+<tr>
+<th width="246">
+<Text id="652"><i>format DocumentContents true/false</i></Text>
+</th>
+<th width="283">
+<Text id="653">ÐÑÐ»Ðž ÐŽÐŸÐºÑÐŒÐµÐœÑ ÐžÐŒÐµÐµÑ ÐžÐµÑÐ°ÑÑ
+ÐžÑ, ÑÐŸ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ, ÐµÑÐ»Ðž ÐœÐµÑ, ÑÐŸ ÑÑÑÐµÐ»ÐºÐž next /previous section (Ðº ÑÐ»ÐµÐŽÑÑÑÐµÐŒÑ/ Ð¿ÑÐµÐŽÑÐŽÑÑÐµÐŒÑ ÑÐ°Ð·ÐŽÐµÐ»Ñ) Ðž ÑÐµÐºÑÑ âpage k of nâ (ÑÑÑÐ°ÐœÐžÑÐ° â k ÐžÐ· n).</Text>
+</th>
+</tr>
+<tr>
+<th width="246">
+<Text id="654"><i>format DocumentButtons string</i></Text>
+</th>
+<th width="283">
+<Text id="655">ÐÐŸÐœÑÑÐŸÐ»ÐžÑÑÐµÑ ÐºÐœÐŸÐ¿ÐºÐž ÐŒÐµÐœÑ ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° (Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ Detach\Highlighf).</Text>
+</th>
+</tr>
+<tr>
+<th width="246">
+<Text id="656"><i>format DocumentText formatstring</i></Text>
+</th>
+<th width="283">
+<Text id="657">Ð€ÐŸÑÐŒÐ°ÑÐžÑÑÐµÑ ÑÐµÐºÑÑ, ÐŸÑÐŸÐ±ÑÐ°Ð¶Ð°ÐµÐŒÑÐ¹ ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°: Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ </Text>
+<CodeLine>Â Â Â Â <i>&lt;center&gt;&lt;table width=537&gt;</i></CodeLine>
+<CodeLine><i>Â Â Â Â Â Â &lt;tr&gt;&lt;td&gt;[Text]&lt;/td&gt;&lt;/tr&gt;</i></CodeLine>
+<CodeLine><i>Â Â Â Â Â Â &lt;/table&gt;&lt;/center&gt;</i></CodeLine>
+</th>
+</tr>
+<tr>
+<th width="246">
+<Text id="658"><i>format DocumentArrowsBottom true/false</i></Text>
+</th>
+<th width="283">
+<Text id="659">ÐÑÐŸÐ±ÑÐ°Ð¶Ð°ÐµÑ ÑÑÑÐµÐ»ÐºÐž next/previous section (Ðº ÑÐ»ÐµÐŽÑÑÑÐµÐŒÑ/ Ð¿ÑÐµÐŽÑÐŽÑÑÐµÐŒÑ ÑÐ°Ð·ÐŽÐµÐ»Ñ) Ð² ÐºÐŸÐœÑÐµ ÑÑÑÐ°ÐœÐžÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° (Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ true)</Text>
+</th>
+</tr>
+<tr>
+<th width="246">
+<Text id="660"><i>format DocumentUseHTML true/false</i></Text>
+</th>
+<th width="283">
+<Text id="661">ÐÑÐ»Ðž true, ÐºÐ°Ð¶ÐŽÑÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ ÐŸÑÐŸÐ±ÑÐ°Ð¶Ð°ÐµÑÑÑ Ð² ÐŸÑÐŽÐµÐ»ÑÐœÐŸÐŒ ÑÑÐµÐ¹ÐŒÐµ. Preferences page   (ÑÑÑÐ°ÐœÐžÑÐ° Ð²ÑÐ±ÐŸÑÐ°) ÑÐŸÐ¶Ðµ ÑÐ»ÐµÐ³ÐºÐ° ÐžÐŒÐµÐœÐžÑÑÑ, ÐŽÐŸÐ±Ð°Ð²ÑÑÑÑ ÐŸÐ¿ÑÐžÐž, Ð¿ÑÐžÐŒÐµÐœÐžÐŒÑÐµ Ðº ÑÐŸÐ²ÐŸÐºÑÐ¿ÐœÐŸÑÑÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž HTML-ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², Ð²ÐºÐ»ÑÑÐ°Ñ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸÐ³ÐŸ Ð¿ÐµÑÐµÑ
+ÐŸÐŽÐ° Ðº ÐžÑÑ
+ÐŸÐŽÐœÐŸÐŒÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ  (Ð³ÐŽÐµ-ÐœÐžÐ±ÑÐŽÑ Ð² Web), Ð° ÐœÐµ Ðº ÐºÐŸÐ¿ÐžÐž Greenstone.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Subsection id="formatting_greenstone_lists">
+<Title>
+<Text id="662">Ð€ÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐ¿ÐžÑÐºÐŸÐ² Greenstone</Text>
+</Title>
+<Content>
+<Text id="663">Ð¡ÑÑÐŸÐºÐž ÑÐŸÑÐŒÐ°ÑÐ°, ÐºÐŸÑÐŸÑÑÐµ ÑÐ¿ÑÐ°Ð²Ð»ÑÑÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐŸÐŒ ÑÐ¿ÐžÑÐºÐŸÐ², ÐŒÐŸÐ³ÑÑ Ð¿ÑÐžÐŒÐµÐœÑÑÑÑÑ ÐœÐ° ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÑÑÐŸÐ²ÐœÑÑ
+ ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ ÑÑÑÑÐºÑÑÑÑ. ÐÐœÐž ÐŒÐŸÐ³ÑÑ ÐžÐ·ÐŒÐµÐœÐžÑÑ Ð²ÑÐµ ÑÐ¿ÐžÑÐºÐž ÐœÐµÐºÐŸÑÐŸÑÐŸÐ³ÐŸ ÑÐžÐ¿Ð° Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ DateList) ÐžÐ»Ðž Ð²ÑÐµÑ
+ ÑÐ°ÑÑÐµÐ¹ ÑÐ¿ÐžÑÐºÐ° (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, Ð²ÑÐµ Ð²Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÑ Ð² ÑÐ¿ÐžÑÐºÐµ Search), ÐžÐ»Ðž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ ÑÐ°ÑÑÑÑ
+ ÐœÐµÐºÐŸÑÐŸÑÐŸÐ³ÐŸ ÑÐ¿ÐžÑÐºÐ° (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, Ð²ÐµÑÑÐžÐºÐ°Ð»ÑÐœÐ°Ñ ÑÐ°ÑÑÑ ÑÐ¿ÐžÑÐºÐ° Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐŸÐ² ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ° AZList).</Text>
+<Text id="664">Ð¡Ð»ÐµÐŽÑÑÑÐžÐ¹ - ÑÑÐŸ format ÐºÐ»ÑÑÐµÐ²ÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð°, ÑÐŸÑÑÐŸÑÑÐµÐ³ÐŸ ÐžÐ· ÐŽÐ²ÑÑ
+ ÑÐ°ÑÑÐµÐ¹, ÐŸÐŽÐœÐ° ÐžÐ· ÐºÐŸÑÐŸÑÑÑ
+ Ð¿ÑÐžÐœÑÐŽÐžÑÐµÐ»ÑÐœÐ°. ÐÐµÑÐ²Ð°Ñ ÑÐ°ÑÑÑ ÐžÐŽÐµÐœÑÐžÑÐžÑÐžÑÑÐµÑ ÑÐ¿ÐžÑÐŸÐº, Ðº ÐºÐŸÑÐŸÑÐŸÐŒÑ ÑÐŸÑÐŒÐ°Ñ ÐŸÐ±ÑÐ°ÑÐ°ÐµÑÑÑ. Ð¡Ð¿ÐžÑÐŸÐº, ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐ¹ Ð¿ÐŸÐžÑÐºÐŸÐŒ, ÐœÐ°Ð·ÑÐ²Ð°ÑÑ Search, Ð² ÑÐŸ Ð²ÑÐµÐŒÑ ÐºÐ°Ðº ÑÐ¿ÐžÑÐºÐž, ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ°ÐŒÐž, ÐœÐ°Ð·ÑÐ²Ð°ÑÑ CL1, CL2, CL3, ... ÐŽÐ»Ñ Ð¿ÐµÑÐ²ÐŸÐ³ÐŸ, Ð²ÑÐŸÑÐŸÐ³ÐŸ, ÑÑÐµÑÑÐµÐ³ÐŸ, ... ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÑÑÐŸ Ð² collect.cfg. ÐÑÐŸÑÐ°Ñ ÑÐ°ÑÑÑ ÐºÐ»ÑÑÐµÐ²ÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð° - ÑÐ°ÑÑÑ ÑÐ¿ÐžÑÐºÐ°, Ðº ÐºÐŸÑÐŸÑÐŸÐŒÑ ÐŽÐŸÐ»Ð¶ÐœÐŸ Ð¿ÑÐžÐŒÐµÐœÑÑÑÑÑ ÑÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ - Ð»ÑÐ±ÐŸÐ¹ HList (ÐŽÐ»Ñ Ð³ÐŸÑÐžÐ·ÐŸÐœÑÐ°Ð»ÑÐœÐŸÐ³ÐŸ ÑÐ¿ÐžÑÐºÐ° Ð¿ÐŸÐŽÐŸÐ±ÐœÐŸ A-Z ÑÐµÐ»ÐµÐºÑÐŸÑÑ Ð² AZList), VList (ÐŽÐ»Ñ Ð²ÐµÑÑÐžÐºÐ°Ð»ÑÐœÐŸÐ³ÐŸ ÑÐ¿ÐžÑÐºÐ°,</Text>
+<Indented>
+<Text id="665"><i>format CL4VList ...</i> Ð¿ÑÐžÐŒÐµÐœÑÐµÑ ÐºÐŸ Ð²ÑÐµÐŒ <i>VLists</i> Ð² CL4</Text>
+</Indented>
+<Indented>
+<Text id="666"><i>format CL2HList ...</i> Ð¿ÑÐžÐŒÐµÐœÑÐµÑ ÐºÐŸ Ð²ÑÐµÐŒ <i>HLists</i> Ð² CL2</Text>
+</Indented>
+<Indented>
+<Text id="667"><i>format CL1DateList ...</i> Ð¿ÑÐžÐŒÐµÐœÑÐµÑ ÐºÐŸ Ð²ÑÐµÐŒ <i>DateLists</i> Ð² CL1</Text>
+</Indented>
+<Indented>
+<Text id="668"><i>format SearchVList ...</i> Ð¿ÑÐžÐŒÐµÐœÑÐµÑ ÐºÐŸ Ð²ÑÐµÐŒ Search Results list</Text>
+</Indented>
+<Indented>
+<Text id="669"><i>format CL3 ...</i> Ð¿ÑÐžÐŒÐµÐœÑÐµÑ ÐºÐŸ Ð²ÑÐµÐŒ ÑÐ·ÐµÐ»ÐºÐ°ÐŒ Ð² CL3, ÐµÑÐ»Ðž ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐŸ ÐœÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐŸ</Text>
+</Indented>
+<Indented>
+<Text id="670"><i>format VList ...</i> Ð¿ÑÐžÐŒÐµÐœÑÐµÑ ÐºÐŸ Ð²ÑÐµÐŒ VLists Ð²ÐŸ Ð²ÑÐµÑ
+ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ°Ñ
+, ÐµÑÐ»Ðž ÐœÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐŸ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐŸ.</Text>
+</Indented>
+<Text id="671">"..." Ð² ÑÑÐžÑ
+ Ð¿ÑÐžÐŒÐµÑÐ°Ñ
+ Ð·Ð°ÐŒÐµÑÐ°ÑÑ ÑÐ¿ÐµÑÐžÑÐžÐºÐ°ÑÐžÐž ÑÐŸÑÐŒÐ°ÑÐ° HTML, ÑÐ¿ÑÐ°Ð²Ð»ÑÑÑÐžÐµ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐµÐ¹ Ðž ÐµÐµ ÑÐ°Ð·ÐŒÐµÑÐµÐœÐžÐµÐŒ, ÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÑÐ²Ð»ÑÑÑÑÑ ÐœÐ° web-ÑÑÑÐ°ÐœÐžÑÐ°Ñ
+, ÐŸÑÐŸÐ±ÑÐ°Ð¶Ð°ÑÑÐžÑ
+ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ. Ð¢Ð°Ðº Ð¶Ðµ, ÐºÐ°Ðº ÑÐ¿ÐµÑÐžÑÐžÐºÐ°ÑÐžÐž HTML, Ð»ÑÐ±ÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŒÐŸÐ³ÑÑ Ð·Ð°ÐºÐ»ÑÑÐ°ÑÑÑÑ Ð² ÐºÐ²Ð°ÐŽÑÐ°ÑÐœÑÐµ ÑÐºÐŸÐ±ÐºÐž: ÑÑÐž Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐžÐœÑÐµÑÐ¿ÐŸÐ»ÐžÑÐŸÐ²Ð°ÐœÑ Ð² ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÐœÐŸÐŒ ÐŒÐµÑÑÐµ. Ð¢Ð°ÐºÐ¶Ðµ Ð»ÑÐ±ÐŸÐ¹ ÐžÐ· ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² Ð² Ð¢Ð°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="the_format_options"/> ÐŒÐŸÐ¶ÐµÑ Ð¿ÑÐžÐŒÐµÐœÑÑÑÑÑ Ð² ÑÑÑÐŸÐºÐ°Ñ
+ ÑÐŸÑÐŒÐ°ÑÐ°. Ð¡ÐžÐœÑÐ°ÐºÑÐžÑ ÐŽÐ»Ñ ÑÑÑÐŸÐº ÑÐ°ÐºÐ¶Ðµ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÑÑÐ»ÐŸÐ²ÐœÑÑ ÐžÐœÑÑÑÑÐºÑÐžÑ, ÐºÐŸÑÐŸÑÐ°Ñ Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐ° Ð² Ð¿ÑÐžÐŒÐµÑÐµ ÐœÐžÐ¶Ðµ.</Text>
+<Text id="672">ÐÐµÑÐµÐ²ÑÐ·ÐŸÐ² Ð²ÑÐµÑ
+ ÑÑÐžÑ
+ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ² ÑÐŸÐ·ÐŽÐ°ÐµÑ ÐžÐµÑÐ°ÑÑ
+ÐžÐž. ÐÐ°Ð¶ÐŽÑÐ¹ ÑÑÐŸÐ²ÐµÐœÑ ÐžÐµÑÐ°ÑÑ
+ÐžÐž ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœ ÐŸÐŽÐœÐžÐŒ ÐžÐ· ÑÐµÑÑÑÐµÑ
+ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÑ
+ ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐ². ÐÑ ÑÐ¶Ðµ ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°Ð»Ðž HLIST, VList Ðž DateList. Ð ÐœÐžÐŒ ÐŸÑÐœÐŸÑÐžÑÑÑ ÑÐ°ÐºÐ¶Ðµ Invisible, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐ²Ð»ÑÐµÑÑÑ ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµÐŒ ÐºÑÐ°ÐŒÑÑ
+ Ð²ÐµÑÑ
+ÐœÑ
+ ÑÑÐŸÐ²ÐœÐµÐ¹ ÐžÐµÑÐ°ÑÑ
+ÐžÐ¹, Ñ.Ðº. ÐžÐŒÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ° Ð²ÑÐµÐ³ÐŽÐ° Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÐŸÑÐŽÐµÐ»ÑÐœÐŸ ÐŸÑ ÐœÐ°Ð²ÐžÐ³Ð°ÑÐžÐŸÐœÐœÐŸÐ³ÐŸ ÐŒÐµÐœÑ GreenÂ¬stone .</Text>
+</Content>
+</Subsection>
+<Subsection id="examples_of_classifiers_and_format_strings">
+<Title>
+<Text id="673">ÐÑÐžÐŒÐµÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ² Ðž ÑÑÑÐŸÐº ÑÐŸÑÐŒÐ°ÑÐ°</Text>
+</Title>
+<Content>
+<Figure id="excerpt_from_the_demo_collection_collect" class="withLineNumber">
+<Title>
+<Text id="674">ÐÑÐ±ÐŸÑÐºÐ° ÐžÐ· ÑÐ°Ð¹Ð»Ð° collectcfg ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐž</Text>
+</Title>
+<CodeLine>classify Hierarchy -hfile sub.txt -metadata Subject -sort Title</CodeLine>
+<CodeLine>classify AZList       -metadata Title</CodeLine>
+<CodeLine>classify Hierarchy -hfile org.txt -metadata Organisation -sort Title</CodeLine>
+<CodeLine>classify List           -metadata Howto</CodeLine>
+<CodeLine>format SearchVList " &lt;td valign=top [link][icon][/link]&lt;/td&gt;&lt;td&gt;{If}</CodeLine>
+<CodeLine>                                       {[parent(All':'):Title],[parent(All':'):Title]:}</CodeLine>
+<CodeLine>                                       [link][Title][/link]&lt;/td&gt; "</CodeLine>
+<CodeLine>format CL4Vlist                 "&lt;br&gt;[link][Howto][/link] "</CodeLine>
+<CodeLine>format DocumentImages   true</CodeLine>
+<CodeLine>format DocumentText       "&lt;h3&gt;[Title]&lt;/h3&gt;\\n\\n&lt;p&gt;[Text]"</CodeLine>
+<CodeLine>format DocumentButtons " Expand Text|Expand contents|Detach|Highlight"</CodeLine>
+</Figure>
+<Text id="675">ÐÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/> Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐ° ÑÐ°ÑÑÑ ÑÐ°Ð¹Ð»Ð° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐŽÐ»Ñ ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒ ÐµÐ³ÐŸ ÐºÐ°Ðº Ð¿ÑÐžÐŒÐµÑ, Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ ÐŸÐœ ÐžÐŒÐµÐµÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÐŸÑÐ»ÐžÑÐœÐŸ ÐŸÑÑÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÑ. ÐÐ±ÑÐ°ÑÐžÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ, ÑÑÐŸ ÐžÐœÑÑÑÑÐºÑÐžÐž Ð² ÑÐ°Ð¹Ð»Ð°Ñ
+ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐœÐµ ÐŽÐŸÐ»Ð¶ÐœÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑ ÑÐžÐŒÐ²ÐŸÐ»Ñ ÐœÐŸÐ²ÐŸÐ¹ ÑÑÑÐŸÐºÐž - Ð² Ð¢Ð°Ð±Ð»ÐžÑÐµ Ð±ÐŸÐ»ÐµÐµ ÐŽÐ»ÐžÐœÐœÑÐµ ÑÑÑÐŸÐºÐž ÑÐ°Ð·Ð±ÐžÐ²Ð°ÑÑÑÑ ÐŽÐ»Ñ ÑÐŽÐŸÐ±ÐŸÑÐžÑÐ°ÐµÐŒÐŸÑÑÐž.</Text>
+<Text id="676">Ð¡ÑÑÐŸÐºÐ° 4 ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ How To ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐœ ÑÐ²Ð»ÑÐµÑÑÑ ÑÐµÑÐ²ÐµÑÑÑÐŒ Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð¿ÐŸÑÑÐŸÐŒÑ ÑÐ¿ÐŸÐŒÐžÐœÐ°ÐµÑÑÑ ÐºÐ°Ðº CL4. ÐÐœÐ°Ð»ÐŸÐ³ÐžÑÐœÐŸÑ ÑÐŸÑÐŒÑÐ»ÐžÑÐŸÐ²ÐºÐ° ÑÐŸÑÐŒÐ°ÑÐ° - ÑÑÑÐŸÐºÐ° 7 ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/>. ÐÐœÑÐŸÑÐŒÐ°ÑÐžÑ "how to" Ð³ÐµÐœÐµÑÐžÑÑÐµÑÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐŒ List, Ð° ÐµÐ³ÐŸ ÑÑÑÑÐºÑÑÑÐ° - ÑÑÐŸ Ð¿ÑÐŸÑÑÐŸÐ¹ ÑÐ¿ÐžÑÐŸÐº Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐŸÐ² (ÑÐŒ. ÑÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="list_classifier"/>). ÐÐ°Ð³ÐŸÐ»ÐŸÐ²ÐºÐž ÑÐ²ÑÐ·Ð°ÐœÑ Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒÐž ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ: ÑÐµÐ»ÑÐŸÐº ÐŒÑÑÑÑ ÐœÐ° Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐµ Ð²ÑÐ·ÑÐ²Ð°ÐµÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ. ÐÐŸÑÐµÑÐœÐžÐµ Ð·Ð°Ð¿ÐžÑÐž Ð²ÐµÑÑ
+ÐœÐµÐ³ÐŸ ÑÑÐŸÐ²ÐœÑ ÐžÐµÑÐ°ÑÑ
+ÐžÐž ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÑ ÐºÐ°Ðº VList (Ð²ÐµÑÑÐžÐºÐ°Ð»ÑÐœÑÐ¹ ÑÐ¿ÐžÑÐŸÐº), ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐµÑÐµÑÐžÑÐ»ÑÐµÑ ÑÐ°Ð·ÐŽÐµÐ»Ñ Ð²ÐµÑÑÐžÐºÐ°Ð»ÑÐœÐŸ. ÐÐŸÑÐºÐŸÐ»ÑÐºÑ ÑÐ²ÑÐ·Ð°ÐœÐœÑÐ¹ ÐŸÐ¿ÐµÑÐ°ÑÐŸÑ format ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐœÐ° ÑÐŸ, ÑÑÐŸ ÐºÐ°Ð¶ÐŽÑÐ¹ ÑÐ»ÐµÐŒÐµÐœÑ ÑÐ¿ÐžÑÐºÐ° ÐœÐ°ÑÐžÐœÐ°ÐµÑÑÑ Ñ ÐœÐŸÐ²ÐŸÐ¹ ÑÑÑÐŸÐºÐž ("&lt;br&gt;") Ðž ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÑÐµÐºÑÑ Howto, Ð³ÐžÐ¿ÐµÑÑÐ²ÑÐ·Ñ Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐŒ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ.</Text>
+<Text id="677">Ð¡ÑÑÐŸÐºÐ° 1 ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÑ Subject ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐ¿ÐŸÐŒÑÐœÑÑÑÑ ÐºÐ°Ðº CL1 (Ð¿ÐµÑÐ²ÑÐ¹ Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž), ÑÑÑÐŸÐºÐ° 3 ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÑ Organisation - CL3. ÐÐ±Ðµ ÑÑÑÐŸÐºÐž ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐŒ Hierarchy Ðž Ð¿ÐŸÑÑÐŸÐŒÑ Ð²ÐºÐ»ÑÑÐ°ÑÑ ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÑÑ ÑÑÑÑÐºÑÑÑÑ VLists.</Text>
+<Text id="678">Ð¡ÑÑÐŸÐºÐ° 2 ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÐŸÑÑÐ°Ð²ÑÑÑÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÑ ÐŽÐ»Ñ ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Titles A-Z (CL2). ÐÐ±ÑÐ°ÑÐžÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ ÐœÐ° ÐŸÑÑÑÑÑÑÐ²ÐžÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÑ
+ ÑÑÑÐŸÐº ÑÐŸÑÐŒÐ°ÑÐ° ÐŽÐ»Ñ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ² CL1. CL3. Greenstone ÐžÐŒÐµÐµÑ Ð²ÑÑÑÐŸÐµÐœÐœÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÐžÐ¿Ð° ÑÑÑÐŸÐºÐž ÑÐŸÑÐŒÐ°ÑÐ° Ðž Ð¿ÐŸÑÑÐŸÐŒÑ ÐœÐµÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÐž ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÑÑ ÑÑÑÐŸÐºÑ ÑÐŸÑÐŒÐ°ÑÐ°, ÐµÑÐ»Ðž ÐÑ ÐœÐµ ÑÐŸÐ±ÐžÑÐ°ÐµÑÐµÑÑ ÐŸÑÐŒÐµÐœÑÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ.</Text>
+<Figure id="formatting_the_document">
+<Title>
+<Text id="679">Ð€ÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°</Text>
+</Title>
+<File width="394" height="277" url="images/Dev_Fig_038.png"/>
+</Figure>
+<Text id="680">Ð­ÑÐŸ ÑÑÐµÑÐœÐ°Ñ Ð·Ð°Ð¿ÐžÑÑ ÐŽÐ»Ñ ÑÑÑÐŸÐºÐž classify (ÑÐŒ. ÑÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/>). ÐÐŸ ÑÐŸÐ²Ð¿Ð°ÐŽÐµÐœÐžÑ, ÐµÑÑÑ ÑÐ°ÐºÐ¶Ðµ ÑÐµÑÑÑÐµ ÑÑÑÐŸÐºÐž format. ÐÐŽÐœÑ ÐŒÑ ÑÐ¶Ðµ ÐŸÐ±ÑÑÐŽÐžÐ»Ðž - ÑÑÐŸ CL4VHst. ÐÑÑÐ°Ð²ÑÐžÐµÑÑ ÑÑÐž - Ð¿ÐµÑÐ²ÑÐ¹ ÑÐžÐ¿ ÑÑÑÐŸÐºÐž ÑÐŸÑÐŒÐ°ÑÐ°, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐœÑÐ¹ Ð² Ð¢Ð°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="items_appearing_in_format_strings"/>. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÑÑÐŸÐºÐ° 8 Ð¿ÐŸÐŒÐµÑÐ°ÐµÑ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ ÐŸÐ±Ð»ÐŸÐ¶ÐºÐž, Ð² Ð²ÐµÑÑ
+ÐœÐµÐŒ Ð»ÐµÐ²ÐŸÐŒ ÑÐ³Ð»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. Ð¡ÑÑÐŸÐºÐ° 9 ÑÐŸÑÐŒÐ°ÑÐžÑÑÐµÑ ÑÐ°ÐºÑÐžÑÐµÑÐºÐžÐ¹ ÑÐµÐºÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ñ ÑÐºÐ°Ð·Ð°ÐœÐžÐµÐŒ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ° ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐ¹ Ð³Ð»Ð°Ð²Ñ ÐžÐ»Ðž ÑÐ°Ð·ÐŽÐµÐ»Ð°, ÑÑÐŸÑÑÐžÑ
+ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ Ð¿ÐµÑÐµÐŽ ÑÐµÐºÑÑÐŸÐŒ. ÐÑÐµ ÑÑÐŸ Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐŸ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="formatting_the_document"/>.</Text>
+<Figure id="formatting_the_search_results">
+<Title>
+<Text id="681">Ð€ÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐŸÐ² Ð¿ÐŸÐžÑÐºÐ°</Text>
+</Title>
+<File width="396" height="243" url="images/Dev_Fig_040.png"/>
+</Figure>
+<Text id="682">Ð¡ÑÑÐŸÐºÐ° 5 ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/> - ÑÐºÐŸÑÐµÐµ ÑÐ»ÐŸÐ¶ÐœÐ°Ñ ÑÐ¿ÐµÑÐžÑÐžÐºÐ°ÑÐžÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÑÐŸÑÐŒÐ°ÑÐžÑÑÐµÑ ÑÐ¿ÐžÑÐŸÐº ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐ° Ð·Ð°Ð¿ÑÐŸÑÐ°, Ð²ÐŸÐ·Ð²ÑÐ°ÑÐµÐœÐœÑÐ¹ Ð¿ÐŸÐžÑÐºÐŸÐŒ, ÑÐ°ÑÑÐž ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÑ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="formatting_the_search_results"/>. Ð£Ð¿ÑÐŸÑÐµÐœÐœÐ°Ñ Ð²ÐµÑÑÐžÑ ÑÑÑÐŸÐºÐž ÑÐŸÑÐŒÐ°ÑÐ°</Text>
+<CodeLine>&lt;td valign=top&gt;[link][icon][/link]&lt;/td&gt;</CodeLine>
+<CodeLine>&lt;td&gt;[link][Title][/link]&lt;/td&gt;</CodeLine>
+<Text id="683">ÐÐœÐ° ÑÐ¿ÑÐŸÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐ° ÑÐ°Ðº, ÑÑÐŸÐ±Ñ ÐŸÑÐŸÐ±ÑÐ°Ð¶Ð°ÑÑÑÑ Ð² Ð²ÐžÐŽÐµ ÑÑÑÐŸÐºÐž ÑÐ°Ð±Ð»ÐžÑÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÑÐ²Ð»ÑÐµÑÑÑ ÑÐ¿ÐžÑÐºÐŸÐŒ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐŸÐ² ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž Ð·Ð°Ð¿ÑÐŸÑÐ°. ÐÐœÐ° ÑÐŸÐ·ÐŽÐ°ÐµÑ ÐœÐµÐ±ÐŸÐ»ÑÑÑÑ ÐžÐºÐŸÐœÐºÑ, ÑÐ²ÑÐ·Ð°ÐœÐœÑÑ Ñ ÑÐµÐºÑÑÐŸÐŒ, Ð° Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÐŸÐ±ÑÑÐœÐŸ ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÐµÑ Ð³ÐžÐ¿ÐµÑÑÐ²ÑÐ·Ñ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐŒ.</Text>
+<Text id="684">Ð ÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÑ ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐž. Ð€Ð°ÐºÑÐžÑÐµÑÐºÐž, Ð²ÑÑÐµÑÐ¿ÐŸÐŒÑÐœÑÑÐ°Ñ Ð³ÐžÐ¿ÐµÑÑÐ²ÑÐ·Ñ Ð·Ð°ÐºÑÐµÐ¿Ð»ÑÐµÑÑÑ Ð·Ð° Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ð°, Ð²ÐŸÐ·Ð²ÑÐ°ÑÐµÐœÐœÐŸÐ³ÐŸ Ð·Ð°Ð¿ÑÐŸÑÐŸÐŒ. ÐÐŽÐœÐ°ÐºÐŸ, Ð±ÑÐ»ÐŸ Ð±Ñ Ð»ÑÑÑÐµ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÑ ÐŽÐ°ÐœÐœÑÑ Ð¿ÑÐŸÑÐµÐŽÑÑÑ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐŸÐŒ Ð²Ð»ÐŸÐ¶ÐµÐœÐœÐŸÐ³ÐŸ ÑÐ°Ð·ÐŽÐµÐ»Ð°, Ð²Ð»ÐŸÐ¶ÐµÐœÐœÐŸÐ¹ Ð³Ð»Ð°Ð²Ñ Ðž ÐºÐœÐžÐ³Ðž, Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐºÐŸÑÐŸÑÑÑ
+ ÐŸÐœÐ° Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑÑ. Ð¡ÑÑÐµÑÑÐ²ÑÐµÑ ÑÐ¿ÐµÑÐžÐ°Ð»ÑÐœÑÐ¹ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ parent, ÐºÐŸÑÐŸÑÑÐ¹ ÐœÐµ ÑÐŸÑ
+ÑÐ°ÐœÑÐµÑÑÑ Ð² ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°Ñ
+, ÐœÐŸ ÐœÐµÑÐ²ÐœÐŸ Ð¿ÑÐžÑÑÑÑÑÐ²ÑÐµÑ Ð² Ð»ÑÐ±ÐŸÐŒ ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐŸÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÐµ, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐŸÐ·ÐŽÐ°ÐµÑ ÑÐ°ÐºÐŸÐ¹ ÑÐ¿ÐžÑÐŸÐº. ÐÐœ Ð»ÐžÐ±ÐŸ Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑ ÑÐŸÐŽÐžÑÐµÐ»ÑÑÐºÐžÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ, Ð»ÐžÐ±ÐŸ, ÐµÑÐ»Ðž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÑÐ¿ÐµÑÐžÑÐžÐºÐ°ÑÐŸÑ All, ÑÐ¿ÐžÑÐŸÐº ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐŸÐ³ÐŸ Ð²ÐºÐ»ÑÑÐµÐœÐžÑ ÑÐŸÐŽÐžÑÐµÐ»ÐµÐ¹, ÐŸÑÐŽÐµÐ»ÐµÐœÐœÑÑ
+ ÑÐžÐŒÐ²ÐŸÐ»ÑÐœÐŸÐ¹ ÑÑÑÐŸÐºÐŸÐ¹, ÐºÐŸÑÐŸÑÑÑ ÐŒÐŸÐ¶ÐœÐŸ Ð²ÑÑÐ°Ð²ÐžÑÑ Ð¿ÐŸÑÐ»Ðµ ÑÐ¿ÐµÑÐžÑÐžÐºÐ°ÑÐŸÑÐ° All. Ð¢Ð°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ</Text>
+<CodeLine>&lt;td valign=top&gt;[link][icon][/link]&lt;/td&gt; <br/>&lt;td&gt;{[parent(All': '):Title]: }[link][Title][/link]&lt;/td&gt;</CodeLine>
+<Text id="685">ÐžÐŒÐµÐµÑ ÑÐŒÑÑÐ» Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²ÐžÑÑ ÑÐ¿ÐžÑÐŸÐº, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐžÐ¹ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº ÐºÐœÐžÐ³Ðž, Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº Ð³Ð»Ð°Ð²Ñ Ðž Ñ.ÐŽ., ÐºÐŸÑÐŸÑÑÐµ Ð²ÐºÐ»ÑÑÐ°ÑÑ ÐºÐŸÐœÐµÑÐœÑÐ¹ ÑÐ°Ð·ÐŽÐµÐ», ÐŸÑÐŽÐµÐ»ÐµÐœÐœÑÐ¹ ÐŽÐ²ÐŸÐµÑÐŸÑÐžÐµÐŒ, Ñ ÐŽÐ°Ð»ÑÐœÐµÐ¹ÑÐžÐŒ ÐŽÐ²ÐŸÐµÑÐŸÑÐžÐµÐŒ, ÑÐŸÐ¿ÑÐŸÐ²ÐŸÐ¶ÐŽÐ°ÐµÐŒÑÐŒ Ð³ÐžÐ¿ÐµÑÑÐ²ÑÐ·ÑÑ Ñ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐŸÐŒ ÑÑÐŸÐ³ÐŸ ÑÐ°Ð·ÐŽÐµÐ»Ð°.</Text>
+<Text id="686">Ð ÑÐŸÐ¶Ð°Ð»ÐµÐœÐžÑ, ÐµÑÐ»Ðž ÐºÐŸÐœÐµÑÐœÑÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ - ÑÐ°ÐŒÐŸÑÑÐŸÑÑÐµÐ»ÑÐœÐ°Ñ ÐºÐœÐžÐ³Ð°, ÐºÐŸÑÐŸÑÐ°Ñ ÐœÐµ ÐžÐŒÐµÐµÑ ÑÐŸÐŽÐžÑÐµÐ»ÑÑÐºÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, ÑÐŸ Ð¿ÐŸÑÐ²ÐžÑÑÑ Ð¿ÑÑÑÐ°Ñ ÑÑÑÐŸÐºÐ°, ÑÐŸÐ¿ÑÐŸÐ²ÐŸÐ¶ÐŽÐ°ÐµÐŒÐ°Ñ ÐŽÐ²ÐŸÐµÑÐŸÑÐžÐµÐŒ. Ð§ÑÐŸÐ±Ñ ÐžÐ·Ð±ÐµÐ¶Ð°ÑÑ ÑÑÐŸÐ³ÐŸ, Ð²ÐŸÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµÑÑ ÑÑÐ»ÐŸÐ²ÐœÑÐŒÐž ÐŸÐ¿ÐµÑÐ°ÑÐŸÑÐ°ÐŒÐž ifÐœÐŸÐ³ ... else Ð² ÑÑÑÐŸÐºÐµ ÑÐŸÑÐŒÐ°ÑÐ°:</Text>
+<CodeLine>{If}{[metadata], action-if-non-null, action-if-null}</CodeLine>
+<CodeLine>{Or}{action, else another-action, else another-action, etc}</CodeLine>
+<Text id="687">ÐÐ°ÐœÐœÑÐµ Ð² ÑÐžÐ³ÑÑÐœÑÑ
+ ÑÐºÐŸÐ±ÐºÐ°Ñ
+ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐ»Ñ ÐžÐœÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ Ð¿ÑÐŸÑÐµÑÑÐ° ÐŸ ÑÐŸÐŒ, ÑÑÐŸ ÑÑÐŸ ÐžÐœÑÑÑÑÐºÑÐžÑ ÐŽÐŸÐ»Ð¶ÐœÐ° Ð±ÑÑÑ ÐœÐµ ÑÐŸÐ»ÑÐºÐŸ ÑÐ°ÑÐ¿ÐµÑÐ°ÑÐ°ÐœÐ° ÐºÐ°Ðº ÑÐµÐºÑÑ, ÐœÐŸ Ðž ÐžÐœÑÐµÑÐ¿ÑÐµÑÐžÑÐŸÐ²Ð°ÐœÐ°. If Ð¿ÑÐŸÐ²ÐµÑÑÐµÑ, Ð¿ÑÑÑÑ Ð»Ðž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ðž Ð±ÐµÑÐµÑ Ð¿ÐµÑÐ²ÐŸÐµ Ð¿ÑÐµÐŽÐ»ÐŸÐ¶ÐµÐœÐžÐµ, Ð² Ð¿ÑÐŸÑÐžÐ²ÐœÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ - Ð²ÑÐŸÑÐŸÐµ (ÐµÑÐ»Ðž ÐŸÐœÐŸ ÑÑÑÐµÑÑÐ²ÑÐµÑ). ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ ÐŒÐŸÐ¶ÐµÑ Ð»ÑÐ±ÐŸÐ¹ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, Ð²Ð¿Ð»ÐŸÑÑ ÐŽÐŸ ÑÐ¿ÐµÑÐžÐ°Ð»ÑÐœÐŸÐ³ÐŸ ÑÐ°Ð·ÐŽÐµÐ»ÐžÑÐµÐ»Ñ. ÐÐ¿ÐµÑÐ°ÑÐŸÑ Or ÐŸÑÐµÐœÐžÐ²Ð°ÐµÑ ÐºÐ°Ð¶ÐŽÐŸÐµ Ð¿ÐŸÑÐ»ÐµÐŽÑÑÑÐµÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ ÐŽÐŸ ÑÐµÑ
+ Ð¿ÐŸÑ, Ð¿ÐŸÐºÐ° ÐœÐµ ÐœÐ°Ð¹ÐŽÐµÑÑÑ ÐœÐµÐœÑÐ»ÐµÐ²ÐŸÐ¹ ÑÐ»ÐµÐŒÐµÐœÑ. Ð ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐµ ÑÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑ ÐºÐŸÐŒÐ°ÐœÐŽÐ° - Ð¿ÑÐŸÐ¿ÑÑÑÐžÑÑ ÐŸÑÑÐ°Ð»ÑÐœÑÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ.</Text>
+<Text id="688">ÐÐŸÐ·Ð²ÑÐ°ÑÐ°ÑÑÑ Ðº ÑÑÑÐŸÐºÐµ 5 Ð ÐžÑÑÐœÐºÐ° <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/>, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÐŒ Ð¿ÐŸÐ»ÐœÑÐ¹ ÑÐŸÑÐŒÐ°Ñ ÑÑÑÐŸÐºÐž</Text>
+<CodeLine>&lt;td valign=top&gt;[link][icon][/link]&lt;/td&gt;</CodeLine>
+<CodeLine>&lt;td&gt;{If}{[parent(All': '):Title],</CodeLine>
+<CodeLine>           [parent(All': '):Title]:}</CodeLine>    
+<CodeLine>      [link][Title][/link]&lt;/td&gt;</CodeLine>
+<Text id="689">Ð­ÑÐŸ Ð¿ÑÐµÐŽÑÐµÑÑÐ²ÑÐµÑ ÑÐ¿ÐµÑÐžÑÐžÐºÐ°ÑÐžÐž parent Ñ ÑÑÐ»ÐŸÐ²ÐœÑÐŒ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÐµÐŒ, ÐºÐŸÑÐŸÑÐŸÐµ Ð¿ÑÐŸÐ²ÐµÑÑÐµÑ, Ð¿ÑÑÑ Ð»Ðž ÑÐµÐ·ÑÐ»ÑÑÐ°Ñ, Ðž Ð² Ð¿ÑÐŸÑÐžÐ²ÐœÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ Ð²ÑÐŽÐ°ÐµÑ ÑÐŸÐŽÐžÑÐµÐ»ÑÑÐºÑÑ Ð·Ð°Ð¿ÐžÑÑ. ÐÑÑÐ°ÑÐž, parent ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœ Ð¢ÐŸÑ Ð²ÐŒÐµÑÑÐŸ ÐÐ, ÐºÐŸÑÐŸÑÑÐ¹ Ð²ÑÐŽÐ°ÐµÑ ÐžÐŒÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ð²ÐµÑÑ
+ÐœÐµÐ³ÐŸ ÑÑÐŸÐ²ÐœÑ, Ð²ÐºÐ»ÑÑÐ°ÑÑÐµÐµ ÑÐ°Ð·ÐŽÐµÐ» - Ð² ÐœÐ°ÑÐµÐŒ ÑÐ»ÑÑÐ°Ðµ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐºÐœÐžÐ³Ðž. ÐÑÐŽÐµÐ»ÐµÐœÐžÐµ ÑÑÑÐŸÐºÐŸÐ¹ ÐŽÐ»Ñ Ð¢ÐŸÑ ÐœÐµ ÑÑÐµÐ±ÑÐµÑÑÑ.</Text>
+<Text id="690">ÐÐµÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÑÐ»ÐµÐŽÐœÐžÐµ Ð¿ÑÐžÐŒÐµÑÑ ÐžÐ»Ð»ÑÑÑÑÐžÑÑÑÑ ÐŽÑÑÐ³ÐžÐµ ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž. DateList ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="datelist_classifier"/> ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐž Dates Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Computists' Weekly (ÐºÐŸÑÐŸÑÑÐ¹ ÑÐ²Ð»ÑÐµÑÑÑ Ð²ÑÐŸÑÑÐŒ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐŒ - CL2). ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ Ðž ÑÐ¿ÐµÑÐžÑÐžÐºÐ°ÑÐžÐž ÑÐŸÑÐŒÐ°ÑÐ° Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÑ ÐœÐžÐ¶Ðµ. ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ DateList ÐŸÑÐ»ÐžÑÐ°ÐµÑÑÑ ÐŸÑ AZList ÑÐµÐŒ, ÑÑÐŸ Ð²ÑÐµÐ³ÐŽÐ° ÑÐŸÑÑÐžÑÑÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Dates, Ð° Ð²ÐµÑÐ²Ðž ÐŸÑÐœÐŸÐ²Ð°ÐœÐžÑ ÐžÐµÑÐ°ÑÑ
+ÐžÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑ DateList Ð²ÐŒÐµÑÑÐŸ VList, ÐºÐŸÑÐŸÑÑÐ¹ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑ Ð³ÐŸÐŽ Ðž ÐŒÐµÑÑÑ ÑÐ»ÐµÐ²Ð° ÐŸÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°.</Text>
+<CodeLine>classify AZSectionList metadata=Creator</CodeLine>
+<CodeLine>format CL2Vlist "&lt;td&gt;[link][icon][/link]&lt;/td&gt; <br/>&lt;td&gt;[Creator]&lt;/td&gt; <br/>&lt;td&gt;&amp;nbsp;&amp;nbsp;[Title]&lt;/td&gt; <br/>&lt;td&gt;[parent(Top):Date]&lt;/td&gt; "</CodeLine>
+<Text id="691">Ð€ÐŸÑÐŒÐ°Ñ ÑÐ¿ÐµÑÐžÑÐžÐºÐ°ÑÐžÐž Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ VLists ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐŒ ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐŒ.</Text>
+<Text id="692">ÐÐµÑ
+Ð°ÐœÐžÐ·ÐŒ ÑÑÑÐŸÐºÐŸÐ²ÐŸÐ³ÐŸ ÑÐŸÑÐŒÐ°ÑÐ° ÑÐ²Ð»ÑÐµÑÑÑ Ð³ÐžÐ±ÐºÐžÐŒ, ÐœÐŸ Ð·Ð°Ð¿ÑÑÐ°ÐœÐœÑÐŒ ÐŽÐ»Ñ ÐžÐ·ÑÑÐµÐœÐžÑ. ÐÑÑÑÐžÐ¹ Ð¿ÑÑÑ - ÑÑÐŸ ÐžÐ·ÑÑÐµÐœÐžÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+</Content>
+</Subsection>
+<Subsection id="linking_to_different_document_versions">
+<Title>
+<Text id="693">Ð¡ÐŸÐµÐŽÐžÐœÐµÐœÐžÑ Ñ ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒÐž Ð²ÐµÑÑÐžÑÐŒÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²</Text>
+</Title>
+<Content>
+<Text id="694">ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÐŒÐµÑ
+Ð°ÐœÐžÐ·ÐŒÐ° [link] ... [/link] Ð² ÑÑÑÐŸÐºÐŸÐ²ÐŸÐŒ ÑÐŸÑÐŒÐ°ÑÐµ ÑÐŸÐ·ÐŽÐ°ÐµÑ Ð³ÐžÐ¿ÐµÑÑÐ²ÑÐ·Ñ Ñ ÑÐµÐºÑÑÐŸÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. ÐÐŸÐ³ÐŽÐ° ÑÑÑÐ»ÐºÐ° Ð°ÐºÑÐžÐ²ÐžÑÑÐµÑÑÑ, ÐœÐ° ÑÐºÑÐ°ÐœÐµ ÐŸÑÐŸÐ±ÑÐ°Ð¶Ð°ÐµÑÑÑ HTML- Ð²ÐµÑÑÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. Ð ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ ÐŽÑÑÐ³ÐžÑ
+ Ð²ÐµÑÑÐžÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². ÐÐ°Ð¿ÑÐžÐŒÐµÑ, Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Microsoft Word Ð±ÑÐ»ÐŸ Ð±Ñ ÐœÐµÐ¿Ð»ÐŸÑ
+ÐŸ ÐŸÑÐŸÐ±ÑÐ°Ð·ÐžÑÑ ÐŸÑÐžÐ³ÐžÐœÐ°Ð»ÑÐœÑÑ Ð²ÐµÑÑÐžÑ Ð² ÑÐŸÑÐŒÐ°ÑÐµ Word ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, Ð° ÐœÐµ ÐºÐŸÐœÐ²ÐµÑÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐ¹ Ð² HTML Ð²Ð°ÑÐžÐ°ÐœÑ; ÑÐŸ Ð¶Ðµ ÑÐ°ÐŒÐŸÐµ ÐºÐ°ÑÐ°ÐµÑÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÑÐŸÑÐŒÐ°ÑÐ° PDF.</Text>
+<Text id="695">ÐÐ»ÑÑ, Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÑÑÐžÐ¹ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ Ð¿ÐŸÐºÐ°Ð·Ð° ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ Ð²ÐµÑÑÐžÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÐŽÐŸÐ»Ð¶ÐµÐœ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÐŒÐµÑÑÐµ ÐžÑ
+ Ñ
+ÑÐ°ÐœÐµÐœÐžÑ - ÐŸÐ± Ð°ÑÑ
+ÐžÐ²Ðµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Greenstone. ÐÐœÑÐŸÑÐŒÐ°ÑÐžÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÑÑÑ Ð² ÑÐŸÑÐŒÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. ÐÐŸÐŒÐµÑÐ°ÐµÐŒ</Text>
+<CodeLine>[link][Title][/link]</CodeLine>
+<Text id="696">Ð² ÑÑÑÐŸÐºÑ ÑÐŸÑÐŒÐ°ÑÐ°, ÑÐŸÐ·ÐŽÐ°ÑÑÐµÐ³ÐŸ ÑÑÑÐ»ÐºÑ Ðº HTML-ÐŽÐŸÐºÑÐŒÐµÐœÑÑ. Ð ÐºÐ°ÑÐµÑÑÐ²Ðµ Ð¿ÐŸÐŒÐµÑÐµÐœÐœÐŸÐ³ÐŸ ÑÐµÐºÑÑÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ðœ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑ Word Ðž PDF Ð³ÐµÐœÐµÑÐžÑÑÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ srclink, ÑÐ°Ðº ÑÑÐŸ ÐµÑÐ»Ðž ÐÑ Ð¿ÐŸÐŒÐµÑÑÐžÐ»Ðž</Text>
+<CodeLine>[srclink][Title][/srclink]</CodeLine>
+<Text id="697">Ð² ÑÐŸÑÐŒÐ°Ñ ÑÑÑÐŸÐºÐž, ÑÐŸ Ð±ÑÐŽÐµÑ ÑÐŸÐ·ÐŽÐ°ÐœÐ° ÑÑÑÐ»ÐºÐ° Ðº ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÑÐŸÑÐŒÐ°ÑÐ° Word ÐžÐ»Ðž PDF; Ð² ÑÑÐŸÐŒ Ð¿ÑÐžÐŒÐµÑÐµ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ Ð¿ÐŸÐŒÐµÑÐµÐœÐœÐŸÐ³ÐŸ ÑÐµÐºÑÑÐ° ÑÐœÐŸÐ²Ð° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ðœ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. Ð¡ÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐµ ÐžÐºÐŸÐœÐºÐž ÐŽÐ»Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Word Ðž PDF ÑÐ°ÐºÐ¶Ðµ Ð³ÐµÐœÐµÑÐžÑÑÑÑÑÑ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµÐŒ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ srcicon</Text>
+<CodeLine>[srclink][srcicon][/srclink]</CodeLine>
+<Text id="698">ÐÐœÐŸ ÑÐŸÐ·ÐŽÐ°ÐµÑ ÑÑÑÐ»ÐºÑ, ÐºÐŸÑÐŸÑÐ°Ñ Ð±ÑÐŽÐµÑ ÐŸÑÐŒÐµÐœÐµÐœÐ° ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÐŸÐ¹ ÐžÐºÐŸÐœÐºÐŸÐ¹ Word ÐžÐ»Ðž PDF (ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸ ÑÐžÐ¿Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°), Ð²ÐŒÐµÑÑÐŸ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="controlling_the_greenstone_user_interface">
+<Title>
+<Text id="699">Ð£Ð¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÑÐºÐžÐŒ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐŸÐŒ Greenstone</Text>
+</Title>
+<Content>
+<Text id="700">ÐÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Greenstone ÑÐ¿ÑÐ°Ð²Ð»ÑÐµÑÑÑ ÐŒÐ°ÐºÑÐŸÑÐ°ÐŒÐž, ÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÑÑÐŸÑÐœÐœÐŸ ÐœÐ°Ñ
+ÐŸÐŽÑÑÑÑ Ð² ÐºÐ°ÑÐ°Ð»ÐŸÐ³Ðµ GSDLHOME/macros. ÐÐœÐž ÐœÐ°Ð¿ÐžÑÐ°ÐœÑ ÐœÐ° ÑÐ·ÑÐºÐµ, ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÐ°ÐœÐœÐŸÐŒ ÑÐ¿ÐµÑÐžÐ°Ð»ÑÐœÐŸ ÐŽÐ»Ñ Greenstone, Ðž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ Ð²ÐŸ Ð²ÑÐµÐŒÑ ÑÐ°Ð±ÐŸÑÑ ÑÐžÑÑÐµÐŒÑ ÐŽÐ»Ñ Ð³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐžÑ web-ÑÑÑÐ°ÐœÐžÑ. Ð¢ÑÐ°ÐœÑÐ»ÑÑÐžÑ ÐŒÐ°ÐºÑÐŸÑÐ·ÑÐºÐ° Ð² HTML -Ð¿ÐŸÑÐ»ÐµÐŽÐœÐžÐ¹ ÑÐ°Ð³ Ð² ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐž ÑÑÑÐ°ÐœÐžÑÑ. Ð¢Ð°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ, ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð² ÐŒÐ°ÐºÑÐŸÑÐ°Ð¹Ð»Ðµ ÐœÐµÐŒÐµÐŽÐ»ÐµÐœÐœÐŸ ÐŸÑÐŸÐ±ÑÐ°Ð¶Ð°ÑÑÑÑ ÐœÐ° ÑÐºÑÐ°ÐœÐµ, Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð±ÑÑÑÑÑÐ¹ Ðž ÐŸÑÐµÐœÑ Ð¿ÑÐŸÑÑÐŸÐ¹ ÐžÐœÑÑÑÑÐŒÐµÐœÑ. ÐÑÐµ ÐŒÐ°ÐºÑÐŸÑÐ°Ð¹Ð»Ñ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐµ Greenstone, Ð¿ÐµÑÐµÑÐžÑÐ»ÐµÐœÑ Ð² GSDLHOME/etc/main.cfg Ðž Ð·Ð°Ð³ÑÑÐ¶Ð°ÑÑÑÑ ÐºÐ°Ð¶ÐŽÑÐ¹ ÑÐ°Ð·, ÐºÐŸÐ³ÐŽÐ° ÐžÑ
+ Ð²ÑÐ·ÑÐ²Ð°ÑÑ. ÐÐŽÐžÐœÑÑÐ²ÐµÐœÐœÐŸÐµ ÐžÑÐºÐ»ÑÑÐµÐœÐžÐµ ÐºÐ°ÑÐ°ÐµÑÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ Windows Local Library - Ð² ÑÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð±ÑÐŽÐµÑ Ð¿ÐµÑÐµÐ·Ð°Ð¿ÑÑÑÐžÑÑ Ð¿ÑÐŸÑÐµÑÑ.</Text>
+<Text id="701">Web-ÑÑÑÐ°ÐœÐžÑÑ Ð³ÐµÐœÐµÑÐžÑÑÑÑÑÑ ÐœÐ° Ð»ÐµÑÑ Ð¿ÐŸ ÑÑÐŽÑ Ð¿ÑÐžÑÐžÐœ, Ðž ÐŒÐ°ÐºÑÐŸÑÐžÑÑÐµÐŒÐ° Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Greenstone ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÑÑ ÑÑÐŸ Ñ ÐœÐµÐ²ÐµÑÐŸÑÑÐœÐŸÐ¹ Ð³ÐžÐ±ÐºÐŸÑÑÑÑ. Ð¡ÑÑÐ°ÐœÐžÑÑ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÑ ÐœÐ° ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ ÑÐ·ÑÐºÐ°Ñ
+, ÑÐµÐºÑÑ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° ÐºÐŸÑÐŸÑÑÑ
+ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÐ·ÑÐºÐ° Ð±ÑÐŽÐµÑ Ñ
+ÑÐ°ÐœÐžÑÑÑÑ Ð² ÑÐ°Ð·ÐœÑÑ
+ ÐŒÐ°ÐºÑÐŸÑÐ°Ð¹Ð»Ð°Ñ
+. ÐÐŸÐ³ÐŽÐ° Greenstone ÐŸÑÐŸÐ±ÑÐ°Ð¶Ð°ÐµÑ ÑÑÑÐ°ÐœÐžÑÑ, ÐŒÐ°ÐºÑÐŸ ÐžÐœÑÐµÑÐ¿ÑÐµÑÐ°ÑÐŸÑ Ð¿ÑÐŸÐ²ÐµÑÑÐµÑ Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÑ ÑÐ·ÑÐºÐ° Ðž Ð·Ð°Ð³ÑÑÐ¶Ð°ÐµÑ ÑÑÑÐ°ÐœÐžÑÑ ÐœÐ° ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐŒ ÑÐ·ÑÐºÐµ (ÑÑÐŸ, Ðº ÑÐŸÐ¶Ð°Ð»ÐµÐœÐžÑ, ÐœÐµ ÐŸÑÐœÐŸÑÐžÑÑÑ Ðº ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°). ÐÐœÐ°ÑÐµÐœÐžÑ ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÑÐºÑÐ°ÐœÐœÑÑ
+ Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÑ
+, Ð¿ÐŸÐŽÐŸÐ±ÐœÑÑ
+ ÐœÐŸÐŒÐµÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², Ð¿ÐŸÐ»ÑÑÐµÐœÐœÑÑ
+ Ð² ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐµ Ð¿ÐŸÐžÑÐºÐ°, ÐœÐµ ÐžÐ·Ð²ÐµÑÑÐœÑ Ð·Ð°ÑÐ°ÐœÐµÐµ; ÐŸÐœÐž ÐžÐœÑÐµÑÐ¿ÐŸÐ»ÐžÑÐŸÐ²Ð°ÐœÑ Ð² ÑÐµÐºÑÑ ÑÑÑÐ°ÐœÐžÑÑ Ð² ÑÐŸÑÐŒÐµ ÐŒÐ°ÐºÑÐŸÑÐ°.</Text>
+<Subsection id="the_macro_file_format">
+<Title>
+<Text id="702">Ð€ÐŸÑÐŒÐ°Ñ ÐŒÐ°ÐºÑÐŸÑÐ°Ð¹Ð»Ð°</Text>
+</Title>
+<Content>
+<Text id="703">ÐÐ°ÐºÑÐŸÑÐ°Ð¹Ð»Ñ ÐžÐŒÐµÑÑ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµ .dm. ÐÐ°Ð¶ÐŽÑÐ¹ ÑÐ°Ð¹Ð» ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÐŸÐŽÐžÐœ ÐžÐ»Ðž Ð±ÐŸÐ»ÐµÐµ packages, ÐºÐ°Ð¶ÐŽÑÐ¹ ÐžÐ· ÐºÐŸÑÐŸÑÑÑ
+ ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÑÑÐŽ ÐŒÐ°ÐºÑÐŸÑÐŸÐ², ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÑ
+ Ñ ÐµÐŽÐžÐœÑÑÐ²ÐµÐœÐœÐŸÐ¹ ÑÐµÐ»ÑÑ. Ð¢Ð°ÐºÐ¶Ðµ, ÐºÐ°Ðº Ðž Ð² ÑÐ»ÑÑÐ°Ðµ Ñ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ°ÐŒÐž Ðž Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÑÐŒÐž, ÑÑÑÐµÑÑÐ²ÑÐµÑ ÑÐ°Ð¹Ð» base.dm, Ð¿ÑÐµÐŽÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÐ¹ ÐŽÐ»Ñ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐŒÐ°ÐºÑÐŸÑÐŸÐ²; ÑÑÐŸÑ ÑÐ°Ð¹Ð» ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÐŸÑÐœÐŸÐ²ÐœÐŸÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ ÑÑÑÐ°ÐœÐžÑÑ.</Text>
+<Text id="704">ÐÐ°ÐºÑÐŸÑÑ ÐžÐŒÐµÑÑ ÐžÐŒÐµÐœÐ°, ÐºÐŸÑÐŸÑÑÐµ ÐœÐ°ÑÐžÐœÐ°ÑÑÑÑ Ðž Ð·Ð°ÐºÐ°ÐœÑÐžÐ²Ð°ÑÑÑÑ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐŒ Ð¿ÐŸÐŽÑÐµÑÐºÐžÐ²Ð°ÐœÐžÑ, Ð° ÐžÑ
+ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ Ð·Ð°ÐºÐ»ÑÑÐ°ÐµÑÑÑ Ð² ÑÐžÐ³ÑÑÐœÑÐµ ÑÐºÐŸÐ±ÐºÐž. Ð¡ÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÑÐµÐºÑÑÐŸÐŒ, HTML (Ð²ÐºÐ»ÑÑÐ°Ñ ÑÑÑÐ»ÐºÐž Ðº Java-Ð°Ð¿Ð¿Ð»ÐµÑÐ°ÐŒ Ðž JavaScript), ÐžÐŒÐµÐœÐµÐŒ ÐŒÐ°ÐºÑÐŸÑÐ° ÐžÐ»Ðž Ð»ÑÐ±ÐŸÐ¹ ÐºÐŸÐŒÐ±ÐžÐœÐ°ÑÐžÐµÐ¹ ÐžÐ· Ð²ÑÑÐµÐ¿ÐµÑÐµÑÐžÑÐ»ÐµÐœÐœÑÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ². ÐÐ°ÐºÑÐŸÐºÐŸÐŒÐ°ÐœÐŽÐ° ÐŸÑ base.dm ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ ÑÑÑÐ°ÐœÐžÑÑ, ÐµÑÐ»Ðž ÐŸÑÑÑÑÑÑÐ²ÑÐµÑ ÐºÐ°ÐºÐ°Ñ-Ð»ÐžÐ±ÐŸ ÐŒÐ°ÐºÑÐŸÐºÐŸÐŒÐ°ÐœÐŽÐ° ÐŸÑÐŒÐµÐœÑ:</Text>
+<CodeLine>_content_ {&lt;p&gt;&lt;h2&gt;Oops&lt;/h2&gt;_textdefaultcontent_}</CodeLine>
+<Text id="705">Ð¡ÑÑÐ°ÐœÐžÑÐ° Ð±ÑÐŽÐµÑ ÑÐžÑÐ°ÑÑ "Oops" ÐœÐ°Ð²ÐµÑÑ
+Ñ, Ðž Jextdefaultcontent _, ÐºÐŸÑÐŸÑÑÐ¹ ÐœÐ° Ð°ÐœÐ³Ð»ÐžÐ¹ÑÐºÐŸÐŒ ÑÐ·ÑÐºÐµ Ð±ÑÐŽÐµÑ Ð²ÑÐŽÐ°Ð²Ð°ÑÑ The requested page could not be found. Please use your browsers 'back' button or the above home button to return to the Greenstone Digital Library (ÐÐ°Ð¿ÑÑÐµÐœÐœÐ°Ñ ÑÑÑÐ°ÐœÐžÑÐ° ÐœÐµ ÐœÐ°Ð¹ÐŽÐµÐœÐ°. ÐÐŸÐ¶Ð°ÑÐ¹ÑÑÐ°, Ð²ÐŸÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµÑÑ ÐºÐœÐŸÐ¿ÐºÐŸÐ¹ Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ° Ð² Ð²Ð°ÑÐµÐŒ Ð±ÑÐŸÑÐ·ÐµÑÐµ ÐžÐ»Ðž ÐºÐœÐŸÐ¿ÐºÐŸÐ¹ Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ° ÐœÐ° ÐŽÐŸÐŒÐ°ÑÐœÑÑ ÑÑÑÐ°ÐœÐžÑÑ ÐŠÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone), ÐºÐ°Ðº Ðž ÐœÐ° ÐŽÑÑÐ³ÐžÑ
+ ÑÐ·ÑÐºÐ°Ñ
+.</Text>
+<Text id="706">_textdefaultcontent_ Ðž _content_ ÐŸÐ±Ð° Ð¿ÐŸÑÑÐŸÑÐœÐœÐŸ ÐœÐ°Ñ
+ÐŸÐŽÑÑÑÑ Ð² Ð¿Ð°ÐºÐµÑÐµ global, Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ ÐŸÐœÐž Ð·Ð°Ð¿ÑÐ°ÑÐžÐ²Ð°ÑÑÑÑ Ð²ÑÐµÐŒÐž ÑÐ°ÑÑÑÐŒÐž Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÑÐºÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°. ÐÐ°ÐºÑÐŸÑÑ ÐŒÐŸÐ³ÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŒÐ°ÐºÑÐŸÑÑ ÐžÐ· ÐŽÑÑÐ³ÐžÑ
+ Ð¿Ð°ÐºÐµÑÐŸÐ², ÐœÐŸ ÑÐŸÐ³ÐŽÐ° ÐŸÐœÐž ÐŽÐŸÐ»Ð¶ÐœÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑ Ð² Ð¿ÑÐµÑÐžÐºÑÐµ ÐžÑ
+ ÐžÐŒÐµÐœÐ° Ðž ÐžÐŒÑ Ð¿Ð°ÐºÐµÑÐ°. ÐÐ°Ð¿ÑÐžÐŒÐµÑ,</Text>
+<CodeLine>_collectionextra_ {This collection contains _about:numdocs_ documents. It was last built _about:builddate_ days ago.)</CodeLine>
+<Text id="707">ÐžÑÑ
+ÐŸÐŽÐžÑ ÐžÐ· english.dm Ðž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐºÐ°Ðº Ð·Ð°ÐŽÐ°ÐœÐœÐŸÐµ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. _collectionextra_ - ÑÐ°ÑÑÑ Ð¿Ð°ÐºÐµÑÐ° global , ÐœÐŸ _numdocs_ Ðž _builddate_ - ÐŸÐ±Ð° ÐžÐ·  Ð¿Ð°ÐºÐµÑÐ° about, ÑÐ»ÐµÐŽÐŸÐ²Ð°ÑÐµÐ»ÑÐœÐŸ ÑÐ»ÐµÐŽÑÐµÑ Ð¿ÐžÑÐ°ÑÑ _about:wMsi_. </Text>
+<Text id="708">ÐÐ°ÑÐ°ÑÑÑÑ ÐŒÐ°ÐºÑÐŸÑ ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÑÑÐ»ÐŸÐ²ÐœÑÐµ ÐžÐœÑÑÑÑÐºÑÐžÐž. ÐÐœÐž ÐœÐ°Ð¿ÐŸÐŒÐžÐœÐ°ÑÑ ÑÑÐ»ÐŸÐ²ÐœÐŸÐµ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÐµ ÑÑÑÐŸÐºÐž ÑÐŸÑÐŒÐ°ÑÐ°, ÐŸÐ¿ÐžÑÐ°ÐœÐœÐŸÐµ Ð²ÑÑÐµ, Ñ
+ÐŸÑÑ ÐžÑ
+ Ð²ÐžÐŽ ÐœÐµÐŒÐœÐŸÐ³ÐŸ ÐŸÑÐ»ÐžÑÐ°ÐµÑÑÑ. ÐÑÐœÐŸÐ²ÐœÐŸÐ¹ ÑÐŸÑÐŒÐ°Ñ - _If_ (Ñ
+, Ñ, z), Ð³ÐŽÐµ Ñ
+ - ÑÑÐ»ÐŸÐ²ÐžÐµ, Ñ -ÐŒÐ°ÐºÑÐŸÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ, ÐµÑÐ»Ðž ÑÑÐ»ÐŸÐ²ÐžÐµ ÐžÑÑÐžÐœÐœÐŸ, Ðž z -ÐŒÐ°ÐºÑÐŸÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ, ÐµÑÐ»Ðž ÑÑÐ»ÐŸÐ²ÐžÐµ ÑÐ²Ð»ÑÐµÑÑÑ Ð»ÐŸÐ¶ÐœÑÐŒ. ÐÐ¿ÐµÑÐ°ÑÐŸÑÑ ÑÑÐ°Ð²ÐœÐµÐœÐžÑ ÑÐµ Ð¶Ðµ ÑÐ°ÐŒÑÐµ, ÑÑÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ Ð² Perl (ÐŒÐµÐœÑÑÐµ ÑÐµÐŒ, Ð±ÐŸÐ»ÑÑÐµ ÑÐµÐŒ, ÑÐ°Ð²ÐœÐŸ, ÐœÐµ ÑÐ°Ð²ÐœÐŸ). Ð ÑÑÐŸÐŒ Ð¿ÑÐžÐŒÐµÑÐµ base.dm ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÑÐµÑÐµÐœÐžÑ Ð·Ð°ÐŽÐ°ÑÐž ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ Ð²ÐµÑÐœÐµÐ¹ ÑÐ°ÑÑÐž ÑÑÑÐ°ÐœÐžÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž about (ÑÑÑÐ°ÐœÐžÑÐ° ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž):</Text>
+<CodeLine>_imagecollection_ {</CodeLine>
+<CodeLine>       _If_( "_iconcollection_ " ne "",</CodeLine>
+<CodeLine>                 &lt;a href = "_httppageabout_ "&gt; </CodeLine>
+<CodeLine>                         &lt;img src = "_iconcollection_ " border = 0&gt;</CodeLine>
+<CodeLine>                         &lt;/a&gt;,</CodeLine>
+<CodeLine>                 _imagecollectionv_)</CodeLine>
+<CodeLine>}</CodeLine>
+<Text id="709">ÐÐ°ÐœÐœÐŸÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ Ð²ÑÐ³Ð»ÑÐŽÐžÑ ÐœÐµÐŒÐœÐŸÐ³ÐŸ ÐœÐµÐ¿ÐŸÐœÑÑÐœÑÐŒ. _iconcollection_ ÐŸÑÑÑÐ»Ð°ÐµÑ Ðº Ð¿ÑÑÑÐŸÐ¹ ÑÑÑÐŸÐºÐµ, ÐµÑÐ»Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐœÐµ ÐžÐŒÐµÐµÑ ÐžÐºÐŸÐœÐºÐž ÐžÐ»Ðž ÐžÐŒÐµÐœÐž ÑÐ°Ð¹Ð»Ð° ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ. ÐÐµÑÐµÑÑÐ°Ð·ÐžÑÑÐµÐŒ Ð²ÑÑÐµÑÐ¿ÐŸÐŒÑÐœÑÑÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ: ÐÑÐ»Ðž ÐµÑÑÑ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ ÐŽÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð²ÑÐ²ÐµÑÑÐž Ð² Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐµ ÑÑÑÐ°ÐœÐžÑÑ About this Collection (ÑÐ¿ÐŸÐŒÑÐœÑÑÑÐ¹ Jittppageabout _), Ð° Ð·Ð°ÑÐµÐŒ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ; ÐžÐœÐ°ÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð°Ð»ÑÑÐµÑÐœÐ°ÑÐžÐ²ÐœÑÐ¹ Ð²ÑÐ²ÐŸÐŽ _imagecollectionv_.</Text>
+<Text id="710">ÐÐ°ÐºÑÐŸÑÑ ÐŒÐŸÐ³ÑÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑ Ð°ÑÐ³ÑÐŒÐµÐœÑÑ. ÐÐŸÑ Ð²ÑÐŸÑÐŸÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐµ ÐŽÐ»Ñ _imagecollection_ ÐŒÐ°ÐºÑÐŸÐºÐŸÐŒÐ°ÐœÐŽÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÐœÐµÐŒÐµÐŽÐ»ÐµÐœÐœÐŸ ÑÐ»ÐµÐŽÑÐµÑ Ð·Ð° ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐµÐŒ, ÐŽÐ°ÐœÐœÑÐŒ Ð²ÑÑÐµ Ð² ÑÐ°Ð¹Ð»Ðµ base.dm:</Text>
+<CodeLine>_imagecollection_[v=1]{_imagecollectionv_}</CodeLine>
+<Text id="711">ÐÐ°ÑÐ°ÐŒÐµÑÑ [v=l] ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ, ÑÑÐŸ Ð²ÑÐŸÑÐŸÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ, ÐºÐŸÐ³ÐŽÐ° Greenstone ÑÐ°Ð±ÐŸÑÐ°ÐµÑ Ð² ÑÐµÐºÑÑÐŸÐ²ÐŸÐŒ ÑÐµÐ¶ÐžÐŒÐµ. ÐÐ°ÐºÑÐŸÑ ÑÐ·ÑÐºÐ° ÑÐ°Ð±ÐŸÑÐ°ÐµÑ Ð¿ÐŸÑ
+ÐŸÐ¶Ðµ -ÐžÑÐºÐ»ÑÑÐµÐœÐžÐµ ÑÐŸÑÑÐ°Ð²Ð»ÑÐµÑ english.dm, Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ ÑÐ²Ð»ÑÐµÑÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµÐŒ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ, Ð²ÑÐµ ÐŒÐ°ÐºÑÐŸÑÑ ÑÐ·ÑÐºÐ° ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ ÑÐ·ÑÐº ÐºÐ°Ðº Ð¿Ð°ÑÐ°ÐŒÐµÑÑ. ÐÐ°Ð¿ÑÐžÐŒÐµÑ,</Text>
+<CodeLine>_textimagehome_ {Home Page}</CodeLine>
+<Text id="712">Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ Ð² Ð°ÐœÐ³Ð»ÐžÐ¹ÑÐºÐŸÐŒ ÐŒÐ°ÐºÑÐŸÑÐ°Ð¹Ð»Ðµ ÑÐ·ÑÐºÐ°, ÑÐŸÐ³ÐŽÐ° ÐºÐ°Ðº ÐŽÐ»Ñ ÐœÐµÐŒÐµÑÐºÐŸÐ¹ Ð²ÐµÑÑÐžÐž</Text>
+<CodeLine>_textimagehome_ [l=de] {Hauptaseite}</CodeLine>
+<Text id="713">ÐÐœÐ³Ð»ÐžÐ¹ÑÐºÐ°Ñ Ðž ÐœÐµÐŒÐµÑÐºÐ°Ñ Ð²ÐµÑÑÐžÐž ÐœÐ°Ñ
+ÐŸÐŽÑÑÑÑ Ð² ÑÐŸÐŒ Ð¶Ðµ ÑÐ°ÐŒÐŸÐŒ Ð¿Ð°ÐºÐµÑÐµ, Ñ
+ÐŸÑÑ Ðž Ð² ÐŸÑÐŽÐµÐ»ÑÐœÑÑ
+ ÑÐ°Ð¹Ð»Ð°Ñ
+ (ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ Ð¿Ð°ÐºÐµÑÐ° ÐŒÐŸÐ³ÑÑ ÐŸÑ
+Ð²Ð°ÑÐžÑÑ Ð±ÐŸÐ»ÑÑÐµ, ÑÐµÐŒ ÐŸÐŽÐžÐœ ÑÐ°Ð¹Ð»). Greenstone ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ /Ð¿Ð°ÑÐ°ÐŒÐµÑÑ Ð²ÐŸ Ð²ÑÐµÐŒÑ Ð·Ð°Ð¿ÑÑÐºÐ°, ÑÑÐŸÐ±Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐ·ÑÐº ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ.</Text>
+<Figure id="part_of_the_aboutdm_macro_file">
+<Title>
+<Text id="714">Part of the <i>about.dm</i> macro file</Text>
+</Title>
+<CodeLine>package about</CodeLine>
+<CodeLine>##############################################</CodeLine>
+<CodeLine># about page content</CodeLine>
+<CodeLine>###############################################</CodeLine>
+<CodeLine>_pagetitle_ {_collectionname_}</CodeLine>
+<CodeLine>_content_ {</CodeLine>
+<CodeLine>&lt;center&gt;</CodeLine>
+<CodeLine>_navigationbar_</CodeLine>
+<CodeLine>&lt;/center&gt;</CodeLine>
+<CodeLine>_query:queryform_</CodeLine>
+<CodeLine>&lt;p&gt;_iconblankbar_</CodeLine>
+<CodeLine>&lt;p&gt;_textabout_</CodeLine>
+<CodeLine>_textsubcollections_</CodeLine>
+<CodeLine>&lt;h3&gt;_help:textsimplehelpheading_&lt;/h3&gt;</CodeLine>
+<CodeLine>_help:simplehelp_</CodeLine>
+<CodeLine>}</CodeLine>
+<CodeLine>_textabout_ {</CodeLine>
+<CodeLine>&lt;h3&gt;_textabcol_&lt;/h3&gt;</CodeLine>
+<CodeLine>_Global:collectionextra_</CodeLine>
+<CodeLine>}</CodeLine>
+</Figure>
+<Text id="715">Ð Ð·Ð°ÐºÐ»ÑÑÐµÐœÐžÐµ Ð¿ÑÐžÐ²ÐµÐŽÐµÐŒ ÑÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="part_of_the_aboutdm_macro_file"/>, ÐœÐ° ÐºÐŸÑÐŸÑÐŸÐŒ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœ ÐŸÑÑÑÐ²ÐŸÐº ÐŒÐ°ÐºÑÐŸÑÐ°Ð¹Ð»Ð° aboutdm, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ Ð³ÐµÐœÐµÑÐ°ÑÐžÐž ÑÑÑÐ°ÐœÐžÑÑ "About this collection" (Ð ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž) ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÐžÐŽÐµÑÑ ÑÐ°Ð±ÐŸÑÑ ÑÑÐµÑ
+ ÐŒÐ°ÐºÑÐŸÑÐŸÐ² _pagetitle _, _content_ Ðž _textabout_.</Text>
+</Content>
+</Subsection>
+<Subsection id="using_macros">
+<Title>
+<Text id="716">Using macros</Text>
+</Title>
+<Content>
+<Text id="717">ÐÐ°ÐºÑÐŸÑ ÑÐ²Ð»ÑÐµÑÑÑ ÐŒÐŸÑÐœÑÐŒ ÐžÐœÑÑÑÑÐŒÐµÐœÑÐŸÐŒ Ðž ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐœÐµÐŒÐœÐŸÐ³ÐŸ ÐœÐµÐ¿ÐŸÐœÑÑÐµÐœ. ÐÐŽÐœÐ°ÐºÐŸ, Ð¿ÑÐž Ñ
+ÐŸÑÐŸÑÐµÐŒ Ð·ÐœÐ°ÐœÐžÐž HTML Ðž ÐœÐµÐ±ÐŸÐ»ÑÑÐŸÐŒ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐŒ ÐŸÐ¿ÑÑÐµ, ÐŸÐœÐž ÑÑÐ°ÐœÐŸÐ²ÑÑÑÑ Ð±ÑÑÑÑÑÐŒ Ðž Ð¿ÑÐŸÑÑÑÐŒ ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐŒ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž Ð²Ð°ÑÐµÐ³ÐŸ Greenstone -ÑÐ°Ð¹ÑÐ°.</Text>
+<Text id="718">ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÐµÑÐ»Ðž Ð²Ñ Ñ
+ÐŸÑÐžÑÐµ ÑÐŸÐ·ÐŽÐ°ÑÑ ÑÑÐ°ÑÐžÑÐµÑÐºÑÑ ÑÑÑÐ°ÐœÐžÑÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÐœÐ°Ð¿ÐŸÐŒÐžÐœÐ°Ð»Ð° Ð±Ñ Ð²Ð°Ñ ÑÐµÐºÑÑÐžÐ¹ Greenstone-ÑÐ°Ð¹Ñ. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐœÐŸÐ²ÑÐ¹ Ð¿Ð°ÐºÐµÑ, ÐœÐ°Ð·Ð²Ð°ÐœÐœÑÐ¹ static, ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, Ð² ÐœÐŸÐ²ÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ Ðž ÐŸÑÐŒÐµÐœÐžÑÑ ÐŒÐ°ÐºÑÐŸÐºÐŸÐŒÐ°ÐœÐŽÑ _content_ . ÐÐŸÐ±Ð°Ð²ÑÑÐµ ÐœÐŸÐ²ÐŸÐµ ÐžÐŒÑ ÑÐ°Ð¹Ð»Ð° Ð² ÑÐ¿ÐžÑÐŸÐº ÐŒÐ°ÐºÑÐŸÑÐŸÐ² Ð² GSDLHOME/etc/main.cfg, ÐºÐŸÑÐŸÑÑÐ¹ Greenstone Ð·Ð°Ð³ÑÑÐ¶Ð°ÐµÑ ÐºÐ°Ð¶ÐŽÑÐ¹ ÑÐ°Ð·. ÐÐ°ÐºÐŸÐœÐµÑ, ÐŸÐ±ÑÐ°ÑÐžÑÐµÑÑ Ðº ÐœÐŸÐ²ÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐµ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Ð²Ð°Ñ Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÑÐ¹ URL Greenstone, ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑ Ð² ÐºÐŸÐœÐµÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑ ?a=p&amp;p=static (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, http://servername/cgi-bin/library?a=p&amp;p=static).</Text>
+<Text id="719">Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÑÑÑ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Greenstone, Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ Ð¿Ð°ÐºÐµÑÑ base Ðž style. Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐŽÐŸÐŒÐ°ÑÐœÑÑ ÑÑÑÐ°ÐœÐžÑÑ Greenstone, ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÑÐ¹ÑÐµ Ð¿Ð°ÐºÐµÑ home (ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÐŒÐŸÐ¶ÐœÐŸ ÐœÐ°Ð¹ÑÐž Ð² ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÑÐžÐž ÐŠÐžÑÑÐŸÐ²Ð°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Greenstone: Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ Ð¿ÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐµ). ÐÐ»Ñ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ ÑÑÑÐ°ÐœÐžÑÑ Ð·Ð°Ð¿ÑÐŸÑÐŸÐ² ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÑÐ¹ÑÐµ query.dm.</Text>
+<Text id="720">Ð¡Ð²ÐŸÐ±ÐŸÐŽÐœÐŸ ÑÐºÑÐ¿ÐµÑÐžÐŒÐµÐœÑÐžÑÑÐ¹ÑÐµ Ñ ÐŒÐ°ÐºÑÐŸÑÐ°ÐŒÐž. ÐÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð¿ÐŸÑÐ²Ð»ÑÑÑÑÑ ÐœÐµÐŒÐµÐŽÐ»ÐµÐœÐœÐŸ, Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ ÐŒÐ°ÐºÑÐŸÑ ÐžÐœÑÐµÑÐ¿ÑÐµÑÐžÑÑÐµÑÑÑ Ð¿ÐŸ ÐŒÐµÑÐµ ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ ÑÑÑÐ°ÐœÐžÑÑ. ÐÐ°ÐºÑÐŸÑÐ·ÑÐº - Ð¿ÐŸÐ»ÐµÐ·ÐœÑÐ¹ ÐžÐœÑÑÑÑÐŒÐµÐœÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÐŒÐŸÐ¶ÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ, ÑÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ Ð²Ð°Ñ ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÑÐ¹, ÑÐœÐžÐºÐ°Ð»ÑÐœÑÐ¹ ÑÑÐžÐ»Ñ ÑÐ°Ð¹ÑÐ° ÐœÐ° Ð±Ð°Ð·Ðµ Greenstone.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="the_packages_directory">
+<Title>
+<Text id="721">ÐÐžÑÐµÐºÑÐŸÑÐžÑ packages</Text>
+</Title>
+<Content>
+<Table id="the_packages_directory_1">
+<Title>
+<Text id="722">ÐÐžÑÐµÐºÑÐŸÑÐžÑ packages</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="217">
+<Text id="723"><b>ÐÐ°ÐºÐµÑ</b></Text>
+</th>
+<th width="180">
+<Text id="724"><b>URL</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="725"><i>mg</i></Text>
+</th>
+<th width="217">
+<Text id="726">MG, ÑÐŸÐºÑÐ°ÑÐµÐœÐœÐŸ ÐŸÑ âManaging Gigabytes.â Ð¡Ð¶Ð°ÑÐžÐµ, Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ ÐžÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÑ Ðž Ð¿ÐŸÐžÑÐºÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ð»ÐŸÑÑ ÐŽÐ»Ñ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ ÑÐµÐºÑÑÐŸÐ²ÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐµÐ¹ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+ Greenstone.</Text>
+</th>
+<th width="180">
+<Text id="727"><i>www.citri.edu.au/mg</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="728"><i>wget</i></Text>
+</th>
+<th width="217">
+<Text id="729">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ web Ð·ÐµÑÐºÐ°Ð»ÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐŽÐ»Ñ Greenstone. ÐÐ°Ð¿ÐžÑÐ°ÐœÐŸ ÐœÐ° C++.</Text>
+</th>
+<th width="180">
+<Text id="730"><i>www.tuwien.ac.at/~prikryl/ wget.html</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="731"><i>w3mir</i></Text>
+</th>
+<th width="217">
+<Text id="732">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° web-Ð·ÐµÑÐºÐ°Ð»ÐžÑÐŸÐ²Ð°ÐœÐžÑ, ÐœÐ°Ð¿ÐžÑÐ°ÐœÐœÐ°Ñ ÐœÐ° Perl. ÐÐµ ÑÐ²Ð»ÑÐµÑÑÑ Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐžÑÐµÐ»ÑÐœÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐŸÐ¹ Ð·ÐµÑÐºÐ°Ð»ÐžÑÐŸÐ²Ð°ÐœÐžÑ Greenstone, Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ ÐŸÑÐœÐŸÐ²Ð°ÐœÐ° ÐœÐ° ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÐŸÐ¹ ÑÑÑÐ°ÑÐµÐ»ÐŸÐ¹ Ð²ÐµÑÑÐžÐž ÐœÐµÐºÐŸÑÐŸÑÐŸÐ³ÐŸ Perl-ÐŒÐŸÐŽÑÐ»Ñ (ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž w3mir). ÐÐ°ÐºÐµÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ Ð¿ÑÐž Ð·Ð°Ð¿ÑÑÐºÐµ Ð¿ÐŸÐŽ Windows.</Text>
+</th>
+<th width="180">
+<Text id="733"><i>www.math.uio.no/~janl/w3mir</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="734"><i>windows</i></Text>
+</th>
+<th width="217">
+<Text id="735">ÐÐ°ÐºÐµÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ Ð¿ÑÐž Ð·Ð°Ð¿ÑÑÐºÐµ Ð¿ÐŸÐŽ Windows.</Text>
+</th>
+<th width="180">
+<Text id="736"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="737"><i>windows/gdbm</i></Text>
+</th>
+<th width="217">
+<Text id="738">ÐÐµÑÑÐžÑ GNU Database Manager ÐŽÐ»Ñ ÑÑÐµÐŽÑ Windows. GDBM ÑÐ²Ð»ÑÐµÑÑÑ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÐŸÐ¹ ÑÐ°ÑÑÑÑ Linux.</Text>
+</th>
+<th width="180">
+<Text id="739"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="740"><i>windows/crypt</i></Text>
+</th>
+<th width="217">
+<Text id="741">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐºÐŸÐŽÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ Ð¿Ð°ÑÐŸÐ»ÐµÐ¹ ÐœÐ° ÑÑÐŸÐ²ÐœÐµ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ Greenstone.</Text>
+</th>
+<th width="180">
+<Text id="742"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="743"><i>windows/stlport</i></Text>
+</th>
+<th width="217">
+<Text id="744">Standard Template Library (Ð¡ÑÐ°ÐœÐŽÐ°ÑÑÐœÐ°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° ÑÐ°Ð±Ð»ÐŸÐœÐŸÐ²) ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð¿ÑÐž ÐºÐŸÐŒÐ¿ÐžÐ»ÑÑÐžÐž Greenstone ÑÐŸÐ²ÐŒÐµÑÑÐœÐŸ Ñ ÐœÐµÐºÐŸÑÐŸÑÑÐŒÐž ÐºÐŸÐŒÐ¿ÐžÐ»ÑÑÐŸÑÐ°ÐŒÐž Windows.</Text>
+</th>
+<th width="180">
+<Text id="745"><i>â</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="746"><i>wv</i></Text>
+</th>
+<th width="217">
+<Text id="747">ÐÐŸÐœÐ²ÐµÑÑÐµÑ Microsoft Word (ÐŽÐ»Ñ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÑÐŸÑÐŒÐ°ÑÐ° Word).</Text>
+</th>
+<th width="180">
+<Text id="748"><i>sourceforge.net/projects/ wvware</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="749"><i>pdftohtml</i></Text>
+</th>
+<th width="217">
+<Text id="750">ÐÐŸÐœÐ²ÐµÑÑÐŸÑ PDF ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÑÐŸÑÐŒÐ°ÑÐ° PDF.</Text>
+</th>
+<th width="180">
+<Text id="751"><i>www.ra.informatik.uni-stutt gart.de/ <br/>~gosho/pdftohtml</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="752"><i>yaz</i></Text>
+</th>
+<th width="217">
+<Text id="753">Z39.50 Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐºÐ»ÐžÐµÐœÑÐ°, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ ÐŽÐ»Ñ ÐžÑÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐžÑ ÑÐŸÐ²ÐŒÐµÑÑÐžÐŒÐŸÑÑÐž Greenstone Ñ Z39.50. Ð Ð¿ÑÐŸÐ³ÑÐµÑÑÐµ ÑÐŸÐŸÐ±ÑÐ°ÑÑ Ð² ÑÐ°Ð¹Ð»Ðµ README.gsdl.</Text>
+</th>
+<th width="180">
+<Text id="754"><i>www.indexdata.dk</i></Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="755">ÐÐžÑÐµÐºÑÐŸÑÐžÑ packages , ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ ÐºÐŸÑÐŸÑÐŸÐ¹ Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐŸ Ð² Ð¢Ð°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="the_packages_directory_1"/>, - ÑÑÐŸ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ, Ð² ÐºÐŸÑÐŸÑÐŸÐ¹ Ñ
+ÑÐ°ÐœÑÑÑÑ Ð²ÑÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐµ Greenstone, ÐœÐŸ ÐœÐ°Ð¿ÐžÑÐ°ÐœÐœÑÐµ ÐŽÑÑÐ³ÐžÐŒÐž ÐžÑÑÐ»ÐµÐŽÐŸÐ²Ð°ÑÐµÐ»ÑÑÐºÐžÐŒÐž Ð³ÑÑÐ¿Ð¿Ð°ÐŒÐž. ÐÑÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ, ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÑÐµÐŒÐŸÐµ ÑÐŸÐ²ÐŒÐµÑÑÐœÐŸ Ñ Greenstone, Ð¿ÐŸÐ¿Ð°ÐŽÐ°ÐµÑ Ð¿ÐŸÐŽ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ ÐÐžÑÐµÐœÐ·ÐžÐŸÐœÐœÐŸÐ³ÐŸ ÑÐŸÐ³Ð»Ð°ÑÐµÐœÐžÑ ÐŸ ÑÐ²ÐŸÐ±ÐŸÐŽÐœÐŸÐŒ ÐŽÐŸÑÑÑÐ¿Ðµ GNU. ÐÐ°Ð¿ÑÑÐºÐ°ÐµÐŒÑÐµ ÑÐ°Ð¹Ð»Ñ, Ð¿ÑÐŸÐžÐ·Ð²ÐµÐŽÐµÐœÐœÑÐµ ÑÑÐžÐŒÐž Ð¿Ð°ÐºÐµÑÐ°ÐŒÐž, Ð¿ÐŸÐŒÐµÑÐµÐœÑ Ð² ÐºÐ°ÑÐ°Ð»ÐŸÐ³ Greenstone -bin. ÐÐ°Ð¶ÐŽÑÐ¹ Ð¿Ð°ÐºÐµÑ Ñ
+ÑÐ°ÐœÐžÑÑÑ Ð² ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÐŸÐŒ ÐºÐ°ÑÐ°Ð»ÐŸÐ³Ðµ. ÐÐœÐž ÐŸÐ±Ð»Ð°ÐŽÐ°ÑÑ ÑÐžÑÐŸÐºÐžÐŒ ÑÐ¿ÐµÐºÑÑÐŸÐŒ ÑÑÐœÐºÑÐžÐ¹, ÐŸÑ ÐžÐœÐŽÐµÐºÑÐ°ÑÐžÐž Ðž ÑÐ¶Ð°ÑÐžÑ ÐŽÐŸ Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÐœÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Microsoft Word Ð² HTML. ÐÐ°Ð¶ÐŽÑÐ¹ Ð¿Ð°ÐºÐµÑ ÐžÐŒÐµÐµÑ README ÑÐ°Ð¹Ð», ÐºÐŸÑÐŸÑÑÐ¹ ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="the_greenstone_runtime_system">
+<Title>
+<Text id="756">Ð Ð°Ð±ÐŸÑÐ° ÑÐžÑÑÐµÐŒÑ Greenstone</Text>
+</Title>
+<Content>
+<Text id="757">Ð­ÑÐ° Ð³Ð»Ð°Ð²Ð° ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ ÑÐ°Ð±ÐŸÑÑ ÑÐžÑÑÐµÐŒÑ Greenstone, ÑÑÐŸÐ±Ñ Ð²Ñ ÐŒÐŸÐ³Ð»Ðž Ð¿ÐŸÐœÑÑÑ, ÑÐ²ÐµÐ»ÐžÑÐžÑÑ Ðž ÑÐ°ÑÑÐžÑÐžÑÑ ÐµÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž. ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ ÐœÐ°Ð¿ÐžÑÐ°ÐœÐŸ ÐœÐ° Ð¡ ++ Ðž Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÐµÑ Ð±ÐŸÐ»ÑÑÐžÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ Ð²ÐžÑÑÑÐ°Ð»ÑÐœÐŸÐ³ÐŸ ÐœÐ°ÑÐ»ÐµÐŽÐžÑ. ÐÑÐ»Ðž Ð²Ñ ÐœÐµÐ·ÐœÐ°ÐºÐŸÐŒÑ Ñ ÑÑÐžÐŒ ÑÐ·ÑÐºÐŸÐŒ, Ð²Ñ ÐŽÐŸÐ»Ð¶ÐœÑ ÐžÐ·ÑÑÐžÑÑ ÐµÐ³ÐŸ Ð¿ÐµÑÐµÐŽ ÑÐµÐŒ, ÐºÐ°Ðº Ð¿ÑÐžÑÑÑÐ¿ÐžÑÑ Ðº ÑÐ°Ð±ÐŸÑÐµ. ÐÐµÐ¹ÑÐµÐ»Ñ Ðž ÐÐµÐ¹ÑÐµÐ»Ñ (1994) Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²ÐžÐ»Ðž Ð²ÑÐµÑÑÐŸÑÐŸÐœÐœÑÑ ÐŸÐ±ÑÑÐ°ÑÑÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, Ð° Ð¡ÑÑÐ°ÑÑÑÑÑÐ¿ (1997) - Ð»Ð°ÐºÐŸÐœÐžÑÐœÑÐ¹ ÑÐ¿ÑÐ°Ð²ÐŸÑÐœÐžÐº. </Text>
+<Text id="758">ÐÑ ÐœÐ°ÑÐžÐœÐ°ÐµÐŒ ÑÐ°ÑÑÐºÐ°Ð· ÐŸ ÑÐžÐ»ÐŸÑÐŸÑÐžÐž ÐŽÐžÐ·Ð°Ð¹ÐœÐ° Ð¿ÐŸÑÐ»Ðµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ ÑÐ°Ð±ÐŸÑÑ ÑÐžÑÑÐµÐŒÑ, ÑÐ°Ðº ÐºÐ°Ðº ÐŸÐœ Ð±ÑÐŽÐµÑ ÐœÐ°Ð¿ÑÑÐŒÑÑ Ð·Ð°Ð²ÐžÑÐµÑÑ ÐŸÑ ÑÑÐŸÐ³ÐŸ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ. Ð¢ÐµÐ¿ÐµÑÑ Ð¿ÑÐžÑÑÑÐ¿ÐžÐŒ Ðº ÐŽÐµÑÐ°Ð»ÑÐŒ, ÐžÐ· ÐºÐŸÑÐŸÑÑÑ
+ ÑÐŸÑÑÐŸÐžÑ ÐŸÑÐœÐŸÐ²ÐœÐ°Ñ ÑÐ°ÑÑÑ Ð³Ð»Ð°Ð²Ñ. ÐÐµÑÑÐžÑ Greenstone, ÐŸÐ¿ÐžÑÐ°ÐœÐœÐ°Ñ Ð·ÐŽÐµÑÑ - ÑÑÐŸ CGI-Ð²ÐµÑÑÐžÑ (Web Library if for Windows users/Web -Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹ Windows). Windows Local Library ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÑÑ Ð¶Ðµ ÑÐ°ÐŒÑÑ ÐžÑÑ
+ÐŸÐŽÐœÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, ÐœÐŸ ÐžÐŒÐµÐµÑ Ð²ÑÑÑÐŸÐµÐœÐœÑÐ¹ web-ÑÐµÑÐ²ÐµÑ. ÐÐ»ÑÑ ÐºÐŸ Ð²ÑÐµÐŒÑ, Local Library - Ð¿ÐŸÑÑÐŸÑÐœÐœÐŸ Ð¿ÑÐŸÐŽÐŸÐ»Ð¶Ð°ÑÑÐžÐ¹ÑÑ Ð¿ÑÐŸÑÐµÑÑ. </Text>
+<Section id="process_structure">
+<Title>
+<Text id="759">Ð¡ÑÑÑÐºÑÑÑÐ° Ð¿ÑÐŸÑÐµÑÑÐ°</Text>
+</Title>
+<Content>
+<Figure id="overview_of_a_general_greenstone_system">
+<Title>
+<Text id="760">ÐÑÐ°ÑÐºÐžÐ¹ ÐŸÐ±Ð·ÐŸÑ ÑÐ°Ð±ÐŸÑÑ ÑÐžÑÑÐµÐŒÑ Greenstone</Text>
+</Title>
+<File width="382" height="335" url="images/Dev_Fig_044.png"/>
+</Figure>
+<Text id="761">ÐÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="overview_of_a_general_greenstone_system"/> Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐŸ, ÐºÐ°Ðº ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹ (ÐŸÐœÐž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÑ Ð² Ð²ÐžÐŽÐµ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐœÑÑ
+ ÑÐµÑÐŒÐžÐœÐ°Ð»ÐŸÐ² ÐœÐ°Ð²ÐµÑÑ
+Ñ ÐŽÐžÐ°Ð³ÑÐ°ÐŒÐŒÑ) ÐŸÐ±ÑÐ°ÑÐ°ÑÑÑÑÑ Ðº ÑÑÐµÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒ Greenstone. ÐÐµÑÐµÐŽ ÑÐµÐŒ, ÐºÐ°Ðº Ð¿ÑÐµÐŽÑÑÐ°ÑÑ Ð² ÑÐµÐ¶ÐžÐŒÐµ on-line, ÑÑÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÑÐŸÑ
+ÐŸÐŽÑÑ Ð¿ÑÐŸÑÐµÑÑÑ ÐžÐŒÐ¿ÐŸÑÑÐ° Ðž ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ, ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐ»Ðž ÐŸÐ¿ÐžÑÐ°ÐœÑ Ð² Ð¿ÑÐµÐŽÑÐŽÑÑÐžÑ
+ Ð³Ð»Ð°Ð²Ð°Ñ
+. Ð¡ÐœÐ°ÑÐ°Ð»Ð° ÐŽÐŸÐºÑÐŒÐµÐœÑÑ, Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐœÑÐµ Ð²ÐœÐžÐ·Ñ ÑÐžÑÑÐœÐºÐ°, ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÑ Ð² XML-ÑÐŸÐ²ÐŒÐµÑÑÐžÐŒÑÐ¹ Ð€ÐŸÑÐŒÐ°Ñ ÐÑÑ
+ÐžÐ²Ð° Greenstone. Ð¢ÐµÐ¿ÐµÑÑ ÐŽÐ»Ñ ÑÐ°Ð¹Ð»ÐŸÐ² ÑÐŸÐ·ÐŽÐ°ÐœÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÐŽÐŸÑÑÑÐ¿ÐœÑÐµ ÐŽÐ»Ñ Ð¿ÐŸÐžÑÐºÐ° ÐžÐœÐŽÐµÐºÑÑ Ðž ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐŸÐœÐœÐ°Ñ Ð±Ð°Ð·Ð° ÐŽÐ°ÐœÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐºÐŸÑÐŸÑÐ°Ñ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐžÐµ ÑÑÑÑÐºÑÑÑÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐž Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°. ÐÐŸÐœÐµÑÐœÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð³ÐŸÑÐŸÐ²Ð° Ðº ÑÐ°Ð±ÐŸÑÐµ Ð² ÑÐµÐ¶ÐžÐŒÐµ on-line Ðž ÑÐ¿ÐŸÑÐŸÐ±ÐœÐ° Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ Ð¿ÐŸ Ð·Ð°Ð¿ÑÐŸÑÐ°ÐŒ.</Text>
+<Text id="762">ÐÐ²Ð° ÑÐµÐœÑÑÐ°Ð»ÑÐœÑÑ
+ ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑÐ° ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÑÑ ÑÐ°Ð±ÐŸÑÑ ÑÐžÑÑÐµÐŒÑ: "receptionists" (ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÑ) Ðž "collection servers" (ÑÐµÑÐ²ÐµÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž). Ð¡ ÑÐŸÑÐºÐž Ð·ÑÐµÐœÐžÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ, ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÑ - ÑÐŸÑÐºÐ° ÐºÐŸÐœÑÐ°ÐºÑÐ° Ñ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐŸÐ¹. ÐÐœÐž Ð¿ÑÐžÐœÐžÐŒÐ°ÑÑ Ð·Ð°Ð¿ÑÐŸÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð² ÑÐŸÑÐŒÐµ ÐºÐ»Ð°Ð²ÐžÐ°ÑÑÑÐœÐŸÐ³ÐŸ Ð²Ð²ÐŸÐŽÐ° Ðž ÑÐµÐ»ÑÐºÐŸÐ² ÐŒÑÑÐž, Ð°ÐœÐ°Ð»ÐžÐ·ÐžÑÑÑÑ ÐžÑ
+, Ð° Ð·Ð°ÑÐµÐŒ Ð¿ÐŸÑÑÐ»Ð°ÑÑ Ð·Ð°Ð¿ÑÐŸÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐŒÑ ÑÐµÑÐ²ÐµÑÑ (ÐžÐ»Ðž ÑÐµÑÐ²ÐµÑÐ°ÐŒ) ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐŽÐµÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑÑÑ ÐŒÐµÑÑÐŸÐœÐ°Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÐµ ÑÑÐµÐ±ÑÐµÐŒÐŸÐ¹ ÑÐ°ÑÑÐž ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž Ðž Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑÑÑ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÑ ÐŽÐ»Ñ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÐµÐœÐžÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ. Ð¡ÐµÑÐ²ÐµÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŽÐµÐ¹ÑÑÐ²ÑÑÑ ÐºÐ°Ðº Ð°Ð±ÑÑÑÐ°ÐºÑÐœÑÐ¹ ÐŒÐµÑ
+Ð°ÐœÐžÐ·ÐŒ, ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð² ÑÐŸ Ð²ÑÐµÐŒÑ ÐºÐ°Ðº ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÑ ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÑ Ð·Ð° ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ.</Text>
+<Figure id="greenstone_system_using_the_null_protocol">
+<Title>
+<Text id="763">Ð¡ÐžÑÑÐµÐŒÐ° Greenstone, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÐ°Ñ ÐœÑÐ»ÐµÐ²ÐŸÐ¹ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»</Text>
+</Title>
+<File width="329" height="424" url="images/Dev_Fig_046.png"/>
+</Figure>
+<Text id="764">ÐÐ°Ðº Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐŸ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="overview_of_a_general_greenstone_system"/>, ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÑ ÑÐ²ÑÐ·ÑÐ²Ð°ÑÑÑÑ Ñ ÑÐµÑÐ²ÐµÑÐ°ÐŒÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐ¹ Ð¿ÑÐŸÑÐŸÐºÐŸÐ». ÐÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ ÑÑÐŸÐ³ÐŸ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð° Ð·Ð°Ð²ÐžÑÐžÑ ÐŸÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐ°, ÐœÐ° ÐºÐŸÑÐŸÑÐŸÐŒ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ ÑÐžÑÑÐµÐŒÐ° ÑÐžÑÑÐŸÐ²ÑÑ
+ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐº. ÐÐ°ÐžÐ±ÐŸÐ»ÐµÐµ Ð¿ÑÐŸÑÑÐŸÐ¹ Ðž Ð¿ÐŸÐŽÑ
+ÐŸÐŽÑÑÐžÐ¹ Ð²ÑÐ±ÐŸÑ - ÑÑÐŸ ÐŸÐŽÐžÐœ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑ Ðž ÐŸÐŽÐžÐœ ÑÐµÑÐ²ÐµÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐºÐŸÑÐŸÑÑÐµ ÐŸÐ±Ð° ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ ÐœÐ° ÐŸÐŽÐœÐŸÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ. ÐÑ Ð¿ÐŸÐ»ÑÑÐ°ÐµÑÐµ ÐžÐŒÐµÐœÐœÐŸ ÑÐ°ÐºÑÑ ÐŒÐŸÐŽÐžÑÐžÐºÐ°ÑÐžÑ, ÐºÐŸÐ³ÐŽÐ° ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑÐµ ÑÐžÑÑÐµÐŒÑ Greenstone Ñ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐ°ÐŒÐž Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ. Ð ÑÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ ÐŸÐ±Ð° Ð¿ÑÐŸÑÐµÑÑÐ° ÐŸÐ±ÑÐµÐŽÐžÐœÐµÐœÑ Ð² ÐŸÐŽÐžÐœ Ð·Ð°Ð¿ÑÑÐºÐ°ÐµÐŒÑÐ¹ ÑÐ°Ð¹Ð» (ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÑÐ¹ library), Ðž ÑÐ»ÐµÐŽÐŸÐ²Ð°ÑÐµÐ»ÑÐœÐŸ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð° ÑÐ²ÐŸÐŽÐžÑÑÑ Ðº ÑÐŸÐ·ÐŽÐ°ÐœÐžÑÑ ÑÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÑÑ
+ Ð·Ð°Ð¿ÑÐŸÑÐŸÐ². ÐÑ ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒ ÑÑÐŸ null protocol (ÐœÑÐ»ÐµÐ²ÑÐŒ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»ÐŸÐŒ). ÐÐœ ÑÐŸÑÐŒÐžÑÑÐµÑ ÐŸÑÐœÐŸÐ²Ñ ÐŽÐ»Ñ ÑÑÐ°ÐœÐŽÐ°ÑÑÐ° out-of-the-box (ÐžÐ· Ð±Ð»ÐŸÐºÐ°) ÑÐžÑÑÐŸÐ²ÐŸÐ¹ ÑÐžÑÑÐµÐŒÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐº Greenstone. ÐÐµ ÑÐ¿ÑÐŸÑÐµÐœÐœÐ°Ñ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐ° ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="greenstone_system_using_the_null_protocol"/> Ñ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÐŸÐŒ, Ð¿ÑÐŸÑÐŸÐºÐŸÐ»ÐŸÐŒ Ðž ÑÐµÑÐ²ÐµÑÐŸÐŒ ÑÐŸÐ²ÐŸÐºÑÐ¿ÐœÐŸÑÑÐž, ÑÐ²ÑÐ·Ð°ÐœÐœÑÐŒÐž Ð²ÐŒÐµÑÑÐµ Ð² ÐŸÐŽÐžÐœ ÐŸÐ±ÑÐµÐºÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž. ÐŠÐµÐ»Ñ ÑÑÐŸÐ¹ Ð³Ð»Ð°Ð²Ñ ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸÐ±Ñ ÐŸÐ±ÑÑÑÐœÐžÑÑ Ð²Ð°ÐŒ, ÐºÐ°Ðº Ð²ÑÐµ ÑÑÐŸ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ.</Text>
+<Text id="765">ÐÐ±ÑÑÐœÐŸ "ÑÐµÑÐ²ÐµÑ" - Ð¿ÐŸÑÑÐŸÑÐœÐœÑÐ¹ Ð¿ÑÐŸÑÐµÑÑ: ÐµÐŽÐžÐœÐŸÐ¶ÐŽÑ Ð·Ð°Ð¿ÑÑÐµÐœÐœÑÐ¹, ÑÐ°Ð±ÐŸÑÐ°ÐµÑ Ð¿ÐŸÑÑÐŸÑÐœÐœÐŸ, ÐŸÑÐ²ÐµÑÐ°Ñ ÐœÐ° Ð»ÑÐ±ÑÐµ Ð²Ñ
+ÐŸÐŽÑÑÐžÐµ Ð·Ð°Ð¿ÑÐŸÑÑ. ÐÐµÑÐŒÐŸÑÑÑ ÐœÐ° ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ, ÑÐµÑÐ²ÐµÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐœÑÐ»ÐµÐ²ÐŸÐ³ÐŸ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð° ÐœÐµ ÑÐ²Ð»ÑÐµÑÑÑ ÑÐµÑÐ²ÐµÑÐŸÐŒ Ð² Ð¿ÑÐžÐ²ÑÑÐœÐŸÐŒ ÑÐŒÑÑÐ»Ðµ ÑÐ»ÐŸÐ²Ð°. Ð€Ð°ÐºÑÐžÑÐµÑÐºÐž, ÐºÐ°Ð¶ÐŽÑÐ¹ ÑÐ°Ð·, ÐºÐŸÐ³ÐŽÐ° Ð²ÑÐ·ÑÐ²Ð°ÑÑ Ð»ÑÐ±ÑÑ web-ÑÑÑÐ°ÐœÐžÑÑ Greenstone, Ð·Ð°Ð¿ÑÑÐºÐ°ÐµÑÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° library (CGI ÐŒÐµÑ
+Ð°ÐœÐžÐ·ÐŒÐŸÐŒ), ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÑÐ²ÐµÑÐ°ÐµÑ ÐœÐ° Ð·Ð°Ð¿ÑÐŸÑ Ðž Ð·Ð°ÑÐµÐŒ Ð²ÑÐ³ÑÑÐ¶Ð°ÐµÑÑÑ. Ð­ÑÐŸ ÐŒÑ ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒ "ÑÐµÑÐ²ÐµÑÐŸÐŒ", Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐŸ ÐŸÐœ ÑÐ°ÐºÐ¶Ðµ Ð¿ÑÐµÐŽÐœÐ°Ð·ÐœÐ°ÑÐµÐœ ÐŽÐ»Ñ ÑÐ°Ð±ÐŸÑÑ Ñ Ð±ÐŸÐ»ÐµÐµ ÐŸÐ±ÑÐµÐ¹ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐµÐ¹ (ÑÐŒ. ÑÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="overview_of_a_general_greenstone_system"/>).</Text>
+<Text id="766">Ð£ÐŽÐžÐ²ÐžÑÐµÐ»ÑÐœÐŸ, ÐœÐŸ ÑÐžÐºÐ» Ð·Ð°Ð¿ÑÑÐºÐ°, ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž Ðž Ð²ÑÑ
+ÐŸÐŽÐ° ÑÐ°Ð±ÐŸÑÐ°ÐµÑ ÐœÐµ ÑÐ°Ðº ÐŒÐµÐŽÐ»ÐµÐœÐœÐŸ, ÐºÐ°Ðº ÐŒÐŸÐ¶ÐœÐŸ Ð±ÑÐ»ÐŸ ÐŸÐ¶ÐžÐŽÐ°ÑÑ. ÐÐŽÐœÐ°ÐºÐŸ, ÑÑÐŸ Ð°Ð±ÑÐŸÐ»ÑÑÐœÐŸ ÐœÐµÑÑÑÐµÐºÑÐžÐ²ÐœÐŸ. Ð¡ÑÑÐµÑÑÐ²ÑÐµÑ ÐŒÐµÑ
+Ð°ÐœÐžÐ·ÐŒ Fast-CGI (www.fastcgi.com), ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ ÑÑÐµÐŽÐœÐžÐ¹ ÑÑÐŸÐ²ÐµÐœÑ. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐµÐ³ÐŸ, Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° library ÐŒÐŸÐ¶ÐµÑ ÐŸÑÑÐ°ÑÑÑÑ Ð² Ð¿Ð°ÐŒÑÑÐž Ð² ÐºÐŸÐœÑÐµ Ð¿ÐµÑÐ²ÐŸÐ³ÐŸ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ Ðž ÐœÐ°ÐºÐ°Ð¿Ð»ÐžÐ²Ð°ÑÑ Ð¿ÐŸÑÐ»ÐµÐŽÑÑÑÐžÐµ ÐœÐ°Ð±ÐŸÑÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ² CGI, ÑÐ°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ ÐžÐ·Ð±ÐµÐ³Ð°Ñ Ð¿ÐŸÐ²ÑÐŸÑÐœÑÑ
+ ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÐ¹ Ðž ÐŽÐŸÑÑÐžÐ³Ð°Ñ Ð¿ÐŸÑÑÐž ÑÐ°ÐºÐŸÐ³ÐŸ Ð¶Ðµ ÑÑÐŸÐ²ÐœÑ ÑÐ°Ð±ÐŸÑÑ, ÐºÐ°Ðº ÑÐµÑÐ²ÐµÑ. Fast-CGI Ð² Greenstone ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐºÐ°Ðº ÐŸÐ¿ÑÐžÑ, ÐŽÐŸÐ¿ÑÑÐºÐ°Ñ Ð¿ÐŸÐ²ÑÐŸÑÐœÑÑ ÐºÐŸÐŒÐ¿ÐžÐ»ÑÑÐžÑ ÐžÑÑ
+ÐŸÐŽÐœÐŸÐ³ÐŸ ÑÐµÐºÑÑÐ° Ñ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐŒÐž Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÐŒÐž.</Text>
+<Text id="767">ÐÐ°Ðº Ð°Ð»ÑÑÐµÑÐœÐ°ÑÐžÐ²Ð° ÐœÑÐ»ÐµÐ²ÐŸÐŒÑ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ñ, Ð¿ÑÐŸÑÐŸÐºÐŸÐ» Greenstone Ð±ÑÐ» ÑÐ°ÐºÐ¶Ðµ ÑÐŸÐ·ÐŽÐ°Ðœ Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ ÐžÐ·Ð²ÐµÑÑÐœÐŸÐ¹ ÑÑ
+ÐµÐŒÑ CORBA (Slama et al, 1999). ÐÐœ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÐŸÐ±ÑÐµÐŽÐžÐœÐµÐœÐœÑÑ ÐŸÐ±ÑÐµÐºÑÐœÐŸ-ÐŸÑÐžÐµÐœÑÐžÑÐŸÐ²Ð°ÐœÐœÑÑ Ð¿Ð°ÑÐ°ÐŽÐžÐ³ÐŒÑ, ÑÑÐŸÐ±Ñ ÑÐ°Ð·ÑÐµÑÐžÑÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒ Ð¿ÑÐŸÑÐµÑÑÐ°ÐŒ, Ð²ÑÐ¿ÐŸÐ»ÐœÑÑÑÐžÐŒÑÑ ÐœÐ° ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐœÑÑ
+ Ð¿Ð»Ð°ÑÑÐŸÑÐŒÐ°Ñ
+ Ðž ÑÐŸÐ·ÐŽÐ°ÐœÐœÑÑ
+ ÐœÐ¿ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÑÐ·ÑÐºÐ°Ñ
+ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ, ÐŸÐ±ÑÐ°ÑÐ°ÑÑÑÑ Ðº ÐŸÐŽÐœÐŸÐŒÑ Ðž ÑÐŸÐŒÑ Ð¶Ðµ ÐœÐ°Ð±ÐŸÑÑ ÑÐ°ÑÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ ÐŸÐ±ÑÐµÐºÑÐŸÐ² Ð² Internet (ÐžÐ»Ðž Ð»ÑÐ±ÐŸÐ¹ ÐŽÑÑÐ³ÐŸÐ¹ ÑÐµÑÐž). Ð¢ÐŸÐ³ÐŽÐ° ÑÑÐµÐœÐ°ÑÐžÐž, Ð¿ÐŸÐŽÐŸÐ±ÐœÐŸ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐœÐŸÐŒÑ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="overview_of_a_general_greenstone_system"/>, ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð¿ÐŸÐ»ÐœÐŸÑÑÑÑ ÐŸÑÑÑÐµÑÑÐ²Ð»ÐµÐœÑ ÑÐŸ Ð²ÑÐµÐŒÐž ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÐ°ÐŒÐž Ðž ÑÐµÑÐ²ÐµÑÐ°ÐŒÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐ°Ð±ÐŸÑÐ°ÑÑÐžÐŒÐž ÐœÐ° ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐ°Ñ
+.</Text>
+<Figure id="graphical_query_interface_to_greenstone">
+<Title>
+<Text id="768">ÐÑÐ°ÑÐžÑÐµÑÐºÐžÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð·Ð°Ð¿ÑÐŸÑÐ° Greenstone</Text>
+</Title>
+<File width="397" height="348" url="images/Dev_Fig_048.png"/>
+</Figure>
+<Text id="769">Ð­ÑÐŸ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÑÑ ÐŽÐ»Ñ ÑÐ°Ð±ÐŸÑÑ Ñ ÑÐµÐŒÐž Ð¶Ðµ ÑÐ°ÐŒÑÐŒÐž ÑÐžÑÑÐŸÐ²ÑÐŒÐž Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐŒÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒÐž ÐœÐ°ÐŒÐœÐŸÐ³ÐŸ Ð±ÐŸÐ»ÐµÐµ ÑÐ»ÐŸÐ¶ÐœÑÐµ ÐžÐœÑÐµÑÑÐµÐ¹ÑÑ. Ð ÐºÐ°ÑÐµÑÑÐ²Ðµ Ð¿ÑÐžÐŒÐµÑÐ° ÑÐ°ÑÑÐŒÐŸÑÑÐžÐŒ ÐŸÐŽÐžÐœ ÑÐžÑÑÐœÐŸÐº (ÑÐŒ. ÑÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="graphical_query_interface_to_greenstone"/>), ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð³ÑÐ°ÑÐžÑÐµÑÐºÐžÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð·Ð°Ð¿ÑÐŸÑÐ°, ÐŸÑÐœÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐœÐ° ÐŽÐžÐ°Ð³ÑÐ°ÐŒÐŒÐ°Ñ
+ ÐÐµÐœÐœÐ°, Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑÐžÐ¹ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÐŒ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ ÑÐ¿ÑÐ°Ð²Ð»ÑÑÑ ÐÑÐ»ÐµÐ²ÑÐŒÐž Ð·Ð°Ð¿ÑÐŸÑÐ°ÐŒÐž. ÐÐ°Ð¿ÐžÑÐ°ÐœÐœÑÐ¹ ÐœÐ° Java, ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð·Ð°Ð¿ÑÑÐºÐ°ÐµÑÑÑ Ð»ÐŸÐºÐ°Ð»ÑÐœÐŸ ÐœÐ° ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÐŸÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÑ CORBA, ÐŸÐœ ÐŸÐ±ÑÐ°ÑÐ°ÐµÑÑÑ Ðº ÐŸÑÐŽÐ°Ð»ÐµÐœÐœÐŸÐŒÑ ÑÐµÑÐ²ÐµÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Greenstone, ÐœÐ°Ð¿ÐžÑÐ°ÐœÐœÐŸÐŒÑ ÐœÐ° C++.</Text>
+<Text id="770">Ð Ð°ÑÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐ¹ Ð¿ÑÐŸÑÐŸÐºÐŸÐ» Ð²ÑÐµ ÐµÑÐµ ÑÐŸÐ²ÐµÑÑÐµÐœÑÑÐ²ÑÐµÑÑÑ Ðž Ð³ÐŸÑÐŸÐ²ÐžÑÑÑ ÐŽÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ, ÑÐ°Ðº ÑÑÐŸ Ð² ÑÑÐŸÐŒ ÑÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ðµ ÐŒÑ Ð±ÐŸÐ»ÐµÐµ ÐœÐµ ÑÑÐ°ÐœÐµÐŒ ÐµÐ³ÐŸ ÐŸÐ±ÑÑÐ¶ÐŽÐ°ÑÑ (ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÑÐµÐœÐžÑ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž ÑÐŒ. Bainbridge et al., 2001).</Text>
+</Content>
+</Section>
+<Section id="conceptual_framework">
+<Title>
+<Text id="771">ÐÐŸÐœÑÐµÐ¿ÑÑÐ°Ð»ÑÐœÐ°Ñ ÑÑÑÑÐºÑÑÑÐ°</Text>
+</Title>
+<Content>
+<Figure id="generating_the_about_this_collection_page">
+<Title>
+<Text id="772">ÐÐµÐœÐµÑÐ°ÑÐžÑ ÑÑÑÐ°ÐœÐžÑÑ "about this collection"</Text>
+</Title>
+<File width="398" height="354" url="images/Dev_Fig_050.png"/>
+</Figure>
+<Text id="773">Ð ÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="generating_the_about_this_collection_page"/> Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÑÑÑÐ°ÐœÐžÑÑ "about this collection" (ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž) ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Greenstone (ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐÑÐŸÐµÐºÑÐ° Gutenberg). Ð¡ÐŒÐŸÑÑÐžÑÐµ URL ÐœÐ°Ð²ÐµÑÑ
+Ñ. Ð¡ÑÑÐ°ÐœÐžÑÐ° ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐ° Ð² ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐµ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ CGI-Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ library, ÐºÐŸÑÐŸÑÐ°Ñ, ÐºÐ°Ðº Ð³ÐŸÐ²ÐŸÑÐžÐ»ÐŸÑÑ Ð²ÑÑÐµ,ÑÐ²Ð»ÑÐµÑÑÑ Ð²ÑÐ¿ÐŸÐ»ÐœÑÐµÐŒÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐŸÐ¹, Ð²ÐºÐ»ÑÑÐ°ÑÑÐµÐ¹ Ðž ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑ Ðž ÑÐµÑÐ²ÐµÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐ²ÑÐ·Ð°ÐœÐœÑÐ¹ Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐž Ñ ÐœÑÐ»ÐµÐ²ÑÐŒ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»ÐŸÐŒ. ÐÑÐ³ÑÐŒÐµÐœÑÑ library - c=gberg, a=p, Ðž p=about. ÐÐœÐž ÐŒÐŸÐ³ÑÑ ÐžÐœÑÐµÑÐ¿ÑÐµÑÐžÑÐŸÐ²Ð°ÑÑÑÑ ÑÐ»ÐµÐŽÑÑÑÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ:</Text>
+<Indented>
+<Text id="774">ÐÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐÑÐŸÐµÐºÑ Gutenberg (c=gberg) ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ Ð³ÐµÐœÐµÑÐžÑÑÐµÑ ÑÑÑÐ°ÐœÐžÑÑ (Ð°=Ñ), ÑÐ³ÐµÐœÑÐžÑÐŸÐ²Ð°ÐœÐœÐ°Ñ ÑÑÑÐ°ÐœÐžÑÐ° ÐœÐ°Ð·Ð²Ð°ÐœÐ° "about" (p=about).</Text>
+</Indented>
+<Figure id="greenstone_runtime_system">
+<Title>
+<Text id="775">Ð Ð°Ð±ÐŸÑÐ° ÑÐžÑÑÐµÐŒÑ Greenstone</Text>
+</Title>
+<File width="534" height="345" url="images/Dev_Fig_052.png"/>
+</Figure>
+<Text id="776">Ð ÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="greenstone_runtime_system"/> ÐžÐ»Ð»ÑÑÑÑÐžÑÑÐµÑ ÐŸÑÐœÐŸÐ²ÐœÑÐµ ÑÐ°ÑÑÐž ÑÐ°Ð±ÐŸÑÑ ÑÐžÑÑÐµÐŒÑ Greenstone. ÐÐ°Ð²ÐµÑÑ
+Ñ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑ ÑÐœÐ°ÑÐ°Ð»Ð° ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·ÐžÑÑÐµÑ ÑÐ²ÐŸÐž ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑÑ, Ð·Ð°ÑÐµÐŒ Ð°ÐœÐ°Ð»ÐžÐ·ÐžÑÑÐµÑ CGI-Ð°ÑÐ³ÑÐŒÐµÐœÑÑ, ÑÑÐŸÐ±Ñ ÑÐµÑÐžÑÑ, ÐºÐ°ÐºÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ Ð·Ð°Ð¿ÑÑÑÐžÑÑ. ÐÑÐž Ð·Ð°Ð¿ÑÑÐºÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ (ÐºÐŸÑÐŸÑÐŸÐµ Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð² ÐŽÐ°Ð»ÑÐœÐµÐ¹ÑÐµÐŒ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÑ CGI Ð°ÑÐ³ÑÐŒÐµÐœÑÐŸÐ²), Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ Ð¿ÑÐŸÑÐŸÐºÐŸÐ», ÑÑÐŸÐ±Ñ ÐŸÐ±ÑÐ°ÑÐžÑÑÑÑ Ðº ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÐ²ÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ Ð³ÐµÐœÐµÑÐ°ÑÐžÐž web-ÑÑÑÐ°ÐœÐžÑÑ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑÐ° ÑÐŸÑÐŒÐ°ÑÐ° Ðž ÐŒÐ°ÐºÑÐŸÑÐ·ÑÐºÐ°.</Text>
+<Text id="777">ÐÐ°ÐºÑÐŸÑÐ·ÑÐº, ÐºÐŸÑÐŸÑÑÐ¹ ÐŒÑ Ð²ÐžÐŽÐµÐ»ÐžÐ² Ð Ð°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Section" ref="controlling_the_greenstone_user_interface"/>, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ, ÑÑÐŸÐ±Ñ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÑÑ ÑÐžÑÑÐŸÐ²ÑÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÑ ÑÐžÑÑÐµÐŒÑ Greenstone Ð»Ð°ÐºÐŸÐœÐžÑÐœÑÐŒ ÑÑÐžÐ»ÐµÐŒ Ðž ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ ÐžÐœÑÐµÑÑÐµÐ¹ÑÑ ÐœÐ° ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÑÐ·ÑÐºÐ°Ñ
+. ÐÐ·Ð°ÐžÐŒÐŸÐŽÐµÐ¹ÑÑÐ²ÐžÐµ Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐŸÐ¹ Ð³ÐµÐœÐµÑÐžÑÑÐµÑ ÑÐºÐµÐ»ÐµÑ web-ÑÑÑÐ°ÐœÐžÑ; ÐŒÐ°ÐºÑÐŸÑ Ð² GSDLHOME/macros ÐœÐ°ÑÐ°ÑÐžÐ²Ð°ÐµÑ ÐœÐ° ÑÑÐŸÑ ÑÐºÐµÐ»ÐµÑ Ð¿Ð»ÐŸÑÑ.</Text>
+<Text id="778">ÐÐ±ÑÐµÐºÑ Macro Language (ÐŒÐ°ÐºÑÐŸÑÐ·ÑÐº) ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="greenstone_runtime_system"/> ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐµÐœ Ð·Ð° ÑÑÐµÐœÐžÐµ ÑÐ°Ð¹Ð»ÐŸÐ² Ðž ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐžÐµ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐ° Ð°ÐœÐ°Ð»ÐžÐ·Ð° ÑÑÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² Ð² Ð¿Ð°ÐŒÑÑÐž. ÐÑÐ±ÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ ÐŒÐŸÐ¶ÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÑÑÐŸÑ ÐŸÐ±ÑÐµÐºÑ, ÑÑÐŸÐ±Ñ ÑÐ°Ð·Ð²ÐµÑÐœÑÑÑ ÐŒÐ°ÐºÑÐŸÐºÐŸÐŒÐ°ÐœÐŽÑ. ÐÐœÐŸ ÐŒÐŸÐ¶ÐµÑ ÐŽÐ°Ð¶Ðµ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐœÐŸÐ²ÑÐµ ÐŒÐ°ÐºÑÐŸÑÑ Ðž ÐŸÑÐŒÐµÐœÐžÑÑ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ, ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑ ÐŽÐžÐœÐ°ÐŒÐžÑÐµÑÐºÐŸÐµ ÑÐ°ÑÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐµ Ð² ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž ÐŒÐ°ÐºÑÐŸÑÐŸÐ².</Text>
+<Text id="779">ÐÐœÐµÑÐœÐžÐ¹ Ð²ÐžÐŽ ÑÑÑÐ°ÐœÐžÑÑ "about this collection" (ÑÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="generating_the_about_this_collection_page"/>) ÐžÐ·Ð²ÐµÑÑÐµÐœ ÐŽÐŸ ÐŒÐŸÐŒÐµÐœÑÐ° Ð·Ð°Ð¿ÑÑÐºÐ° Ðž Ð·Ð°ÐºÐŸÐŽÐžÑÐŸÐ²Ð°Ðœ Ð² ÐŒÐ°ÐºÑÐŸÑÐ°Ð¹Ð»Ðµ about.dm. ÐÐ°Ð³ÐŸÐ»ÐŸÐ²ÐºÐž, ÐœÐžÐ¶ÐœÐžÐµ ÐºÐŸÐ»ÐŸÐœÑÐžÑÑÐ»Ñ Ðž ÑÐŸÐœÐŸÐ²Ð°Ñ Ð·Ð°Ð»ÐžÐ²ÐºÐ° ÐŽÐ°Ð¶Ðµ ÐœÐµ ÑÐ¿ÐŸÐŒÑÐœÑÑÑ, Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ ÐŸÐœÐž ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÑ Ð² Ð¿Ð°ÐºÐµÑÐµ ÐŒÐ°ÐºÑÐŸÐºÐŸÐŒÐ°ÐœÐŽÑ Global. ÐÐŽÐœÐ°ÐºÐŸ, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐ¹ "about" ÑÐµÐºÑÑ (ÑÐµÐºÑÑ ÐŽÐ»Ñ ÑÑÑÐ°ÐœÐžÑÑ "Ð ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž") ÐŽÐ»Ñ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐœÐµ ÐžÐ·Ð²ÐµÑÑÐµÐœ Ð·Ð°ÑÐ°ÐœÐµÐµ, ÐŸÐœ Ñ
+ÑÐ°ÐœÐžÑÑÑ Ð² ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ Ð±Ð°Ð·Ðµ ÐŽÐ°ÐœÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð² ÑÐµÑÐµÐœÐžÐµ Ð¿ÑÐŸÑÐµÑÑÐ° ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ. Ð­ÑÐ° ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ Ð²ÑÐ·ÑÐ²Ð°ÐµÑÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð° Ðž Ñ
+ÑÐ°ÐœÐžÑÑÑ ÐºÐ°Ðº _collectionextra_ Ð² Ð¿Ð°ÐºÐµÑÐµ ÐŒÐ°ÐºÑÐŸÐºÐŸÐŒÐ°ÐœÐŽÑ Global. ÐÐ±ÑÐ°ÑÐžÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ ÐœÐ° ÑÐŸ, ÑÑÐŸ ÐžÐŒÑ ÐŒÐ°ÐºÑÐŸÑÐ° - Ð¿ÐŸ ÑÑÑÐµÑÑÐ²Ñ ÐžÐŒÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐŸÐµ ÐŽÐ»Ñ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ ÑÑÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐŸÐ¿ÐžÑÐ°ÐœÐœÐŸÐŒ Ð² Ð Ð°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Section" ref="configuration_file"/>. Ð§ÑÐŸÐ±Ñ ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ ÑÑÑÐ°ÐœÐžÑÑ, Ð±ÑÐ»Ð° ÑÐ°ÑÑÐžÑÐµÐœÐ° ÐŒÐ°ÐºÑÐŸÐºÐŸÐŒÐ°ÐœÐŽÐ° _content_ Ð² Ð¿Ð°ÐºÐµÑÐµ about (ÑÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="part_of_the_aboutdm_macro_file"/>) . ÐÐœÐ° Ð² ÑÐ²ÐŸÑ ÐŸÑÐµÑÐµÐŽÑ Ð·Ð°Ð¿ÑÑÐºÐ°ÐµÑ _textabout _, ÐºÐŸÑÐŸÑÑÐ¹ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ ÐŸÐ±ÑÐ°ÑÐ°ÐµÑÑÑ Ðº _collectionextra _, ÑÐŸÐ»ÑÐºÐŸ ÑÑÐŸ ÐŽÐžÐœÐ°ÐŒÐžÑÐµÑÐºÐž Ð¿ÐŸÐŒÐµÑÐµÐœÐœÐŸÐ¹ ÑÑÐŽÐ°.</Text>
+<Text id="780">Ð¡Ð»ÐµÐŽÑÑÑÐžÐ¹ Ð²Ð°Ð¶ÐœÑÐ¹ ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑ - ÐŸÐ±ÑÐµÐºÑ Format. ÐÐ¿ÐµÑÐ°ÑÐŸÑÑ Ð·Ð°ÐŽÐ°ÐœÐžÑ ÑÐŸÑÐŒÐ°ÑÐ° Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð·Ð°ÑÑÐ°Ð³ÐžÐ²Ð°ÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐžÑ
+ ÑÐ°ÑÑÐµÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž, ÐºÐ°Ðº ÐŸÐ¿ÐžÑÐ°ÐœÐŸ Ð² Ð Ð°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Section" ref="formatting_greenstone_output"/>. ÐÐœÐž ÐŸÐ±ÑÐ°Ð±ÐŸÑÐ°ÐœÑ ÐŸÐ±ÑÐµÐºÑÐŸÐŒ Format (ÑÐŒ. ÑÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="greenstone_runtime_system"/>). ÐÑÐœÐŸÐ²ÐœÐ°Ñ Ð·Ð°ÐŽÐ°ÑÐ° ÑÑÐŸÐ³ÐŸ ÐŸÐ±ÑÐµÐºÑÐ° ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸÐ±Ñ Ð°ÐœÐ°Ð»ÐžÐ·ÐžÑÐŸÐ²Ð°ÑÑ Ðž ÐŸÑÐµÐœÐžÐ²Ð°ÑÑ ÐžÐœÑÑÑÑÐºÑÐžÐž ÑÐžÐ¿Ð° ÑÑÑÐŸÐº ÑÐŸÑÐŒÐ°ÑÐ° (ÑÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="excerpt_from_the_demo_collection_collect"/>). ÐÐ°Ðº ÑÑÐ°Ð»ÐŸ ÑÑÐœÐŸ ÐžÐ· Ð Ð°Ð·ÐŽÐµÐ»Ð° <CrossRef target="Section" ref="formatting_greenstone_output"/>, ÐŸÐœÐž ÐŒÐŸÐ³ÑÑ Ð²ÐºÐ»ÑÑÐ°ÑÑ ÑÑÑÐ»ÐºÐž ÐœÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð² ÐºÐ²Ð°ÐŽÑÐ°ÑÐœÑÑ
+ ÑÐºÐŸÐ±ÐºÐ°Ñ
+ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, [Title]), ÐºÐŸÑÐŸÑÑÐµ ÐŽÐŸÐ»Ð¶ÐµÐœÑ Ð±ÑÑÑ ÐœÐ°Ð¹ÐŽÐµÐœÑ ÑÐµÑÐ²ÐµÑÐŸÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ·Ð°ÐžÐŒÐŸÐŽÐµÐ¹ÑÑÐ²ÐžÐµ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ ÐŒÐµÐ¶ÐŽÑ ÐŸÐ±ÑÐµÐºÑÐŸÐŒ Format Ðž ÐŸÐ±ÑÐµÐºÑÐŸÐŒ Macro Language, Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ ÐŸÐ¿ÐµÑÐ°ÑÐŸÑÑ Ð·Ð°ÐŽÐ°ÐœÐžÑ ÑÐŸÑÐŒÐ°ÑÐ° ÐŒÐŸÐ³ÑÑ Ð²ÐºÐ»ÑÑÐ°ÑÑ ÐŒÐ°ÐºÑÐŸÑÑ, ÐºÐŸÑÐŸÑÑÐµ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÑÐ°ÑÑÐžÑÐµÐœÐžÑ Ð²ÐºÐ»ÑÑÐ°ÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, ÐºÐŸÑÐŸÑÑÐµ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÑÐ°ÑÑÐžÑÐµÐœÐžÑ Ð²ÐºÐ»ÑÑÐ°ÑÑ ÐŒÐ°ÐºÑÐŸÑÑ Ðž ÑÐ°Ðº ÐŽÐ°Ð»ÐµÐµ.</Text>
+<Text id="781">ÐÐœÐžÐ·Ñ ÑÐžÑÑÐœÐºÐ° <CrossRef target="Figure" ref="greenstone_runtime_system"/>, ÑÐµÑÐ²ÐµÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐ°ÐºÐ¶Ðµ Ð¿ÑÐŸÑ
+ÐŸÐŽÐžÑ Ð¿ÑÐŸÑÐµÑÑ ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÐž, ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°Ñ ÐŸÐ±ÑÐµÐºÑÑ Filter Ðž Source, ÑÑÐŸÐ±Ñ ÐŸÑÐ²ÐµÑÐžÑÑ ÐœÐ° Ð²Ñ
+ÐŸÐŽÑÑÐžÐµ Ð·Ð°Ð¿ÑÐŸÑÑ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð°, Ðž ÐŸÐ±ÑÐµÐºÑ Search, ÑÑÐŸÐ±Ñ ÐŸÐ±Ð»ÐµÐ³ÑÐžÑÑ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ Ð·Ð°ÐŽÐ°ÑÐž. Ð ÐºÐŸÐœÐµÑÐœÐŸÐŒ ÑÑÐµÑÐµ ÐŸÐœÐž ÐŸÐ±ÑÐ°ÑÐ°ÑÑÑÑ Ðº ÐžÐœÐŽÐµÐºÑÐ°ÐŒ Ðž ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ Ð±Ð°Ð·Ðµ ÐŽÐ°ÐœÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐºÐŸÑÐŸÑÑÐµ ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°Ð»ÐžÑÑ Ð² Ð¿ÑÐŸÑÐµÑÑÐµ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="782">ÐÐ³ÐœÐŸÑÐžÑÑÑ Ð¿ÑÑÑÑÐµ ÑÑÑÐŸÐºÐž, ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑ ÑÐŸÐŽÐµÑÐ¶ÐžÑ 15 000 ÑÑÑÐŸÐº Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ. Ð¡ÐµÑÐ²ÐµÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÑÐŸÐ»ÑÐºÐŸ 5 000 ÑÑÑÐŸÐº (75 % ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ Ð·Ð°ÐœÐžÐŒÐ°ÑÑ ÑÐ°Ð¹Ð»Ñ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ°). Ð¡ÐµÑÐ²ÐµÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð±ÐŸÐ»ÐµÐµ ÐºÐŸÐŒÐ¿Ð°ÐºÑÐµÐœ, Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ ÑÐµÐ»ÐµÐ²Ð°ÐœÑÐœÑÐ¹ Ð¿ÐŸÐžÑÐº Ð¿ÑÐŸÑ
+ÐŸÐŽÐžÑ ÑÐµÑÐµÐ· ÐŽÐ²Ðµ Ð¿ÑÐµÐŽÐŸÑÐºÐŸÐŒÐ¿ÐžÐ»ÑÑÐžÐŸÐœÐœÑÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ. ÐÐ»Ñ Ð¿ÐŸÐžÑÐºÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð¿ÐŸÐ»ÐœÐŸÑÐµÐºÑÑÐŸÐ²Ð°Ñ Ð¿ÐŸÐžÑÐºÐŸÐ²Ð°Ñ ÑÐžÑÑÐµÐŒÐ° MG, Ð° ÐŽÐ»Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐž ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ Ð±Ð°Ð·Ñ ÐŽÐ°ÐœÐœÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð¡Ð£ÐÐ GDBM.</Text>
+<Text id="783">ÐÐ»Ñ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ ÑÐ°ÑÑÐžÑÑÐµÐŒÐŸÑÑÐž Ðž Ð³ÐžÐ±ÐºÐŸÑÑÐž Greenstone ÑÐžÑÐŸÐºÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ Ð¿ÐŸÑÑÐŽÐŸÐº ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐžÑ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ Action, Filter, Source Ðž Search. ÐÐ»Ñ Ð¿ÑÐŸÑÑÐŸÐ¹ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž, ÑÐ¿ÐµÑÐžÐ°Ð»ÐžÐ·ÐžÑÐŸÐ²Ð°ÐœÐœÐŸÐ¹ ÐœÐ° ÑÐµÐºÑÑÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÑÐŸ ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ, ÑÑÐŸ Ð²Ñ ÐŽÐŸÐ»Ð¶ÐœÑ ÑÐ·ÐœÐ°ÑÑ ÐœÐµÐŒÐœÐŸÐ³ÐŸ Ð±ÐŸÐ»ÑÑÐµ, ÑÑÐŸÐ±Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐžÑÐŸÐ²Ð°ÑÑ ÑÐžÑÑÐµÐŒÑ. ÐÐŽÐœÐ°ÐºÐŸ, ÑÑÐŸ ÑÐ°ÐºÐ¶Ðµ ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ, ÑÑÐŸ MG Ðž GDBM ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð»ÐµÐ³ÐºÐŸ Ð·Ð°ÐŒÐµÐœÐµÐœÑ, ÐµÑÐ»Ðž Ð²ÐŸÐ·ÐœÐžÐºÐœÐµÑ Ð¿ÐŸÑÑÐµÐ±ÐœÐŸÑÑÑ. ÐÑÐŸÐŒÐµ ÑÐŸÐ³ÐŸ, Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐ°Ñ Ð°ÑÑ
+ÐžÑÐµÐºÑÑÑÐ° ÐŽÐŸÑÑÐ°ÑÐŸÑÐœÐŸ Ð±ÐŸÐ³Ð°ÑÐ°, ÑÑÐŸÐ±Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶Ð°ÑÑ Ð¿ÐŸÐ»ÐœÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž ÐŒÑÐ»ÑÑÐžÐŒÐµÐŽÐžÐ°, ÑÐžÐ¿Ð° ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐŸÐŒ ÑÐµÑÐµÐ· ÑÑÑÑÐŸÐ¹ÑÑÐ²ÐŸ ÑÐµÑÐµÐ²ÐŸÐ³ÐŸ Ð²Ð²ÐŸÐŽÐ° ÐžÐ»Ðž Ð¿ÐµÑÐµÐŽÐ°ÑÐž Ð·Ð°Ð¿ÑÐŸÑÐŸÐ² Ð² Ð²ÐžÐŽÐµ Ð³ÑÐ°ÑÐžÑÐµÑÐºÑ
+ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐ¹.</Text>
+</Content>
+</Section>
+<Section id="how_the_conceptual_framework_fits_together">
+<Title>
+<Text id="784">Ð¡ÐŸÐ²ÐŒÐµÑÑÐžÐŒÐŸÑÑÑ ÐºÐŸÐœÑÐµÐ¿ÑÑÐ°Ð»ÑÐœÐŸÐ¹ ÑÑÑÑÐºÑÑÑÑ</Text>
+</Title>
+<Content>
+<Text id="785">Ð Ð°Ð·ÐŽÐµÐ»Ñ <CrossRef target="Section" ref="collection_server"/> Ðž <CrossRef target="Section" ref="receptionist"/> ÐŸÐ±ÑÑÑÐœÑÑÑ Ð²Ð·Ð°ÐžÐŒÐŸÐŽÐµÐ¹ÑÑÐ²ÐžÐµ ÑÐµÑÐ²ÐµÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÐ° Ð±ÐŸÐ»ÐµÐµ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸ, ÐŸÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÑÑÑ ÐœÐ° ÐºÐ°Ð¶ÐŽÐŸÐŒ ÐŒÐŸÐŽÑÐ»Ðµ ÑÐžÑÑÐœÐºÐ° <CrossRef target="Figure" ref="greenstone_runtime_system"/> Ðž ÐŸÐ¿ÐžÑÑÐ²Ð°Ñ, ÐºÐ°Ðº ÑÑÐŸ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ. ÐÐŸÐ»ÐµÐ·ÐœÐŸ ÑÐœÐ°ÑÐ°Ð»Ð° ÑÐ°Ð·ÐŸÐ±ÑÐ°ÑÑÑÑ ÐœÐ° Ð¿ÑÐžÐŒÐµÑÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ, Ð²Ð·Ð°ÐžÐŒÐŸÐŽÐµÐ¹ÑÑÐ²ÑÑÑÐµÐ³ÐŸ Ñ Greenstone, Ðž ÐŸÐ¿ÐžÑÑÐ²Ð°ÑÑ ÑÐŸ, ÑÑÐŸ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ. ÐÑÐµÐŽÐ¿ÐŸÐ»Ð°Ð³Ð°ÐµÑÑÑ, ÑÑÐŸ Ðº ÐœÐ°ÑÑÐŸÑÑÐµÐŒÑ ÐŒÐŸÐŒÐµÐœÑÑ Ð²ÑÐµ ÐŸÐ±ÑÐµÐºÑÑ Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸ ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·ÐžÑÐŸÐ²Ð°ÐœÑ. ÐÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÑ - Ð·Ð°Ð¿ÑÑÐ°ÐœÐœÐ°Ñ Ð¿ÑÐŸÑÐµÐŽÑÑÐ°, Ðº ÐºÐŸÑÐŸÑÐŸÐ¹ ÐŒÑ Ð²ÐµÑÐœÐµÐŒÑÑ Ð² Ð Ð°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Section" ref="initialisation"/>.</Text>
+<Subsection id="performing_a_search">
+<Title>
+<Text id="786">ÐÐŸÐžÑÐº</Text>
+</Title>
+<Content>
+<Figure id="searching_gutenberg_for_darcy">
+<Title>
+<Text id="787">ÐÐŸÐžÑÐº Ð¿ÐŸ Ð·Ð°Ð¿ÑÐŸÑÑ Darcy Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Gutenberg</Text>
+</Title>
+<File width="396" height="353" url="images/Dev_Fig_054.png"/>
+</Figure>
+<Text id="788">ÐÐŸÐ³ÐŽÐ° Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð²Ð²ÐŸÐŽÐžÑ Ð·Ð°Ð¿ÑÐŸÑ, ÐœÐ°Ð¶ÐžÐŒÐ°Ñ ÐºÐœÐŸÐ¿ÐºÑ Begin search ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ Ð¿ÐŸÐžÑÐºÐ°, Ð·Ð°Ð¿ÑÑÐºÐ°ÐµÑÑÑ ÐœÐŸÐ²ÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ Greenstone, ÐºÐŸÑÐŸÑÐŸÐµ Ð·Ð°ÐºÐ°ÐœÑÐžÐ²Ð°ÑÑÑ, Ð³ÐµÐœÐµÑÐžÑÑÐµÑ ÐœÐŸÐ²ÑÑ HTML-ÑÑÑÐ°ÐœÐžÑÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐŒÐ°ÐºÑÐŸÑÐ·ÑÐº. ÐÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="searching_gutenberg_for_darcy"/> Ð¿ÐŸÐºÐ°Ð·Ð°Ðœ ÑÐµÐ·ÑÐ»ÑÑÐ°Ñ Ð¿ÐŸÐžÑÐºÐ° Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Project Gutenberg ÐŽÐ»Ñ Ð¿ÐŸÐžÑÐºÐŸÐ²ÐŸÐ³ÐŸ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÑ Darcy. Ð Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ Ð¿ÐµÑÐ²ÐŸÐœÐ°ÑÐ°Ð»ÑÐœÐŸÐ¹ HTML -ÑÑÑÐ°ÐœÐžÑÑ ÑÐºÑÑÑÐ° ÐžÐœÑÑÑÑÐºÑÐžÑ Ð¿ÐŸÐžÑÐºÐ° a=q. ÐÐŸÐ³ÐŽÐ° ÐºÐœÐŸÐ¿ÐºÐ° Ð¿ÐŸÐžÑÐºÐ° ÐœÐ°Ð¶Ð°ÑÐ°, ÑÑÐ° ÐžÐœÑÑÑÑÐºÑÐžÑ Ð°ÐºÑÐžÐ²ÐžÐ·ÐžÑÑÐµÑÑÑ Ðž ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑ ÐœÐŸÐ²ÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ - queryaction. ÐÐ°Ð¿ÑÑÐº queryaction ÐœÐ°Ð¿ÑÐ°Ð²Ð»ÑÐµÑ Ð·Ð°Ð¿ÑÐŸÑ Ðº ÐŸÐ±ÑÐµÐºÑÑ Filter/Ð€ÐžÐ»ÑÑÑ (c=gberg), ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÐŒÑÐ¹ ÐŽÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐµÑÐµÐ· Ð¿ÑÐŸÑÐŸÐºÐŸÐ».</Text>
+<Text id="789">Ð€ÐžÐ»ÑÑÑÑ - Ð²Ð°Ð¶ÐœÐ°Ñ ÐŸÑÐœÐŸÐ²ÐœÐ°Ñ ÑÑÐœÐºÑÐžÑ ÑÐµÑÐ²ÐµÑÐŸÐ² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÐžÑÐ¿ÐŸÑÐŸÐ±Ð»ÐµÐœÐœÑÐµ ÐŽÐ»Ñ ÐŽÐµÐ¹ÑÑÐ²ÐžÐ¹ Ð¿ÐŸÐžÑÐºÐ° Ðž Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°, ÐŸÐœÐž ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÑÑ ÑÐ¿ÐŸÑÐŸÐ±Ñ Ð²ÑÐ±ÐŸÑÐ° Ð¿ÐŸÐŽÐŒÐœÐŸÐ¶ÐµÑÑÐ²Ð° ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž ÐžÐ· ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð ÑÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ, queryaction ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑ Ð·Ð°Ð¿ÑÐŸÑ ÑÐžÐ»ÑÑÑÐ°:</Text>
+<BulletList>
+<Bullet>
+<Text id="790">ÑÑÑÐ°ÐœÐ°Ð²ÐºÐ° ÑÐžÐ¿Ð° ÑÐžÐ»ÑÑÑÐ° Ð·Ð°Ð¿ÑÐŸÑÐ° QueryFilter (Ð Ð°Ð·ÐŽÐµÐ» <CrossRef target="Section" ref="collection_server"/> ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÑÐžÐ¿Ñ ÑÐžÐ»ÑÑÑÐŸÐ²);</Text>
+</Bullet>
+<Bullet>
+<Text id="791">ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐžÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐŸÐº Ð¿ÐŸÐžÑÐºÐ° Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð² ÑÐžÐ»ÑÑÑÐµ Ð·Ð°Ð¿ÑÐŸÑÐ°;</Text>
+</Bullet>
+<Bullet>
+<Text id="792">Ð²ÑÐ·ÐŸÐ² ÑÑÐœÐºÑÐžÐž filterQ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐœÑÐ»ÐµÐ²ÐŸÐ¹ Ð¿ÑÐŸÑÐŸÐºÐŸÐ».</Text>
+</Bullet>
+</BulletList>
+<Text id="793">ÐÐ°Ð¿ÑÐŸÑÑ Ðº Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ñ ÑÐžÐœÑ
+ÑÐŸÐœÐœÑ. Ð ÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑ ÑÑÑÐµÐºÑÐžÐ²ÐœÐŸ Ð±Ð»ÐŸÐºÐžÑÑÐµÑÑÑ, Ð¿ÐŸÐºÐ° Ð·Ð°Ð¿ÑÐŸÑ ÑÐžÐ»ÑÑÑÐ° ÐœÐµ Ð±ÑÐŽÐµÑ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐ°Ðœ ÑÐµÑÐ²ÐµÑÐŸÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð²ÑÐµ ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ ÐŽÐ°ÐœÐœÑÐµ Ð±ÑÐŽÑÑ ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÑ.</Text>
+<Text id="794">ÐÐŸÐ³ÐŽÐ° Ð·Ð°Ð¿ÑÐŸÑ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð° ÑÐžÐ¿Ð° QueryFilter ÑÐŽÐµÐ»Ð°Ðœ, ÐŸÐ±ÑÐµÐºÑ Filter (ÑÐŒ. ÑÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="greenstone_runtime_system"/>) ÐŽÐµÐºÐŸÐŽÐžÑÑÐµÑ Ð²Ð°ÑÐžÐ°ÐœÑÑ Ðž Ð·Ð°Ð¿ÑÐ°ÑÐžÐ²Ð°ÐµÑ ÐŸÐ±ÑÐµÐºÑ Search, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ MG ÐŽÐ»Ñ ÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ Ð¿ÐŸÐžÑÐºÐ°. Ð ÐŸÐ»Ñ ÐŸÐ±ÑÐµÐºÑÐ° Search ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸ ÐŸÐœ ÐŽÐŸÐ»Ð¶ÐµÐœ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÑÑ Ð°Ð±ÑÑÑÐ°ÐºÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÑ Ð¿ÐŸÐžÑÐº, ÐœÐµÐ·Ð°Ð²ÐžÑÐžÐŒÐŸ ÐŸÑ ÐŸÑÐœÐŸÐ²ÐœÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐŸÐ³ÐŸ ÑÑÐµÐŽÑÑÐ²Ð° Ð¿ÐŸÐžÑÐºÐ°. Ð€ÐŸÑÐŒÐ°Ñ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐ¹ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÑÑ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÑ, ÑÐ°ÐºÐ¶Ðµ Ð¿ÑÐµÐŽÐ¿ÐžÑÑÐ²Ð°ÐµÑ Ð°Ð±ÑÑÑÐ°ÐºÑÐžÑ, ÑÑÐµÐ±ÑÑ ÐŸÑ ÐŸÐ±ÑÐµÐºÑÐ° Search ÑÑÐ°ÐœÑÐ»ÐžÑÐŸÐ²Ð°ÑÑ ÐŽÐ°ÐœÐœÑÐµ, ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ ÑÑÐµÐŽÑÑÐ²ÐŸÐŒ Ð¿ÐŸÐžÑÐºÐ° Ð² ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÑ ÑÐŸÑÐŒÑ.</Text>
+<Text id="795">ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÑ Ð¿ÐŸÐžÑÐºÐ° Ð²ÐŸÐ·Ð²ÑÐ°ÑÐµÐœÑ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÑ, ÐŽÐ°Ð»ÑÐœÐµÐ¹ÑÐžÐŒ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµÐŒ ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ ÑÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐŸÐ² ÐŽÐ»Ñ ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐŸÐ±ÑÐµÐºÑ Format Ðž ÐÐ°ÐºÑÐŸÑÐ·ÑÐº. ÐÐ°Ðº Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐŸ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="searching_gutenberg_for_darcy"/>, ÐŸÐœ Ð²ÑÐ³Ð»ÑÐŽÐžÑ ÑÐ»ÐµÐŽÑÑÑÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ: ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐ¹ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº Greenstone, ÐœÐžÐ¶ÐœÐžÐ¹ ÐºÐŸÐ»ÐŸÐœÑÐžÑÑÐ», ÐœÐ°Ð²ÐžÐ³Ð°ÑÐžÐŸÐœÐœÐ°Ñ ÐŸÐ±Ð»Ð°ÑÑÑ Ðž ÑÐŸÐœ; Ð¿ÐŸÐ²ÑÐŸÑÐµÐœÐžÐµ ÐŸÑÐœÐŸÐ²ÐœÐŸÐ¹ ÑÐ°ÑÑÐž ÑÑÑÐ°ÐœÐžÑÑ Ð·Ð°Ð¿ÑÐŸÑÐ° ÑÐŸÐ»ÑÐºÐŸ ÐœÐžÐ¶Ðµ ÐœÐ°Ð²ÐžÐ³Ð°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐŸÐ±Ð»Ð°ÑÑÐž; ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ ÐºÐœÐžÐ¶ÐœÐŸÐ³ÐŸ Ð·ÐœÐ°ÑÐºÐ°, Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ° Ðž Ð°Ð²ÑÐŸÑÐ° ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÐœÐ°Ð¹ÐŽÐµÐœÐœÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸ. Ð€ÐŸÑÐŒÐ°Ñ Ð¿ÐŸÑÐ»ÐµÐŽÐœÐµÐ¹ ÑÐ°ÑÑÐž ÑÐ¿ÑÐ°Ð²Ð»ÑÐµÑÑÑ ÐžÐœÑÑÑÑÐºÑÐžÐµÐ¹ format SearchVList Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÐµÐ¶ÐŽÐµ ÑÐµÐŒ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº Ðž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð°Ð²ÑÐŸÑÐ° Ð±ÑÐŽÑÑ ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÑ, ÐŸÐœÐž ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐœÐ°Ð¹ÐŽÐµÐœÑ ÑÐµÑÐ²ÐµÑÐŸÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð¢ÑÑ ÑÑÐµÐ±ÑÐµÑÑÑ Ð·Ð°Ð¿ÑÐŸÑ Ðº Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ñ, ÐœÐ° ÑÐµÐ¹ ÑÐ°Ð· ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ BrowseFilter.</Text>
+</Content>
+</Subsection>
+<Subsection id="retrieving_a_document">
+<Title>
+<Text id="796">Retrieving a document</Text>
+</Title>
+<Content>
+<Text id="797">ÐÐŸÑÐ»Ðµ Ð²ÑÑÐµÑÐ¿ÐŸÐŒÑÐœÑÑÐŸÐ³ÐŸ Ð·Ð°Ð¿ÑÐŸÑÐ° ÐŽÐ»Ñ Darcy, ÑÐ°ÑÑÐŒÐŸÑÑÐžÐŒ ÐŸÑÐŸÐ±ÑÐ°Ð¶Ð°ÐµÐŒÑÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ. Ð ÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="the_golf_course_mystery"/> Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÑÐµÐ·ÑÐ»ÑÑÐ°Ñ ÑÐµÐ»ÑÐºÐ° Ð¿ÐŸ ÐžÐºÐŸÐœÐºÐµ ÐŸÐºÐŸÐ»ÐŸ The Golf Course Mystery ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="searching_gutenberg_for_darcy"/>.</Text>
+<Figure id="the_golf_course_mystery">
+<Title>
+<Text id="798"><i>The Golf Course Mystery</i></Text>
+</Title>
+<File width="393" height="349" url="images/Dev_Fig_056.png"/>
+</Figure>
+<Text id="799">ÐÑÑ
+ÐŸÐŽÐœÑÐ¹ ÑÐµÐºÑÑ ÐŽÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Gutenberg Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÐŸÐŽÐžÐœ ÐŽÐ»ÐžÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» ÐºÐœÐžÐ³Ðž. ÐÐŸ Ð²ÑÐµÐŒÑ ÐºÐŸÐŒÐ¿ÐŸÐœÐŸÐ²ÐºÐž, ÑÑÐŸÑ ÑÐ°Ð¹Ð» ÑÐ°Ð·Ð±ÐžÑ ÐœÐ° ÐŸÑÐŽÐµÐ»ÑÐœÑÐµ ÑÑÑÐ°ÐœÐžÑÑ, ÐºÐ°Ð¶ÐŽÐ°Ñ Ð¿ÐŸ 200 ÑÑÑÐŸÐº ÐžÐ»Ðž ÐŸÐºÐŸÐ»ÐŸ ÑÑÐŸÐ³ÐŸ, Ðž ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐ°Ñ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÑ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐ° Ð² ÐžÐœÐŽÐµÐºÑÐ°Ñ
+ Ðž ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ Ð±Ð°Ð·Ðµ ÐŽÐ°ÐœÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð Ð²ÐµÑÑ
+ÐœÐµÐ¹ ÑÐ°ÑÑÐž ÑÐžÑÑÐœÐºÐ° <CrossRef target="Figure" ref="the_golf_course_mystery"/> ÑÐºÐ°Ð·Ð°ÐœÐŸ, ÑÑÐŸ ÑÑÐ° ÐºÐœÐžÐ³Ð° ÑÐŸÐŽÐµÑÐ¶ÐžÑ 104 ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÐµÐŒÑÑ
+ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐŸÐŒ ÑÑÑÐ°ÐœÐžÑÑ, Ðž ÐœÐžÐ¶Ðµ - ÐœÐ°ÑÐ°Ð»ÐŸ ÑÑÑÐ°ÐœÐžÑÑ ÐŸÐŽÐžÐœ: ÐºÑÐŸ Ð²Ð²ÐµÐ» ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ, Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº, Ð°Ð²ÑÐŸÑ, ÐœÐ°ÑÐ°Ð»ÐŸ ÐŸÐ³Ð»Ð°Ð²Ð»ÐµÐœÐžÑ (ÑÑÐŸ ÑÐ°ÑÑÑ ÑÐ°Ð±Ð»ÐžÑÐœÐŸÐ¹ ÑÐŸÑÐŒÑ ÐžÑÑ
+ÐŸÐŽÐœÐŸÐ³ÐŸ ÑÐµÐºÑÑÐ° Gutenberg, ÐŸÐœÐ° ÐœÐµ Ð±ÑÐ»Ð° ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐ° Greenstone). Ð Ð²ÐµÑÑ
+ÐœÐµÐ¹ Ð»ÐµÐ²ÐŸÐ¹ ÑÐ°ÑÑÐž ÐœÐ°Ñ
+ÐŸÐŽÑÑÑÑ ÐºÐœÐŸÐ¿ÐºÐž, ÐºÐŸÑÐŸÑÑÐµ ÑÐ¿ÑÐ°Ð²Ð»ÑÑÑ Ð²ÐœÐµÑÐœÐžÐŒ Ð²ÐžÐŽÐŸÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°: ÑÐŸÐ»ÑÐºÐŸ ÐŸÐŽÐœÐ° ÑÑÑÐ°ÐœÐžÑÐ° ÐžÐ»Ðž ÑÐµÐ»ÑÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ; Ð¿ÐŸÐŽÑÐ²ÐµÑÐºÐ° ÑÐµÑÐŒÐžÐœÐ° Ð·Ð°Ð¿ÑÐŸÑÐ° Ð²ÐºÐ». ÐžÐ»Ðž Ð²ÑÐºÐ».; ÐŽÐµÐ¹ÑÑÐ²ÐžÑÐµÐ»ÑÐœÐŸ Ð»Ðž ÐºÐœÐžÐ³Ð° ÐŽÐŸÐ»Ð¶ÐœÐ° Ð±ÑÑÑ ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐ° Ð² ÐµÐµ ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÐŸÐŒ ÐŸÐºÐœÐµ; ÐŸÑÐŽÐµÐ»ÐµÐœÐžÐµ Ð¿ÐŸÐžÑÐºÐŸÐ²ÐŸÐ¹ ÑÐ°ÑÑÐž ÐŸÑ ÐŸÐºÐœÐ° Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°. Ð Ð²ÐµÑÑ
+ÐœÐµÐ¹ Ð¿ÑÐ°Ð²ÐŸÐ¹ ÑÐ°ÑÑÐž - ÐœÐ°Ð²ÐžÐ³Ð°ÑÐžÐŸÐœÐœÐ°Ñ Ð¿ÐŸÐŒÐŸÑÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð¿ÑÑÐŒÐŸÐ¹ ÐŽÐŸÑÑÑÐ¿ Ðº Ð»ÑÐ±ÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐµ Ð² ÐºÐœÐžÐ³Ðµ: Ð¿ÑÐŸÑÑÐŸ ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ ÐœÐŸÐŒÐµÑ ÑÑÑÐ°ÐœÐžÑÑ Ðž ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐºÐœÐŸÐ¿ÐºÑ "go to page" (Ð¿ÐµÑÐµÐ¹ÑÐž Ðº ÑÑÑÐ°ÐœÐžÑÐµ). ÐÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐŸ ÐŒÐŸÐ¶ÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŽÐ»Ñ Ð¿ÐµÑÐµÑ
+ÐŸÐŽÐ° Ð¿ÐŸ ÑÑÑÐ°ÐœÐžÑÐ°ÐŒ ÑÑÑÐµÐ»ÐºÐž next/previous pages (ÑÐ»ÐµÐŽÑÑÑÐ°Ñ/Ð¿ÑÐµÐŽÑÐŽÑÑÐ°Ñ ÑÑÑÐ°ÐœÐžÑÐ°).</Text>
+<Text id="800">ÐÐµÐ¹ÑÑÐ²ÐžÐµ Ð¿ÐŸÐžÑÐºÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² documentaction ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐŸÐ¹ a=d Ðž ÐžÐŒÐµÐµÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÑÑ
+ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ². ÐÐ°ÐžÐ±ÐŸÐ»ÐµÐµ Ð²Ð°Ð¶ÐœÑÐ¹ - ÐŽÐ¿ÐŸÐžÑÐº ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°: ÑÑÐŸ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐŸ ÑÐµÑÐµÐ· Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÑ d. ÐÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="the_golf_course_mystery"/> ÑÑÐŸ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐŸ ÐºÐ°Ðº d=HASH51e598821ed6cbbdf0942b. 1 ÐœÐ°Ð¹ÑÐž Ð¿ÐµÑÐ²ÑÑ ÑÑÑÐ°ÐœÐžÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ñ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐŒ HASH51e598821ed6cbbdf0942b, Ð·ÐœÐ°Ñ Ð±ÐŸÐ»ÐµÐµ ÐŽÑÑÐ¶ÐµÑÑÐ²ÐµÐœÑÐ¹ ÑÐµÑÐŒÐžÐœ The Golf Course Mystery. ÐÑÑÐ°Ð»ÑÐœÑÐµ Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ: Ð²ÐºÐ». ÐžÐ»Ðž Ð²ÑÐºÐ». Ð¿ÐŸÐŽÑÐ²ÐµÑÐºÑ ÑÐµÑÐŒÐžÐœÐ° Ð·Ð°Ð¿ÑÐŸÑÐ° (hi), ÐŸÑÐŸÐ±ÑÐ°Ð·ÐžÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÑÐŸÐŒ, ÐºÐ°ÐºÐ°Ñ ÑÑÑÐ°ÐœÐžÑÐ° ÐºÐœÐžÐ³Ðž ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐ° (gt). Ð­ÑÐž Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐ»Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐž ÐŽÐµÐ¹ÑÑÐ²ÐžÐ¹, Ð¿ÑÐµÐŽÐ»Ð°Ð³Ð°ÐµÐŒÑÑ
+ ÐºÐœÐŸÐ¿ÐºÐ°ÐŒÐž ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ (ÑÐŒ. ÑÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="the_golf_course_mystery"/>), ÐŸÐ¿ÐžÑÐ°ÐœÐœÐŸÐ¹ Ð²ÑÑÐµ. ÐÐœÐ°ÑÐµÐœÐžÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ, ÐµÑÐ»Ðž Ð»ÑÐ±Ð°Ñ ÐžÐ· ÑÑÐžÑ
+ Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÑ
+ ÐŸÐ¿ÑÑÐµÐœÐ°.</Text>
+<Text id="801">ÐÐµÐ¹ÑÑÐ²ÐžÐµ ÑÐ»ÐµÐŽÑÐµÑ Ð·Ð° Ð¿ÑÐŸÑÐµÐŽÑÑÐŸÐ¹ queryaction: ÐŸÑÐµÐœÐºÐ° CGI -Ð°ÑÐ³ÑÐŒÐµÐœÑÐ°, ÐŽÐŸÑÑÑÐ¿ Ðº ÑÐµÑÐ²ÐµÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Ð¿ÑÐŸÑÐŸÐºÐŸÐ» Ðž ÑÐµÐ·ÑÐ»ÑÑÐ°Ñ ÐŽÐ»Ñ Ð³ÐµÐœÐµÑÐ°ÑÐžÐž web-ÑÑÑÐ°ÐœÐžÑÑ. ÐÐ°ÑÐžÐ°ÐœÑÑ, ÐºÐ°ÑÐ°ÑÑÐžÐµÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, ÐŽÐµÐºÐŸÐŽÐžÑÐŸÐ²Ð°ÐœÑ CGI-Ð°ÑÐ³ÑÐŒÐµÐœÑÐŸÐŒ Ðž ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÑ Ð² ÐŸÐ±ÑÐµÐºÑÐµ ÐŽÐ»Ñ ÐŽÐ°Ð»ÑÐœÐµÐ¹ÑÐµÐ¹ ÑÐ°Ð±ÐŸÑÑ. Ð§ÑÐŸÐ±Ñ ÐŸÑÑÑÐºÐ°ÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ ÐœÐ° ÑÐµÑÐ²ÐµÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒ ÑÐŸÐ»ÑÐºÐŸ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, ÑÑÐŸÐ±Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ Ð·Ð°Ð¿ÑÐŸÑ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð° Ðº get_document (). ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÑÐµÐºÑÑ ÐœÐ°Ð¹ÐŽÐµÐœ, ÐŽÐŸÐ»Ð¶ÐœÐŸ Ð±ÑÑÑ Ð¿ÑÐŸÐžÐ·Ð²ÐµÐŽÐµÐœÐŸ Ð·ÐœÐ°ÑÐžÑÐµÐ»ÑÐœÐŸÐµ ÑÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ. ÐÐ»Ñ ÑÑÐŸÐ³ÐŸ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐŽÐŸÑÑÑÐ¿Ð° Ðº documentaction ÑÐŸÑ
+ÑÐ°ÐœÑÐµÑ Ð°ÑÐ³ÑÐŒÐµÐœÑ Ðž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÐŸÐ±ÑÐµÐºÑ Format Ðž ÐÐ°ÐºÑÐŸÑÐ·ÑÐº.</Text>
+</Content>
+</Subsection>
+<Subsection id="browsing_a_hierarchical_classifier">
+<Title>
+<Text id="802">ÐÑÐŸÑÐŒÐŸÑÑ ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ°</Text>
+</Title>
+<Content>
+<Text id="803">ÐÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="browsing_titles_in_the_gutenberg_collection"/> Ð¿ÐŸÐºÐ°Ð·Ð°Ðœ Ð¿ÑÐžÐŒÐµÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°, Ð³ÐŽÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð²ÑÐ±ÑÐ°Ð» Titles Ð-Z (ÐÐ°Ð³ÐŸÐ»ÐŸÐ²ÐºÐž A-Z) Ðž ÐŸÐ±ÑÐ°ÑÐžÐ»ÑÑ Ðº Ð³ÐžÐ¿ÐµÑÑÐ²ÑÐ·Ðž ÐŽÐ»Ñ ÑÐžÐŒÐ²ÐŸÐ»Ð° Ð. Ð­ÑÐŸ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ Ð±Ð»Ð°Ð³ÐŸÐŽÐ°ÑÑ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ documentaction, ÐºÐŸÑÐŸÑÐŸÐµ Ð·Ð°ÐŽÐ°ÐµÑÑÑ CGI -Ð°ÑÐ³ÑÐŒÐµÐœÑÐŸÐŒ a=d. ÐÐŽÐœÐ°ÐºÐŸ, ÐŽÐŸ Ð¿ÐŸÐŽÐºÐ»ÑÑÐµÐœÐžÑ Ð¿ÐµÑÐµÐŒÐµÐœÐœÐŸÐ¹ d ÑÑÐŸÐžÑ ÐŸÐ³ÐŸÐ²ÐŸÑÐžÑÑÑÑ, ÑÑÐŸ Ð² ÐŽÐ°ÐœÐœÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ ÐŸÐœÐ° ÐœÐµ Ð±ÑÐ»Ð° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐ°. ÐÐŒÐµÑÑÐŸ ÑÑÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ð»ÑÑ ÑÐ·ÐµÐ» Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐŽÐŸÑÑÑÐ¿ÐœÐŸÐ¹ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐžÐµÑÐ°ÑÑ
+ÐžÐž ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐž, ÑÑÐŸÐ±Ñ ÐŸÑÐŸÐ±ÑÐ°Ð·ÐžÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÑ cl. Ð ÐŽÐ°ÐœÐœÐŸÐŒ Ð¿ÑÐžÐŒÐµÑÐµ ÐŸÐœÐ° Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÑ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐž, ÑÐ³ÑÑÐ¿Ð¿ÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐŒ Ð. Ð­ÑÐŸÑ ÑÐ¿ÐžÑÐŸÐº Ð±ÑÐ» ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°Ðœ Ð²ÐŸ Ð²ÑÐµÐŒÑ ÐºÐŸÐŒÐ¿Ð°ÐœÐŸÐ²ÐºÐž Ðž ÑÐŸÑ
+ÑÐ°ÐœÐµÐœ Ð² ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ Ð±Ð°Ð·Ðµ ÐŽÐ°ÐœÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Figure id="browsing_titles_in_the_gutenberg_collection">
+<Title>
+<Text id="804">ÐÑÐŸÑÐŒÐŸÑÑ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐŸÐ² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Gutenberg</Text>
+</Title>
+<File width="394" height="351" url="images/Dev_Fig_058.png"/>
+</Figure>
+<Text id="805">ÐÐ°Ð¿ÐžÑÐž, ÐºÐŸÑÐŸÑÑÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÑÑ ÑÐ·Ð»Ñ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ° Ð² Ð±Ð°Ð·Ðµ ÐŽÐ°ÐœÐœÑÑ
+, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑ Ð¿ÑÐµÑÐžÐºÑ CL, ÑÐŸÐ¿ÑÐŸÐ²ÐŸÐ¶ÐŽÐ°ÐµÐŒÑÐ¹ ÑÐžÑÐ»Ð°ÐŒÐž, ÐŸÑÐŽÐµÐ»ÐµÐœÐœÑÐŒÐž Ð¿ÐµÑÐžÐŸÐŽÐ°ÐŒÐž (.), ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑÐžÐŒÐž ÐžÑ
+ ÐœÐ°Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÐµ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ Ð²Ð»ÐŸÐ¶ÐµÐœÐœÐŸÐ¹ ÑÑÑÑÐºÑÑÑÑ. ÐÐ³ÐœÐŸÑÐžÑÑÑ ÐºÐœÐŸÐ¿ÐºÑ Ð¿ÐŸÐžÑÐºÐ° (Ð»ÐµÐ²ÑÐ¹ ÐºÑÐ°Ð¹ Ð² ÐœÐ°Ð²ÐžÐ³Ð°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐŸÐ±Ð»Ð°ÑÑÐž), ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ Ð¿ÑÐŸÐœÑÐŒÐµÑÐŸÐ²Ð°ÐœÑ Ð¿ÐŸÑÐ»ÐµÐŽÐŸÐ²Ð°ÑÐµÐ»ÑÐœÐŸ Ð² Ð¿ÐŸÑÑÐŽÐºÐµ Ð²ÐŸÐ·ÑÐ°ÑÑÐ°ÐœÐžÑ, ÑÐ»ÐµÐ²Ð° ÐœÐ°Ð¿ÑÐ°Ð²ÐŸ, ÐœÐ°ÑÐžÐœÐ°Ñ Ñ 1. Ð¢Ð°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ, ÑÐ·ÐµÐ» ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ° Ð²ÐµÑÑ
+ÐœÐµÐ³ÐŸ ÑÑÐŸÐ²ÐœÑ ÐŽÐ»Ñ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐŸÐ² Ð² ÐœÐ°ÑÐµÐŒ Ð¿ÑÐžÐŒÐµÑÐµ - CL1, Ð° ÑÐ°Ð·ÑÑÐºÐžÐ²Ð°ÐµÐŒÐ°Ñ ÑÑÑÐ°ÐœÐžÑÐ° ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐ° ÑÑÑÐ°ÐœÐŸÐ²ÐºÐŸÐ¹ cl=CLl.ll. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐ²ÐžÐŽÐµÑÑ ÑÑÐŸ Ð² ÑÑÑÐŸÐºÐµ URL ÐœÐ°Ð²ÐµÑÑ
+Ñ ÑÐžÑÑÐœÐºÐ° <CrossRef target="Figure" ref="browsing_titles_in_the_gutenberg_collection"/>.</Text>
+<Text id="806">ÐÐ»Ñ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž Ð·Ð°Ð¿ÑÐŸÑÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° cl ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŸÐ±ÑÐµÐºÑ Filter, ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÑÑÑÐºÐžÐ²Ð°ÐµÑ ÑÐ·ÐµÐ» Ð¿ÐŸ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ñ. Ð²ÐŸÐ·Ð²ÑÐ°ÑÐµÐœÐœÑÑ
+ ÐŽÐ°ÐœÐœÑÑ
+, ÐŽÐ°Ð»ÑÐœÐµÐ¹ÑÐžÐµ Ð·Ð°Ð¿ÑÐŸÑÑ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð° ÑÐŽÐµÐ»Ð°ÐœÑ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÐŸÑÑÑÐºÐ°ÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. Ð ÐŽÐ°ÐœÐœÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ ÐœÐ°Ð¹ÐŽÐµÐœÑ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐž ÐºÐœÐžÐ³. ÐÐŽÐœÐ°ÐºÐŸ, ÐµÑÐ»Ðž ÑÐ·ÐµÐ» Ð±ÑÐ» Ð²ÐœÑÑÑÐµÐœÐœÐžÐ¹, ÐŽÐŸÑÐµÑÐœÐžÐµ Ð·Ð°Ð¿ÐžÑÐž ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ - ÑÐ°ÐŒÐŸÑÑÐŸÑÑÐµÐ»ÑÐœÑÐµ ÑÐ·Ð»Ñ, ÑÐŸ Ð±ÑÐ»Ðž Ð±Ñ ÐœÐ°Ð¹ÐŽÐµÐœÑ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐž ÐŽÐŸÑÐµÑÐœÐžÑ
+ Ð²ÐµÑÑÐžÐœ. Ð¡ ÑÐŸÑÐºÐž Ð·ÑÐµÐœÐžÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ, ÑÑÐŸ ÑÐŸÐ¶Ðµ ÑÐ°ÐŒÐŸÐµ Ðž ÐŸÐ±ÑÐ°Ð±ÐŸÑÐ°ÐœÐŸ ÑÐµÐŒ Ð¶Ðµ ÑÐ°ÐŒÑÐŒ ÐŒÐµÑ
+Ð°ÐœÐžÐ·ÐŒÐŸÐŒ.</Text>
+<Text id="807">ÐÐ°ÐºÐŸÐœÐµÑ, Ð²ÑÑ ÐœÐ°Ð¹ÐŽÐµÐœÐœÐ°Ñ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÑÐ²ÑÐ·Ð°ÐœÐ° Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ ÐŒÐ°ÐºÑÐŸÑÐ·ÑÐºÐ° Ðž ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐ° ÐœÐ° web-ÑÑÑÐ°ÐœÐžÑÐµ, Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐœÐŸÐ¹ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="browsing_titles_in_the_gutenberg_collection"/>.</Text>
+</Content>
+</Subsection>
+<Subsection id="generating_the_home_page">
+<Title>
+<Text id="808">Generating the home page</Text>
+</Title>
+<Content>
+<Figure id="greenstone_home_page">
+<Title>
+<Text id="809">ÐÐµÐœÐµÑÐ°ÑÐžÑ ÐŽÐŸÐŒÐ°ÑÐœÐµÐ¹ ÑÑÑÐ°ÐœÐžÑÑ</Text>
+</Title>
+<File width="397" height="393" url="images/Dev_Fig_060.png"/>
+</Figure>
+<Text id="810">Ð ÐºÐ°ÑÐµÑÑÐ²Ðµ Ð¿ÐŸÑÐ»ÐµÐŽÐœÐµÐ³ÐŸ Ð¿ÑÐžÐŒÐµÑÐ° ÐŒÑ ÑÐ°ÑÑÐŒÐŸÑÑÐžÐŒ ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐŽÐŸÐŒÐ°ÑÐœÐµÐ¹ ÑÑÑÐ°ÐœÐžÑÑ Greenstone . Ð ÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="greenstone_home_page"/> ÐŽÐµÐŒÐŸÐœÑÑÑÐžÑÑÐµÑ ÐŽÐŸÐŒÐ°ÑÐœÑÑ ÑÑÑÐ°ÐœÐžÑÑ Greenstone, ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐœÑÑ ÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑÐŒÐž Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ. ÐÐµ URL, ÐºÐŸÑÐŸÑÑÐ¹ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÐžÐŽÐµÑÑ ÐœÐ°Ð²ÐµÑÑ
+Ñ ÑÐºÑÐ°ÐœÐ°, Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð°ÑÐ³ÑÐŒÐµÐœÑÑ Ð°=Ñ np=home. Ð¢Ð°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ, Ð¿ÐŸÐŽÐŸÐ±ÐœÐŸ ÑÑÑÐ°ÐœÐžÑÐµ "about this collection" (ÐŸÐ± ÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž), ÐŸÐœÐ° Ð±ÑÐ»Ð° ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐ°ÑÐ°^ÐµÐ°ÑÐ¹'ÐŸÐž (Ð°=Ñ), ÐœÐŸ ÐœÐ° ÑÐµÐ¹ ÑÐ°Ð· Ð¿ÑÐžÐŒÐµÐœÑÐ»ÐŸÑÑ home (p=home). ÐÐŸÑÑÐŸÐŒÑ ÐŒÐ°ÐºÑÐŸÑÐ·ÑÐº ÐŸÐ±ÑÐ°ÑÐ°ÐµÑÑÑ Ðº ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ home.dm. Ð ÐŽÐ°ÐœÐœÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ ÐœÐµÑ ÐœÐžÐºÐ°ÐºÐŸÐ¹ ÐœÐ°Ð±ÐŸÐŽÐœÐŸÑÑÐž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ (Ñ Ð¿ÐµÑÐµÐŒÐµÐœÐœÐŸÐ¹ Ñ).</Text>
+<Text id="811">The purpose of the home page is to show what collections are available. Clicking on an icon takes the user to the âabout this collectionâ page for that collection. The menu of collections is dynamically generated every time the page is loaded, based on the collections that are in the file system at that time. When a new one comes online, it automatically appears on the home page when that page is reloaded (provided the collection is stipulated to be âpublicâ).</Text>
+<Text id="812">To do this the receptionist uses the protocol (of course). As part of appraising the CGI arguments, <i>pageaction</i> is programmed to detect the special case when <i>p=home</i>. Then, the action uses the protocol call <i>get_collection_list()</i> to establish the current set of online collections. For each of these it calls <i>get_collectinfo()</i> to obtain information about it. This information includes whether the collection is publicly available, what the URL is for the collection's icon (if any), and the collection's full name. This information is used to generate an appropriate entry for the collection on the home page.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="source_code">
+<Title>
+<Text id="813">Source code</Text>
+</Title>
+<Content>
+<Table id="standalone_programs_included_in_greenstone">
+<Title>
+<Text id="814">Standalone programs included in Greenstone</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="815"><i>setpasswd/</i></Text>
+</th>
+<th width="397">
+<Text id="816">Password support for Windows.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="817"><i>getpw/</i></Text>
+</th>
+<th width="397">
+<Text id="818">Password support for Unix.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="819"><i>txt2db/</i></Text>
+</th>
+<th width="397">
+<Text id="820">Convert an XML-like ASCII text format to Gnu's database format.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="821"><i>db2txt/</i></Text>
+</th>
+<th width="397">
+<Text id="822">Convert the Gnu database format to an XML-like ASCII text format.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="823"><i>phind/</i></Text>
+</th>
+<th width="397">
+<Text id="824">Hierarchical phrase browsing tool.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="825"><i>hashfile/</i></Text>
+</th>
+<th width="397">
+<Text id="826">Compute unique document ID based on content of file.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="827"><i>mgpp/</i></Text>
+</th>
+<th width="397">
+<Text id="828">Rewritten and updated version of Managing Gigabytes package in C++.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="829"><i>w32server/</i></Text>
+</th>
+<th width="397">
+<Text id="830">Local library server for Windows.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="831"><i>checkis/</i></Text>
+</th>
+<th width="397">
+<Text id="832">Specific support for installing Greenstone under Windows.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="833">The source code for the runtime system resides in <i>GSDLHOME/src</i>. It occupies two subdirectories, <i>recpt</i> for the receptionist's code and <i>colservr</i> for the collection server's. Greenstone runs on Windows systems right down to Windows 3.1, and unfortunately this imposes an eight-character limit on file and directory names. This explains why cryptic abbreviations like <i>recpt</i> and <i>colservr</i> are used. The remaining subdirectories include standalone utilities, mostly in support of the building process. They are listed in Table <CrossRef target="Table" ref="standalone_programs_included_in_greenstone"/>.</Text>
+<Text id="834">Another directory, <i>GSDLHOME/lib</i>, includes low-level objects that are used by both receptionist and collection server. This code is described in Section <CrossRef target="Section" ref="common_greenstone_types"/>.</Text>
+<Text id="835">Greenstone ÑÐžÑÐŸÐºÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ Standard Template Library (STL)/ Ð¡ÑÐ°ÐœÐŽÐ°ÑÑÐœÑÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÑ ÑÐ°Ð±Ð»ÐŸÐœÐŸÐ² Ð¡ ++,- ÑÐŸÐ·ÐŽÐ°ÐœÐœÑÑ Silicon Graphics (www.sgi.com), ÐºÐŸÑÐŸÑÐ°Ñ ÑÐ²Ð»ÑÐµÑÑÑ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐŸÐŒ ÐŒÐœÐŸÐ³ÐžÑ
+ Ð»ÐµÑ ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÐºÐž Ðž ÑÐ°Ð·Ð²ÐžÑÐžÑ. ÐÐŸÐŽÐŸÐ±ÐœÐŸ Ð²ÑÐµÐŒ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÐŒ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ, ÐŸÐœÐ° ÑÑÐµÐ±ÑÐµÑ ÐœÐµÐºÐŸÑÐŸÑÐŸÐ³ÐŸ Ð²ÑÐµÐŒÐµÐœÐž ÐœÐ° ÐžÐ·ÑÑÐµÐœÐžÐµ. ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ Ð ÐŽÐ°ÐµÑ ÐºÑÐ°ÑÐºÐžÐ¹ ÐŸÐ±Ð·ÐŸÑ ÐºÐ»ÑÑÐµÐ²ÑÑ
+ ÑÐ°ÑÑÐµÐ¹, ÐºÐŸÑÐŸÑÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ Ð²ÑÑÐŽÑ Ð² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐµ Greenstone. ÐÐ»Ñ Ð±ÐŸÐ»ÐµÐµ Ð¿ÐŸÐ»ÐœÐŸÐ³ÐŸ ÐŸÐ·ÐœÐ°ÐºÐŸÐŒÐ»ÐµÐœÐžÑ ÐŸÐ±ÑÐ°ÑÐ°Ð¹ÑÐµÑÑ Ðº ÐŸÑÐžÑÐžÐ°Ð»ÑÐœÐŸÐŒÑ STL ÑÐ¿ÑÐ°Ð²ÐŸÑÐœÐŸÐŒÑ ÑÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ñ, ÐŽÐŸÑÑÑÐ¿ÐœÐŸÐŒÑ ÐœÐ° ÑÐ°Ð¹ÑÐµ www.sgi.com, ÐžÐ»Ðž Ðº ÐŸÐŽÐœÐŸÐŒÑ ÐžÐ· ÐŒÐœÐŸÐ³ÐžÑ
+ ÑÑÐµÐ±ÐœÐžÐºÐŸÐ² STL, ÐœÐ°Ð¿ÑÐžÐŒÐµÑ Josuttis (1999).</Text>
+</Content>
+</Section>
+<Section id="common_greenstone_types">
+<Title>
+<Text id="836">ÐÐ±ÑÐžÐµ ÑÐžÐ¿Ñ Greenstone</Text>
+</Title>
+<Content>
+<Text id="837">ÐÐ±ÑÐµÐºÑÑ, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐµ Ð² GSDLHOME/lib, ÑÐ²Ð»ÑÑÑÑÑ ÐŸÐ±ÑÐµÐºÑÐ°ÐŒÐž Greenstone ÐœÐžÐ¶ÐœÐµÐ³ÐŸ ÑÑÐŸÐ²ÐœÑ, ÐŸÑÐœÐŸÐ²ÑÐ²Ð°ÑÑÑ ÐœÐ° Ð²ÐµÑÑÐžÐœÐµ STL, ÐºÐŸÑÐŸÑÑÐµ Ð²Ñ
+ÐŸÐŽÑÑ Ð² ÐžÑÑ
+ÐŸÐŽÐœÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ. Ð¡ÐœÐ°ÑÐ°Ð»Ð° ÐŒÑ ÐŽÐµÑÐ°Ð»ÑÐœÐŸ ÑÐ°ÑÑÐŒÐŸÑÑÐžÐŒ Ð±ÑÐµÐºÑ text_t, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÑÐµÐºÑÑÐ° Ð² ÑÐŸÑÐŒÐ°ÑÐµ Unicode. ÐÐŸÑÐ»Ðµ ÑÐµÐ³ÐŸ ÐŒÑ ÑÐŒÐŸÐ¶ÐµÐŒ ÐºÑÐ°ÑÐºÐŸ ÐžÐ·Ð»ÐŸÐ¶ÐžÑÑ ÑÐµÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð° Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž.</Text>
+<Subsection id="the_text_t_object">
+<Title>
+<Text id="838">ÐÐ±ÑÐµÐºÑ text_t</Text>
+</Title>
+<Content>
+<Text id="839">Greenstone ÑÐ°Ð±ÐŸÑÐ°ÐµÑ Ñ ÐŒÐœÐŸÐ³ÐžÐŒÐž ÑÐ·ÑÐºÐ°ÐŒÐž Ðž ÐŽÐ»Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ðž Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÑÐºÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°. ÐÐ»Ñ ÑÑÐŸÐ³ÐŸ ÐžÑÑ
+ÐŸÐŽÐœÐ°Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Ð¿ÐŸÐ²ÑÐµÐŒÐµÑÑÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ Unicode. ÐÑÐœÐŸÐ²ÐœÑÐŒ ÐŸÐ±ÑÐµÐºÑÐŸÐŒ, ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐœÐžÐŒÐ°ÐµÑ ÑÑÑÐŸÐºÑ Unicode ÑÐ²Ð»ÑÐµÑÑÑ <i>text_t</i>.</Text>
+<Figure id="the_text_t_api" class="withLineNumber">
+<Title>
+<Text id="840"><i>text_t</i> API (Ð² ÑÐŸÐºÑÐ°ÑÐµÐœÑ)</Text>
+</Title>
+<CodeLine>typedef vector&lt;unsigned short&gt; usvector;</CodeLine>
+<CodeLine/>
+<CodeLine>class text_t {</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>usvector text;</CodeLine>
+<CodeLine>unsigned short encoding; // 0 = unicode, 1 = other</CodeLine>
+<CodeLine/>
+<CodeLine>public:</CodeLine>
+<CodeLine>   // constructors</CodeLine>
+<CodeLine>   text_t ();</CodeLine>
+<CodeLine>   text_t (int i);</CodeLine>
+<CodeLine>   text_t (char *s); // assumed to be a normal c string</CodeLine>
+<CodeLine/>
+<CodeLine>   void setencoding (unsigned short theencoding);</CodeLine>
+<CodeLine>   unsigned short getencoding ();</CodeLine>
+<CodeLine/>
+<CodeLine>   // STL container support</CodeLine>
+<CodeLine>   iterator begin ();</CodeLine>
+<CodeLine>   iterator end ();</CodeLine>
+<CodeLine/>
+<CodeLine>   void erase(iterator pos);</CodeLine>
+<CodeLine>   void push_back(unsigned short c);</CodeLine>
+<CodeLine>   void pop_back();</CodeLine>
+<CodeLine/>
+<CodeLine>   void reserve (size_type n);</CodeLine>
+<CodeLine/>
+<CodeLine>   bool empty () const {return text.empty();}</CodeLine>
+<CodeLine>   size_type size() const {return text.size();}</CodeLine>
+<CodeLine/>
+<CodeLine>   // added functionality</CodeLine>
+<CodeLine>   void clear ();</CodeLine>
+<CodeLine>   void append (const text_t &amp;t);</CodeLine>
+<CodeLine/>
+<CodeLine>   // support for integers</CodeLine>
+<CodeLine>   void appendint (int i);</CodeLine>
+<CodeLine>   void setint (int i);</CodeLine>
+<CodeLine>   int getint () const;</CodeLine>
+<CodeLine/>
+<CodeLine>   // support for arrays of chars</CodeLine>
+<CodeLine>   void appendcarr (char *s, size_type len);</CodeLine>
+<CodeLine>   void setcarr (char *s, size_type len);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="841">Unicode ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÐŽÐ²Ð° Ð±Ð°Ð¹ÑÐ° ÐŽÐ»Ñ Ñ
+ÑÐ°ÐœÐµÐœÐžÑ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÐžÐŒÐ²ÐŸÐ»Ð°. ÐÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="the_text_t_api"/> Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÑ Ð³Ð»Ð°Ð²ÐœÑÐµ ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž text_t Application Program Interface/ ÐÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÑÐžÐºÐ»Ð°ÐŽÐœÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ (API). ÐÐœ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð²ÑÐ¿ÐŸÐ»ÐœÐžÑÑ ÐŽÐ²ÑÑ
+Ð±Ð°Ð¹ÑÐŸÐ²ÐŸÐµ ÑÑÐµÐ±ÐŸÐ²Ð°ÐœÐžÐµ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Ð¡ ++ Ð²ÑÑÑÐŸÐµÐœÐœÑÐ¹ ÑÐžÐ¿ short, ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœ ÐºÐ°Ðº ÐŽÐ²ÑÑ
+Ð±Ð°Ð¹ÑÐŸÐ²ÐŸÐµ ÑÐµÐ»ÐŸÐµ ÑÐžÑÐ»ÐŸ. ÐŠÐµÐœÑÑÐ°Ð»ÑÐœÑÐ¹ ÑÐžÐ¿ ÐŽÐ°ÐœÐœÑÑ
+ ÐŸÐ±ÑÐµÐºÑÐ° text_t - ÑÑÐŸ ÐŽÐžÐœÐ°ÐŒÐžÑÐµÑÐºÐžÐ¹ ÐŒÐ°ÑÑÐžÐ², ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐœÑÐ¹ short, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ STL ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ vector&lt;unsigned short&gt; Ðž Ð¿ÐŸÐ»ÑÑÐµÐœÐœÐŸÐµ ÑÐŸÐºÑÐ°ÑÐµÐœÐœÐŸÐµ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ usvector.</Text>
+<Text id="842">Ð€ÑÐœÐºÑÐžÐž ÐºÐŸÐœÑÑÑÑÐºÑÐŸÑÐ° (ÑÑÑÐŸÐºÐž 10-12) ÑÐ²ÐœÐŸ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑ ÑÑÐž ÑÐŸÑÐŒÑ ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÐž: ÐºÐŸÐœÑÑÑÑÐºÑÐžÑ Ð±ÐµÐ· Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ², ÐºÐŸÑÐŸÑÐ°Ñ Ð³ÐµÐœÐµÑÐžÑÑÐµÑ Ð¿ÑÑÑÑÑ ÑÑÑÐŸÐºÑ Unicode; ÐºÐŸÐœÑÑÑÑÐºÑÐžÑ Ñ ÑÐµÐ»ÐŸÑÐžÑÐ»ÐµÐœÐœÑÐŒ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐŒ, ÐºÐŸÑÐŸÑÐ°Ñ Ð³ÐµÐœÐµÑÐžÑÑÐµÑ Ð²ÐµÑÑÐžÑ ÑÐµÐºÑÑÐ° Unicode ÑÐžÑÐ»ÐŸÐ²ÐŸÐ³ÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐœÐŸÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ; ÐºÐŸÐœÑÑÑÑÐºÑÐžÑ Ñ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐŒ char*, ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑ Ð°ÑÐ³ÑÐŒÐµÐœÑ ÐºÐ°Ðº ÑÑÑÐŸÐºÑ Ð¡ ++ Ñ ÐœÑÐ»ÐµÐ²ÑÐŒ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐŒ Ð² ÐºÐŸÐœÑÐµ Ðž Ð³ÐµÐœÐµÑÐžÑÑÐµÑ Ð²ÐµÑÑÐžÑ Unicode.</Text>
+<Text id="843">ÐÐŸÑÐ»Ðµ ÑÑÐŸÐ³ÐŸ, Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² (ÑÑÑÐŸÐºÐž 17-28), Ð¿ÐµÑÐµÑ
+ÐŸÐŽÑÑ ÐœÐ° ÐŸÐ±ÑÐ»ÑÐ¶ÐžÐ²Ð°ÐœÐžÐµ STL Ð²ÐµÐºÑÐŸÑÐœÐŸÐ³ÐŸ ÐºÐŸÐœÑÐµÐ¹ÐœÐµÑÐ°: beginQ, endQ,push_back(), emptyQ Ðž Ñ.ÐŽ. ÐÐŽÐµÑÑ ÐžÐŒÐµÐµÑÑÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐ° ÐŸÑÐžÑÑÐºÐž Ðž ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ ÑÑÑÐŸÐºÐž, Ð° ÑÐ°ÐºÐ¶Ðµ Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐ»ÐŸÑÐžÑÐ»ÐµÐœÐœÐŸÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ Ð² ÑÑÑÐŸÐºÑ ÑÐµÐºÑÑÐ° Unicode, Ðž Ð²ÐŸÐ·Ð²ÑÐ°ÑÐµÐœÐžÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐ³ÐŸ ÑÐµÐ»ÐŸÑÐžÑÐ»ÐµÐœÐœÐŸÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÑÐµÐºÑÑÐ°, ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÑ ÐœÐŸÐŒÐµÑ.</Text>
+<Figure id="overloaded_operators_to_text_t" class="withLineNumber">
+<Title>
+<Text id="844">ÐÐµÑÐµÐ³ÑÑÐ¶ÐµÐœÐœÑÐµ ÐŸÐ¿ÐµÑÐ°ÑÐŸÑÑ <i>text_t</i></Text>
+</Title>
+<CodeLine>class text_t {</CodeLine>
+<CodeLine>   // ...</CodeLine>
+<CodeLine>   public:</CodeLine>
+<CodeLine>   text_t &amp;operator=(const text_t &amp;x);</CodeLine>
+<CodeLine>   text_t &amp;operator+= (const text_t &amp;t);</CodeLine>
+<CodeLine>   reference operator[](size_type n);</CodeLine>
+<CodeLine/>
+<CodeLine>   text_t &amp;operator=(int i);</CodeLine>
+<CodeLine>   text_t &amp;operator+= (int i);^ \\</CodeLine>
+<CodeLine>   text_t &amp;operator= (char *s);</CodeLine>
+<CodeLine>   text_t &amp;operator+= (char *s);</CodeLine>
+<CodeLine/>
+<CodeLine>   friend inline bool operator!=(const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>   friend inline bool operator==(const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>   friend inline bool operator&lt; (const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>   friend inline bool operator&gt; (const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>   friend inline bool operator&gt;=(const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>   friend inline bool operator&lt;=(const text_t&amp; x, const text_t&amp; y);</CodeLine>
+<CodeLine>   // ...</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="845">Ð¡ÑÑÐµÑÑÐ²ÑÐµÑ ÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐŸ Ð¿ÐµÑÐµÐ³ÑÑÐ¶ÐµÐœÐœÑÑ
+ ÐŸÐ¿ÐµÑÐ°ÑÐŸÑÐŸÐ² , ÐºÐŸÑÐŸÑÑÐµ ÐœÐµ Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÑ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="the_text_t_api"/>. ÐÑÐŸÐ±ÐŸ Ð·ÐœÐ°ÑÐžÐŒÑÐµ ÐŸÐ¿ÐµÑÐ°ÑÐŸÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÑ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="overloaded_operators_to_text_t"/>. Ð¡ÑÑÐŸÐºÐ° 4 Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÑ ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŸÐŽÐœÐŸÐ³ÐŸ ÐŸÐ±ÑÐµÐºÑÐ° text_t ÐŽÑÑÐ³ÐŸÐŒÑ, Ð° ÑÑÑÐŸÐºÐ° 5 Ð¿ÐµÑÐµÐ³ÑÑÐ¶Ð°ÐµÑ ÐŸÐ¿ÐµÑÐ°ÑÐŸÑ+ = , ÑÑÐŸÐ±Ñ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÑÑ Ð±ÐŸÐ»ÐµÐµ ÐµÑÑÐµÑÑÐ²ÐµÐœÐœÑÐ¹ ÑÐ¿ÐŸÑÐŸÐ± ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ ÐŸÐŽÐœÐŸÐ³ÐŸ ÐŸÐ±ÑÐµÐºÑÐ° text_t Ð² ÐºÐŸÐœÐµÑ ÐŽÑÑÐ³ÐŸÐ³ÐŸ. Ð¢Ð°ÐºÐ¶Ðµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ ÑÐµÑÐµÐ· ÑÑÑÐŸÐºÑ 6 ÐŸÐ±ÑÐ°ÑÐžÑÑÑÑ Ðº ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐŸÐŒÑ ÑÐžÐŒÐ²ÐŸÐ»Ñ Unicode (Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐœÐŸÐŒÑ ÐºÐ°Ðº short), ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Ð·ÐœÐ°Ðº ÐŒÐ°ÑÑÐžÐ²Ð° []. ÐÐ°Ð»ÐµÐµ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÐœÐ°Ð·ÐœÐ°ÑÐžÑÑ Ðž ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ Ð² ÐºÐŸÐœÐµÑ ÐŸÐ¿ÐµÑÐ°ÑÐŸÑÑ, Ð¿ÑÐµÐŽÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÐµ ÐŽÐ»Ñ ÑÑÑÐŸÐº C++ Ðž ÑÐµÐ»ÑÑ
+ ÑÐžÑÐµÐ». Ð¡ÑÑÐŸÐºÐž 12-18 Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÑÑ ÐÑÐ»ÐµÐ²Ñ ÐŸÐ¿ÐµÑÐ°ÑÐŸÑÑ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÑÑÐ°Ð²ÐœÐžÑÑ ÐŽÐ²Ð° ÐŸÐ±ÑÐµÐºÑÐ° text_t: ÑÐ°Ð²ÐœÐŸ, ÐœÐµ ÑÐ°Ð²ÐœÐŸ, Ð¿ÑÐµÐŽÑÐµÑÑÐ²ÑÐµÑ Ð² Ð°Ð»ÑÐ°Ð²ÐžÑÐœÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ Ðž ÑÐ°Ðº ÐŽÐ°Ð»ÐµÐµ.</Text>
+<Text id="846">Ð€ÑÐœÐºÑÐžÑ-ÑÐ»ÐµÐœ, ÐºÐŸÑÐŸÑÐ°Ñ Ð±ÐµÑÐµÑ Ð°ÑÐ³ÑÐŒÐµÐœÑ const Ð²ÐŒÐµÑÑÐŸ ÐœÐµ-const, ÑÐ°ÐºÐ¶Ðµ ÐžÐŒÐµÐµÑÑÑ (ÐœÐŸ ÐœÐ° ÑÐžÑÑÐœÐºÐµ ÐœÐµ Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐ°). Ð¢Ð°ÐºÐŸÐµ Ð¿ÐŸÐ²ÑÐŸÑÐµÐœÐžÐµ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÐŸ ÐŽÐ»Ñ ÐŸÐ±ÑÐµÐºÑÐŸÐ² C++, ÐŽÐµÐ»Ð°Ñ API Ð±ÐŸÐ»ÐµÐµ Ð²ÐµÑÐŸÐŒÑÐŒ, ÐœÐŸ ÐœÐµ Ð±ÐŸÐ»ÐµÐµ ÐºÐŸÐœÑÐµÐ¿ÑÑÐ°Ð»ÑÐœÑÐŒ. Ð ÐŽÐµÐ¹ÑÑÐ²ÐžÑÐµÐ»ÑÐœÐŸÑÑÐž, ÐŒÐœÐŸÐ³ÐžÐµ ÐžÐ· ÑÑÐžÑ
+ ÑÑÐœÐºÑÐžÐ¹ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÑ ÐºÐ°Ðº ÐŸÑÐŽÐµÐ»ÑÐœÑÐµ ÐŽÐµÐ¹ÑÑÐ²ÑÑÑÐžÐµ ÐžÐœÑÑÑÑÐºÑÐžÐž. ÐÐ»Ñ Ð±ÐŸÐ»ÐµÐµ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸÐ³ÐŸ ÐžÐ·ÑÑÐµÐœÐžÑ ÐŸÐ±ÑÐ°ÑÐžÑÐµÑÑ Ðº ÐžÑÑ
+ÐŸÐŽÐœÐŸÐŒÑ ÑÐ°Ð¹Ð»Ñ GSDLHOME/lib/text_t.h.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_greenstone_library_code">
+<Title>
+<Text id="847">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone</Text>
+</Title>
+<Content>
+<Text id="848">Ð€Ð°Ð¹Ð»Ñ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ° Ð² GSDLHOME/lib Ð²ÐºÐ»ÑÑÐ°ÑÑ ÑÐŒÐµÑÑ ÑÑÐœÐºÑÐžÐ¹ Ðž ÐŸÐ±ÑÐµÐºÑÐŸÐ², ÑÑÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ ÑÐ°Ð±ÐŸÑÑ ÑÐžÑÑÐµÐŒÑ Greenstone. ÐÐ»Ñ Ð±ÐŸÐ»ÑÑÐµÐ¹ ÑÑÑÐµÐºÑÐžÐ²ÐœÐŸÑÑÐž ÐŸÑÐœÐŸÑÐµÐœÐžÑ, ÑÑÐœÐºÑÐžÐž Ðž ÑÑÐœÐºÑÐžÐž-ÑÐ»ÐµÐœÑ ÐŸÐ±ÑÑÐ²Ð»ÐµÐœÑ ÐºÐ°Ðº inline. ÐÐ»Ñ Ð±ÐŸÐ»ÑÑÐµÐ¹ ÑÐ°ÑÑÐž Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸÑÑÐž Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑÑ Ð² ÐºÐŸÐ¿ÐžÐž ÑÐ°Ð¹Ð»Ð° Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ° .ÑÑÑ.</Text>
+<Table class="hidden">
+<Title/>
+<TableContent>
+<tr>
+<th width="100">
+<Text id="849"><b>cfgread.h</b></Text>
+</th>
+<th width="450">
+<Text id="850">Ð€ÑÐœÐºÑÐžÐž ÐŽÐ»Ñ ÑÑÐµÐœÐžÑ Ðž Ð·Ð°Ð¿ÐžÑÐž ÑÐ°Ð¹Ð»Ð° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, read_cfg_line () ÐºÐ°Ðº Ð°ÑÐ³ÑÐŒÐµÐœÑ ÐŽÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ Ð±ÐµÑÐµÑ Ð²Ñ
+ÐŸÐŽÐœÐŸÐ¹ Ð¿ÐŸÑÐŸÐº Ðž text_tarray (ÐŸÐ±ÑÐ°Ð±ÐŸÑÐ°ÐœÐœÑÐ¹ ÐŽÐ»Ñ vector&lt;text_t&gt;), ÑÑÐŸÐ±Ñ Ð·Ð°Ð¿ÐŸÐ»ÐœÐžÑÑ ÐŽÐ°ÐœÐœÑÐŒÐž ÐŽÐ»Ñ ÑÑÐµÐœÐžÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="851"><b>display.h</b></Text>
+</th>
+<th width="450">
+<Text id="852">Ð¡Ð»ÐŸÐ¶ÐœÑÐ¹ ÐŸÐ±ÑÐµÐºÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐ¹ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÐŸÐŒ ÐŽÐ»Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž, Ñ
+ÑÐ°ÐœÐµÐœÐžÑ Ðž ÑÐ°ÑÑÐžÑÐµÐœÐžÑ ÐŒÐ°ÐºÑÐŸÑÐ°, Ð¿Ð»ÑÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐž ÑÐžÐ¿ÐŸÐ². ÐÐŸÐŽÑÐŸÐ±ÐœÐŸÑÑÐž Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÐœÐ°Ð¹ÑÐž Ð² Ð Ð°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Section" ref="receptionist"/>.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="853"><b>fileutil.h</b></Text>
+</th>
+<th width="450">
+<Text id="854">Ð€ÑÐœÐºÑÐžÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐž ÐœÐµÐ·Ð°Ð²ÐžÑÐžÐŒÐŸÑÑÐž ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ²ÑÑ
+ ÑÑÐžÐ»ÐžÑ Ð² ÐŸÐ¿ÐµÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÐµ. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, fllename_cat () Ð±ÐµÑÐµÑ ÐŽÐŸ ÑÐµÑÑÐž text_t Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ² Ðž Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑ textjt, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐ²Ð»ÑÐµÑÑÑ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐŸÐŒ ÑÐ²ÑÐ·ÑÐ²Ð°ÐœÐžÑ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ², ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐ¹ ÐŽÐžÑÐµÐºÑÐžÐ²ÐœÑÐ¹ ÑÐ°Ð·ÐŽÐµÐ»ÐžÑÐµÐ»Ñ ÐŽÐ»Ñ ÑÐµÐºÑÑÐµÐ¹ ÐŸÐ¿ÐµÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="855"><b>gsdlconf.h</b></Text>
+</th>
+<th width="450">
+<Text id="856">Ð¡ÐžÑÑÐµÐŒÐœÐŸ-ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐžÐµ ÑÑÐœÐºÑÐžÐž, ÐºÐŸÑÐŸÑÑÐµ ÐŸÑÐ²ÐµÑÐ°ÑÑ ÐœÐ° Ð²ÐŸÐ¿ÑÐŸÑÑ ÑÐžÐ¿Ð°: ÐŸÐ¿ÐµÑÐ°ÑÐžÐŸÐœÐœÐ°Ñ ÑÐžÑÑÐµÐŒÐ°, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ ÐŽÐ»Ñ ÑÑÐ°ÐœÑÐ»ÑÑÐžÐž, ÐŽÐŸÐ»Ð¶ÐœÐ° ÐŸÐ±ÑÐ°ÑÐžÑÑÑÑ Ðº strings.h ÑÐ°Ðº Ð¶Ðµ, ÐºÐ°Ðº string.ht ÐÐµÐ¹ÑÑÐ²ÐžÑÐµÐ»ÑÐœÐŸ Ð»Ðž Ð²ÑÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŽÐ»Ñ Ð·Ð°ÐºÑÑÑÐžÑ ÑÐ°Ð¹Ð»Ð°, Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÐŸÐ³ÐŸ?</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="857"><b>gsdltimes.h</b></Text>
+</th>
+<th width="450">
+<Text id="858">Ð€ÑÐœÐºÑÐžÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐž ÐŽÐ°Ñ Ðž Ð²ÑÐµÐŒÐµÐœÐž. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, time2text () Ð±ÐµÑÐµÑ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐœÐŸÐµ Ð²ÑÐµÐŒÑ, Ð²ÑÑÐ°Ð¶ÐµÐœÐœÐŸÐµ Ð² ÐºÐŸÐ»ÐžÑÐµÑÑÐ²Ðµ ÑÐµÐºÑÐœÐŽ, ÐºÐŸÑÐŸÑÑÐµ Ð¿ÑÐŸÑÐ»Ðž Ñ 1 ÑÐœÐ²Ð°ÑÑ 1970, ÐºÐŸÐœÐ²ÐµÑÑÐžÑÑÐµÑ ÐžÑ
+ Ð² ÑÐŸÑÐŒÑ YYYY/MM/DD (ÐÐÐÐ/ÐÐ/ÐÐ), hh:mm:ss (ÑÑ:ÐŒÐŒ:ÑÑ) Ðž Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑ ÐºÐ°Ðº ÑÐžÐ¿ textjt.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="859"><b>gsdltools.h</b></Text>
+</th>
+<th width="450">
+<Text id="860">Ð Ð°Ð·Ð»ÐžÑÐœÐ°Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐ° ÑÐ°Ð±ÐŸÑÑ ÑÐžÑÑÐµÐŒÑ Greenstone: ÐŸÐ±ÑÑÑÐœÑÐµÑ, ÐµÑÐ»Ðž HttleEndian ÐžÐ»Ðž bigEndian; Ð¿ÑÐŸÐ²ÐµÑÑÐµÑ, ÐŽÐŸÑÑÑÐ¿ÐµÐœ Ð»Ðž Perl; Ð²ÑÐ¿ÐŸÐ»ÐœÑÐµÑ ÑÐžÑÑÐµÐŒÐœÑÑ ÐºÐŸÐŒÐ°ÐœÐŽÑ (Ñ ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÐŒÐž ÐœÐµÐœÑÐ¶ÐœÑÐŒÐž ÑÐ²ÐŸÐ¹ÑÑÐ²Ð°ÐŒÐž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ) Ðž ÐžÐ·Ð±Ð°Ð²Ð»ÑÐµÑ ÐŸÑ ÑÐ¿ÐµÑÐžÐ°Ð»ÑÐœÑÑ
+ ÐŒÐ°ÐºÑÐŸÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ² Ð² text_t ÑÑÑÐŸÐºÐµ. </Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="861"><b>gsdlunicode.h</b></Text>
+</th>
+<th width="450">
+<Text id="862">Ð ÑÐŽ ÑÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÑ
+ ÐŸÐ±ÑÐµÐºÑÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÑ Unicode text_t ÑÑÑÐŸÐºÐž ÑÐµÑÐµÐ· Ð¿ÐŸÑÐŸÐºÐž Ð®, ÑÐžÐ¿Ð° Unicode Ðº UTF-8 Ðž ÐœÐ°ÐŸÐ±ÐŸÑÐŸÑ; ÑÐŽÐ°Ð»ÐµÐœÐžÐµ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ² ÐœÑÐ»ÐµÐ²ÐŸÐ¹ ÑÐžÑÐžÐœÑ. ÐÐŸÐŽÐŽÐµÑÐ¶ÐºÐ° ÑÐ°Ñ-ÑÐ°Ð¹Ð»ÐŸÐ² ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐ° ÑÐµÑÐµÐ· ÐŸÐ±ÑÐµÐºÑ mapconvert Ñ ÑÐ°ÑÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑÐŒÐž, Ð·Ð°Ð³ÑÑÐ¶ÐµÐœÐœÑÐŒÐž ÐžÐ· GSDLHOME/mappings.</Text>
+</th>
+</tr>
+<tr>
+<th width="100">
+<Text id="863"><b>text_t.h</b></Text>
+</th>
+<th width="450">
+<Text id="864">ÐÑÐµÐ¶ÐŽÐµ Ð²ÑÐµÐ³ÐŸ ÑÑÐŸ ÐŸÐ±ÑÐµÐºÑ ÑÐµÐºÑÑÐ° Unicode, ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÐ¹ Ð²ÑÑÐµ. ÐÐŸ ÑÐ°ÐºÐ¶Ðµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ ÐŽÐ²Ð° ÐºÐ»Ð°ÑÑÐ° ÐŽÐ»Ñ Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÐœÐžÑ Ð¿ÐŸÑÐŸÐºÐŸÐ²: inconvertclass Ðž outconvertclass. Ð­ÑÐŸ - Ð±Ð°Ð·ÐŸÐ²ÑÐµ ÐºÐ»Ð°ÑÑÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐµ Ð² gsdlunicode.h.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="collection_server">
+<Title>
+<Text id="865">Collection server</Text>
+</Title>
+<Content>
+<Text id="866">Ð¢ÐµÐ¿ÐµÑÑ ÐŽÐµÑÐ°Ð»ÑÐœÐŸ ÐŸÐ±ÑÑÑÐœÐžÐŒ Ð²ÑÐµ ÐŸÐ±ÑÐµÐºÑÑ Ð² ÐºÐŸÐœÑÐµÐ¿ÑÑÐ°Ð»ÑÐœÐŸÐ¹ ÑÑÑÑÐºÑÑÑÐµ ÑÐžÑÑÐœÐºÐ° <CrossRef target="Figure" ref="greenstone_runtime_system"/>. ÐÑ ÐœÐ°ÑÐœÐµÐŒ Ñ ÐœÐžÐ·Ð° ÐŽÐžÐ°Ð³ÑÐ°ÐŒÐŒÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐ²Ð»ÑÐµÑÑÑ ÑÐ°ÐºÐ¶Ðµ ÐŸÑÐœÐŸÐ²ÐŸÐ¹ ÑÐžÑÑÐµÐŒÑ, Ðž Ñ Search (ÐÐŸÐžÑÐº), Source (ÐÑÑÐŸÑÐœÐžÐº), Ð ÐšÐµÐ³(Ð€ÐžÐ»ÑÑ) Ðž Ð¿ÑÐŸÐŽÐŸÐ»Ð¶ÐžÐŒ ÐœÐ°Ñ Ð¿ÑÑÑ ÑÐµÑÐµÐ· ÑÑÐŸÐ²ÐµÐœÑ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð° Ðº ÑÐµÐœÑÑÐ°Ð»ÑÐœÑÐŒ ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑÐ°ÐŒ Ð² ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÐµ: Actions (ÐÐµÐ¹ÑÑÐ²ÐžÑ), Format (Ð€ÐŸÑÐŒÐ°Ñ) Ðž Macro Language (ÐÐ°ÐºÑÐŸÑÐ·ÑÐº). ÐÐ°ÑÐµÐŒ ÐŒÑ ÑÐŸÑÑÐµÐŽÐŸÑÐŸÑÐžÐŒÑÑ ÐœÐ° ÐŸÐ±ÑÐµÐºÑÐœÐŸÐ¹ ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÐž, ÑÐ°Ðº ÐºÐ°Ðº ÑÑÐŸ Ð±ÑÐŽÐµÑ Ð¿ÑÐŸÑÐµ Ð¿ÐŸÐœÑÑÑ, ÐµÑÐ»Ðž ÑÐ¶Ðµ ÐžÐ·Ð²ÐµÑÑÐœÐ° ÑÐŸÐ»Ñ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÐŸÐ±ÑÐµÐºÑÐŸÐ².</Text>
+<Text id="867">ÐÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ ÐºÐ»Ð°ÑÑÐŸÐ², ÑÐµÐœÑÑÐ°Ð»ÑÐœÑÑ
+ Ð² ÐºÐŸÐœÑÐµÐ¿ÑÑÐ°Ð»ÑÐœÐŸÐ¹ ÑÑÑÑÐºÑÑÑÐµ, Ð²ÑÑÐ°Ð¶ÐµÐœÐŸ Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ Ð²ÐžÑÑÑÐ°Ð»ÑÐœÐŸÐ³ÐŸ ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐžÑ, ÑÑÐŸÐ±Ñ Ð¿ÐŸÐŒÐŸÑÑ ÑÐ°ÑÑÐžÑÑÐµÐŒÐŸÑÑÐž. ÐÑÐž Ð²ÐžÑÑÑÐ°Ð»ÑÐœÐŸÐŒ ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐžÐž ÑÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐµ ÐŸÐ±ÑÐµÐºÑÑ ÐŒÐŸÐ¶ÐœÐŸ Ð¿ÐµÑÐµÐŽÐ°ÑÑ Ð¿ÐŸ ÐºÑÑÐ³Ñ, ÐºÐ°Ðº ÐžÑ
+ Ð±Ð°Ð·ÐŸÐ²ÑÐ¹ ÐºÐ»Ð°ÑÑ, ÐœÐŸ ÐºÐŸÐ³ÐŽÐ° Ð²ÑÐ·Ð²Ð°ÐœÐ° ÑÑÐœÐºÑÐžÑ-ÑÐ»ÐµÐœ, ÐµÐµ Ð²ÐµÑÑÐžÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐ° Ð² Ð¿ÑÐžÐ·Ð²Ð°ÐœÐœÐŸÐŒ ÑÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÐŸÐŒ ÐŸÐ±ÑÐµÐºÑÐµ. ÐÐ°ÑÐ°ÐœÑÐžÑÑÑ, ÑÑÐŸ ÐžÑÑ
+ÐŸÐŽÐœÐ°Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Greenstone ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ Ð±Ð°Ð·ÐŸÐ²ÑÐ¹ ÐºÐ»Ð°ÑÑ Ð¿ÐŸÐ²ÑÑÐŽÑ, ÐºÑÐŸÐŒÐµ ÑÐŸÑÐºÐž ÐŸÐ±ÑÐµÐºÑÐ° ÐºÐŸÐœÑÑÑÑÐºÑÐžÐž, ÑÑÐŸ ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ, ÑÑÐŸ ÑÐ°Ð·Ð»ÐžÑÐœÐŸÐµ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ - ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ ÐœÐ° ÐŸÑÐœÐŸÐ²Ðµ ÑÐ°ÐŽÐžÐºÐ°Ð»ÑÐœÐŸ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÑÐµÑ
+ÐœÐŸÐ»ÐŸÐ³ÐžÐ¹ - ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð»ÐµÐ³ÐºÐŸ ÑÐ°Ð·ÐŒÐµÑÐµÐœÐŸ ÐœÐ° ÐŒÐµÑÑÐµ.</Text>
+<Text id="868">ÐÐ°Ð¿ÑÐžÐŒÐµÑ, Ð¿ÑÐµÐŽÐ¿ÐŸÐ»ÐŸÐ¶ÐžÐŒ, ÑÑÐŸ Ð±Ð°Ð·ÐŸÐ²ÑÐ¹ ÐºÐ»Ð°ÑÑ Ð¿ÐŸ ÐžÐŒÐµÐœÐž BaseCalc ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ ÐŸÑÐœÐŸÐ²ÐœÑÑ Ð°ÑÐžÑÐŒÐµÑÐžÐºÑ: ÑÐ»ÐŸÐ¶ÐµÐœÐžÐµ, Ð²ÑÑÐžÑÐ°ÐœÐžÐµ, ÑÐŒÐœÐŸÐ¶ÐµÐœÐžÐµ Ðž ÐŽÐµÐ»ÐµÐœÐžÐµ. ÐÑÐ»Ðž Ð²ÑÐµ ÐµÐ³ÐŸ ÑÑÐœÐºÑÐžÐž ÐŸÐ±ÑÑÐ²Ð»ÐµÐœÑ Ð²ÐžÑÑÑÐ°Ð»ÑÐœÑÐŒÐž, Ð° Ð°ÑÐ³ÑÐŒÐµÐœÑÑ Ðž Ð²ÐŸÐ·Ð²ÑÐ°ÑÐœÑÐµ ÑÐžÐ¿Ñ Ð²ÑÐµ ÐŸÐ±ÑÑÐ²Ð»ÐµÐœÑ ÐºÐ°Ðº ÑÑÑÐŸÐºÐž, ÐŒÑ ÐŒÐŸÐ¶ÐµÐŒ Ð»ÐµÐ³ÐºÐŸ ÐŸÑÑÑÐµÑÑÐ²ÐžÑÑ ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐžÐµ Ð²ÐµÑÑÐžÐž ÐŸÐ±ÑÐµÐºÑÐ°. ÐÐŽÐžÐœ ÐžÐ· ÐœÐžÑ
+, ÐœÐ°Ð·Ð²Ð°ÐœÐœÑÐ¹ FixedPrecisionCalc, ÐŒÐŸÐ³ Ð±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐµ ÑÑÐœÐºÑÐžÐž Ð¡, ÑÑÐŸÐ±Ñ ÑÐŸÐ²ÐµÑÑÐ°ÑÑ ÐºÐŸÐœÐ²ÐµÑÑÐ°ÑÐžÑ ÐŒÐµÐ¶ÐŽÑ ÑÑÑÐŸÐºÐ°ÐŒÐž Ðž ÑÐµÐ»ÑÐŒÐž ÑÐžÑÐ»Ð°ÐŒÐž Ðž ÐŸÐ±ÑÐ°ÑÐœÐŸ, ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÑ Ð²ÑÑÐžÑÐ»ÐµÐœÐžÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐµ Ð°ÑÐžÑÐŒÐµÑÐžÑÐµÑÐºÐžÐµ ÐŸÐ¿ÐµÑÐ°ÑÐŸÑÑ: +, -, *, Ðž /. ÐÑÑÐ³ÐŸÐ¹, ÐœÐ°Ð·Ð²Ð°ÐœÐœÑÐ¹ InfinitePrecisionCalc, ÐŒÐŸÐ³ Ð±Ñ ÐŸÐ±ÑÐ°ÑÐ°ÑÑÑÑ Ðº ÑÑÑÐŸÐºÐŸÐ²ÑÐŒ Ð°ÑÐ³ÑÐŒÐµÐœÑÐ°ÐŒ Ðž ÑÐžÐŒÐ²ÐŸÐ»Ð°ÐŒ ÐŸÐŽÐœÐŸÐ²ÑÐµÐŒÐµÐœÐœÐŸ, ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÑ Ð°ÑÐžÑÐŒÐµÑÐžÑÐµÑÐºÐžÐµ ÐŸÐ¿ÐµÑÐ°ÑÐžÐž Ñ Ð±ÐµÑÐºÐŸÐœÐµÑÐœÐŸÐ¹ ÑÐŸÑÐœÐŸÑÑÑÑ. ÐÐ°Ð¿ÐžÑÐ°ÐœÐœÐ°Ñ Ð³Ð»Ð°Ð²ÐœÐ°Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ BaseCalc Ð¿ÐŸÐ²ÑÑÐŽÑ, Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ ÐµÐµ ÑÐ°Ð±ÐŸÑÑ ÐŒÐŸÐ³ÑÑ ÑÐµÐ³ÑÐ»ÐžÑÐŸÐ²Ð°ÑÑÑÑ Ð¿ÐµÑÐµÐºÐ»ÑÑÐµÐœÐžÐµÐŒ ÐŒÐµÐ¶ÐŽÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐœÐŸÐ¹ ÑÐŸÑÐœÐŸÑÑÑÑ Ðž Ð±ÐµÑÐºÐŸÐœÐµÑÐœÐŸÐ¹ ÑÐŸÑÐœÐŸÑÑÑÑ, ÑÐµÐŽÐ°ÐºÑÐžÑÑÑ ÑÐŸÐ»ÑÐºÐŸ ÐŸÐŽÐœÑ ÑÑÑÐŸÐºÑ: Ð¿ÑÐœÐºÑ, Ð³ÐŽÐµ ÑÐŸÐ·ÐŽÐ°Ðœ ÐŸÐ±ÑÐµÐºÑ - ÐºÐ°Ð»ÑÐºÑÐ»ÑÑÐŸÑ.</Text>
+<Subsection id="the_search_object">
+<Title>
+<Text id="869">ÐÐ±ÑÐµÐºÑ Search</Text>
+</Title>
+<Content>
+<Figure id="search_base_class_api">
+<Title>
+<Text id="870">Search Ð±Ð°Ð·ÐŸÐ²ÑÐ¹ ÐºÐ»Ð°ÑÑ API</Text>
+</Title>
+<CodeLine>class searchclass {</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   searchclass ();</CodeLine>
+<CodeLine>   virtual ~searchclass ();</CodeLine>
+<CodeLine>   // the index directory must be set before any searching</CodeLine>
+<CodeLine>   // is done</CodeLine>
+<CodeLine>   virtual void setcollectdir (const text_t &amp;thecollectdir);</CodeLine>
+<CodeLine>   // the search results are returned in queryresults</CodeLine>
+<CodeLine>   // search returns 'true' if it was able to do a search</CodeLine>
+<CodeLine>   virtual bool search(const queryparamclass &amp;queryparams,</CodeLine>
+<CodeLine>                         queryresultsclass &amp;queryresults)=0;</CodeLine>
+<CodeLine>   // the document text for 'docnum' is placed in 'output'</CodeLine>
+<CodeLine>   // docTargetDocument returns 'true' if it was able to</CodeLine>
+<CodeLine>   // try to get a document</CodeLine>
+<CodeLine>   // collection is needed to see if an index from the</CodeLine>
+<CodeLine>   // collection is loaded. If no index has been loaded</CodeLine>
+<CodeLine>   // defaultindex is needed to load one</CodeLine>
+<CodeLine>   virtual bool docTargetDocument(const text_t &amp;defaultindex,</CodeLine>
+<CodeLine>                                               const text_t &amp;defaultsubcollection,</CodeLine>
+<CodeLine>                                               const text_t &amp;defaultlanguage,</CodeLine>
+<CodeLine>                                               const text_t &amp;collection,</CodeLine>
+<CodeLine>                                               int docnum,</CodeLine>
+<CodeLine>                                               text_t &amp;output)=0;</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>   querycache *cache;</CodeLine>
+<CodeLine>   text_t collectdir; // the collection directory</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="871">Ð ÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="search_base_class_api"/> ÐŽÐµÐŒÐŸÐœÑÑÑÐžÑÑÐµÑ Ð»ÐžÑÑÐžÐœÐ³ Ð±Ð°Ð·ÐŸÐ²ÐŸÐ³ÐŸ ÐºÐ»Ð°ÑÑÑ API ÐŽÐ»Ñ ÐŸÐ±ÑÐµÐºÑÐ° Search (ÑÐŒ. ÑÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="greenstone_runtime_system"/>). Ð­ÑÐŸ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÐŽÐ²Ðµ Ð²ÐžÑÑÑÐ°Ð»ÑÐœÑÐµ ÑÑÐœÐºÑÐžÐž-ÑÐ»ÐµÐœÑ: search() Ðž docTargetDocument(). ÐÐ· ÑÐžÑÑÐœÐºÐ° Ð²ÐžÐŽÐœÐŸ, ÑÑÐŸ =0, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐ»ÐµÐŽÑÐµÑ Ð·Ð° ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµÐŒ Ð°ÑÐ³ÑÐŒÐµÐœÑÐ°, ÑÑÐŸ ÑÑÐœÐºÑÐžÑ ÑÐžÐ³Ðµ, ÐŸÐ·ÐœÐ°ÑÐ°ÑÑÐ°Ñ, ÑÑÐŸ ÐºÐ»Ð°ÑÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÐœÐ°ÑÐ»ÐµÐŽÑÐµÑ ÐŸÐ±ÑÐµÐºÑ, ÐŽÐŸÐ»Ð¶ÐµÐœ ÐŸÑÑÑÐµÑÑÐ²ÐžÑÑ ÐŸÐ±Ðµ ÑÑÐœÐºÑÐžÐž (ÐžÐœÐ°ÑÐµ ÐºÐŸÐŒÐ¿ÐžÐ»ÑÑÐŸÑ Ð²ÑÐŽÐ°ÑÑ ÑÐŸÐŸÐ±ÑÐµÐœÐžÐµ).</Text>
+<Text id="872">ÐÐ»Ð°ÑÑ ÑÐ°ÐºÐ¶Ðµ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÐŽÐ²Ð° Ð·Ð°ÑÐžÑÐµÐœÐœÑÑ
+ Ð¿ÐŸÐ»Ñ ÐŽÐ°ÐœÐœÑÑ
+: collectdir Ðž cache. ÐÐ±ÑÐµÐºÑ Search ÐžÐ»Ð»ÑÑÑÑÐžÑÑÐµÑÑÑ Ð¿ÑÐžÐŒÐµÑÐ°ÐŒÐž ÐŽÐ»Ñ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð° Ð¿ÐŸÐ»Ðµ collectdir ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ Ñ
+ÑÐ°ÐœÐµÐœÐžÑ ÑÐžÑÑÐµÐŒÑ ÑÐ°Ð¹Ð»ÐŸÐ² (Ðž ÑÑÐŸ ÐµÑÐµ Ð±ÐŸÐ»ÐµÐµ Ð²Ð°Ð¶ÐœÐŸ - ÐžÑ
+ ÑÐ°Ð¹Ð»Ñ ÐžÐœÐŽÐµÐºÑÐ°) Ð² ÐŒÐµÑÑÐµ ÐœÐ°Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐŸÐ»Ðµ ÑÐ°ÑÐ¹ÐµÑÐŸÑ
+ÑÐ°ÐœÑÐµÑ ÑÐµÐ·ÑÐ»ÑÑÐ°Ñ Ð·Ð°Ð¿ÑÐŸÑÐ°. Ð­ÑÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ, ÑÑÐŸÐ±Ñ ÑÑÐºÐŸÑÐžÑÑ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÑ Ð¿ÐŸÑÐ»ÐµÐŽÑÑÑÐžÑ
+ Ð·Ð°Ð¿ÑÐŸÑÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐŽÑÑ ÐŽÑÐ±Ð»ÐžÑÐŸÐ²Ð°ÑÑ ÑÑÐŸÑ Ð·Ð°Ð¿ÑÐŸÑ (Ðž ÐµÐ³ÐŸ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ). Ð ÑÐŸ Ð²ÑÐµÐŒÑ, ÐºÐ°Ðº ÐžÐŽÐµÐœÑÐžÑÐœÑÐµ Ð²ÐŸÐ¿ÑÐŸÑÑ ÐŒÐŸÐ³ÑÑ ÐºÐ°Ð·Ð°ÑÑÑÑ ÐŒÐ°Ð»ÐŸÐ²ÐµÑÐŸÑÑÐœÑÐŒÐž, ÑÐ°ÐºÑÐžÑÐµÑÐºÐž ÐŸÐœÐž Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÑÑ ÑÐµÐ³ÑÐ»ÑÑÐœÐŸ. ÐÑÐŸÑÐŸÐºÐŸÐ» Greenstone ÑÐ²Ð»ÑÐµÑÑÑ Ð¿ÑÐŸÑÑÑÐŒ. Ð§ÑÐŸÐ±Ñ ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÑÑ ÑÑÑÐ°ÐœÐžÑÑ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐŸÐ², Ð¿ÐŸÐŽÐŸÐ±ÐœÑÑ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐœÐŸÐ¹ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="searching_gutenberg_for_darcy"/>, ÐœÐŸ ÐŽÐ»Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ñ 11 Ð¿ÐŸ 20 ÑÐŸÐ³ÐŸ Ð¶Ðµ ÑÐ°ÐŒÐŸÐ³ÐŸ Ð·Ð°Ð¿ÑÐŸÑÐ°, Ð¿ÐŸÐžÑÐº ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑÑ ÑÐœÐŸÐ²Ð°, ÐœÐ° ÑÐµÐ¹ ÑÐ°Ð· ÐŸÐ³ÐŸÐ²ÐŸÑÐžÐ² Ð·Ð°ÑÐ°ÐœÐµÐµ, Ð²ÐŸÐ·Ð²ÑÐ°Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² 11-20. ÐÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐŽÐµÐ»Ð°ÐµÑ ÑÑÐŸ ÑÑÑÐµÐºÑÐžÐ²ÐœÑÐŒ, ÑÐŸÑ ÑÐ°ÐºÑ, ÑÑÐŸ Ð¿ÐŸÐžÑÐº Ð±ÑÐ» ÑÐ¶Ðµ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœ, ÐŸÐ±ÐœÐ°ÑÑÐ¶ÐµÐœÐœÑÐµ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÑ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐžÐ·Ð²Ð»ÐµÑÐµÐœÑ Ð¿ÑÑÐŒÐŸ ÐžÐ· ÐºÑÑÐ°.</Text>
+<Text id="873">ÐÐ±Ð° Ð¿ÐŸÐ»Ñ ÐŽÐ°ÐœÐœÑÑ
+ Ð¿ÑÐžÐŒÐµÐœÐžÐŒÑ Ðº ÐºÐ°Ð¶ÐŽÐŸÐŒÑ ÑÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÐŸÐŒÑ ÐŸÐ±ÑÐµÐºÑÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÐµÑ ÐŒÐµÑ
+Ð°ÐœÐžÐ·ÐŒ Ð¿ÐŸÐžÑÐºÐ°. Ð­ÑÐŸ - ÑÐŸ, Ð¿ÐŸÑÐµÐŒÑ ÐŸÐœÐž Ð¿ÐŸÑÐ²Ð»ÑÑÑÑÑ Ð² Ð°Ð·ÐŸÐ²ÐŸÐŒ ÐºÐ»Ð°ÑÑÐµ, Ðž ÐŸÐ±ÑÑÐ²Ð»ÐµÐœÑ Ð·Ð°ÑÐžÑÐµÐœÐœÐŸÐ¹ ÑÐµÐºÑÐžÐµÐ¹ ÐºÐ»Ð°ÑÑÐ° ÑÐ°Ðº, ÑÑÐŸÐ±Ñ ÑÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐµ ÐºÐ»Ð°ÑÑÑ ÐŒÐŸÐ³Ð»Ðž Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÐœÐžÐŒ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ.</Text>
+</Content>
+</Subsection>
+<Subsection id="search_and_retrieval_with_mg">
+<Title>
+<Text id="874">Search and retrieval with MG</Text>
+</Title>
+<Content>
+<Text id="875">Greenstone ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ MG (ÑÐŸÐºÑÐ°ÑÐµÐœÐœÐŸ ÐŸÑ Managing Gigabytes, CM.Witten et al., 1999) ÐŽÐ»Ñ ÐžÐœÐŽÐµÐºÑÐ°ÑÐžÐž Ðž Ð²ÐŸÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÐžÑÑ
+ÐŸÐŽÐœÐ°Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Ð²ÐºÐ»ÑÑÐµÐœÐ° Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ GSDLHOME/packages. MG ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÐŒÐµÑÐŸÐŽÑ ÑÐ¶Ð°ÑÐžÑ, ÑÑÐŸÐ±Ñ ÐŒÐ°ÐºÑÐžÐŒÐ°Ð»ÑÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŒÐµÑÑÐŸ ÐœÐ° ÐŽÐžÑÐºÐµ, ÐœÐµ ÑÑÐ°Ð²Ñ Ð¿ÐŸÐŽ ÑÐ³ÑÐŸÐ·Ñ ÑÐºÐŸÑÐŸÑÑÑ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ. ÐÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐœÐ° Ð°ÐœÐ³Ð»ÐžÐ¹ÑÐºÐŸÐŒ ÑÐ·ÑÐºÐµ ÑÐ¶Ð°ÑÑÐ¹ ÑÐµÐºÑÑ Ðž Ð¿ÐŸÐ»ÐœÑÐ¹ ÑÐµÐºÑÑ ÐžÐœÐŽÐµÐºÑÐžÑÑÑÑÑÑ Ð²ÐŒÐµÑÑÐµ Ðž ÐŸÑÑÐœÐŸ Ð·Ð°ÐœÐžÐŒÐ°ÑÑ ÐŸÐŽÐœÑ ÑÑÐµÑÑ ÐŒÐµÑÑÐ°, Ð·Ð°ÐœÐžÐŒÐ°ÐµÐŒÐŸÐ³ÐŸ ÐœÐµÑÐ¶Ð°ÑÑÐŒ ÑÐµÐºÑÑÐŸÐŒ. ÐÐŸÐžÑÐº Ðž ÐžÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÑÐ°ÑÑÐŸ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÑÑ Ð±ÑÑÑÑÐµÐµ, ÑÐµÐŒ Ð¿ÐŸÐŽÐŸÐ±ÐœÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ ÐœÐ° ÐœÐµÑÐ¶Ð°ÑÐŸÐ¹ Ð²ÐµÑÑÐžÐž, Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑÑ ÐŒÐµÐœÑÑÐµ ÐŽÐžÑÐºÐŸÐ²ÑÑ
+ ÐŸÐ¿ÐµÑÐ°ÑÐžÐ¹.</Text>
+<Figure id="api_for_direct_access_to_mg">
+<Title>
+<Text id="876">API ÐŽÐ»Ñ Ð¿ÑÑÐŒÐŸÐ³ÐŸ ÐŽÐŸÑÑÑÐ¿Ð° Ðº MG (ÑÐŸÐºÑÐ°ÑÐµÐœÐœÑÐ¹ Ð²Ð°ÑÐžÐ°ÐœÑ)</Text>
+</Title>
+<CodeLine>enum result_kinds {</CodeLine>
+<CodeLine>   result_docs,           // Return the documents found in last search</CodeLine>
+<CodeLine>   result_docnums,     // Return document id numbers and weights</CodeLine>
+<CodeLine>   result_termfreqs, // Return terms and frequencies</CodeLine>
+<CodeLine>   result_terms           // Return matching query terms</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine>int mgq_ask(char *line);</CodeLine>
+<CodeLine>int mgq_results(enum result_kinds kind, int skip, int howmany,</CodeLine>
+<CodeLine>                               int (*sender)(char *, int, int, float, void *),</CodeLine>
+<CodeLine>                               void *ptr);</CodeLine>
+<CodeLine>int mgq_numdocs(void);</CodeLine>
+<CodeLine>int mgq_numterms(void);</CodeLine>
+<CodeLine>int mgq_equivterms(unsigned char *wordstem,</CodeLine>
+<CodeLine>                           int (*sender)(char *, int, int, float, void *),</CodeLine>
+<CodeLine>                           void *ptr);</CodeLine>
+<CodeLine>int mgq_docsretrieved (int *total_retrieved, int *is_approx);</CodeLine>
+<CodeLine>int mgq_getmaxstemlen ();</CodeLine>
+<CodeLine>void mgq_stemword (unsigned char *word);</CodeLine>
+</Figure>
+<Text id="877">MG ÐŸÐ±ÑÑÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð² ÐžÐœÑÐµÑÐ°ÐºÑÐžÐ²ÐœÐŸÐŒ ÑÐµÐ¶ÐžÐŒÐµ, Ð¿ÐµÑÐ°ÑÐ°Ñ ÐºÐŸÐŒÐ°ÐœÐŽÑ Ð² ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐµ. ÐÐŽÐžÐœ ÐžÐ· ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐ² Ð°ÐºÑÐžÐ²Ð°ÑÐžÐž mgsearchclass Ð·Ð°ÐºÐ»ÑÑÐ°ÐµÑÑÑ Ð² ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Ð¡ systemQ, Ð²ÑÐ·ÑÐ²Ð°ÐµÐŒÐŸÐ¹ Ñ ÐŸÐ±ÑÐµÐºÑÐŸÐŒ, Ð·Ð°Ð¿ÑÑÐºÐŸÐŒ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐ¹ ÐºÐŸÐŒÐ°ÐœÐŽÑ MG. ÐÐŸÐ»ÐµÐµ ÑÑÑÐµÐºÑÐžÐ²ÐœÑÐ¹ Ð¿ÐŸÐŽÑ
+ÐŸÐŽ, ÐŸÐŽÐœÐ°ÐºÐŸ, ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸÐ±Ñ ÐŸÑÐºÑÑÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ MG ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÑÑÐœÐºÑÐžÑ Ð²ÑÐ·ÐŸÐ²Ð°. ÐÐŽÐœÐ°ÐºÐŸ, ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ ÑÑÐµÐ±ÑÐµÑÑÑ Ð±ÐŸÐ»ÐµÐµ Ð³Ð»ÑÐ±ÐŸÐºÐŸÐµ Ð·ÐœÐ°ÐœÐžÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ MG. ÐÐŸÐ»ÑÑÐ°Ñ ÑÐ°ÑÑÑ ÑÑÑÐŽÐœÐŸÑÑÐµÐ¹ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÑÐºÑÑÑÐ° Ð·Ð° ÐœÐŸÐ²ÑÐŒ API , ÐºÐŸÑÐŸÑÑÐ¹ ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ ÑÐŸÑÐºÐŸÐ¹ ÑÐŸÐ¿ÑÐžÐºÐŸÑÐœÐŸÐ²ÐµÐœÐžÑ ÐŽÐ»Ñ ÐŸÐ±ÑÐµÐºÑÐ° mgsearchclass. Ð­ÑÐŸ - ÑÐŸÐ»Ñ colserver/mgq. Ñ, ÑÐµÐ¹ API Ð¿ÐŸÐºÐ°Ð·Ð°Ðœ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="api_for_direct_access_to_mg"/>.</Text>
+<Text id="878">Ð¡Ð¿ÐŸÑÐŸÐ± Ð¿ÐµÑÐµÐŽÐ°ÑÐž Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ² Ðº MG - ÑÐµÑÐµÐ· mgq_ask (), ÐºÐŸÑÐŸÑÑÐ¹ Ð±ÐµÑÐµÑ Ð²Ð°ÑÐžÐ°ÐœÑÑ ÑÐµÐºÑÑÐ° Ð² ÑÐŸÑÐŒÐ°ÑÐµ, ÐžÐŽÐµÐœÑÐžÑÐœÐŸÐŒ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐŸÐŒÑ Ð² ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐµ:</Text>
+<CodeLine>mgq_ask( ".set casefold off ");</CodeLine>
+<Text id="879">Ð­ÑÐŸ ÑÐ°ÐºÐ¶Ðµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð¿ÑÐž Ð²ÑÐ·ÐŸÐ²Ðµ Ð·Ð°Ð¿ÑÐŸÑÐ°. Ð ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐ°ÐŒ ÐŸÐ±ÑÐ°ÑÐ°ÑÑÑÑ ÑÐµÑÐµÐ· mgq_results, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÑÐºÐ°Ð·Ð°ÑÐµÐ»Ñ ÐœÐ° ÑÑÐœÐºÑÐžÑ, ÐºÐ°Ðº ÐµÐµ ÑÐµÑÐ²ÐµÑÑÑÐ¹ Ð¿Ð°ÑÐ°ÐŒÐµÑÑ. Ð­ÑÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð³ÐžÐ±ÐºÐžÐ¹ ÑÐ¿ÐŸÑÐŸÐ± Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÐœÐžÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž, Ð²ÐŸÐ·Ð²ÑÐ°ÑÐµÐœÐœÐŸÐ¹ Ð² ÑÑÑÑÐºÑÑÑÑ ÐŽÐ°ÐœÐœÑÑ
+ MG Ð¿ÐŸ ÑÑÐµÐ±ÐŸÐ²Ð°ÐœÐžÑ mgsearchclass. ÐÑÐ·ÐŸÐ² mgqjiumdocs Ð, mgqjiumterms () Ðž mgq_docsretrieved () ÑÐ°ÐºÐ¶Ðµ Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ, ÐœÐŸ ÐœÐ° ÑÐµÐ¹ ÑÐ°Ð· Ñ Ð±ÐŸÐ»ÐµÐµ Ð¶ÐµÑÑÐºÐžÐŒÐž ÑÑÐ»ÐŸÐ²ÐžÑÐŒÐž. ÐÐŸÑÐ»ÐµÐŽÐœÐžÐµ ÐŽÐ²Ð° ÐŸÐºÐ°Ð·ÑÐ²Ð°ÑÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ Ð¿ÑÐž Ð²ÐŸÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐžÐž.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_source_object">
+<Title>
+<Text id="880">ÐÐ±ÑÐµÐºÑ Source</Text>
+</Title>
+<Content>
+<Figure id="source_base_class_api">
+<Title>
+<Text id="881">Source Ð±Ð°Ð·ÐŸÐ²ÑÐ¹ ÐºÐ»Ð°ÑÑ API</Text>
+</Title>
+<CodeLine>class sourceclass {</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   sourceclass ();</CodeLine>
+<CodeLine>   virtual ~sourceclass ();</CodeLine>
+<CodeLine>   // configure should be called once for each configuration line</CodeLine>
+<CodeLine>   virtual void configure (const text_t &amp;key, const text_tarray &amp;cfgline);</CodeLine>
+<CodeLine>   // init should be called after all the configuration is done but</CodeLine>
+<CodeLine>   // before any other methods are called</CodeLine>
+<CodeLine>   virtual bool init (ostream &amp;logout);</CodeLine>
+<CodeLine>   // translate_OID translates OIDs using " .pr " , . " fc " etc.</CodeLine>
+<CodeLine>   virtual bool translate_OID (const text_t &amp;OIDin, text_t &amp;OIDout, comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   // get_metadata fills out the metadata if possible, if it is not</CodeLine>
+<CodeLine>   // responsible for the given OID then it return s false.</CodeLine>
+<CodeLine>   virtual bool get_metadata (const text_t &amp;requestParams, const text_t &amp;refParams,</CodeLine>
+<CodeLine>                           bool getParents, const text_tset &amp;fields, const text_t &amp;OID,</CodeLine>
+<CodeLine>                           MetadataInfo_tmap &amp;metadata, comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual bool get_document (const text_t &amp;OID, text_t &amp;doc, </CodeLine>
+<CodeLine>                           comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="882">Ð ÐŸÐ»Ñ Source (ÑÐŒ. ÑÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="greenstone_runtime_system"/>) - ÐŽÐŸÑÑÑÐ¿ Ðº ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒ Ðž ÑÐµÐºÑÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. ÐÐ³ÐŸ Ð±Ð°Ð·ÐŸÐ²ÑÐ¹ ÐºÐ»Ð°ÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="source_base_class_api"/>. Ð€ÑÐœÐºÑÐžÑ-ÑÐ»ÐµÐœ ÐœÐ°ÐœÐŸÑÐžÑ ÐœÐ° ÐºÐ°ÑÑÑ Ðº ÐºÐ°Ð¶ÐŽÐŸÐ¹ Ð·Ð°ÐŽÐ°ÑÐµ: getjnetadata () Ðž get_document () ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸ. ÐÐ±Ð° ÐŸÐ±ÑÑÐ²Ð»ÐµÐœÑ virtual, ÑÐ°Ðº ÑÑÐŸ Ð²ÐµÑÑÐžÑ, ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÑÑÑÑÑÑ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµÐŒ Ð±Ð°Ð·ÐŸÐ²ÐŸÐ³ÐŸ ÐºÐ»Ð°ÑÑÐ°, Ð²ÑÐ·ÑÐ²Ð°ÑÑ Ð²ÐŸ Ð²ÑÐµÐŒÑ ÑÐ°Ð±ÐŸÑÑ. ÐÐŽÐœÐ° ÑÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÐ°Ñ Ð²ÐµÑÑÐžÑ ÑÑÐŸÐ³ÐŸ ÐŸÐ±ÑÐµÐºÑÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ GDBM, ÑÑÐŸÐ±Ñ Ð·Ð°Ð¿ÑÑÑÐžÑÑ get_metadata 0 Ðž MG, ÑÑÐŸÐ±Ñ Ð·Ð°Ð¿ÑÑÑÐžÑÑ get_document (): ÐŒÑ ÐŽÐµÑÐ°Ð»ÐžÐ·ÐžÑÑÐµÐŒ ÑÑÑ Ð²ÐµÑÑÐžÑ ÐœÐžÐ¶Ðµ.</Text>
+<Text id="883">ÐÑÑÐ³Ð°Ñ ÑÑÐœÐºÑÐžÑ-ÑÐ»ÐµÐœ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐ° ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="source_base_class_api"/> - configure^, init () Ðž translate_OID Q. ÐÐµÑÐ²ÑÐµ ÐŽÐ²Ð° ÐºÐ°ÑÐ°ÑÑÑÑ Ð¿ÑÐŸÑÐµÑÑÐ° ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÐž, ÐŸÐ¿ÐžÑÐ°ÐœÐœÐŸÐ³ÐŸ Ð² Ð Ð°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Section" ref="initialisation"/>.</Text>
+<Text id="884">ÐÑÑÐ°Ð²ÑÐ°ÑÑÑ, translate_OID (), ÑÐ°Ð±ÐŸÑÐ°ÐµÑ Ñ ÑÐžÐœÑÐ°ÐºÑÐžÑÐŸÐŒ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ Ð²ÑÑÐ°Ð·ÐžÑÑ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. ÐÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="the_golf_course_mystery"/> ÐŒÑ Ð²ÐžÐŽÐµÐ»Ðž, ÐºÐ°Ðº ÐœÐŸÐŒÐµÑ ÑÑÑÐ°ÐœÐžÑÑ ÐŒÐŸÐ³ Ð±ÑÑÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœ Ð² ÐºÐŸÐœÐµÑ Ðº ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, ÑÑÐŸÐ±Ñ Ð²ÑÐ·Ð²Ð°ÑÑ ÑÐŸÐ»ÑÐºÐŸ ÑÑÑ ÑÑÑÐ°ÐœÐžÑÑ. Ð­ÑÐŸ Ð±ÑÐ»ÐŸ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ, Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ ÑÑÑÐ°ÐœÐžÑÑ Ð±ÑÐ»Ðž ÐžÐŽÐµÐœÑÐžÑÐžÑÐžÑÐŸÐ²Ð°ÐœÑ ÐºÐ°Ðº "ÑÐ°Ð·ÐŽÐµÐ»Ñ" Ð¿ÑÐž ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÐµ Ð² ÐºÐŸÐœÐµÑ " . 1" Ðº OID Ð²ÑÐ·ÑÐ²Ð°ÐµÑ Ð¿ÐµÑÐ²ÑÐ¹ ÑÐ°Ð·ÐŽÐµÐ» ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. Ð Ð°Ð·ÐŽÐµÐ»Ñ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð²Ð»ÐŸÐ¶ÐµÐœÐœÑÐŒÐž Ðž ÐŽÐŸÑÑÑÐ¿ÐœÑ ÐŽÐ»Ñ ÐŸÐ±ÑÐ°ÑÐµÐœÐžÑ Ð±Ð»Ð°Ð³ÐŸÐŽÐ°ÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÐŸÐŒÑ ÐœÐŸÐŒÐµÑÑ, ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐœÐŸÐŒÑ Ð¿ÐµÑÐžÐŸÐŽÐ°ÐŒÐž.</Text>
+<Text id="885">Ð¢Ð°Ðº Ð¶Ðµ, ÐºÐ°Ðº ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐžÐµ ÐœÐŸÐŒÐµÑÐ° ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐ², ÑÐžÐœÑÐ°ÐºÑÐžÑ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÑ ÑÐŸÑÐŒÑ ÐŸÑÐœÐŸÑÐžÑÐµÐ»ÑÐœÐŸÐ³ÐŸ ÐŽÐŸÑÑÑÐ¿Ð°. ÐÐ»Ñ ÑÐµÐºÑÑÐµÐ³ÐŸ ÑÐ°Ð·ÐŽÐµÐ»Ð° ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐŽÐŸÑÑÑÐ¿ Ðº first child, ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑ Ð² ÐºÐŸÐœÐµÑ /Ñ, Ðº last child, ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑ Ð² ÐºÐŸÐœÐµÑ .1Ñ, Ðº parent, ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑ Ð² ÐºÐŸÐœÐµÑ .ÑÐ³, Ðº next sibling, ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑ Ð² ÐºÐŸÐœÐµÑ .ns Ðž ^previous sibling, ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑ Ð² ÐºÐŸÐœÐµÑ .ps.</Text>
+<Text id="886"> Ð€ÑÐœÐºÑÐžÑ translate_OID () ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ OIDin Ðž OIDout, ÑÑÐŸÐ±Ñ Ñ
+ÑÐ°ÐœÐžÑÑ ÐžÑÑ
+ÐŸÐŽÐœÑÐ¹ Ð²Ð°ÑÐžÐ°ÐœÑ Ðž ÑÐµÐ·ÑÐ»ÑÑÐ°Ñ Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÐœÐžÑ. Ð¢ÑÐµÐ±ÑÐµÑÑÑ ÐŽÐ²Ð° ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÑÑ
+ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐ° - err Ðž logout. ÐÐœÐž ÑÐŸÐŸÐ±ÑÐ°ÑÑ Ð»ÑÐ±ÐŸÐ¹ ÑÑÐ°ÑÑÑ ÐŸÑÐžÐ±ÐºÐž, ÐºÐŸÑÐŸÑÑÐ¹ ÐŒÐŸÐ¶ÐµÑ Ð²ÐŸÐ·ÐœÐžÐºÐœÑÑÑ Ð²ÐŸ Ð²ÑÐµÐŒÑ Ð¿ÐµÑÐµÐ²ÐŸÐŽÐ°, Ðž ÑÐµÑÐ°ÑÑ, ÐºÐŸÐ³ÐŽÐ° Ðž ÐºÑÐŽÐ° Ð¿ÐŸÑÐ»Ð°ÑÑ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐžÐŸÐœÐœÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ. ÐÐ°ÑÐ°ÐŒÐµÑÑÑ ÑÐ²Ð»ÑÑÑÑÑ Ð±Ð»ÐžÐ·ÐºÐžÐŒÐž ÑÐŸÑÐ·ÐœÐžÐºÐ°ÐŒÐž Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð°, ÐŒÑ Ðº ÑÑÐŸÐŒÑ Ð²ÐµÑÐœÐµÐŒÑÑ Ð² Ð Ð°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Section" ref="protocol"/>.</Text>
+<Part id="database_retrieval_with_gdbm">
+<Title>
+<Text id="887">ÐÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ Ð±Ð°Ð· ÐŽÐ°ÐœÐœÑÑ
+ Ñ gdbm</Text>
+</Title>
+<Content>
+<Text id="888">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° GDBM - ÐŒÐµÐœÐµÐŽÐ¶ÐµÑ Ð±Ð°Ð·Ñ ÐŽÐ°ÐœÐœÑÑ
+ GNU (www.gnu.org). ÐÐœÐ° ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÐµÑ Ð¿ÑÐŸÑÑÑÑ ÑÑÑÑÐºÑÑÑÑ Ð·Ð°Ð¿ÐžÑÐµÐ¹ Ð¿Ð°Ñ ÐºÐ»ÑÑ/ÐŽÐ°ÐœÐœÑÐµ Ðž ÑÐŸÐ²ÐŒÐµÑÑÐžÐŒÐ° Ñ DBM Ðž NDBM. ÐÐ¿ÐµÑÐ°ÑÐžÐž Ð²ÐºÐ»ÑÑÐ°ÑÑ Ñ
+ÑÐ°ÐœÐµÐœÐžÐµ, ÐžÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ Ðž ÑÐŽÐ°Ð»ÐµÐœÐžÐµ Ð·Ð°Ð¿ÐžÑÐµÐ¹ Ð¿ÐŸ ÐºÐ»ÑÑÑ, Ð° ÑÐ°ÐºÐ¶Ðµ Ð¿ÑÐµÑÐµÑÐµÐœÐžÐµ Ð²ÑÐµÑ
+ ÐœÐµÐ·Ð°ÐºÐ°Ð·Ð°ÐœÐœÑÑ
+ ÐºÐ»ÑÑÐµÐ¹. </Text>
+<Figure id="gdbm_database_for_the_gutenberg_collection">
+<Title>
+<Text id="889">GDBM Ð±Ð°Ð·Ð° ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Gutenberg (ÑÑÐ°Ð³ÐŒÐµÐœÑ)</Text>
+</Title>
+<CodeLine>[HASH01d7b30d4827b51282919e9b]</CodeLine>
+<CodeLine>&lt;doctype&gt;         doc</CodeLine>
+<CodeLine>&lt;hastxt&gt;           0</CodeLine>
+<CodeLine>&lt;Title&gt;             The Winter's Tale</CodeLine>
+<CodeLine>&lt;Creator&gt;         William Shakespeare</CodeLine>
+<CodeLine>&lt;archivedir&gt;   HASH01d7/b30d4827.dir</CodeLine>
+<CodeLine>&lt;thistype&gt;       Invisible</CodeLine>
+<CodeLine>&lt;childtype&gt;     Paged</CodeLine>
+<CodeLine>&lt;contains&gt;        " .1; " .2; " .3; " .4; " .5; " .6; " .7; " .8; " .9; " .10; " .11; " .12;            \ <br/>                           " .13; " .14; " .15; " .16; " .17; " .18; " .19; " .20; " .21; " .22;            \ <br/>                           " .23; " .24; " .25; " .26; " .27; " .28; " .29; " .30; " .31; " .32;            \ <br/>                           " .33; " .34; " .35</CodeLine>
+<CodeLine>&lt;docnum&gt;           168483</CodeLine>
+<CodeLine>âââââââââââââââââââââââ-</CodeLine>
+<CodeLine>[CL1]</CodeLine>
+<CodeLine>&lt;doctype&gt;         classify</CodeLine>
+<CodeLine>&lt;hastxt&gt;           0</CodeLine>
+<CodeLine>&lt;childtype&gt;     HList</CodeLine>
+<CodeLine>&lt;Title&gt;             Title</CodeLine>
+<CodeLine>&lt;numleafdocs&gt; 1818</CodeLine>
+<CodeLine>&lt;thistype&gt;       Invisible</CodeLine>
+<CodeLine>&lt;contains&gt;       " .1; " .2; " .3; " .4; " .5; " .6; " .7; " .8; " .9; " .10; " .11; " .12;          \ <br/>                           " .13; " .14; " .15; " .16; " .17; " .18; " .19; " .20; " .21; " .22;          \ <br/>                            " .23; " .24</CodeLine>
+<CodeLine>âââââââââââââââââââââââ-</CodeLine>
+<CodeLine>[CL1.1]</CodeLine>
+<CodeLine>&lt;doctype&gt;         classify</CodeLine>
+<CodeLine>&lt;hastxt&gt;           0</CodeLine>
+<CodeLine>&lt;childtype&gt;     VList</CodeLine>
+<CodeLine>&lt;Title&gt;             A</CodeLine>
+<CodeLine>&lt;numleafdocs&gt; 118</CodeLine>
+<CodeLine>&lt;contains&gt;      HASH0130bc5f9f90089b3723431f;HASH9cba43bacdab5263c98545;\</CodeLine>
+<CodeLine>                          HASH12c88a01da6e8379df86a7;HASH9c86579a83e1a2e4cf9736;   \</CodeLine>
+<CodeLine>                           HASHdc2951a7ada1f36a6c3aca;HASHea4dda6bbc7cdeb4abfdee;   \</CodeLine>
+<CodeLine>                          HASHce55006513c47235ac38ba;HASH012a33acaa077c0e612b9351;\</CodeLine>
+<CodeLine>                          HASH010dd1e923a123826ae30e4b;HASHaf674616785679fed4b7ee;\</CodeLine>
+<CodeLine>                         HASH0147eef4b9d1cb135e096619;HASHe69b9dbaa83ffb045d963b;\</CodeLine>
+<CodeLine>                         HASH01abc61c646c8e7a8ce88b10;HASH5f9cd13678e21820e32f3a;\</CodeLine>
+<CodeLine>                         HASHe8cbba1594c72c98f9aa1b;HASH01292a2b7b6b60dec96298bc;\</CodeLine>
+<CodeLine>                         ...</CodeLine>
+</Figure>
+<Text id="890">Ð ÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="gdbm_database_for_the_gutenberg_collection"/> Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÑ ÑÑÐ°Ð³ÐŒÐµÐœÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ Ð±Ð°Ð·Ñ ÐŽÐ°ÐœÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐºÐŸÑÐŸÑÐ°Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐ° Ð¿ÑÐž ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Gutenberg. Ð€ÑÐ°Ð³ÐŒÐµÐœÑ Ð±ÑÐ» ÑÐŸÐ·ÐŽÐ°Ðœ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÑÑÐžÐ»ÐžÑÑ db2txt ÑÐžÑÑÐµÐŒÑ Greenstone, ÐºÐŸÑÐŸÑÐ°Ñ ÐºÐŸÐœÐ²ÐµÑÑÐžÑÑÐµÑ GDBM ÐŽÐ²ÐŸÐ¹ÐœÐŸÐ¹ ÑÐŸÑÐŒÐ°Ñ Ð±Ð°Ð·Ñ ÐŽÐ°ÐœÐœÑÑ
+ Ð² ÑÐµÐºÑÑÐŸÐ²ÑÑ ÑÐŸÑÐŒÑ. Ð ÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="gdbm_database_for_the_gutenberg_collection"/> ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÑÑÐž Ð·Ð°Ð¿ÐžÑÐž, ÐŸÑÐŽÐµÐ»ÐµÐœÐœÑÐµ Ð³ÐŸÑÐžÐ·ÐŸÐœÑÐ°Ð»ÑÐœÑÐŒÐž Ð»ÐžÐœÐžÑÐŒÐž. ÐÐµÑÐ²ÑÐ¹ - Ð²Ñ
+ÐŸÐŽ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, ÐŽÑÑÐ³ÐžÐµ ÐŽÐ²Ð° - ÑÐ°ÑÑÑ ÐžÐµÑÐ°ÑÑ
+ÐžÐž, ÑÐŸÐ·ÐŽÐ°ÐœÐœÐŸÐ¹ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐŒ AZList ÐŽÐ»Ñ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐŸÐ² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐµÑÐ²Ð°Ñ ÑÑÑÐŸÐºÐ° ÐºÐ°Ð¶ÐŽÐŸÐ¹ Ð·Ð°Ð¿ÐžÑÐž - ÐµÐµ ÐºÐ»ÑÑ.</Text>
+<Text id="891">ÐÐ°Ð¿ÐžÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ñ
+ÑÐ°ÐœÐžÑ Ð·Ð°Ð³Ð»Ð°Ð²ÐžÐµ ÐºÐœÐžÐ³Ðž, Ð°Ð²ÑÐŸÑÐ° Ðž Ð»ÑÐ±ÑÐµ ÐŽÑÑÐ³ÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, ÑÐŸÐ·ÐŽÐ°ÐœÐœÑÐµ (ÐžÐ»Ðž ÐžÐ·Ð²Ð»ÐµÑÐµÐœÐœÑÐµ) Ð²ÐŸ Ð²ÑÐµÐŒÑ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ°Ð¿ÐžÑÑ ÑÐ°ÐºÐ¶ÐµÐ±ÑÐ²Ð°ÐµÑ ÐŽÐ»Ñ Ð²ÐœÑÑÑÐµÐœÐœÐµÐ³ÐŸ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ Ðž Ñ
+ÑÐ°ÐœÐžÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÑÐŸÐŒ, Ð³ÐŽÐµ ÐœÐ°Ñ
+ÐŸÐŽÑÑÑÑ ÑÐ°Ð¹Ð»Ñ, ÑÐ²ÑÐ·Ð°ÐœÐœÑÐµ Ñ ÑÑÐžÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐŒ (<i>&lt;archivedir&gt;</i>), Ðž ÐœÐŸÐŒÐµÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐ¹ Ð²ÐœÑÑÑÐž MG (<i>&lt;docnum&gt;</i>).</Text>
+<Text id="892">ÐÐŸÐ»Ðµ <i>&lt;contains&gt;</i> Ñ
+ÑÐ°ÐœÐžÑ ÑÐ¿ÐžÑÐŸÐº ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ², ÐŸÑÐŽÐµÐ»ÐµÐœÐœÑÑ
+ ÑÐŸÑÐºÐ°ÐŒÐž Ñ Ð·Ð°Ð¿ÑÑÐŸÐ¹. Ð­ÑÐŸ ÑÐŸÑÐºÐž, ÑÐ²ÑÐ·ÑÐ²Ð°ÑÑÐžÐµ Ð·Ð°Ð¿ÐžÑÐž Ð² Ð±Ð°Ð·Ðµ ÐŽÐ°ÐœÐœÑÑ
+. ÐÐ»Ñ Ð·Ð°Ð¿ÐžÑÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° <i>&lt;contains&gt;</i> ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ, ÑÑÐŸÐ±Ñ ÑÐºÐ°Ð·Ð°ÑÑ ÐœÐ° Ð²Ð»ÐŸÐ¶ÐµÐœÐœÑÐµ ÑÐ°Ð·ÐŽÐµÐ»Ñ. ÐÐŸÑÐ»ÐµÐŽÑÑÑÐžÐµ ÐºÐ»ÑÑÐž Ð·Ð°Ð¿ÐžÑÐž ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÑ, ÑÐ²ÑÐ·ÑÐ²Ð°Ñ ÑÐµÐºÑÑÐžÐ¹ ÐºÐ»ÑÑ Ñ ÐŸÐŽÐœÐžÐŒ ÐžÐ· ÐŽÐŸÑÐµÑÐœÐžÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² (ÐŸÑÐŽÐµÐ»ÐµÐœÐœÑÑ
+ Ð¿ÐµÑÐžÐŸÐŽÐŸÐŒ).</Text>
+<Text id="893">ÐÑÐŸÑÐ°Ñ Ð·Ð°Ð¿ÐžÑÑ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="gdbm_database_for_the_gutenberg_collection"/> - Ð³Ð»Ð°Ð²ÐœÑÐ¹ ÑÐ·ÐµÐ» ÐŽÐ»Ñ ÐžÐµÑÐ°ÑÑ
+ÐžÐž ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐž Titles AâZ. ÐÐ³ÐŸ ÐŽÐµÑÐž ÐŽÐŸÑÑÑÐ¿ÐœÑ ÑÐµÑÐµÐ· Ð¿ÐŸÐ»Ðµ &lt;contains&gt;, Ð²ÐºÐ»ÑÑÐ°Ñ CL 1.1, CL1.2, CL1.3 Ðž ÑÐ°Ðº ÐŽÐ°Ð»ÐµÐµ, ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐµ ÐžÐœÐŽÐžÐ²ÐžÐŽÑÐ°Ð»ÑÐœÑÐŒ ÑÑÑÐ°ÐœÐžÑÐ°ÐŒ ÐŽÐ»Ñ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ² Ð, Ð, Ð¡ Ðž Ñ.ÐŽ. ÐÐŒÐµÐµÑÑÑ ÑÐŸÐ»ÑÐºÐŸ 24 ÑÐµÐ±ÐµÐœÐºÐ°: ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ AZList ÑÐ»ÐžÐ» Q-R Ðž Y-Z Ð²Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÑ, Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ ÐŸÐœÐž ÐŸÑ
+Ð²Ð°ÑÐžÐ»Ðž ÑÐŸÐ»ÑÐºÐŸ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ Ð·Ð°Ð³Ð»Ð°Ð²ÐžÐ¹.</Text>
+<Text id="894">ÐÐµÑÐž Ð² Ð¿ÐŸÐ»Ðµ <i>&lt;contains&gt;</i> ÑÑÐµÑÑÐµÐ¹ Ð·Ð°Ð¿ÐžÑÐž, CL 1.1,- ÑÑÐŸ ÐºÐŸÐœÐµÑÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ. ÐÐŸÐ·ÐŒÐŸÐ¶ÐœÑ Ðž Ð±ÐŸÐ»ÐµÐµ ÑÐ»ÐŸÐ¶ÐœÑÐµ ÑÑÑÑÐºÑÑÑÑ - Ð¿ÐŸÐ»Ðµ <i>&lt;contains&gt;</i> ÐŒÐŸÐ¶ÐµÑ Ð²ÐºÐ»ÑÑÐ°ÑÑ ÑÐŒÐµÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ CL ÑÐ·Ð»ÐŸÐ². ÐÐ»ÑÑÐž, Ð²ÑÑÐ°Ð¶ÐµÐœÐœÑÐµ ÐŸÑÐœÐŸÑÐžÑÐµÐ»ÑÐœÐŸ ÑÐµÐºÑÑÐµÐ³ÐŸ, ÐŸÑÐ»ÐžÑÐ°ÑÑ ÐŸÑ Ð°Ð±ÑÐŸÐ»ÑÑÐœÑÑ
+ ÐºÐ»ÑÑÐµÐ¹, Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ ÐŸÐœÐž ÐœÐ°ÑÐžÐœÐ°ÑÑÑÑ Ñ ÐºÐ°Ð²ÑÑÐµÐº (").</Text>
+</Content>
+</Part>
+<Part id="using_mg_and_gdbm_to_implement_a_source_object">
+<Title>
+<Text id="895">ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ MG Ðž GDBM ÐŽÐ»Ñ ÑÐµÐ°Ð»ÐžÐ·Ð°ÑÐžÐž ÐŸÐ±ÑÐµÐºÑÐ° Source</Text>
+</Title>
+<Content>
+<Figure id="api_for_mg_and_gdbm_based_version_of_sourceclass">
+<Title>
+<Text id="896">API ÐŽÐ»Ñ sourceclass Ð±Ð°Ð·ÐŸÐ²ÐŸÐ¹ Ð²ÐµÑÑÐžÐž MG Ðž GDBM (ÑÐŸÐºÑÐ°ÑÐµÐœÐœÑÐ¹ Ð²Ð°ÑÐžÐ°ÐœÑ)</Text>
+</Title>
+<CodeLine>class mggdbmsourceclass : public sourceclass {</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>   // Omitted, data fields that store:</CodeLine>
+<CodeLine>   //     collection specific file information</CodeLine>
+<CodeLine>   //     index substructure</CodeLine>
+<CodeLine>   //     information about parent</CodeLine>
+<CodeLine>   //     pointers to gdbm and mgsearch objects</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   mggdbmsourceclass ();</CodeLine>
+<CodeLine>   virtual ~mggdbmsourceclass ();</CodeLine>
+<CodeLine>   void set_gdbmptr (gdbmclass *thegdbmptr);</CodeLine>
+<CodeLine>   void set_mgsearchptr (searchclass *themgsearchptr);</CodeLine>
+<CodeLine>   void configure (const text_t &amp;key, const text_tarray &amp;cfgline);</CodeLine>
+<CodeLine>   bool init (ostream &amp;logout);</CodeLine>
+<CodeLine>   bool translate_OID (const text_t &amp;OIDin, text_t &amp;OIDout,</CodeLine>
+<CodeLine>                                           comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   bool get_metadata (const text_t &amp;requestParams,</CodeLine>
+<CodeLine>                                           const text_t &amp;refParams,</CodeLine>
+<CodeLine>                                         bool getParents, const text_tset &amp;fields,</CodeLine>
+<CodeLine>                                         const text_t &amp;OID, MetadataInfo_tmap &amp;metadata,</CodeLine>
+<CodeLine>                                         comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   bool get_document (const text_t &amp;OID, text_t &amp;doc,</CodeLine>
+<CodeLine>                                         comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="897">ÐÐ±ÑÐµÐºÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐŸÐµÐŽÐžÐœÑÐµÑ MG Ðž GDBM, ÑÑÐŸÐ±Ñ ÑÐµÐ°Ð»ÐžÐ·ÐŸÐ²Ð°ÑÑ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ sourceclass -ÑÑÐŸ mggdbmsourceclass. Ð ÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="api_for_mg_and_gdbm_based_version_of_sourceclass"/> ÐŽÐµÐŒÐŸÐœÑÑÑÐžÑÑÐµÑ ÐµÐ³ÐŸ API. ÐÐ²Ðµ ÐœÐŸÐ²ÑÑ
+ ÑÑÐœÐºÑÐžÐž-ÑÐ»ÐµÐœÐ° set_gdbmptr () Ðž set_mgsearchptr () Ñ
+ÑÐ°ÐœÑÑ ÑÐºÐ°Ð·Ð°ÑÐµÐ»Ðž ÐœÐ° ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐµ ÐžÐŒ ÐŸÐ±ÑÐµÐºÑÑ, ÑÐ°Ðº, ÑÑÐŸÐ±Ñ Ð¿ÑÐž Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐž getjnetadata Ð Ðž get_document () ÐžÐŒÐµÑÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐŒ ÐžÐœÑÑÑÑÐŒÐµÐœÑÐ°Ð»ÑÐœÑÐŒ ÑÑÐµÐŽÑÑÐ²Ð°ÐŒ ÐŽÐ»Ñ Ð·Ð°Ð²ÐµÑÑÐµÐœÐžÑ ÑÐ°Ð±ÐŸÑÑ.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="the_filter_object">
+<Title>
+<Text id="898">ÐÐ±ÑÐµÐºÑ Filter</Text>
+</Title>
+<Content>
+<Figure id="api_for_the_filter_base_class">
+<Title>
+<Text id="899">API for the Filter base class</Text>
+</Title>
+<CodeLine>class filterclass {</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>   text_t gsdlhome;</CodeLine>
+<CodeLine>   text_t collection;</CodeLine>
+<CodeLine>   text_t collectdir;</CodeLine>
+<CodeLine>   FilterOption_tmap filterOptions;</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   filterclass ();</CodeLine>
+<CodeLine>   virtual ~filterclass ();</CodeLine>
+<CodeLine>   virtual void configure (const text_t &amp;key,Â const text_tarray &amp;cfgline);</CodeLine>
+<CodeLine>   virtual bool init (ostream &amp;logout);</CodeLine>
+<CodeLine>   // returns the name of this filter</CodeLine>
+<CodeLine>   virtual text_t get_filter_name ();</CodeLine>
+<CodeLine>   // returns the current filter options</CodeLine>
+<CodeLine>   virtual void get_filteroptions (InfoFilterOptionsResponse_t &amp;response,</CodeLine>
+<CodeLine>                                 comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void filter (const FilterRequest_t &amp;request,</CodeLine>
+<CodeLine>                         FilterResponse_t &amp;response,</CodeLine>
+<CodeLine>                         comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="900">API Ð±Ð°Ð·ÐŸÐ²ÐŸÐ³ÐŸ ÐºÐ»Ð°ÑÑÐ° ÐŽÐ»Ñ ÐŸÐ±ÑÐµÐºÑÐ° Filter (ÑÐŒ. ÑÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="greenstone_runtime_system"/>) Ð¿ÐŸÐºÐ°Ð·Ð°Ðœ ÐœÐ° Ð ÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="api_for_the_filter_base_class"/>. ÐÐœ ÐœÐ°ÑÐžÐœÐ°ÐµÑÑÑ Ñ Ð·Ð°ÑÐžÑÐµÐœÐœÑÑ
+ Ð¿ÐŸÐ»ÐµÐ¹ ÐŽÐ°ÐœÐœÑÑ
+ gsdlhome, collection Ðž collectdir. ÐÐœÐž ÐŸÐ±ÑÑÐœÐŸ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÑÑ Ð² ÐºÐ»Ð°ÑÑÐ°Ñ
+, ÐºÐŸÑÐŸÑÑÐµ ÐŽÐŸÐ»Ð¶ÐœÑ ÐŸÐ±ÑÐ°ÑÐžÑÑÑÑ Ðº ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹ ÑÐ°Ð¹Ð»Ð°ÐŒ.</Text>
+<BulletList>
+<Bullet>
+<Text id="901"><i>gsdlhome</i> ÑÐŸÑÐœÐŸ ÑÐ°ÐºÐŸÐ¹ Ð¶Ðµ, ÐºÐ°Ðº GSDLHOME, Ð¿ÑÐµÐŽÐœÐ°Ð·ÐœÐ°ÑÐµÐœ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÐŸÐ±ÑÐµÐºÑ ÐŒÐŸÐ³ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÐŒÐµÑÑÐŸÐœÐ°Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÐµ ÑÐ°Ð¹Ð»ÐŸÐ² Greenstone.</Text>
+</Bullet>
+<Bullet>
+<Text id="902"><i>collection</i> - ÐžÐŒÑ ÐºÐ°ÑÐ°Ð»ÐŸÐ³Ð°, ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐ³ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+</Bullet>
+<Bullet>
+<Text id="903"><i>collectdir</i> - Ð¿ÐŸÐ»ÐœÐŸÐµ ÐžÐŒÑ Ð¿ÑÑÐž Ðº ÐºÐ°ÑÐ°Ð»ÐŸÐ³Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (ÑÑÐŸ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ, Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐœÐµ ÐŽÐŸÐ»Ð¶ÐœÐ° Ð¿ÐŸÑÑÐŸÑÐœÐœÐŸ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑÑ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ GSDLHOME ÐŸÐ±Ð»Ð°ÑÑÐž).</Text>
+</Bullet>
+</BulletList>
+<Text id="904"><i>mggdbsourceclass</i> - ÐŽÑÑÐ³ÐŸÐ¹ ÐºÐ»Ð°ÑÑ, ÐºÐŸÑÐŸÑÑÐ¹ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÑÑÐž ÑÑÐž Ð¿ÐŸÐ»Ñ ÐŽÐ°ÐœÐœÑÑ
+.</Text>
+<Text id="905">Ð€ÑÐœÐºÑÐžÐž-ÑÐ»ÐµÐœÑ conflgure() Ðž init() (ÑÐ°ÐœÐµÐµ ÑÐ¿ÐŸÐŒÐžÐœÐ°Ð²ÑÐžÐµÑÑ Ð² sourceclass) ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ Ð¿ÑÐŸÑÐµÑÑÐŸÐŒ ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÐž. Ð¡Ð°ÐŒ ÐŸÐ±ÑÐµÐºÑ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÐœÐµÐŽÐ°Ð»ÐµÐºÐŸ ÐŸÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐ¹ ÑÐ°ÑÑÐž ÑÐžÐ»ÑÑÑÐ° Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð°; Ð² ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž getjilteroptions Ð Ðž fllter() ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑ ÐŸÐŽÐžÐœ ÐŽÑÑÐ³ÐŸÐŒÑ.</Text>
+<Figure id="how_a_filter_option_is_stored">
+<Title>
+<Text id="906">ÐÐ°Ðº Ñ
+ÑÐ°ÐœÐžÑÑÑ ÐŸÐ¿ÑÐžÑ filter</Text>
+</Title>
+<CodeLine>struct FilterOption_t {</CodeLine>
+<CodeLine>   void clear (); \   void check_defaultValue ();</CodeLine>
+<CodeLine>   FilterOption_t () {clear();}</CodeLine>
+<CodeLine>   text_t name;</CodeLine>
+<CodeLine>   enum type_t {booleant=0, integert=1, enumeratedt=2, stringt=3};</CodeLine>
+<CodeLine>   type_t type;</CodeLine>
+<CodeLine>   enum repeatable_t {onePerQuery=0, onePerTerm=1, nPerTerm=2};</CodeLine>
+<CodeLine>   repeatable_t repeatable;</CodeLine>
+<CodeLine>   text_t defaultValue;</CodeLine>
+<CodeLine>   text_tarray validValues;</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine>struct OptionValue_t {</CodeLine>
+<CodeLine>   void clear ();</CodeLine>
+<CodeLine>   text_t name;</CodeLine>
+<CodeLine>   text_t value;</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="907">Ð ÑÐµÐœÑÑÐ°Ð»ÑÐœÑÐŒ ÐŸÐ¿ÑÐžÑÐŒ ÑÐžÐ»ÑÑÑÐ° ÐŸÑÐœÐŸÑÑÑÑÑ ÐŽÐ²Ð° ÐºÐ»Ð°ÑÑÐ°, Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐœÑÐµ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="how_a_filter_option_is_stored"/>. Ð¡ÐŸÑ
+ÑÐ°ÐœÐµÐœÐœÑÐµ Ð²ÐœÑÑÑÐž FilterOption_t - ÑÑÐŸ Ð¿Ð°ÑÐµ ÐŸÐ¿ÑÐžÐž, ÐµÐµ type Ðž ÐŽÐµÐ¹ÑÑÐ²ÐžÑÐµÐ»ÑÐœÐŸ Ð»Ðž ÑÑÐŸ - repeatable. ÐÐœÑÐµÑÐ¿ÑÐµÑÐ°ÑÐžÑ validValues Ð·Ð°Ð²ÐžÑÐžÑ ÐŸÑ ÑÐžÐ¿Ð° ÐŸÐ¿ÑÐžÐž. ÐÐ»Ñ ÐÑÐ»ÐµÐ²Ð° ÑÐžÐ¿Ð° Ð¿ÐµÑÐ²ÑÐŒ Ð·ÐœÐ°ÑÐµÐœÐžÐµÐŒ Ð¿ÐµÑÐµÐŒÐµÐœÐŸÐ¹ ÑÐ²Ð»ÑÐµÑÑÑ^Ð³/5Ðµ,Ð° Ð²ÑÐŸÑÑÐŒ - true. ÐÐ»Ñ ÑÐµÐ»ÐŸÑÐžÑÐ»ÐµÐœÐœÐŸÐ³ÐŸ ÑÐžÐ¿Ð° Ð¿ÐµÑÐ²ÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ - ÐŒÐžÐœÐžÐŒÐ°Ð»ÑÐœÑÐ¹ ÐœÐŸÐŒÐµÑ, Ð²ÑÐŸÑÐŸÐ¹ - ÐŒÐ°ÐºÑÐžÐŒÐ°Ð»ÑÐœÑÐ¹. ÐÐ»Ñ Ð¿ÐµÑÐµÑÐžÑÐ»ÑÐµÐŒÐŸÐ³ÐŸ ÑÐžÐ¿Ð° Ð²ÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ Ð¿ÐµÑÐµÑÐžÑÐ»ÐµÐœÑ. ÐÐ»Ñ ÑÑÑÐŸÐºÐŸÐ²ÐŸÐ³ÐŸ ÑÐžÐ¿Ð° Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐ³ÐœÐŸÑÐžÑÑÐµÑÑÑ. ÐÐ»Ñ Ð±ÐŸÐ»ÐµÐµ Ð¿ÑÐŸÑÑÑÑ
+ ÑÐžÑÑÐ°ÑÐžÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ OptionValue_t, Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ Ð·Ð°Ð¿ÐžÑÐž ÐºÐ°Ðº text_t name ÐŸÐ¿ÑÐžÐž Ðž ÐµÐµ value.</Text>
+<Text id="908">ÐÐ°Ð¿ÑÐŸÑ Ðž ÐŸÑÐ²ÐµÑ ÐŸÐ±ÑÐµÐºÑÐ° Ð¿ÑÐŸÑ
+ÐŸÐŽÑÑ ÐºÐ°Ðº Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ juuLJilterclass. Ð¡ÐŸÐ·ÐŽÐ°ÐœÑÑ ÐžÐ· ÐœÐžÑ
+ ÐŽÐ²Ð° ÐºÐ»Ð°ÑÑÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑ Ð°ÑÑÐŸÑÐžÐ°ÑÐžÐ²ÐœÑÐµ ÐŒÐ°ÑÑÐžÐ²Ñ, ÑÑÐŸÐ±Ñ ÑÐŸÑ
+ÑÐ°ÐœÐžÑÑ ÐœÐ°Ð±ÐŸÑ ÑÐžÐ¿ÐŸÐ² ÐŸÐ¿ÑÐžÐ¹, ÑÑÐµÐ±ÑÐµÐŒÑÑ
+ ÐŽÐ»Ñ InfoFilterOptionsResponseJ. ÐÐ»Ñ ÐŽÐµÑÐ°Ð»ÑÐœÐŸÐ³ÐŸ ÐžÑÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐžÑ Ð²ÐŸÐ¿ÑÐŸÑÐ° ÑÐŒÐŸÑÑÐžÑÐµ GSDLHOME/src/recpt/comtypes.h.</Text>
+</Content>
+</Subsection>
+<Subsection id="inherited_filter_objects">
+<Title>
+<Text id="909">ÐÐ±ÑÐµÐºÑÑ ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐžÑ Filter</Text>
+</Title>
+<Content>
+<Figure id="inheritance_hierarchy_for_filter">
+<Title>
+<Text id="910">ÐÐµÑÐ°ÑÑ
+ÐžÑ ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐžÑ Filter</Text>
+</Title>
+<File width="337" height="245" url="images/Dev_Fig_080.png"/>
+</Figure>
+<Text id="911">ÐÐ²Ð° ÑÑÐŸÐ²ÐœÑ ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐžÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐ»Ñ ÑÐžÐ»ÑÑÑÐŸÐ², ÐºÐ°Ðº Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐŸ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="inheritance_hierarchy_for_filter"/>. Ð¡ÐœÐ°ÑÐ°Ð»Ð° Ð±ÑÐ»ÐŸ ÑÐŽÐµÐ»Ð°ÐœÐŸ ÑÐ°Ð·Ð»ÐžÑÐžÐµ ÐŒÐµÐ¶ÐŽÑ ÑÐžÐ»ÑÑÑÐ°ÐŒÐž Query Ðž Browse, Ð° Ð·Ð°ÑÐµÐŒ Ð¿ÐµÑÐ²ÐŸÐŒÑ ÐžÐ· ÐœÐžÑ
+ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐŸ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ, ÐŸÑÐœÐŸÐ²Ð°ÐœÐœÐŸÐµ ÐœÐ° MG. ÐÐ»Ñ ÐºÐŸÑÑÐµÐºÑÐœÐŸÐ¹ ÑÐ°Ð±ÐŸÑÑ mgqueryfilterclass ÑÑÐµÐ±ÑÐµÑÑÑ ÐŽÐŸÑÑÑÐ¿ Ðº MG ÑÐµÑÐµÐ· mgsearchclass Ðž Ðº GDBM ÑÐµÑÐµÐ· gdbmclass. browsefllterclass ÐœÑÐ¶ÐŽÐ°ÐµÑÑÑ Ð² ÐŽÐŸÑÑÑÐ¿Ðµ ÑÐŸÐ»ÑÐºÐŸ Ðº GDBM. Ð£ÐºÐ°Ð·Ð°ÑÐµÐ»Ðž ÐœÐ° ÑÑÐž ÐŸÐ±ÑÐµÐºÑÑ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÑ ÐºÐ°Ðº Ð·Ð°ÑÐžÑÐµÐœÐœÑÐµ Ð¿ÐŸÐ»Ñ ÐŽÐ°ÐœÐœÑÑ
+ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÑ
+ ÐºÐ»Ð°ÑÑÐŸÐ².</Text>
+</Content>
+</Subsection>
+<Subsection id="the_collection_server_code">
+<Title>
+<Text id="912">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÑÐµÑÐ²ÐµÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="913">Ð Ð°ÑÑÐŒÐŸÑÑÐžÐŒ ÑÐ°Ð¹Ð»Ñ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ° Ð² GSDLHOME/SRC/COLSERVR Ñ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµÐŒ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÐžÐ· ÐœÐžÑ
+. ÐÐŒÑ ÑÐ°Ð¹Ð»Ð° Ð²ÐŸÐŸÐ±ÑÐµ Ð¿ÐŸÐ²ÑÐŸÑÑÐµÑ ÐžÐŒÑ ÐŸÐ±ÑÐµÐºÑÐ°, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÐŸÐµ Ð² ÐµÐ³ÐŸ Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+.</Text>
+<Table class="hidden">
+<Title/>
+<TableContent>
+<tr>
+<th width="120">
+<Text id="914"><b>browsefilter.h</b></Text>
+</th>
+<th width="420">
+<Text id="915">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐ¹ mfilterdass, ÑÑÐŸÑ ÐŸÐ±ÑÐµÐºÑ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ ÐŽÐŸÑÑÑÐ¿ Ðº GDBM (ÐÐ¿ÐžÑÐ°Ðœ Ð²ÑÑÐµ).</Text>
+</th>
+</tr>
+<tr>
+<th width="120"/>
+</tr>
+<tr>
+<th width="120">
+<Text id="916"><b>collectserver.h</b></Text>
+</th>
+<th width="420">
+<Text id="917">Ð­ÑÐŸÑ ÐŸÐ±ÑÐµÐºÑ ÑÐ²ÑÐ·ÑÐ²Ð°ÐµÑ Ð²ÐŒÐµÑÑÐµ Filters Ðž Sources ÐŽÐ»Ñ ÐŸÐŽÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐŸÑÐŒÐžÑÑÑ ÐŸÐ±ÑÐµÐºÑ Collection, Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐœÑÐ¹ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="greenstone_runtime_system"/>.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="918"><b>colservrconfig.h</b></Text>
+</th>
+<th width="420">
+<Text id="919">Ð€ÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÐ°Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐ° ÐŽÐ»Ñ ÑÑÐµÐœÐžÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹ ÑÐ°Ð¹Ð»ÐŸÐ² etc/'collect, cfg Ðž index/build, cfg. ÐÐµÑÐ²ÑÐ¹ ÐžÐ· ÐœÐžÑ
+ - ÑÐ°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐŸÑÐ»ÐµÐŽÐœÐžÐ¹ - ÑÐ°Ð¹Ð», ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐ¹ Ð¿ÑÐŸÑÐµÑÑÐŸÐŒ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÐŽÐµÐ»Ð°ÐµÑ Ð·Ð°Ð¿ÐžÑÑ Ð²ÑÐµÐŒÐµÐœÐž Ð¿ÐŸÑÐ»ÐµÐŽÐœÐµÐ¹ ÑÑÐ¿ÐµÑÐœÐŸÐ¹ ÐºÐŸÐŒÐ¿ÐŸÐœÐŸÐ²ÐºÐž, ÐºÐ°ÑÑÑ ÐžÐœÐŽÐµÐºÑÐœÐŸÐ³ÐŸ ÑÐ¿ÐžÑÐºÐ°, Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÑÐºÐŸÐ»ÑÐºÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð±ÑÐ»ÐŸ ÐžÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐŸ Ðž ÐºÐ°Ðº ÑÐºÐŸÐ»ÑÐºÐŸ Ð±Ð°Ð¹Ñ ÐŸÐœÐž Ð·Ð°ÐœÐžÐŒÐ°ÑÑ (Ð² ÑÐ°ÑÐ¿Ð°ÐºÐŸÐ²Ð°ÐœÐœÐŸÐŒ Ð²ÐžÐŽÐµ).</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="920"><b>filter.h</b></Text>
+</th>
+<th width="420">
+<Text id="921">ÐÐ±ÑÐµÐºÑ Ð±Ð°Ð·ÐŸÐ²ÐŸÐ³ÐŸ ÐºÐ»Ð°ÑÑÐ° Filter fllterclass ÐŸÐ¿ÐžÑÐ°Ðœ Ð²ÑÑÐµ.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="922"><b>maptools.h</b></Text>
+</th>
+<th width="420">
+<Text id="923">ÐÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÐºÐ»Ð°ÑÑ, ÐœÐ°Ð·Ð²Ð°ÐœÐœÑÐ¹ stringmap, ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ Ðž Ð±ÑÑÑÑÑÐ¹ Ð¿ÑÐŸÑÐŒÐŸÑÑ, Ð¿ÐŸÐŒÐœÐžÑ Ð¿ÐµÑÐ²ÐŸÐœÐ°ÑÐ°Ð»ÑÐœÑÐ¹ Ð¿ÐŸÑÑÐŽÐŸÐº ÐºÐ°ÑÑÑ text_t. ÐÑÐ¿ÐŸÐ»ÑÐ·ÐµÑÑÑ Ð² mggdbmsourceclass Ðž query'fllterclass.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="924"><b>mggdbmsource.h</b></Text>
+</th>
+<th width="420">
+<Text id="925">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŸÑ sourcedass, ÑÑÐŸÑ ÐŸÐ±ÑÐµÐºÑ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÐµÑ ÐŽÐŸÑÑÑÐ¿ Ðº MG Ðž GDBM (ÐŸÐ¿ÐžÑÐ°Ðœ Ð²ÑÑÐµ).</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="926"><b>mgppqueryfilter.h</b></Text>
+</th>
+<th width="420">
+<Text id="927">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŸÑ query'filterclass, ÑÑÐŸÑ ÐŸÐ±ÑÐµÐºÑ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ QueryFilter, ÐŸÑÐœÐŸÐ²Ð°ÐœÐœÐŸÐ³ÐŸ ÐœÐ° MG++, ÑÐ»ÑÑÑÐµÐœÐœÐŸÐ¹ Ð²ÐµÑÑÐžÐž MG, ÐœÐ°Ð¿ÐžÑÐ°ÐœÐœÐŸÐ¹ ÐœÐ° C++. ÐÐ±ÑÐ°ÑÐžÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ, ÑÑÐŸ Greenstone ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ, ÑÑÐŸÐ±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ MG Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ, ÑÐ°Ðº ÐºÐ°Ðº MG++ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð²ÑÐµ ÐµÑÐµ Ð² ÑÐ°Ð·Ð²ÐžÑÐžÐž.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="928"><b>mgppsearch.h</b></Text>
+</th>
+<th width="420">
+<Text id="929">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŸÑ searchclass, ÑÑÐŸÑ ÐŸÐ±ÑÐµÐºÑ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ Search /ÐÐŸÐžÑÐºÐ°, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ MG++. ÐÐŸÐŽÐŸÐ±ÐœÐŸ mgppqueryfllterclass, ÐŸÐœ ÐœÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="930"><b>mgq.h</b></Text>
+</th>
+<th width="420">
+<Text id="931">ÐÐœÑÐµÑÑÐµÐ¹Ñ ÑÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÐŸÐ³ÐŸ ÑÑÐŸÐ²ÐœÑ Ðº Ð¿Ð°ÐºÐµÑÑ MG. ÐÑÐœÐŸÐ²ÐœÑÐµ ÑÑÐœÐºÑÐžÐž <i>mg_ask()</i> Ðž <i>mg_results()</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="932"><b>mgqueryfilter.h</b></Text>
+</th>
+<th width="420">
+<Text id="933">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŸÑ queryfllterclass, ÑÑÐŸÑ ÐŸÐ±ÑÐµÐºÑ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµÐÐžÐµÐ³ÑÐ ÐšÐµÐ³, ÐŸÑÐœÐŸÐ²Ð°ÐœÐœÐŸÐ³ÐŸ ÐœÐ° MG.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="934"><b>mgsearch.h</b></Text>
+</th>
+<th width="420">
+<Text id="935">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŸÑ searchclass, ÑÑÐŸÑ ÐŸÐ±ÑÐµÐºÑ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ Search, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ MG (ÐŸÐ¿ÐžÑÐ°Ðœ Ð²ÑÑÐµ.)</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="936"><b>phrasequeryfilter.h</b></Text>
+</th>
+<th width="420">
+<Text id="937">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŸÑ mgqueryclass, ÑÑÐŸÑ ÐŸÐ±ÑÐµÐºÑ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ Ð·Ð°Ð¿ÑÐŸÑÐ°, ÐŸÑÐœÐŸÐ²Ð°ÐœÐœÐŸÐ³ÐŸ ÐœÐ° ÑÑÐ°Ð·Ðµ. ÐÐœ ÐœÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð² Ð·Ð°ÐŽÐ°ÐœÐœÐŸÐ¹ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž. ÐÐŒÐµÑÑÐŸ ÑÑÐŸÐ³ÐŸ mgqueryfllterclass ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ ÑÑÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ ÑÐµÑÐµÐ· ÑÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÑÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ ÐŸÑ phrasesearch.h.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="938"><b>phrasesearch.h</b></Text>
+</th>
+<th width="420">
+<Text id="939">Ð€ÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÐ°Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐ° Ð¿ÑÐŸÐ²ÐµÐŽÐµÐœÐžÑ Ð¿ÐŸÐžÑÐºÐ° Ð¿ÐŸ ÑÑÐ°Ð·Ðµ, ÐºÐ°Ðº ÐŸÐ¿ÐµÑÐ°ÑÐžÑ Ð¿ÐŸÑÑÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="940"><b>querycache.h</b></Text>
+</th>
+<th width="420">
+<Text id="941">ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ searchclass Ðž ÐµÐ³ÐŸ ÑÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐŒÐž ÐºÐ»Ð°ÑÑÐ°ÐŒÐž ÐŽÐ»Ñ ÐºÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐŸÐ² Ð·Ð°Ð¿ÑÐŸÑÐ°, Ð¿ÑÐž Ð³ÐµÐœÐµÑÐ°ÑÐžÐž ÑÑÑÐ°ÐœÐžÑ Ð¿ÐŸÐžÑÐºÐŸÐ²ÑÑ
+ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐŸÐ² ÐœÐ°ÐžÐ±ÐŸÐ»ÐµÐµ ÑÑÑÐµÐºÑÐžÐ²ÐµÐœ (ÐŸÐ¿ÐžÑÐ°Ðœ Ð²ÑÑÐµ.)</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="942"><b>queryfilter.h</b></Text>
+</th>
+<th width="420">
+<Text id="943">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŸÑ Ð±Ð°Ð·ÐŸÐ²ÐŸÐ³ÐŸ ÐºÐ»Ð°ÑÑÐ° Filter filterclass, ÑÑÐŸÑ ÐŸÐ±ÑÐµÐºÑ ÐŸÑÐœÐŸÐ²ÑÐ²Ð°ÐµÑ Ð±Ð°Ð·ÐŸÐ²ÑÐ¹ ÐºÐ»Ð°ÑÑ ÐŽÐ»Ñ ÐŸÐ±ÑÐµÐºÑÐŸÐ² Query filter (ÐŸÐ¿ÐžÑÐ°Ðœ Ð²ÑÑÐµ.)</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="944"><b>queryinfo.h</b></Text>
+</th>
+<th width="420">
+<Text id="945">ÐÐŸÐŽÐŽÐµÑÐ¶ÐºÐ° Ð¿ÐŸÐžÑÐºÐ°: ÑÑÑÑÐºÑÑÑÑ ÐŽÐ°ÐœÐœÑÑ
+ Ðž ÐŸÐ±ÑÐµÐºÑÑ ÑÐŸÐŽÐµÑÐ¶Ð°Ñ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ Ð·Ð°Ð¿ÑÐŸÑÐ°, ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÑ Ð¿ÐŸÐžÑÐºÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ðž ÑÐ°ÑÑÐŸÑÑ Ð²ÑÑÑÐµÑÐ°ÐµÐŒÐŸÑÑÐž ÑÐµÑÐŒÐžÐœÐ°.</Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="946"><b>search.h</b></Text>
+</th>
+<th width="420">
+<Text id="947">ÐÐ°Ð·ÐŸÐ²ÑÐ¹ ÐºÐ»Ð°ÑÑ Search ÐŸÐ±ÑÐµÐºÑ searchclass (ÐŸÐ¿ÐžÑÐ°Ðœ Ð²ÑÑÐµ.) </Text>
+</th>
+</tr>
+<tr>
+<th width="120">
+<Text id="948"><b>source.h</b></Text>
+</th>
+<th width="420">
+<Text id="949">ÐÐ°Ð·ÐŸÐ²ÑÐ¹ ÐºÐ»Ð°ÑÑÐÐŸÐžÐ³ÑÐµ ÐŸÐ±ÑÐµÐºÑ sourceclass (ÐŸÐ¿ÐžÑÐ°Ðœ Ð²ÑÑÐµ.)</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="protocol">
+<Title>
+<Text id="950">ÐÑÐŸÑÐŸÐºÐŸÐ»</Text>
+</Title>
+<Content>
+<Table id="list_of_protocol_calls">
+<Title>
+<Text id="951">Ð¡Ð¿ÐžÑÐŸÐº Ð·Ð°Ð¿ÑÐŸÑÐŸÐ² Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð°</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="952"><i>get_protocol_name()</i></Text>
+</th>
+<th width="397">
+<Text id="953">ÐÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑ ÐžÐŒÑ ÑÑÐŸÐ³ÐŸ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð°. ÐÑÐ±ÐŸÑÑ Ð²ÐºÐ»ÑÑÐ°ÑÑ nullproto, corbaproto Ðž z3950proto. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð²ÐŸ Ð²ÑÐµÐŒÑ ÑÐ°Ð±ÐŸÑÑ ÑÐžÑÑÐµÐŒÑ ÑÑÐ²ÑÑÐ²ÐžÑÐµÐ»ÑÐœÑÐŒÐž Ðº Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ñ ÑÐ°ÑÑÑÐŒÐž, ÑÑÐŸÐ±Ñ ÑÐµÑÐžÑÑ, ÐºÐ°ÐºÐžÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Ð·Ð°Ð¿ÑÑÑÐžÑÑ ÐœÐ° Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="954"><i>get_collection_list()</i></Text>
+</th>
+<th width="397">
+<Text id="955">ÐÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑ ÑÐ¿ÐžÑÐŸÐº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÐŸ ÐºÐŸÑÐŸÑÑÑ
+ ÑÑÐŸÑ Ð¿ÑÐŸÑÐŸÐºÐŸÐ» ÐžÐŒÐµÐµÑ ÑÐ²ÐµÐŽÐµÐœÐžÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="956"><i>has_collection()</i></Text>
+</th>
+<th width="397">
+<Text id="957">ÐÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÑÑÐžÐœÑ, ÐµÑÐ»Ðž Ð¿ÑÐŸÑÐŸÐºÐŸÐ» ÐŒÐŸÐ¶ÐµÑ ÑÐ²ÑÐ·Ð°ÑÑÑÑ Ñ ÐœÐ°Ð·Ð²Ð°ÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹, ÑÐŸ ÐµÑÑÑ ÑÑÐŸ - Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÑÐ¿ÐžÑÐºÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="958"><i>ping()</i></Text>
+</th>
+<th width="397">
+<Text id="959">ÐÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÑÑÐžÐœÑ, ÐµÑÐ»Ðž ÑÑÐ¿ÐµÑÐœÐŸ Ð±ÑÐ»Ð° ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° ÑÐ²ÑÐ·Ñ Ñ ÐœÐ°Ð·Ð²Ð°ÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹. Ð ÐœÑÐ»ÐµÐ²ÐŸÐŒ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ðµ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ ÐžÐŽÐµÐœÑÐžÑÐœÐŸ <i>has_collection().</i></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="960"><i>get_collectinfo()</i></Text>
+</th>
+<th width="397">
+<Text id="961">ÐÐŸÐ»ÑÑÐ°ÐµÑ ÐŸÐ±ÑÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÐœÐ°Ð·Ð²Ð°ÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž: ÐºÐŸÐ³ÐŽÐ° ÐŸÐœÐ° Ð±ÑÐ»Ð° ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐ°, ÑÐºÐŸÐ»ÑÐºÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐŸÐœÐ° ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ðž Ñ.ÐŽ. Ð¢Ð°ÐºÐ¶Ðµ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ   ÑÐ°Ð¹Ð»Ð° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž: ÑÐµÐºÑÑ ÐŽÐ»Ñ ÑÑÑÐ°ÐœÐžÑÑ"Ð°ÐªÐŸÐž1 this collection"; ÐžÐºÐŸÐœÐºÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ñ.ÐŽ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="962"><i>get_filterinfo()</i></Text>
+</th>
+<th width="397">
+<Text id="963">ÐÐŸÐ»ÑÑÐ°ÐµÑ ÑÐ¿ÐžÑÐŸÐº Ð²ÑÐµÑ
+ Filters ÐŽÐ»Ñ ÐœÐ°Ð·Ð²Ð°ÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. get</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="964"><i>get_filteroptions()</i></Text>
+</th>
+<th width="397">
+<Text id="965">ÐÐŸÐ»ÑÑÐ°ÐµÑ Ð²ÑÐµ Ð²Ð°ÑÐžÐ°ÐœÑÑ ÐŽÐ»Ñ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐŸÐ³ÐŸ Filter Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐœÐ°Ð·Ð²Ð°ÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="966"><i>filter()</i></Text>
+</th>
+<th width="397">
+<Text id="967">ÐÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÑ Ð¿ÐŸÐžÑÐº Ðž Ð¿ÑÐŸÑÐŒÐŸÑÑ, ÐŽÐ»Ñ ÐŽÐ°ÐœÐœÐŸÐ³ÐŸ ÑÐžÐ¿Ð° ÑÐžÐ»ÑÑÑÐ° Ðž Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ² ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž, ÐŸÐ±ÑÐ°ÑÐ°ÐµÑÑÑ Ðº ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÐœÐ°Ð·Ð²Ð°ÐœÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÑÑÐŸÐ±Ñ Ð²ÐŸÑÐ¿ÑÐŸÐžÐ·Ð²ÐµÑÑÐž ÑÐµÐ·ÑÐ»ÑÑÐ°Ñ, ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÑÑÐžÐ»ÑÑÑÐŸÐ²Ð°Ðœ Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐž Ñ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐ°ÐŒÐž ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž. ÐÐŸÐ·Ð²ÑÐ°ÑÐµÐœÐœÑÐµ Ð¿ÐŸÐ»Ñ ÐŽÐ°ÐœÐœÑÑ
+ ÑÐ°ÐºÐ¶Ðµ Ð·Ð°Ð²ÐžÑÑÑ ÐŸÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ² ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž: Ð¿ÑÐžÐŒÐµÑÑ Ð²ÐºÐ»ÑÑÐ°ÑÑ ÑÐ°ÑÑÐŸÑÑ Ð²ÑÑÑÐµÑÐ°ÐµÐŒÐŸÑÑÐž ÑÐµÑÐŒÐžÐœÐ° Ð·Ð°Ð¿ÑÐŸÑÐ° Ðž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="968"><i>get_document()</i></Text>
+</th>
+<th width="397">
+<Text id="969">ÐÐŸÐ»ÑÑÐ°ÐµÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ ÐžÐ»Ðž ÑÐ°Ð·ÐŽÐµÐ» ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="970">Ð¢Ð°Ð±Ð»ÐžÑÐ° <CrossRef target="Table" ref="list_of_protocol_calls"/> Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÑ ÑÐ¿ÐžÑÐŸÐº Ð·Ð°Ð¿ÑÐŸÑÐŸÐ² ÑÑÐœÐºÑÐžÐž Ðº Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ñ Ðž ÑÐµÐ·ÑÐŒÐµ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ Ð²Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÑ. ÐÑÐžÐŒÐµÑÑ Ð² Ð Ð°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Section" ref="how_the_conceptual_framework_fits_together"/> ÐŸÑ
+Ð²Ð°ÑÐžÐ»Ðž Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ ÐžÐ· ÐœÐžÑ
+. Ð€ÑÐœÐºÑÐžÐž, ÐœÐµ ÑÐ¿ÐŸÐŒÑÐœÑÑÑÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ - has_collection (), ping (), get_protocol_name () Ðž get_filteroptions (). ÐÐµÑÐ²ÑÐµ ÐŽÐ²Ðµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÑÑ ÐŸÑÐ²ÐµÑÑ ÐŽÐ°\ÐœÐµÑ ÐœÐ° Ð²ÐŸÐ¿ÑÐŸÑÑ "ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÑÑÐµÑÑÐ²ÑÐµÑ ÐœÐ° ÑÑÐŸÐŒ ÑÐµÑÐ²ÐµÑÐµ? " Ðž "ÑÑÐŸ Ð²ÑÐ¿ÐŸÐ»ÐœÑÐµÑÑÑ? ". ÐŠÐµÐ»Ñ ÐŽÐ²ÑÑ
+ ÐŽÑÑÐ³ÐžÑ
+ ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸÐ±Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶Ð°ÑÑ ÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐµÐœÐœÑÐµ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ñ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ Ð°ÑÑ
+ÐžÑÐµÐºÑÑÑÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÑÐ°ÑÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐ° Ð¿ÐŸ ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐ°ÐŒ, Ð° ÐœÐµ ÑÐŸÐ»ÑÐºÐŸ ÐœÑÐ»ÐµÐ²ÐŸÐ¹ Ð¿ÑÐŸÑÐŸÐºÐŸÐ», Ð±Ð°Ð·ÐžÑÑÑÑÐžÐ¹ÑÑ ÐœÐ° ÐŸÑÐŽÐµÐ»ÑÐœÐŸ Ð²ÑÐ¿ÐŸÐ»ÐœÑÐµÐŒÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐµ, ÐŸÐ¿ÐžÑÐ°ÐœÐœÐŸÐ¹ Ð·ÐŽÐµÑÑ. ÐÐŽÐœÐ° ÐžÐ· ÐœÐžÑ
+ ÑÐ°Ð·Ð»ÐžÑÐ°ÐµÑ, ÐºÐ°ÐºÐŸÐ¹ Ð¿ÑÐŸÑÐŸÐºÐŸÐ» ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ. ÐÑÑÐ³Ð°Ñ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÑ ÐŸÐ¿ÑÐ°ÑÐžÐ²Ð°ÑÑ ÑÐµÑÐ²ÐµÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÑÐŸÐ±Ñ ÐœÐ°Ð¹ÑÐž, ÐºÐ°ÐºÐžÐµ Ð²Ð°ÑÐžÐ°ÐœÑÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑÑÑ, Ðž ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ ÐŽÐžÐœÐ°ÐŒÐžÑÐµÑÐºÐž Ð²ÑÐ±ÐžÑÐ°ÑÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž, ÑÑÐŸÐ±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð²ÑÐµ Ð¿ÑÐµÐžÐŒÑÑÐµÑÑÐ²Ð° ÑÑÐ»ÑÐ³, Ð¿ÑÐµÐŽÐ»Ð°Ð³Ð°ÐµÐŒÑÑ
+ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐžÐŒ ÑÐµÑÐ²ÐµÑÐŸÐŒ.</Text>
+<Figure id="null_protocol_api">
+<Title>
+<Text id="971">ÐÑÐ»ÐµÐ²ÐŸÐ¹ Ð¿ÑÐŸÑÐŸÐºÐŸÐ» API (ÑÐŸÐºÑÐ°ÑÐµÐœÐœÑÐ¹ Ð²Ð°ÑÐžÐ°ÐœÑ)</Text>
+</Title>
+<CodeLine>class nullproto : public recptproto {</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   virtual text_t get_protocol_name ();</CodeLine>
+<CodeLine>   virtual void get_collection_list (text_tarray &amp;collist,</CodeLine>
+<CodeLine>                comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void has_collection (const text_t &amp;collection,</CodeLine>
+<CodeLine>                bool &amp;hascollection,</CodeLine>
+<CodeLine>                comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void ping (const text_t &amp;collection,</CodeLine>
+<CodeLine>                  bool &amp;wassuccess,</CodeLine>
+<CodeLine>                  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void get_collectinfo (const text_t &amp;collection,</CodeLine>
+<CodeLine>                  ColInfoResponse_t &amp;collectinfo,</CodeLine>
+<CodeLine>                  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void get_filterinfo (const text_t &amp;collection,</CodeLine>
+<CodeLine>                   InfoFiltersResponse_t &amp;response,</CodeLine>
+<CodeLine>                   comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void get_filteroptions (const text_t &amp;collection,</CodeLine>
+<CodeLine>                   const InfoFilterOptionsRequest_t &amp;request,</CodeLine>
+<CodeLine>                   InfoFilterOptionsResponse_t &amp;response,</CodeLine>
+<CodeLine>                   comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void filter (const text_t &amp;collection,</CodeLine>
+<CodeLine>                   FilterRequest_t &amp;request,</CodeLine>
+<CodeLine>                   FilterResponse_t &amp;response,</CodeLine>
+<CodeLine>                   comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void get_document (const text_t &amp;collection,</CodeLine>
+<CodeLine>                  const DocumentRequest_t &amp;request,</CodeLine>
+<CodeLine>                  DocumentResponse_t &amp;response,</CodeLine>
+<CodeLine>                  comerror_t &amp;err, ostream &amp;logout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="972">Ð ÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="null_protocol_api"/> Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ API ÐŽÐ»Ñ ÐœÑÐ»ÐµÐ²ÐŸÐ³ÐŸ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð°. ÐÐŸÐŒÐŒÐµÐœÑÐ°ÑÐžÐž Ðž ÐœÐµÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸÑÑÐž ÐœÐžÐ·ÐºÐŸÐ³ÐŸ ÑÑÐŸÐ²ÐœÑ Ð±ÑÐ»Ðž ÐŸÐ¿ÑÑÐµÐœÑ (ÑÐŒ. ÐžÑÑ
+ÐŸÐŽÐœÑÐ¹ ÑÐ°Ð¹Ð» recpt/nullproto.h ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÑÐµÐœÐžÑ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸÑÑÐµÐ¹).</Text>
+<Text id="973">Ð­ÑÐŸÑ Ð¿ÑÐŸÑÐŸÐºÐŸÐ» ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°Ð»ÑÑ ÐŸÑ Ð±Ð°Ð·ÐŸÐ²ÐŸÐ³ÐŸ ÐºÐ»Ð°ÑÑÐ° recptproto. ÐÐžÑÑÑÐ°Ð»ÑÐœÐŸÐµ ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐžÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÑÐ°Ðº, ÑÑÐŸÐ±Ñ Ð±ÐŸÐ»ÑÑÐµ, ÑÐµÐŒ ÐŸÐŽÐžÐœ ÑÐžÐ¿ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð°, ÐŽÐ°Ð¶Ðµ ÐœÐµ Ð·Ð°ÐŽÑÐŒÐ°ÐœÐœÐŸÐ³ÐŸ, Ð²ÑÐµ Ð¶Ðµ ÐŒÐŸÐ³ Ð»ÐµÐ³ÐºÐŸ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑÑÑ ÐŸÑÑÐ°Ð»ÑÐœÐŸÐ¹ ÑÐ°ÑÑÑÑ ÐžÑÑ
+ÐŸÐŽÐœÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ.</Text>
+<Text id="974">ÐÐ° ÐžÑÐºÐ»ÑÑÐµÐœÐžÐµÐŒ get_protocol_name (), ÐºÐŸÑÐŸÑÑÐ¹ ÐœÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ Ðž Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑ ÐžÐŒÑ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð° ÐºÐ°Ðº ÑÑÑÐŸÐºÑ ÑÐµÐºÑÑÐ° Unicode, Ð²ÑÐµ ÑÑÐœÐºÑÐžÐž Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð° Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑ ÐŸÑÐžÐ±ÐºÐž Ðž Ð²ÑÑ
+ÐŸÐŽÐœÐŸÐ¹ Ð¿ÐŸÑÐŸÐº, ÐºÐ°Ðº Ð¿ÐŸÑÐ»ÐµÐŽÐœÐžÐµ ÐŽÐ²Ð° Ð°ÑÐ³ÑÐŒÐµÐœÑÐ°. ÐÐ°ÑÐ°ÐŒÐµÑÑ ÐŸÑÐžÐ±ÐºÐž ÐŽÐµÐ»Ð°ÐµÑ Ð·Ð°Ð¿ÐžÑÑ Ð»ÑÐ±ÑÑ
+ ÐŸÑÐžÐ±ÐŸÐº, ÐºÐŸÑÐŸÑÑÐµ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÑÑ Ð² Ñ
+ÐŸÐŽÐµ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ Ð·Ð°Ð¿ÑÐŸÑÐ° Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð°, Ð° Ð²ÑÑ
+ÐŸÐŽÐœÐŸÐ¹ Ð¿ÐŸÑÐŸÐº ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐžÐž ÑÐµÐ»Ðž. Ð€ÑÐœÐºÑÐžÐž ÐŸÑÐœÐŸÑÑÑÑÑ Ðº ÑÐžÐ¿Ñ void - ÐŸÐœÐž ÐœÐµ Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐºÐ°Ðº ÐžÑ
+ Ð·Ð°ÐºÐ»ÑÑÐžÑÐµÐ»ÑÐœÐ°Ñ ÐžÐœÑÑÑÑÐºÑÐžÑ, ÐœÐŸ Ð²ÐŒÐµÑÑÐŸ ÑÑÐŸÐ³ÐŸ Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÑÑ ÐŽÐ°ÐœÐœÑÐµ ÑÐµÑÐµÐ· ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÐŒÑÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ ÑÐžÐ¿Ð° ÑÐ¶Ðµ Ð²Ð²ÐµÐŽÐµÐœÐœÐŸÐ³ÐŸ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐ° ÐŸÑÐžÐ±ÐºÐž. Ð ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÑÐ·ÑÐºÐ°Ñ
+ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÑÐ°ÐºÐžÐµ Ð¿ÐŸÐŽÐ¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Ð±ÑÐ»Ðž Ð±Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÑ ÐºÐ°Ðº Ð¿ÑÐŸÑÐµÐŽÑÑÑ, Ð° ÐœÐµ ÑÑÐœÐºÑÐžÐž, ÐœÐŸ C++ ÐœÐµ ÐŽÐµÐ»Ð°ÐµÑ ÐœÐžÐºÐ°ÐºÐŸÐ³ÐŸ ÑÐžÐœÑÐ°ÐºÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÑÐ°Ð·Ð»ÐžÑÐžÑ.</Text>
+<Text id="975">ÐÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ ÑÑÐœÐºÑÐžÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÐžÐŒÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐºÐ°Ðº Ð¿Ð°ÑÐ°ÐŒÐµÑÑ. Ð¢ÑÐž ÑÑÐœÐºÑÐžÐž-ÑÐ»ÐµÐœÑ, get_filteroptions (), filterQ, Ðž get_document (), ÑÐ»ÐµÐŽÑÑÑ Ð·Ð° ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµÐŒ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐ° Request Ðž Ð¿ÐŸÐ»ÑÑÐµÐœÐžÐµÐŒ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐŸÐ² Ð² Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐµ Response.</Text>
+</Content>
+</Section>
+<Section id="receptionist">
+<Title>
+<Text id="976">Ð ÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑ</Text>
+</Title>
+<Content>
+<Text id="977">ÐÐ°ÐºÐ»ÑÑÐžÑÐµÐ»ÑÐœÑÐ¹ ÑÑÐŸÐ²ÐµÐœÑ ÐºÐŸÐœÑÐµÐ¿ÑÑÐ°Ð»ÑÐœÐŸÐ¹ ÐŒÐŸÐŽÐµÐ»Ðž - ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑ. ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ CGI-Ð°ÑÐ³ÑÐŒÐµÐœÑÑ Ð±ÑÐŽÑÑ Ð¿ÑÐŸÐ°ÐœÐ°Ð»ÐžÐ·ÐžÑÐŸÐ²Ð°ÐœÑ, ÐŸÑÐœÐŸÐ²ÐœÐ°Ñ ÐŽÐµÑÑÐµÐ»ÑÐœÐŸÑÑÑ Ð·Ð°Ð¿ÑÑÐºÐ°ÐµÑ ÐœÐ° Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ Action, Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÐŒÑÑ ÐŸÐ±ÑÐµÐºÑÐ°ÐŒÐž Format Ðž Macro Language. ÐÐœÐž ÐŸÐ¿ÐžÑÐ°ÐœÑ ÐœÐžÐ¶Ðµ. Ð¥ÐŸÑÑ ÐŸÐœÐž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÑ ÐºÐ°Ðº ÐŸÐ±ÑÐµÐºÑÑ Ð² ÐºÐŸÐœÑÐµÐ¿ÑÑÐ°Ð»ÑÐœÐŸÐ¹ ÑÑÑÑÐºÑÑÑÐµ, ÐŸÐ±ÑÐµÐºÑÑ Format Ðž Macro Language - ÐœÐµ ÑÐŸÐ²ÑÐµÐŒ ÑÐ²Ð»ÑÑÑÑÑ ÐŸÐ±ÑÐµÐºÑÐ°ÐŒÐž Ñ ÑÐŸÑÐºÐž Ð·ÑÐµÐœÐžÑ C++. Ð ÐŽÐµÐ¹ÑÑÐ²ÐžÑÐµÐ»ÑÐœÐŸÑÑÐž, Format - ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÑÑÑÐºÑÑÑ ÐŽÐ°ÐœÐœÑÑ
+ Ñ ÐœÐ°Ð±ÐŸÑÐŸÐŒ ÑÑÐœÐºÑÐžÐ¹, ÐºÐŸÑÐŸÑÑÐµ ÐŸÐ¿ÐµÑÐžÑÑÑÑ ÐžÐŒÐž, Ð° ÐŸÐ±ÑÐµÐºÑ Macro Language ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°Ðœ Ð²ÐŸÐºÑÑÐ³ display class, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœ Ð² lib/display.h, Ñ Ð¿ÐŸÑÐŸÐºÐŸÐ²ÐŸÐ¹ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐŸÐ¹ ÐºÐŸÐœÐ²ÐµÑÑÐ°ÑÐžÐž ÐŸÑ lib/gsdlunicode.h.</Text>
+<Subsection id="actions">
+<Title>
+<Text id="978">ÐÐµÐ¹ÑÑÐ²ÐžÑ</Text>
+</Title>
+<Content>
+<Table id="actions_in_greenstone">
+<Title>
+<Text id="979">Actions Ð² ÑÐžÑÑÐµÐŒÐµ Greenstone</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="980"><i>action</i></Text>
+</th>
+<th width="397">
+<Text id="981">ÐÐ°Ð·ÐŸÐ²ÑÐ¹ ÐºÐ»Ð°ÑÑ ÐŽÐ»Ñ Ð²ÐžÑÑÑÐ°Ð»ÑÐœÐŸÐ³ÐŸ ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐžÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="982"><i>authenaction</i></Text>
+</th>
+<th width="397">
+<Text id="983">ÐÐŸÐŽÐŽÐµÑÐ¶ÐºÐ° ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐž Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ: Ð·Ð°Ð¿ÑÐŸÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐŸÑÐœÐŸÑÐžÑÐµÐ»ÑÐœÐŸ Ð¿Ð°ÑÐŸÐ»Ñ, ÐµÑÐ»Ðž ÐœÐµ Ð±ÑÐ» Ð²Ð²ÐµÐŽÐµÐœ; Ð¿ÑÐŸÐ²ÐµÑÐºÐ° Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸÑÑÐž; Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÐµÐœÐžÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð¿ÐŸÐ²ÑÐŸÑÐœÐŸÐ³ÐŸ Ð²Ñ
+ÐŸÐŽÐ°, ÐµÑÐ»Ðž ÐŽÐŸÑÑÐ°ÑÐŸÑÐœÐŸÐµ Ð²ÑÐµÐŒÑ ÐžÑÑÐµÐºÐ»ÐŸ ÐŒÐµÐ¶ÐŽÑ ÐŽÐŸÑÑÑÐ¿Ð°ÐŒÐž.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="984"><i>collectoraction</i></Text>
+</th>
+<th width="397">
+<Text id="985">ÐÐµÐœÐµÑÐžÑÑÐµÑ ÑÑÑÐ°ÐœÐžÑÑ ÐŽÐ»Ñ Collector (Ð¡ÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="986"><i>documentaction</i></Text>
+</th>
+<th width="397">
+<Text id="987">ÐÑÑÑÐºÐžÐ²Ð°ÐµÑ   ÐŽÐŸÐºÑÐŒÐµÐœÑÑ, ÑÐ°Ð·ÐŽÐµÐ»Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, ÑÐ°ÑÑÐž ÐžÐµÑÐ°ÑÑ
+ÐžÐž ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐž ÐžÐ»Ðž ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŽÐ»Ñ ÑÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÐžÑ .</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="988"><i>extlinkaction</i></Text>
+</th>
+<th width="397">
+<Text id="989">ÐÐµÑÐµÐœÐŸÑÐžÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ Ðº   URL, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐ²Ð»ÑÐµÑÑÑ Ð²ÐœÐµÑÐœÐžÐŒ ÐŽÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, no-Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž ÑÐœÐ°ÑÐ°Ð»Ð° Ð³ÐµÐœÐµÑÐžÑÑÑ Ð°Ð²Ð°ÑÐžÐ¹ÐœÑÑ ÑÑÑÐ°ÐœÐžÑÑ (Ð¿ÑÐŸÐŽÐžÐºÑÐŸÐ²Ð°ÐœÐœÑÑ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ°ÐŒÐž Preferences).</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="990"><i>pageaction</i></Text>
+</th>
+<th width="397">
+<Text id="991">ÐÐµÐœÐµÑÐžÑÑÐµÑ ÑÑÑÐ°ÐœÐžÑÑ Ð²ÐŒÐµÑÑÐµ Ñ ÐŒÐ°ÐºÑÐŸÑÐ·ÑÐºÐŸÐŒ. pingaction   ÐÑÑÑÐœÑÐµÑ, ÐžÐœÑÐµÑÐ°ÐºÑÐžÐ²ÐœÐ° Ð»Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. queryaction   ÐÑÐ¿ÐŸÐ»ÐœÑÐµÑ Ð¿ÐŸÐžÑÐº.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="992"><i>pingaction</i></Text>
+</th>
+<th width="397">
+<Text id="993">Checks to see whether a collection is online.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="994"><i>queryaction</i></Text>
+</th>
+<th width="397">
+<Text id="995">Performs a search.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="996"><i>statusaction</i></Text>
+</th>
+<th width="397">
+<Text id="997">ÐÐµÐœÐµÑÐžÑÑÐµÑ ÑÑÑÐ°ÐœÐžÑÑ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="998"><i>tipaction</i></Text>
+</th>
+<th width="397">
+<Text id="999">ÐÑÐŽÐ°ÐµÑ ÑÐ»ÑÑÐ°Ð¹ÐœÑÐ¹ ÑÐŸÐ²ÐµÑ ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1000"><i>usersaction</i></Text>
+</th>
+<th width="397">
+<Text id="1001">ÐÐŸÐ±Ð°Ð²Ð»ÑÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ, ÑÐŽÐ°Ð»ÐµÐœÐžÐµ Ðž ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÑÐºÐžÐŒ ÐŽÐŸÑÑÑÐ¿ÐŸÐŒ.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="1002">Greenstone Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÑ ÐŸÐŽÐžÐœÐœÐ°ÐŽÑÐ°ÑÑ ÐŽÐµÐ¹ÑÑÐ²ÐžÐ¹, ÑÐ²ÐµÐŽÐµÐœÐœÑÑ
+ Ð² Ð¢Ð°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="actions_in_greenstone"/>.</Text>
+<Figure id="using_the_cgiargsinfoclass_from_pageactioncpp" class="withLineNumber">
+<Title>
+<Text id="1003">ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ cgiargsinfoclass ÐžÐ· pageaction.cpp</Text>
+</Title>
+<CodeLine>cgiarginfo arg_ainfo;</CodeLine>
+<CodeLine>arg_ainfo.shortname = " a " ;</CodeLine>
+<CodeLine>arg_ainfo.longname = " action" ;</CodeLine>
+<CodeLine>arg_ainfo.multiplechar = true;</CodeLine>
+<CodeLine>arg_ainfo.argdefault = " p" ;</CodeLine>
+<CodeLine>arg_ainfo.defaultstatus = cgiarginfo::weak;</CodeLine>
+<CodeLine>arg_ainfo.savedarginfo = cgiarginfo::must;</CodeLine>
+<CodeLine>argsinfo.addarginfo (NULL, arg_ainfo);</CodeLine>
+<CodeLine/>
+<CodeLine>arg_ainfo.shortname = " p" ;</CodeLine>
+<CodeLine>arg_ainfo.longname = " page" ;</CodeLine>
+<CodeLine>arg_ainfo.multiplechar = true;</CodeLine>
+<CodeLine>arg_ainfo.argdefault = " home" ;</CodeLine>
+<CodeLine>arg_ainfo.defaultstatus = cgiarginfo::weak;</CodeLine>
+<CodeLine>arg_ainfo.savedarginfo = cgiarginfo::must;</CodeLine>
+<CodeLine>argsinfo.addarginfo (NULL, arg_ainfo);</CodeLine>
+</Figure>
+<Text id="1004">CGI-Ð°ÑÐ³ÑÐŒÐµÐœÑÑ ÑÐ²Ð»ÑÑÑÑÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÑÐŒÐž ÐŽÐµÐ¹ÑÑÐ²ÐžÑÐŒÐž ÑÐŸÑÐŒÐ°Ð»ÑÐœÐŸ ÐŸÐ±ÑÑÐ²Ð»ÐµÐœÐœÑÐŒÐž Ð² ÑÑÐœÐºÑÐžÐž ÐºÐŸÐœÑÑÑÑÐºÑÐŸÑÐ°, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÐžÐŒÐž cgiarginfo (ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐ¹ Ð² recpt/cgiargs.h). Ð ÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="using_the_cgiargsinfoclass_from_pageactioncpp"/> Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð²ÑÐ±ÐŸÑÐºÑ ÐžÐ· pageaction ÑÑÐœÐºÑÐžÐž ÐºÐŸÐœÑÑÑÑÐºÑÐŸÑÐ°, ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÑÐ°Ð·ÐŒÐµÑ Ðž ÑÐ²ÐŸÐ¹ÑÑÐ²Ð° CGI-Ð°ÑÐ³ÑÐŒÐµÐœÑÐŸÐ² Ð° Ðž Ñ.</Text>
+<Text id="1005">ÐÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ CGI-Ð°ÑÐ³ÑÐŒÐµÐœÑÐ° ÐºÐŸÐœÑÑÑÑÐºÑÐŸÑ ÐŽÐŸÐ»Ð¶ÐµÐœ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÐµÐ³ÐŸ ÐºÑÐ°ÑÐºÐŸÐµ ÐžÐŒÑ (ÑÑÑÐŸÐºÐž 2 Ðž 10), ÐºÐŸÑÐŸÑÐŸÐµ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ ÑÐ²Ð»ÑÐµÑÑÑ ÐžÐŒÐµÐœÐµÐŒ CGI-Ð¿ÐµÑÐµÐŒÐµÐœÐœÐŸÐ¹; Ð¿ÐŸÐ»ÐœÐŸÐµ ÐžÐŒÑ (ÑÑÑÐŸÐºÐž 3 Ðž 11), ÐºÐŸÑÐŸÑÐŸÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ, ÑÑÐŸÐ±Ñ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÑÑ Ð±ÐŸÐ»ÐµÐµ Ð·ÐœÐ°ÑÐžÐŒÐŸÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ; Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÑ Ð»Ðž ÑÑÐŸ ÐµÐŽÐžÐœÑÑÐ²ÐµÐœÐœÐŸÐµ ÐžÐ»Ðž ÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐµÐœÐœÐŸÐµ ÑÐžÐŒÐ²ÐŸÐ»ÑÐœÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ (ÑÑÑÐŸÐºÐž 4 Ðž 12); Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ (ÑÑÑÐŸÐºÐž 5 Ðž 13); ÑÑÐŸ ÑÐ»ÑÑÐ°ÐµÑÑÑ, ÐºÐŸÐ³ÐŽÐ° Ð·Ð°ÐŽÐ°ÐœÐŸ Ð±ÐŸÐ»ÑÑÐµ ÑÐµÐŒ ÐŸÐŽÐœÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ (ÑÑÑÐŸÐºÐž 6 Ðž 14) (ÑÐ°Ðº ÐºÐ°Ðº Ð·ÐœÐ°ÑÐµÐœÐžÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÐŒÐŸÐ³ÑÑ ÑÐ°ÐºÐ¶Ðµ Ð±ÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ Ð² ÑÐ°Ð¹Ð»Ð°Ñ
+ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž); ÐŽÐµÐ¹ÑÑÐ²ÐžÑÐµÐ»ÑÐœÐŸ Ð»Ðž Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÑÐŸÑ
+ÑÐ°ÐœÑÐµÑÑÑ Ð² ÐºÐŸÐœÑÐµ ÑÑÐŸÐ³ÐŸ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ (ÑÑÑÐŸÐºÐž 7 Ðž 15).</Text>
+<Text id="1006">Ð¢Ð°Ðº ÐºÐ°Ðº ÑÑÐŸ Ð²ÑÑÑÐŸÐµÐœÐŸ Ð² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, web-ÑÑÑÐ°ÐœÐžÑÑ, ÐºÐŸÑÐŸÑÑÐµ ÐŽÐµÑÐ°Ð»ÐžÐ·ÐžÑÑÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ, ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž. Statusaction Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑ ÑÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐ²ÐžÐŽÐµÑÑ ÑÑÐŸ, Ð²Ð²ÐµÐŽÑ URL ÑÑÑÐ°ÐœÐžÑÑ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ Greenstone.</Text>
+<Text id="1007">ÐÐ²ÐµÐœÐ°ÐŽÑÐ°ÑÑ ÑÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÑ
+ ÐŽÐµÐ¹ÑÑÐ²ÐžÐ¹ ÑÐŸÐ·ÐŽÐ°ÐœÑ Ð² main(), ÑÑÐœÐºÑÐžÑ Ð²ÐµÑÑ
+ÐœÐµÐ³ÐŸ ÑÑÐŸÐ²ÐœÑ ÐŽÐ»Ñ Ð²ÑÐ¿ÐŸÐ»ÐœÑÐµÐŒÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ library, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐµ ÐºÐŸÑÐŸÑÐŸÐ¹ ÐŽÐ°ÐµÑÑÑ Ð² recpt/librarymain.cpp, ÑÐ°ÐŒ Ð¶Ðµ, Ð³ÐŽÐµ Ð±ÑÐ» ÑÐŸÐ·ÐŽÐ°Ðœ ÐŸÐ±ÑÐµÐºÑ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÐ° (ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐ¹ Ð² recpt/receptionist.cpp). ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸÑÑÑ Ð·Ð° Ð²ÑÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ Ð¿ÐµÑÐµÐŽÐ°ÑÑ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑ ÐžÑ
+, ÐŸÐ±ÑÐ»ÑÐ¶ÐžÐ²Ð°Ñ ÐºÐ°Ðº Ð¿ÐŸÐ»Ðµ ÐŽÐ°ÐœÐœÑÑ
+ Ð°ÑÑÐŸÑÐžÐ°ÑÐžÐ²ÐœÐŸÐ³ÐŸ ÐŒÐ°ÑÑÐžÐ²Ð° Ð±Ð°Ð·ÐŸÐ²ÐŸÐ³ÐŸ ÐºÐ»Ð°ÑÑÐ° Action, ÐžÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐœÐŸÐ³ÐŸ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµÐŒ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ.</Text>
+<Figure id="action_base_class_api">
+<Title>
+<Text id="1008">Action Ð±Ð°Ð·ÐŸÐ²ÑÐ¹ ÐºÐ»Ð°ÑÑ API</Text>
+</Title>
+<CodeLine>class action {</CodeLine>
+<CodeLine>protected:</CodeLine>
+<CodeLine>   cgiargsinfoclass argsinfo;</CodeLine>
+<CodeLine>   text_t gsdlhome;</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   action ();</CodeLine>
+<CodeLine>   virtual ~action ();</CodeLine>
+<CodeLine>   virtual void configure (const text_t &amp;key, const text_tarray &amp;cfgline);</CodeLine>
+<CodeLine>   virtual bool init (ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual text_t get_action_name ();</CodeLine>
+<CodeLine>   cgiargsinfoclass getargsinfo ();</CodeLine>
+<CodeLine>   virtual bool check_cgiargs (cgiargsinfoclass &amp;argsinfo,</CodeLine>
+<CodeLine>              cgiargsclass &amp;args, ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual bool check_external_cgiargs (cgiargsinfoclass &amp;argsinfo,</CodeLine>
+<CodeLine>              cgiargsclass &amp;args,</CodeLine>
+<CodeLine>              outconvertclass &amp;outconvert,</CodeLine>
+<CodeLine>              const text_t &amp;saveconf,</CodeLine>
+<CodeLine>              ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void get_cgihead_info (cgiargsclass &amp;args,</CodeLine>
+<CodeLine>              recptprotolistclass *protos,</CodeLine>
+<CodeLine>              response_t &amp;response,</CodeLine>
+<CodeLine>              text_t &amp;response_data,</CodeLine>
+<CodeLine>              ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual bool uses_display (cgiargsclass &amp;args);</CodeLine>
+<CodeLine>   virtual void define_internal_macros (displayclass &amp;disp,</CodeLine>
+<CodeLine>              cgiargsclass &amp;args,</CodeLine>
+<CodeLine>              recptprotolistclass *protos,</CodeLine>
+<CodeLine>              ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual void define_external_macros (displayclass &amp;disp,</CodeLine>
+<CodeLine>              cgiargsclass &amp;args,</CodeLine>
+<CodeLine>              recptprotolistclass *protos,</CodeLine>
+<CodeLine>              ostream &amp;logout);</CodeLine>
+<CodeLine>   virtual bool do_action (cgiargsclass &amp;args,</CodeLine>
+<CodeLine>              recptprotolistclass *protos,</CodeLine>
+<CodeLine>              browsermapclass *browsers,</CodeLine>
+<CodeLine>              displayclass &amp;disp,</CodeLine>
+<CodeLine>              outconvertclass &amp;outconvert,</CodeLine>
+<CodeLine>              ostream &amp;textout,</CodeLine>
+<CodeLine>              ostream &amp;logout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="1009">Ð ÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="action_base_class_api"/> Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ API ÐŽÐ»Ñ Ð±Ð°Ð·ÐŸÐ²ÐŸÐ³ÐŸ ÐºÐ»Ð°ÑÑÐ° Action. ÐÑÐž Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐž ÐŽÐµÐ¹ÑÑÐ²ÐžÑ, receptionist (ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑ) Ð²ÑÐ·ÑÐ²Ð°ÐµÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÑÐœÐºÑÐžÐ¹, ÐœÐ°ÑÐžÐœÐ°Ñ Ñ check_cgiargs (). ÐÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ Ð¿ÐŸÐŒÐŸÐ³Ð°ÑÑ Ð¿ÑÐŸÐ²ÐµÑÐžÑÑ, ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ, Ðž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ Ðž ÐŒÐ°ÐºÑÐŸÑÑ; Ð² ÑÐŸ Ð²ÑÐµÐŒÑ ÐºÐ°Ðº dojzction () ÑÐ°ÐºÑÐžÑÐµÑÐºÐž Ð³ÐµÐœÐµÑÐžÑÑÐµÑ ÑÑÑÐ°ÐœÐžÑÑ Ð²ÑÐ²ÐŸÐŽÐ°. Ð ÑÐ°ÑÑÐœÐŸÑÑÐž, ÑÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŸÐ±ÑÐµÐºÑ ÐœÐµ ÐžÐŒÐµÐµÑ ÐœÐžÐºÐ°ÐºÐŸÐ³ÐŸ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÐŽÐ»Ñ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐŸÐ¹ ÑÑÐœÐºÑÐžÐž-ÑÐ»ÐµÐœÐ°, ÑÑÐŸ Ð¿ÑÐŸÑ
+ÐŸÐŽÐžÑ ÑÐµÑÐµÐ· ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐµ Ð±Ð°Ð·ÐŸÐ²ÐŸÐ³ÐŸ ÐºÐ»Ð°ÑÑÐ°, ÐºÐŸÑÐŸÑÐŸÐµ ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÐµÑ Ð·Ð°ÐŽÐ°ÐœÐœÐŸÐµ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ Ð¿ÐŸÐ²ÐµÐŽÐµÐœÐžÐµ.</Text>
+<Text id="1010">ÐÐ±ÑÑÑÐœÐµÐœÐžÑ ÑÑÐœÐºÑÐžÐ¹-ÑÐ»ÐµÐœÐŸÐ² ÑÐ»ÐµÐŽÑÑÑÐžÐµ.</Text>
+<BulletList>
+<Bullet>
+<Text id="1011"><i>get_action_name()</i>  Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ CGI-Ð°ÑÐ³ÑÐŒÐµÐœÑÐ°, ÐºÐŸÑÐŸÑÐŸÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÑÑÐŸ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ. ÐÐŒÑ ÐŽÐŸÐ»Ð¶ÐœÐŸ Ð±ÑÑÑ ÐºÐŸÑÐŸÑÐºÐžÐŒ, ÐœÐŸ Ð±ÐŸÐ»ÐµÐµ ÐŸÐŽÐœÐŸÐ³ÐŸ ÑÐžÐŒÐ²ÐŸÐ»Ð°.</Text>
+</Bullet>
+<Bullet>
+<Text id="1012"><i>check_cgiargs()</i> Ð²ÑÐ·ÑÐ²Ð°ÐµÑÑÑ Ð¿ÑÐµÐ¶ÐŽÐµ get_cgihead_info(),deflne_external_macros() Ðž do_action (). ÐÑÐ»Ðž ÐŸÑÐžÐ±ÐºÐ° ÐœÐ°Ð¹ÐŽÐµÐœÐ°, ÑÐŸÐŸÐ±ÑÐµÐœÐžÐµ ÐžÐœÑÐŸÑÐŒÐžÑÑÐµÑ ÐŸ Ð²ÑÑ
+ÐŸÐŽÐµ ÐžÐ· ÑÐžÑÑÐµÐŒÑ; ÐµÑÐ»Ðž ÑÑÐŸ ÑÐµÑÑÐµÐ·ÐœÐŸ, ÑÑÐœÐºÑÐžÑ Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ false Ðž ÐœÐžÐºÐ°ÐºÐ°Ñ Ð·Ð°Ð³ÑÑÐ·ÐºÐ° ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÑÑÐ°ÐœÐžÑÑ ÐœÐµ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑÑ.</Text>
+</Bullet>
+<Bullet>
+<Text id="1013"><i>check_external_cgiargs()</i> Ð²ÑÐ·ÑÐ²Ð°ÐµÑÑÑ Ð¿ÐŸÑÐ»Ðµ check_cgiargs () ÐŽÐ»Ñ Ð²ÑÐµÑ
+ ÐŽÐµÐ¹ÑÑÐ²ÐžÐ¹. ÐÐœÐ° Ð¿ÑÐµÐŽÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐ° ÑÐŸÐ»ÑÐºÐŸ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÐŸÑÐŒÐµÐœÐžÑÑ ÐœÐµÐºÐŸÑÐŸÑÐŸÐµ ÐœÐŸÑÐŒÐ°Ð»ÑÐœÐŸÐµ Ð¿ÐŸÐ²ÐµÐŽÐµÐœÐžÐµ, ÐœÐ°Ð¿ÑÐžÐŒÐµÑ Ð²ÐŸÑÐ¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÑ ÑÑÑÐ°ÐœÐžÑÑ Ð²Ñ
+ÐŸÐŽÐ° Ð² ÑÐžÑÑÐµÐŒÑ, ÐºÐŸÐ³ÐŽÐ° ÑÑÐµÐ±ÑÐµÑÑ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÑ.</Text>
+</Bullet>
+<Bullet>
+<Text id="1014"><i>get_cgihead_info()</i> ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐµ CGI. ÐÑÐ»Ðž response (ÐŸÑÐ²ÐµÑ) ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ, ÐºÐ°Ðº location (ÐŒÐµÑÑÐŸÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÐµ), ÑÐŸ response_data ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ð¿ÐµÑÐµÐ°ÐŽÑÐµÑÐ°ÑÐžÑ. ÐÑÐ»Ðž response  ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ, ÐºÐ°Ðº content (ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ), ÑÐŸ response_data ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÑÐžÐ¿ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ.</Text>
+</Bullet>
+<Bullet>
+<Text id="1015"><i>uses_display()</i> Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑ true, ÐµÑÐ»Ðž displayclass ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒ, ÐŽÐ»Ñ Ð²ÑÐ²ÐŸÐŽÐ° ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÑÑÑÐ°ÐœÐžÑÑ (Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ).</Text>
+</Bullet>
+<Bullet>
+<Text id="1016"><i>define_internal_macros()</i> ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ Ð²ÑÐµ ÐŒÐ°ÐºÑÐŸÑÑ, ÐºÐŸÑÐŸÑÑÐµ ÑÐ²ÑÐ·Ð°ÐœÑ ÑÐŸ ÑÑÑÐ°ÐœÐžÑÐ°ÐŒÐž, ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐŒÐž ÑÑÐžÐŒ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµÐŒ.</Text>
+</Bullet>
+<Bullet>
+<Text id="1017"><i>define_external_macros()</i> ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ Ð²ÑÐµ ÐŒÐ°ÐºÑÐŸÑÑ, ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³Ð»Ðž Ð±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ ÐŽÑÑÐ³ÐžÐŒÐž ÐŽÐµÐ¹ÑÑÐ²ÐžÑÐŒÐž ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÑÑÑÐ°ÐœÐžÑ.</Text>
+</Bullet>
+<Bullet>
+<Text id="1018"><i>do_action()</i> Ð³ÐµÐœÐµÑÐžÑÑÐµÑ ÑÑÑÐ°ÐœÐžÑÑ Ð²ÑÐ²ÐŸÐŽÐ° ÐŸÐ±ÑÑÐœÐŸ Ð² Ð¿ÐŸÑÐŸÐºÐµ ÐŸÐ±ÑÐµÐºÑÐ° ÐŒÐ°ÐºÑÐŸÑÐ·ÑÐºÐ° display Ðž Ð²ÑÐ²ÐŸÐŽÐžÑ Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÐœÐžÐµ ÐŸÐ±ÑÐµÐºÑÐ° textout. ÐÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ false, ÐµÑÐ»Ðž Ð¿ÑÐŸÐžÐ·ÐŸÑÐ»Ð° ÐŸÑÐžÐ±ÐºÐ°, ÐºÐŸÑÐŸÑÐ°Ñ Ð¿ÑÐµÐŽÐŸÑÐ²ÑÐ°ÑÐžÐ»Ð° ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ ÐºÐ°ÐºÐŸÐ³ÐŸ-ÐœÐžÐ±ÑÐŽÑ Ð²ÑÐ²ÐŸÐŽÐ°.</Text>
+</Bullet>
+</BulletList>
+<Text id="1019">Ð ÐœÐ°ÑÐ°Ð»Ðµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÐºÐ»Ð°ÑÑÐ° argsinfo - ÑÑÐŸ Ð·Ð°ÑÐžÑÐµÐœÐœÐŸÐµ Ð¿ÐŸÐ»Ðµ ÐŽÐ°ÐœÐœÑÑ
+ (ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐŸÐµ Ð² Ð²ÑÐ±ÐŸÑÐºÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, ÑÐŒ.ÑÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="using_the_cgiargsinfoclass_from_pageactioncpp"/>), ÐºÐŸÑÐŸÑÐŸÐµ Ñ
+ÑÐ°ÐœÐžÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ CGI-Ð°ÑÐ³ÑÐŒÐµÐœÑÐ°, ÑÐºÐ°Ð·Ð°ÐœÐœÑÑ Ð² ÑÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÐŸÐ¹ ÑÑÐœÐºÑÐžÐž ÐºÐŸÐœÑÑÑÑÐºÑÐŸÑÐ° Action. ÐÑÑÐ³ÐŸÐµ Ð¿ÐŸÐ»Ðµ ÐŽÐ°ÐœÐœÑÑ
+, gsdlhome, ÑÐŸÐ·ÐŽÐ°ÐµÑ Ð·Ð°Ð¿ÐžÑÑ GSDLHOME ÐŽÐ»Ñ ÑÐŽÐŸÐ±ÐœÐŸÐ³ÐŸ ÐŽÐŸÑÑÑÐ¿Ð°<FootnoteRef id="4"/>. ÐÐ±ÑÐµÐºÑ ÑÐ°ÐºÐ¶Ðµ Ð²ÐºÐ»ÑÑÐ°ÐµÑ conflgure() Ðž init () Ñ ÑÐµÐ»ÑÑ ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÐž.</Text>
+</Content>
+</Subsection>
+<Subsection id="formatting">
+<Title>
+<Text id="1020">Ð€ÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ</Text>
+</Title>
+<Content>
+<Figure id="core_data_structures_in_format">
+<Title>
+<Text id="1021">ÐÑÐœÐŸÐ²ÐœÑÐµ ÑÑÑÑÐºÑÑÑÑ ÐŽÐ°ÐœÐœÑÑ
+ Ð² Format</Text>
+</Title>
+<CodeLine>enum command_t {comIf, comOr, comMeta, comText, comLink, comEndLink,</CodeLine>
+<CodeLine>         comNum, comIcon, comDoc,</CodeLine>
+<CodeLine>         comHighlight, comEndHighlight};</CodeLine>
+<CodeLine>enum pcommand_t {pNone, pImmediate, pTop, pAll};</CodeLine>
+<CodeLine>enum dcommand_t {dMeta, dText};</CodeLine>
+<CodeLine>enum mcommand_t {mNone, mCgiSafe};</CodeLine>
+<CodeLine>struct metadata_t {</CodeLine>
+<CodeLine>   void clear();</CodeLine>
+<CodeLine>   metadata_t () {clear();}</CodeLine>
+<CodeLine>   text_t metaname;</CodeLine>
+<CodeLine>   mcommand_t metacommand;</CodeLine>
+<CodeLine>   pcommand_t parentcommand;</CodeLine>
+<CodeLine>   text_t parentoptions;</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine>// The decision component of an {If}{decision,true-text,false-text}</CodeLine>
+<CodeLine>// formatstring. The decision can be based on metadata or on text;</CodeLine>
+<CodeLine>// normally that text would be a macro like</CodeLine>
+<CodeLine>// _cgiargmode_.</CodeLine>
+<CodeLine>struct decision_t {</CodeLine>
+<CodeLine>   void clear();</CodeLine>
+<CodeLine>   decision_t () {clear();}</CodeLine>
+<CodeLine>   dcommand_t command;</CodeLine>
+<CodeLine>   metadata_t meta;</CodeLine>
+<CodeLine>   text_t text;</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine>struct format_t {</CodeLine>
+<CodeLine>   void clear();</CodeLine>
+<CodeLine>   format_t () {clear();}</CodeLine>
+<CodeLine>   command_t command;</CodeLine>
+<CodeLine>   decision_t decision;</CodeLine>
+<CodeLine>   text_t text;</CodeLine>
+<CodeLine>   metadata_t meta;</CodeLine>
+<CodeLine>   format_t *nextptr;</CodeLine>
+<CodeLine>   format_t *ifptr;</CodeLine>
+<CodeLine>   format_t *elseptr;</CodeLine>
+<CodeLine>   format_t *orptr;</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="1022">Ð¥ÐŸÑÑ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="greenstone_runtime_system"/> ÑÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐŸ ÐºÐ°Ðº ÐŸÑÐŽÐµÐ»ÑÐœÑÐ¹ ÐŸÐ±ÑÐµÐºÑ, Ð² ÐŽÐµÐ¹ÑÑÐ²ÐžÑÐµÐ»ÑÐœÐŸÑÑÐž ÐŸÐœÐŸ ÑÐŸÑÑÐ°Ð²Ð»ÑÐµÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÑÑÑÐºÑÑÑ ÐŽÐ°ÐœÐœÑÑ
+ Ðž ÑÑÐœÐºÑÐžÐ¹. ÐÐœÐž ÑÐŸÐ±ÑÐ°ÐœÑ Ð²ÐŒÐµÑÑÐµ Ð¿ÐŸÐŽ ÑÐ°Ð¹Ð»ÐŸÐŒ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ° recpt/formattools.h. ÐÑÐœÐŸÐ²ÐœÑÐµ ÑÑÑÑÐºÑÑÑÑ ÐŽÐ°ÐœÐœÑÑ
+ Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÑ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="core_data_structures_in_format"/>.</Text>
+<Figure id="data_structures_built_for_sample_format_statement">
+<Title>
+<Text id="1023">Ð¡ÑÑÑÐºÑÑÑÑ ÐŽÐ°ÐœÐœÑÑ
+, ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ ÐŽÐ»Ñ Ð²ÑÐ±ÐŸÑÐºÐž ÐŸÐ¿ÐµÑÐ°ÑÐŸÑÐ° /ormutf</Text>
+</Title>
+<File width="395" height="152" url="images/Dev_Fig_090.png"/>
+</Figure>
+<Text id="1024">Ð­ÑÐŸÑ Ð¿ÑÐŸÑÐµÑÑ Ð»ÑÑÑÐµ Ð²ÑÐµÐ³ÐŸ ÐŸÐ±ÑÑÑÐœÐžÑÑ ÐœÐ° Ð¿ÑÐžÐŒÐµÑÐµ. ÐÐŸÐ³ÐŽÐ° ÐŸÐ¿ÐµÑÐ°ÑÐŸÑ Ð·Ð°ÐŽÐ°ÐœÐžÑ ÑÐŸÑÐŒÐ°ÑÐ°</Text>
+<CodeLine>format CL1Vlist</CodeLine>
+<Text id="1025" type="code">"[link][Title]{If}{[Creator], by [Creator]}[/link]} "</Text>
+<Text id="1026">ÑÐžÑÐ°ÐµÑÑÑ ÐžÐ· ÑÐ°Ð¹Ð»Ð° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐŸÐœ Ð°ÐœÐ°Ð»ÐžÐ·ÐžÑÑÐµÑÑÑ ÑÑÐœÐºÑÐžÑÐŒÐž Ð² formattools.cpp Ðž ÑÐŸÑÐŒÐžÑÑÐµÑ ÑÐ²ÑÐ·Ð°ÐœÐœÑÐµ ÑÑÑÑÐºÑÑÑÑ ÐŽÐ°ÐœÐœÑÑ
+, Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐœÑÐµ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="data_structures_built_for_sample_format_statement"/>.</Text>
+<Text id="1027">ÐÐœÐ°ÑÐµÐœÐžÐµ ÐŽÐ»Ñ gsdlhome ÐžÑÑ
+ÐŸÐŽÐžÑ ÐžÐ· gsdlsite.cfg, ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐœÐŸÐ³ÐŸ Ð² ÑÐŸÐŒ Ð¶Ðµ ÑÐ°ÐŒÐŸÐŒ ÐºÐ°ÑÐ°Ð»ÐŸÐ³Ðµ, ÑÑÐŸ Ðž CGI-Ð²ÑÐ¿ÐŸÐ»ÐœÑÐµÐŒÐ°Ñ library, ÑÐŸÐ³ÐŽÐ° ÐºÐ°Ðº GSDLHOME ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑÑÑ Ð·Ð°Ð¿ÑÑÐºÐŸÐŒ ÑÐºÑÐžÐ¿ÑÐ° setup, ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÐ±ÑÐ°ÑÐ°ÐµÑÑÑ Ðº ÐŽÑÑÐ³ÐŸÐŒÑ ÑÐ°Ð¹Ð»Ñ, ÑÐ°Ðº ÐºÐ°Ðº ÑÐµÑ
+ÐœÐžÑÐµÑÐºÐž ÑÑÐŸ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ ÐŽÐ»Ñ ÐŽÐ²ÑÑ
+ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹. Ð¥ÐŸÑÑ ÑÑÐŸ Ðž Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ, ÐœÐŸ Ð²ÑÐµ Ð¶Ðµ ÐœÐµ Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÐŸ, Ðž Ð²ÑÐµ Ð²ÑÑÐµÑÐºÐ°Ð·Ð°ÐœÐœÐŸÐµ ÐœÐ°Ð¿ÐžÑÐ°ÐœÐŸ Ð² Ð¿ÑÐµÐŽÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÐž, ÑÑÐŸ ÑÐ°Ð¹Ð»Ñ ÑÐµ Ð¶Ðµ ÑÐ°ÐŒÑÐµ. ÐÐŸÐ³ÐŽÐ° ÐŸÐ¿ÐµÑÐ°ÑÐŸÑ Ð·Ð°ÐŽÐ°ÐœÐžÑ ÑÐŸÑÐŒÐ°ÑÐ° ÐŽÐŸÐ»Ð¶ÐµÐœ Ð±ÑÑÑ ÐŸÑÐµÐœÐµÐœ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµÐŒ, ÑÑÑÑÐºÑÑÑÐ° ÐŽÐ°ÐœÐœÑÑ
+ Ð¿ÐµÑÐµÑÐµÐºÐ°ÐµÑÑÑ. ÐÐ°ÑÑÑÑÑ, Ð¿ÑÐµÐŽÐ¿ÑÐžÐœÑÑÑÐ¹ Ð² comIf  Ðž  comOr ÑÐ·Ð»Ð°Ñ
+, Ð·Ð°Ð²ÐžÑÐžÑ ÐŸÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÐºÐŸÑÐŸÑÑÐµ Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÑÑ Ð·Ð°Ð¿ÑÐŸÑ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ñ. ÐÐŽÐœÐŸ ÐŸÑÐ»ÐŸÐ¶ÐœÐµÐœÐžÐµ ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸ, ÐºÐŸÐ³ÐŽÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐœÐ°Ð¹ÐŽÐµÐœÑ, ÐŸÐœÐž ÐŒÐŸÐ³ÑÑ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð¿ÐŸÑÐ»ÐµÐŽÑÑÑÐžÐµ ÐŒÐ°ÐºÑÐŸÑÑ Ðž ÑÐŸÑÐŒÐ°Ñ ÑÐžÐœÑÐ°ÐºÑÐžÑÐ°. ÐÑÐž ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÐž ÑÑÐŸ ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑÑÑ Ð¿ÐµÑÐµÐºÐ»ÑÑÐµÐœÐžÐŒ ÐœÐ°Ð·Ð°ÐŽ Ðž Ð²Ð¿ÐµÑÐµÐŽ ÐŒÐµÐ¶ÐŽÑ ÑÐžÐœÑÐ°ÐºÑÐžÑÐµÑÐºÐžÐŒ Ð°ÐœÐ°Ð»ÐžÐ·ÐŸÐŒ Ðž ÐŸÑÐµÐœÐºÐŸÐ¹, ÐºÐ°Ðº ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ.</Text>
+</Content>
+</Subsection>
+<Subsection id="macro_language">
+<Title>
+<Text id="1028">ÐÐ°ÐºÑÐŸÑÐ·ÑÐº</Text>
+</Title>
+<Content>
+<Text id="1029">Macro Language, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐœÑÐ¹ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="greenstone_runtime_system"/>, ÑÐ°Ðº Ð¶Ðµ, ÐºÐ°Ðº Format ÐœÐµ ÑÐ²Ð»ÑÐµÑÑÑ ÑÑÐœÐºÑÐžÐµÐ¹ ÐŸÐŽÐœÐŸÐ³ÐŸ ÐºÐ»Ð°ÑÑÐ° C++. Ð ÑÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ - ÑÑÐŸ ÐŸÑÐœÐŸÐ²ÐœÐŸÐ¹ ÐºÐ»Ð°ÑÑ, ÐœÐŸ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ ÐŒÐ°ÐºÑÐŸÑÐ·ÑÐºÐ° ÑÐ°ÐºÐ¶Ðµ Ð²ÑÐ·ÑÐ²Ð°ÐµÑ ÑÑÐœÐºÑÐžÐž Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐž Ðž ÐºÐ»Ð°ÑÑÑ.</Text>
+<Text id="1030">Ð ÑÐœÐŸÐ²Ð° Ð² ÐŸÐ±ÑÑÑÐœÐµÐœÐžÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒ Ð¿ÑÐžÐŒÐµÑ. Ð¡ÐœÐ°ÑÐ°Ð»Ð° ÐŒÑ ÐŽÐ°ÐµÐŒ ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÑÐžÐ¿ÐŸÐ²ÑÐµ ÐŒÐ°ÐºÑÐŸÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ, ÐºÐŸÑÐŸÑÑÐµ ÐžÐ»Ð»ÑÑÑÑÐžÑÑÑÑ ÐŒÐ°ÐºÑÐŸÑÑÐ°ÑÑÐžÐœÑÑÐ²ÐŸ, Ð·Ð°ÑÐµÐŒ, Ð¿ÑÐž Ð¿ÐŸÐŒÐŸÑÐž ÐŽÐžÐ°Ð³ÑÐ°ÐŒÐŒÑ, ÐŒÑ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÐŒ ÐŸÑÐœÐŸÐ²ÐœÑÐµ ÑÑÑÑÐºÑÑÑÑ ÐŽÐ°ÐœÐœÑÑ
+, ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ, ÑÑÐŸÐ±Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶Ð°ÑÑ ÑÑÑ ÐŽÐµÑÑÐµÐ»ÑÐœÐŸÑÑÑ. ÐÐ°ÐºÐŸÐœÐµÑ, ÐŒÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÐŒ Ðž ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÐŒ ÐŸÑÐºÑÑÑÑÐµ ÑÑÐœÐºÑÐžÐž-ÑÐ»ÐµÐœÑ displayclass, ÐŒÐ°ÐºÑÐŸÐŸÐ±ÑÐµÐºÑÐ° Ð²ÐµÑÑ
+ÐœÐµÐ³ÐŸ ÑÑÐŸÐ²ÐœÑ.</Text>
+<Figure id="illustration_of_macro_precedence">
+<Title>
+<Text id="1031">ÐÐ»Ð»ÑÑÑÑÐ°ÑÐžÑ ÐŒÐ°ÐºÑÐŸ ÑÑÐ°ÑÑÐžÐœÑÑÐ²Ð°</Text>
+</Title>
+<CodeLine>package query</CodeLine>
+<CodeLine>_header_ []         {_querytitle_}</CodeLine>
+<CodeLine>_header_ [l=en]     {Search page}</CodeLine>
+<CodeLine>_header_ [c=demo]   {&lt;table bgcolor=green&gt;&lt;tr&gt;&lt;td&gt;_querytitle_&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;}</CodeLine>
+<CodeLine>_header_ [v=1]      {_textquery_}</CodeLine>
+<CodeLine>_header_ [l=fr,v=1,c=hdl] {HDL Page de recherche}</CodeLine>
+</Figure>
+<Text id="1032">Ð ÑÐžÐ¿ÐžÑÐœÐŸÐ¹ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž Greenstone, ÐŒÐ°ÐºÑÐŸÑÑÐ°ÑÑÐžÐœÑÑÐ²ÐŸ ÐŸÐ±ÑÑÐœÐŸ: Ñ (ÐŽÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž) ÐžÐŒÐµÐµÑ Ð¿ÑÐžÐŸÑÐžÑÐµÑ ÐœÐ°ÐŽ v (ÐŽÐ»Ñ Ð³ÑÐ°ÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐžÐ»Ðž ÑÐµÐºÑÑÐŸÐ²ÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°), ÐºÐŸÑÐŸÑÑÐ¹ ÐžÐŒÐµÐµÑ Ð¿ÑÐžÐŸÑÐžÑÐµÑ ÐœÐ°ÐŽ / (ÐŽÐ»Ñ ÑÐ·ÑÐºÐ°). Ð­ÑÐŸ ÐŽÐŸÑÑÐžÐ³Ð°ÐµÑÑÑ ÑÑÑÐŸÐºÐŸÐ¹</Text>
+<CodeLine>macroprecedence c,v,l</CodeLine>
+<Text id="1033">Ð² ÐŸÑÐœÐŸÐ²ÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž main.cfg. ÐÐ°ÐºÑÐŸÐžÐœÑÑÑÑÐºÑÐžÐž ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="illustration_of_macro_precedence"/> ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ ÑÐžÐ¿ÐŸÐ²ÐŸÐ¹ ÐŒÐ°ÐºÑÐŸÑ ÐŽÐ»Ñ _header_ Ð² Ð¿Ð°ÐºÐµÑÐµ Ð·Ð°Ð¿ÑÐŸÑÐ° ÐŽÐ»Ñ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ² ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž Ñ, v Ðž /. ÐÑÐ»Ðž CGI -Ð°ÑÐ³ÑÐŒÐµÐœÑ Ð·Ð°ÐŽÐ°Ðœ, ÐºÐŸÐ³ÐŽÐ° Ð²ÑÐ·Ð²Ð°ÐœÐœÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ Ð²ÐºÐ»ÑÑÐ°ÐµÑ c=dls, v=l Ðž 1=ÐµÐ¿, ÐŒÐ°ÐºÑÐŸÐºÐŸÐŒÐ°ÐœÐŽÐ° Jieader _ [v=l] Ð±ÑÐ»Ð° Ð±Ñ Ð²ÑÐ±ÑÐ°ÐœÐ° ÐŽÐ»Ñ ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ. ÐÐœÐ° Ð±ÑÐ»Ð° Ð±Ñ Ð²ÑÐ±ÑÐ°ÐœÐ° ÑÐ°ÐœÑÑÐµ of _content _ [1=ÐµÐ¿], Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ v ÐžÐŒÐµÐµÑ Ð±ÐŸÐ»ÐµÐµ Ð²ÑÑÐŸÐºÐžÐ¹ Ð¿ÑÐžÐŸÑÐžÑÐµÑ, ÑÐµÐŒ /. Ð ÐŒÐ°ÐºÑÐŸÐºÐŸÐŒÐ°ÐœÐŽÐ° _content_[l=fr, v=l, c=dls] ÐœÐµ Ð±ÑÐ»Ð° Ð±Ñ Ð²ÑÐ±ÑÐ°ÐœÐ° Ð²ÐŸÐŸÐ±ÑÐµ, Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ Ð¿Ð°ÑÐ°ÐŒÐµÑÑ / ÐŽÐ»Ñ ÑÑÑÐ°ÐœÐžÑÑ Ð·Ð°ÐŽÐ°Ðœ ÑÐŸÐ²ÑÐµÐŒ ÐŽÑÑÐ³ÐŸÐ¹.</Text>
+<Figure id="data_structures_representing_the_default_macros">
+<Title>
+<Text id="1034">Ð¡ÑÑÑÐºÑÑÑÑ ÐŽÐ°ÐœÐœÑÑ
+, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÑÑÐžÐµ ÐŒÐ°ÐºÑÐŸÑ, Ð·Ð°ÐŽÐ°ÐœÐœÑÐ¹ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ</Text>
+</Title>
+<File width="382" height="194" url="images/Dev_Fig_094.png"/>
+</Figure>
+<Text id="1035">Ð ÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="data_structures_representing_the_default_macros"/> Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐŸÑÐœÐŸÐ²ÐœÑÑ ÑÑÑÑÐºÑÑÑÑ ÐŽÐ°ÐœÐœÑÑ
+, ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐœÑÑ Ð¿ÑÐž ÑÑÐµÐœÐžÐž ÐŒÐ°ÐºÑÐŸÑÐ°Ð¹Ð»ÐŸÐ², ÑÐºÐ°Ð·Ð°ÐœÐœÑÑ
+ Ð² etc/main.cfg. ÐÐŸ ÑÑÑÐµÑÑÐ²Ñ, ÑÑÐŸ -Ð°ÑÑÐŸÑÐžÐ°ÑÐžÐ²ÐœÑÐ¹ ÐŒÐ°ÑÑÐžÐ² Ð°ÑÑÐŸÑÐžÐ°ÑÐžÐ²ÐœÑÑ
+ ÐŒÐ°ÑÑÐžÐ²ÐŸÐ² Ð°ÑÑÐŸÑÐžÐ°ÑÐžÐ²ÐœÑÑ
+ ÐŒÐ°ÑÑÐžÐ²ÐŸÐ². ÐÑÑÑÐžÐ¹ ÑÑÐŸÐ²ÐµÐœÑ (Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐœÑÐ¹ ÑÐ»ÐµÐ²Ð°) - ÑÑÐŸ ÐžÐœÐŽÐµÐºÑÑ, ÐºÐŸÑÐŸÑÑÐµ ÑÐ¿Ð°ÐºÐŸÐ²ÑÐ²Ð°ÑÑ ÐŒÐ°ÐºÑÐŸÐºÐŸÐŒÐ°ÐœÐŽÑ, Ð²ÑÐŸÑÐŸÐ¹ ÑÑÐŸÐ²ÐµÐœÑ ÐžÐœÐŽÐµÐºÑÐžÑÑÐµÑ ÐŒÐ°ÐºÑÐŸÐžÐŒÑ. ÐÐŸÐœÐµÑÐœÑÐ¹ ÑÑÐŸÐ²ÐµÐœÑ ÐžÐœÐŽÐµÐºÑÐžÑÑÐµÑ Ð»ÑÐ±ÑÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ, ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐ»Ðž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÑ, ÑÐŸÑ
+ÑÐ°ÐœÑÑ ÐºÐ°Ð¶ÐŽÑÐ¹ ÐºÐ°Ðº ÑÐžÐ¿ mvalue, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐŸÐ·ÐŽÐ°ÐµÑ Ð·Ð°Ð¿ÐžÑÑ, ÐœÐ°ÑÑÐŽÑ Ñ ÐŒÐ°ÐºÑÐŸÐ·ÐœÐ°ÑÐµÐœÐžÐµÐŒ, ÑÐ°Ð¹Ð»Ð°, ÐžÐ· ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ ÐŸÐœÐŸ ÐžÑÑ
+ÐŸÐŽÐžÐ»ÐŸ. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÐµÐºÑÑ, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐ¹ ÐŽÐ»Ñ Jieader _ [1=ÐµÐ¿] ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="illustration_of_macro_precedence"/> ÐŒÐŸÐ¶ÐœÐŸ ÑÐ²ÐžÐŽÐµÑÑ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐœÑÐŒ ÐœÐžÐ¶Ðµ ÐŽÐ²ÑÑ
+ Ð·Ð°Ð¿ÐžÑÐµÐ¹ mvalue ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="data_structures_representing_the_default_macros"/>.</Text>
+<Figure id="displayclass_api">
+<Title>
+<Text id="1036"><i>Displayclass</i> API (ÑÐŸÐºÑÐ°ÑÐµÐœÐœÑÐ¹ Ð²Ð°ÑÐžÐ°ÐœÑ)</Text>
+</Title>
+<CodeLine>class displayclass</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>public:</CodeLine>
+<CodeLine>   displayclass ();</CodeLine>
+<CodeLine>   ~displayclass ();</CodeLine>
+<CodeLine>   int isdefaultmacro (text_t package, const text_t &amp;macroname);</CodeLine>
+<CodeLine>   int setdefaultmacro (text_t package, const text_t &amp;macroname,  </CodeLine>
+<CodeLine>         text_t params, const text_t &amp;macrovalue);</CodeLine>
+<CodeLine>   int loaddefaultmacros (text_t thisfilename);</CodeLine>
+<CodeLine>   void openpage (const text_t &amp;thispageparams,</CodeLine>
+<CodeLine>         const text_t &amp;thisprecedence);</CodeLine>
+<CodeLine>   void setpageparams (text_t thispageparams,</CodeLine>
+<CodeLine>         text_t thisprecedence);</CodeLine>
+<CodeLine>   int setmacro (const text_t &amp;macroname,</CodeLine>
+<CodeLine>         text_t package,</CodeLine>
+<CodeLine>         const text_t &amp;macrovalue);</CodeLine>
+<CodeLine>   void expandstring (const text_t &amp;inputtext, text_t &amp;outputtext);</CodeLine>
+<CodeLine>   void expandstring (text_t package, const text_t &amp;inputtext,</CodeLine>
+<CodeLine>         text_t &amp;outputtext, int recursiondepth = 0);</CodeLine>
+<CodeLine>   void setconvertclass (outconvertclass *theoutc) {outc = theoutc;}</CodeLine>
+<CodeLine>   outconvertclass *getconvertclass () {return outc;}</CodeLine>
+<CodeLine>   ostream *setlogout (ostream *thelogout);</CodeLine>
+<CodeLine>};</CodeLine>
+</Figure>
+<Text id="1037">ÐŠÐµÐœÑÑÐ°Ð»ÑÐœÑÐ¹ ÐŸÐ±ÑÐµÐºÑ, ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÑ ÐŒÐ°ÐºÑÐŸÑÐ·ÑÐº - displayclass, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐ¹ Ð² lib/display, h. ÐÐ³ÐŸ ÐŸÑÐºÑÑÑÑÐµ ÑÑÐœÐºÑÐžÐž-ÑÐ»ÐµÐœÑ Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÑ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="displayclass_api"/>. ÐÐ»Ð°ÑÑ ÑÐžÑÐ°ÐµÑ ÑÐºÐ°Ð·Ð°ÐœÐœÑÐµ ÐŒÐ°ÐºÑÐŸÑÐ°Ð¹Ð»Ñ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ loaddefaultmacros (), ÑÐŸÑ
+ÑÐ°ÐœÑÑ Ð² Ð·Ð°ÑÐžÑÐµÐœÐœÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐºÐ»Ð°ÑÑÐ° (ÐœÐµ Ð¿ÐŸÐºÐ°Ð·Ð°Ðœ) ÑÐžÐ¿ ÑÑÑÑÐºÑÑÑÑ ÐŽÐ°ÐœÐœÑÑ
+, Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐœÐŸÐ¹ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="data_structures_representing_the_default_macros"/>. ÐÐ»Ñ ÐŒÐ°ÐºÑÐŸÑÐ° ÑÐ°ÐºÐ¶Ðµ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÐŸ Ð±ÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐœÑÐŒ ÑÐžÑÑÐµÐŒÐŸÐ¹ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐž Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ setmacro () (Ð² Ð¿ÐŸÑÐ»ÐµÐŽÐœÐµÐŒ Ð¿ÑÐžÐŒÐµÑÐµ Ð Ð°Ð·ÐŽÐµÐ»Ð° <CrossRef target="Section" ref="how_the_conceptual_framework_fits_together"/>, pageaction ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑ _homeextra_ ÐºÐ°Ðº ÐŽÐžÐœÐ°ÐŒÐžÑÐµÑÐºÐž ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐœÑÑ ÑÐ°Ð±Ð»ÐžÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÑÑÑ ÑÑÐœÐºÑÐžÑ). Ð­ÑÐŸ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÑÑÑ ÐœÐ°Ð±ÐŸÑÐŸÐŒ Ð°ÑÑÐŸÑÐžÐ°ÑÐžÐ²ÐœÑÑ
+ ÐŒÐ°ÑÑÐžÐ²ÐŸÐ², Ð¿ÐŸÐŽÐŸÐ±ÐœÑÑ
+ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐŒ ÐŽÐ»Ñ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐŒÐ°ÐºÑÐŸÑÐ°Ð¹Ð»ÐŸÐ² (ÐŸÐœÐž ÐœÐµ ÐžÐŽÐµÐœÑÐžÑÐœÑ, Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ Ð² Ð¿ÐµÑÐ²ÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ ÐœÐµ ÑÑÐµÐ±ÑÐµÑÑÑ ÑÑÐŸÐ²ÐµÐœÑ "Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐ°"). Ð displayclass ÑÑÐµÐœÐžÐµ ÐŒÐ°ÐºÑÐŸÑÐ° ÐžÐ· ÑÐ°Ð¹Ð»Ð° ÑÐ¿ÐŸÐŒÐžÐœÐ°ÐµÑÑÑ ÐºÐ°Ðº default macros. ÐÐŸÐºÐ°Ð»ÑÐœÑÐ¹ ÐŒÐ°ÐºÑÐŸÑ, ÑÐºÐ°Ð·Ð°ÐœÐœÑÐ¹ ÑÐµÑÐµÐ· setmacro (), ÑÐ¿ÐŸÐŒÐžÐœÐ°ÐµÑÑÑ ÐºÐ°Ðº current macros Ðž ÑÐŽÐ°Ð»ÑÐµÑÑÑ ÐžÐ· Ð¿Ð°ÐŒÑÑÐž, ÐºÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÑÑÑÐ°ÐœÐžÑÐ° Ð±ÑÐ»Ð° ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐ°.</Text>
+<Text id="1038">ÐÐŸÐ³ÐŽÐ° ÑÑÑÐ°ÐœÐžÑÐ° ÐŽÐŸÐ»Ð¶ÐœÐ° Ð±ÑÑÑ Ð²ÐŸÑÐ¿ÑÐŸÐžÐ·Ð²ÐµÐŽÐµÐœÐ°, ÑÐœÐ°ÑÐ°Ð»Ð° Ð²ÑÐ·ÑÐ²Ð°ÐµÑÑÑ openpage Ð, ÑÑÐŸÐ±Ñ ÑÐŸÐŸÐ±ÑÐžÑÑ ÑÐµÐºÑÑÐžÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ² ÑÑÑÐ°ÐœÐžÑÑ (1=ÐµÐ¿ Ðž ÑÐ°Ðº ÐŽÐ°Ð»ÐµÐµ). Ð¡Ð»ÐµÐŽÐŸÐŒ, ÑÐµÐºÑÑ Ðž ÐŒÐ°ÐºÑÐŸÑ Ð¿ÐŸÑÐŸÐºÐŸÐ²ÐŸ Ð¿ÑÐŸÑ
+ÐŸÐŽÑÑ ÑÐµÑÐµÐ· ÐºÐ»Ð°ÑÑ, ÐŸÐ±ÑÑÐœÐŸ Ñ actionclass, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÑÑÑÐŸÐºÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ:</Text>
+<CodeLine>cout &lt;&lt; text_t2ascii &lt;&lt; display &lt;&lt; "_amacro_ "</CodeLine>
+<CodeLine>         &lt;&lt; "_anothermacro_ ";</CodeLine>
+<Text id="1039">Ð ÐµÐ·ÑÐ»ÑÑÐ°Ñ - ÐŒÐ°ÐºÑÐŸÑ, ÑÐ°ÑÑÐžÑÐµÐœÐœÑÐ¹ ÑÐŸÐ³Ð»Ð°ÑÐœÐŸ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐ°ÐŒ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ² ÑÑÑÐ°ÐœÐžÑÑ. ÐÑÐ»Ðž ÑÑÐµÐ±ÑÐµÑÑÑ, ÑÑÐž Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŸÑÑÐ°ÑÑÐž ÐžÐ·ÐŒÐµÐœÐµÐœÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ setpageparams(). ÐÑÑÐ°ÑÑÐžÐµÑÑ ÐŸÑÐºÑÑÑÑÐµ ÑÑÐœÐºÑÐžÐž-ÑÐ»ÐµÐœÑ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÑÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ Ð±ÐŸÐ»ÐµÐµ ÐœÐžÐ·ÐºÐŸÐ³ÐŸ ÑÑÐŸÐ²ÐœÑ.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_receptionist_code">
+<Title>
+<Text id="1040">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÐ°</Text>
+</Title>
+<Content>
+<Text id="1041">ÐÑÐœÐŸÐ²ÐœÑÐµ ÐŸÐ±ÑÐµÐºÑÑ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÐ° Ð±ÑÐ»Ðž ÐŸÐ¿ÐžÑÐ°ÐœÑ. ÐÐžÐ¶Ðµ ÐŒÑ ÐŽÐµÑÐ°Ð»ÐžÐ·ÐžÑÑÐµÐŒ ÐºÐ»Ð°ÑÑÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐž, ÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÑÑÐŸÑÐœÐœÐŸ ÐœÐ°Ñ
+ÐŸÐŽÑÑÑÑ Ð² GSDLHOME/SRC/RECPT. ÐÑÐŸÐŒÐµ ÑÐŸÐ³ÐŸ, ÑÐ°ÐŒ Ð³ÐŽÐµ Ð³Ð»Ð°Ð²ÐœÑÐŒ ÑÐ²Ð»ÑÐµÑÑÑ ÑÑÑÐµÐºÑÐžÐ²ÐœÐŸÑÑÑ, ÐºÐŸÐ³ÐŽÐ° ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ Ð²ÑÑÑÐŸÐµÐœÑ, Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸÑÑÐž Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑÑ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐºÐŸÐ¿ÐžÐž ÑÐ°Ð¹Ð»Ð° Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ° .ÑÑÑ. Ð€Ð°Ð¹Ð»Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐž ÑÐ°ÑÑÐŸ Ð²ÐºÐ»ÑÑÐ°ÑÑ ÑÐ»ÐŸÐ²ÐŸ tool ÐºÐ°Ðº ÑÐ°ÑÑÑ ÐžÐŒÐµÐœÐž ÑÐ°Ð¹Ð»Ð°, ÐºÐ°Ðº Ð² OIDtools.h nformattools.h.</Text>
+<Text id="1042">ÐÑÐŸÑÐŸÐ¹ ÐœÐ°Ð±ÐŸÑ Ð»ÐµÐºÑÐžÑÐµÑÐºÐž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð¿ÑÐµÑÐžÐºÑ z3950. Ð€Ð°Ð¹Ð»Ñ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÑÑ ÑÐŽÐ°Ð»ÐµÐœÐœÑÐ¹ ÐŽÐŸÑÑÑÐ¿ Ðº ÐžÐœÑÐµÑÐ°ÐºÑÐžÐ²ÐœÑÐŒ Ð±Ð°Ð·Ð°ÐŒ ÐŽÐ°ÐœÐœÑÑ
+ Ðž ÐºÐ°ÑÐ°Ð»ÐŸÐ³Ð°ÐŒ, ÐºÐŸÑÐŸÑÑÐµ ÐŽÐµÐ»Ð°ÑÑ ÐžÑ
+ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ ÐŸÐ±ÑÐµÐŽÐŸÑÑÑÐ¿ÐœÑÐŒ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Ð¿ÑÐŸÑÐŸÐºÐŸÐ» Z39.50 .</Text>
+<Text id="1043">ÐÑÑÐ³Ð°Ñ Ð±ÐŸÐ»ÑÑÐ°Ñ Ð³ÑÑÐ¿Ð¿Ð° ÑÐ°Ð¹Ð»ÐŸÐ² Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐž Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÑÐµÑÐŒÐžÐœ browserclass. Ð­ÑÐŸ ÑÐ°Ð¹Ð»Ñ, ÑÐ²ÑÐ·Ð°ÐœÐœÑÐµ ÑÐµÑÐµÐ· Ð²ÐžÑÑÑÐ°Ð»ÑÐœÑÑ ÐžÐµÑÐ°ÑÑ
+ÐžÑ ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐžÑ. ÐÐ°Ðº Ð³ÑÑÐ¿Ð¿Ð°, ÐŸÐœÐž Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑ Ð°Ð±ÑÑÑÐ°ÐºÑÐœÐŸÐµ Ð¿ÐŸÐœÑÑÐžÐµ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°: Ð¿ÐŸÑÐ»ÐµÐŽÐŸÐ²Ð°ÑÐµÐ»ÑÐœÐ°Ñ Ð³ÐµÐœÐµÑÐ°ÑÐžÑ ÑÑÑÐ°ÐœÐžÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐœÐŸÐ³ÐŸ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµÐŒ ÐžÐ»Ðž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž. ÐÑÐŸÑÐŒÐ°ÑÑÐžÐ²Ð°ÑÑÐžÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð¿ÑÐŸÑÐŒÐŸÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÑÐ¿ÐŸÑÑÐŽÐŸÑÐµÐœÐœÑÑ
+ Ð² Ð°Ð»ÑÐ°Ð²ÐžÑÐœÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐž Ñ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐŸÐŒ ÐžÐ»Ðž Ñ
+ÑÐŸÐœÐŸÐ»ÐŸÐ³ÐžÑÐµÑÐºÐž Ð¿ÐŸ Ð²ÑÐµÐŒÐµÐœÐž; ÑÐ°Ð·Ð²ÐžÑÐžÐµ ÑÐµÑÐµÐ· Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐž, Ð²ÐŸÐ·Ð²ÑÐ°ÑÐµÐœÐœÑÐµ Ð·Ð°Ð¿ÑÐŸÑÐŸÐŒ, - ÐŽÐµÑÑÑÑ Ð²Ñ
+ÐŸÐŽÐŸÐ² ÐŸÐŽÐœÐŸÐ²ÑÐµÐŒÐµÐœÐœÐŸ; ÐŽÐŸÑÑÑÐ¿ Ðº ÐŸÑÐŽÐµÐ»ÑÐœÑÐŒ ÑÑÑÐ°ÐœÐžÑÐ°ÐŒ ÐºÐœÐžÐ³Ðž, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐŒÐµÑ
+Ð°ÐœÐžÐ·ÐŒ "go to page" (Ð¿ÐµÑÐµÐ¹ÑÐž Ðº ÑÑÑÐ°ÐœÐžÑÐµ) . ÐÐ°Ð¶ÐŽÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐŸ ÐŸÑ Ð±Ð°Ð·ÐŸÐ²ÐŸÐ³ÐŸ ÐºÐ»Ð°ÑÑÐ° browserclass:</Text>
+<BulletList>
+<Bullet>
+<Text id="1044"><i>datelistbrowserclass</i> ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ Ñ
+ÑÐŸÐœÐŸÐ»ÐŸÐ³ÐžÑÐµÑÐºÐžÐŒ ÑÐ¿ÐžÑÐºÐ°ÐŒ;</Text>
+</Bullet>
+<Bullet>
+<Text id="1045"><i>hlistbrowserclass</i> ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ Ð³ÐŸÑÐžÐ·ÐŸÐœÑÐ°Ð»ÑÐœÑÐŒ ÑÐ¿ÐžÑÐºÐ°ÐŒ;</Text>
+</Bullet>
+<Bullet>
+<Text id="1046"><i>htmlbrowserclass</i> ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ ÑÑÑÐ°ÐœÐžÑÐ°ÐŒ HTML;</Text>
+</Bullet>
+<Bullet>
+<Text id="1047"><i>invbrowserclass</i> ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ ÐœÐµÐ²ÐžÐŽÐžÐŒÑÐŒ ÑÐ¿ÐžÑÐºÐ°ÐŒ;</Text>
+</Bullet>
+<Bullet>
+<Text id="1048"><i>pagedbrowserclass</i> ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ ÐŒÐµÑ
+Ð°ÐœÐžÐ·ÐŒÐ° "go to page" (Ð¿ÐµÑÐµÐ¹ÑÐž Ðº ÑÑÑÐ°ÐœÐžÑÐµ);</Text>
+</Bullet>
+<Bullet>
+<Text id="1049"><i>vlistbrowserclass</i> ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ Ð²ÐµÑÑÐžÐºÐ°Ð»ÑÐœÑÐŒ ÑÐ¿ÐžÑÐºÐ°ÐŒ.</Text>
+</Bullet>
+</BulletList>
+<Text id="1050">ÐÐµÐ¹ÑÑÐ²ÐžÑ ÐŸÐ±ÑÐ°ÑÐ°ÑÑÑÑ Ðº ÐŸÐ±ÑÐµÐºÑÐ°ÐŒ browserclass ÑÐµÑÐµÐ· <i>browsetools.h</i>.</Text>
+<Table class="hidden">
+<Title/>
+<TableContent>
+<tr>
+<th width="140">
+<Text id="1051"><b>OIDtools.h</b></Text>
+</th>
+<th width="390">
+<Text id="1052">Ð€ÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÐ°Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐ° ÐŸÑÐµÐœÐºÐž ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ² ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ð¿ÐŸ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ñ.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1053"><b>action.h</b></Text>
+</th>
+<th width="390">
+<Text id="1054">ÐÐ°Ð·ÐŸÐ²ÑÐ¹ ÐºÐ»Ð°ÑÑ ÐŽÐ»Ñ ÐŸÐ±ÑÐµÐºÑÐ° Actions , ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐœÐŸÐ³ÐŸ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="greenstone_runtime_system"/>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1055"><b>authenaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1056">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ ÐŽÐ»Ñ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐž Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1057"><b>browserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1058">ÐÐ°Ð·ÐŸÐ²ÑÐ¹ ÐºÐ»Ð°ÑÑ ÐŽÐ»Ñ ÑÐµÐ·ÑÐŒÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1059"><b>browsetools.h</b></Text>
+</th>
+<th width="390">
+<Text id="1060">Ð€ÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÐ°Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐ°, ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÐ±ÑÐ°ÑÐ°ÐµÑÑÑ Ðº ÐžÐµÑÐ°ÑÑ
+ÐžÐž browserclass. Ð€ÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž Ð²ÐºÐ»ÑÑÐ°ÑÑ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµ Ðž Ð·Ð°ÐºÐ»ÑÑÐµÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐ³ÐŸ, Ð²ÑÐ²ÐŸÐŽÐ° ÐŸÐ³Ð»Ð°Ð²Ð»ÐµÐœÐžÑ Ðž ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐŒÐµÑ
+Ð°ÐœÐžÐ·ÐŒÐ° ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ ÑÐžÐ¿Ð° "go to page" (Ð¿ÐµÑÐµÐ¹ÑÐž Ðº ÑÑÑÐ°ÐœÐžÑÐµ).</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1061"><b>cgiargs.h</b></Text>
+</th>
+<th width="390">
+<Text id="1062">ÐÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ <i>cgiarginfo</i> ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐ¹ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="using_the_cgiargsinfoclass_from_pageactioncpp"/>, Ð¿ÑÐž Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐµ ÑÑÑÑÐºÑÑÑÑ ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐ»Ñ CGI-Ð°ÑÐ³ÑÐŒÐµÐœÑÐŸÐ².</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1063"><b>cgiutils.h</b></Text>
+</th>
+<th width="390">
+<Text id="1064">Ð€ÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÐ°Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐ° CGI-Ð°ÑÐ³ÑÐŒÐµÐœÑÐŸÐ², ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÑÑÑÑÐºÑÑÑÑ ÐŽÐ°ÐœÐœÑÑ
+, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐµ Ð² <i>cgiargs.h</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1065"><b>cgiwrapper.h</b></Text>
+</th>
+<th width="390">
+<Text id="1066">Ð€ÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÐ°Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐ°, ÐºÐŸÑÐŸÑÐ°Ñ ÐŽÐµÐ»Ð°ÐµÑ Ð²ÑÐµ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÐµ ÐŽÐ»Ñ Ð²ÑÐ²ÐŸÐŽÐ° ÑÑÑÐ°ÐœÐžÑÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ CGI-Ð¿ÑÐŸÑÐŸÐºÐŸÐ». ÐÐŸÑÑÑÐ¿ ÑÐµÑÐµÐ· ÑÑÐœÐºÑÐžÑ</Text>
+<CodeLine>void cgiwrapper (receptionist &amp;recpt, text_t collection);</CodeLine>
+<Text id="1067">ÐºÐŸÑÐŸÑÐ°Ñ ÑÐ²Ð»ÑÐµÑÑÑ ÐµÐŽÐžÐœÑÑÐ²ÐµÐœÐœÐŸÐ¹ ÑÑÐœÐºÑÐžÐµÐ¹, ÐŸÐ±ÑÑÐ²Ð»ÐµÐœÐœÐŸÐ¹ Ð² ÑÐ°Ð¹Ð»Ðµ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ°. ÐÑÐµ ÐŸÑÑÐ°Ð»ÑÐœÑÐµ ÑÑÐœÐºÑÐžÐž - .ÑÑÑ ÐºÐŸÐ¿ÐžÐž, Ð»ÐµÐºÑÐžÑÐµÑÐºÐž ÐŸÐ³ÑÐ°ÐœÐžÑÐµÐœÐœÑÐµ, ÑÑÐŸÐ±Ñ Ð±ÑÑÑ Ð»ÐŸÐºÐ°Ð»ÑÐœÑÐŒÐž Ð¿ÐŸ ÐŸÑÐœÐŸÑÐµÐœÐžÑ Ðº ÑÐ°Ð¹Ð»Ñ (ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐºÐ»ÑÑÐµÐ²ÐŸÐµ ÑÐ»ÐŸÐ²ÐŸ C++ static). ÐÑÐ»Ðž ÑÑÐœÐºÑÐžÑ Ð²ÑÐ¿ÐŸÐ»ÐœÑÐµÑÑÑ ÐŽÐ»Ñ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐŸÐ³ÐŽÐ° collection ÐŽÐŸÐ»Ð¶ÐœÐ° Ð±ÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ°, ÐžÐœÐ°ÑÐµ ÑÑÐŸ ÐŽÐŸÐ»Ð¶ÐœÐ° Ð±ÑÑÑ Ð¿ÑÑÑÐ°Ñ ÑÑÑÐŸÐºÐ° " ". ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ Fast-CGI.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1068"><b>collectoraction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1069">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ ÐŸÐ±Ð»ÐµÐ³ÑÐ°ÐµÑ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐºÐŸÐœÐµÑÐœÐŸÐ³ÐŸ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÑÐµÑÐµÐ· Collector. Ð¡Ð³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐœÐ°Ñ ÑÑÑÐ°ÐœÐžÑÐ° ÐžÑÑ
+ÐŸÐŽÐžÑ ÐžÐ· collect.dm Ðž ÑÐ¿ÑÐ°Ð²Ð»ÑÐµÑÑÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐŒ CGI -Ð°ÑÐ³ÑÐŒÐµÐœÑÐ° p=page.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1070"><b>comtypes.h</b></Text>
+</th>
+<th width="390">
+<Text id="1071">ÐÑÐœÐŸÐ²ÐœÑÐµ ÑÐžÐ¿Ñ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»ÐŸÐ².</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1072"><b>converter.h</b></Text>
+</th>
+<th width="390">
+<Text id="1073">ÐÐ±ÑÐµÐºÑÐœÐ°Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐ° Ð¿ÐŸÑÐŸÐºÐŸÐ²ÑÐŒ ÐºÐŸÐœÐ²ÐµÑÑÐµÑÐ°ÐŒ.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1074"><b>datelistbrowserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1075">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŸÑ browserclass, ÑÑÐŸÑ ÐŸÐ±ÑÐµÐºÑ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° Ñ
+ÑÐŸÐœÐŸÐ»ÐŸÐ³ÐžÑÐµÑÐºÐžÑ
+ ÑÐ¿ÐžÑÐºÐŸÐ², ÑÐžÐ¿Ð° Ð²ÐžÐŽÐµÐœÐœÐŸÐ³ÐŸ ÐœÐ°ÐŒÐž ÑÐ°ÐœÐµÐµ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Greenstone Archives Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° Ð¿ÐŸ "ÐŽÐ°ÑÐ°ÐŒ" Ð² ÐœÐ°Ð²ÐžÐ³Ð°ÑÐžÐŸÐœÐœÐŸÐŒ ÐŒÐµÐœÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1076"><b>documentaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1077">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐŸÐµ ÐŽÐ»Ñ Ð²ÐŸÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÐžÐ»Ðž ÑÐ°ÑÑÐž ÐžÐµÑÐ°ÑÑ
+ÐžÐž ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐž.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1078"><b>extlinkaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1079">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ Ð¿ÑÐŸÐ²ÐµÑÑÐµÑ, ÐŽÐµÐ¹ÑÑÐ²ÐžÑÐµÐ»ÑÐœÐŸ Ð»Ðž Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐžÐŽÐµÑ Ð¿ÑÑÐŒÐŸ Ð¿ÐŸ Ð²ÐœÐµÑÐœÐµÐ¹ ÑÑÑÐ»ÐºÐµ ÐžÐ»Ðž Ð¿ÑÐŸÑ
+ÐŸÐŽÐžÑ ÑÐµÑÐµÐ· ÑÑÑÐ°ÐœÐžÑÑ Ð¿ÑÐµÐŽÑÐ¿ÑÐµÐ¶ÐŽÐµÐœÐžÑ, ÐŸÐ¿ÐŸÐ²ÐµÑÐ°ÑÑÑÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐŸ ÑÐŸÐŒ ÑÐ°ÐºÑÐµ, ÑÑÐŸ ÐŸÐœ ÑÐŸÐ±ÐžÑÐ°ÐµÑÑÑ Ð¿ÐŸÐºÐžÐœÑÑÑ ÑÐžÑÑÐŸÐ²ÑÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÑ ÑÐžÑÑÐµÐŒÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1080"><b>formattools.h</b></Text>
+</th>
+<th width="390">
+<Text id="1081">Ð€ÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÐ°Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐ° Ð°ÐœÐ°Ð»ÐžÐ·Ð° Ðž ÐŸÑÐµÐœÐºÐž ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŸÐ¿ÐµÑÐ°ÑÐŸÑÐ°ÐŒÐž/ormutf. ÐÐŸÐŽÑÐŸÐ±ÐœÐŸÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ Ð² Ð Ð°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Subsection" ref="formatting"/>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1082"><b>historydb.h</b></Text>
+</th>
+<th width="390">
+<Text id="1083">Ð¡ÑÑÑÐºÑÑÑÑ ÐŽÐ°ÐœÐœÑÑ
+ Ðž ÑÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÐ°Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐ° ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ Ð±Ð°Ð·ÐŸÐ¹ ÐŽÐ°ÐœÐœÑÑ
+ Ð¿ÑÐµÐŽÑÐŽÑÑÐžÑ
+ Ð·Ð°Ð¿ÑÐŸÑÐŸÐ², ÑÐ°Ðº ÑÑÐŸ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐŒÐŸÐ¶ÐµÑ Ð·Ð°Ð¿ÑÑÑÐžÑÑ ÐœÐŸÐ²ÑÐ¹ Ð·Ð°Ð¿ÑÐŸÑ, ÐºÐŸÑÐŸÑÑÐ¹ Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð¿ÑÐµÐŽÑÐŽÑÑÐžÐµ ÑÑÐ»ÐŸÐ²ÐžÑ Ð·Ð°Ð¿ÑÐŸÑÐ°.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1084"><b>hlistbrowserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1085">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŸÑ browserclass, ÑÑÐŸÑ ÐŸÐ±ÑÐµÐºÑ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° Ð³ÐŸÑÐžÐ·ÐŸÐœÑÐ°Ð»ÑÐœÑÑ
+ ÑÐ¿ÐžÑÐºÐŸÐ².</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1086"><b>htmlbrowserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1087">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŸÑ browserclass, ÑÑÐŸÑ ÐŸÐ±ÑÐµÐºÑ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÑÑÑÐ°ÐœÐžÑ HTML.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1088"><b>htmlgen.h</b></Text>
+</th>
+<th width="390">
+<Text id="1089">Ð€ÑÐœÐºÑÐžÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐž Ð¿ÐŸÐŽÑÐ²ÐµÑÐºÐž ÑÐµÑÐŒÐžÐœÐŸÐ² Ð·Ð°Ð¿ÑÐŸÑÐ° Ð² text_t ÑÑÑÐŸÐºÐµ.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1090"><b>htmlutils.h</b></Text>
+</th>
+<th width="390">
+<Text id="1091">Ð€ÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÐ°Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐ°, ÐºÐŸÑÐŸÑÐ°Ñ ÐºÐŸÐœÐ²ÐµÑÑÐžÑÑÐµÑ text_t ÑÑÑÐŸÐºÑ Ð² ÑÐºÐ²ÐžÐ²Ð°Ð»ÐµÐœÑÐœÑÐ¹ HTML. Ð¡ÐžÐŒÐ²ÐŸÐ»Ñ ", &amp;, &lt;, Ðž &gt; Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²ÑÐ²Ð°ÑÑÑÑ Ð² &quot;, &amp;Ð°ÑÑ;, &lt; Ðž &gt; ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸ.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1092"><b>infodbclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1093">ÐÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÐŽÐ²Ð° ÐºÐ»Ð°ÑÑÐ°: gdbmclass Ðž infodbclass. ÐÐµÑÐ²ÑÐ¹ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Greenstone API Ðº GDBM; Ð¿ÐŸÑÐ»ÐµÐŽÐœÐžÐ¹ - ÐŸÐ±ÑÐµÐºÑÐœÑÐ¹ ÐºÐ»Ð°ÑÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐ¹ ÐŽÐ»Ñ Ñ
+ÑÐ°ÐœÐµÐœÐžÑ Ð·Ð°Ð¿ÐžÑÐµÐ¹ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² ÑÑÐµÐœÐžÑ ÐžÐ· GDBM Ð±Ð°Ð·Ñ ÐŽÐ°ÐœÐœÑÑ
+, Ð° Ð¿ÐŸ ÑÑÑÐµÑÑÐ²Ñ - Ð°ÑÑÐŸÑÐžÐ°ÑÐžÐ²ÐœÑÐ¹ ÐŒÐ°ÑÑÐžÐ² ÐžÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐœÑÑ
+ ÑÐµÐ»ÑÐŒ ÑÐžÑÐ»ÐŸÐŒ ÐŒÐ°ÑÑÐžÐ²ÐŸÐ² text_t ÑÑÑÐŸÐº.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1094"><b>invbrowserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1095">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŸÑ browserclass, ÑÑÐŸÑ ÐŸÐ±ÑÐµÐºÑ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÑÐ¿ÐžÑÐºÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÐœÐµ Ð¿ÑÐµÐŽÐœÐ°Ð·ÐœÐ°ÑÐµÐœÑ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° (ÐœÐµÐ²ÐžÐŽÐžÐŒÑÐµ).</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1096"><b>nullproto.h</b></Text>
+</th>
+<th width="390">
+<Text id="1097">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŸÑ recptproto, ÑÑÐŸÑ ÐºÐ»Ð°ÑÑ Ð¿ÐŸÐœÐžÐŒÐ°ÐµÑ ÐœÑÐ»ÐµÐ²ÐŸÐ¹ Ð¿ÑÐŸÑÐŸÐºÐŸÐ», ÑÐµÐ°Ð»ÐžÐ·ÐŸÐ²Ð°ÐœÐœÑÐ¹ ÑÐµÑÐµÐ· ÑÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÑÐµ Ð·Ð°Ð¿ÑÐŸÑÑ ÐŸÑ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÐ° ÐœÐ° ÑÐµÑÐ²ÐµÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1098"><b>pageaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1099">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ Ð²ÐŒÐµÑÑÐµ Ñ ÐŒÐ°ÐºÑÐŸÑÐ°Ð¹Ð»ÐŸÐŒ, ÐœÐ°Ð·Ð²Ð°ÐœÐœÑÐŒ sp=page, Ð³ÐµÐœÐµÑÐžÑÑÐµÑ web-ÑÑÑÐ°ÐœÐžÑÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1100"><b>pagedbrowserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1101">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŸÑ browserclass, ÑÑÐŸÑ ÐŸÐ±ÑÐµÐºÑ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ ÐŒÐµÑ
+Ð°ÐœÐžÐ·ÐŒÐ° Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° "go to page" (Ð¿ÐµÑÐµÐ¹ÑÐž Ðº ÑÑÑÐ°ÐœÐžÑÐµ), ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, Ð² Gutenberg ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. </Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1102"><b>pingaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1103">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ Ð²ÑÑÑÐœÑÐµÑ, ÐŸÑÐ²ÐµÑÐ°ÐµÑ Ð»Ðž ÑÐ°ÑÑÐœÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1104"><b>queryaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1105">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ Ð±ÐµÑÐµÑ Ð¿ÑÐµÐŽÑÑÐŒÐŸÑÑÐµÐœÐœÑÐ¹ Ð·Ð°Ð¿ÑÐŸÑ, Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž Ðž Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÑ Ðž ÐžÑÐ¿ÐŸÐ»ÐœÑÐµÑ Ð¿ÐŸÐžÑÐº, Ð³ÐµÐœÐµÑÐžÑÑÑ Ð² ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐµ Ð¿ÐŸÐŽÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐŸ ÐŸ=Ð¿ÐžÑ, ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ, ÐœÐ°ÑÐžÐœÐ°ÑÑÐžÐŒÑÑ Ð² Ð¿ÐŸÐ·ÐžÑÐžÐž Ð³=Ð¿ÐžÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1106"><b>querytools.h</b></Text>
+</th>
+<th width="390">
+<Text id="1107">Ð€ÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÐ°Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐ° Ð·Ð°Ð¿ÑÐŸÑÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1108"><b>receptionist.h</b></Text>
+</th>
+<th width="390">
+<Text id="1109">ÐÐ±ÑÐµÐºÑ Ð²ÐµÑÑ
+ÐœÐµÐ³ÐŸ ÑÑÐŸÐ²ÐœÑ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÐ°. ÐÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÑ Ð·Ð°Ð¿ÐžÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž CGI-Ð°ÑÐ³ÑÐŒÐµÐœÑÐ°, ÑÐµÐ°Ð»ÐžÐ·Ð°ÑÐžÑ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÐŸÐ³ÐŸ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ, ÑÐµÐ°Ð»ÐžÐ·Ð°ÑÐžÑ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÐŸÐ³ÐŸ Ð±ÑÐŸÑÐ·ÐµÑÐ°, ÐŸÑÐœÐŸÐ²ÐœÐŸÐ¹ ÐŒÐ°ÐºÑÐŸÑÐ·ÑÐº ÐŸÐ±ÑÐµÐºÑÐ° displayclass Ðž Ð²ÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÐµ ÐºÐŸÐœÐ²ÐµÑÑÐµÑÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1110"><b>recptconfig.h</b></Text>
+</th>
+<th width="390">
+<Text id="1111">Ð€ÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÐ°Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐ° ÑÐžÑÐµÐœÐžÑ ÑÐ°Ð¹ÑÐ° Ðž ÐŸÑÐœÐŸÐ²ÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1112"><b>recptproto.h</b></Text>
+</th>
+<th width="390">
+<Text id="1113">ÐÐ°Ð·ÐŸÐ²ÑÐ¹ ÐºÐ»Ð°ÑÑ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð°.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1114"><b>statusaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1115">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ Ð²ÐŒÐµÑÑÐµ ÑÐŸ status.dm Ð³ÐµÐœÐµÑÐžÑÑÐµÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÑÑÑÐ°ÐœÐžÑÑ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1116"><b>tipaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1117">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑ Ð²ÐŒÐµÑÑÐµ Ñ tip.dm web-ÑÑÑÐ°ÐœÐžÑÑ, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑÑ ÑÐŸÐ²ÐµÑ, Ð²Ð·ÑÑÑÐ¹ ÐœÐ°ÑÐ³Ð°ÐŽ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ð¿ÐŸÐŽÑÐºÐ°Ð·ÐŸÐº, ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐœÑÑ
+ Ð² <i>tip.dm</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1118"><b>userdb.h</b></Text>
+</th>
+<th width="390">
+<Text id="1119">Ð¡ÑÑÑÐºÑÑÑÐ° ÐŽÐ°ÐœÐœÑÑ
+ Ðž ÑÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÐ°Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐ° GDBM Ð±Ð°Ð·Ñ ÐŽÐ°ÐœÐœÑÑ
+ ÐŸÐ±ÑÐ»ÑÐ¶ÐžÐ²Ð°ÐœÐžÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹: ÐžÑ
+ Ð¿Ð°ÑÐŸÐ»Ðž, Ð³ÑÑÐ¿Ð¿Ñ Ðž ÑÐ°Ðº ÐŽÐ°Ð»ÐµÐµ.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1120"><b>usersaction.h</b></Text>
+</th>
+<th width="390">
+<Text id="1121">ÐÐµÐ¹ÑÑÐ²ÐžÑ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐ°ÑÐŸÑÐ°, ÐœÐ°ÑÐ»ÐµÐŽÑÐµÐŒÑÐµ Ð±Ð°Ð·ÐŸÐ²ÑÐŒ ÐºÐ»Ð°ÑÑÐŸÐŒ, ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÐµ Ðž ÑÐŽÐ°Ð»ÐµÐœÐžÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹, Ð° ÑÐ°ÐºÐ¶Ðµ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÐµ Ð³ÑÑÐ¿Ð¿, Ð² ÐºÐŸÑÐŸÑÑÑ
+ ÐŸÐœÐž ÐœÐ°Ñ
+ÐŸÐŽÑÑÑÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1122"><b>vlistbrowserclass.h</b></Text>
+</th>
+<th width="390">
+<Text id="1123">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŸÑ browserclass, ÑÑÐŸÑ ÐŸÐ±ÑÐµÐºÑ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐŽÐ»Ñ Ð²ÐµÑÑÐžÐºÐ°Ð»ÑÐœÑÑ
+ ÑÐ¿ÐžÑÐºÐŸÐ², ÐŸÑÐœÐŸÐ²Ñ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ². ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÐŽÐŸÑÐµÑÐœÐžÐµ Ð·Ð°Ð¿ÐžÑÐž ÑÐ·Ð»Ð° ÐŽÐ»Ñ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐŸÐ², ÐœÐ°ÑÐžÐœÐ°ÑÑÐžÑ
+ÑÑ Ñ ÑÐžÐŒÐ²ÐŸÐ»Ð° N Ð¿ÑÐµÐŽÑÑÐŒÐŸÑÑÐµÐœÑ Ð² VList.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1124"><b>z3950cfg.h</b></Text>
+</th>
+<th width="390">
+<Text id="1125">Ð¡ÑÑÑÐºÑÑÑÐ° ÐŽÐ°ÐœÐœÑÑ
+, Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑÐ°Ñ Ð¿ÑÐŸÑÐŸÐºÐŸÐ» Z39.50. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐ¹ z3950proto. cpp, ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÐŸÑÐœÐŸÐ²ÐœÐŸÐ¹ ÐºÐ»Ð°ÑÑ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð° (ÑÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŸÑ Ð±Ð°Ð·ÐŸÐ²ÐŸÐ³ÐŸ ÐºÐ»Ð°ÑÑÐ° recptproto) Ðž ÑÐžÐœÑÐ°ÐºÑÐžÑÐµÑÐºÐžÐ¹ Ð°ÐœÐ°Ð»ÐžÐ·Ð°ÑÐŸÑ ÑÐ°Ð¹Ð»Ð° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž zparse.y (Ð¿ÐžÑÑÐŒÐµÐœÐœÐŸÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ YACC).</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1126"><b>z3950proto.h</b></Text>
+</th>
+<th width="390">
+<Text id="1127">Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŸÑ recptproto, ÑÑÐŸÑ ÐºÐ»Ð°ÑÑ ÑÐµÐ°Ð»ÐžÐ·ÑÐµÑ Ð¿ÑÐŸÑÐŸÐºÐŸÐ» Z39.50 ÑÐ°Ðº, ÑÑÐŸÐ±Ñ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑ Greenstone ÐŒÐŸÐ³ ÐŸÐ±ÑÐ°ÑÐžÑÑÑÑ Ðº ÐŸÑÐŽÐ°Ð»ÐµÐœÐœÑÐŒ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐŒ ÑÐ°Ð¹ÑÐ°ÐŒ, ÑÐ°Ð±ÐŸÑÐ°ÑÑÐžÐŒ ÐœÐ° ÑÐµÑÐ²ÐµÑÐ°Ñ
+ Z39.50.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="1128"><b>z3950server.h</b></Text>
+</th>
+<th width="390">
+<Text id="1129">ÐÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐ°Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐ° ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð° Z39.50.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="initialisation">
+<Title>
+<Text id="1130">ÐÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÑ</Text>
+</Title>
+<Content>
+<Text id="1131">ÐÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÑ Ð² Greenstone - ÑÐ»ÐŸÐ¶ÐœÐ°Ñ ÐŸÐ¿ÐµÑÐ°ÑÐžÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑ ÑÐ°Ð¹Ð»Ñ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž Ðž Ð¿ÑÐžÑÐ²Ð°ÐžÐ²Ð°ÐµÑ Ð¿ÐŸÐ»ÑÐŒ ÐŽÐ°ÐœÐœÑÑ
+ Ð·ÐœÐ°ÑÐµÐœÐžÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ . Ð ÐŽÐŸÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ Ðº ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐžÑ Ðž ÑÑÐœÐºÑÐžÑÐŒ ÐºÐŸÐœÑÑÑÑÐºÑÐŸÑÐ°, ÐŸÑÐœÐŸÐ²ÐœÑÐµ ÐŸÐ±ÑÐµÐºÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ ÑÑÐœÐºÑÐžÐž init () Ðž conflgure(), ÑÑÐŸÐ±Ñ Ð¿ÐŸÐŒÐŸÑÑ ÑÑÐ°ÐœÐŽÐ°ÑÑÐžÐ·ÐŸÐ²Ð°ÑÑ Ð·Ð°ÐŽÐ°ÑÑ. ÐÐ°Ð¶Ðµ Ð² ÑÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ Ð¿ÐŸÑÑÐŽÐŸÐº Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð·Ð°ÑÑÑÐŽÐœÐµÐœ. ÐÐ°ÑÑÐŸÑÑÐžÐ¹ ÑÐ°Ð·ÐŽÐµÐ» ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ ÐºÐ°Ðº Ð²ÑÐµ ÑÑÐŸ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ.</Text>
+<Text id="1132">Greenstone ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÐ°Ð¹Ð»ÐŸÐ² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐŽÐ»Ñ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÑÐµÐ»ÐµÐ¹, ÐœÐŸ Ð²ÑÐµ ÐŸÐœÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑ ÐŸÐŽÐžÐœ Ðž ÑÐŸÑ Ð¶Ðµ ÑÐžÐœÑÐ°ÐºÑÐžÑ. ÐÑÐ»Ðž ÑÑÑÐŸÐºÐ° ÐœÐµ ÐœÐ°ÑÐžÐœÐ°ÐµÑÑÑ Ñ Ñ
+ÑÑ-ÑÐžÐŒÐ²ÐŸÐ»Ð° (#) ÐžÐ»Ðž ÑÐŸÑÑÐŸÐžÑ Ð¿ÐŸÐ»ÐœÐŸÑÑÑÑ ÐžÐ· Ð¿ÑÑÑÐŸÐ³ÐŸ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ð°, Ð¿ÐµÑÐ²ÐŸÐµ ÑÐ»ÐŸÐ²ÐŸ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÐºÐ»ÑÑÐµÐ²ÐŸÐµ ÑÐ»ÐŸÐ²ÐŸ, Ð° ÐŸÑÑÐ°ÑÑÐžÐµÑÑ ÑÐ»ÐŸÐ²Ð° Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²ÐºÑ ÑÐ°ÑÑÐœÐŸÑÑÐž ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ ÐºÐ»ÑÑÐµÐ²ÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð°.</Text>
+<Text id="1133">Ð¡ÑÑÐŸÐºÐž ÑÐ°Ð¹Ð»ÐŸÐ² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž Ð¿ÐµÑÐµÐŽÐ°ÑÑ, Ð¿ÐŸ ÐŸÐŽÐœÐŸÐŒÑ, ÐŽÐ»Ñ conflgure() ÐŽÐ²Ð° Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐ°: ÐºÐ»ÑÑÐµÐ²ÐŸÐµ ÑÐ»ÐŸÐ²ÐŸ Ðž ÐŒÐ°ÑÑÐžÐ² ÐŸÑÑÐ°ÑÑÐžÑ
+ÑÑ ÑÐ»ÐŸÐ². ÐÑÐœÐŸÐ²Ð°ÐœÐœÐ°Ñ ÐœÐ° ÐºÐ»ÑÑÐµÐ²ÐŸÐŒ ÑÐ»ÐŸÐ²Ðµ, ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐ°Ñ Ð²ÐµÑÑÐžÑ Ð²ÑÐ±ÐŸÑÐ° configure() ÑÐµÑÐ°ÐµÑ, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÑ Ð»Ðž ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐžÐœÑÐµÑÐµÑ, Ðž ÐµÑÐ»Ðž ÑÑÐŸ ÑÐ°Ðº ÑÐŸ ÑÐŸÑ
+ÑÐ°ÐœÑÐµÑ ÐµÐµ. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, collectserver (ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐºÐ°Ð·Ð°Ðœ ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="greenstone_runtime_system"/>), ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑ ÐŸÐ¿ÐµÑÐ°ÑÐŸÑÑ Ð·Ð°ÐŽÐ°ÐœÐžÑ ÑÐŸÑÐŒÐ°ÑÐ° Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐŸÐ³ÐŽÐ° ÑÐŸÑÐŒÐ°Ñ ÐºÐ»ÑÑÐµÐ²ÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð° Ð¿ÐµÑÐµÐŽÐ°ÑÑ configure(), ÐŸÐ¿ÐµÑÐ°ÑÐŸÑ if Ð·Ð°Ð¿ÑÑÐºÐ°ÐµÑ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐœÑÑ Ð² ÐŸÐ±ÑÐµÐºÑÐµ ÐºÐŸÐ¿ÐžÑ Ð²ÑÐŸÑÐŸÐ³ÐŸ Ð°ÑÐ³ÑÐŒÐµÐœÑÐ° ÑÑÐœÐºÑÐžÐž.</Text>
+<Text id="1134">ÐÐŸÑÐ»Ðµ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž ÐºÐ»ÑÑÐµÐ²ÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð° Ðž Ð¿ÑÐµÐ¶ÐŽÐµ, ÑÐµÐŒ ÑÑÐœÐºÑÐžÑ Ð·Ð°ÐºÐŸÐœÑÐžÑ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ, ÐœÐµÐºÐŸÑÐŸÑÑÐµ Ð²ÐµÑÑÐžÐž conflgure() Ð¿ÐµÑÐµÐŽÐ°ÑÑ ÐŽÐ°ÐœÐœÑÐµ ÑÑÐœÐºÑÐžÐž configure() Ð² ÐŽÑÑÐ³ÐžÑ
+ ÐŸÐ±ÑÐµÐºÑÐ°Ñ
+. ÐÐ±ÑÐµÐºÑ Receptionist (ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑ) Ð²ÑÐ·ÑÐ²Ð°ÐµÑ Ð²ÑÐ±ÐŸÑ configureQ ÐŽÐ»Ñ Actions , Protocols Ðž Browsers. ÐÐ±ÑÐµÐºÑ NullProtocol Ð²ÑÐ·ÑÐ²Ð°ÐµÑ conflgure() ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÐŸÐ±ÑÐµÐºÑÐ° Collection; Collection Ð²ÑÐ·ÑÐ²Ð°ÐµÑ Filters Ðž Sources.</Text>
+<Text id="1135">Ð C++ Ð¿ÐŸÐ»Ñ ÐŽÐ°ÐœÐœÑÑ
+ ÐŸÐ±ÑÑÐœÐŸ ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·ÐžÑÑÑÑÑÑ ÑÑÐœÐºÑÐžÐµÐ¹ ÐºÐŸÐœÑÑÑÑÐºÑÐŸÑÐ° ÐŸÐ±ÑÐµÐºÑÐ°. ÐÐŽÐœÐ°ÐºÐŸ, Ð² Greenstone ÐœÐµÐºÐŸÑÐŸÑÐ°Ñ ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÑ Ð·Ð°Ð²ÐžÑÐžÑ ÐŸÑ ÑÑÐµÐœÐžÑ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ ÐžÐ· ÑÐ°Ð¹Ð»ÐŸÐ² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž, ÑÐ°Ðº ÑÑÐŸ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒ Ð²ÑÐŸÑÐŸÐ¹ ÑÐ°ÑÐœÐŽ ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÐž. Ð­ÑÐŸ - ÑÐµÐ»Ñ init () ÑÑÐœÐºÑÐžÐž-ÑÐ»ÐµÐœÐ°, Ð² ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÑÐ»ÑÑÐ°ÑÑ
+ ÐŸÐœÐ° Ð²ÐµÐŽÐµÑ Ðº Ð¿ÐŸÑÐ»ÐµÐŽÑÑÑÐµÐŒÑ Ð²ÑÐ·ÐŸÐ²Ñ conflgure().</Text>
+<Figure id="initialising_greenstone_using_the_null_protocol">
+<Title>
+<Text id="1136">ÐÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÑ Greenstone, Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ    , ÐœÑÐ»Ñ-Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð°</Text>
+</Title>
+<CodeLine>============</CodeLine>
+<CodeLine>Main program</CodeLine>
+<CodeLine>============</CodeLine>
+<CodeLine>Statically construct Receptionist</CodeLine>
+<CodeLine>Statically construct NullProtocol</CodeLine>
+<CodeLine>Establish the value for 'gsdlhome' by reading gsdlsite.cfg</CodeLine>
+<CodeLine>Foreach directory in GSDLHOME/collect that isn't "modelcol":</CodeLine>
+<CodeLine>   Add directory name (now treated as collection name) to NullProtocol:</CodeLine>
+<CodeLine>       Dynamically construct Collection</CodeLine>
+<CodeLine>       Dynamically construct Gdbm class</CodeLine>
+<CodeLine>       Dynamically construct the Null Filter</CodeLine>
+<CodeLine>       Dynamically construct the Browse Filter</CodeLine>
+<CodeLine>       Dynamically construct MgSearch</CodeLine>
+<CodeLine>       Dynamically construct the QueryFilter</CodeLine>
+<CodeLine>       Dynamically construct the MgGdbmSource</CodeLine>
+<CodeLine>       Configure Collection with 'collection'</CodeLine>
+<CodeLine>           Passing 'collection' value on to Filters and Sources:</CodeLine>
+<CodeLine>       Configure Receptionist with 'collectinfo':</CodeLine>
+<CodeLine>           Passing 'collectinfo' value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>Add NullProtocol to Receptionist</CodeLine>
+<CodeLine>Add in UTF-8 converter</CodeLine>
+<CodeLine>Add in GB converter</CodeLine>
+<CodeLine>Add in Arabic converter</CodeLine>
+<CodeLine>Foreach Action:</CodeLine>
+<CodeLine>   Statically construct Action</CodeLine>
+<CodeLine>   Add Action to Receptionist</CodeLine>
+<CodeLine>Foreach Browsers:</CodeLine>
+<CodeLine>   Statically construct Browser</CodeLine>
+<CodeLine>   Add Browser to Receptionist</CodeLine>
+<CodeLine>Call function cgiwrapper:</CodeLine>
+<CodeLine>   =================</CodeLine>
+<CodeLine>   Configure objects</CodeLine>
+<CodeLine>   =================</CodeLine>
+<CodeLine>   Configure Receptionist with 'collection'</CodeLine>
+<CodeLine>       Passing 'collection' value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>       NullProtocol not interested in 'collection'</CodeLine>
+<CodeLine>   Configure Receptionist with 'httpimg'</CodeLine>
+<CodeLine>       Passing 'httpimg' value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>       NullProtocol passing 'httpimg' on to Collection</CodeLine>
+<CodeLine>       Passing 'httpimg' value on to Filters and Sources:</CodeLine>
+<CodeLine>   Configure Receptionist with 'gwcgi'</CodeLine>
+<CodeLine>       Passing 'gwcgi' value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>       NullProtocol passing 'gwcgi' on to Collection</CodeLine>
+<CodeLine>           Passing 'gwcgi' value on to Filters and Sources:</CodeLine>
+<CodeLine>   Reading in site configuration file gsdlsite.cfg</CodeLine>
+<CodeLine>       Configure Recptionist with 'gsdlhome'</CodeLine>
+<CodeLine>           Passing 'gsdlhome' value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>           NullProtocol passing 'gsdlhome' on to Collection</CodeLine>
+<CodeLine>               Passing 'gsdlhome' value on to Filters and Sources:</CodeLine>
+<CodeLine>       Configure Recptionist with ...</CodeLine>
+<CodeLine>       ... and so on for all entries in gsdlsite.cfg</CodeLine>
+<CodeLine>   Reading in main configuration file main.cfg</CodeLine>
+<CodeLine>       Confiugre Recptionist with ...</CodeLine>
+<CodeLine>       ... and so on for all entries in main.cfg</CodeLine>
+<CodeLine>   ====================</CodeLine>
+<CodeLine>   Initialising objects</CodeLine>
+<CodeLine>   ====================</CodeLine>
+<CodeLine>   Initialise the Receptionist</CodeLine>
+<CodeLine>       Configure Receptionist with 'collectdir'</CodeLine>
+<CodeLine>           Passing 'collectdir' value on to Actions, Protocols, and Browsers:</CodeLine>
+<CodeLine>           NullProtocol not interested in 'collectdir'</CodeLine>
+<CodeLine>       Read in Macro files</CodeLine>
+<CodeLine>       Foreach Actions</CodeLine>
+<CodeLine>           Initialise Action</CodeLine>
+<CodeLine>       Foreach Protocol</CodeLine>
+<CodeLine>           Initialise Protocol</CodeLine>
+<CodeLine>           When Protocol==NullProtocol:</CodeLine>
+<CodeLine>               Foreach Collection</CodeLine>
+<CodeLine>                   Reading Collection's build.cfg</CodeLine>
+<CodeLine>                   Reading Collection's collect.cfg</CodeLine>
+<CodeLine>                       Configure Collection with 'creator'</CodeLine>
+<CodeLine>                           Passing 'creator' value on to Filters and Sources:</CodeLine>
+<CodeLine>                       Configure Collection with 'maintainer'</CodeLine>
+<CodeLine>                           Passing 'maintainer' value on to Filters and Sources:</CodeLine>
+<CodeLine>                       ... and so on for all entries in collect.cfg</CodeLine>
+<CodeLine>       Foreach Browsers</CodeLine>
+<CodeLine>           Initialise Browser</CodeLine>
+<CodeLine>   =============</CodeLine>
+<CodeLine>   Generate page</CodeLine>
+<CodeLine>   =============</CodeLine>
+<CodeLine>   Parse CGI arguments</CodeLine>
+<CodeLine>   Execute designated Action to produce page</CodeLine>
+<CodeLine>End.</CodeLine>
+</Figure>
+<Text id="1137">ÐÐ° ÑÐžÑÑÐœÐŸÐºÐµ <CrossRef target="Figure" ref="initialising_greenstone_using_the_null_protocol"/> Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÑ ÐŽÐžÐ°Ð³ÐœÐŸÑÑÐžÑÐµÑÐºÐžÐµ ÐžÐœÑÑÑÑÐºÑÐžÐž, ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ Greenstone, ÑÐ²ÐµÐ»ÐžÑÐµÐœÐœÑÐµ ÑÐ°Ðº, ÑÑÐŸÐ±Ñ Ð²ÑÐŽÐµÐ»ÐžÑÑ Ð¿ÑÐŸÑÐµÑÑ ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÐž. ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐœÐ°ÑÐžÐœÐ°ÐµÑÑÑ Ñ ÑÑÐœÐºÑÐžÐž main() Ð² recpt/librarymain.cpp. ÐÐœÐ° ÑÐŸÐ·ÐŽÐ°ÐµÑ ÐŸÐ±ÑÐµÐºÑ Receptionist Ðž ÐŸÐ±ÑÐµÐºÑ NullProtocol, Ð·Ð°ÑÐµÐŒ Ð¿ÑÐŸÑÐŒÐ°ÑÑÐžÐ²Ð°ÐµÑ gsdlsite.cfg (ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐœÑÐ¹ Ð² ÑÐŸÐŒ Ð¶Ðµ ÑÐ°ÐŒÐŸÐŒ ÐºÐ°ÑÐ°Ð»ÐŸÐ³Ðµ, ÑÑÐŸ Ðž Ð²ÑÐ¿ÐŸÐ»ÐœÑÐµÐŒÐ°Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° library) ÐŽÐ»Ñ gsdlhome Ðž ÑÐŸÑ
+ÑÐ°ÐœÑÐµÑ ÐµÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ð² Ð¿ÐµÑÐµÐŒÐµÐœÐœÐŸÐ¹.</Text>
+<Text id="1138">ÐÐ°Ð»ÐµÐµ mainQ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑ ÐŸÐ±ÑÐµÐºÑ NullProtocol Ðº Receptionist (Ð ÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÑ), ÐºÐŸÑÐŸÑÑÐ¹ ÑÐŸÑ
+ÑÐ°ÐœÑÐµÑ ÐŒÐ°ÑÑÐžÐ² Ð¿ÑÐŸÑÐŸÐºÐŸÐ»ÐŸÐ² Ð±Ð°Ð·ÐŸÐ²ÐŸÐ³ÐŸ ÐºÐ»Ð°ÑÑÐ° Ð² Ð·Ð°ÑÐžÑÐµÐœÐœÐŸÐŒ Ð¿ÐŸÐ»Ðµ ÐŽÐ°ÐœÐœÑÑ
+, Ð° Ð·Ð°ÑÐµÐŒ ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐºÐŸÐœÐ²ÐµÑÑÐµÑÐŸÐ². main() ÑÐŸÐ·ÐŽÐ°ÐµÑ Ð²ÑÐµ Actions Ðž Browsers, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐµ Ð² Ð²ÑÐ¿ÐŸÐ»ÐœÑÐµÐŒÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐµ, Ðž ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑ ÐžÑ
+ Ðº Ð ÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÑ. Ð Ð·Ð°Ð²ÐµÑÑÐµÐœÐžÐµ ÑÑÐœÐºÑÐžÑ Ð²ÑÐ·ÑÐ²Ð°ÐµÑ cgiwrapper () Ð² cgiwrapper.cpp, ÐºÐŸÑÐŸÑÑÐ¹ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÑÑÑÐµÑÑÐ²ÐµÐœÐœÑÑ ÐŸÐ±ÑÐµÐºÑÐœÑÑ ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÑ.</Text>
+<Text id="1139">Ð¡ÑÑÐµÑÑÐ²ÑÑÑ ÑÑÐž ÑÑÐ°Ð¿Ð° cgiwrapper(): ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÑ, ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÑ Ðž Ð³ÐµÐœÐµÑÐ°ÑÐžÑ ÑÑÑÐ°ÐœÐžÑÑ. Ð¡ÐœÐ°ÑÐ°Ð»Ð° Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÑÑÑÑ Ð°Ð¿Ð¿Ð°ÑÐ°ÑÐœÑÐµ Ð·Ð°Ð¿ÑÐŸÑÑ conflgure(). ÐÐ°ÑÐµÐŒ ÑÐžÑÐ°ÐµÑÑÑ gsdlsite.cfg Ðž Ð²ÑÐ·ÑÐ²Ð°ÐµÑÑÑ configure() ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÑÑÑÐŸÐºÐž. Ð¢ÐŸ Ð¶Ðµ ÑÐ°ÐŒÐŸÐµ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑÑ ÐŽÐ»Ñ etc/main.cfg.</Text>
+<Text id="1140">ÐÑÐŸÑÐŸÐ¹ ÑÑÐ°Ð¿ cgiwrapper () ÐŽÐµÐ»Ð°ÐµÑ Ð·Ð°Ð¿ÑÐŸÑÑ Ðº init (). Ð ÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑ ÐŽÐµÐ»Ð°ÐµÑ ÑÐŸÐ»ÑÐºÐŸ ÐŸÐŽÐžÐœ Ð·Ð°Ð¿ÑÐŸÑ Ðº ÑÐ²ÐŸÐµÐ¹ ÑÑÐœÐºÑÐžÐž init (), ÐœÐŸ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµÐŒ Ð²ÑÐ·ÐŸÐ²Ð° Ð·Ð°Ð¿ÑÑÐºÐ°ÐµÑ ÑÑÐœÐºÑÐžÐž init () Ð² ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÐŸÐ±ÑÐµÐºÑÐ°Ñ
+, ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐœÑÑ
+ Ð² ÐµÐ³ÐŸ Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+. Ð¡ÐœÐ°ÑÐ°Ð»Ð° Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑÑ Ð°Ð¿Ð¿Ð°ÑÐ°ÑÐœÑÐ¹ Ð·Ð°Ð¿ÑÐŸÑ conflgure(), ÑÑÐŸÐ±Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ collectdir, Ð¿ÐŸÑÐ»Ðµ ÑÐµÐ³ÐŸ ÑÐžÑÐ°ÑÑÑÑ ÐŒÐ°ÐºÑÐŸÑÐ°Ð¹Ð»Ñ. ÐÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ Ð²ÑÐ·ÑÐ²Ð°ÑÑ ÐµÐ³ÐŸ init () ÑÑÐœÐºÑÐžÑ. Ð¢ÐŸ Ð¶Ðµ ÑÐ°ÐŒÐŸÐµ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð°, ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐœÐŸÐ³ÐŸ Ð² ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÐµ, ÐœÐŸ Ð² ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÐŒÐŸÐ¹ ÑÐžÑÑÐµÐŒÐµ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœ ÑÐŸÐ»ÑÐºÐŸ ÐŸÐŽÐžÐœ Ð¿ÑÐŸÑÐŸÐºÐŸÐ» - NullProtocol. ÐÐ°Ð¿ÑÐŸÑ init () ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ ÐŸÐ±ÑÐµÐºÑÐ° Ð²ÑÐ·ÑÐ²Ð°ÐµÑ ÐŽÐ°Ð»ÑÐœÐµÐ¹ÑÑÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÑ: ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð² NullProtocol ÑÐžÑÐ°ÑÑÑÑ Ðž ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÑÑÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹ build.cfg Ðž collect.cfg, Ñ Ð·Ð°Ð¿ÑÐŸÑÐŸÐŒ configure() ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÑÑÑÐŸÐºÐž.</Text>
+<Text id="1141">ÐÐ° Ð·Ð°ÐºÐ»ÑÑÐžÑÐµÐ»ÑÐœÐŸÐŒ ÑÑÐ°Ð¿Ðµ cgiwrapper () ÐŽÐŸÐ»Ð¶ÐµÐœ Ð¿ÑÐŸÐ°ÐœÐ°Ð»ÐžÐ·ÐžÑÐŸÐ²Ð°ÑÑ CGI -Ð°ÑÐ³ÑÐŒÐµÐœÑÑ Ðž Ð·Ð°ÑÐµÐŒ Ð²ÑÐ·Ð²Ð°ÑÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ. ÐÐ±Ð° ÑÑÐžÑ
+ Ð·Ð°Ð¿ÑÐŸÑÐ° Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÑÑÑÑ Ð¿ÑÐž Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐµ ÐŸÐ±ÑÐµÐºÑÐ° Receptionist.</Text>
+<Text id="1142">ÐÑÐžÑÐžÐœÐ° ÐŽÐ»Ñ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž, ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÐž Ðž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Ð³ÐµÐœÐµÑÐ°ÑÐžÐž ÑÑÑÐ°ÐœÐžÑÑ ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸ Greenstone ÐŸÐ¿ÑÐžÐŒÐžÐ·ÐžÑÐŸÐ²Ð°Ðœ ÐŽÐ»Ñ ÑÐ°Ð±ÐŸÑÑ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÑÐµÑÐ²ÐµÑÐ° (ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Fast-cgi, ÐžÐ»Ðž Ð¿ÑÐŸÑÐŸÐºÐŸÐ» Corba, ÐžÐ»Ðž Windows Local Library). Ð ÑÑÐŸÐŒ ÑÐµÐ¶ÐžÐŒÐµ ÑÐ°Ð±ÐŸÑÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÑ Ðž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÐž Ð·Ð°Ð¿ÑÑÐºÐ°ÑÑÑÑ ÐŸÐŽÐœÐ°Ð¶ÐŽÑ, Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐŸÑÑÐ°ÐµÑÑÑ Ð² Ð¿Ð°ÐŒÑÑÐž Ðž Ð³ÐµÐœÐµÑÐžÑÑÐµÑ ÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐŸ web-ÑÑÑÐ°ÐœÐžÑ Ð² ÐŸÑÐ²ÐµÑ ÐœÐ° Ð·Ð°Ð¿ÑÐŸÑÑ ÐŸÑ ÐºÐ»ÐžÐµÐœÑÐŸÐ², ÐœÐµ ÑÑÐµÐ±ÑÑ Ð¿ÐµÑÐµÑÑÑÐ°ÐœÐŸÐ²ÐºÐž.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="configuring_your_greenstone_site">
+<Title>
+<Text id="1143">ÐÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð²Ð°ÑÐµÐ³ÐŸ Greenstone - ÑÐ°Ð¹ÑÐ°</Text>
+</Title>
+<Content>
+<Text id="1144">Ð ÑÐžÑÑÐµÐŒÐµ Greenstone ÐžÐŒÐµÐµÑÑÑ ÐŽÐ²Ð° ÑÐ°Ð¹Ð»Ð° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž, ÐºÐŸÑÐŸÑÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÑÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ Ð°ÑÐ¿ÐµÐºÑÑ Ð²Ð°ÑÐµÐ³ÐŸ Greenstone-ÑÐ°Ð¹ÑÐ°. "ÐÑÐœÐŸÐ²ÐœÐŸÐ¹" ÑÐ°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž main.cfg ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² GSDLHOME/ETC, Ðž ÑÐ°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž "ÑÐ°Ð¹ÑÐ°" gsdlsite.cfg ÐŸÐœ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² GSDLHOME/CGI-BIN. ÐÐ°Ð¶ÐŽÑÐ¹ ÐžÐ· ÑÑÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² ÑÐ¿ÑÐ°Ð²Ð»ÑÐµÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐŒÐž Ð°ÑÐ¿ÐµÐºÑÐ°ÐŒÐž ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž Ð²ÑÐµÐ³ÐŸ ÑÐ°Ð¹ÑÐ°. ÐÐ±Ð° ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÐœÑ ÑÐŸ ÑÑÑÐ°ÐœÐžÑÑ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ Greenstone.</Text>
+<Section id="main_configuration_file">
+<Title>
+<Text id="1145">ÐÑÐœÐŸÐ²ÐœÐŸÐ¹ ÑÐ°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="1146">ÐÑÐœÐŸÐ²ÐœÐŸÐ¹ ÑÐ°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž main, cfg ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÐºÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑÐ° ÐºÐ°Ðº ÑÐ°ÑÑÐž Greenstone ÐŽÐ»Ñ Ð¿ÐŸÐ»Ñ Ð·Ð°Ð¿ÑÐŸÑÐŸÐ² Ðž ÐŽÐ»Ñ ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ ÑÑÑÐ°ÐœÐžÑ. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐ¿ÑÐ°Ð²Ð»ÑÑÑ Ð²ÑÐµÐŒ, ÐœÐ°ÑÐžÐœÐ°Ñ ÐŸÑ ÑÐ·ÑÐºÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÐžÐœÑÐµÑÑÐµÐ¹Ñ, Ðž Ð·Ð°ÐºÐ°ÐœÑÐžÐ²Ð°Ñ Ñ
+ÑÐ°ÐœÐµÐœÐžÐµÐŒ ÐŽÐ°ÐœÐœÑÑ
+ ÐŸ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐžÐž.</Text>
+<Subsection id="site_maintenance_and_logging">
+<Title>
+<Text id="1147">ÐÐ±ÑÐ»ÑÐ¶ÐžÐ²Ð°ÐœÐžÐµ ÑÐ°Ð¹ÑÐ° Ðž ÑÐµÐ³ÐžÑÑÑÐ°ÑÐžÑ</Text>
+</Title>
+<Content>
+<Text id="1148">Ð¡ÑÑÐŸÐºÐž Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÑÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÐœÐ° ÑÐŸ, ÐºÐ°Ðº ÐŽÐŸÐ»Ð¶ÐµÐœ ÐŸÐ±ÑÐ»ÑÐ¶ÐžÐ²Ð°ÑÑÑÑ Ð²Ð°Ñ Greenstone-ÑÐ°Ð¹Ñ, ÐºÐ°ÐºÐžÐµ ÑÑÐµÐŽÑÑÐ²Ð° ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ Ð¿ÑÐµÐŽÐ»Ð°Ð³Ð°ÑÑÑÑ, ÐºÐ°ÐºÐžÐµ ÑÐµÐ³ÐžÑÑÑÐžÑÑÑÑÑÑ ÑÐŸÐ±ÑÑÐžÑ Ðž ÐºÐ°ÐºÐžÐµ ÑÐŸÐŸÐ±ÑÐµÐœÐžÑ Ð¿ÐŸÐ»ÑÑÐ°ÐµÑ ÑÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð Ð¢Ð°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="configuration_options_for_site_maintenance_and_logging"/> Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÑ ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÐŽÐŸÑÑÑÐ¿ÐœÑÐµ ÐŸÐ¿ÑÐžÐž; ÐŸÑÑÐ°Ð»ÑÐœÑÐµ ÐŸÐ¿ÐžÑÐ°ÐœÑ Ð² ÑÐ»ÐµÐŽÑÑÑÐžÑ
+ ÑÐ°Ð·ÐŽÐµÐ»Ð°Ñ
+.</Text>
+<Table id="configuration_options_for_site_maintenance_and_logging">
+<Title>
+<Text id="1149">Ð¯Ð·ÑÐºÐŸÐ²Ð°Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐ°</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132"/>
+<th width="151">
+<Text id="1150"><b>ÐÐœÐ°ÑÐµÐœÐžÐµ</b></Text>
+</th>
+<th width="246">
+<Text id="1151"><b>ÐŠÐµÐ»Ñ</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1152"><i>maintainer</i></Text>
+</th>
+<th width="151">
+<Text id="1153">NULL ÐžÐ»Ðž E-mail Ð°ÐŽÑÐµÑ</Text>
+</th>
+<th width="246">
+<Text id="1154">ÐÐŽÑÐµÑ ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ Ð¿ÐŸÑÑÑ Ð»ÐžÑÐ°, ÐŸÐ±ÑÐ»ÑÐ¶ÐžÐ²Ð°ÑÑÐµÐ³ÐŸ ÑÐ°Ð¹Ñ, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ñ ÑÐµÐ»ÑÑ ÑÐ²ÐµÐŽÐŸÐŒÐ»ÐµÐœÐžÑ. ÐÑÐ»Ðž NULL, E-mail ÑÐŸÐ±ÑÑÐžÑ Ð·Ð°Ð±Ð»ÐŸÐºÐžÑÐŸÐ²Ð°ÐœÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1155"><i>MailServer</i></Text>
+</th>
+<th width="151">
+<Text id="1156">NULL ÐžÐ»Ðž ÐžÐŒÑ ÑÐµÑÐ²ÐµÑÐ°</Text>
+</th>
+<th width="246">
+<Text id="1157">Ð¡ÐµÑÐ²ÐµÑ ÐžÑÑ
+ÐŸÐŽÑÑÐµÐ¹ Ð¿ÐŸÑÑÑ ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ ÑÐ°Ð¹ÑÐ°. ÐÑÐ»ÐžNULL,       ÑÐŸ       ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ       mail. ÐŽÐŸÐŒÐµÐœ-ÐŸÐ±ÑÐ»ÑÐ¶ÐžÐ²Ð°ÑÑÐµÐ³ÐŸ ÑÐ°Ð¹Ñ Ð»ÐžÑÐ° (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐµÑÐ»Ðž ÐŸÐ±ÑÐ»ÑÐ¶ÐžÐ²Ð°ÐµÑ ÑÐ°Ð¹Ñ - help@example.com, ÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ - mail.example.com). ÐÑÐ»Ðž ÑÑÐŸ ÐœÐµ ÑÐ°Ð·ÑÐµÑÐµÐœÐŸ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÑÐŒ SMTP-ÑÐµÑÐ²ÐµÑÐŸÐŒ, ÑÐŸ E-mail ÑÐŸÐ±ÑÑÐžÑ ÐœÐµ Ð±ÑÐŽÑÑ ÑÐ°Ð±ÐŸÑÐ°ÑÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1158"><i>status</i></Text>
+</th>
+<th width="151">
+<Text id="1159"><i>enabled</i> ÐžÐ»Ðž <i>disabled</i></Text>
+</th>
+<th width="246">
+<Text id="1160">ÐÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ, ÐŽÐŸÐ»Ð¶ÐœÐ° Ð»Ðž ÑÑÑÐ°ÐœÐžÑÐ° "ÐÐ±ÑÐ»ÑÐ¶ÐžÐ²Ð°ÐœÐžÐµ Ðž Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ" Ð±ÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÐŸÐ¹</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1161"><i>collector</i></Text>
+</th>
+<th width="151">
+<Text id="1162"><i>enabled</i> ÐžÐ»Ðž <i>disabled</i></Text>
+</th>
+<th width="246">
+<Text id="1163">ÐÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ, ÐŽÐŸÑÑÑÐ¿ÐœÐ° Ð»Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐºÐŸÐœÐµÑÐœÐŸÐ³ÐŸ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ, ÑÐŸÑÐŒÐžÑÑÑÑÐ°Ñ ÑÑÐµÐŽÑÑÐ²ÐŸ "ÐºÐŸÐ»Ð»ÐµÐºÑÐŸÑÐ°"</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1164"><i>logcgiargs</i></Text>
+</th>
+<th width="151">
+<Text id="1165"><i>true</i> ÐžÐ»Ðž <i>false</i></Text>
+</th>
+<th width="246">
+<Text id="1166">ÐÑÐ»Ðž true, ÑÐµÐ³ÐžÑÑÑÐ°ÑÐžÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ Ñ
+ÑÐ°ÐœÐžÑÑÑ Ð² usage.txt. ÐÑÐ»Ðž true, ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÑ
+ ÑÐ°Ð¹ÑÐ°</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1167"><i>usecookies</i></Text>
+</th>
+<th width="151">
+<Text id="1168"><i>true</i> ÐžÐ»Ðž <i>false</i></Text>
+</th>
+<th width="246">
+<Text id="1169">ÑÐŸÐ±ÑÐ°ÐœÐ° (ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ cookies) Ðž Ð·Ð°Ð¿ÐžÑÐ°ÐœÐ° Ð² usage.txt(ÑÑÐŸ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ ÑÐŸÐ»ÑÐºÐŸ Ð² ÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ, ÐµÑÐ»Ðž logcgiargs Ð¿ÑÐžÐœÐžÐŒÐ°ÐµÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ true)</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1170"><i>LogDateFormat</i></Text>
+</th>
+<th width="151">
+<Text id="1171"><i>LocalTime</i> ÐžÐ»Ðž <br/><i>UTCTime</i> ÐžÐ»Ðž <br/><i>Absolute</i></Text>
+</th>
+<th width="246">
+<Text id="1172">Ð€ÐŸÑÐŒÐ°Ñ, Ð² ÐºÐŸÑÐŸÑÐŸÐŒ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ Ð²ÑÐµÐŒÐµÐœÐž Ð¿ÑÐžÐ¿ÐžÑÐ°ÐœÐ° Ðº ÑÐ°Ð¹Ð»Ñ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐžÐž. LocalTimeÐ¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑ ÑÐŸÑÐŒÐ°Ñ "ÑÐµÑÐ²ÐµÑÐ³ 07 ÐŽÐµÐºÐ°Ð±ÑÑ 12:34 NZDT 2000 ", UTCTIME - ÑÐŸÑ Ð¶Ðµ ÑÐ°ÐŒÑÐ¹ ÑÐŸÑÐŒÐ°Ñ, ÐœÐŸ Ð² GMT (ÑÑÐµÐŽÐœÐµÐŒ Ð²ÑÐµÐŒÐµÐœÐž Ð¿ÐŸ ÐÑÐžÐœÐ²ÐžÑÑ), Ðž absolute- ÑÐµÐ»ÐŸÐµ ÑÐžÑÐ»ÐŸ, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÑÑÐµÐµ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ ÑÐµÐºÑÐœÐŽ Ñ ÐŒÐŸÐŒÐµÐœÑÐ° 00:00:00 01/01/1970 GMT</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1173"><i>LogEvents</i></Text>
+</th>
+<th width="151">
+<Text id="1174"><i>AllEvents</i> ÐžÐ»Ðž <br/><i>CollectorEvents</i><br/> ÐžÐ»Ðž <i>disabled</i></Text>
+</th>
+<th width="246">
+<Text id="1175">Ð ÐµÐ³ÐžÑÑÑÐ°ÑÐžÑ ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÑÐŸÐ±ÑÑÐžÐ¹ Ð² events.txt. AllEvents ÑÐµÐ³ÐžÑÑÑÐžÑÑÐµÑ Ð²ÑÐµ ÑÐŸÐ±ÑÑÐžÑ Greenstone, CollectorEvents ÑÐµÐ³ÐžÑÑÑÐžÑÑÐµÑ ÑÐŸÐ»ÑÐºÐŸ ÑÐŸÐ±ÑÑÐžÑ, ÑÐ²ÑÐ·Ð°ÐœÐœÑÐµ Ñ Collector (ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑÐŸÐŒ), a disabled ÐœÐµ ÑÐµÐ³ÐžÑÑÑÐžÑÑÐµÑ ÐœÐžÐºÐ°ÐºÐžÑ
+ ÑÐŸÐ±ÑÑÐžÐ¹.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1176"><i>EmailEvents</i></Text>
+</th>
+<th width="151">
+<Text id="1177"><i>enabled</i> ÐžÐ»Ðž <i>disabled</i></Text>
+</th>
+<th width="246">
+<Text id="1178">ÐÑÐ¿ÑÐ°Ð²ÐºÐ° ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ Ð¿ÐŸÑÑÑ Ð»ÐžÑÑ, ÐŸÐ±ÑÐ»ÑÐ¶ÐžÐ²Ð°ÑÑÐµÐŒÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ (ÐµÑÐ»Ðž ÐŸÐœ ÐŸÐŽÐžÐœ - ÑÐŒ. ÐµÐ³ÐŸ ÐŸÐ¿ÑÐžÑ), ÐºÐ°Ð¶ÐŽÑÐ¹ ÑÐ°Ð·, ÐºÐŸÐ³ÐŽÐ° ÑÑÐŸ-ÑÐŸ ÑÐ»ÑÑÐ°ÐµÑÑÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1179"><i>EmailUserEvents</i></Text>
+</th>
+<th width="151">
+<Text id="1180"><i>enabled</i> ÐžÐ»Ðž <i>disabled</i></Text>
+</th>
+<th width="246">
+<Text id="1181">ÐÑÐ¿ÑÐ°Ð²ÐºÐ° ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ Ð¿ÐŸÑÑÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð² ÐŸÑÐ²ÐµÑ ÐœÐ° ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐ±ÑÑÐžÑ - ÐœÐ°Ð¿ÑÐžÐŒÐµÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐŸÑÐ°, Ð·Ð°ÐºÐ°ÐœÑÐžÐ²Ð°ÑÑÐµÐ³ÐŸ ÐºÐŸÐŒÐ¿ÐŸÐœÐŸÐ²ÐºÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1182"><i>macrofiles</i></Text>
+</th>
+<th width="151">
+<Text id="1183">ÑÐ¿ÐžÑÐŸÐº ÐŒÐ°ÐºÑÐŸ ÐžÐŒÐµÐœ ÑÐ°Ð¹Ð»ÐŸÐ²</Text>
+</th>
+<th width="246">
+<Text id="1184">ÐÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ, ÐºÐ°ÐºÐŸÐ¹ ÐŒÐ°ÐºÑÐŸÑ ÑÐ²Ð»ÑÐµÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒ ÐŽÐ»Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Greenstone</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+<Subsection id="language_support">
+<Title>
+<Text id="1185">Ð¯Ð·ÑÐºÐŸÐ²Ð°Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐ°</Text>
+</Title>
+<Content>
+<Text id="1186">ÐÐ²Ð° Ð²ÐžÐŽÐ° Ð²Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÐ¹ Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž main.cfg Ð·Ð°ÑÑÐ°Ð³ÐžÐ²Ð°ÑÑ Ð¿ÑÑÐž ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÑÐ·ÑÐºÐŸÐ². ÐÐœÐž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ, ÐºÐ°ÐºÐžÐµ ÑÐ·ÑÐºÐž Ðž ÐºÐŸÐŽÐžÑÐŸÐ²ÐºÐž ÑÐ²Ð»ÑÑÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ Preferences page. Ð¡ÑÑÐŸÐºÐž Encoding ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÑÐžÐ¿Ñ ÐºÐŸÐŽÐžÑÐŸÐ²ÐºÐž ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð²ÑÐ±ÑÐ°ÐœÑ. Ð¡ÑÑÐŸÐºÐž Language ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ, ÐºÐ°ÐºÐžÐµ ÑÐ·ÑÐºÐž ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð²ÑÐ±ÑÐ°ÐœÑ (ÐºÐŸÐœÐµÑÐœÐŸ, ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÐ³ÐŸ ÑÐ·ÑÐºÐ° ÐŽÐŸÐ»Ð¶ÐœÐ° ÑÑÑÐµÑÑÐ²ÐŸÐ²Ð°ÑÑ ÐŒÐ°ÐºÑÐŸÐºÐŸÐŒÐ°ÐœÐŽÐ° ÑÐ·ÑÐºÐ°).</Text>
+<Text id="1187">Ð¡ÑÑÐŸÐºÐ° Encoding ÐŒÐŸÐ¶ÐµÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑ ÑÐµÑÑÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÑ
+ Ð·ÐœÐ°ÑÐµÐœÐžÑ: shortname, longname, map Ðž multibyte. Shortname - ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÐ°Ñ ÐŒÐµÑÐºÐ° ÐœÐ°Ð±ÐŸÑÐ° ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ², Ðž ÐŽÐŸÐ»Ð¶ÐœÐ° Ð±ÑÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐœÐ° ÐŽÐ»Ñ Ð²ÑÐµÐ³ÐŸ ÐºÐŸÐŽÐžÑÐŸÐ²Ð°ÐœÐžÑ. Longname ÐŽÐ°ÐµÑ ÐžÐŒÑ ÐºÐŸÐŽÐžÑÐŸÐ²Ð°ÐœÐžÑ, ÐºÐŸÑÐŸÑÐŸÐµ ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐŸ ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ Ð²ÑÐ±ÐŸÑÐ° Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÐ¹ -Preferences page. ÐÑÐ»Ðž ÑÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŸÑÑÑÑÑÑÐ²ÑÐµÑ, ÑÐŸ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ shortname. ÐÐœÐ°ÑÐµÐœÐžÐµ ÑÐ°Ñ Ð¿ÑÐžÐœÑÐŽÐžÑÐµÐ»ÑÐœÐŸ ÐŽÐ»Ñ Ð²ÑÐµÑ
+ ÐºÐŸÐŽÐžÑÐŸÐ²ÐŸÐº, ÐºÑÐŸÐŒÐµ utf8, ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐ°ÐœÐ° Ð²ÐœÑÑÑÐµÐœÐœÐµ (Ðž Ð²ÑÐµÐ³ÐŽÐ° ÐŽÐŸÐ»Ð¶ÐœÐ° Ð±ÑÑÑ ÐŽÐŸÐ¿ÑÑÑÐžÐŒÐ°). ÐÐœÐ°ÑÐµÐœÐžÐµ multibyte ÐŽÐŸÐ»Ð¶ÐœÐŸ Ð±ÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐŸ ÐŽÐ»Ñ Ð²ÑÐµÑ
+ ÐœÐ°Ð±ÐŸÑÐŸÐ² ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÑÑÐµÐ±ÑÑÑ Ð±ÐŸÐ»ÑÑÐµ, ÑÐµÐŒ ÐŸÐŽÐžÐœ Ð±Ð°Ð¹Ñ ÐœÐ° ÑÐžÐŒÐ²ÐŸÐ». Ð€Ð°Ð¹Ð» main.cfg ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐŸ ÐºÐŸÐŽÐžÑÐŸÐ²ÐŸÐº, Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ ÐžÐ· ÐºÐŸÑÐŸÑÑÑ
+ Ð±ÑÐ»ÐŸ Ð¿ÑÐŸÐºÐŸÐŒÐŒÐµÐœÑÐžÑÐŸÐ²Ð°ÐœÐŸ. Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ¿ÑÑÑÐžÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÐºÐŸÐŽÐžÑÐŸÐ²ÐŸÐº, ÑÐŽÐ°Ð»ÐžÑÐµ ÑÐžÐŒÐ²ÐŸÐ» ÐºÐŸÐŒÐŒÐµÐœÑÐ°ÑÐžÑ "#".</Text>
+<Text id="1188">ÐÐ°Ð¶ÐŽÐ°Ñ ÑÑÑÐŸÐºÐ° Language ÐŒÐŸÐ¶ÐµÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑ ÑÑÐž Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÑ
+ Ð·ÐœÐ°ÑÐµÐœÐžÑ, shortname, longname, Ðž default_encoding. Shortname - ÐŽÐ²ÑÑ
+Ð±ÑÐºÐ²ÐµÐœÐœÐŸÐµ ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÐžÐµ ÑÐ·ÑÐºÐ° Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐž Ñ ÑÑÐµÐ±ÐŸÐ²Ð°ÐœÐžÑÐŒÐž ISO 639. Longname -ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÑÐ·ÑÐºÐ° ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ Ð²ÑÐ±ÐŸÑÐ° Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÐ¹ - Preferences page. ÐÑÐž ÐŸÑÑÑÑÑÑÐ²ÐžÐž ÑÑÐŸÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ, Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ shortname. ÐÐ¿ÑÐžÑ default_encoding ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ, ÑÑÐŸÐ±Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐžÑÐµÐ»ÑÐœÑÑ ÐºÐŸÐŽÐžÑÐŸÐ²ÐºÑ ÐŽÐ»Ñ Ð²ÑÐ±ÑÐ°ÐœÐœÐŸÐ³ÐŸ ÑÐ·ÑÐºÐ°.</Text>
+</Content>
+</Subsection>
+<Subsection id="page_parameters_and_cgi_arguments">
+<Title>
+<Text id="1189">ÐÐ°ÑÐ°ÐŒÐµÑÑÑ ÑÑÑÐ°ÐœÐžÑ Ðž  CGI-Ð°ÑÐ³ÑÐŒÐµÐœÑÐŸÐ²</Text>
+</Title>
+<Content>
+<Text id="1190">ÐÐ°ÑÐ°ÐŒÐµÑÑÑ ÑÑÑÐ°ÐœÐžÑÑ Ðž CGI-Ð°ÑÐ³ÑÐŒÐµÐœÑÐŸÐ² ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÑ Ð²ÐœÑÑÑÐž ÑÐ°Ð¹Ð»Ð° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž main.cfg. ÐÐµÑÐœÐµÐŒÑÑ Ðº ÑÐžÑÑÐœÐºÑ <CrossRef target="Figure" ref="using_the_cgiargsinfoclass_from_pageactioncpp"/>, ÐžÐ· ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ Ð²ÐžÐŽÐœÐŸ, ÑÑÐŸ Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ CGI -Ð°ÑÐ³ÑÐŒÐµÐœÑÐŸÐ² ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐŸ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž C++. ÐÐŽÐœÐ°ÐºÐŸ, ÐžÐœÐŸÐ³ÐŽÐ° Ð¿ÐŸÐ»ÐµÐ·ÐœÐŸ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÐœÐŸÐ²ÑÐµ Ð°ÑÐ³ÑÐŒÐµÐœÑÑ ÐžÐ»Ðž ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ Ð²ÐŸ Ð²ÑÐµÐŒÑ Ð¿ÑÐŸÑÐµÑÑÐ° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž, ÑÐ°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ ÐžÐ·Ð±ÐµÐ³Ð°Ñ Ð¿ÐŸÑÑÐµÐ±ÐœÐŸÑÑÐž Ð¿ÐµÑÐµÑÑÐ°ÐœÑÐ»ÐžÑÐŸÐ²Ð°ÑÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÑ.</Text>
+<Text id="1191">Ð§ÑÐŸÐ±Ñ ÑÐŽÐµÐ»Ð°ÑÑ ÑÑÐŸ, Ð²Ñ ÐŽÐŸÐ»Ð¶ÐœÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŸÐ¿ÑÐžÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž cgiarg. Cgiarg ÐŒÐŸÐ¶ÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŽÐŸ ÑÐµÑÑÐž Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ²; shortname, longname, multiplechar, argdefault, defaultstatus Ðž savedarginfo. Ð­ÑÐž Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑ Ð²Ð°ÑÐžÐ°ÐœÑÐ°ÐŒ CGI-Ð°ÑÐ³ÑÐŒÐµÐœÑÐ°, ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÐŒ Ð² Ð Ð°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Section" ref="receptionist"/>. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, Ð² Ð·ÐœÐ°ÑÐµÐœÐžÐž Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ main.cfg ÐŸÐ¿ÑÐžÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž cgiarg ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ, ÑÑÐŸÐ±Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÑ
+ Ð° Ðž Ñ CGI-Ð°ÑÐ³ÑÐŒÐµÐœÑÐŸÐ² ÐŽÐ»ÑÑ Ðž home ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸ.</Text>
+<Text id="1192">ÐÐ°ÑÐ°ÐŒÐµÑÑÑ ÑÑÑÐ°ÐœÐžÑÑ - ÑÐ°ÑÑÐœÑÐµ ÑÐ»ÑÑÐ°Ðž CGI-Ð°ÑÐ³ÑÐŒÐµÐœÑÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐ°ÐŒ Ð² ÑÐ°Ð¹Ð»Ð°Ñ
+ ÐŒÐ°ÐºÑÐŸÐºÐŸÐŒÐ°ÐœÐŽÑ Greenstone. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, CGI-Ð°ÑÐ³ÑÐŒÐµÐœÑ /ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ / = Ð² ÐŒÐ°ÐºÑÐŸÑÐ°Ð¹Ð»Ð°Ñ
+. Ð§ÑÐŸÐ±Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ CGI-Ð°ÑÐ³ÑÐŒÐµÐœÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐ°ÐºÐ¶Ðµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐŒ ÑÑÑÐ°ÐœÐžÑÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐŸÐ¿ÑÐžÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž pageparam.</Text>
+<Text id="1193">ÐÑÑÑÐžÐ¹ ÑÐ¿ÐŸÑÐŸÐ± ÑÐ·ÐœÐ°ÑÑ ÐŸ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ Ð²Ð°ÑÐžÐ°ÐœÑÐ°Ñ
+ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž, Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÑ
+ Ð² ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž main-cfg, ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸÐ±Ñ ÑÐºÑÐ¿ÐµÑÐžÐŒÐµÐœÑÐžÑÐŸÐ²Ð°ÑÑ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ Ñ ÑÑÐžÐŒ ÑÐ°Ð¹Ð»ÐŸÐŒ. ÐÐ±ÑÐ°ÑÐžÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ ÐœÐ° ÑÐŸ, ÑÑÐŸ ÐµÑÐ»Ðž Ð²Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ Ð»ÐŸÐºÐ°Ð»ÑÐœÑÑ Windows-Ð²ÐµÑÑÐžÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone, ÑÐŸ Ð¿ÑÐµÐ¶ÐŽÐµ ÑÐµÐŒ Ð»ÑÐ±ÑÐµ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ ÑÐ°Ð¹Ð»ÐŸÐ² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž Ð²ÑÑÑÐ¿ÑÑ Ð² ÑÐžÐ»Ñ, Ð²Ð°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð±ÑÐŽÐµÑ Ð¿ÐµÑÐµÐ·Ð°Ð¿ÑÑÑÐžÑÑ ÑÐµÑÐ²ÐµÑ.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="site_configuration_file">
+<Title>
+<Text id="1194"> Ð€Ð°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÑÐ°Ð¹ÑÐ°</Text>
+</Title>
+<Content>
+<Table id="lines_in_gsdlsitecfg">
+<Title>
+<Text id="1195">Lines in <i>gsdlsite.cfg</i></Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="1196"><b>Line</b></Text>
+</th>
+<th width="397">
+<Text id="1197"><b>Function</b></Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1198"><i>gsdlhome</i></Text>
+</th>
+<th width="397">
+<Text id="1199">A path to the <i>GSDLHOME</i> directory.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1200"><i>httpprefix</i></Text>
+</th>
+<th width="397">
+<Text id="1201">The web address of <i>GSDLHOME</i>. If the document root on your web server is set to <i>GSDLHOME</i> you do not need this line.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1202"><i>httpimage</i></Text>
+</th>
+<th width="397">
+<Text id="1203">The web address of the directory containing the images for the user interface. If your web-server's document root is set to <i>GSDLHOME</i> this will be <i>/images</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1204"><i>gwcgi</i></Text>
+</th>
+<th width="397">
+<Text id="1205">The web address of this cgi script (usually ends in <i>library</i>). This is not needed if your web server sets the environment variable <i>SCRIPT_NAME</i>.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="1206"><i>maxrequests</i></Text>
+</th>
+<th width="397">
+<Text id="1207">(Only applies if <i>fast-cgi</i> is in use.) The number of requests fast-cgi should process before it exits. When debugging the library this should be set to a small number, otherwise it should be a large number.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="1208">Ð€Ð°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÑÐ°Ð¹ÑÐ° gsdlsite.cfg ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑ Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÐµ, ÐºÐŸÑÐŸÑÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐŒ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµÐŒ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Ðž Ð²ÐµÐ±-ÑÐµÑÐ²ÐµÑÐŸÐŒ Ð²ÐŸ Ð²ÑÐµÐŒÑ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ Ðž Ð¿ÐŸÑÑÐŸÑÐœÐœÐŸ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² ÑÐŸÐŒ Ð¶Ðµ ÑÐ°ÐŒÐŸÐŒ ÐºÐ°ÑÐ°Ð»ÐŸÐ³Ðµ, ÑÑÐŸ Ðž Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐ°Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ°. Ð¢Ð°Ð±Ð»ÐžÑÐ° <CrossRef target="Table" ref="lines_in_gsdlsitecfg"/> ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ ÑÑÑÐŸÐºÐž Ð² ÑÑÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ; Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐµÐµ ÐŸÐœÐž ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°ÑÑÑÑ Ð² Ð Ð°Ð·ÐŽÐµÐ»Ðµ 5 ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÑÐžÐž - ÐŠÐžÑÑÐŸÐ²Ð°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Greenstone: Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ Ð¿ÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐµ.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="appendix_a_stl">
+<Title>
+<Text id="1209">ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ Ð: Ð¡ÑÐ°ÐœÐŽÐ°ÑÑÐœÐ°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° ÑÐ°Ð±Ð»ÐŸÐœÐŸÐ² C++</Text>
+</Title>
+<Content>
+<Text id="1210">Ð¡ÑÐ°ÐœÐŽÐ°ÑÑÐœÐ°Ñ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° ÐšÐ°Ð±Ð»ÐŸÐœÐŸÐ² (STL) - ÑÐžÑÐŸÐºÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° C++ ÐŸÑ Silicon Graphics (www.sgi.com). Ð ÐŽÐ°ÐœÐœÐŸÐŒ ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœ ÐºÑÐ°ÑÐºÐžÐ¹ ÐŸÐ±Ð·ÐŸÑ ÐºÐ»ÑÑÐµÐ²ÑÑ
+ ÑÐ°ÑÑÐµÐ¹, ÐºÐŸÑÐŸÑÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ Ð²ÑÑÐŽÑ Ð² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐµ Greenstone. ÐÐ»Ñ ÐŸÐ·ÐœÐ°ÐºÐ»ÐŒÐ»ÐµÐœÐžÑ Ñ Ð±ÐŸÐ»ÐµÐµ Ð¿ÐŸÐ»ÐœÑÐŒ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµÐŒ ÐŸÐ·ÐœÐ°ÐºÐŸÐŒÑÑÐµÑÑ Ñ ÐŸÑÐžÑÐžÐ°Ð»ÑÐœÑÐŒ ÑÐ¿ÑÐ°Ð²ÐŸÑÐœÑÐŒ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµÐŒ STL, ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒ Ð² ÑÐµÐ¶ÐžÐŒÐµ on-line ÐœÐ° ÑÐ°Ð¹ÑÐµ www.sgi.com, ÐžÐ»Ðž Ñ ÐŸÐŽÐœÐžÐŒ ÐžÐ· ÐŒÐœÐŸÐ³ÐžÑ
+ STL-ÑÑÐµÐ±ÐœÐžÐºÐŸÐ², ÐœÐ°Ð¿ÑÐžÐŒÐµÑ Josuttis (1999). </Text>
+<Text id="1211">ÐÐ°Ðº Ð¿ÑÐµÐŽÐ¿ÐŸÐ»Ð°Ð³Ð°ÐµÑ ÑÐ»ÐŸÐ²ÐŸ "ÑÐ°Ð±Ð»ÐŸÐœ", STL - ÐœÐµ ÑÐŸÐ»ÑÐºÐŸ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° ÐŸÐ±ÑÐµÐºÑÐœÑÑ
+ ÐŒÐŸÐŽÑÐ»ÐµÐ¹ plug-and-use (Ð¿ÐŸÐŽÐºÐ»ÑÑÐ°Ð¹-Ðž-ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹). ÐÐŒÐµÑÑÐµ Ñ ÐŒÐµÑ
+Ð°ÐœÐžÐ·ÐŒÐŸÐŒ ÑÐ°Ð±Ð»ÐŸÐœÐŸÐ² Ð² C++, ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑÑÑ ÑÐŸÑÑÐŒ ÐŽÐ»Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐžÑÑÐŸÐ², ÑÑÐŸÐ±Ñ ÑÐ°Ð·ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÑÑ ÐžÑ
+ ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÑÐµ ÐŸÐ±ÑÐµÐºÑÑ, ÐºÐŸÑÐŸÑÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑ Ð°Ð»Ð³ÐŸÑÐžÑÐŒÐžÑÐµÑÐºÐžÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž, ÑÐµÐ°Ð»ÐžÐ·ÐŸÐ²Ð°ÐœÐœÑÐµ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ STL. Ð ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐµ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÑÑ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÑÐ¹ ÑÑÐŸÐ²ÐµÐœÑ ÑÐ»ÐŸÐ¶ÐœÐŸÑÑÐž, ÐœÐŸ ÑÑÐŸ ÑÑÐŸÐžÑ ÑÐŸÐ³ÐŸ.</Text>
+<Text id="1212">ÐÐŸÐŒÐŸÑÑ Ð¿ÐŸÐœÑÑÑ Ð¿ÑÐ³ÑÐ°ÐŒÐŒÑ Greenstone Ð²Ð°ÐŒ Ð¿ÐŸÐŒÐŸÐ³ÑÑ Ð¿ÐŸÐŽÐ±ÐŸÑÐºÐž, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐœÑÐµ Ð² ÑÑÐŸÐŒ ÑÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ðµ, ÐºÐŸÑÐŸÑÑÐµ ÐŒÑ ÑÐœÐ°Ð±ÐŽÐžÐ»Ðž ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÐŒ Ð¿ÑÐžÐŒÐµÑÐ°ÐŒ ÐŸÐ±ÑÑÐ°ÑÑÐµÐ³ÐŸ ÑÑÐŸÐ²ÐœÑ Ð¿ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ STL.</Text>
+<Section id="lists">
+<Title>
+<Text id="1213">Ð¡Ð¿ÐžÑÐºÐž (Lists)</Text>
+</Title>
+<Content>
+<Figure id="programming_a_list_of_integers" class="withLineNumber">
+<Title>
+<Text id="1214">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐ¿ÐžÑÐºÐ° ÑÐµÐ»ÑÑ
+ ÑÐžÑÐµÐ»</Text>
+</Title>
+<CodeLine>#include &lt;iostream.h&gt;</CodeLine>
+<CodeLine/>
+<CodeLine>#define nil 0</CodeLine>
+<CodeLine/>
+<CodeLine>struct intlist {</CodeLine>
+<CodeLine>   int val;</CodeLine>
+<CodeLine>   struct intlist* next;</CodeLine>
+<CodeLine>};</CodeLine>
+<CodeLine/>
+<CodeLine>int total_int_list(intlist* head)</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>   int total = 0;</CodeLine>
+<CodeLine>   intlist* curr = head;</CodeLine>
+<CodeLine>   while (curr!=nil)</CodeLine>
+<CodeLine>   {</CodeLine>
+<CodeLine>       total += curr-&gt;val;</CodeLine>
+<CodeLine>       curr = curr-&gt;next;</CodeLine>
+<CodeLine>   }</CodeLine>
+<CodeLine/>
+<CodeLine>   return total;</CodeLine>
+<CodeLine>}</CodeLine>
+<CodeLine/>
+<CodeLine>void main()</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>   intlist node1 = { 5, nil };</CodeLine>
+<CodeLine>   intlist node2 = { 4, nil };</CodeLine>
+<CodeLine>   node2.next = &amp;node1;</CodeLine>
+<CodeLine/>
+<CodeLine>   int total = total_int_list(&amp;node2);</CodeLine>
+<CodeLine>  cout &lt;&lt; " List items total to: " &lt;&lt; total &lt;&lt; endl;</CodeLine>
+<CodeLine>}</CodeLine>
+</Figure>
+<Text id="1215">Ð¡ÐœÐ°ÑÐ°Ð»Ð° ÐŒÑ ÐžÐ·ÑÑÐžÐŒ ÐŽÐ²Ðµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, ÐºÐŸÑÐŸÑÑÐµ ÑÐµÐ°Ð»ÐžÐ·ÑÑÑ ÑÐµÐ»ÐŸÑÐžÑÐ»ÐµÐœÐœÑÐ¹ ÑÐ¿ÐžÑÐŸÐº. ÐÑÐµÐ²ÐŸÐœÐ°ÑÐ°Ð»ÑÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐŸÑÐœÐŸÐ²ÐœÑÐµ ÑÐžÐ¿Ñ C++ (Ð¿ÑÑÑ "Ð¿ÐŸ Ð¿ÑÐŸÑÐŸÑÐµÐœÐœÐŸÐ¹ ÐŽÐŸÑÐŸÐ¶ÐºÐµ"), ÐŽÐ°Ð»ÐµÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ STL. Ð ÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="programming_a_list_of_integers"/> Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ ÐžÑÑ
+ÐŸÐŽÐœÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, ÐºÐŸÑÐŸÑÐŸÐµ ÐœÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ STL. Ð¡ÑÑÐŸÐºÐž 5-8 ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ ÐŸÑÐœÐŸÐ²ÐœÑÑ ÑÑÑÑÐºÑÑÑÑ ÐŽÐ°ÐœÐœÑÑ
+, ÐºÐŸÑÐŸÑÑÑ ÐŒÑ ÑÐŸÐ±ÐžÑÐ°ÐµÐŒÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ: Ð¿ÐŸÐ»Ðµ val ÑÐŸÑ
+ÑÐ°ÐœÑÐµÑ ÑÐµÐ»ÐŸÑÐžÑÐ»ÐµÐœÐœÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ, a next ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐœÐ° ÑÐ»ÐµÐŽÑÑÑÐžÐ¹ ÑÐ»ÐµÐŒÐµÐœÑ Ð² ÑÐ¿ÐžÑÐºÐµ - ÐºÐ»Ð°ÑÑÐžÑÐµÑÐºÐŸÐµ Ð²ÐŸÐ¿Ð»ÐŸÑÐµÐœÐžÐµ ÑÐ¿ÐžÑÐºÐ° ÑÐ²ÑÐ·ÐµÐ¹.</Text>
+<Text id="1216">Ð§ÑÐŸÐ±Ñ Ð¿ÑÐŸÐŽÐµÐŒÐŸÐœÑÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÑÑÑÑÐºÑÑÑÑ ÐŽÐ°ÐœÐœÑÑ
+, ÐŸÑÐœÐŸÐ²ÐœÐ°Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° (ÑÑÑÐŸÐºÐž 23-32), ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑ ÑÐµÐ»ÐŸÑÐžÑÐ»ÐµÐœÐœÑÐ¹ ÑÐ¿ÐžÑÐŸÐº Ñ ÑÐ»ÐµÐŒÐµÐœÑÐ°ÐŒÐž [5, 4]. Ð¢ÐŸÐ³ÐŽÐ° Ð²ÑÐ·ÑÐ²Ð°ÐµÑÑÑ ÑÑÐœÐºÑÐžÑ total_int_list (ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÐ°Ñ Ð² ÑÑÑÐŸÐºÐ°Ñ
+ 10-21), ÐºÐŸÑÐŸÑÐ°Ñ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐµÐµ ÐµÐŽÐžÐœÑÑÐ²ÐµÐœÐœÐŸÐ³ÐŸ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐ° Ð±ÐµÑÐµÑ ÑÐºÐ°Ð·Ð°ÑÐµÐ»Ñ ÐœÐ° Ð²ÐµÑÑÐžÐœÑ ÑÐ¿ÐžÑÐºÐ° Ðž ÑÑÐŒÐŒÐžÑÑÐµÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ Ð² ÐœÐµÐŒ. ÐÐŸÐ·Ð²ÑÐ°ÑÐµÐœÐœÑÐ¹ ÐŸÑÐ²ÐµÑ (Ð² ÐœÐ°ÑÐµÐŒ Ð¿ÑÐžÐŒÐµÑÐµ 9) Ð²ÑÐ²ÐŸÐŽÐžÑÑÑ ÐœÐ° ÑÐºÑÐ°Ðœ.</Text>
+<Text id="1217">ÐÑÐœÐŸÐ²ÐœÐ°Ñ ÑÐ°Ð±ÐŸÑÐ° ÐŽÐŸÑÑÐžÐ³Ð°ÐµÑÑÑ ÑÑÑÐŸÐºÐ°ÐŒÐž 12-18. Ð¡ÐœÐ°ÑÐ°Ð»Ð° Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑÑ ÐœÐµÐ±ÐŸÐ»ÑÑÐ°Ñ ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÑ: Ð»ÐŸÐºÐ°Ð»ÑÐœÐ°Ñ Ð¿ÐµÑÐµÐŒÐµÐœÐœÐ°Ñ total ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐžÐ²Ð°ÐµÑ nil Ðž ÑÐžÐ³Ð³, ÑÑÐŸÐ±Ñ ÑÐºÐ°Ð·Ð°ÑÑ ÐœÐ° ÐœÐ°ÑÐ°Ð»ÐŸ ÑÐ¿ÐžÑÐºÐ°. Ð¢ÐŸÐ³ÐŽÐ° ÑÐžÐºÐ» Ñ ÑÑÐ»ÐŸÐ²ÐžÐµÐŒ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑ ÑÐµÐºÑÑÐžÐ¹ ÑÐµÐ»ÐŸÑÐžÑÐ»ÐµÐœÐœÑÐ¹ ÑÐ»ÐµÐŒÐµÐœÑ Ð² ÑÐ¿ÐžÑÐŸÐº ÐŽÐ»Ñ ÐŸÐ±ÑÐµÐ³ÐŸ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ (total += curr. >val;) Ð¿ÐµÑÐµÐŽ Ð¿ÐµÑÐµÑ
+ÐŸÐŽÐŸÐŒ Ðº ÑÐ»ÐµÐŽÑÑÑÐµÐŒÑ ÑÐ»ÐµÐŒÐµÐœÑÑ (curr = curr. >next;). ÐŠÐžÐºÐ» Ñ ÑÑÐ»ÐŸÐ²ÐžÐµÐŒ Ð·Ð°ÐºÐ°ÐœÑÐžÐ²Ð°ÐµÑÑÑ, ÐºÐŸÐ³ÐŽÐ° curr ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ ÑÐ°Ð²ÐœÑÐŒ nil, Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°Ñ, ÑÑÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² ÐŽÐ»Ñ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž Ð±ÐŸÐ»ÑÑÐµ ÐœÐµ ÐŸÑÑÐ°Ð»ÐŸÑÑ.</Text>
+<Figure id="programming_a_list_of_integers_using_stl">
+<Title>
+<Text id="1218">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐ¿ÐžÑÐºÐ° ÑÐµÐ»ÑÑ
+ ÑÐžÑÐµÐ» Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ STL</Text>
+</Title>
+<CodeLine>#include &lt;iostream.h&gt;</CodeLine>
+<CodeLine>#include &lt;list&gt;</CodeLine>
+<CodeLine/>
+<CodeLine>int total_int_list(list&lt;int&gt;* head)</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>   int total = 0;</CodeLine>
+<CodeLine>   list&lt;int&gt;::iterator curr = head-&gt;begin();</CodeLine>
+<CodeLine>   while (curr!=head-&gt;end())</CodeLine>
+<CodeLine>   {</CodeLine>
+<CodeLine>       total += *curr;</CodeLine>
+<CodeLine>       curr++;</CodeLine>
+<CodeLine>   }</CodeLine>
+<CodeLine/>
+<CodeLine>   return total;</CodeLine>
+<CodeLine>}</CodeLine>
+<CodeLine/>
+<CodeLine>void main()</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>   list&lt;int&gt; vals;</CodeLine>
+<CodeLine>   vals.push_back(5);</CodeLine>
+<CodeLine>   vals.push_back(4);</CodeLine>
+<CodeLine/>
+<CodeLine>   int total = total_int_list(&amp;vals);</CodeLine>
+<CodeLine>   cout &lt;&lt; " List items total to: " &lt;&lt; total &lt;&lt; endl;</CodeLine>
+<CodeLine>}</CodeLine>
+</Figure>
+<Text id="1219">Ð ÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="programming_a_list_of_integers_using_stl"/> Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÑÐºÐ²ÐžÐ²Ð°Ð»ÐµÐœÑÐœÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, ÑÐŸÐ·ÐŽÐ°ÐœÐœÑÑ Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ STL. ÐÐŸÐ»ÑÑÐµ ÐœÐµÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÐž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ Ð¿ÐŸÐŽÑ
+ÐŸÐŽÑÑÑÑ ÑÑÑÑÐºÑÑÑÑ ÐŽÐ°ÐœÐœÑÑ
+ Ð² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐµ; Ð²ÑÐµ, ÑÑÐŸ ÑÐ²Ð»ÑÐµÑÑÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÑÐŒ - ÑÑÐŸ ffinclude &lt;list&gt; ÑÐºÐ°Ð·Ð°ÐœÐžÐµ Ð² ÑÑÑÐŸÐºÐµ 2, ÐºÐŸÑÐŸÑÐŸÐµ Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð²ÐµÑÑÐžÑ ÑÐ°Ð±Ð»ÐŸÐœÐ° ÐŽÐ»Ñ ÑÐ¿ÐžÑÐºÐ°, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÐŸÐ³ÐŸ Ð² STL. ÐÐ±ÑÐµÐºÑ ÐœÐ°Ð·ÑÐ²Ð°ÑÑ "ÐºÐ»Ð°ÑÑ-ÐºÐŸÐœÑÐµÐ¹ÐœÐµÑ", Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ, ÐºÐŸÐ³ÐŽÐ° ÐŒÑ ÐŸÐ±ÑÑÐ²Ð»ÑÐµÐŒ Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÑ ÑÑÐŸÐ³ÐŸ ÑÐžÐ¿Ð°, ÐŒÑ ÑÐ°ÐºÐ¶Ðµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÐŒ ÑÐžÐ¿, Ð² ÐºÐŸÑÐŸÑÐŸÐŒ ÐŒÑ Ñ
+ÐŸÑÐžÐŒ ÐµÐµ ÑÐŸÑ
+ÑÐ°ÐœÐžÑÑ. Ð ÑÑÑÐŸÐºÐµ 19 ÑÐµÐ»ÐŸÑÐžÑÐ»ÐµÐœÐœÑÐ¹ ÑÐ¿ÐžÑÐŸÐº ÑÐµÐ°Ð»ÐžÐ·ÐŸÐ²Ð°Ðœ Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ ÐŸÐ¿ÐµÑÐ°ÑÐŸÑÐ° list&lt;int&gt; vals;. Ð­Ð»ÐµÐŒÐµÐœÑÑ ÐŒÐŸÐ¶ÐœÐŸ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ Ðº ÐŸÐ±ÑÐµÐºÑÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÑÑÐœÐºÑÐžÑ-ÑÐ»ÐµÐœ push_back(), ÐºÐ°Ðº ÑÑÐŸ ÑÐŽÐµÐ»Ð°ÐœÐŸ Ð² ÑÑÑÐŸÐºÐ°Ñ
+ 20-21.</Text>
+<Text id="1220">ÐÑÐœÐŸÐ²ÐœÐ°Ñ ÑÐ°Ð±ÐŸÑÐ° Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐ° ÑÑÑÐŸÐºÐ°ÐŒÐž 6-12. ÐÑÑÑ Ð²ÑÐµ ÐµÑÐµ ÐŽÐ²Ðµ ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÐž Ðž ÑÐžÐºÐ» Ñ ÑÑÐ»ÐŸÐ²ÐžÐµÐŒ, ÐœÐŸ ÐŸÑÐ»ÐžÑÐ°ÑÑÐžÐ¹ÑÑ ÐŸÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐœÐŸÐ³ÐŸ Ð² Ð¿ÑÐµÐŽÑÐŽÑÑÐµÐŒ ÑÐ»ÑÑÐ°Ðµ. ÐÐŸÐ²ÑÐ¹ ÑÐžÐœÑÐ°ÐºÑÐžÑ ÐžÐŒÐµÐµÑ ÐœÐµÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÑÐµÐ³ÐŸ ÑÐŸ ÑÑÐ°ÑÑÐŒ. ÐÐ»ÑÑÐµÐ²ÑÐŒ ÐŒÐŸÐŒÐµÐœÑÐŸÐŒ ÑÑÐŸÐ³ÐŸ ÐœÐŸÐ²ÐŸÐ³ÐŸ ÑÐ¿ÐŸÑÐŸÐ±Ð° ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž ÑÐ²Ð»ÑÐµÑÑÑ Ð¿ÐµÑÐµÐŒÐµÐœÐœÐ°Ñ ÑÐžÐ¿Ð° iterator (ÑÑÑÐŸÐºÐ° 7). Ð STL ÐŒÐœÐŸÐ³ÐŸ ÐºÐ»Ð°ÑÑÐŸÐ² Ð²ÐºÐ»ÑÑÐ°ÑÑ ÑÐžÐ¿Ñ iterator, ÑÑÐŸÐ±Ñ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÑÑ ÐŸÐŽÐœÐŸÑÐŸÐŽÐœÑÐ¹ ÑÐ¿ÐŸÑÐŸÐ± ÑÐ°Ð±ÐŸÑÑ ÑÐµÑÐµÐ· Ð¿ÐŸÑÐ»ÐµÐŽÐŸÐ²Ð°ÑÐµÐ»ÑÐœÐŸÑÑÑ ÐºÐŸÐœÑÐµÐ¹ÐœÐµÑÐœÑÑ
+ ÐŸÐ±ÑÐµÐºÑÐŸÐ². ÐÐµÑÐ²ÑÐ¹ ÑÐ»ÐµÐŒÐµÐœÑ Ð²ÐŸÐ·Ð²ÑÐ°ÑÐµÐœ Ñ begin(), Ðž ÑÐŸÐ»ÑÐºÐŸ ÐŸÐŽÐžÐœ - Ð¿ÐŸÑÐ»ÐµÐŽÐœÐžÐ¹ ÑÐ»ÐµÐŒÐµÐœÑ Ñ end(). ÐÐµÑÐµÐŒÐµÑÐµÐœÐžÐµ Ðº ÑÐ»ÐµÐŽÑÑÑÐµÐŒÑ ÑÐ»ÐµÐŒÐµÐœÑÑ ÐŽÐŸÑÑÐžÐ³ÐœÑÑÐŸ ÐŸÐ¿ÐµÑÐ°ÑÐžÐµÐ¹ Ð¿ÑÐžÑÐ°ÑÐµÐœÐžÑ ++, ÐºÐŸÑÐŸÑÐ°Ñ Ð¿ÐµÑÐµÐ³ÑÑÐ¶ÐµÐœÐ° ÐºÐ»Ð°ÑÑÐŸÐŒ iterator, ÑÑÐŸÐ±Ñ ÐŸÑÑÑÐµÑÑÐ²ÐžÑÑ ÑÑÑ Ð·Ð°ÐŽÐ°ÑÑ, Ðž Ðº Ð·ÐœÐ°ÑÐµÐœÐžÑ, ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐœÐŸÐŒÑ ÑÐ°ÐŒ, ÐŸÐ±ÑÐ°ÑÐ°ÑÑÑÑ ÑÐµÑÐµÐ· ÑÐ°Ð·ÑÐŒÐµÐœÐŸÐ²Ð°ÐœÐžÐµ (*ÑÐžÐ³Ð³ ÐœÐ° ÑÑÑÐŸÐºÐµ 10), ÐºÐŸÑÐŸÑÑÐ¹ ÑÐ°ÐºÐ¶Ðµ ÑÐ²Ð»ÑÐµÑÑÑ Ð¿ÐµÑÐµÐ³ÑÑÐ¶ÐµÐœÐœÑÐŒ.</Text>
+<Text id="1221">STL-ÑÐµÐ°Ð»ÐžÐ·Ð°ÑÐžÑ ÑÑÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐœÐµÐŒÐœÐŸÐ³ÐŸ ÐŒÐµÐœÑÑÐµ, ÑÐµÐŒ ÐŸÐ±ÑÑÐœÐ°Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° (25 ÑÑÑÐŸÐº Ð¿ÑÐŸÑÐžÐ² 31). Ð­ÑÐŸ ÐŽÐŸÑÑÐžÐ¶ÐµÐœÐžÐµ ÐœÐ°ÐžÐ±ÐŸÐ»ÐµÐµ Ð²Ð°Ð¶ÐœÐŸ ÐŽÐ»Ñ Ð±ÐŸÐ»ÑÑÐžÑ
+ Ð¿ÑÐŸÐµÐºÑÐŸÐ², Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ ÐŸÐ±ÑÐµÐºÑ list STL Ð±ÐŸÐ»ÐµÐµ ÐŒÐŸÑÐœÑÐ¹, ÑÐµÐŒ ÐžÐ»Ð»ÑÑÑÑÐžÑÑÐµÐŒÑÐ¹ ÐœÐ°ÐŒÐž Ð¿ÑÐžÐŒÐµÑ. ÐÐŸÐ·ÑÐŒÐµÐŒ Ðº Ð¿ÑÐžÐŒÐµÑÑ, ÐŽÐ²ÐŸÐ¹ÐœÐŸÐ¹ ÑÐ²ÑÐ·Ð°ÐœÐœÑÐ¹ ÑÐ¿ÐžÑÐŸÐº, ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÐŸÑÐŒ Ð²ÑÑÐ°Ð²ÐºÐž Ðž ÑÐŽÐ°Ð»ÐµÐœÐžÑ - ÐºÐŸÐµ-ÑÑÐŸ, ÑÑÐŸ ÑÑÐµÐ±ÐŸÐ²Ð°Ð»ÐŸ Ð±Ñ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÑÑ
+ ÑÑÐžÐ»ÐžÐ¹ Ð¿ÐŸ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐŽÐŸÐ¿ÐŸÐ»ÐµÐœÐžÐ¹ Ðº ÐŸÑÐœÐŸÐ²ÐœÐŸÐ¹ ÑÐµÐ»ÐŸÑÐžÑÐ»ÐµÐœÐœÐŸÐ¹ Ð²ÐµÑÑÐžÐž ÑÐ¿ÐžÑÐºÐ°.</Text>
+<Text id="1222">ÐÐ±ÑÐ°ÑÐžÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ, ÑÑÐŸ Ð¿Ð°ÑÐ°ÐŒÐµÑÑ ÐŽÐ»Ñ total_int_list ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="programming_a_list_of_integers_using_stl"/> Ð±ÑÐ» ÑÐµÐ°Ð»ÐžÐ·ÐŸÐ²Ð°Ðœ ÐºÐ°Ðº ÑÐºÐ°Ð·Ð°ÑÐµÐ»Ñ, ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐŸÐ²Ð°Ð²ÑÐžÐ¹ ÑÐºÐ°Ð·Ð°ÑÐµÐ»Ñ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐŸÐŒÑ Ð² total_int_list ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="programming_a_list_of_integers"/>. Ð STL Ð·Ð°ÑÐ°ÑÑÑÑ Ð±ÐŸÐ»ÐµÐµ ÐµÑÑÐµÑÑÐ²ÐµÐœÐœÐŸ (Ðž Ð±ÐŸÐ»ÐµÐµ Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÐŸ) ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÑÑÑÐ»ÐºÐž, Ð° ÐœÐµ ÑÐºÐ°Ð·Ð°ÑÐµÐ»Ðž. Ð¢ÐŸÐ³ÐŽÐ° Ð¿Ð°ÑÐ°ÐŒÐµÑÑ ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ list&lt;int&gt;&amp; head, Ðž ÐµÐ³ÐŸ ÑÑÐœÐºÑÐžÐž-ÑÐ»ÐµÐœÑ Ð²ÑÐ·ÑÐ²Ð°ÑÑÑÑ ÑÐžÐœÑÐ°ÐºÑÐžÑÐŸÐŒ head, begin 0; Ðž ÑÐ°Ðº ÐŽÐ°Ð»ÐµÐµ.</Text>
+</Content>
+</Section>
+<Section id="maps">
+<Title>
+<Text id="1223">Maps</Text>
+</Title>
+<Content>
+<Text id="1224">ÐÑÐž ÑÐµÐ°Ð»ÐžÐ·Ð°ÑÐžÐž ÑÐžÑÑÐµÐŒÑ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐºÐž, Ð¿ÐŸÐ»ÐµÐ·ÐœÐŸ ÐžÐŒÐµÑÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐžÑ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² Ð² ÐŒÐ°ÑÑÐžÐ²Ðµ, ÐžÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐœÐŸÐŒ ÑÐµÐºÑÑÐŸÐ²ÑÐŒÐž ÑÑÑÐŸÐºÐ°ÐŒÐž, Ð° ÐœÐµ ÑÐžÑÐ»ÐŸÐ²ÑÐŒÐž ÐžÐœÐŽÐµÐºÑÐ°ÐŒÐž. Ð Greenstone, ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÑÐŸ ÐŸÑÐµÐœÑ ÑÐ¿ÑÐŸÑÐ°ÐµÑ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐžÐµ ÐŒÐ°ÐºÑÐŸÑÐ°Ð¹Ð»ÐŸÐ², ÐºÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐŸÐœÐž ÑÑÐžÑÐ°Ð»ÐžÑÑ, Ðž ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž. Ð¢ÐžÐ¿ ÐŽÐ°ÐœÐœÑÑ
+, ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÑ ÑÐ°ÐºÐŸÐ¹ ÐŽÐŸÑÑÑÐ¿, ÐœÐ°Ð·ÑÐ²Ð°ÑÑ associative array (Ð°ÑÑÐŸÑÐžÐ°ÑÐžÐ²ÐœÑÐŒ ÐŒÐ°ÑÑÐžÐ²ÐŸÐŒ), Ðž ÐŸÐœ ÑÐ°ÑÑÐŸ Ð²ÑÑÑÐ°ÐžÐ²Ð°ÐµÑÑÑ Ð² ÑÐŸÐ²ÑÐµÐŒÐµÐœÐœÑÐµ ÑÐ·ÑÐºÐž Ð²ÑÑÐŸÐºÐŸÐ³ÐŸ ÑÑÐŸÐ²ÐœÑ. ÐÐœ ÑÐ°ÐºÐ¶Ðµ ÐžÐ·Ð²ÐµÑÑÐµÐœ Ð¿ÐŸÐŽ ÐžÐŒÐµÐœÐµÐŒ hash array (ÐŸÑÐŸÐ±ÐµÐœÐœÐŸ Ð² Perl), ÑÐ°Ðº ÐºÐ°Ðº Ñ
+ÐµÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ - ÐœÐŸÑÐŒÐ°Ð»ÑÐœÐ°Ñ ÐŒÐµÑÐŸÐŽÐžÐºÐ°, Ð¿ÐŸ ÐŸÐ±ÑÐºÐœÐŸÐ²ÐµÐœÐžÑ ÑÐµÐ°Ð»ÐžÐ·ÑÑÑÐ°Ñ ÑÐµÐºÑÑÐŸÐ²ÑÐ¹ ÐžÐœÐŽÐµÐºÑ.</Text>
+<Figure id="using_associative_arrays_in_stl" class="withLineNumber">
+<Title>
+<Text id="1225">ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ Ð°ÑÑÐŸÑÐžÐ°ÑÐžÐ²ÐœÑÑ
+ ÐŒÐ°ÑÑÐžÐ²ÐŸÐ² Ð² STL</Text>
+</Title>
+<CodeLine>#include &lt;iostream.h&gt;</CodeLine>
+<CodeLine>#include &lt;map&gt;</CodeLine>
+<CodeLine/>
+<CodeLine>int total_int_table(map&lt;char*, int&gt;&amp; table)</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>   int total = 0;</CodeLine>
+<CodeLine>   map&lt;char*, int&gt;::iterator curr = table.begin();</CodeLine>
+<CodeLine>   while (curr!=table.end())</CodeLine>
+<CodeLine>   {</CodeLine>
+<CodeLine>       total += (curr-&gt;second);</CodeLine>
+<CodeLine>       curr++;</CodeLine>
+<CodeLine>   }</CodeLine>
+<CodeLine/>
+<CodeLine>   return total;</CodeLine>
+<CodeLine>}</CodeLine>
+<CodeLine/>
+<CodeLine>int main()</CodeLine>
+<CodeLine>{</CodeLine>
+<CodeLine>   map&lt;char*, int&gt; table;</CodeLine>
+<CodeLine>   table["Alice"] = 31;</CodeLine>
+<CodeLine>   table["Peter"] = 24;</CodeLine>
+<CodeLine>   table["Mary"]   = 47;</CodeLine>
+<CodeLine/>
+<CodeLine>   int total = total_int_table(table);</CodeLine>
+<CodeLine>   cout &lt;&lt; " Age total: " &lt;&lt; total &lt;&lt; endl;</CodeLine>
+<CodeLine>  }</CodeLine>
+</Figure>
+<Text id="1226">Ð STL Ð°ÑÑÐŸÑÐžÐ°ÑÐžÐ²ÐœÑÐµ ÐŒÐ°ÑÑÐžÐ²Ñ ÐŽÐŸÑÑÐžÐ³Ð°ÑÑÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ ÐŸÐ±ÑÐµÐºÑÐ° ÑÐ°Ñ. Ð ÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="using_associative_arrays_in_stl"/> Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð¿ÑÐžÐŽÑÐŒÐ°ÐœÐœÑÐ¹ Ð¿ÑÐžÐŒÐµÑ, Ð² ÐºÐŸÑÐŸÑÐŸÐŒ Ð²ÐŸÐ·ÑÐ°ÑÑ ÑÑÐµÑ
+ ÑÐµÐ»ÐŸÐ²ÐµÐº (ÐÐ»ÐžÑÐ°, ÐÐžÑÐµÑ Ðž ÐÑÑÐž) Ñ
+ÑÐ°ÐœÐžÑÑÑ Ð² Ð°ÑÑÐŸÑÐžÐ°ÑÐžÐ²ÐœÐŸÐŒ ÐŒÐ°ÑÑÐžÐ²Ðµ Ð¿ÐŸÐŽ ÐžÑ
+ ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÑÐŒÐž ÐžÐŒÐµÐœÐ°ÐŒÐž (ÑÑÑÐŸÐºÐž 19-22). ÐÑÐŸÐ±Ð»ÐµÐŒÐ° ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸÐ±Ñ Ð·Ð°Ð¿ÐžÑÐ°ÑÑ ÑÑÐœÐºÑÐžÑ, ÐºÐŸÑÐŸÑÐ°Ñ Ð²ÑÑÐžÑÐ»ÑÐµÑ Ð¿ÐŸÐ»ÐœÑÐ¹ Ð²ÐŸÐ·ÑÐ°ÑÑ Ð»ÑÐŽÐµÐ¹, ÐœÐµ Ð·ÐœÐ°Ñ, ÑÐºÐŸÐ»ÑÐºÐŸ ÐžÑ
+ ÐžÐŒÐµÐµÑÑÑ ÐžÐ»Ðž ÐºÐ°ÐºÐŸÐ²Ñ ÐžÑ
+ ÐžÐŒÐµÐœÐ°. ÐÐŸÐœÐµÑÐœÐŸ, ÑÑÐŸ ÐŒÐŸÐ³Ð»ÐŸ Ð±Ñ Ð±ÑÑÑ ÑÐµÑÐµÐœÐŸ Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÑ
+ ÑÐžÑÐ»ÐŸÐ²ÑÑ
+ ÐŒÐ°ÑÑÐžÐ²ÐŸÐ² ÑÐµÐ»ÑÑ
+ ÑÐžÑÐµÐ». ÐÐ°ÐœÐœÑÐ¹ Ð¿ÑÐžÐŒÐµÑ Ð±ÑÐ» Ð¿ÑÐžÐŽÑÐŒÐ°Ðœ, ÑÑÐŸÐ±Ñ Ð¿ÑÐŸÐŽÐµÐŒÐŸÐœÑÑÑÐžÑÐŸÐ²Ð°ÑÑ, ÑÑÐŸ ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž ÑÐ°Ñ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÑÑ Ð¿ÐŸÐŽÐŸÐ±ÐžÐµ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž Ñ ÐŸÐ±ÑÐµÐºÑÐŸÐŒ list ÑÐŸÐ²ÐŒÐµÑÑÐœÐŸ Ñ iterator.</Text>
+<Text id="1227">ÐÐŸÐŽÐŸÐ±ÐœÐŸ list, map ÐŸÑÐœÐŸÑÐžÑÑÑ Ðº ÐºÐ»Ð°ÑÑÑ-ÐºÐŸÐœÑÐµÐ¹ÐœÐµÑÑ. ÐÐŽÐœÐ°ÐºÐŸ, Ð¿ÑÐž ÐŸÐ±ÑÑÐ²Ð»ÐµÐœÐžÐž Ð¿ÐµÑÐµÐŒÐµÐœÐœÐŸÐ¹ ÑÑÐŸÐ³ÐŸ ÑÐžÐ¿Ð° ÐŒÑ ÐŽÐŸÐ»Ð¶ÐœÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÐŽÐ²Ðµ<FootnoteRef id="5"/> Ð²ÐµÑÐž: ÐžÐœÐŽÐµÐºÑÐœÑÐ¹ ÑÐžÐ¿, Ðž ÑÐžÐ¿ ÑÐ»ÐµÐŒÐµÐœÑÐ°. ÐÐ°Ðº Ð²Ñ ÐŒÐŸÐ³Ð»Ðž Ð·Ð°ÐŒÐµÑÐžÑÑ Ð² ÑÑÑÐŸÐºÐµ 19, ÐŒÑ Ð¿ÐŸÐ»ÑÑÐ°ÐµÐŒ Ð°ÑÑÐŸÑÐžÐ°ÑÐžÐ²ÐœÑÐ¹ ÐŒÐ°ÑÑÐžÐ², ÐºÐŸÑÐŸÑÑÐ¹ ÑÐŸÑ
+ÑÐ°ÐœÑÐµÑ ÑÐµÐ»ÑÐµ ÑÐžÑÐ»Ð°, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ char* (ÐºÐŸÑÐŸÑÑÐ¹ ÑÐ²Ð»ÑÐµÑÑÑ ÑÑÑÐŸÐºÐŸÐ¹, ÐŸÐ±ÑÑÐ²Ð»ÐµÐœÐœÐŸÐ¹ Ð² C++) ÐºÐ°Ðº ÐžÐœÐŽÐµÐºÑÐœÑÐ¹ ÑÐžÐ¿, ÑÐŸÐ¿ÑÐŸÐ²ÐŸÐ¶ÐŽÐ°ÐµÐŒÑÐ¹ int Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÑÐžÐ¿Ð° ÑÐ»ÐµÐŒÐµÐœÑÐ°.</Text>
+<Text id="1228">ÐÑÑÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐ² ÑÐŸÑ
+ÑÐ°ÐœÐžÑÑ ÑÐ»ÐµÐŒÐµÐœÑÑ Ð² Ð°ÑÑÐŸÑÐžÐ°ÑÐžÐ²ÐœÐŸÐŒ ÐŒÐ°ÑÑÐžÐ²Ðµ. Ð ÐŽÐ°ÐœÐœÐŸÐŒ Ð¿ÑÐžÐŒÐµÑÐµ Ð² ÑÑÑÐŸÐºÐ°Ñ
+ 20-22 Ð¿ÐµÑÐµÐ³ÑÑÐ¶ÐµÐœÐœÑÐ¹ ÐŒÐ°ÑÑÐžÐ² ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑÑÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ [], ÑÑÐŸÐ±Ñ ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·ÐžÑÐŸÐ²Ð°ÑÑ ÑÐ°Ð±Ð»ÐžÑÑ Ñ Ð²ÐŸÐ·ÑÐ°ÑÑÐ°ÐŒÐž ÑÑÐžÑ
+ ÑÑÐµÑ
+ ÑÐµÐ»ÐŸÐ²ÐµÐº. ÐÐŸÐŽÐŸÐ±ÐœÐŸ total_int_table, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»ÐœÑÐµÑ ÐŸÑÐœÐŸÐ²ÐœÐŸÐµ Ð²ÑÑÐžÑÐ»ÐµÐœÐžÐµ Ð² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐµ, ÐœÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="programming_a_list_of_integers"/> ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ total_int_list Ð€Ð°ÐºÑÐžÑÐµÑÐºÐž, ÐŸÐœÐž Ð¿ÐŸÑÑÐž ÐžÐŽÐµÐœÑÐžÑÐœÑ, Ðž ÑÑÐŸ ÐœÐµ ÐœÐžÐºÐ°ÐºÐŸÐµ ÑÐŸÐ²Ð¿Ð°ÐŽÐµÐœÐžÐµ. STL ÑÑÑÐŽÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐžÐµ ÑÐ°Ðº, ÑÑÐŸÐ±Ñ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÐŸÐ±ÑÐµÐºÑÑ Ð²ÑÐµ ÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ð»Ðž ÑÐµ Ð¶Ðµ ÑÐ°ÐŒÑÐµ ÑÑÐœÐŽÐ°ÐŒÐµÐœÑÐ°Ð»ÑÐœÑÐµ ÐŸÐ¿ÐµÑÐ°ÑÐžÐž. Ð­ÑÐŸ ÐŸÑÐŸÐ±ÐµÐœÐœÐŸ ÑÐŸÑÐœÐŸ Ð² ÐŸÑÐœÐŸÑÐµÐœÐžÐž ÐžÑÐµÑÐ°ÑÐŸÑÐŸÐ². ÐÐµÐ±ÐŸÐ»ÑÑÐžÐµ ÑÐ°Ð·Ð»ÐžÑÐžÑ ÐŒÐµÐ¶ÐŽÑ ÐŽÐ²ÑÐŒÑ ÑÑÐœÐºÑÐžÑÐŒÐž ÑÐŸÑÑÐŸÑÑ Ð² ÑÐŸÐŒ, ÑÑÐŸ ÐžÑÐµÑÐ°ÑÐŸÑ ÑÐµÐ¿ÐµÑÑ Ð¿ÐŸÐ»ÑÑÐµÐœ ÐžÐ· map&lt;char*, int&gt; Ðž ÐŽÐŸÑÑÑÐ¿ Ðº ÐµÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ°ÐŒ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ ÑÐŸÐ²ÐŒÐµÑÑÐœÐŸ Ñ curr .&gt;second(), Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ ÑÐ°Ð·ÑÐŒÐµÐœÐŸÐ²Ð°ÐœÐžÐµ Ð¿ÐµÑÐµÐŒÐµÐœÐœÐŸÐ¹ (*ÑÐžÐ³Ð³) ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐŸ, ÑÑÐŸÐ±Ñ Ð²ÐŸÐ·Ð²ÑÐ°ÑÐžÑÑ ÐŸÐ±ÑÐµÐºÑ ÑÐžÐ¿Ð°ÑÑÐ³. ÐÐœ ÑÐŸÐ·ÐŽÐ°ÐµÑ Ð·Ð°Ð¿ÐžÑÑ Ðž ÐžÐœÐŽÐµÐºÑÐœÐŸÐ³ÐŸ ÐžÐŒÐµÐœÐž (first), Ðž Ð·ÐœÐ°ÑÐµÐœÐžÑ ÑÐ»ÐµÐŒÐµÐœÑÐ° (second), ÐœÐŸ ÐŒÑ Ñ
+ÐŸÑÐžÐŒ ÐžÐŒÐµÑÑ ÑÐŸÐ»ÑÐºÐŸ Ð¿ÐŸÑÐ»ÐµÐŽÐœÐµÐµ. ÐÑÐŸÐŒÐµ ÑÑÐŸÐ³ÐŸ, Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐŸÑÑÐ°ÐµÑÑÑ ÑÐŸÐ¹Ð¶Ðµ ÑÐ°ÐŒÐŸÐ¹. ÐÐŽÐžÐœÑÑÐ²ÐµÐœÐœÐŸÐµ ÐŸÑÑÐ°ÑÑÐµÐµÑÑ ÐŸÑÐ»ÐžÑÐžÐµ - ÑÑÐŸ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÐµ ÐµÐŽÐžÐœÑÑÐ²ÐµÐœÐœÐŸÐ³ÐŸ Ð°ÑÐ³ÑÐŒÐµÐœÑÐ° ÑÑÐœÐºÑÐžÐž Ñ ÑÐºÐ°Ð·Ð°ÑÐµÐ»Ñ ÐœÐ° ÑÑÑÐ»ÐºÑ - ÑÐ²Ð»ÑÐµÑÑÑ ÐœÐµÐ·ÐœÐ°ÑÐžÑÐµÐ»ÑÐœÑÐŒ.</Text>
+<Text id="1229">ÐÐ²Ð° ÐŽÑÑÐ³ÐžÑ
+ ÑÐžÐ¿Ð° STL, ÑÐžÑÐŸÐºÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐµ Ð² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐµ Greenstone - ÑÑÐŸ vector Ðž set. ÐÐµÑÐ²ÑÐ¹ ÐŸÐ±Ð»ÐµÐ³ÑÐ°ÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶Ð°ÐœÐžÐµ ÐŽÐžÐœÐ°ÐŒÐžÑÐµÑÐºÐžÑ
+ ÐŒÐ°ÑÑÐžÐ²ÐŸÐ², Ð° Ð¿ÐŸÑÐ»ÐµÐŽÐœÐžÐ¹ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÑ ÐŒÐ°ÑÐµÐŒÐ°ÑÐžÑÐµÑÐºÐžÐµ ÐŸÐ¿ÐµÑÐ°ÑÐžÐž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÑÐžÐ¿Ð° ÐŸÐ±ÑÐµÐŽÐžÐœÐµÐœÐžÑ, Ð¿ÐµÑÐµÑÐµÑÐµÐœÐžÑ Ðž ÑÐ°Ð·Ð»ÐžÑÐžÑ.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="bibliography">
+<Title>
+<Text id="1230">ÐÐžÑÐµÑÐ°ÑÑÑÐ°</Text>
+</Title>
+<Content>
+<Text id="1231">Aulds, C. (2000) <i>Linux Apache Web Server Administration</i>. Sybex.</Text>
+<Text id="1232">Bainbridge, D., Buchanan, G., McPherson, J., Jones, S., Mahoui, A. and Witten, I.H. (2001) âGreenstone: A platform for distributed digital library development.â Research Report, Computer Science Department, University of Waikato, New Zealand.</Text>
+<Text id="1233">Christiansen, T. Torkington, N. and Wall, L. (1998) <i>Perl Cookbook.</i> O'Reilly and Associates.</Text>
+<Text id="1234">Coar, K.A.L. (1998) <i>Apache Server For Dummies</i>. IDG Books.</Text>
+<Text id="1235">Deitel, H.M. and Deitel, P.J. (1994) <i>C++: How to Program</i>. Prentice Hall, Englewood Cliffs, New Jersey.</Text>
+<Text id="1236">Dublin Core (2001) âThe Dublin Core Metadata Initiativeâ at http://purl.org/dc/, accessed 16 January 2001.</Text>
+<Text id="1237">Josuttis, N.M. (1999) <i>The C++ standard library: a tutorial and reference.</i> Addison-Wesley, 1999.</Text>
+<Text id="1238">Keller, M. and Holden, G. (1999) <i>Apache Server for Windows Little Black Book</i>. Coriolis Group.</Text>
+<Text id="1239">Schwartz, R.L. and Christiansen, T. (1997) <i>Learning Perl</i>(2nd Edition). O'Reilly and Associates.</Text>
+<Text id="1240">Slama, D., Garbis, J. and Russell, P. (1999) <i>Enterprise CORBA</i>. Prentice Hall, Englewood Cliffs, New Jersey.</Text>
+<Text id="1241">Stroustroup, B. (1997) <i>The C++ Programming Language</i>. Addison-Wesley.</Text>
+<Text id="1242">Thiele, H. (1997) âThe Dublin Core and Warwick Framework: A Review of the Literature, March 1995âSeptember 1997.â <i>D-Lib Magazine</i>, January. &lt;http://www.dlib.org/dlib/january98/01thiele.html&gt;</Text>
+<Text id="1243">Wall, L., Christiansen, T. and Orwant, J. (2000) <i>Programming Perl</i>(3rd Edition). O'Reilly and Associates.</Text>
+<Text id="1244">Weibel, S. (1999) âThe State of the Dublin Core Metadata Initiative.â <i>D-Lib Magazine</i>, Volume 5 Number 4; April. &lt;http://www.dlib.org/dlib/april99/04weibel.html&gt;</Text>
+<Text id="1245">Witten, I.H., Moffat, A. and Bell, T.C. (1999) <i>Managing gigabytes: compressing and indexing documents and images</i>. Morgan Kaufmann, San Francisco.</Text>
+</Content>
+</Chapter>
+<FootnoteList>
+<Footnote id="1">
+<Text id="1246">ÐÐ»Ñ ÐŸÐ¿ÐµÑÐ°ÑÐžÐŸÐœÐœÑÑ
+ ÑÐžÑÑÐµÐŒ Windows 95/98 Ð·Ð°Ð¿ÑÑÐº setup.bat ÐŒÐŸÐ¶ÐµÑ Ð·Ð°ÐºÐŸÐœÑÐžÑÑÑÑ ÐœÐµÑÐŽÐ°ÑÐœÐŸ, Ðž ÑÐžÑÑÐµÐŒÐ° Ð²ÑÐŽÐ°ÑÑ ÑÐŸÐŸÐ±ÑÐµÐœÐžÐµ ÐŸÐ± ÐŸÑÐžÐ±ÐºÐµ "Out of environment space". ÐÑÐ»Ðž ÑÑÐŸ Ð¿ÑÐžÐ·ÐŸÑÐ»ÐŸ, ÑÐŸ Ð²Ð°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐžÑÑÐµÐŒÐœÑÐ¹ ÑÐ°Ð¹Ð» config.sys (ÐŸÐ±ÑÑÐœÐŸ ÐŸÐœ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² C:\config.sys) Ðž ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ Ð² ÐœÐµÐ³ÐŸ ÑÑÑÐŸÐºÑ shell=C:\command.com /e:4096 /p (Ð³ÐŽÐµ Ð¡: ÐžÐŒÑ Ð²Ð°ÑÐµÐ³ÐŸ ÑÐžÑÑÐµÐŒÐœÐŸÐ³ÐŸ ÐŽÐžÑÐºÐ°). ÐÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÑÑÐž ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð²ÑÑÑÐ¿ÐžÐ»Ðž Ð² ÑÐžÐ»Ñ, ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð¿ÐµÑÐµÐ·Ð°Ð³ÑÑÐ·ÐžÑÑ Ð²Ð°Ñ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑ Ðž Ð¿ÐŸÐ²ÑÐŸÑÐžÑÑ Ð²ÑÐµ ÑÐ°Ð³Ðž ÐŽÐ»Ñ Ð·Ð°Ð¿ÑÑÐºÐ° Greenstone.</Text>
+</Footnote>
+<Footnote id="2">
+<Text id="1247">ÐÐ±ÑÐ°ÑÐžÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ, ÑÑÐŸ Ð² ÑÐžÑÑÐµÐŒÐµ Greenstone ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐµ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÑ ÐžÐœÑÐµÑÐ¿ÑÐµÑÐžÑÑÑÑÑÑ ÑÐ·ÑÐºÐŸÐŒ Perl, ÐºÐŸÑÐŸÑÑÐ¹ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐŸÑÐ»ÐžÑÐ°ÐµÑÑÑ ÐŸÑ ÐŽÑÑÐ³ÐžÑ
+. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, "*" ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ ÐœÑÐ»Ñ ÐžÐ»Ðž Ð±ÐŸÐ»ÑÑÐµÐŒÑ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²Ñ Ð¿ÐŸÐ²ÑÐŸÑÐµÐœÐžÐ¹ Ð¿ÑÐµÐŽÑÐŽÑÑÐµÐ³ÐŸ ÑÐžÐŒÐ²ÐŸÐ»Ð°, Ð² ÑÐŸ Ð²ÑÐµÐŒÑ ÐºÐ°Ðº "."-Ð¿Ð°ÑÐµ Ð»ÑÐ±ÑÑ
+ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ². Ð¢Ð°Ðº, nugget.* ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ Ð»ÑÐ±ÐŸÐ¹ ÑÑÑÐŸÐºÐµ Ñ Ð¿ÑÐµÑÐžÐºÑÐŸÐŒ "nugget," ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ð»Ðž ÐŸÐœÐ° ÐžÐ»Ðž ÐœÐµÑ Ð¿ÑÐŸÐ±ÐµÐ» Ð¿ÐŸÑÐ»Ðµ Ð¿ÑÐµÑÐžÐºÑÐ°. Ð§ÑÐŸÐ±Ñ ÑÑÐµÑÑÑ ÑÑÐŸÑ Ð¿ÑÐŸÐ±ÐµÐ», ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÐµÐ³ÐŸ ÐŸÐ±ÐŸÐ¹ÑÐž, ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ ÐœÑÐ¶ÐœÐŸ ÐœÐ°Ð¿ÐžÑÐ°ÑÑ nugget\.. *.</Text>
+</Footnote>
+<Footnote id="3">
+<Text id="1248">Note that more recent versions of the Demo collection use a Hierarchy classifier to display the how to metadata. In this case they will be displayed slightly differently to what is shown in Figure <CrossRef target="Figure" ref="list_classifier"/>.</Text>
+</Footnote>
+<Footnote id="4">
+<Text id="1249">ÐœÐ°ÑÐµÐœÐžÐµ ÐŽÐ»Ñ gsdlhome ÐžÑÑ
+ÐŸÐŽÐžÑ ÐžÐ· gsdlsite.cfg, ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐœÐŸÐ³ÐŸ Ð² ÑÐŸÐŒ Ð¶Ðµ ÑÐ°ÐŒÐŸÐŒ ÐºÐ°ÑÐ°Ð»ÐŸÐ³Ðµ, ÑÑÐŸ Ðž CGI-Ð²ÑÐ¿ÐŸÐ»ÐœÑÐµÐŒÐ°Ñ library, ÑÐŸÐ³ÐŽÐ° ÐºÐ°Ðº GSDLHOME ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑÑÑ Ð·Ð°Ð¿ÑÑÐºÐŸÐŒ ÑÐºÑÐžÐ¿ÑÐ° setup, ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÐ±ÑÐ°ÑÐ°ÐµÑÑÑ Ðº ÐŽÑÑÐ³ÐŸÐŒÑ ÑÐ°Ð¹Ð»Ñ, ÑÐ°Ðº ÐºÐ°Ðº ÑÐµÑ
+ÐœÐžÑÐµÑÐºÐž ÑÑÐŸ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ ÐŽÐ»Ñ ÐŽÐ²ÑÑ
+ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹. Ð¥ÐŸÑÑ ÑÑÐŸ Ðž Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ, ÐœÐŸ Ð²ÑÐµ Ð¶Ðµ ÐœÐµ Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÐŸ, Ðž Ð²ÑÐµ Ð²ÑÑÐµÑÐºÐ°Ð·Ð°ÐœÐœÐŸÐµ ÐœÐ°Ð¿ÐžÑÐ°ÐœÐŸ Ð² Ð¿ÑÐµÐŽÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÐž, ÑÑÐŸ ÑÐ°Ð¹Ð»Ñ ÑÐµ Ð¶Ðµ ÑÐ°ÐŒÑÐµ.</Text>
+</Footnote>
+<Footnote id="5">
+<Text id="1250">Ð¢ÐµÑ
+ÐœÐžÑÐµÑÐºÐž ÐµÑÑÑ ÑÐµÑÑÑÐµ ÑÐžÐ¿Ð°, ÐœÐŸ Ð¿ÐŸÑÐ»ÐµÐŽÐœÐžÐµ ÐŽÐ²Ð° ÑÐ²Ð»ÑÑÑÑÑ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÑÐŒÐž. Ð¢Ð°Ðº ÐºÐ°Ðº ÐŒÑ ÑÐŸÐ»ÑÐºÐŸ ÐŽÐ°ÐµÐŒ ÐŸÑÐœÐŸÐ²ÐœÐŸÐµ Ð²Ð²ÐµÐŽÐµÐœÐžÐµ Ð² ÑÑÐŸÑ ÐºÐ»Ð°ÑÑ STL, Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸÑÑÐž ÐŸÐ± ÑÑÐžÑ
+ Ð¿ÐŸÑÐ»ÐµÐŽÐœÐžÑ
+ ÐŽÐ²ÑÑ
+ ÑÐžÐ¿Ð°Ñ
+ ÐŸÐ¿ÑÑÐµÐœÑ.</Text>
+</Footnote>
+</FootnoteList>
+</Manual>
Index: /tags/start/gsdl-documentation/manuals/xml-source/ru/Install_ru.xml
===================================================================
--- /tags/start/gsdl-documentation/manuals/xml-source/ru/Install_ru.xml	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/xml-source/ru/Install_ru.xml	(revision 13666)
@@ -0,0 +1,1198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Manual>
+<Heading>
+<Text id="1">ÐŠÐÐ€Ð ÐÐÐÐ¯ ÐÐÐÐÐÐÐ¢ÐÐÐ GREENSTONE</Text>
+</Heading>
+<Title>
+<Text id="2">ÐÐÐ¡Ð¢Ð Ð£ÐÐŠÐÐ¯ ÐÐ Ð£Ð¡Ð¢ÐÐÐÐÐÐ</Text>
+</Title>
+<Author>
+<Text id="3">Dr Michel Loots, Dan Camarzan and lan H. Witten</Text>
+</Author>
+<Affiliation>
+<Text id="4">Department of Computer ScienceÂ <br/>University of Waikato, New Zealand</Text>
+</Affiliation>
+<Text id="5">Greenstone ÑÐ²Ð»ÑÐµÑÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐŸÐ¹, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐŸÐ¹ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ Ðž ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÐµÐœÐžÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÐœÐ°Ñ
+ÐŸÐŽÑÑÐžÑ
+ÑÑ Ð² ÑÐžÑÑÐŸÐ²ÐŸÐŒ ÑÐŸÑÐŒÐ°ÑÐµ. ÐÐœÐ° Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐœÐŸÐ²ÑÐ¹ ÑÐ¿ÐŸÑÐŸÐ± ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐž Ðž Ð¿ÑÐ±Ð»ÐžÐºÐ°ÑÐžÐž ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž Ð² ÐÐœÑÐµÑÐœÐµÑÐµ ÐžÐ»Ðž ÐœÐ° ÐºÐŸÐŒÐ¿Ð°ÐºÑ-ÐŽÐžÑÐºÐ°Ñ
+ CD-ROM. Greenstone Ð±ÑÐ» ÑÐŸÐ·ÐŽÐ°Ðœ Ð¿ÐŸ Ð¿ÑÐŸÐµÐºÑÑ New Zealand Digital Library Project Ð¿ÑÐž ÑÐœÐžÐ²ÐµÑÑÐžÑÐµÑÐµ ÐÐ°Ð¹ÐºÐ°ÑÐŸ, ÐŽÐŸÑÐ°Ð±ÐŸÑÐ°Ðœ Ðž ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÐµÐœ Ð¿ÑÐž ÑÐŸÐŽÐµÐ¹ÑÑÐ²ÐžÐž Ð®ÐÐÐ¡ÐÐ Ðž ÐœÐµÐ¿ÑÐ°Ð²ÐžÑÐµÐ»ÑÑÑÐ²ÐµÐœÐœÐŸÐ¹ ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐžÂ Â  Human info. Ð­ÑÐ° Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐŽÐŸÑÑÑÐ¿ÐœÐ° Ð²ÑÐµÐŒ ÐœÐ° ÑÐ°Ð¹ÑÐµ http://greenstone.org Ðž ÑÐŸÐŸÑÐ²ÐµÑÑÑÑÐµÑ ÑÑÐ»ÐŸÐ²ÐžÑÐŒ GNU General Public License.</Text>
+<Comment>
+<Text id="6">ÐÑ ÐœÐ°ÐŽÐµÐµÐŒÑÑ, ÑÑÐŸ ÑÑÐŸ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ Ñ
+ÐŸÑÐŸÑÐŸ. ÐÐŸÐ¶Ð°Ð»ÑÐ¹ÑÑÐ°, ÑÐŸÐŸÐ±ÑÐžÑÐµ ÐŸ Ð»ÑÐ±ÑÑ
+ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÐ°Ñ
+ Ð¿ÐŸ Ð°ÐŽÑÐµÑÑ:greenstone@cs.waikato.ac.nz</Text>
+</Comment>
+<Version>
+<Text id="7">Greenstone gsdl-2.50</Text>
+</Version>
+<Date>
+<Text id="8">ÐÐ°ÑÑ 2004</Text>
+</Date>
+<Section id="about_this_manual">
+<Title>
+<Text id="9">ÐÐ± ÑÑÐŸÐ¹ ÐžÐœÑÑÑÑÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="10">Ð­ÑÐŸÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ ÐŸÐ±ÑÑÑÐœÑÐµÑ, ÐºÐ°Ðº ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Greenstone ÑÐ°Ðº ÑÑÐŸÐ±Ñ Ð²Ñ ÐŒÐŸÐ³Ð»Ðž Ð·Ð°Ð¿ÑÑÐºÐ°ÑÑ ÐžÐ· ÑÐ²ÐŸÐµÐ³ÐŸ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐ°. ÐÐŽÐµÑÑ ÑÐ°ÐºÐ¶Ðµ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑÑÑ Ð±ÐµÑÐ¿Ð»Ð°ÑÐœÐŸ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÐŒÑÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐœÐ° Ð²ÐµÐ±-ÑÐµÑÐ²ÐµÑÐµ Apache Ðž Perl. ÐÑ ÐŽÐ°ÐŽÐžÐŒ Ð¿ÑÐŸÑÑÑÐµ Ð¿ÑÐžÐŒÐµÑÑ Ð¿ÑÐŸÑÐµÐŽÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž.</Text>
+<Text id="11">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ ÐŒÐŸÐ¶ÐµÑ ÑÐ°Ð±ÐŸÑÐ°ÑÑ ÐœÐ° ÑÐ°Ð·ÐœÑÑ
+ Ð¿Ð»Ð°ÑÑÐŸÑÐŒÐ°Ñ
+ Ðž Ð² ÑÐ°Ð·ÐœÑÑ
+ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÑÑ
+. Ð Ð°Ð·ÐŽÐµÐ» <CrossRef target="Chapter" ref="versions_of_greenstone"/> ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ Ð²ÐŸÐ¿ÑÐŸÑÐŸÐ² Ð²ÐŸÐ·ÐœÐžÐºÐ°ÑÑÐžÑ
+ Ð¿ÑÐž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Greenstone. Ð Ð°Ð·ÐŽÐµÐ» <CrossRef target="Chapter" ref="installation_procedure"/> ÐŽÐµÑÐ°Ð»ÑÐœÐŸ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ Ð¿ÑÐŸÑÐµÐŽÑÑÑ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐ¹ ÐŽÐ»Ñ Ð²ÑÐµÑ
+ Ð²ÐµÑÑÐžÐž, Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÑÐžÑÐ°ÑÑ ÑÑ ÑÐ°ÑÑÑ ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÑÐœÐŸÑÐžÑÑÑ Ðº Ð²Ð°ÑÐµÐ¹ ÐŸÐ¿ÐµÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÐµ. Ð Ð°Ð·ÐŽÐµÐ» <CrossRef target="Chapter" ref="greenstone_collections"/> ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ ÐŽÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Ð²ÐºÐ»ÑÑÐµÐœÐœÑÐµ Ð² ÐŽÐžÑÑÑÐžÐ±ÑÑÐžÐ²Ñ. Ð Ð°Ð·ÐŽÐµÐ» <CrossRef target="Chapter" ref="setting_up_webserver"/> ÐŸÐ±ÑÑÑÐœÑÐµÑ ÐºÐ°Ðº ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÑÑ ÐŸÐ±ÑÐžÐµ Ð²ÐµÐ±-ÑÐµÑÐ²ÐµÑÑ, Apache Ðž Microsoft PWS/IIS Ð¿ÑÐž ÑÐ°Ð±ÐŸÑÐµ Ñ Greenstone. Ð Ð°Ð·ÐŽÐµÐ» <CrossRef target="Chapter" ref="configuring_your_site"/> ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐµ ÐŸÐ¿ÑÐžÐž Greenstone Ðž Ð Ð°Ð·ÐŽÐµÐ» <CrossRef target="Chapter" ref="personalizing"/> Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐºÐ°Ðº ÐŽÐµÐ»Ð°ÑÑ Ð¿ÐµÑÑÐŸÐœÐ°Ð»ÑÐœÑÑ ÐŽÐŸÐŒÐ°ÑÐœÐžÑ ÑÑÑÐ°ÐœÐžÑÑ ÐŽÐ»Ñ ÑÐŸÐµÐŽÐžÐœÐµÐœÐžÑ Ñ Ð²Ð°ÑÐµÐ¹ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐŸÐ¹.</Text>
+</Content>
+</Section>
+<Section id="companion_documents">
+<Title>
+<Text id="12">Ð¡ÐŸÐ¿ÑÑÑÑÐ²ÑÑÑÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ</Text>
+</Title>
+<Content>
+<Text id="13">ÐÐŸÐ»ÐœÑÐ¹ ÐºÐŸÐŒÐ¿Ð»ÐµÐºÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÑÐžÐž Ðº Greenstone ÑÐŸÑÑÐŸÐžÑ ÐžÐ· Ð¿ÑÑÐž ÑÐŸÐŒÐŸÐ²:</Text>
+<BulletList>
+<Bullet>
+<Text id="14">Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ Ð¿ÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐµ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone (ÑÑÐŸÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ)</Text>
+</Bullet>
+<Bullet>
+<Text id="15">ÐÐœÑÑÑÑÐºÑÐžÑ ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="16">Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐº Ð° ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="17">ÐŠÐžÑÑÐŸÐ²Ð°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Greenstone: ÐŸÑ ÐÑÐŒÐ°Ð³Ðž ÐŽÐŸ ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Bullet>
+<Bullet>
+<Text id="18">ÐŠÐžÑÑÐŸÐ²Ð°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Greenstone: ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÐÑÐ³Ð°ÐœÐ°Ð¹Ð·ÐµÑÐ°</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Section>
+<Section id="acknowledgements">
+<Title>
+<Text id="19">ÐÐ»Ð°Ð³ÐŸÐŽÐ°ÑÐœÐŸÑÑÑ</Text>
+</Title>
+<Content>
+<Text id="20">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ Greenstone - Ð¿ÑÐŸÐŽÑÐºÑ ÑÐŸÐ²ÐŒÐµÑÑÐœÐŸÐ³ÐŸ ÑÑÑÐŽÐ° ÐŒÐœÐŸÐ¶ÐµÑÑÐ²Ð° Ð»ÑÐŽÐµÐ¹. Rodger McNab Ðž Stefan Boddie Ð¿ÑÐžÐœÑÐžÐ¿ÐžÐ°Ð»ÑÐœÑÐµ ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐž ÑÐžÑÑÐµÐŒÑ. ÐÐµÐŸÑÐµÐœÐžÐŒÑÐ¹ Ð²ÐºÐ»Ð°ÐŽ Ð²ÐœÐµÑÐ»Ðž David Bainbridge, George Buchanan, Hong Chen, Michael Dewsnip, Katherine Don, Elke Duncker, Carl Gutwin, Geoff Holmes, Dana McKay, John McPherson, Craig Nevill-Manning, Dynal Patel, Gordon Paynter, Bernhard Pfahringer, Todd Reed, Bill Rogers, John Thompson, Ðž Stuart Yeates. ÐÑÑÐ°Ð»ÑÐœÑÐµ ÑÐ»ÐµÐœÑ ÐÑÐŸÐµÐºÑÐ° ÐÐŸÐ²ÐŸÐ·ÐµÐ»Ð°ÐœÐŽÑÐºÐŸÐ¹ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐžÂ  ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÐ°Ð»Ðž Ð²ÐŽÐŸÑ
+ÐœÐŸÐ²ÐµÐœÐœÑÐ¹ ÐŽÐžÐ·Ð°Ð¹Ðœ Ð²ÑÐµÐ¹ ÑÐžÑÑÐµÐŒÑ: Mark Apperley, Sally Jo Cunningham, Matt Jones, Steve Jones, Te Taka Keegan, Michel Loots, Malika Mahoui, Gary Marsden, Dave Nichols Ðž Lloyd Smith. ÐÑ ÑÐ°ÐºÐ¶Ðµ Ð²ÑÑÐ°Ð¶Ð°ÐµÐŒ ÑÐ²ÐŸÑ Ð¿ÑÐžÐ·ÐœÐ°ÑÐµÐ»ÑÐœÐŸÑÑÑ Ð²ÑÐµÐŒ ÑÐµÐŒ, ÐºÑÐŸ ÑÑÑÐŽÐžÐ»ÑÑ ÐœÐ°ÐŽ ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµÐŒ Ð¿Ð°ÐºÐµÑÐŸÐ², Ð¿ÐŸÐ¿Ð°ÐŽÐ°ÑÑÐžÑ
+ Ð¿ÐŸÐŽ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ Ð»ÐžÑÐµÐœÐ·ÐžÐžÂ  GNU, Ðž Ð²ÐºÐ»ÑÑÐµÐœÐœÑÑ
+ Ð² ÐŽÐžÑÑÑÐžÐ±ÑÑÐžÐ²: MG, GDBM, PDFTOHTML, PERL, WGET, WVWARE Ðž XLHTML.</Text>
+</Content>
+</Section>
+<Chapter id="versions_of_greenstone">
+<Title>
+<Text id="21">ÐÐµÑÑÐžÐž Greenstone</Text>
+</Title>
+<Content>
+<Text id="22">Greenstone ÐŒÐŸÐ¶ÐµÑ ÑÐ°Ð±ÐŸÑÐ°ÑÑ ÐœÐ° ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ Ð¿Ð»Ð°ÑÑÐŸÑÐŒÐ°Ñ
+ Ðž ÐžÐŒÐµÐµÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐµ Ð²ÐµÑÑÐžÐž, ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÐµ ÐœÐ° Ð ÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="different_options"/>.</Text>
+<Figure id="different_options">
+<Title>
+<Text id="23"/>
+</Title>
+<File width="550" height="297" url="images/Install_Fig_1.png"/>
+</Figure>
+<Text id="24">Ð¡ÑÑÐµÑÑÐ²ÑÐµÑ ÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÑÑÐŸÑÑÐµÐ»ÑÑÑÐ², ÑÐ¿ÐŸÑÐŸÐ±ÐœÑÑ
+ Ð¿ÐŸÐ²Ð»ÐžÑÑÑ ÐœÐ° Ð¿ÑÐŸÑÐµÑÑÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž. ÐÐµÑÐµÐŽ ÑÐµÐŒ, ÐºÐ°Ðº Ð¿ÑÐŸÐŽÐŸÐ»Ð¶ÐžÑÑ, ÐŒÑ ÑÐŸÐ²ÐµÑÑÐµÐŒ Ð²Ð°ÐŒ ÐŸÑÐ²ÐµÑÐžÑÑ ÐœÐ°ÑÐ»ÐµÐŽÑÑÑÐžÐµ Ð²ÐŸÐ¿ÑÐŸÑÑ:</Text>
+<BulletList>
+<Bullet>
+<Text id="25">Ð ÐºÐ°ÐºÐŸÐ¹ ÑÐžÑÑÐµÐŒÐµ Ð²Ñ ÑÐ°Ð±ÐŸÑÐ°ÐµÑÐµ - Windows ÐžÐ»Ðž Unix?</Text>
+</Bullet>
+<Bullet>
+<Text id="26">ÐÑÐ»Ðž Windows, ÑÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ Ð»Ðž Ð²Ñ Windows 3.1/3.11 ÐžÐ»Ðž Ð±ÐŸÐ»ÐµÐµ ÐœÐŸÐ²ÑÐµÐ²ÐµÑÑÐžÐž? Ð¥ÐŸÑÑ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÑÐŒÐ°ÑÑÐžÐ²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÑÑÐŸÐ¹ Ð²ÐµÑÑÐžÐž,Ð²Ñ ÐœÐµ ÑÐŒÐŸÐ¶ÐµÑÐµ ÐžÑ
+ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ. ÐÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐŒÐŸÐ¶ÐœÐŸ ÑÐµÐ°Ð»ÐžÐ·ÐŸÐ²Ð°ÑÑÐ² Ð²ÐµÑÑÐžÑÑ
+ 95/98/ÐÐµ,ÐÐ¢/2000.</Text>
+</Bullet>
+<Bullet>
+<Text id="27">ÐÑÐ»Ðž Ð²Ñ ÑÐ°Ð±ÐŸÑÐ°ÐµÑÐµ Ñ Unix, ÑÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ Ð»Ðž Ð²Ñ Linux ÐžÐ»Ðž ÐŽÑÑÐ³ÐžÐµ Ð²ÐµÑÑÐžÐž?ÐÐ»Ñ Linux ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð±ÐžÐœÐ°ÑÐœÐ°Ñ Ð²ÐµÑÑÐžÑ ÑÐžÑÑÐµÐŒÑ, ÐºÐŸÑÐŸÑÐ°Ñ Ð»ÐµÐ³ÐºÐ° Ð² ÑÑÑÐ°ÐœÐŸÐ²ÐºÐµ. ÐÐ»Ñ ÐŽÑÑÐ³ÐžÑ
+ Ð²ÐµÑÑÐžÐ¹ Linux Ð²Ð°ÐŒ Ð¿ÑÐžÐŽÐµÑÑÑ ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÑÑ ÐžÑÑ
+ÐŸÐŽÐœÑÐ¹ ÐºÐŸÐŽ (source code) Ðž ÐºÐŸÐŒÐ¿ÐžÐ»ÐžÑÐŸÐ²Ð°ÑÑ ÐµÐ³ÐŸ. Ð­ÑÐŸ ÐŒÐŸÐ¶ÐµÑ Ð¿ÐŸÑÑÐµÐ±ÐŸÐ²Ð°ÑÑ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ.</Text>
+</Bullet>
+<Bullet>
+<Text id="28">ÐÑÐ»Ðž ÑÑÐŸ Windows NT/2000 ÐžÐ»Ðž Unix, ÑÐŸ ÐºÐ°Ðº Ð²Ñ Ð²Ñ
+ÐŸÐŽÐžÑÐµ Ð² ÑÐžÑÑÐµÐŒÑ - ÐºÐ°Ðº "Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐ°ÑÐŸÑ" ÐžÐ»Ðž "root"? Ð­ÑÐŸ ÑÐ°Ð·Ð»ÐžÑÐžÐµ ÐŒÐŸÐ¶ÐµÑ ÑÑÐ³ÑÐ°ÑÑ ÑÐŸÐ»Ñ Ð¿ÑÐž ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐµ ÑÐµÑÐµÐ²ÐŸÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ° Greenstone.</Text>
+</Bullet>
+<Bullet>
+<Text id="29">ÐÑÐ¶ÐµÐœ Ð»Ðž Ð²Ð°ÐŒ ÐžÑÑ
+ÐŸÐŽÐœÐ¹ ÐºÐŸÐŽ? ÐÑÐ»Ðž Ð²Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ Windows ÐžÐ»Ðž Linux, ÑÐŸ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÑÑÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ Ð±ÐžÐœÐ°ÑÑ. ÐÐŸ Ð² ÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ, ÐµÑÐ»Ðž Ð²Ð°ÐŒ Ð¿ÐŸÐœÐ°ÐŽÐŸÐ±ÐžÑÑÑ ÐžÑÑ
+ÐŸÐŽÐœÑÐ¹ ÐºÐŸÐŽ, ÐŸÐœ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² ÐŽÐžÑÑÑÐžÐ±ÑÑÐžÐ²Ðµ Greenstone.</Text>
+</Bullet>
+<Bullet>
+<Text id="30">ÐÑÐŽÐµÑÐµ Ð»Ðž Ð²Ñ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ ÐœÐŸÐ²ÑÐµ ÑÐžÑÑÐŸÐ²ÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž? ÐÑÐ»Ðž ÐŽÐ°, ÑÐŸ Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ Perl, ÐºÐŸÑÐŸÑÑÐ¹ ÐŽÐŸÑÑÑÐ¿ÐµÐœ ÐºÐ°Ðº ÐŽÐ»Ñ Windows, ÑÐ°Ðº Ðž ÐŽÐ»Ñ Unix.</Text>
+</Bullet>
+<Bullet>
+<Text id="31">ÐÑÑÑ Ð»Ðž ÐœÐ° Ð²Ð°ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ? ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐ¹ Ð¿Ð°ÐºÐµÑ Greenstone ÐžÐŽÐµÑ Ð²ÐŒÐµÑÑÐµ Ñ ÑÐµÑÐµÐ²ÑÐŒ ÑÐµÑÐ²ÐµÑÐŸÐŒ Windows. ÐÐŸ ÐµÑÐ»Ðž ÐœÐ° Ð²Ð°ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ ÐŸÐœ ÑÐ¶Ðµ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ, ÐŒÐŸÐ¶ÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ðž ÐµÐ³ÐŸ. ÐÐ»Ñ Linux Ð²Ð°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ.</Text>
+</Bullet>
+<Bullet>
+<Text id="32">ÐÐœÐ°ÐµÑÐµ Ð»Ðž Ð²Ñ, ÐºÐ°Ðº ÐœÐ°Ð»Ð°Ð¶ÐžÐ²Ð°ÑÑ ÑÐµÑÐ²ÐµÑ, ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐœÑÐ¹ ÐœÐ° Ð²Ð°ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ? ÐÑÐ»Ðž ÐœÐµÑ, ÑÐŸ Ð»ÑÑÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÑÐµÑÐ²ÐµÑ Greenstone, ÑÐ°Ðº ÐºÐ°Ðº Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ Ð±ÑÐŽÐµÑ ÐœÐ°ÑÑÑÐŸÐžÑÑ Ð²Ð°Ñ ÑÐµÑÐ²ÐµÑ ÑÐ°Ðº, ÑÑÐŸÐ±Ñ ÐŸÐœ ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°Ð²Ð°Ð» Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ Greenstone.</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Chapter>
+<Chapter id="installation_procedure">
+<Title>
+<Text id="33">ÐÑÐŸÑÐµÑÑ ÐÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="34">Ð¡ÑÑÐµÑÑÐ²ÑÑÑ ÑÐ°Ð·ÐœÑÐµ Ð²ÐµÑÑÐžÐž Greenstone, ÑÐŸÐ·ÐŽÐ°ÐœÐœÑÐµ ÐŽÐ»Ñ Windows Ðž Unix, Ðž ÐŸÐœÐž ÐŽÐŸÑÑÑÐ¿ÐœÑ Ð² ÐŽÐ²ÑÑ
+ ÑÐŸÑÐŒÐ°Ñ
+: Ð±ÐžÐœÐ°ÑÐœÐ°Ñ ÑÐŸÑÐŒÐ° Ðž ÐžÑÑ
+ÐŸÐŽÐœÑÐ¹ ÐºÐŸÐŽ. ÐÐ»Ñ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐÐœÑÐµÑÐœÐµÑ-Ð±ÑÐ°ÑÐ·ÐµÑ: Netscape Navigator ÐžÐ»Ðž Internet Explorer (Ð²ÐµÑÑÐžÐž 4.0 ÐžÐ»Ðž Ð²ÑÑÐµ Ð² ÐŸÐ±ÐŸÐžÑ
+ ÑÐ»ÑÑÐ°ÑÑ
+). ÐÑÐ»Ðž ÐœÐ° Ð²Ð°ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ ÐµÑÐµ ÐœÐµ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ ÐÐœÑÐµÑÐœÐµÑ-Ð±ÑÐ°ÑÐ·ÐµÑ, ÑÐŸ ÐœÐ° ÑÑÐŸÐŒ CD-ROM ÐµÑÑÑ Windows - Ð²ÐµÑÑÐžÑ Netscape Navigator.</Text>
+<Section id="windows">
+<Title>
+<Text id="35">Windows</Text>
+</Title>
+<Content>
+<Text id="36">ÐÑÐ»Ðž Ð²Ñ ÑÐ²Ð»ÑÐµÑÐµÑÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐŒ Unix, ÑÐŸ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÐ¿ÑÑÑÐžÑÑ ÑÑÑ ÑÐ°ÑÑÑ Ðž ÐœÐ°ÑÐ°ÑÑ Ñ ÑÐ°ÑÑÐž 2.2. ÐÐ»Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹ Windows, Ð¶ÐµÐ»Ð°ÑÑÐžÑ
+ Ð²ÑÐ¿ÐŸÐ»ÐœÐžÑÑ "ÐŸÐ±ÑÑÐœÑÑ ÑÑÑÐ°ÐœÐŸÐ²ÐºÑ" (simple installation), ÐœÐ°ÐŽÐŸ Ð·ÐœÐ°ÑÑ, ÑÑÐŸ Ð²ÐµÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐ¹ Ð¿Ð°ÐºÐµÑ Greenstone Ð·Ð°Ð¹ÐŒÐµÑ ÐŸÐºÐŸÐ»ÐŸ 40 Mb ÐœÐ° Ð¶ÐµÑÑÐºÐŸÐŒ ÐŽÐžÑÐºÐµ.</Text>
+<Text id="37">ÐÑÐ»Ðž Ð²Ñ Ð²ÑÐ±ÐµÑÐµÑÐµ ÐŽÑÑÐ³ÑÑ ÑÐŸÑÐŒÑ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž, ÑÐŸ Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ ÑÐµÑÐžÑÑ, ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÑÑ Ð»Ðž Ð²Ð°ÐŒ Ð±ÐžÐœÐ°ÑÐœÑÐ¹ ÐºÐŸÐŽ ÐžÐ»Ðž ÐžÑÑ
+ÐŸÐŽÐœÑÐ¹ ÐºÐŸÐŽ. ÐÑÐ»Ðž ÑÐŸÐŒÐœÐµÐ²Ð°ÐµÑÐµÑÑ, ÑÐŸ Ð»ÑÑÑÐµ Ð²ÑÐ±ÐµÑÐžÑÐµ Ð±ÐžÐœÐ°ÑÐœÑÐ¹ ÐºÐŸÐŽ. ÐÑÐŸÑÐµÑÑ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐžÐŽÐµÐœÑÐžÑÐµÐœ ÐŽÐ»Ñ ÐŸÐ±ÐŸÐžÑ
+ÑÐžÐ¿ÐŸÐ². ÐÐžÐ¶Ðµ ÐŸÐ¿ÐžÑÐ°ÐœÑ ÐŸÐ¿ÑÐžÐž, Ñ ÐºÐŸÑÐŸÑÑÐŒÐž Ð²Ñ ÑÑÐŸÐ»ÐºÐœÐµÑÐµÑÑ Ð¿ÑÐž Ð²ÑÐ±ÐŸÑÐµ ÑÐžÐ¿Ð° ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž.</Text>
+<Text id="38">ÐÐŸÑÐ»Ðµ Ð·Ð°Ð²ÐµÑÑÐµÐœÐžÑ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÑÑÐ°Ð·Ñ Ð¶Ðµ Ð¿ÐµÑÐµÐ¹ÑÐž Ðº ÑÐ°ÑÑÐž 2.3.</Text>
+<Subsection id="simple_installation">
+<Title>
+<Text id="39">ÐÐ±ÑÑÐœÐ°Ñ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÑ</Text>
+</Title>
+<Content>
+<Text id="40">ÐÐ»Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ð²ÐµÑÑÐžÐž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Ð¿ÐŸÐŽ Windows Ð²ÑÑÐ°Ð²ÑÑÐµ CD-ROM Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐ¹ ÐŽÐžÑÐºÐŸÐ²ÐŸÐŽ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ D:). ÐÑÐ»Ðž Ð¿ÑÐŸÑÐµÑÑ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž ÐœÐµ ÐœÐ°ÑÐœÐµÑÑÑ ÑÐµÑÐµÐ· 20 ÑÐµÐºÑÐœÐŽ, ÑÐŸ ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐŒÐµÐœÑ ÐÑÑÐº, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐÑÐ¿ÐŸÐ»ÐœÐžÑÑ Ðž ÐœÐ°Ð¿ÐžÑÐžÑÐµ D:\setup.exe Ð³ÐŽÐµ D: ÑÑÐŸ ÐŽÐžÑÐºÐŸÐ²ÐŸÐŽ ÐŽÐ»Ñ CD-ROM. Ð Ð²ÐµÑÑÐžÐž Windows 3.1,Â Â  Ð²ÑÐ±ÐµÑÐžÑÐµÂ Â Â Â  ÐÑÐ¿ÐŸÐ»ÐœÐžÑÑÂ Â  ÐÐÂ Â  Ð€Ð°Ð¹Ð»ÐŸÐ²ÐŸÐ³ÐŸÂ  ÐŒÐµÐœÐµÐŽÐ¶ÐµÑÐ° ÐÂ Â  Ð²Ð²ÐµÐŽÐžÑÐµ D:\Windows\win3.1\setup.exe.</Text>
+<Text id="41">ÐÐ»Ñ Ð¿ÑÐŸÑÑÐŸÐ¹ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ð²ÑÐ±ÐžÑÐ°Ð¹ÑÐµ Ð²ÑÐµ ÑÑÐ»ÐŸÐ²ÐžÑ, ÐºÐŸÑÐŸÑÑÐµ Ð¿ÑÐµÐŽÐ»Ð°Ð³Ð°ÑÑÑÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ, ÐœÐ°Ð¶ÐžÐŒÐ°Ñ ÐœÐ° ÐºÐœÐŸÐ¿ÐºÑ ÐÐ°Ð»ÐµÐµ(Next) . Ð­ÑÐŸ Ð²ÑÐµ, ÑÑÐŸ Ð²Ð°ÐŒ ÐœÐ°ÐŽÐŸ ÑÐŽÐµÐ»Ð°ÑÑ! Greenstone Ð±ÑÐŽÐµÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž C:\Program Files\gsdl.</Text>
+<Text id="42">ÐÐŸÑÐ»Ðµ Ð·Ð°Ð²ÐµÑÑÐœÐžÑ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŽÐ»Ñ Ð·Ð°Ð¿ÑÑÐºÐ° ÑÐžÑÑÐµÐŒÑ ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐºÐœÐŸÐ¿ÐºÑ ÐÑÑÐº, Ð²ÑÐ±ÐµÑÐžÑÐµÐÐµÐœÑ ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, Ð·Ð°ÑÐµÐŒÂ  Greenstone Digital Library, Ð·Ð°Ð¿ÑÑÐ³ÐžÐ² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ. ÐÐ»Ñ Ð²Ñ
+ÐŸÐŽÐ° Ð² ÐÐµÐŒÐŸ-ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÑÑ ÐžÐºÐŸÐœÐºÑ Ð² ÐÐ»Ð°Ð²ÐœÐŸÐŒ ÐŒÐµÐœÑ Greenstone</Text>
+<Figure id="your_greenstone_home_page">
+<Title>
+<Text id="43">ÐÐŸÐŒÐ°ÑÐœÑÑ ÑÑÑÐ°ÐœÐžÑÐ°</Text>
+</Title>
+<File width="407" height="341" url="images/Install_Fig_2.png"/>
+</Figure>
+</Content>
+</Subsection>
+<Subsection id="windows_binaries">
+<Title>
+<Text id="44">ÐÐžÐœÐ°ÑÐœÑÐµ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Ð¿ÐŸÐŽ Windows</Text>
+</Title>
+<Content>
+<Text id="45">ÐÐ° CD-ROM ÐµÑÑÑ ÐŽÐ²Ðµ ÐŸÑÐŽÐµÐ»ÑÐœÑÐµ Ð±ÐžÐœÐ°ÑÐœÑÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Ð¿ÐŸÐŽ Wmdows:Local Library (ÐÐŸÐºÐ°Ð»ÑÐœÐ°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°)Â  Ð Web Library (ÐÐœÑÐµÑÐœÐµÑ-Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°). ÐÑÐž ÐŸÐ±ÑÑÐœÐŸÐ¹ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž, ÐŸÐ¿ÐžÑÐ°ÐœÐŸÐ¹ Ð²ÑÑÐµ, ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑÑÑ ÐÐŸÐºÐ°Ð»ÑÐœÐ°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°. ÐÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÐŒ Ð²Ð°ÐŒ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐžÐŒÐµÐœÐœÐŸ ÐµÑ, ÑÐ°Ðº ÐºÐ°Ðº ÐÐœÑÐµÑÐœÐµÑ-Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÑ ÑÑÑÐŽÐœÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ, Ðž ÐŸÐœÐ° ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐ° ÑÐŸÐ»ÑÐºÐŸ Ð² ÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ, ÐµÑÐ»Ðž Ñ Ð²Ð°Ñ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ Ðž Ð²Ñ ÐœÐ°ÐŒÐµÑÐµÐ²Ð°ÐµÑÐµÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐµÐ³ÐŸ ÑÐŸÐ»ÑÐºÐŸ ÐŽÐ»Ñ Greenstone. ÐÐµÑÐŒÐŸÑÑÑ ÐœÐ° ÑÐ²ÐŸÑ ÑÐºÑÐŸÐŒÐœÐŸÐµ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ, ÐÐŸÐºÐ°Ð»ÑÐœÐ°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ Ð¿ÐŸÐ»ÐœÑÐŒ, Ð°Ð²ÑÐŸÐœÐŸÐŒÐœÑÐŒ, ÑÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÑÐŒ Ð¿ÐŸÑÐµÐœÑÐžÐ°Ð»ÐŸÐŒ ÑÐ°Ð±ÐŸÑÑ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÑÐµÑÐµÐ²ÐŸÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ°.</Text>
+<Text id="46">ÐÐŸÐºÐ°Ð»ÑÐœÐ°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°. Ð¡ Ð¿ÐŸÐŒÐŸÑÑÑ ÐÐŸÐºÐ°Ð»ÑÐœÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž ÐŒÐŸÐ¶ÐœÐŸ ÑÐ°Ð±ÐŸÑÐ°ÑÑ Ñ Ð³ÐŸÑÐŸÐ²ÑÐŒÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒÐž Greenstone Ð² Ð»ÑÐ±ÐŸÐ¹ Ð²ÐµÑÑÐžÐž Windows. ÐÐµÐŒÐŸ-ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑÑÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž. ÐÑ ÑÐ°ÐºÐ¶Ðµ ÐŒÐŸÐ¶ÐµÑÐµ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑÑ ÐœÐŸÐ²ÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ñ ÐºÐŸÐŒÐ¿Ð°ÐºÑ-ÐŽÐžÑÐºÐ° (ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÐµ Ð² Ð§Ð°ÑÑÐž <CrossRef target="Chapter" ref="greenstone_collections"/>).</Text>
+<Text id="47">ÐÐŸÐºÐ°Ð»ÑÐœÐ°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Ð¿ÑÐµÐŽÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐ° ÐŽÐ»Ñ ÑÐ°Ð±ÐŸÑÑ ÐœÐ° ÐŸÑÐŽÐµÐ»ÑÐœÑÑ
+ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐ°Ñ
+ ÐžÐ»Ðž ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐ°Ñ
+, ÐœÐ° ÐºÐŸÑÐŸÑÑÑ
+ ÐµÑÐµ ÐœÐµ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ ÑÐµÑÐµÐ²ÑÐµ ÑÐµÑÐ²ÐµÑÑ. ÐÐœÐ° ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐœÐµÐ±ÐŸÐ»ÑÑÐŸÐ¹ Ð²ÑÑÑÐŸÐµÐœÐœÑÐ¹ ÑÐµÑÐ²ÐµÑ, ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ ÑÑÐŸÐ±Ñ ÐŽÑÑÐ³ÐžÐµ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÑ, Ð¿ÐŸÐŽÐºÐ»ÑÑÐµÐœÐœÑÐµ Ðº ÑÐŸÐ¹ Ð¶Ðµ ÑÐµÑÐž, ÐŒÐŸÐ³Ð»Ðž ÐžÐŒÐµÑÑ ÐŽÐŸÑÑÑÐ¿ Ðº Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐµ (ÐœÐŸ ÑÑÐŸÑ ÑÐµÑÐ²ÐµÑ ÐžÐŒÐµÐµÑ ÐŸÐ³ÑÐ°ÐœÐžÑÐµÐœÐœÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž).</Text>
+<Text id="48">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐ¹ Ð¿Ð°ÐºÐµÑ Ð»ÐŸÐºÐ°Ð»ÑÐœÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÐœÐ°Ð»ÐžÑÐžÐµÂ  Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, ÐŸÑÐ²ÐµÑÐ°ÑÑÐµÐ¹ Ð·Ð° ÑÐµÑÐµÐ²ÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž ÐœÐ° Ð²Ð°ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ, Ðž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ, Ð¿ÐŸÐŽÐºÐ»ÑÑÐµÐœÑ Ð»Ðž Ð²Ñ Ðº ÑÐµÑÐž. ÐÐŸ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑ ÐŽÐ²Ðµ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÑ Ñ ÑÑÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐŸÐ¹:</Text>
+<BulletList>
+<Bullet>
+<Text id="49">ÐÑÐµÐŒÑ ÐŸÑ Ð²ÑÐµÐŒÐµÐœÐž ÐŒÐŸÐ¶ÐµÑ ÑÐŸÐ²ÐµÑÑÐ°ÑÑÑÑ ÐœÐµÐ·Ð°Ð¿Ð»Ð°ÐœÐžÑÐŸÐ²Ð°ÐœÐœÑÐ¹ dial-up</Text>
+</Bullet>
+<Bullet>
+<Text id="50">ÐÐœÐ° ÐŒÐŸÐ¶ÐµÑ ÐœÐµ ÑÐ°Ð±ÐŸÑÐ°ÑÑ ÐžÐ·-Ð·Ð° ÐœÐµÐ¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸÐ¹ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÑÐµÑÐµÐ²ÐŸÐ³ÐŸ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ.</Text>
+</Bullet>
+</BulletList>
+<Text id="51">ÐÐ»Ñ ÐžÐ·Ð±ÐµÐ¶Ð°ÐœÐžÑ ÑÐ°ÐºÐžÑ
+ Ð¿ÑÐŸÐ±Ð»ÐµÐŒ ÐŽÐžÑÐº ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐŸÐ³ÑÐ°ÐœÐžÑÐµÐœÐœÑÑ Ð²ÐµÑÑÐžÑ ÐÐŸÐºÐ°Ð»ÑÐœÐŸÑÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž, ÐºÐŸÑÐŸÑÑÑ ÐŒÐŸÐ¶ÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð²ÐŒÐµÑÑÐŸ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÐŸÐ¹. Ð­ÑÐ° Ð²ÐµÑÑÐžÑ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ ÑÐŸÐ»ÑÐºÐŸ Ð² Netscape- ÐÑÐž Ð·Ð°Ð¿ÑÑÐºÐµ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Ð²Ñ ÑÐ²ÐžÐŽÐžÑÐµ ÐžÐºÐŸÐœÐºÑ, Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑÑÑ Ð²ÐŸÐ¹ÑÐž Ð² ÑÑÑ Ð²ÐµÑÑÐžÑ. ÐÑÐµÐŽÐ¿ÐŸÑÑÐžÑÐµÐ»ÑÐœÐµÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÑ Ð²ÐµÑÑÐžÑ, ÐœÐµ Ð²ÑÐ·ÑÐ²Ð°ÑÑÑÑ ÑÑÐžÑ
+ Ð¿ÑÐŸÐ±Ð»ÐµÐŒ.</Text>
+<Text id="52">ÐÐœÑÐµÑÐœÐµÑ - Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° (Web Library). Ð¡ Ð¿ÐŸÐŒÐŸÑÑÑ ÑÑÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Ðž Ð¿ÑÐž ÐœÐ°Ð»ÐžÑÐžÐž ÑÐµÑÐµÐ²ÐŸÐ³ÐŸÂ Â  ÑÐµÑÐ²ÐµÑÐ° ÐŒÐŸÐ¶ÐœÐŸÑÐ°Ð±ÐŸÑÐ°ÑÑ Ñ Ð³ÐŸÑÐŸÐ²ÑÐŒÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒÐž.Ð­ÑÐ° Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÑ Ñ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐŒ ÑÐµÑÐµÐ²ÑÐŒ ÑÐµÑÐ²ÐµÑÐŸÐŒ ÑÐ°Ð±ÐŸÑÐ°ÑÑ Ñ Ð³ÐŸÑÐŸÐ²ÑÐŒÐž Greenstone ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒÐž. ÐÐ°Ðº Ðž Ð² ÑÐ»ÑÑÐ°Ðµ Ñ Ð»ÐŸÐºÐ°Ð»ÑÐœÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐŸÐ¹, ÐÐµÐŒÐŸ-ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÐ°ÐºÐ¶Ðµ Ð±ÑÐŽÐµÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž. ÐÑ ÑÐ°ÐºÐ¶Ðµ ÐŒÐŸÐ¶ÐµÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ Ðž ÐŽÑÑÐ³ÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐœÐ°Ñ
+ÐŸÐŽÑÑÐžÐµÑÑ ÐœÐ° CD-ROM, (ÑÐŒÐŸÑÑÐžÑÐµ Ð§Ð°ÑÑÑ <CrossRef target="Chapter" ref="greenstone_collections"/>).</Text>
+<Text id="53">ÐÑÐ»ÐžÑÐžÐµ ÐÐœÑÐµÑÐœÐµÑ-Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž ÐŸÑ ÐÐŸÐºÐ°Ð»ÑÐœÐŸÐ¹ ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸ ÐŸÐœÐ° Ð¿ÑÐµÐŽÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐ° ÐŽÐ»Ñ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÑÐ¶Ðµ ÐžÐŒÐµÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐ¹ Ð¿Ð°ÐºÐµÑ ÑÐµÑÐµÐ²ÐŸÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ°.</Text>
+<Text id="54">ÐÐ»Ñ Ð·Ð°Ð¿ÑÑÐºÐ° ÐÐœÑÐµÑÐœÐµÑ-Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Ð²Ð°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒ:</Text>
+<BulletList>
+<Bullet>
+<Text id="55">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐ¹ Ð¿Ð°ÐºÐµÑ ÑÐµÑÐµÐ²ÐŸÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ°. ÐÐ»Ñ ÑÑÐŸÐ³ÐŸ ÐŒÐŸÐ¶ÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Apache (ÑÐŒÐŸÑÑÐžÑÐµ ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ <CrossRef target="Chapter" ref="appendix_associated_software"/>)</Text>
+</Bullet>
+<Bullet>
+<Text id="56">ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑ. Ð­ÑÐŸÑ ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑ Ð²ÐºÐ»ÑÑÐµÐœ ÐºÐ°Ðº Ð² ÐÐŸÐºÐ°Ð»ÑÐœÑÑ, ÑÐ°Ðº Ðž Ð² ÐÐœÑÐµÑÐœÐµÑ-Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÑ Ðž Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð²Ð°ÐŒ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð²Ð°ÑÐµÐŒÑ ÑÑÐŒÐŸÑÑÐµÐœÐžÑ. (Ð Windows 3.1/3.11 ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑ ÐœÐµ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ).</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Subsection>
+<Subsection id="windows_webserver_configuration">
+<Title>
+<Text id="57">ÐÐ°ÑÑÑÐŸÐ¹ÐºÐ° ÑÐµÑÐµÐ²ÐŸÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ° Windows (Ð¢ÐŸÐ»ÑÐºÐŸ ÐŽÐ»Ñ Ð²ÐµÑÑÐžÐž ÐÐœÑÐµÑÐœÐµÑ-Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž)</Text>
+</Title>
+<Content>
+<Text id="58">ÐÑÐµÐžÐŒÑÑÐµÑÑÐ²ÐŸÐŒ ÐÐŸÐºÐ°Ð»ÑÐœÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž ÑÐ²Ð»ÑÐµÑÑÑ ÑÐŸ, ÑÑÐŸ ÐµÐµ ÐŒÐŸÐ¶ÐœÐŸ Ð·Ð°Ð¿ÑÑÑÐžÑÑ ÑÑÐ°Ð·Ñ Ð¶Ðµ Ð¿ÐŸÑÐ»Ðµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž, Ðž ÐŸÐœÐ° ÐœÐµ ÐœÑÐ¶ÐŽÐ°ÐµÑÑÑ Ð² ÐºÐ°ÐºÐŸÐ¹-Ð»ÐžÐ±ÐŸ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐµ. Ð ÑÐ»ÑÑÐ°Ðµ Ñ ÐÐœÑÐµÑÐœÐµÑ-Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐŸÐ¹ Ð²Ð°ÐŒ Ð¿ÑÐµÐŽÑÑÐŸÐžÑ ÐœÐ°ÑÑÑÐŸÐžÑÑ Ð²Ð°Ñ ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ. ÐÑÐ»Ðž ÐœÐ° Ð²Ð°ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ ÑÐ¶Ðµ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ, ÑÐŸ Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ Ð²Ð²ÐµÑÑÐž ÐœÐµÐ±ÐŸÐ»ÑÑÐžÐµ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð² ÐµÐ³ÐŸ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» ÐŽÐ»Ñ ÑÐ°Ð±ÐŸÑÑ Ñ Greenstone.</Text>
+<Text id="59">Ð¡Ð¿ÐµÑÐžÐ°Ð»ÑÐœÑÐ¹ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐŸÐœÐœÑÐ¹ ÑÐºÑÐžÐ¿Ñ Apache Ð³ÐŸÐ²ÐŸÑÐžÑ ÐŸ ÑÐŸÐŒ, ÑÑÐŸ ÐžÐŒÐµÐœÐœÐŸ ÐœÐ°ÐŽÐŸ ÑÐŽÐµÐ»Ð°ÑÑ-ÑÐŒÐŸÑÑÐžÑÐµ ÑÐ°ÑÑÑ <CrossRef target="Section" ref="pws_and_iis_webservers"/> ÐžÐœÑÑÑÑÐºÑÐžÐž Ð¿ÐŸ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐµ ÑÐµÑÐµÐ²ÑÑ
+ ÑÐµÑÐ²ÐµÑÐŸÐ² PWS, MS. ÐÐ°ÐŒ, Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ, Ð¿ÐŸÐœÐ°ÐŽÐŸÐ±ÐžÑÑÑ Ð¿ÐŸÐŒÐŸÑÑ ÑÐžÑÑÐµÐŒÐœÐŸÐ³ÐŸ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐ°ÑÐŸÑÐ° ÐŽÐ»Ñ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ°.</Text>
+<Text id="60">ÐÑÐ»Ðž Ñ Ð²Ð°Ñ ÐµÑÐµ ÐœÐµÑ ÑÐµÑÐµÐ²ÐŸÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ°, ÑÐŸ Ð²Ð°ÐŒ ÐµÐ³ÐŸ ÐœÑÐ¶ÐœÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ (ÑÐŒÐŸÑÑÐžÑÐµ Ð² ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐž <CrossRef target="Chapter" ref="appendix_associated_software"/> ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸÐ± Apache). ÐÐ°ÑÐµÐŒ Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ Ð±ÑÐŽÐµÑ ÐµÐ³ÐŸ Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸ ÐœÐ°ÑÑÑÐŸÐžÑÑ. Ð <CrossRef target="Chapter" ref="setting_up_webserver"/> ÑÐ°ÑÑÐž ÐŽÐ°ÐœÐŸ ÐŽÐµÑÐ°Ð»ÑÐœÐŸÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº ÐŸÑÐŽÐµÐ»ÑÐœÑÐµ ÑÐ°ÑÑÐž Ð²ÐµÐ±-ÑÐµÑÐ²ÐµÑÐ° Ð²Ð»ÐžÑÑÑ ÐœÐ° Greenstone Ðž ÐºÐ°Ðº ÐœÑÐ¶ÐœÐŸ ÐžÑ
+ ÐžÐ·ÐŒÐµÐœÐžÑÑ. ÐÑÐµ ÑÑÐŸ ÑÐ²ÐŸÐŽÐžÑÑÑ Ðº ÑÐŸÐŒÑ, ÑÑÐŸ ÐœÑÐ¶ÐœÐŸ Ð±ÑÐŽÐµÑ Ð²Ð²ÐµÑÑÐž ÐŸÐºÐŸÐ»ÐŸ ÑÐµÑÑÐž ÑÑÑÐŸÐº Ð² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð».</Text>
+</Content>
+</Subsection>
+<Subsection id="windows_source">
+<Title>
+<Text id="61">ÐÑÑ
+ÐŸÐŽÐœÑÐ¹ ÐºÐŸÐŽ ÐŽÐ»Ñ Windows</Text>
+</Title>
+<Content>
+<Text id="62">ÐÑÑ
+ÐŸÐŽÐœÑÐ¹ ÐºÐŸÐŽ Greenstone Ð·Ð°ÐœÐžÐŒÐ°ÐµÑ 50 Mb Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ð°, ÐœÐŸ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ ÑÑÐŸÐ±Ñ ÐµÐ³ÐŸ ÑÐºÐŸÐŒÐ¿ÐžÐ»ÐžÑÐŸÐ²Ð°ÑÑ Ð²Ð°ÐŒ Ð¿ÐŸÑÑÐµÐ±ÑÐµÑÑÑ ÐŸÐºÐŸÐ»ÐŸ 90Mb. ÐÐ»Ñ ÐºÐŸÐŒÐ¿ÐžÐ»ÑÑÐžÐž Ð²Ð°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒ:</Text>
+<BulletList>
+<Bullet>
+<Text id="63">The Microsoft Visual C++ compiler (ÐœÐ° ÐŽÐ°ÐœÐœÑÐ¹ ÐŒÐŸÐŒÐµÐœÑ ÐŒÑ ÑÐµÑÐ°ÐµÐŒ ÐœÐµÐ±ÐŸÐ»ÑÑÐžÐµ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÑ Ð¿ÐŸ Ð¿ÐŸÐ²ÐŸÐŽÑ ÐºÐŸÐŒÐ¿ÐžÐ»ÑÑÐžÐž Greenstone Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÑÐ°Ð·ÐœÑÑ
+Ñ Ð¿ÐŸÑÑÐŸÐ² GNU GCC.)</Text>
+</Bullet>
+</BulletList>
+<Text id="64">(ÐÐ°ÐŒ ÐœÐµ ÐœÑÐ¶ÐµÐœ GDBM, Ð¡Ð£ÐÐ Gnu database manager, ÑÐ°Ðº ÐºÐ°Ðº ÐŸÐœ Ð²ÐºÐ»ÑÑÐµÐœ Ð²Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐ¹ Ð¿Ð°ÐºÐµÑ Greenstone).</Text>
+<Text id="65">ÐÐ°Ð»ÐŸÐ²ÐµÑÐŸÑÑÐœÐŸ, ÑÑÐŸ Ð²Ñ ÑÐŒÐŸÐ¶ÐµÑÐµ ÑÐºÐŸÐŒÐ¿ÐžÐ»ÐžÑÐŸÐ²Ð°ÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Ð² Windows 3.1/3.11.</Text>
+<Text id="66">ÐÑÐ»Ðž Ð²Ñ Ð¿ÐµÑÐµÐºÐŸÐŒÐ¿ÐžÐ»ÐžÑÑÐµÑÐµ Greenstone Ðž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ ÑÑÑ Ð²ÐµÑÑÐžÑ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ CD-ROM, Ð²Ñ ÐŽÐŸÐ»Ð¶ÐœÑ Ð·Ð°Ð¿ÐŸÐŒÐœÐžÑÑ, ÑÑÐŸ ÐºÐŸÐŽ, ÑÐŸÐ·ÐŽÐ°ÐœÐœÑÐ¹ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ Ð¿ÐŸÑÐ»ÐµÐŽÐœÐžÑ
+ÐÐµÑÑÐžÐ¹ ÐTPP/ C++ compiler, ÐœÐµ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ Ð² Windows 3.1/3.11, ÑÐŸÐ³ÐŽÐ° ÐºÐ°Ðº ÐœÐ°ÐŽÑÑÐ³ÐžÑ
+ Ð±ÐŸÐ»ÐµÐµ ÐœÐŸÐ²ÑÑ
+ Ð²ÐµÑÑÐžÑÑ
+ (95,98,Me,N7,2000) ÐŸÐœ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ. ÐÑÐ»Ðž Ð²Ñ Ñ
+ÐŸÑÐžÑÐµ,ÑÑÐŸÐ±Ñ Ð¿ÐµÑÐµÐºÐŸÐŒÐ¿ÐžÐ»ÐžÑÐŸÐ²Ð°ÐœÐœÐ°Ñ Ð²ÐµÑÑÐžÑ ÑÐ°Ð±ÐŸÑÐ°Ð»Ð° ÐœÐ° Ð±ÐŸÐ»ÐµÐµ ÑÐ°ÐœÐœÐžÑ
+ Ð²ÐµÑÑÐžÑÑ
+Windows, ÑÐŸ Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ Ð±ÑÐŽÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŽÑÑÐ³ÑÑ Ð²ÐµÑÑÐžÑ ÐºÐŸÐŒÐ¿ÐžÐ»ÑÑÐŸÑÐ°.ÐÐŸÐ»ÐµÐµ ÑÐŸÐ³ÐŸ,Â  GreenstoneÂ  ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ STL,Â  C++ standard templatelibrary(ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÐ°Ñ ÑÐ°Ð±Ð»ÐŸÐœÐœÐ°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°), Ð Ð¥ÐÐ¢Ð¯ ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÐÐÐÐÐÐÐ¯Ð¢ÐÐ Ð«ÑÐŸÐŽÐµÑÐ¶Ð°Ñ STL, ÑÑÐ° Ð²ÐµÑÑÐžÑ ÐœÐµ Ð±ÑÐŽÐµÑ ÑÐ°Ð±ÐŸÑÐ°ÑÑ ÐœÐŸÑÐŒÐ°Ð»ÑÐœÐŸ. ÐÐŸÑÑÐŸÐŒÑ ÐŽÐ»ÑÐ¿ÐµÑÐµÐºÐŸÐŒÐ¿ÐžÐ»ÑÑÐžÐž Greenstone, ÑÑÐŸÐ±Ñ ÐŸÐœ ÑÐ°Ð±ÐŸÑÐ°Ð» ÐœÐ° ÑÐ°ÐœÐœÐžÑ
+ Ð²ÐµÑÑÐžÑÑ
+ Windows,Ð²Ð°ÐŒ ÐœÑÐ¶ÐµÐœ:</Text>
+<BulletList>
+<Bullet>
+<Text id="67">The Microsoft Visual C++ compiler, ÐÐµÑÑÐžÑ 4.0 ÐžÐ»Ðž 4.2</Text>
+</Bullet>
+<Bullet>
+<Text id="68">ÐÐœÐµÑÐœÑÑ Ð²ÐµÑÑÐžÑ STL, C++Â  STL Ð²Ñ
+ÐŸÐŽÐžÑ Ð² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ Greenstone ÑÐ¿ÐµÑÐžÐ°Ð»ÑÐœÐŸ ÐŽÐ»Ñ ÑÐ°Ð±ÐŸÑÑ Ñ ÑÑÐžÐŒÐž Ð²ÐµÑÑÐžÑÐŒÐž ÐºÐŸÐŒÐ¿ÐžÐ»ÑÑÐŸÑÐŸÐ².</Text>
+</Bullet>
+</BulletList>
+<Text id="69">ÐÑÐ¶ÐœÐŸ Ð·Ð°ÐŒÐµÑÐžÑÑ, ÑÑÐŸ Ð¿ÑÐž Ð²ÑÐ±ÐŸÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐžÑÑ
+ÐŸÐŽÐœÐŸÐ³ÐŸ ÐºÐŸÐŽÐ° Ð² Ð¿ÑÐŸÑÐµÑÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Greenstone, ÐºÐŸÐŽ ÐœÐµ Ð±ÑÐŽÐµÑ ÐºÐŸÐŒÐ¿ÐžÐ»ÐžÑÐŸÐ²Ð°ÑÑÑÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž. ÐÐœÑÑÑÑÐºÑÐžÐž, ÑÐ²ÑÐ·Ð°ÐœÐœÑÐµ Ñ ÐºÐŸÐŒÐ¿ÐžÐ»ÑÑÐžÐµÐ¹ Greenstone, ÑÐŒÐŸÑÑÐžÑÐµ Ð² ÐŽÐŸÐºÑÐŒÐµÐœÑÐµ lnstall.txt, ÐºÐŸÑÐŸÑÑÐ¹ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž (C:\Program Files\gsdl Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ).</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="unix">
+<Title>
+<Text id="70">Â  Unix</Text>
+</Title>
+<Content>
+<Text id="71">Ð­ÑÐ° ÑÐ°ÑÑÑ ÐœÐ°Ð¿ÐžÑÐ°ÐœÐ° ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹ UnixÂ  (ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ðž Windows ÐŒÐŸÐ³ÑÑ ÑÑÐ°Ð·Ñ Ð¿ÐµÑÐµÐ¹ÑÐž Ðº ÑÐ°ÑÑÐž <CrossRef target="Section" ref="how_to_find_greenstone"/>).ÐÐ»Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ Ð±ÑÐŽÐµÑ Ð²ÑÐ±ÑÐ°ÑÑ ÐŒÐµÐ¶ÐŽÑ Ð±ÐžÐœÐ°ÑÐœÑÐŒ Ðž ÐžÑÑ
+ÐŸÐŽÐœÑÐŒ ÐºÐŸÐŽÐ°ÐŒÐž. ÐÐžÐœÐ°ÑÐœÑÐ¹ ÐºÐŸÐŽ Ð·Ð°ÐœÐžÐŒÐ°ÐµÑ ÐŸÐºÐŸÐ»ÐŸ 50 Mb; ÐžÑÑ
+ÐŸÐŽÐœÑÐ¹ ÐºÐŸÐŽ ÑÑÐµÐ±ÑÐµÑ 160ÐÐ¬ ÐŽÐ»Ñ ÐºÐŸÐŒÐ¿ÐžÐ»ÑÑÐžÐž.</Text>
+<Subsection id="unix_binaries">
+<Title>
+<Text id="72">ÐÐžÐœÐ°ÑÐœÑÐ¹ ÐºÐŸÐŽ ÐŽÐ»Ñ Unix</Text>
+</Title>
+<Content>
+<Text id="73">ÐÐžÐœÐ°ÑÐœÑÐ¹ ÐºÐŸÐŽ ÐœÑÐ¶ÐŽÐ°ÐµÑÑÑ Ð²Â  Linux ÐŽÐžÑÑÑÐžÐ±ÑÑÐžÐ²Ðµ, ÐŸÑÐœÐŸÐ²Ð°ÐœÐœÐŸÐŒ ÐœÐ° IntelÑ
+8Ð±, ÐºÐŸÑÐŸÑÑÐ¹ Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð² ÑÐµÐ±Ñ ELF binary support. ÐÐžÐ¶Ðµ Ð¿ÐµÑÐµÑÐžÑÐ»ÐµÐœÑ ÐŽÐžÑÑÑÐžÐ±ÑÑÐžÐ²Ñ, ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑ ÑÑÐžÐŒ ÑÑÐµÐ±ÐŸÐ²Ð°ÐœÐžÑÐŒ:</Text>
+<BulletList>
+<Bullet>
+<Text id="74">RedHat 5.1</Text>
+</Bullet>
+<Bullet>
+<Text id="75">SuSe Linux 6.1</Text>
+</Bullet>
+<Bullet>
+<Text id="76">Debian 2.1</Text>
+</Bullet>
+<Bullet>
+<Text id="77">Slackware 4.0</Text>
+</Bullet>
+</BulletList>
+<Text id="78">ÐÐŸÐ»ÐµÐµ ÑÐ°ÐœÐœÐžÐµ Ð²ÐµÑÑÐžÐž ÑÑÐžÑ
+ ÐŽÐžÑÑÑÐžÐ±ÑÑÐžÐ²ÐŸÐ² ÑÐ°ÐºÐ¶Ðµ ÐŽÐŸÐ»Ð¶ÐœÑ ÑÐ°Ð±ÐŸÑÐ°ÑÑ.</Text>
+<Text id="79">ÐÐ°ÐŒ Ð¿ÐŸÑÑÐµÐ±ÑÐµÑÑÑ ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ: ÐŒÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÐŒ Apache. ÐÑ ÑÐ°ÐºÐ¶Ðµ ÐœÐ°ÑÑÐŸÑÑÐµÐ»ÑÐœÐŸ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÐŒ Ð²Ð°ÐŒ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ ÐŽÐŸ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº Ð²Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÐµ Greenstone - ÑÑÐŸ Ð·ÐœÐ°ÑÐžÑÐµÐ»ÑÐœÐŸ ÐŸÐ±Ð»ÐµÐ³ÑÐžÑ Ð¿ÑÐŸÑÐµÑÑ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž. ÐÑÐ»Ðž Ð²Ñ Ð¿Ð»Ð°ÐœÐžÑÑÐµÑÐµ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ ÑÐžÑÑÐŸÐ²ÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐŸ Ð²Ð°ÐŒ ÑÐ°ÐºÐ¶Ðµ Ð¿ÐŸÐœÐ°ÐŽÐŸÐ±ÐžÑÑÑ Perl, ÐµÑÐ»Ðž ÐŸÐœ ÐµÑÐµ ÐœÐµ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ ÐœÐ° Ð²Ð°ÑÐµÐ¹ ÑÐžÑÑÐµÐŒÐµ. ÐÐŸ ÐŒÐœÐŸÐ³ÐžÑ
+ Ð²ÐµÑÑÐžÑÑ
+ Linux Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Perl ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑÑÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ. Ð ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐž <CrossRef target="Chapter" ref="appendix_associated_software"/> Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐ·ÐœÐ°ÑÑ, Ð³ÐŽÐµ Ðž ÐºÐ°Ðº Ð¿ÑÐžÐŸÐ±ÑÐµÑÑÐž Apache Ðž Perl.</Text>
+</Content>
+</Subsection>
+<Subsection id="unix_source">
+<Title>
+<Text id="80">ÐÑÑ
+ÐŸÐŽÐœÑÐ¹ ÐºÐŸÐŽ ÐŽÐ»Ñ Unix</Text>
+</Title>
+<Content>
+<Text id="81">ÐÑÑ
+ÐŸÐŽÐœÑÐ¹ ÐºÐŸÐŽ ÐŽÐ»Ñ Unix ÑÐ²Ð»ÑÐµÑÑÑ ÑÐ°ÐºÐžÐŒ Ð¶Ðµ, ÐºÐ°Ðº Ðž ÐŽÐ»Ñ Windows. ÐÐœ Ð±ÑÐ» ÑÐºÐŸÐŒÐ¿ÐžÐ»ÐžÑÐŸÐ²Ð°Ðœ Ðž Ð¿ÑÐŸÐ²ÐµÑÐµÐœ ÐœÐ° Linux, Solaris, Macintosh OS/X. ÐÐ°ÑÑÑÐŸÐžÑÑ ÑÑÐŸÑ ÐºÐŸÐŽ Ð¿ÐŸÐŽ ÐŽÑÑÐ³ÐžÐµ Ð²ÐµÑÑÐžÐž Unix Ð±ÑÐŽÐµÑ ÐœÐµ ÑÐ»ÐŸÐ¶ÐœÐŸ.</Text>
+<Text id="82">ÐÐ»Ñ ÐºÐŸÐŒÐ¿ÐžÐ»ÑÑÐžÐž ÐžÑÑ
+ÐŸÐŽÐœÐŸÐ³ÐŸ ÐºÐŸÐŽÐ° ÐœÐ° Unix Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ ÐžÐŒÐµÑÑ</Text>
+<BulletList>
+<Bullet>
+<Text id="83">GCC, Gnu C++ compiler</Text>
+</Bullet>
+<Bullet>
+<Text id="84">GDBM, Gnu database manager.</Text>
+</Bullet>
+</BulletList>
+<Text id="85">ÐÐ»Ñ Ð·Ð°Ð¿ÑÑÐºÐ° Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Greenstone Ð²Ð°ÐŒ ÑÐ°ÐºÐ¶Ðµ Ð¿ÐŸÐœÐ°ÐŽÐŸÐ±ÐžÑÑÑ ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ Ðž Perl, ÐºÐ°Ðº Ð±ÑÐ»ÐŸ ÐŸÐ¿ÐžÑÐ°ÐœÐŸ Ð²ÑÑÐµ.</Text>
+</Content>
+</Subsection>
+<Subsection id="unix_installation">
+<Title>
+<Text id="86">Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐ° Unix</Text>
+</Title>
+<Content>
+<Text id="87">ÐÐ»Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ð²ÐµÑÑÐžÐž Unix Ñ ÐºÐŸÐŒÐ¿Ð°ÐºÑ-ÐŽÐžÑÐºÐ° Ð²ÑÑÐ°Ð²ÑÑÐµ ÐŽÐžÑÐº Ð² ÐŽÐžÑÐºÐŸÐ²ÐŸÐŽ ÐžÐÐ²ÐµÐŽÐžÑÐµ ÑÐ»ÐµÐŽÑÑÑÐžÐµ ÐºÐŸÐŒÐ°ÐœÐŽÑ:</Text>
+<Table class="hidden" id="table_commands">
+<Title/>
+<TableContent>
+<tr>
+<th width="126">
+<CodeLine>mount /cdrom</CodeLine>
+</th>
+<th width="281">
+<Text id="88">Â (ÑÑÐ° ÐºÐŸÐŒÐ°ÐœÐŽÐ° ÐŒÐŸÐ¶ÐµÑ ÐŸÑÐ»ÐžÑÐ°ÑÑÑ ÐŸÑ ÐŸÐŽÐœÐŸÐ¹ Ð²ÐµÑÑÐžÐž Ðº ÐŽÑÑÐ³ÐŸÐ¹; ÐœÐ°Ð¿ÑÐžÐŒÐµÑ ÐœÐ° OS/X Ð²Ñ Ð²Ð²ÐŸÐŽÐžÐ³Ð³ÐµÐŽÐžÑÐµÐºÑÐŸÑÐžÑÂ <i>/VolumesÂ </i>Â a Ð·Ð°ÑÐµÐŒÂ <i>Ð²</i>Â ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÑÑ Ð¿ÐŸÐŽÐŽÐžÑÐµÐºÑÐŸÑÐžÑ ÐŽÐ»Ñ CD-ROM)</Text>
+</th>
+</tr>
+<tr>
+<th width="126">
+<CodeLine>cd /cdrom</CodeLine>
+</th>
+<th width="281">
+<Text id="89">change directory to the CD-ROM's top level</Text>
+</th>
+</tr>
+<tr>
+<th width="126">
+<CodeLine>cd Unix</CodeLine>
+</th>
+<th width="281">
+<Text id="90">ÐÐ·ÐŒÐµÐœÐžÑÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ ÑÑÐŽÐ°, Ð³ÐŽÐµ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÂ <br/>ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐŸÐœÐœÑÐ¹ ÑÐºÑÐžÐ¿Ñ Unix .</Text>
+</th>
+</tr>
+<tr>
+<th width="126">
+<CodeLine>sh Install.sh</CodeLine>
+</th>
+<th width="281">
+<Text id="91">ÐÐ°ÑÐ°ÑÑ Ð¿ÑÐŸÑÐµÑÑ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž (Ð±ÑÐºÐ²ÐµÐœÐœÐŸÐµ ÑÐŸÑÐµÑÐ°ÐœÐžÐµ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÑÐ°Ðº ÐºÐ°Ðº Ð²ÐŸ ÐŒÐœÐŸÐ³ÐžÑ
+ ÑÐ»ÑÑÐ°ÑÑ
+ Ð²Ñ ÐœÐµ ÐŒÐŸÐ¶ÐµÑÐµ ÐœÐ°ÑÐ°ÑÑ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒ Ð¿ÑÑÐŒÐŸ Ñ ÐºÐŸÐŒÐ¿Ð°ÐºÑ-ÐŽÐžÑÐºÐ°).</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="92">ÐÐ°ÑÐ°ÑÑ Ð¿ÑÐŸÑÐµÑÑ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž (Ð±ÑÐºÐ²ÐµÐœÐŸÐµ ÑÐŸÑÐµÑÐ°ÐœÐžÐµ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÑÐ°Ðº ÐºÐ°Ðº Ð²ÐŸ ÐŒÐœÐŸÐ³ÐžÑ
+ ÑÐ»ÑÑÐ°ÑÑ
+ Ð²Ñ ÐœÐµ ÐŒÐŸÐ¶ÐµÑÐµ ÐœÐ°ÑÐ°ÑÑ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒ Ð¿ÑÑÐŒÐŸ Ñ ÐºÐŸÐŒÐ¿Ð°ÐºÑ-ÐŽÐžÑÐºÐ°).</Text>
+<Text id="93">ÐÐŸÑÐ»ÐµÐŽÐœÑÑ ÐºÐŸÐŒÐ°ÐœÐŽÐ° Ð²ÑÐ·ÑÐ²Ð°ÐµÑ ÐžÐœÑÐµÑÐ°ÐºÑÐžÐ²ÐœÐŸÐµ ÐŽÐžÐ°Ð»ÐŸÐ³ÐŸÐ²ÐŸÐµ ÐŸÐºÐœÐŸ, Ð² ÐºÐŸÑÐŸÑÐŸÐŒ Ð·Ð°Ð¿ÑÐ°ÑÐžÐ²Ð°ÐµÑÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ, ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐ°Ñ ÐŽÐ»Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Greenstone. Ð ÑÑÐŸÐŒ ÐŸÐºÐœÐµ Ð¿ÐŸÐŒÐµÑÐ°ÐµÑÑÑ ÐŽÐµÑÐ°Ð»ÑÐœÑÐ¹ ÐŸÑÑÐµÑ ÐŸ ÑÐŸÐŒ, ÑÑÐŸ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ. ÐÑÐŸÑÐµÑÑ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐœÐ°ÑÐžÐœÐ°ÐµÑÑÑ Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸ Ñ Ð²Ð°Ñ Ð·Ð°Ð¿ÑÐ°ÑÐžÐ²Ð°ÐµÑÑÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ, Ð² ÐºÐŸÑÐŸÑÑÑ Ð²Ñ Ð¶ÐµÐ»Ð°ÐµÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ. ÐÐµÑÐ²ÑÐ¹ ÑÐ°Ð¹Ð», ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐŒÐµÑÐ°ÐµÑÑÑ Ð² ÑÑÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ, - ÑÑÐŸ ÑÐ°Ð¹Ð» "ÑÐŽÐ°Ð»ÐžÑÑ" (uninstall), ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÑÐžÑÐ°ÐµÑ ÑÑÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ ÐŸÑ ÑÐ°Ð¹Ð»ÐŸÐ² ÐœÐµÐ·Ð°Ð²ÐµÑÑÐµÐœÐœÐŸÐ¹ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž, Ð² ÑÐ»ÑÑÐ°Ðµ, ÐµÑÐ»Ðž Ñ Ð²Ð°Ñ Ð²ÐŸÐ·ÐœÐžÐºÐœÑÑ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÑ ÐžÐ»Ðž Ð²Ñ Ð¿ÑÐžÐŸÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÑ. Ð¡Ð»ÐµÐŽÑÑÑÐžÐ¹ - ÑÐ°Ð³ Ð²Ñ ÐŽÐŸÐ»Ð¶ÐœÑ Ð²ÑÐ±ÑÐ°ÑÑ ÐŒÐµÐ¶ÐŽÑ Ð±ÐžÐœÐ°ÑÐœÑÐŒ Ðž ÐžÑÑ
+ÐŸÐŽÐœÑÐŒ ÐºÐŸÐŽÐ°ÐŒÐž. ÐÐ°ÑÐµÐŒ Ð¿ÐŸÑÐ²Ð»ÑÑÑÑÑ Ð²ÐŸÐ¿ÑÐŸÑÑ ÐŸ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐ°Ñ
+ Ð²Ð°ÑÐµÐ³ÐŸ WWW-Ð±ÑÐ°ÑÐ·ÐµÑÐ°. ÐÐ°ÐŒ ÐœÑÐ¶ÐœÐŸ ÐžÐŒÐµÑÑ ÐžÑÐ¿ÑÐ°Ð²ÐœÑÑ cgi executable directory (ÐŸÐ±ÑÑÐœÐŸ ÐœÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ "cgi-bin" Ð² ÑÐžÑÑÐµÐŒÐ°Ñ
+ Unix); Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐœÐŸÐ²ÑÑ Ð»ÐžÐ±ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÑÑÐ°ÑÑÑ. ÐÑÐ»Ðž Ð²Ñ ÑÐŸÐ·ÐŽÐ°ÐŽÐžÑÐµ ÐœÐŸÐ²ÑÑ, ÑÐŸ Ð²Ð°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð²Ð²ÐµÑÑÐž ÑÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ Ð² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð»Â  ÑÐµÑÐµÐ²ÐŸÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ°. Ð Ð»ÑÐ±ÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ Ð±ÑÐŽÐµÑ Ð²Ð²ÐµÑÑÐž WWW-Ð°ÐŽÑÐµÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž cgi. ÐÐœÑÐµÑÐ°ÐºÑÐžÐ²ÐœÑÐµ ÐŸÐºÐœÐ° Ð¿ÑÐŸÐ²ÐµÐŽÑÑ Ð²Ð°Ñ ÑÐµÑÐµÐ· Ð²ÐµÑÑ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐŸÐœÐœÑÐ¹ Ð¿ÑÐŸÑÐµÑÑ. ÐÑÐµÐœÑ Ð²Ð°Ð¶ÐœÐŸ Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸ Ð²Ð²ÐŸÐŽÐžÑÑÂ Â  file permissionsÂ Â Â Â Â Â  Ð² ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑÑ
+, Ð³ÐŽÐµ Ñ Ð²Ð°Ñ Ð¿ÐŸÑÑÐµÐ±ÑÑÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ. Ð ÐœÐ°ÐºÐŸÐœÐµÑ Ñ Ð²Ð°Ñ Ð¿ÐŸÑÑÐµÐ±ÑÑÑ Ð¿Ð°ÑÐŸÐ»Ñ. ÐÐ»Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ "Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐ°ÑÐŸÑ" Ð²Ð²ÐµÐŽÐžÑÐµ "admin".</Text>
+<Text id="94">ÐÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ, Greenstone ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑÑÑ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž /usr/local/gsdl, ÐµÑÐ»Ðž ÑÑÑÐ°ÐœÐŸÐ²ÐºÑ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑ "ÐºÐŸÑÐœÐµÐ²ÐŸÐ¹"(Ð³ÐŸÐŸ1) Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ, Ð° Ð² ÐžÐœÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ - Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ ~/gsdl (Ð³ÐŽÐµ "~" ÑÐ²Ð»ÑÐµÑÑÑ Ð³Ð»Ð°Ð²ÐœÐŸÐ¹ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐµÐ¹ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ).</Text>
+<Text id="95">Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐ° Ð±ÐžÐœÐ°ÑÐœÐŸÐ³ÐŸ ÐºÐŸÐŽÐ° Ð·Ð°ÐœÐžÐŒÐ°ÐµÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐŒÐžÐœÑÑ. ÐÑÐ»Ðž Ð²Ñ ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑÐµ ÐžÑÑ
+ÐŸÐŽÐœÑÐ¹ ÐºÐŸÐŽ, ÑÐŸ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐŸÐœÐœÑÐ¹ ÑÐºÑÐžÐ¿Ñ Ð±ÑÐŽÐµÑ ÐºÐŸÐŒÐ¿ÐžÐ»ÐžÑÐŸÐ²Ð°ÑÑ ÐµÐ³ÐŸ, ÑÑÐŸ Ð·Ð°Ð¹ÐŒÐµÑ ÐŸÑ 10 ÐŒÐžÐœÑÑ ÐŽÐŸ ÑÐ°ÑÐ°, Ð² Ð·Ð°Ð²ÐžÑÐžÐŒÐŸÑÑÐž ÐŸÑ ÑÐºÐŸÑÐŸÑÑÐž Ð²Ð°ÑÐµÐ³ÐŸ Ð¿ÑÐŸÑÐµÑÑÐŸÑÐ°.</Text>
+<Text id="96">ÐÐ»Ñ ÑÐŽÐ°Ð»ÐµÐœÐžÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Ð²Ð²ÐµÐŽÐžÑÐµ</Text>
+<CodeLine>cd ~/gsdlÂ Â Â </CodeLine>
+<Text id="97">Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  ÐžÐ»Ðž /user/local/gsdl, Ð° "ÐºÐŸÑÐœÐµÐ²ÐŸÐ¹" Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÂ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  ÐŒÐŸÐ¶ÐµÑ Ð²Ð²ÐµÑÑÐž ÐºÐŸÐŒÐ°ÐœÐŽÑ</Text>
+<CodeLine>sh Uninstall.sh</CodeLine>
+<Text id="98">Ð Ð¿ÑÐŸÑÐµÑÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ð¿ÐŸÐŒÐžÐŒÐŸ ÐÐµÐŒÐŸ-ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ Ðž ÐŽÑÑÐ³ÐžÐµÂ  ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐµÐŒÐŸ-ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Greenstone ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑÑÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž; ÑÐ²ÐµÐŽÐµÐœÐžÑ ÐŸÐ± ÐŸÑÑÐ°Ð»ÑÐœÑÑ
+ Ð²Ñ ÐœÐ°Ð¹ÐŽÐµÑÐµ Ð² <CrossRef target="Chapter" ref="greenstone_collections"/> ÑÐ°ÑÑÐž.</Text>
+</Content>
+</Subsection>
+<Subsection id="unix_webserver_configuration">
+<Title>
+<Text id="99">ÐÐ°ÑÑÑÐŸÐ¹ÐºÐ° ÑÐµÑÐµÐ²ÐŸÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ° Unix</Text>
+</Title>
+<Content>
+<Text id="100">ÐÑÐ»Ðž ÐœÐ° Ð²Ð°ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ ÑÐ¶Ðµ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ, ÑÐŸ Ð² ÐµÐ³ÐŸ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» ÐœÑÐ¶ÐœÐŸ Ð±ÑÐŽÐµÑ Ð²ÐœÐµÑÑÐž ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ, ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ ÑÑÐŸÐ±Ñ ÐŸÐœ Ð±ÑÐ» ÑÐŸÐ²ÐŒÐµÑÑÐžÐŒ Ñ Greenstone. Ð ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐŸÐœÐœÐŸÐŒ ÑÐºÑÐžÐ¿ÑÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐŸ, ÐºÐ°Ðº ÑÑÐŸ ÐœÐ°ÐŽÐŸ ÑÐŽÐµÐ»Ð°ÑÑ. ÐÐ»Ñ Ð²Ð°ÑÐµÐ³ÐŸ ÑÐŽÐŸÐ±ÑÑÐ²Ð° ÑÑÐŸÑ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐŸÐœÐœÑÐ¹ ÑÐºÑÐžÐ¿Ñ Ð·Ð°Ð¿ÐžÑÐ°Ðœ Ð² ÑÐ°Ð¹Ð»Ðµ INSTALL RECORD Ð² ÑÐŸÐ¹ Ð¶Ðµ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž, Ð² ÐºÐŸÑÐŸÑÑÑ Ð²Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐžÐ»Ðž Greenstone</Text>
+<Text id="101">ÐÑÐ»Ðž Ñ Ð²Ð°Ñ ÐµÑÐµ ÐœÐµÑ ÑÐµÑÐµÐ²ÐŸÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ°, ÑÐŸ ÐµÐ³ÐŸ ÐœÑÐ¶ÐœÐŸ Ð±ÑÐŽÐµÑ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ. Ð ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐž <CrossRef target="Chapter" ref="appendix_associated_software"/> ÐµÑÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸÐ± Apache. ÐÐ°ÑÐµÐŒ Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ Ð±ÑÐŽÐµÑ ÐµÐ³ÐŸ ÐœÐ°ÑÑÑÐŸÐžÑÑ. Ð <CrossRef target="Chapter" ref="setting_up_webserver"/> ÑÐ°ÑÑÐž ÐŸÐ¿ÐžÑÐ°ÐœÑ ÑÐ°ÑÑÐž WWW-ÑÐµÑÐ²ÐµÑÐ° Apache, ÐºÐŸÑÐŸÑÑÐµ Ð²Ð·Ð°ÐžÐŒÐŸÑÐ²ÑÐ·Ð°ÐœÑ Ñ Greenstone, Ðž ÑÐŸ, ÐºÐ°Ðº ÐžÑ
+ ÐœÑÐ¶ÐœÐŸ ÐžÐ·ÐŒÐµÐœÐžÑÑ. ÐÑÐµ ÑÐ²ÐŸÐŽÐžÑÑÑ Ðº ÑÐŸÐŒÑ, ÑÑÐŸ Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ Ð±ÑÐŽÐµÑ Ð²Ð²ÐµÑÑÐž Ð¿ÐŸÐ»ÐŽÑÐ¶ÐžÐœÑ ÑÑÑÐŸÐº Ð² ÐµÐ³ÐŸ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð».</Text>
+<Text id="102">ÐÐ°ÐŒ ÐœÐµ ÐŸÐ±ÑÐ·Ð°ÑÐµÐ»ÑÐœÐŸ Ð±ÑÑÑ ÐºÐŸÑÐœÐµÐ²ÑÐŒ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐŒ Unix ÐŽÐ»Ñ ÑÐŸÐ²ÐµÑÑÐµÐœÐžÑ ÐŸÐ¿ÐžÑÐ°ÐœÐœÐŸÐ³ÐŸ Ð²ÑÑÐµ Ð¿ÑÐŸÑÐµÑÑÐ° ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž. ÐÐŸ ÐºÐŸÐ³ÐŽÐ° ÐŽÐµÐ»ÐŸ ÐŽÐŸÑ
+ÐŸÐŽÐžÑ ÐŽÐŸ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž ÑÐµÑÐµÐ²ÐŸÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ° Apache, ÑÐŸÐ³ÐŽÐ° Ð²Ð°ÐŒÂ Â  Ð¿ÐŸÐœÐ°ÐŽÐŸÐ±ÑÑÑÑ Ð¿ÑÐžÐ²ÐžÐ»ÐµÐ³ÐžÐž ÐºÐŸÑÐœÐµÐ²ÐŸÐ³ÐŸ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ. ÐÑÐ»Ðž Ð²Ñ Ð¶ÐµÐ»Ð°ÐµÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ Ð²ÑÐŸÑÐŸÐ¹ ÑÐµÑÐ²ÐµÑ Apache, ÑÐŸ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÑÑÐŸ ÑÐŽÐµÐ»Ð°ÑÑ, ÐŽÐ°Ð¶Ðµ ÐµÑÐ»Ðž ÐœÐ°Â  Ð²Ð°ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ ÑÐ¶Ðµ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ ÐŸÐŽÐžÐœ.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="how_to_find_greenstone">
+<Title>
+<Text id="103">Ð Ð°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÐµ Greenstone</Text>
+</Title>
+<Content>
+<Subsection id="local_library_windows_only">
+<Title>
+<Text id="104">ÐÐŸÐºÐ°Ð»ÑÐœÐ°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° (ÑÐŸÐ»ÑÐºÐŸ ÐŽÐ»Ñ Windows)</Text>
+</Title>
+<Content>
+<Text id="105">ÐÑÐ»Ðž Ð²Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ ÐÐŸÐºÐ°Ð»ÑÐœÑÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÑ, ÑÐŸ Ð¿ÑÐŸÑÑÐŸ Ð·Ð°Ð¿ÑÑÑÐžÑÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Greenstone ÐºÐœÐŸÐ¿ÐºÐŸÐ¹ ÐÑÑÐºÂ  Ð² ÐŒÐµÐœÑ. Ð­ÑÐŸ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž Ð·Ð°Ð³ÑÑÐ¶Ð°ÐµÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, Ðž ÐœÐ° ÑÐºÑÐ°ÐœÐµ Ð² ÐŸÐºÐœÐµ Ð²Ð°ÑÐµÐ³ÐŸ Ð±ÑÐ°ÑÐ·ÐµÑÐ° Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ ÑÑÐ°ÑÑÐŸÐ²Ð°Ñ ÑÑÑÐ°ÐœÐžÑÐ°. Ð¡ ÑÑÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÑ ÑÐ°ÐºÐ¶Ðµ ÐŽÐŸÑÑÑÐ¿ÐœÐ° ÐÐµÐ»Ñ-Â Â Â  ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. Ð ÐŽÐžÐ°Ð»ÐŸÐ³ÐŸÐ²ÐŸÐŒ&lt;*&gt;ÐºÐÐµ ÐŒÐµÐœÑ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÐ·ÐŒÐµÐœÐžÑÑ Ð²Ð°Ñ Ð±ÑÐ°ÑÐ·ÐµÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ. ÐÐµÑ ÐœÐžÐºÐ°ÐºÐŸÐ¹ ÑÐ°Ð·ÐœÐžÑÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ Ð»Ðž Ð²Ñ Internet Explorer ÐžÐ»Ðž Netscape Navigator, Ð·Ð° ÐžÑÐºÐ»ÑÑÐµÐœÐžÐµÐŒ ÑÐŸÐ³ÐŸ, ÑÑÐŸ ÐµÑÐ»Ðž Ñ Ð²Ð°Ñ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ Windows 2000, ÑÐŸ ÐŒÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÐŒ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Internet Explorer.</Text>
+</Content>
+</Subsection>
+<Subsection id="web_library_windows_and_unix">
+<Title>
+<Text id="106">ÐÐœÑÐµÑÐœÐµÑ-ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° (Windows Ðž Unix)</Text>
+</Title>
+<Content>
+<Text id="107">ÐÑÐ»Ðž Ð²Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ ÐÐœÑÐµÑÐœÐµÑ-Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÑ, ÑÐŸ Ð¿ÐŸÑÐ»Ðµ Ð·Ð°Ð²ÐµÑÑÐµÐœÐžÑ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ðž ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž ÑÐµÑÐµÐ²ÐŸÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ°, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÑÐ»ÐµÐŽÑÑÑÐžÐ¹ WWW-Ð°ÐŽÑÐµÑ ÐŽÐ»Ñ Ð²Ñ
+ÐŸÐŽÐ° Ð² Ð²Ð°ÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ:</Text>
+<Text id="108"><i>http://localhost/gsdl/cgi-bin/library</i></Text>
+<Text id="109">ÐÐµÐŒÐŸ-ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Greenstone ÑÐ°ÐºÐ¶Ðµ ÐŽÐŸÐ»Ð¶ÐœÐ° Ð±ÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÐ° Ñ ÑÑÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÑ.</Text>
+</Content>
+</Subsection>
+<Subsection id="the_collector">
+<Title>
+<Text id="110">ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑ</Text>
+</Title>
+<Content>
+<Text id="111">Ð ÑÑÐ°ÑÑÐŸÐ²ÐŸÐŒ ÐŸÐºÐœÐµ Greenstone ÐµÑÑÑ ÑÑÑÐ»ÐºÐ° Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐŸÑÑ (Collector).</Text>
+</Content>
+</Subsection>
+<Subsection id="administration">
+<Title>
+<Text id="112">ÐÐŽÐŒÐžÐœÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ</Text>
+</Title>
+<Content>
+<Text id="113">Ð¢Ð°ÐŒ ÑÐ°ÐºÐ¶Ðµ ÐµÑÑÑ ÑÑÑÐ»ÐºÐ° Ðº ÑÑÑÐ°ÐœÐžÑÐµ ÐÐŽÐŒÐžÐœÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ. ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ "Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐ°ÑÐŸÑ" ÐœÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ admin, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ Ð¿Ð°ÑÐŸÐ»Ñ, ÑÐºÐ°Ð·Ð°ÐœÐœÑÐ¹ Ð² Ð¿ÑÐŸÑÐµÑÑÐµ ÐÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž. ÐÐŽÐŒÐžÐœÐžÑÑÑÐ°ÑÐŸÑ ÐŒÐŸÐ¶ÐµÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑÑ ÐœÐŸÐ²ÑÑ
+ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹ Ðž ÑÐ°Ð·ÑÐµÑÐ°ÐµÑ ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐœÐŸÐ²ÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="the_greenstone_librarian_interface_(gli)">
+<Title>
+<Text id="114">Â  ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Greenstone (GLI)</Text>
+</Title>
+<Content>
+<Text id="115">ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Greenstone (GLI) â ÑÑÐŸ ÐžÐœÑÑÑÑÐŒÐµÐœÑ ÐŽÐ»Ñ Ð¿ÐŸÐŒÐŸÑÐž ÐÐ°ÐŒ Ð¿ÑÐž ÑÐŸÐ·ÐŽÐ°ÐœÐžÐž ÑÐžÑÑÐŸÐ²ÑÑ
+ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐº Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ Greenstone. ÐÐœ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÐµÑ ÐÐ°ÐŒ ÐŽÐŸÑÑÑÐ¿ Ðº ÑÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÑÐŒ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑÐŒ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž ÑÐŽÐŸÐ±ÐœÐŸÐŒÑ Ð² ÑÐ°Ð±ÐŸÑÐµ ÐžÐœÑÐµÑÑÐµÐ¹ÑÑ Â«Ð¿ÑÐœÐºÑ Ðž ÑÐµÐ»ÑÐŸÐºÂ».</Text>
+<Text id="116">GLI ÐžÐœÑÑÐ°Ð»Ð»ÐžÑÑÐµÑÑÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž Ð²ÐŸ Ð²ÑÐµÑ
+ ÐŽÐžÑÑÑÐžÐ±ÑÑÐžÐ²Ð°Ñ
+ Greenstone. ÐÐœ Ð¿ÐŸÐŒÐµÑÐµÐœ Ð² Ð¿ÐŸÐŽÐŽÐžÑÐµÐºÑÐŸÑÐžÐž gli Ð³Ð»Ð°Ð²ÐœÐŸÐ¹ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž Greenstone (C:\Program Files\gsdl\gli Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ). ÐÐ±ÑÐ°ÑÐžÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ ÐœÐ° ÑÐŸ, ÑÑÐŸ ÐŸÐœ Ð·Ð°Ð¿ÑÑÐºÐ°ÐµÑÑÑÂ  Ð² ÑÐŸÑÐµÑÐ°ÐœÐžÐž Ñ Greenstone Ðž ÐœÐµ Ð±ÑÐŽÐµÑ ÑÐ°Ð±ÐŸÑÐ°ÑÑ ÐºÐŸÑÑÐµÐºÑÐœÐŸ, ÐµÑÐ»Ðž ÐœÐµ Ð¿ÐŸÐŒÐµÑÐµÐœ Ð² Ð¿ÐŸÐŽÐŽÐžÑÐµÐºÑÐŸÑÐžÑ Ð¿ÑÐž ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž Greenstone. ÐÑÐ»Ðž ÐÑ Ð·Ð°Ð³ÑÑÐ·ÐžÐ»Ðž ÐŸÐŽÐžÐœ ÐžÐ· ÐŽÐžÑÑÑÐžÐ±ÑÑÐžÐ²ÐŸÐ² Greenstone, ÑÐŸ ÑÑÐµÐ±ÑÐµÐŒÐŸÐµ ÐŽÐŸÐ»Ð¶ÐœÐŸ ÐžÐŒÐµÑÑ ÐŒÐµÑÑÐŸ.</Text>
+<Text id="117">Ð§ÑÐŸÐ±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ GLI, ÐœÐ° ÐÐ°ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ ÐŽÐŸÐ»Ð¶ÐœÐ° ÐžÐŒÐµÑÑÑÑ Java Runtime Environment (JRE). ÐÑÐ»Ðž ÑÑÐŸ ÐœÐµ ÑÐŽÐµÐ»Ð°ÐœÐŸ, ÑÐŸ Ð¿ÑÐž ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž ÐÐ°ÐŒ Ð±ÑÐŽÐµÑ Ð¿ÑÐµÐŽÐ»ÐŸÐ¶ÐµÐœÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ Ð²ÐµÑÑÐžÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÐœÐ° CD-ROM. ÐÑÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž Unix ÐÑ Ð±ÑÐŽÐµÑÐµ ÐœÑÐ¶ÐŽÐ°ÑÑÑÑ ÑÐ°ÐºÐ¶Ðµ Ð² ÑÐŸÐŒ, ÑÑÐŸÐ±Ñ Ð±ÑÐ» ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ PerlÂ  (ÐŽÐ»Ñ Windows Perl ÑÐ¶Ðµ Ð²ÐºÐ»ÑÑÐµÐœ Ð² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ Greenstone). ÐÐŸÐ¶Ð°Ð»ÑÐ¹ÑÑÐ°, ÑÐŸÐŸÐ±ÑÐžÑÐµ ÐŸ Ð»ÑÐ±ÑÑ
+ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÐ°Ñ
+, ÐºÐŸÑÐŸÑÑÐµ Ð²ÐŸÐ·ÐœÐžÐºÐ°ÑÑ Ñ ÐÐ°Ñ Ð¿ÑÐž Ð·Ð°Ð¿ÑÑÐºÐµ ÐžÐ»Ðž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° Ð¿ÐŸ Ð°ÐŽÑÐµÑÑ:greenstone@cs.waikato.ac.nz.</Text>
+<Subsection id="running_under_windows">
+<Title>
+<Text id="118">ÐÐ°Ð¿ÑÑÐº Ð¿ÐŸÐŽ Windows</Text>
+</Title>
+<Content>
+<Text id="119">Ð§ÑÐŸÐ±Ñ Ð·Ð°Ð¿ÑÑÑÐžÑÑ GLI Ð¿ÐŸÐŽ Windows, ÐŸÐ±ÑÐ°ÑÐžÑÐµÑÑ Ðº Ð¿Ð°Ð¿ÐºÐµ gli Ð² ÐÐ°ÑÐµÐ¹ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž Greenstone, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ, ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, Windows Explorer, Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ ÐŽÐ²Ð°Ð¶ÐŽÑ ÐœÐ° ÑÐ°Ð¹Ð»Ðµ Ñ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµÐŒ gli.bat. Ð­ÑÐŸÑ ÑÐ°Ð¹Ð» Ð¿ÑÐŸÐ²ÐµÑÑÐµÑ ÐœÐ°Ð»ÐžÑÐžÐµ Greenstone, JRE Ðž Perl Ðž Ð·Ð°Ð¿ÑÑÐºÐ°ÐµÑ GLI.</Text>
+</Content>
+</Subsection>
+<Subsection id="running_under_unix">
+<Title>
+<Text id="120">ÐÐ°Ð¿ÑÑÐº Ð¿ÐŸÐŽ Unix</Text>
+</Title>
+<Content>
+<Text id="121">Ð§ÑÐŸÐ±Ñ Ð·Ð°Ð¿ÑÑÑÐžÑÑ GLI Ð¿ÐŸÐŽ Unix, ÐžÐ·ÐŒÐµÐœÐžÑÐµ ÐœÐ° gli ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ Ð² ÐÐ°ÑÐµÐ¹ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐµ Greenstone, Ð° Ð·Ð°ÑÐµÐŒ Ð·Ð°Ð¿ÑÑÑÐžÑÐµ ÑÐºÑÐžÐ¿ÑÂ  gli.sh. Ð­ÑÐŸÑ ÑÐºÑÐžÐ¿Ñ Ð¿ÑÐŸÐ²ÐµÑÑÐµÑ ÐœÐ°Ð»ÐžÑÐžÐµ Greenstone, JRE Ðž Perl ÐœÐ° Ð¿ÐŸÐžÑÐºÐŸÐ²ÐŸÐŒ Ð¿ÑÑÐž Ðž Ð·Ð°Ð¿ÑÑÐºÐ°ÐµÑ GLI.</Text>
+</Content>
+</Subsection>
+<Subsection id="getting_help">
+<Title>
+<Text id="122">ÐÐŸÐ»ÑÑÐµÐœÐžÐµ Ð¿ÐŸÐŒÐŸÑÐž</Text>
+</Title>
+<Content>
+<Text id="123">GLI Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÐµÑ ÐŸÐ±ÑÐžÑÐœÑÐµ ÐŽÐžÐ°Ð»ÐŸÐ³ÐŸÐ²ÑÐµ ÑÑÐµÐŽÑÑÐ²Ð° Ð¿ÐŸÐŒÐŸÑÐž. Ð§ÑÐŸÐ±Ñ Ð¿ÐŸÐ»ÑÑÐžÑÑ Ð¿ÐŸÐŒÐŸÑÑ, ÑÐµÐ»ÐºÐœÐžÑÐµ ÐºÐœÐŸÐ¿ÐºÐŸÐ¹ Help Ð² Ð²ÐµÑÑ
+ÐœÐµÐ¹ Ð¿ÑÐ°Ð²ÐŸÐ¹ ÑÐ°ÑÑÐž ÑÐºÑÐ°ÐœÐ°. Ð­ÑÐŸ ÐŸÑÐºÑÐŸÐµÑ ÑÐµÐºÑÑ ÑÐ°Ð·ÐŽÐµÐ»Ð°, ÐºÐŸÑÐŸÑÑÐ¹ ÐºÐ°ÑÐ°ÐµÑÑÑ ÑÐŸÐ³ÐŸ, ÑÑÐŸ ÐÑ ÐŽÐµÐ»Ð°ÐµÑÐµ â ÐºÐ°ÐºÐ°Ñ ÐžÐ· Ð¿Ð°ÐœÐµÐ»ÐµÐ¹ GLI Ð² ÐœÐ°ÑÑÐŸÑÑÐµÐµ Ð²ÑÐµÐŒÑ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐµÐ»ÐºÐœÑÑÑ Ð¿ÐŸ ÑÐµÐºÑÑÑ Ð¿ÐŸÐŒÐŸÑÐž, ÑÑÐŸÐ±Ñ ÐžÐ·ÑÑÐžÑÑ ÑÐŸ, ÑÑÐŸ ÐÐ°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð·ÐœÐ°ÑÑ. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÑÑÐŸ.</Text>
+</Content>
+</Subsection>
+<Subsection id="compiling_gli">
+<Title>
+<Text id="124">ÐÐŸÐŒÐ¿ÐžÐ»ÐžÑÐŸÐ²Ð°ÐœÐžÐµ GLI</Text>
+</Title>
+<Content>
+<Text id="125">ÐÑÐ»Ðž ÐÑ Ð·Ð°Ð¿ÑÑÑÐžÐ»Ðž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐŽÐžÑÑÑÐžÐ±ÑÑÐžÐ²Ð° Greenstone, ÑÐŸ ÐÑ Ð±ÑÐŽÐµÑÐµ ÐžÐŒÐµÑÑ ÐžÑÑ
+ÐŸÐŽÐœÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑÂ  Java ÐžÐ· GLI. Ð§ÑÐŸÐ±Ñ Ð²ÑÐ¿ÐŸÐ»ÐœÐžÑÑ ÐºÐŸÐŒÐ¿ÐžÐ»ÐžÑÐŸÐ²Ð°ÐœÐžÐµ, ÐÐ°Ñ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑ ÐŽÐŸÐ»Ð¶ÐµÐœ ÐžÐŒÐµÑÑÂ <i>Java Development Kit</i>. Ð Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐž <CrossRef target="Chapter" ref="appendix_associated_software"/> ÐŽÐ°ÐµÑÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸÑÐœÐŸÑÐžÑÐµÐ»ÑÐœÐŸ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº ÐµÐµ Ð¿ÐŸÐ»ÑÑÐžÑÑ. Ð§ÑÐŸÐ±Ñ ÐºÐŸÐŒÐ¿ÐžÐ»ÐžÑÐŸÐ²Ð°ÑÑ ÐžÑÑ
+ÐŸÐŽÐœÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, Ð²Ð²ÐµÐŽÐžÑÐµ ÑÐ°Ð¹Ð»ÑÂ <i>makegli.bat (</i>Â Windows)Â  ÐžÐ»ÐžÂ Â <i>makegli.sh</i>Â (Unix). ÐÐŸÑÐ»Ðµ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº ÐºÐŸÐŒÐ¿ÐžÐ»ÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð·Ð°Ð²ÐµÑÑÐµÐœÐŸ, ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð·Ð°Ð¿ÑÑÑÐžÑÑ GLI, ÐºÐ°Ðº Ð±ÑÐ»ÐŸ ÐŸÐ¿ÐžÑÐ°ÐœÐŸ Ð²ÑÑÐµ.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="testing_and_troubleshooting">
+<Title>
+<Text id="126">ÐÑÐŸÐ²ÐµÑÐºÐ° Ðž Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÐµ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÑ</Text>
+</Title>
+<Content>
+<Text id="127">ÐÐ»Ñ Ð¿ÑÐŸÐ²ÐµÑÐºÐž Ðž ÐŸÐ±Ð·ÐŸÑÐ°Â <i>Greenstone</i>, Ð¿ÑÐŸÑÑÐŸ ÐœÐ°ÑÐœÐžÑÐµ Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐÐµÐŒÐŸ-ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž ÐŽÑÑÐ³ÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÐºÐŸÑÐŸÑÑÐµ Ð²Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐžÐ»Ðž. ÐÐ°Ð¶ÐžÐŒÐ°Ð¹ÑÐµ ÐœÐ° Ð²ÑÐµ ÐºÐœÐŸÐ¿ÐºÐž Ð±ÐµÐ· ÐŸÐ¿Ð°ÑÐµÐœÐžÑ -Ð²Ñ ÐœÐžÑÐµÐ³ÐŸ ÐœÐµ Ð¿ÐŸÐ²ÑÐµÐŽÐžÑÐµ. ÐÑÐ»Ðž Ð·Ð°ÐŽÐµÑÐ¶Ð°ÑÑ ÐºÑÑÑÐŸÑ ÐŒÑÑÐž ÐœÐ° ÐºÐ°ÐºÐŸÐŒ-Ð»ÐžÐ±ÐŸ ÑÐžÑÑÐœÐºÐµÐ»Ð³ÐŸÑÐžÑÑÑ ÑÐŸÐŸÐ±ÑÐµÐœÐžÐµ, Ð² ÐºÐŸÑÐŸÑÐŸÐŒ ÐœÐ°Ð¿ÐžÑÐ°ÐœÐŸ ÑÐŸ, ÑÑÐŸ Ð¿ÑÐŸÐžÐ·ÐŸÐ¹ÐŽÐµÑ, ÐµÑÐ»Ðž Ð²Ñ ÐœÐ°Ð¶ÐŒÐµÑÐµ ÐœÐ° ÐœÐµÐ³ÐŸ. Ð­ÐºÑÐ¿ÐµÑÐžÐŒÐµÐœÑÐžÑÑÐ¹ÑÐµ! ÐÐ»Ñ Ð±ÐŸÐ»ÑÑÐµÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž ÑÐŒÐŸÑÑÐžÑÐµÂ <i>Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ.</i>
+</Text>
+<Subsection id="troubleshooting">
+<Title>
+<Text id="128">Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÐµ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÑ</Text>
+</Title>
+<Content>
+<Table id="table_troubleshooting">
+<Title/>
+<TableContent>
+<tr>
+<th width="140">Â </th>
+<th width="161">
+<Text id="129"><b>ÐÑÐŸÐ±Ð»ÐµÐŒÐ°</b></Text>
+</th>
+<th width="242">
+<Text id="130"><b>ÐÐŸÐ¿ÑÐŸÐ±ÑÐ¹ÑÐµ</b></Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="131">
+<b>ÐÐŸÐºÐ°Ð»ÑÐœÐ°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° (ÑÐŸÐ»ÑÐºÐŸ Windows)</b>
+</Text>
+</th>
+<th width="161">
+<Text id="132">ÐÐŸÐ³ÐŽÐ° Ñ Ð·Ð°Ð¿ÑÑÐºÐ°Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, ÐºÐŸÐŒÐ¿ÑÑÑÐµÑ Ð¿ÑÐŸÑÐžÑ ÐŒÐµÐœÑ ÐœÐ°Ð±ÑÐ°ÑÑ ÐœÐŸÐŒÐµÑ ÐžÐœÑÐµÑÐœÐµÑ-Ð¿ÑÐŸÐ²Ð°Ð¹ÐŽÐµÑÐ°.</Text>
+</th>
+<th width="242">
+<Text id="133">ÐÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐºÐœÐŸÐ¿ÐºÑ ÐÑÐŒÐµÐœÐ°.. ÐÐ±ÑÑÐœÐŸ ÑÑÐŸÐ³ÐŸ ÐŽÐŸÑÑÐ°ÑÐŸÑÐœÐŸ, ÑÑÐŸÐ±Ñ ÑÐµÑÐžÑÑ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">Â </th>
+<th width="161">
+<Text id="134">ÐÐŸÐ³ÐŽÐ° Ñ Ð·Ð°Ð¿ÑÑÐºÐ°Ñ Greenstone, ÐºÐŸÐŒÐ¿ÑÑÑÐµÑ Ð¿ÑÐŸÐŽÐŸÐ»Ð¶Ð°ÐµÑ Ð·Ð°Ð¿ÑÐ°ÑÐžÐ²Ð°ÑÑ Ð¿ÐŸÐŽÐºÐ»ÑÑÐµÐœÐžÐµ Ðº ÐžÐœÑÐµÑÐœÐµÑ-Ð¿ÑÐŸÐ²Ð°Ð¹ÐŽÐµÑÑÂ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â </Text>
+</th>
+<th width="242">
+<Text id="135">ÐÑÐ±ÐµÑÐžÑÐµ "Restricted version"(ÐŸÐ³ÑÐ°ÐœÐžÑÐµÐœÐœÐ°Ñ Ð²ÐµÑÑÐžÑ) Ð¿ÑÐž Ð·Ð°Ð¿ÑÑÐºÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ. ÐÐœÐ° ÑÐ°Ð±ÐŸÑÐ°ÐµÑ Ð»ÐžÑÑ Ð² Netscape.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">Â </th>
+<th width="161">
+<Text id="136">ÐÐŸÐ³ÐŽÐ° Ñ Ð¿ÑÑÐ°ÑÑÑ Ð¿ÐŸÐ¿Ð°ÑÑÑ ÐœÐ° ÑÑÑÐ°ÐœÐžÑÑ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž, ÐŸÐœÐ° ÐœÐµ ÐŒÐŸÐ¶ÐµÑÂ Â Â Â Â Â Â Â Â Â </Text>
+</th>
+<th width="242">
+<Text id="137">ÐÑÐŸÐ²ÐµÑÑÑÐµ Ð²Ð°ÑÐž ÐÐœÑÐµÑÐœÐµÑ proxy - ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž Edit preferences Ð² Netscape Ðž Internet options (ÑÐ²ÐŸÐ¹ÑÑÐ²Ð° ÐŸÐ±ÐŸÐ·ÑÐµÐ²Ð°ÑÐµÐ»Ñ) Ð² Explorer</Text>
+</th>
+</tr>
+<tr>
+<th width="140">Â </th>
+<th width="161">
+<Text id="138">ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ ÐŸÑÐµÐœÑ ÐŒÐµÐŽÐ»ÐµÐœÐœÐŸ!</Text>
+</th>
+<th width="242">
+<Text id="139">ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ Ð»Ðž Ð²Ñ Netscape Ð² Windows 2000? ÐÑÐ»Ðž ÑÑÐŸ ÑÐ°Ðº, ÑÐŸ Ð¿ÐŸÐ¿ÑÐŸÐ±ÑÐ¹ÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Internet Explorer Ð² Windows 2000. Ð£ Windows 2000 ÑÑÑÐµÑÑÐ²ÑÐµÑ ÐºÐ°ÐºÐ°Ñ- ÑÐŸ ÐœÐµÑÐŸÐ²ÐŒÐµÑÑÐžÐŒÐŸÑÑÑ Ñ Netscape.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="142"><b>ÐÐœÑÐµÑÐœÐµÑ-Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° (Windows Ðž Unix)</b></Text>
+</th>
+<th width="161">
+<Text id="143">ÐÐŸÑÐ»Ðµ Ð·Ð°Ð¿ÑÑÐºÐ° Apache, ÐŸÐœ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž Ð·Ð°ÐºÑÑÐ²Ð°ÐµÑÑÑ.</Text>
+</th>
+<th width="242">
+<Text id="144">ÐÐŸÐ±Ð°Ð²ÑÑÐµ ÑÐºÐ°Ð·Ð°ÐœÐžÐµ ServerName localhost Ð² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» Apache (<CrossRef target="Section" ref="apache_web_server"/>).</Text>
+</th>
+</tr>
+<tr>
+<th width="140">Â </th>
+<th width="161">
+<Text id="145">ÐÐŸÐ³ÐŽÐ° Ñ Ð¿ÑÑÐ°ÑÑÑ Ð¿ÐŸÐ¿Ð°ÑÑÑ Ð² ÑÐžÑÑÐŸÐ²ÑÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÑ, ÐžÐ·ÐŸÐ±ÑÐ°Ð¶Ð°ÐµÑÑÑ ÐŒÑÑÐŸÑ - Ð±ÐžÐœÐ°ÑÐœÑÐ¹ ÑÐ°Ð¹Ð»</Text>
+</th>
+<th width="242">
+<Text id="146">ÐÑÐŸÐ²ÐµÑÑÑÐµ ÐŽÐžÑÐµÐºÑÐžÐ²ÑÂ Â Â Â  ScriptAliasÂ Â Â Â Â  Ð² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ Apache, ÑÐŽÐŸÑÑÐŸÐ²ÐµÑÑÑÐµÑÑ, ÑÑÐŸ ÐŸÐœÐ° ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÐŽÐŸ ÐŽÐžÑÐµÐºÑÐžÐ²Ñ Alias (ÑÐŒÐŸÑÑÐžÑÐµ ÑÐ°ÑÑÑ 4.2 Ðž 4.3).</Text>
+</th>
+</tr>
+<tr>
+<th width="140">Â </th>
+<th width="161">
+<Text id="147">Ð¯ Ð¿ÐŸÐ¿Ð°ÐŽÐ°Ñ ÐœÐ° ÑÑÐ°ÑÑÐŸÐ²ÑÑ ÑÑÑÐ°ÐœÐžÑÑ Greenstone(<CrossRef target="Figure" ref="your_greenstone_home_page"/>), ÐœÐŸ ÐžÐºÐŸÐœÐºÐ° ÐÐµÐŒÐŸ-ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐœÐµ Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ.</Text>
+</th>
+<th width="242">
+<Text id="148">ÐÐ°Ð¿ÑÑÑÐžÑÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ library (Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž cgi-bin) ÐžÐ· DOS ÐŽÐ»Ñ Ð·Ð°Ð¿ÑÑÐºÐ° ÐŸÑÐ»Ð°ÐŽÐºÐž ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐžÂ Â  (debugging information) ÐŽÐ»Ñ ÐŸÐ±ÐœÐ°ÑÑÐ¶ÐµÐœÐžÑ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="140">
+<Text id="149"><b>ÐÐ±Ðµ Ð²ÐµÑÑÐžÐž</b></Text>
+</th>
+<th width="161">
+<Text id="150">ÐÐŸÐ³ÐŽÐ° Ñ Ð¿ÑÑÐ°ÑÑÑ Ð¿ÐŸÐ¿Ð°ÑÑÑ ÐœÐ° ÑÑÑÐ°ÐœÐžÑÑÂ  ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž, Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐœÐµ ÐŒÐŸÐ¶ÐµÑ ÐµÐµ ÐœÐ°Ð¹ÑÐž.Â Â Â Â Â Â Â Â Â Â Â Â Â Â </Text>
+</th>
+<th width="242">
+<Text id="151">ÐÐŸÐ¿ÑÑÐ°Ð¹ÑÐµÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ 127.0.0.1 Ð²ÐŒÐµÑÑÐŸ localhost . Ð­ÑÐŸ Ð·Ð°ÑÐµÐ·ÐµÑÐ²ÐžÑÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐœÐŸÐŒÐµÑ IP Ð°ÐŽÑÐµÑÐ° Ðž Ð¿ÑÐµÐŽÐœÐ°Ð·ÐœÐ°ÑÐµÐœ ÑÐ»ÑÐ¶ÐžÑÑ, ÐºÐ°Ðº "loopback" ÐŽÐ»Ñ Ð²Ð°ÑÐµÐ³ÐŸ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐ°.</Text>
+</th>
+</tr>
+<tr>
+<th width="140">Â </th>
+<th width="161">
+<Text id="152">ÐÑÐ°ÑÐ·ÐµÑ ÐœÐµ ÐŒÐŸÐ¶ÐµÑ ÐœÐ°Ð¹ÑÐž main.cfgÂ Â Â Â Â </Text>
+</th>
+<th width="242">
+<Text id="153">ÐÑÐŸÐ²ÐµÑÑÑÐµ, ÑÑÑÐµÑÑÐ²ÑÑÑ Ð»Ðž ÑÐ°Ð¹Ð»Ñ Greenstone Ðž ÐŽÐŸÑÑÑÐ¿ÐœÑ Ð»Ðž ÐŸÐœÐž ÐŽÐ»Ñ ÑÑÐžÑÑÐ²Ð°ÐœÐžÑ. ÐÑÐ»Ðž Ð²Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ ÐÐœÑÐµÑÐœÐµÑ-Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÑ Ð¿ÐŸÐ¿ÑÐŸÐ±ÑÐ¹ÑÐµ Ð·Ð°Ð¿ÑÑÑÐžÑÑÂ Â  Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑÂ Â  libraryÂ Â  Ñ ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐž. ÐÑÐ»Ðž ÐŸÐœÐ° Ð·Ð°Ð¿ÑÑÑÐžÑÑÑ, ÑÐŸ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÐ° ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² file permissionsÂ Â  (ÑÐŒÐŸÑÑÐžÑÐµ ÑÐ°ÑÑÑ <CrossRef target="Section" ref="file_permissions"/>). ÐÑÐ»Ðž ÐœÐµÑ,Â Â  ÑÐŸÂ Â  Ð¿ÐµÑÐµÐŒÐµÐœÐœÐ°Ñ Ð² gsdlhome ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐŒ ÑÐ°Ð¹Ð»ÐµÂ Â  gsdlsite.cfg ÐœÐ°Ð²ÐµÑÐœÑÐºÐ° ÐœÐ°ÑÑÑÐŸÐµÐœÐ° ÐœÐµÐ¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸ (ÑÐŒÐŸÑÑÐžÑÐµ Ð§Ð°ÑÑÑ <CrossRef target="Section" ref="gsdlsite_configuration_file"/>)</Text>
+</th>
+</tr>
+<tr>
+<th width="140">Â </th>
+<th width="161">
+<Text id="154">Ð¯ ÐžÐŒÐµÑ ÐœÐµÐ¿ÑÐžÑÑÐœÐŸÑÑÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑ</Text>
+</th>
+<th width="242">
+<Text id="155">ÐÑÐŸÑÑÐžÑÐµ Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ. Ð§Ð°ÑÑÑ <CrossRef external="User" lang="ru" target="Chapter" ref="making_greenstone_collections"/></Text>
+</th>
+</tr>
+<tr>
+<th width="140">Â </th>
+<th width="161">
+<Text id="156">Ð¯ ÐŽÐŸÐ±Ð°Ð²ÐžÐ» ÐœÐŸÐ²ÐŸÐ³ÐŸ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ, ÐœÐŸ ÐŸÐœÐ° ÐœÐµ ÐŒÐŸÐ¶ÐµÑ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑÑÑ.</Text>
+</th>
+<th width="242">
+<Text id="157">Ð£ÐŽÐŸÑÑÐŸÐ²ÐµÑÑÑÐµÑÑ, ÑÑÐŸ Ð²ÑÐµ, ÑÑÐŸ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž C:\Program Files\gsdl\etc, ÐŽÐŸÑÑÑÐ¿ÐœÐŸ ÐŽÐ»Ñ ÐŸÐ±ÑÐµÐ³ÐŸ ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÑ (ÑÐ°ÑÑÑ <CrossRef target="Section" ref="file_permissions"/>)</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="learn_more">
+<Title>
+<Text id="158">Ð£Ð·ÐœÐ°ÑÑ Ð±ÐŸÐ»ÑÑÐµ</Text>
+</Title>
+<Content>
+<Text id="159">Ð§ÑÐŸÐ±Ñ ÑÐ·ÐœÐ°ÑÑ Ð±ÐŸÐ»ÑÑÐµ ÐŸ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸÑÑÑÑ
+ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐÑÐžÐœÑÑÐŸÑÐœ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµÂ <i>Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž ÐÑÐžÐœÑÑÐŸÑÐœ</i>, Ð²ÐºÐ»ÑÑÐ°ÑÑÐµÐµ ÑÐ°ÐºÐžÐµ ÐŽÐµÑÐ°Ð»Ðž ÐºÐ°Ðº - ÑÑÑÑÐºÑÑÑÐ° ÐŽÐžÑÐµÐºÑÐŸÑÐžÐ¹ Ðž ÐºÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð²ÐµÐ± ÑÐ°Ð¹ÑÐ° ÑÐŸÐ·ÐŽÐ°ÐœÐœÐŸÐ³ÐŸ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐÑÐžÐœÑÑÐŸÑÐœ.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="greenstone_collections">
+<Title>
+<Text id="160">ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž Greenstone</Text>
+</Title>
+<Content>
+<Text id="161">ÐÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐŽÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Greenstone Ð²ÐºÐ»ÑÑÐµÐœÐŸ Ð² CD-ROM. ÐÑÐ»Ðž ÐÑ ÐžÐŒÐµÐµÑÐµ ÐŽÐŸÑÑÑÐ¿ Ðº ÐÐœÑÐµÑÐœÐµÑÑ, ÑÐŸ ÐŒÐœÐŸÐ³ÐŸ ÐŽÑÑÐ³ÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð·Ð°Ð³ÑÑÐ¶ÐµÐœÐŸ Ñ Ð²ÐµÐ±-ÑÐ°Ð¹ÑÐ° ÐÐŸÐ²ÐŸÐ·ÐµÐ»Ð°ÐœÐŽÑÐºÐŸÐ³ÐŸ Ð¿ÑÐŸÐµÐºÑÐ° ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž (nzdl.org) Ð² Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð¿ÐŸÑÑÑÐŸÐµÐœÐœÐŸÐŒ ÐžÐ»Ðž ÐœÐµ Ð¿ÐŸÑÑÑÐŸÐµÐœÐœÐŸÐŒÂ  Ð²ÐžÐŽÐµ.</Text>
+<Text id="162">ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Greenstone â ÑÑÐŸ ÐœÐµÐ±ÐŸÐ»ÑÑÐ°Ñ, ÐŽÐŸÐ²ÐµÐŽÐµÐœÐœÐ°Ñ ÐŽÐŸ ÑÐŸÐ²ÐµÑÑÐµÐœÑÑÐ²Ð°, ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐÑÐŒÐ°ÐœÐžÑÐ°ÑÐœÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž ÑÐ°Ð·Ð²ÐžÑÐžÑ (HDL). ÐÐœÐ° ÐžÐ»Ð»ÑÑÑÑÐžÑÑÐµÑ, ÐºÐ°ÐºÐžÐµ Ð±ÐŸÐ»ÑÑÐžÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÑ, ÐµÑÐ»Ðž ÐŽÐŸÑÑÑÐ¿ÐœÑ Ð¿ÐŸÐŽÑ
+ÐŸÐŽÑÑÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ. ÐÐœÐ° Ð²ÐºÐ»ÑÑÐ°ÐµÑÑÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž Ð¿ÑÐž ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ.</Text>
+<Text id="163">Greenstone ÑÐ°ÐºÐ¶Ðµ ÐžÐŽÐµÑ Ñ ÐœÐµÐºÐŸÑÐŸÑÑÐŒÐž Ñ
+ÐŸÑÐŸÑÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐŒÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒÐž, ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐ°Ñ
+ ÐºÐŸÑÐŸÑÑÑ
+ Â«Ð ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐžÂ» ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑÑÑ, ÐºÐ°Ðº ÐŸÐœÐž Ð¿ÐŸÑÑÑÐŸÐµÐœÑ. ÐÐœÐž ÐŽÐµÐŒÐŸÐœÑÑÑÐžÑÑÑÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž Greenstone. Ð£ÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐœÑÐµ ÐŽÐžÐ°Ð»ÐŸÐ³Ðž ÐŸÐ¿ÑÐŸÑÑÑ, Ñ
+ÐŸÑÐžÑÐµ Ð»Ðž ÐÑ Ð²ÐºÐ»ÑÑÐžÑÑ ÐžÑ
+ Ð² ÐžÐœÑÑÐ°Ð»Ð»ÐžÑÑÐµÐŒÑÑ ÐÐ°ÐŒÐž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Greenstone, ÑÐºÐ°Ð¶ÑÑ Ð¿ÑÐžÐ±Ð»ÐžÐ·ÐžÑÐµÐ»ÑÐœÑÐ¹ ÐŸÐ±ÑÐµÐŒ ÐœÐ° ÐŽÐžÑÐºÐµ, ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÑÐ¹ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Table class="hidden" id="table_collections">
+<Title/>
+<TableContent>
+<tr>
+<th width="123">
+<Text id="164"><i>demo</i></Text>
+</th>
+<th width="127">
+<Text id="165">ÐÐµÐŒÐŸÐœÑÑÑÐ°-ÑÐžÐŸÐœÐœÑÐ¹ Ð¿ÑÐžÐŒÐµÑ GreenstoneÂ <br/>(7 MÐ±)</Text>
+</th>
+<th width="298">
+<Text id="166">ÐÐµÐ±ÐŸÐ»ÑÑÐ°Ñ ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ HDL. ÐÑÐ»Ðž ÐÑ ÐºÐ»ÐŸÐœÐžÑÑÐµÑÐµ ÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÑÐŸ Ð¿ÐŸÐ»ÐœÑÐ¹ ÐœÐ°Ð±ÐŸÑ ÑÑÐµÐŽÑÑÐ² ÐŸÐ±ÑÐ»ÑÐ¶ÐžÐ²Ð°ÐœÐžÑ Ð¿ÐŸÑÐ²ÐžÑÑÑ ÑÐŸÐ»ÑÐºÐŸ Ð² ÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ, ÐµÑÐ»Ðž ÐÐ°ÑÐž ÐœÐŸÐ²ÑÐµ ÑÐ°Ð¹Ð»Ñ ÑÐŸÐ¿ÑÐŸÐ²ÐŸÐ¶ÐŽÐ°ÑÑÑÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐµÐ¹ ÐŸ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="167"><i>dls-e</i></Text>
+</th>
+<th width="127">
+<Text id="168">Ð¡ÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž ÑÐ°Ð·Ð²ÐžÑÐžÑÂ <br/>(150 ÐÐ±)</Text>
+</th>
+<th width="298">
+<Text id="169">ÐÐŸÐŽÐŸÐ±ÐœÐŸ ÐŽÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐŒÑ Ð¿ÑÐžÐŒÐµÑÑ Greenstone, ÑÑÐŸ - ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÂ  HDL, ÐœÐŸ ÐœÐ°ÐŒÐœÐŸÐ³ÐŸ Ð±ÐŸÐ»ÑÑÐµÐ³ÐŸ ÐŸÐ±ÑÐµÐŒÐ°. ÐÐœÐ° ÑÐŸÐŽÐµÑÐ¶ÐžÑ 250 Ð¿ÑÐ±Ð»ÐžÐºÐ°ÑÐžÐ¹ - ÐºÐœÐžÐ³, ÑÐŸÐŸÐ±ÑÐµÐœÐžÐ¹ Ðž Ð¶ÑÑÐœÐ°Ð»ÐŸÐ² - Ð² ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÐŸÐ±Ð»Ð°ÑÑÑÑ
+ ÑÐ°Ð·Ð²ÐžÑÐžÑ ÑÐµÐ»ÐŸÐ²ÐµÑÐµÑÑÐ²Ð° (Ð¿ÐŸÐ»ÐœÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ HDL ÑÐŸÐŽÐµÑÐ¶ÐžÑ 1230 Ð¿ÑÐ±Ð»ÐžÐºÐ°ÑÐžÐ¹). ÐÐœÐ° ÐžÐŒÐµÐµÑ ÑÑ Ð¶Ðµ ÑÐ°ÐŒÑÑ ÑÑÑÑÐºÑÑÑÑ, ÑÑÐŸ Ðž ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Greenstone. ÐÐœÐ° ÐŽÐŸÐ²ÐŸÐ»ÑÐœÐŸ ÑÐ»ÐŸÐ¶ÐœÐ°. ÐÐŸÑÑÐŸÐŒÑ, ÐµÑÐ»Ðž ÐÑ ÑÐŸÐ»ÑÐºÐŸ ÐœÐ°ÑÐžÐœÐ°ÐµÑÐµ ÑÐ°Ð±ÐŸÑÐ°ÑÑ, ÑÐŸ Ð»ÑÑÑÐµ ÐœÐ°ÑÐ°ÑÑ Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÐŽÑÑÐ³ÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐŽÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐ¹ MSWord, PDF, Ð°ÑÑ
+ÐžÐ²Ð° Greenstone ÐžÐ»Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÑÐŸÑÑÑÑ
+ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐ¹).</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="170"><i>wrdpdf-e</i></Text>
+</th>
+<th width="127">
+<Text id="171">ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÑ MSWord Ðž PDFÂ <br/>(4 ÐÐ±)</Text>
+</th>
+<th width="298">
+<Text id="172">ÐÐœÐ° ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð² ÑÐŸÑÐŒÐ°ÑÐµ PDF, MSWord, RTF, PostScript, ÐŽÐµÐŒÐŸÐœÑÑÑÐžÑÑÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð² ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÑÐŸÑÐŒÐ°ÑÐ°Ñ
+. ÐÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŸÑÐµÐœÑ Ð¿ÑÐŸÑÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="173"><i>gsarch-e</i></Text>
+</th>
+<th width="127">
+<Text id="174">ÐÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð°ÑÑ
+ÐžÐ²ÐŸÐ² GreenstoneÂ <br/>(5 ÐÐ±)</Text>
+</th>
+<th width="298">
+<Text id="175">ÐÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÐŸÐŸÐ±ÑÐµÐœÐžÐ¹ ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ Ð¿ÐŸÑÑÑ ÐžÐ· Ð°ÑÑ
+ÐžÐ²Ð° ÑÐ¿ÐžÑÐºÐŸÐ² Ð°ÐŽÑÐµÑÐ°ÑÐŸÐ² Greenstone, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÐ°Ñ Ð¿Ð»Ð°Ð³ÐžÐœ Email, ÐºÐŸÑÐŸÑÑÐ¹ Ð°ÐœÐ°Ð»ÐžÐ·ÐžÑÑÐµÑ ÑÐ°Ð¹Ð»Ñ Ð² ÑÐŸÑÐŒÐ°ÑÐ°Ñ
+ ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ Ð¿ÐŸÑÑÑ. ÐÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŸÑÐµÐœÑ Ð¿ÑÐŸÑÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="176"><i>Ñltbib-e</i></Text>
+</th>
+<th width="127">
+<Text id="177">ÐÐžÐ±Ð»ÐžÐŸÐ³ÑÐ°ÑÐžÑÐµÑÐºÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÂ <br/>(7 ÐÐ±)</Text>
+</th>
+<th width="298">
+<Text id="178">Ð­ÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð¿ÑÐžÐ±Ð»ÐžÐ·ÐžÑÐµÐ»ÑÐœÐŸ 4000 Ð±ÐžÐ±Ð»ÐžÐŸÐ³ÑÐ°ÑÐžÑÐµÑÐºÐžÑ
+ Ð·Ð°Ð¿ÐžÑÐµÐ¹. ÐÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÐŸÐžÑÐºÐ° ÑÐŸÐ·ÐŽÐ°Ðœ ÐœÐ° ÐŸÑÐœÐŸÐ²Ðµ Ð±Ð»Ð°ÐœÐºÐ°, ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑÑ Ð¿ÐŸÐžÑÐº Ð¿ÐŸ Ð¿ÐŸÐ»ÑÐŒ Ð·Ð°Ð¿ÐžÑÐž. Ð­ÑÐŸ ÐŽÐŸÐ²ÐŸÐ»ÑÐœÐŸ ÑÐ»ÐŸÐ¶ÐœÑÐ¹ ÐºÐŸÐŒÐ¿Ð»ÐµÐºÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="179"><i>cltext-c</i></Text>
+</th>
+<th width="127">
+<Text id="180">ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ Ð±ÐžÐ±Ð»ÐžÐŸÐ³ÑÐ°ÑÐžÐž (1 ÐÐ±)</Text>
+</th>
+<th width="298">
+<Text id="181">Ð­ÑÐŸ ÐºÑÐŸÑÐµÑÐœÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ñ Ð±ÐžÐ±Ð»ÐžÐŸÐ³ÑÐ°ÑÐžÑÐµÑÐºÐžÐŒÐž Ð·Ð°Ð¿ÐžÑÑÐŒÐž ÐžÐ»Ð»ÑÑÑÑÐžÑÑÐµÑ ÑÑÐµÐŽÑÑÐ²ÐŸ Â«ÑÑÐ¿ÐµÑÐºÐŸÐ»Ð»ÐµÐºÑÐžÐžÂ», ÐºÐŸÑÐŸÑÐŸÐµ Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑ Ð¿ÐŸÐžÑÐº Ð² Ð¿ÐµÑÐµÑÐµÐºÐ°ÑÑÐžÑ
+ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+. ÐÐœÐ° ÑÐ°Ð±ÐŸÑÐ°ÐµÑ Ð²ÐŒÐµÑÑÐµ Ñ ÐÐžÐ±Ð»ÐžÐŸÐ³ÑÐ°ÑÐžÑÐµÑÐºÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹. ÐÐµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» Ð¿ÐŸÑÑÐž ÑÐ°ÐºÐŸÐ¹ Ð¶Ðµ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="182"><i>MARC-e</i></Text>
+</th>
+<th width="127">
+<Text id="183">ÐÑÐžÐŒÐµÑ MARC (1 ÐÐ±)</Text>
+</th>
+<th width="298">
+<Text id="184">ÐÑÐœÐŸÐ²Ð°ÐœÐœÐ°Ñ ÐœÐ° ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ Ð·Ð°Ð¿ÐžÑÑÑ
+ MARC ÐžÐ· ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž ÐÐŸÐœÐ³ÑÐµÑÑÐ°, ÑÑÐŸ Ð¿ÑÐŸÑÑÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐœÐµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑÐ°Ñ Ð¿ÑÐŸÐ²ÐµÐŽÐµÐœÐžÐµ Ð¿ÐŸÐžÑÐºÐ° ÐœÐ° ÐŸÑÐœÐŸÐ²Ðµ Ð·Ð°ÐŽÐ°ÐœÐœÐŸÐ¹ ÑÐŸÑÐŒÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="185"><i>oai-e</i></Text>
+</th>
+<th width="127">
+<Text id="186">ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐž-ÐŸÐœÐœÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ OAI (18 ÐÐ±)</Text>
+</th>
+<th width="298">
+<Text id="187">ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐŸÑÐºÑÑÑÑÐ¹ Ð°ÑÑ
+ÐžÐ²ÐœÑÐ¹ Ð¿ÑÐŸÑÐŸÐºÐŸÐ» Ðž ÑÑÐµÐŽÑÑÐ²Ð° ÐÐŒÐ¿ÐŸÑÑÐ°, ÐŸÐœÐ° Ð²ÐŸÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐžÐ· Ð°ÑÑ
+ÐžÐ²Ð° Ðž ÑÑÑÐŸÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐžÐ· Ð·Ð°Ð¿ÐžÑÐµÐ¹. Ð ÐŽÐ°ÐœÐœÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ ÐŸÐœÐž ÑÐ²Ð»ÑÑÑÑÑ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑÐŒÐž, ÑÐ°Ðº ÑÑÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŸÐ±Ð° Ð¿Ð»Ð°Ð³ÐžÐœÐ° OAI Ðž Image.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="188"><i>image-e</i></Text>
+</th>
+<th width="127">
+<Text id="189">ÐÑÐŸÑÑÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐ¹ (1 ÐÐ±)</Text>
+</th>
+<th width="298">
+<Text id="190">Ð­ÑÐŸ ÐŸÑÐµÐœÑ ÐŸÑÐœÐŸÐ²Ð°ÑÐµÐ»ÑÐœÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐ¹ ÐœÐµ ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐœÐžÐºÐ°ÐºÐŸÐ³ÐŸ ÑÐµÐºÑÑÐ° Ðž ÐœÐžÐºÐ°ÐºÐžÑ
+ ÑÐ²ÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÑÐŸ ÐŽÐµÐ»Ð°ÐµÑ ÐµÐµ ÐŽÐŸÐ²ÐŸÐ»ÑÐœÐŸ ÐœÐµÑÐµÐ°Ð»ÐžÑÑÐžÑÐœÐŸÐ¹. ÐÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» ÑÐ²Ð»ÑÐµÑÑÑ Ð¿ÑÐŸÑÑÑÐŒ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="191"><i>authen-e</i></Text>
+</th>
+<th width="127">
+<Text id="192">ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÑ ÑÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°-ÐœÐžÑ Ðž Ð°ÑÑÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐž (8 ÐÐ±)</Text>
+</th>
+<th width="298">
+<Text id="193">ÐÐ° ÑÐŸÐŒ Ð¶Ðµ ÑÐ°ÐŒÐŸÐŒ ÐŒÐ°ÑÐµÑÐžÐ°Ð»Ðµ, ÑÑÐŸ Ðž Ð¿ÐµÑÐ²ÐŸÐœÐ°ÑÐ°Ð»ÑÐœÐ°Ñ ÐŽÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Greenstone, ÐŸÐœÐ° ÐŸÑÐ»ÐžÑÐ°ÐµÑÑÑ ÐŽÐ²ÑÐŒÑ ÐœÐµÐ·Ð°Ð²ÐžÑÐžÐŒÑÐŒÐž ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÑÐŒÐž: ÑÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐœÐµÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ðž ÑÐ¿ÑÐ°Ð²Ð»ÑÐµÐŒÑÐ¹ ÐŽÐŸÑÑÑÐ¿ Ðº ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ Ð¿ÐŸÑÐ»Ðµ Ð°ÑÑÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐž Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="194"><i>garish</i></Text>
+</th>
+<th width="127">
+<Text id="195">Ð ÐµÐ·ÐºÐ°Ñ Ð²ÐµÑÑÐžÑ ÐŽÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœ-ÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (8 ÐÐ±)</Text>
+</th>
+<th width="298">
+<Text id="196">Ð­ÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÐ°ÐºÐ¶Ðµ ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÑÐŸÑ Ð¶Ðµ ÑÐ°ÐŒÑÐ¹ ÐŒÐ°ÑÐµÑÐžÐ°Ð», ÑÑÐŸ Ðž ÐŽÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ Ð¿ÑÐžÐŒÐµÑ Greenstone. ÐÐµ Ð²ÐžÐŽ Ð±ÑÐ» ÐžÐ·ÐŒÐµÐœÐµÐœ, ÑÑÐŸÐ±Ñ Ð¿ÐŸÐºÐ°Ð·Ð°ÑÑ, ÐºÐ°Ðº Ð³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ ÑÑÑÐ°ÐœÐžÑÑ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐžÐ·Ð»ÐŸÐ¶ÐµÐœÑ Ð¿ÐŸ-ÐŽÑÑÐ³ÐŸÐŒÑ. ÐÐœÐ° ÑÐµÐ°Ð»ÐžÐ·ÐŸÐ²Ð°ÐœÐ° Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÐŸÐ³ÐŸ ÐŒÐ°ÐºÑÐŸ-ÑÐ°Ð¹Ð»Ð°, ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÐµÑÑÑ Ð²ÐŒÐµÑÑÐµ Ñ Greenstone.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="197"><i>isis-e</i></Text>
+</th>
+<th width="127">
+<Text id="198">ÐÑÐžÐŒÐµÑ CDS/ISIS (1 ÐÐ±)</Text>
+</th>
+<th width="298">
+<Text id="199">Ð­ÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÐŸÐ·ÐŽÐ°ÐœÐ° ÐžÐ· Ð±Ð°Ð·Ñ ÐŽÐ°ÐœÐœÑÑ
+ CDS/ISIS, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐµÐ¹ ÐŸÐºÐŸÐ»ÐŸ 150 Ð±ÐžÐ±Ð»ÐžÐŸÐ³ÑÐ°ÑÐžÑÐµÑÐºÐžÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ². ÐÐ»Ñ ÑÑÐµÐœÐžÑ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÑ
+ ÐŽÐ»Ñ ISIS ÑÐ°Ð¹Ð»ÐŸÐ² .mst Ðž .ftd Ðž Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÐœÐžÑ ÐžÑ
+ Ð² ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÐµ Greenstone ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð¿Ð»Ð°Ð³ÐžÐœ ISISPlug.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Chapter>
+<Chapter id="setting_up_webserver">
+<Title>
+<Text id="200">ÐÐ°ÑÑÑÐŸÐ¹ÐºÐ° ÑÐµÑÐµÐ²ÐŸÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ°</Text>
+</Title>
+<Content>
+<Text id="201">Ð ÑÑÐŸÐ¹ ÑÐ°ÑÑÐž ÐŸÐ¿ÐžÑÐ°Ðœ Ð¿ÑÐŸÑÐµÑÑ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž ÑÐµÑÐµÐ²ÐŸÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ° ÐŽÐ»Ñ ÑÐ°Ð±ÐŸÑÑ Ñ Greenstone. ÐÑÐµ ÑÐŸ, ÑÑÐŸ Ð±ÑÐŽÐµÑ ÐŸÐ¿ÐžÑÐ°ÐœÐŸ ÐœÐžÐ¶Ðµ, ÐžÐŒÐµÐµÑ ÐŸÑÐœÐŸÑÐµÐœÐžÐµ ÑÐŸÐ»ÑÐºÐŸ Ðº ÐÐœÑÐµÑÐœÐµÑ-Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐµ, Ðž Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÐ¿ÑÑÑÐžÑÑ ÑÑÑ ÑÐ°ÑÑÑ, ÐµÑÐ»Ðž Ñ Ð²Ð°Ñ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° Ð»ÐŸÐºÐ°Ð»ÑÐœÐ°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°.</Text>
+<Text id="202">ÐÑ Ð±ÑÐŽÐµÐŒ ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°ÑÑ ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ Apache, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ ÐºÐ°Ðº Ð² Windows, ÑÐ°Ðº Ðž Ð² Unix (ÑÐŒÐŸÑÑÐžÑÐµ ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ <CrossRef target="Chapter" ref="appendix_associated_software"/> ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÑÐµÐœÐžÑ Ð±ÐŸÐ»ÑÑÐµÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž),Microsoft's Personal Web Server (Ð \Ð/8)(Ð¡ÐµÑÐµÐ²Ð ÑÐµÑÐ²ÐµÑ Microsoft) Ðž ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ Internet Information Services (US). PWS ÑÐ²Ð»ÑÐµÑÑÑ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐŒ ÑÐµÑÐµÐ²ÑÐŒ Ð¿ÑÐŸÐŽÑÐºÑÐŸÐŒ Microsoft Ð¿ÐŸÐŽ Windows 95/98; US ÑÐŸÐ·ÐŽÐ°Ðœ Ð¿ÐŸÐŽ Windows 2000 Ðž Windows XP; Windows NT ÑÐ°ÐºÐ¶Ðµ ÐŒÐŸÐ¶ÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÑÑÐŸÑ ÑÐµÑÐ²ÐµÑ. Apache ÑÐ°Ð±ÐŸÑÐ°ÐµÑ ÐºÐ°Ðº Ñ Ð²ÐµÑÑÐžÐµÐ¹ ÑÐµÑÐµÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž ÐŽÐ»Ñ Windows, ÑÐ°Ðº Ðž ÐŽÐ»Ñ Unix (ÐœÐŸ ÐŒÑ Ð±ÑÐŽÐµÐŒ ÑÐ¿ÐŸÑÑÐµÐ±Ð»ÑÑÑ ÑÐµÑÐŒÐžÐœÐŸÐ»ÐŸÐ³ÐžÑ Windows); ÑÐ°ÑÑÑ, ÐºÐ°ÑÐ°ÑÑÐ°ÑÑÑ PWI/IIS, Ð¿ÑÐžÐ²ÐµÐŽÐµÐœÐ° ÑÐŸÐ»ÑÐºÐŸ ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹ Windows.</Text>
+<Text id="203">ÐÐŸÑÐ»Ðµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÑÐµÑÐµÐ²ÐŸÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ° ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÑÐ°ÐŒ Greenstone. ÐÑÐ»Ðž Ð² Ð¿ÑÐŸÑÐµÑÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ð±ÑÐŽÐµÑÐµ ÐœÐ°Ð¶ÐžÐŒÐ°ÑÑ ÐºÐœÐŸÐ¿ÐºÐž, Ð²ÑÐ±ÑÐ°ÐœÐœÑÐµ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ, ÑÐŸ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Ð±ÑÐŽÐµÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ C:\Program Files\gsdl Ð²ÐŒÐµÑÑÐµ ÑÐŸ Ð²ÑÐµÐŒÐž ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÑÐŒÐž ÑÐ°Ð¹Ð»Ð°ÐŒÐž.</Text>
+<Text id="204">ÐÑÐµ ÑÐµÑÐµÐ²ÑÐµ ÑÐµÑÐ²ÐµÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑ ÑÐ¿ÐµÑÐžÐ°Ð»ÑÐœÑÐ¹ URL Ð°ÐŽÑÐµÑ "localhost" ÐŽÐ»Ñ ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÐžÑ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐ°, ÐœÐ° ÐºÐŸÑÐŸÑÐŸÐŒ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ. Ð¢Ð°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ, Ð¿ÐŸÑÐ»Ðµ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº Ð²Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÐµ ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ, Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐŽÐŸÑÑÑÐ¿ Ðº Ð²Ð°ÑÐžÐŒ HTML-ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ, Ð²Ð²ÐµÐŽÑ URL http://localhost Ð² ÐŸÐºÐœÐµ Ð±ÑÐ°ÑÐ·ÐµÑÐ°. ÐÑÐ»Ðž ÐœÐ° Ð²Ð°ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐŸ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐŽÐŸÐŒÐµÐœÐ°, ÑÐŸ ÐŸÐœ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð²ÐŒÐµÑÑÐŸ localhost ÐŽÐ»Ñ ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÐžÑ Ð²Ð°ÑÐµÐ³ÐŸ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐ° Ð² ÑÐµÑÐž. Ð¢Ð°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ, ÐŽÐ»Ñ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐ° ÑÐµÑÐ²ÐµÑÐ° New Zealand Digital Library Ð°ÐŽÑÐµÑÐ° http://nzdl.org ÐžÂ  http://locahost ÐŸÐŽÐžÐœÐ°ÐºÐŸÐ²Ñ. ÐÑÐ»Ðž Ð²Ñ Ð²Ð²ÐµÐŽÐµÑÐµÂ Â  http://nzdl.org Ð² Ð²Ð°ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ, Ð²Ñ ÑÐŸÐµÐŽÐžÐœÐžÑÐµÑÑ Ñ ÑÐµÑÐ²ÐµÑÐŸÐŒ New Zealand Digital Library, Ð² ÑÐŸ Ð²ÑÐµÐŒÑ ÐºÐ°Ðº ÐµÑÐ»Ðž Ð²Ñ Ð²Ð²ÐµÐŽÐµÑÐµ http://localhost, Ð²Ñ Ð²ÑÐ¹ÐŽÐµÑÐµ ÐœÐ° Ð²Ð°Ñ ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ.</Text>
+<Section id="apache_web_server">
+<Title>
+<Text id="205">Ð¡ÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ Apache</Text>
+</Title>
+<Content>
+<Text id="206">ÐÐ±ÑÑÐœÐŸ ÑÑÐŸÑ ÑÐµÑÐ²ÐµÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ Ð² C:\Program Files\Apache Group\Apache Ðž ÐœÐ°ÑÑÑÐŸÐµÐœ ÑÐ°Ðº, ÑÑÐŸÐ±Ñ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ cgi-bin ÐœÐ°Ñ
+ÐŸÐŽÐžÐ»Ð°ÑÑ Ð² Ð¿ÐŸÐŽÐŽÐžÑÐµÐºÑÐŸÑÐžÐž \cgi-bin Ðž ÐºÐŸÑÐœÐµÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° (document root) ÑÐ²Ð»ÑÐ»Ð°ÑÑ Ð¿ÐŸÐŽÐŽÐžÑÐµÐºÑÐŸÑÐžÑ \htdocs. ÐÐ°ÑÑÑÐŸÐ¹ÐºÐž ÐŒÐŸÐ¶ÐœÐŸ ÐžÐ·ÐŒÐµÐœÐžÑÑ Ð¿ÑÑÐµÐŒÂ  ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð° C:\Program Files\Apache Group\conf\httpd.conf. ÐÐœ ÑÐ²Ð»ÑÐµÑÑÑ ÑÐµÐºÑÑÐŸÐ²ÑÐŒ ÑÐ°Ð¹Ð»ÐŸÐŒ Ðž Ð»ÐµÐ³ÐºÐŸ ÑÐžÑÐ°ÐµÐŒ.</Text>
+<Text id="207">Ð Ð·Ð°Ð²ÐžÑÐžÐŒÐŸÑÑÐž ÐŸÑ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº ÐœÐ° Ð²Ð°ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµÂ  ÐœÐ°ÑÑÑÐŸÐµÐœÐŸ ÑÐµÑÐµÐ²ÐŸÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ, Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ Ð±ÑÐŽÐµÑ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÑÑÑÐŸÐºÑ Ð² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» Apache, httpd.conf:</Text>
+<CodeLine>ServerName localhost</CodeLine>
+<Text id="208">ÐÑÐ»Ðž ÑÑÐ° ÑÑÑÐŸÐºÐ° ÐœÐµ Ð²ÐºÐ»ÑÑÐµÐœÐ°, ÑÐŸ ÑÐžÑÑÐµÐŒÐ° Ð¿ÐŸÐ¿ÑÑÐ°ÐµÑÑÑ ÐœÐ°Ð¹ÑÐž ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ Ð²Ð°ÑÐµÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ°. Ð¢ÐµÐŒ ÐœÐµ ÐŒÐµÐœÐµÐµ, Ð² ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ Ð²ÐµÑÑÐžÑÑ
+ Windows ÑÑÑÐµÑÑÐ²ÑÑÑ ÐŸÑÐžÐ±ÐºÐž, ÐºÐŸÑÐŸÑÑÐµ ÐœÐµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ ÑÐžÑÑÐµÐŒÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÐµÐ³ÐŸ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ. Ð ÑÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ Ð¿ÐŸÑÐ»Ðµ Ð·Ð°Ð¿ÑÑÐºÐ° Apache ÐœÐµÐŒÐµÐŽÐ»ÐµÐœÐœÐŸ Ð·Ð°ÐºÑÐŸÐµÑÑÑ. ÐÐŸÑÐ²Ð»ÑÐµÑÑÑ ÐŸÐºÐœÐŸ Ñ ÑÐŸÐŸÐ±ÑÐµÐœÐžÐµÐŒ ÐŸÐ± ÐŸÑÐžÐ±ÐºÐµ, ÐœÐŸ ÐŸÐœÐŸ ÐŒÐŸÐŒÐµÐœÑÐ°Ð»ÑÐœÐŸ ÐžÑÑÐµÐ·Ð°ÐµÑ, Ðž Ð²Ñ ÑÐºÐŸÑÐµÐµ Ð²ÑÐµÐ³ÐŸ ÐµÐ³ÐŸ ÐœÐµ ÑÐ²ÐžÐŽÐžÑÐµ Ð²ÐŸÐŸÐ±ÑÐµ.</Text>
+<Subsection id="setting_up_cgi-bin_directory">
+<Title>
+<Text id="209">ÐÐ°ÑÑÑÐŸÐ¹ÐºÐ° Greenstone ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž cgi-bin</Text>
+</Title>
+<Content>
+<Text id="210">Ð¡ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž Cgi-bin ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ ÐŸÐ±ÑÐ°ÑÐ°ÐµÑÑÑ Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒÐž, ÐºÐ°Ðº Ñ Ð²ÑÐ¿ÐŸÐ»ÐœÑÐµÐŒÑÐŒÐž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ°ÐŒÐž (executable programs). ÐÐžÑÐµÐºÑÐžÐ²Ð° ScriptAlias ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž cgi-bin. ÐÐ°ÐŒÐµÑÑÑÐµ, ÑÑÐŸ ÑÑÐ° ÐŽÐžÑÐµÐºÑÐžÐ²Ð° ÑÐ¿ÐŸÑÐŸÐ±ÐœÐ° Ð¿ÑÐµÐ²ÑÐ°ÑÐžÑÑ Ð»ÑÐ±ÑÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ Ð² cgi-ÐžÑÐ¿ÐŸÐ»ÐœÐžÐŒÑÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ -ÐœÐµ ÐŸÐ±ÑÐ·Ð°ÑÐµÐ»ÑÐœÐŸ, ÑÑÐŸÐ±Ñ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ ÐœÐ°Ð·ÑÐ²Ð°Ð»Ð°ÑÑ cgi-bin! Ð ÐœÐ°ÐŸÐ±ÐŸÑÐŸÑ, ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ cgi-bin ÐœÐµ ÑÐ²Ð»ÑÐµÑÑÑ ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÐ¹ ÐŽÐŸ ÑÐŸÐ³ÐŸ ÐŒÐŸÐŒÐµÐœÑÐ°, ÐºÐ°Ðº Ðº ÐœÐµÐ¹ ÐœÐµ Ð¿ÑÐžÐŒÐµÐœÐžÑÑ ScriptAlias.</Text>
+<Text id="211">ÐÐŸÑÐ»Ðµ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž Apache ÐžÐŒÐµÐµÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑÂ <i>cgi-bin</i>Â Ð²Â <i>C:\Program Files\Apache</i>
+<i>Group\Apache\cgi-bin</i>. Ð­ÑÐŸ ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ, ÑÑÐŸ ÐµÑÐ»Ðž Ð²Ð²ÐµÑÑÐž Ð°ÐŽÑÐµÑ URLÂ <i>http://localhost/cgi-bin/hello</i>, ÑÐŸ ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ Ð¿ÐŸÐ¿ÑÐŸÐ±ÑÐµÑ Ð·Ð°Ð¿ÑÑÑÐžÑÑ ÑÐ°Ð¹Ð», ÐœÐ°Ð·ÑÐ²Ð°ÑÑÐžÐ¹ÑÑ hello, ÐžÐ· ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž.</Text>
+<Text id="212">ÐÑÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Greenstone, ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÐ°Ñ libmry.exe,Â  ÐºÐŸÑÐŸÑÑÑ ÐœÑÐ¶ÐœÐŸ Ð·Ð°Ð¿ÑÑÑÐžÑÑ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÑÐµÑÐµÐ²ÐŸÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ°; Ð² ÑÐ²ÐŸÑ ÐŸÑÐµÑÐµÐŽÑ ÐŸÐœÐ°Â Â  ÑÑÐžÑÑÐ²Ð°ÐµÑ ÑÐ°Ð¹Ð», ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÑÐ¹ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» ÐŒÐµÑÑÐŸÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÑ Greenstone, ÐžÐ»Ðž "Â <i>gsdlsite.cfg</i>Â ", ÐºÐŸÑÐŸÑÑÐ¹ ÐŽÐŸÐ»Ð¶ÐµÐœ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² ÑÐŸÐ¹ Ð¶Ðµ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž.</Text>
+<Text id="213">ÐÑÑÑÐžÐ¹ ÑÐ¿ÐŸÑÐŸÐ±, ÑÑÐŸÐ±Ñ Ð²ÑÐ¿ÐŸÐ»ÐœÐžÑÑ ÑÑÐŸ, ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŽÐžÑÐµÐºÑÐžÐ²Ñ ScriptAlias ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐœÐŸÐ²ÐŸÐ¹ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐžÂ Â  cgi-bin. ÐÐŸÑ ÑÐ°ÑÑÑ ÐžÐ· ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð° Apache httpd.conf, ÐºÐŸÑÐŸÑÐ°Ñ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÂ <i>C:\Program Files\gsdl\cgi-bin</i>Â Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐŸÐ¹Â <i>cgi-bin</i>Â ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž:</Text>
+<CodeLine>ScriptAlias /gsdl/cgi-bin/ "C:/Program Files/gsdl/cgi-bin/"</CodeLine>
+<CodeLine>Â  &lt;Directory C:/Program Files/gsdl/cgi-bin&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â Â  Options None</CodeLine>
+<CodeLine>Â Â Â Â Â Â  AllowOverride None</CodeLine>
+<CodeLine>&lt;/Directory&gt;</CodeLine>
+<Text id="214">(ÐÐœÑÐµÑÐµÑÐœÑÐ¹ ÑÐ°ÐºÑ ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» Apache ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ / Ð²ÐŒÐµÑÑÐŸ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÑ
+ ÐŽÐ»Ñ Windows \).</Text>
+<Text id="215">Ð­ÑÐŸ ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ, ÑÑÐŸ Ð»ÑÐ±ÐŸÐ¹ URLÐ°ÐŽÑÐµÑ Ð²ÑÐŸÐŽÐµ http://localhost/gsdl/cgi-bin...Ð±ÑÐŽÐµÑ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑÑ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž C:\Program Files\gsdl\cgi-bin Ðž Ð·Ð°Ð¿ÑÑÐµÐœ ÑÐµÑÐµÐ²ÑÐŒ ÑÐµÑÐ²ÐµÑÐŸÐŒ. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, Ð¿ÑÐž Ð²ÑÑÑÐµÑÐµ Ñ URL http://localhost/gsdl/cgi-bin/hello ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ Ð¿ÐŸÐ¿ÑÑÐ°ÐµÑÑÑ ÐžÐ·Ð²Ð»ÐµÑÑ ÑÐ°Ð¹Ð» C:\Program Files\gsdl\cgi-bin\hello Ðž Ð·Ð°Ð¿ÑÑÑÐžÑÑ ÐµÐ³ÐŸ. Ð¢ÐµÐŒ ÐœÐµ ÐŒÐµÐœÐµÐµ, URLÂ  http://localhost/cgi-bin/helloÂ  Ð±ÑÐŽÐµÑ ÐžÑÐºÐ°ÑÑ Ð² ÐŸÐ±ÑÑÐœÐŸÐ¹ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž cgi-bin ApacheÂ  ÑÐ°Ð¹Ð»Â Â  C:\Program Files\Apache Group\Apache\cgi-bin\hello Ðž Ð¿ÑÑÐ°ÑÑÑÑ Ð·Ð°Ð¿ÑÑÑÐžÑÑ ÐµÐ³ÐŸ, ÑÐ°Ðº Ð¶Ðµ, ÐºÐ°Ðº Ðž Ð¿ÑÐµÐ¶ÐŽÐµ.</Text>
+</Content>
+</Subsection>
+<Subsection id="document_root_directory">
+<Title>
+<Text id="216">ÐÐŸÑÐœÐµÐ²Ð°Ñ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°</Text>
+</Title>
+<Content>
+<Text id="217">ÐÐŸÑÐœÐµÐ²Ð°Ñ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÑÐ²Ð»ÑÐµÑÑÑ ÐºÐŸÑÐœÐµÐŒ ÑÑÑÑÐºÑÑÑÑ Ð²Ð°ÑÐµÐ¹ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž. ÐÐŸÑÐ»Ðµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Apache ÑÐŸÐ·ÐŽÐ°ÐµÑ ÐºÐŸÑÐœÐµÐ²ÐŸÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ Ð² C:\Program Files\Apache Group\Apache\htdocs. Ð­ÑÐŸ ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ, ÑÑÐŸ ÐµÑÐ»Ðž Ð² ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ Ð²Ð²ÐµÑÑÐž URL http://localhost/hello.html, ÑÐŸ ÐŸÐœ Ð¿ÐŸÐ¿ÑÑÐ°ÐµÑÑÑ ÐžÐ·Ð²Ð»ÐµÑÑ ÑÐ°Ð¹Ð», ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÑÐ¹ hello.html, ÐžÐ· ÑÐŸÐ¹ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž.</Text>
+<Text id="218">ÐÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÐ°Ð¹Ð»ÐŸÐ² Ð² Greenstone ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÑÑÐžÑÑÐ²Ð°ÐµÐŒÑ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÑÐµÑÐµÐ²ÐŸÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ°. Ð¡Ð°ÐŒÑÐ¹ Ð¿ÑÐŸÑÑÐŸÐ¹ ÑÐ¿ÐŸÑÐŸÐ± Ð²ÑÐ¿ÐŸÐ»ÐœÐžÑÑ ÑÑÑ Ð·Ð°ÐŽÐ°ÑÑ ÑÑÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŽÐžÑÐµÐºÑÐžÐ²Ñ Alias, ÐºÐŸÑÐŸÑÐ°Ñ Ð¿ÐŸÑÑÐž ÑÐ°ÐºÐ°Ñ Ð¶Ðµ, ÐºÐ°ÐºÂ Â  ScriptAlias, Ð·Ð° ÐžÑÐºÐ»ÑÑÐµÐœÐžÐµÐŒ ÑÐŸÐ³ÐŸ, ÑÑÐŸ ÐŸÐœÐ° ÑÐ°Ð±ÐŸÑÐ°ÐµÑ Ñ Ð¿ÑÐŸÑÑÑÐŒÐž WWW-ÑÑÑÐ°ÐœÐžÑÐ°ÐŒÐž, Ð° ÐœÐµ ÑÐŸ ÑÐºÑÐžÐ¿ÑÐ°ÐŒÐž cgi. ÐÐ²ÐµÐŽÐžÑÐµ ÑÑÐž ÑÑÑÐŸÐºÐž Ð² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» Apache Ð¿ÐŸÑÐ»Ðµ ÐŽÐžÑÐµÐºÑÐžÐ²Ñ ScriptAlias, ÑÑÐŸ ÑÐŽÐµÐ»Ð°ÐµÑ C:\Program Files\gsdl ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÑÐŒ ÐŒÐµÑÑÐŸÐŒ Ð¿ÐŸÐžÑÐºÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ².</Text>
+<CodeLine>Alias /gsdl/ "C:/Program Files/gsdl/"</CodeLine>
+<CodeLine>Â  &lt;Directory C:/Program Files/gsdl&gt;</CodeLine>
+<CodeLine>Â Â Â Â Â  Options Indexes MultiViews FollowSymLinks</CodeLine>
+<CodeLine>Â Â Â  Â Â Â AllowOverride None</CodeLine>
+<CodeLine>Â  Â Order allow,deny</CodeLine>
+<CodeLine>Â  Allow from all</CodeLine>
+<CodeLine>&lt;/Directory&gt;</CodeLine>
+<Text id="219">Ð­ÑÐŸ ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ, ÑÑÐŸ Ð»ÑÐ±ÑÐµ URL, ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐ²Ð¿Ð°ÐŽÐ°ÑÑ Ñ Ð¿ÐµÑÐ²ÑÐŒ Ð°ÑÐ³ÑÐŒÐµÐœÑÐŸÐŒ Alias (gsdl), Ð±ÑÐŽÑÑ ÑÐ°Ð·ÑÑÐºÐžÐ²Ð°ÑÑÑÑ Ð² ÑÐŸÐ»Ðž ÑÐ°Ð¹Ð»ÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑ Ð²ÑÐŸÑÐŸÐŒÑ Ð°ÑÐ³ÑÐŒÐµÐœÑÑ.Â  ÐÑÑÐ³ÐžÐŒÐž ÑÐ»ÐŸÐ²Ð°ÐŒÐž, URL Ð²ÐžÐŽÐŸÐ² http://localhost/gsdl...Ð±ÑÐŽÑÑ ÑÐ°Ð·ÑÑÐºÐžÐ²Ð°ÑÑÑÑ, ÐºÐ°Ðº ÑÐ°Ð¹Ð»Ñ ÐžÐ· ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž C:\Program Files\gsdl. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, Ð¿ÑÐž Ð²ÑÑÑÐµÑÐµ Ñ URL http://localhost/gsdl/hello.html, ÑÐµÑÐ²ÐµÑ Ð¿ÐŸÐ¿ÑÑÐ°ÐµÑÑÑ ÐžÐ·Ð²Ð»ÐµÑÑ ÑÐ°Ð¹Ð» C:\Program Files\gsdl\hello.html. Ð¢ÐµÐŒ ÐœÐµ ÐŒÐµÐœÐµÐµ,Â  URL http://localhost/ hello.htmlÂ Â  ÐžÑÐµÑ ÑÐ°Ð¹Ð» Ð² Ð¿ÑÐŸÑÑÐŸÐ¹ htdocs ÐŽÐžÑÐµÐºÑÐŸÑÐžÐžC:\Program Files\Apache Group\Apache\htdocs\hello.html ÑÐ°ÐºÐ¶Ðµ, ÐºÐ°Ðº Ðž Ð¿ÑÐµÐ¶ÐŽÐµ.</Text>
+<Text id="220">ÐÐµ Ð·Ð°Ð±ÑÐŽÑÑÐµ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐŽÐžÑÐµÐºÑÐžÐ²Ñ Alias Ð¿ÐŸÑÐ»Ðµ ÐŽÐžÑÐµÐºÑÐžÐ²Ñ ScriptAlias.Â  ÐÑÐž ÑÐºÐ°Ð·Ð°ÐœÐžÐž Apache ÐŽÐ»Ñ alias /gsdl ÐŽÐŸ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº /gsdl/cgi-bin ÑÐŸÐ²Ð¿Ð°ÐŽÐµÑ Ñ URL / gsdl/cgi-bin/library, ÐŽÐŸ ÐŽÐžÑÐµÐºÑÐžÐ²Ñ Alias ÐœÐµÐ¶ÐµÐ»Ðž ScriptAlias, ÐŸÐœ Ð±ÑÐŽÐµÑ ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°Ðœ, ÐºÐ°Ðº Ð·Ð°Ð¿ÑÐŸÑ Ðº ÐŽÐŸÐºÑÐŒÐµÐœÑÑ, ÑÐµÐŒ ÐŽÐ»Ñ Ð·Ð°Ð¿ÑÑÐºÐ° Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ. Ð ÐžÑÐŸÐ³Ðµ Ð±ÐžÐœÐ°ÑÐœÑÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐ¹ ÑÐ°Ð¹Ð» ÐŽÐŸÐ»Ð¶ÐµÐœ Ð±ÑÑÑ "Ð²ÑÐ²ÐµÐŽÐµÐœ, Ð¿ÐŸÐºÐ°Ð·Ð°Ðœ" Ð² ÐŸÐºÐœÐµ ÐÐœÑÐµÑÐœÐµÑ-Ð±ÑÐ°ÑÐ·ÐµÑÐ° Ð²ÐŒÐµÑÑÐŸ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÐµÐ³ÐŸ Ð·Ð°Ð¿ÑÑÑÐžÑÑ.</Text>
+</Content>
+</Subsection>
+<Subsection id="security">
+<Title>
+<Text id="221">ÐÐµÐ·ÐŸÐ¿Ð°ÑÐœÐŸÑÑÑ</Text>
+</Title>
+<Content>
+<Text id="222">ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ Ð·ÐœÐ°ÑÑ, ÑÑÐŸ ÐµÑÐ»ÐžÂ  ÐÐœÑÐµÑÐœÐµÑ-Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Ð±ÑÐŽÐµÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° ÑÐ°Ðº, ÐºÐ°Ðº ÐŸÐ¿ÐžÑÐ°ÐœÐŸ Ð²ÑÑÐµ, ÑÐŸ ÐºÐ°Ð¶ÐŽÑÐ¹ ÑÐŒÐŸÐ¶ÐµÑ Ð·Ð°Ð³ÑÑÐ¶Ð°ÑÑ Ð»ÑÐ±ÐŸÐ¹ ÑÐ°Ð¹Ð» ÐžÐ· ÑÑÑÑÐºÑÑÑÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž gsdl. Ð­ÑÐŸ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÐžÐœÐŽÐµÐºÑÐœÑÐµ ÑÐ°Ð¹Ð»Ñ, ÐžÑÑ
+ÐŸÐŽÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð»ÑÐ±ÐŸÐ¹ Ð³ÐŸÑÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÑÐºÐ°Ñ Ð±Ð°Ð·Ð° ÐŽÐ°ÐœÐœÑÑ
+, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐµ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐžÐŸÐœÐœÑÐµ ÑÐ°Ð¹Ð»Ñ (logs) Ðž Ñ.ÐŽ.</Text>
+<Text id="223">ÐÑÐ»Ðž ÐŽÐ°ÐœÐœÐ°Ñ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ Ð²Ð°Ð¶ÐœÐ°, Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð° ÑÐµÑÐ²ÐµÑÐ° ÐŽÐ»Ñ ÑÐ¶ÐµÑÑÐŸÑÐµÐœÐžÑ Ð±ÐµÐ·ÐŸÐ¿Ð°ÑÐœÐŸÑÑÐž. Ð ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ ÑÐµÑÐµÐ²ÐŸÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ° Apache Ð²Ð²ÐµÐŽÐžÑÐµ ÑÐ»ÐµÐŽÑÑÑÐžÐµ ÑÑÑÐŸÐºÐž Ð²ÐŒÐµÑÑÐŸ Ð²ÑÑÐµÐ¿ÐŸÐºÐ°Ð·Ð°ÐœÐœÑÑ
+</Text>
+<CodeLine>Alias /gsdl/ "C:/Program Files/gsdl/"</CodeLine>
+<CodeLine>Â  &lt;Directory "C:/Program Files/gsdl"&gt;</CodeLine>
+<CodeLine>Â Â Â  Order allow,deny</CodeLine>
+<CodeLine>Â Â Â  Deny from all</CodeLine>
+<CodeLine>Â Â Â  &lt;FilesMatch</CodeLine>
+<CodeLine>"\.(gif|jpe?g|png|css|mov|mpeg|ps|pdf|doc|rtf|jar|class)$"&gt;</CodeLine>
+<CodeLine>Â Â  Order allow,deny</CodeLine>
+<CodeLine>Â Â  Allow from all</CodeLine>
+<CodeLine>Â  &lt;/FilesMatch&gt; </CodeLine>
+<CodeLine>&lt;/Directory&gt;</CodeLine>
+<Text id="224">Ð­ÑÐŸ ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ, ÑÑÐŸ ÑÐŸÐ»ÑÐºÐŸ ÑÐµ ÑÐ°Ð¹Ð»Ñ, ÑÑÐµ ÑÐ°Ð·ÑÐµÑÐµÐœÐžÐµ ÑÐŸÐ²Ð¿Ð°ÐŽÐ°ÐµÑ Ñ regular expression Ð² ÑÑÑÐŸÐºÐµ FilesMatch, ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð·Ð°Ð³ÑÑÐ¶ÐµÐœÑ.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="pws_and_iis_webservers">
+<Title>
+<Text id="225">Ð¡ÐµÑÐµÐ²ÑÐµ ÑÐµÑÐ²ÐµÑÑ PWS, MS</Text>
+</Title>
+<Content>
+<Text id="226">Ð¥ÐŸÑÑ ÐœÐž PWS ÐœÐž MS Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÐœÐµ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ Ð² ÑÐžÑÑÐµÐŒÐ°Ñ
+ Windows, ÐžÑ
+ ÐŒÐŸÐ¶ÐœÐŸ Ð»ÐµÐ³ÐºÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ, Ð¿ÐŸÐ»ÑÐ·ÑÑÑÑ ÐŒÐµÐœÑ Ð¿Ð°ÐœÐµÐ»Ðž ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ "Ð£ÐŽÐ°Ð»ÐžÑÑ/ ÐÐŸÐ±Ð°Ð²ÐžÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ". ÐÑÐ»Ðž ÐžÑ
+ ÐœÐµÑ ÐœÐ° ÐºÐŸÐŒÐ¿Ð°ÐºÑ-ÐŽÐžÑÐºÐµ, ÑÐŸ ÐžÑ
+ ÐŒÐŸÐ¶ÐœÐŸ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ Ñ ÑÐ°Ð¹ÑÐ° Microsoft (www.mircosoft.com) ÐÑÐŸÑÐµÑÑ ÐžÐœÑÑÐ°Ð»ÑÑÐžÐž ÐŽÐ»Ñ ÐŸÐ±ÐµÐžÑ
+ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒ ÐŸÐŽÐžÐœÐ°ÐºÐŸÐ².</Text>
+<Text id="227">ÐÐ°Ð¿ÑÑÑÐžÑÐµ Personal Web Manager Ðž ÑÐŸÐ²ÐµÑÑÐžÑÐµ ÑÐ»ÐµÐŽÑÑÑÐžÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="228">ÐÑÐ±ÐµÑÐžÑÐµ Advanced (ÑÐ°ÑÑÐžÑÐµÐœÐœÑÐ¹) ÐŽÐ»Ñ Ð²ÑÐ²ÐŸÐŽÐ° ÐŸÐºÐœÐ° Advanced Options (Ð Ð°ÑÑÐžÑÐµÐœÐœÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="229">ÐÑÐ±ÐµÑÐžÑÐµ ÐÐŸÑÐµ(ÐÐ°ÑÐ°Ð»ÐŸ) Ðž ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐÑÐ(ÐÐŸÐ±Ð°Ð²ÐžÑÑ). ÐÐ°Ð¿ÐŸÐ»ÐœÐžÑÐµ Ð¿ÐŸÐ»Ñ ÑÐ»ÐµÐŽÑÑÑÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ:</Text>
+<Text id="230">Ð Ð¿ÐŸÐ»Ðµ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ: C:\Program Files\gsdl</Text>
+<Text id="231">Ð Ð¿ÐŸÐ»Ðµ Alias :Â <i>gsdl</i>
+</Text>
+<Text id="232">Ð Ð¿ÐŸÐ»Ðµ Access permissions (ÑÐ°Ð·ÑÐµÑÐµÐœÐœÑÐ¹ ÐŽÐŸÑÑÑÐ¿): Read (ÑÑÐµÐœÐžÐµ)</Text>
+<Text id="233">Ð Ð¿ÐŸÐ»Ðµ Application permissions: None</Text>
+<Text id="234">ÐÐ°Ð¶ÐŒÐžÑÐµ OK</Text>
+<Text id="235">Ð¡ ÑÑÐžÐŒÐž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ°ÐŒÐž ÑÐ°Ð¹Ð»Ñ Greenstone Ð±ÑÐŽÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑ ÐŽÐ»Ñ ÑÐµÑÐ²ÐµÑÐ°.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="236">ÐÐµÑÐœÐžÑÐµÑÑ Ð² Advanced Options, Ð²ÑÐ±ÐµÑÐžÑÐµ^/ Ðž ÐºÐ»ÐžÐºÐœÐžÑÐµ Add ÐÐ°Ð¿ÐŸÐ»ÐœÐžÑÐµ ÑÐ»ÐµÐŽÑÑÑÐžÐµ Ð¿ÐŸÐ»Ñ:</Text>
+<Text id="237">Directory field:.C:\Program Files\gsdl\cgi-bin</Text>
+<Text id="238">Alias field: cgi-bin</Text>
+<Text id="239">Access permissions:Â <i>None</i></Text>
+<Text id="240">Application permissions:Â <i>Execute</i></Text>
+<Text id="241">ÐÐ°Ð¶ÐŒÐžÑÐµ OK</Text>
+<Text id="242">ÐÐŸÑÐ»Ðµ ÑÑÐŸÐ³ÐŸ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Greenstone library.exe to be executed by the Webserver.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="243">ÐÐ²ÐµÐŽÐžÑÐµ Ð°ÐŽÑÐµÑ URLÂ <i>http://localhost/gsdl/cgi-bin/library.exe</i></Text>
+<Text id="244">ÐÑÐžÐŒÐµÑÐ°ÐœÐžÐµ: Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ ÐŽÐŸÐ¿ÐžÑÑÐ²Ð°ÑÑ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµ .ÐµÑ
+Ðµ Ð¿ÑÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž PWS, MS.</Text>
+</NumberedItem>
+</NumberedList>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="configuring_your_site">
+<Title>
+<Text id="245">ÐÐ°ÑÑÑÐŸÐ¹ÐºÐ° ÑÐ°Ð¹ÑÐ°</Text>
+</Title>
+<Content>
+<Text id="246">ÐÐ»Ñ Ð¿ÐŸÐ»ÐœÐŸÑÐµÐœÐœÐŸÐ³ÐŸ ÑÑÐœÐºÑÐžÐŸÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ Greenstone ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÐœÐ°ÑÑÑÐŸÐžÑÑ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ ÐŽÐŸÑÑÑÐ¿Ð° ÐŽÐ»Ñ ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ². ÐÐŽÐŸÐ±Ð°Ð²ÐŸÐº ÑÑÑÐµÑÑÐ²ÑÐµÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð», ÑÐ²ÑÐ·Ð°ÐœÐœÑÐ¹ Ñ ÐºÐ°Ð¶ÐŽÑÐŒ ÐŒÐµÑÑÐŸÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÐµÐŒ Greenstone. Ð Ð¿ÑÐŸÑÐµÑÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÑÐŸÐ·ÐŽÐ°ÐµÑÑÑ Ð±Ð°Ð·ÐŸÐ²ÑÐ¹ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð», ÐŸÑÐœÐŸÐ²ÑÐ²Ð°ÑÑÐžÐ¹ÑÑ ÐœÐ° Ð²Ð°ÑÐžÑ
+ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐ°Ñ
+ Ð²ÐŸ Ð²ÑÐµÐŒÑ ÑÑÐŸÐ¹ Ð¿ÑÐŸÑÐµÐŽÑÑÑ; ÑÐµÐŒ ÐœÐµ ÐŒÐµÐœÐµÐµ, ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ ÑÑÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð° ÐŒÐŸÐ¶ÐœÐŸ ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐŽÐ»Ñ ÐŸÐ¿ÑÐžÐŒÐžÐ·Ð°ÑÐžÐž</Text>
+<Section id="file_permissions">
+<Title>
+<Text id="247">Ð€Ð°Ð¹Ð»Ñ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ</Text>
+</Title>
+<Content>
+<Text id="248">ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ðž Windows 95/98 ÐŒÐŸÐ³ÑÑ Ð¿ÑÐŸÐ¿ÑÑÑÐžÑÑ ÑÑÑ ÑÐ°ÑÑÑ, ÑÐ°Ðº ÐºÐ°Ðº ÑÑÐž Ð²ÐµÑÑÐžÐž ÐœÐµ ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°ÑÑ Ð²Ð»Ð°ÐŽÐµÐ»ÑÑÐµÐ² ÑÐ°Ð¹Ð»ÐŸÐ².</Text>
+<Text id="249">Ð Windows NT, 2000, Unix cgi ÑÐºÑÐžÐ¿ÑÑ ÐœÐµ ÐŒÐŸÐ³ÑÑ ÑÐ°Ð±ÐŸÑÐ°ÑÑ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐœÐŸÑÐŒÐ°Ð»ÑÐœÑÑ
+ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹, ÑÐ°Ðº ÐºÐ°Ðº Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹ ÐœÐµÐ»ÑÐ·Ñ ÐžÐŽÐµÐœÑÐžÑÐžÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐµÑÐµÐ· WWW.Â  ÐÐŒÐµÑÑÐŸ ÑÑÐŸÐ³ÐŸ cgi scriptÂ Â  ÑÐ°Ð±ÐŸÑÐ°ÐµÑ ÐºÐ°Ðº Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ, ÐºÐŸÑÐŸÑÑÐ¹ Ð·Ð°Ð¿ÑÑÑÐžÐ» ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ ( Ð² Windows), ÐžÐ»Ðž ÐºÐ°Ðº ÑÐ°ÑÑÐœÑÐ¹ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ (Ð² Unix ÑÐ°ÑÑÐŸ ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÑÐ¹Â Â Â  nobodyÂ Â  (ÐœÐžÐºÑÐŸ)). Ð ÑÐ²ÑÐ·Ðž Ñ ÑÑÐžÐŒ Ð²ÑÐµ ÑÐ°Ð¹Ð»Ñ Ðž ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž Ð² C:\Program Files\gsdl ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑ ÐŽÐ»Ñ Ð²ÑÐµÐŸÐ±ÑÐµÐ³ÐŸ ÑÑÐµÐœÐžÑ (ÐžÐ»Ðž, Ð¿ÐŸ ÐºÑÐ°Ð¹ÐœÐµÐ¹ ÐŒÐµÑÐµ, ÐŽÐŸÑÑÑÐ¿ÐœÑ ÐŽÐ»Ñ ÑÑÐµÐœÐžÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÐŒ cgi-script, ÑÐ°ÐºÐžÐŒ ÐºÐ°Ðº "nobody"). ÐÐ»Ñ Ð¿ÑÐŸÐ²ÐµÑÐºÐž ÑÐŸÐ³ÐŸ, Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸ Ð»Ðž ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ ÑÐ°Ð¹Ð»Ñ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ, Ð·Ð°Ð¿ÑÑÑÐžÑÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ library.exe ÐžÐ· ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐž. ÐÑÐ»Ðž ÑÐ°Ð¹Ð»Ñ ÐœÐ°Ñ
+ÐŸÐŽÑÑÑÑ Ð² ÐœÑÐ¶ÐœÐŸÐŒ ÐŒÐµÑÑÐµ, ÐœÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ ÐŽÐŸÑÑÑÐ¿Ð° ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ ÐœÐµÐ¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸ, Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Ð·Ð°Ð¿ÑÑÑÐžÑÑÑ Ñ ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐž, ÐºÐŸÐ³ÐŽÐ°Â Â Â  ';ÑÂ Â  Ð·Ð°Ð¿ÑÑÑÐžÑÐµ ÐµÑ - ÐœÐŸ ÐœÐµ Ñ Ð±ÑÐ°ÑÐ·ÐµÑÐ°, Ñ.Ðµ. ÐºÐŸÐ³ÐŽÐ° nobody Ð¿ÐŸÐ¿ÑÑÐ°ÐµÑÑÑ Ð·Ð°Ð¿ÑÑÑÐžÑÑ ÐµÑ.</Text>
+<Text id="250">ÐÐ»Ñ ÑÐ°Ð±ÐŸÑÑ Ð²ÐœÐµÑÐœÐžÑ
+ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹ ÑÐµÑÐµÐ· Ð±ÑÐ°ÑÐ·ÐµÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ, ÑÑÐŸÐ±Ñ Ð²ÑÐµ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž Greenstone Ð±ÑÐ»Ðž ÐŸÐ±ÑÐµÐŽÐŸÑÑÑÐ¿ÐœÑ ÐŽÐ»Ñ ÑÑÐžÑÑÐ²Ð°ÐœÐžÑ. ÐÐžÑÐµÐºÑÐŸÑÐžÑ C:\Program Files\gsdl\etc Ðž Ð²ÑÑ ÐµÑ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ ÑÐ°ÐºÐ¶Ðµ ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑ ÐŽÐ»Ñ ÐŸÐ±ÑÐµÐ³ÐŸÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð·ÑÐžÐŒÑÐŒ.Ð­ÑÐ° ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ, Ð² ÐºÐŸÑÐŸÑÑÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐ°Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Ð·Ð°Ð¿ÐžÑÑÐ²Ð°ÐµÑ Ð²ÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐµ Ð»ÐŸÐ³Ðž, ÐŸÑÐžÐ±ÐºÐž Ðž ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÐŸÐœÐœÑÐµ Ð»ÐŸÐ³Ðž Ðž ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ Ð±Ð°Ð·Ñ ÐŽÐ°ÐœÐœÑÑ
+ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹. ÐÐŸ ÐµÑÐ»Ðž Ð²Ñ Ð²ÑÑ Ð¶Ðµ Ð¶ÐµÐ»Ð°ÐµÑÐµ ÐŸÐ³ÑÐ°ÐœÐžÑÐžÑÑ ÐŽÐŸÑÑÑÐ¿ ÐŒÐœÐŸÐ³ÐžÑ
+ Ðº Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ, Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐ°Ð·ÑÐµÑÐžÑÑ ÐŽÐŸÑÑÑÐ¿ ÑÐŸÐ»ÑÐºÐŸ Ðº initout.txt, key.db, users.db, history.db, usage.txt ÐŽÐ»Ñ Ð²ÐœÐµÑÐµÐœÐžÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÐ¹ eg [-Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÐŒ.</Text>
+<Text id="251">ÐÑÐ»Ðž ÑÐ°Ð¹Ð»Ñ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐž ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ ÐœÐµÐ¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸ ÐŽÐ»Ñ C:\Program Files\gsdl\etc, Ð²Ñ Ð·Ð°ÐŒÐµÑÐžÑÐµ, ÑÑÐŸ ÑÑÐœÐºÑÐžÑ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐž Ðž search history ÐœÐµ ÑÐ°Ð±ÐŸÑÐ°ÑÑ Ðž ÑÑÐŸ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐœÐµ ÑÐŸÐ·ÐŽÐ°ÐµÑ usage log (usage.txt).</Text>
+</Content>
+</Section>
+<Section id="gsdlsite_configuration_file">
+<Title>
+<Text id="252">ÐÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» gsdlsite.cfg</Text>
+</Title>
+<Content>
+<Text id="253">Ð Ð¿ÑÐŸÑÐµÑÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÑÐŸÐ·ÐŽÐ°ÐµÑÑÑ Ð±Ð°Ð·ÐŸÐ²ÑÐ¹ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð», ÐŸÑÐœÐŸÐ²ÑÐ²Ð°ÑÑÐžÐ¹ÑÑ ÐœÐ° Ð²Ð°ÑÐžÑ
+ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐ°Ñ
+ Ð²ÐŸ Ð²ÑÐµÐŒÑ ÑÑÐŸÐ¹ Ð¿ÑÐŸÑÐµÐŽÑÑÑ. Ð­ÑÐŸ ÑÐ°Ð¹Ð» C:\Program Files\gsdl\cgi-bin\gsdlsite.cfg Ðž Ð²ÐŸÑ ÐµÐ³ÐŸ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ:</Text>
+<CodeLine># Site configuration file for Greenstone.</CodeLine>
+<CodeLine># Lines begining with</CodeLine>
+<CodeLine># are comments.</CodeLine>
+<CodeLine># This file should be placed in the same directory as your library</CodeLine>
+<CodeLine># executable file. it should be edited to suit your site.</CodeLine>
+<CodeLine># points to the GSDLHOME directory</CodeLine>
+<CodeLine>gsdlhome âC:/Program Files/gsdlâ</CodeLine>
+<CodeLine># this is the http address of GSDLHOME</CodeLine>
+<CodeLine># if your webservers DocumentRoot is set to $GSDLHOME </CodeLine>
+<CodeLine># then httpprefix can be commented out</CodeLine>
+<CodeLine>httpprefix /gsdl</CodeLine>
+<CodeLine># this is the http address of the directory which</CodeLine>
+<CodeLine># contains the images for the interface.</CodeLine>
+<CodeLine>httpimg /gsdl/images</CodeLine>
+<CodeLine># should contain the http address of this cgi script. This</CodeLine>
+<CodeLine># is not needed if the http server sets the environment variable</CodeLine>
+<CodeLine># SCRIPT_NAME</CodeLine>
+<CodeLine>#gwcgi /cgi-bin/library</CodeLine>
+<CodeLine># maxrequests is the most requests a fastcgi process</CodeLine>
+<CodeLine># will serve before it exits. This can be set to a</CodeLine>
+<CodeLine># low figure (like 1) while debugging and then set</CodeLine>
+<CodeLine># to a high figure (like 10000) when everything is</CodeLine>
+<CodeLine># working well.</CodeLine>
+<CodeLine>#maxrequests 10000</CodeLine>
+<Text id="254">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐœÐ°ÑÑÑÐŸÐžÑÑ Ð²ÑÐµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž Ð¿ÑÑÐµÐŒ ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÑ ÑÑÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð°, Ñ
+ÐŸÑÑ ÑÐºÐŸÑÐµÐµ Ð²ÑÐµÐ³ÐŸ Ð²Ð°ÐŒ ÑÑÐŸ ÐœÐµ Ð¿ÐŸÐœÐ°ÐŽÐŸÐ±ÐžÑÑÑ.</Text>
+<Text id="255">Ð¡ÑÑÐŸÐºÐ°Â <i>gsdlhome</i>Â ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐœÐ° ÐŽÐžÑÐµÐºÑÐŸÑÐžÑÂ <i>C:\Program Files\gsdl</i></Text>
+<Text id="256"><i>httpprefix</i>Â ÑÐ²Ð»ÑÐµÑÑÑ WWW-Ð°ÐŽÑÐµÑÐŸÐŒ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž, Ð² ÐºÐŸÑÐŸÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ Greenstone. ÐÑÐµÐ¶ÐŽÐµ ÐŒÑ ÐŸÐ¿ÐžÑÑÐ²Ð°Ð»Ðž, ÐºÐ°Ðº ÑÐŸÐ·ÐŽÐ°ÑÑ alias ÑÐ°Ðº, ÑÑÐŸÐ±Ñ Ð¿ÐŸÐžÑÐº ÐÐœÑÐµÑÐœÐµÑ-Ð°ÐŽÑÐµÑÐŸÐ² ÑÐžÐ¿Ð°http://localhost/gsdl/... ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÐ»ÑÑ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÐžÂ <i>C:\Program Files\gsdl</i>.Â  ÐÐ²ÐµÐŽÐµÐœÐžÐµ ÑÑÑÐŸÐºÐžÂ Â <i>httpprefix /gsdl</i>Â Ð² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» gsdlsite ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑ ÑÐµ Ð¶Ðµ ÑÐ°ÐŒÑÐµ ÑÑÐ»ÐŸÐ²ÐžÑ ÐŽÐ»Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ Greenstone.</Text>
+<Text id="257"><i>httpimg</i>Â ÑÐ²Ð»ÑÐµÑÑÑ ÐÐœÑÐµÑÐœÐµÑ-Ð°ÐŽÑÐµÑÐŸÐŒ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐžÂ <i>C:\Program Files\gsdl\images</i>, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ð²ÑÐµ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ ÑÐŸÑÐŒÐ°ÑÐŸÐ² gif, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÑ
+ Ð² ÐžÐœÑÐµÑÑÐµÐ¹ÑÐµ. Ð Ð»ÑÐ±ÐŸÐ¹ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÐŸÐ¹ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž Greenstone ÑÑÐŸ Ð²ÑÐµÐ³ÐŽÐ° Ð±ÑÐŽÐµÑÂ <i>httpprefix/images</i>, Ðž ÑÑÑÐŸÐºÑ Ð² ÑÐ°Ð¹Ð»Ðµ Ð²ÑÑÐµ ÐŒÐŸÐ¶ÐœÐŸ ÐœÐµ ÐžÐ·ÐŒÐµÐœÑÑÑ.</Text>
+<Text id="258"><i>gwcgi</i>Â ÑÐ²Ð»ÑÐµÑÑÑ ÐÐœÑÐµÑÐœÐµÑ-Ð°ÐŽÑÐµÑÐŸÐŒ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ cgi. Ð­ÑÐ° ÑÑÑÐŸÐºÐ° ÐœÐµ ÐœÑÐ¶ÐœÐ° Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²Ñ ÑÐµÑÐ²ÐµÑÐŸÐ² (Ð²ÐºÐ»ÑÑÐ°Ñ Apache), Ðž ÐµÑ ÐœÑÐ¶ÐœÐŸ ÐŸÑÑÐ°Ð²ÐžÑÑ Ð² ÐœÐ°ÑÐ°Ð»ÑÐœÐŸÐŒ Ð²ÐžÐŽÐµ.</Text>
+<Text id="259"><i>maxrequests</i>Â ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð²ÐµÑÑÐžÑÐŒÐž Greenstone, ÐºÐŸÑÐŸÑÑÐµ ÑÐºÐŸÐŒÐ¿ÐžÐ»ÐžÑÐŸÐ²Ð°ÐœÑ Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ ÐŸÐ¿ÑÐžÐž "fast-cgi". Ð¡ÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐ¹ Ð±ÐžÐœÐ°ÑÐœÑÐ¹ ÐŽÐžÑÑÑÐžÐ±ÑÑÐžÐ² ÐœÐµ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÑÑÑ ÐŸÐ¿ÑÐžÑ, ÑÐ°Ðº ÐºÐ°Ðº ÐœÐµ Ð²ÑÐµ ÑÐµÑÐµÐ²ÑÐµ ÑÐµÑÐ²ÐµÑÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑ ÑÑÑ ÐŸÐ¿ÑÐžÑ. Fastcgi ÑÑÐºÐŸÑÑÐµÑ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ cgi Ð·Ð° ÑÑÐµÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ main executable Ð² Ð¿Ð°ÐŒÑÑÐž ÐŒÐµÐ¶ÐŽÑ invocations Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, Ðž ÐŸÑÑÑÑÑÑÐ²ÐžÑ Ð¿ÐŸÑÑÐµÐ±ÐœÐŸÑÑÐž Ð² Ð¿ÐŸÑÑÐŸÑÐœÐœÐŸÐ¹ Ð·Ð°Ð³ÑÑÐ·ÐºÐµ Ñ ÐŽÐžÑÐºÐ° ÐºÐ°Ð¶ÐŽÑÐ¹ ÑÐ°Ð·, ÐºÐŸÐ³ÐŽÐ° Ð·Ð°Ð¿ÑÐ°ÑÐžÐ²Ð°ÐµÑÑÑ Ð²ÐµÐ±-ÑÑÑÐ°ÐœÐžÑÐ°. Trade off ÑÐ²Ð»ÑÐµÑÑÑ ÐŸÐ±ÑÐµÐŒ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐŸÐ¹ Ð¿Ð°ÐŒÑÑÐž, ÐºÐŸÑÐŸÑÑÐ¹ ÐŒÐŸÐ¶ÐµÑ ÑÐ²ÐµÐ»ÐžÑÐžÐ²Ð°ÑÑÑÑ ÑÐŸ Ð²ÑÐµ Ð±ÐŸÐ»ÑÑÐžÐŒ ÐºÐŸÐœÑÐŸÐŒ.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="personalizing">
+<Title>
+<Text id="260">ÐÐ°ÑÑÑÐŸÐ¹ÐºÐ° Ð±Ð°Ð·ÐŸÐ²ÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÑ</Text>
+</Title>
+<Content>
+<Text id="261">ÐÐ°Ð²ÐµÑÐœÑÐºÐ° Ð¿ÐµÑÐ²ÑÐŒ ÐŽÐµÐ»ÐŸÐŒ Ð¿ÐŸÑÐ»Ðµ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº Ð²Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÐµ Ðž ÐœÐ°Ð»Ð°ÐŽÐžÑÐµ Greenstone, Ð²Ñ Ð·Ð°Ñ
+ÐŸÑÐžÑÐµ ÐœÐ°ÑÑÑÐŸÐžÑÑ Ð±Ð°Ð·ÐŸÐ²ÑÑ ÑÑÑÐ°ÐœÐžÑÑ Greenstone. Ð€Ð°Ð¹Ð», ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÑÐ²ÐµÑÐ°ÐµÑ Ð·Ð° ÑÑÑ ÑÑÑÐ°ÐœÐžÑÑ ÐœÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ home.dm Ðž ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² Ð¿ÐŸÐŽÐŽÐžÑÐµÐºÑÐŸÑÐžÐž macros Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž, ÐºÑÐŽÐ° Ð±ÑÐ» ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ Greenstone (ÐÑÐž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐµ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑÂ Â  ÑÑÐŸ C:\Program Files\gsdl). Ð­ÑÐŸÑ ÑÐ°Ð¹Ð» ÑÐ²Ð»ÑÐµÑÑÑ Ð¿ÑÑÑÑÐŒ ÑÐµÐºÑÑÐŸÐ²ÑÐŒ ÑÐ°Ð¹Ð»ÐŸÐŒ, ÐºÐŸÑÐŸÑÑÐ¹ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐœÐŸÐ²ÐŸÐ¹ Ð±Ð°Ð·ÐŸÐ²ÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÑ. ÐÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÐŒ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐœÐŸÐ²ÑÐ¹ ÑÐ°Ð¹Ð», ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, yourhome.dm Ð²ÐŒÐµÑÑÐŸ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ home.dm. ÐÐœ Ð±ÑÐŽÐµÑ Ð¿ÐŸÑ
+ÐŸÐ¶ ÐœÐ° home.dm, ÐœÐŸ Ð±ÑÐŽÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ "package home". Ð­ÑÐ° ÑÐ°ÑÑÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÑÐ²ÐµÑÐ°ÐµÑ Ð·Ð° Ð²ÑÑ ÑÐ°Ð±ÐŸÑÑ ÐœÐµÐŒÐœÐŸÐ³ÐŸ Ð¿ÐŸ-ÐŽÑÑÐ³ÐŸÐŒÑ.</Text>
+<Text id="262">ÐÑÐž ÑÐŸÐ·ÐŽÐ°ÐœÐžÐž ÐŸÑÐŽÐµÐ»ÑÐœÐŸÐ¹ Ð±Ð°Ð·ÐŸÐ²ÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÑ ÐœÑÐ¶ÐœÐŸ ÑÐŸÐµÐŽÐžÐœÐžÑÑ ÐµÑ Ñ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐŸÐ¹. Ð ÐµÑÐµÐœÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ Ð¿ÑÐµÐŽÐ»Ð°Ð³Ð°ÐµÑ Greenstone, ÑÐŸÑÐŸÐžÑ Ð² ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž "ÐŒÐ°ÐºÑÐŸÑÐŸÐ²"(ÐŒÐ°ÐºÑÐŸÑÐ»ÐµÐŒÐµÐœÑÑ, ÐŒÐ°ÐºÑÐŸÐºÐŸÐŒÐ°ÐœÐŽÑ).ÐÐŸÑÑÐŸÐŒÑ ÐœÐ°ÑÐ°Ð»ÑÐœÐ°Ñ Ð±Ð°Ð·ÐŸÐ²Ð°Ñ ÑÑÑÐ°ÐœÐžÑÐ° ÐžÐŒÐµÐµÑ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµ ".dm", Ð° ÐœÐµ ".html". Ð€Ð°Ð¹Ð» macro Ð±ÐŸÐ»ÑÑÐµ ÐœÐµÐ¶ÐµÐ»Ðž Ð¿ÑÐŸÑÑÐŸÐ¹ HTML. ÐÐŸ ÐœÐµ Ð±ÐµÑÐ¿ÐŸÐºÐŸÐ¹ÑÐµÑÑ: ÐŒÐ°ÐºÑÐŸ-ÑÐ°Ð¹Ð» ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ð¿ÑÐŸÑÑÐŸÐ¹ HTML Ðž ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐµÐœÐžÐ¹, ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÑ
+ ÐœÐžÐ¶Ðµ. ÐÐ°ÐºÑÐŸÑÐ·ÑÐº ÑÐ²Ð»ÑÐµÑÑÑ ÐŒÐŸÑÐœÑÐŒ ÑÑÐµÐŽÑÑÐ²ÐŸÐŒ, Ðž ÑÐŸÐ»ÑÐºÐŸ ÐŒÐ°Ð»Ð°Ñ ÐµÐ³ÐŸ ÑÐ°ÑÑÑ ÐŸÐ¿ÐžÑÐ°ÐœÐ° ÐœÐžÐ¶Ðµ - ÑÐŒÐŸÑÑÐžÑÐµ Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° ÐŽÐ»Ñ Ð±ÐŸÐ»ÑÑÐµÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž.</Text>
+<Section id="example">
+<Title>
+<Text id="263">ÐÑÐžÐŒÐµÑ</Text>
+</Title>
+<Content>
+<Figure id="your_own_greenstone_home_page">
+<Title>
+<Text id="264">Ð ÐžÑÑÐœÐŸÐº 3 ÐÐ°ÑÐ° ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÐ°Ñ ÐŽÐŸÐŒÐ°ÑÐœÑÑ ÑÑÑÐ°ÐœÐžÑÐ°</Text>
+</Title>
+<File width="407" height="242" url="images/Install_Fig_3.png"/>
+</Figure>
+<Text id="265">ÐÐ° ÑÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="your_own_greenstone_home_page"/> Ð¿ÐŸÐºÐ°Ð·Ð°Ðœ Ð¿ÑÐžÐŒÐµÑ ÑÐŸÐ·ÐŽÐ°ÐœÐœÐŸÐ¹ Ð±Ð°Ð·ÐŸÐ²ÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž. ÐÐ°Ð¶ÐŽÐ°Ñ ÐžÐ· ÑÑÑÐ»ÐŸÐº "click here" (ÐœÐ°Ð¶ÐŒÐžÑÐµ) Ð¿ÑÐžÐ²ÐµÐŽÐµÑ Ð²Ð°Ñ Ðº ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐŒ ÑÑÐµÐŽÑÑÐ²Ð°ÐŒ Greenstone. Ð­ÑÐ° ÑÑÑÐ°ÐœÐžÑÐ° Ð±ÑÐ»Ð° ÑÐŸÐ·ÐŽÐ°ÐœÐ° ÑÐ°Ð¹Ð»ÐŸÐŒ yourhome.dm, Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐœÑÐŒ ÐœÐ° Ð ÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="yourhome_dm"/>.</Text>
+<Figure id="yourhome_dm">
+<Title>
+<Text id="266"><i>yourhome.dm</i>, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ Ð ÐžÑÑÐœÐºÐ° <CrossRef target="Figure" ref="your_own_greenstone_home_page"/></Text>
+</Title>
+<File width="407" height="388" url="Install_files/image011.jpg"/>
+</Figure>
+<Text id="267">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð ÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="yourhome_dm"/> ÐºÐ°Ðº ÐŸÑÐœÐŸÐ²Ñ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ Ð²Ð°ÑÐžÑ
+ Ð±Ð°Ð·ÐŸÐ²ÑÑ
+ ÑÑÑÐ°ÐœÐžÑ Ð² Greenstone. Ð ÑÑÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ Ð²ÑÐµ ÑÐ²ÐŸÐŽÐžÑÑÑ Ðº ÑÐŸÐŒÑ, ÑÑÐŸÐ±Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÐŒÐ°ÐºÑÐŸÑ, ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÑÐ¹ content (ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ). ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÑÐµÐºÑÑ, ÑÐ°ÐºÐ¶Ðµ Ð»ÑÐ±ÑÐµ ÑÐŸÑÐŒÐ°ÑÐœÑÐµ ÐºÐŸÐŒÐ°ÐœÐŽÑ HTML, ÐŽÐ»Ñ Ð¿ÐŸÐŒÐµÑÐµÐœÐžÑ Ð²ÑÐµÐ³ÐŸ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÐ³ÐŸ Ð²Ð°ÐŒ ÐœÐ° ÑÑÑ ÑÑÑÐ°ÐœÐžÑÑ Ð¢ÐµÐºÑ Ñ, ÐºÐŸÑÐŸÑÑÐ¹ Ð²Ñ Ð²Ð²ÐŸÐŽÐžÑÐµ, ÑÑÐŸ Ð¿ÑÐŸÑÑÐŸÐ¹ HTML; ÐµÑÐ»Ðž Ð²Ñ Ð¶ÐµÐ»Ð°ÐµÑÐµ, ÐŒÐŸÐ¶ÐœÐŸ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ Ð³ÐžÐ¿ÐµÑÑÑÑÐ»ÐºÐž Ðž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŽÑÑÐ³ÐžÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž, Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÐµÐŒÑÐµ HTML.</Text>
+<Text id="268">ÐÐ»Ñ ÑÐŸÐµÐŽÐžÐœÐµÐœÐžÑ Ð²Ð°ÑÐµÐ¹ ÐœÐŸÐ²ÐŸÐ¹ Ð±Ð°Ð·ÐŸÐ²ÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÑ Ñ ÐŽÑÑÐ³ÐžÐŒÐž ÑÑÑÐ°ÐœÐžÑÐ°ÐŒÐž Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Ð²Ð°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÐŸÐµ "ÑÐºÐ°Ð·Ð°ÐœÐžÐµ". Ð ÑÐ·ÑÐºÐµ ÐŒÐ°ÐºÑÐŸÑ ÐžÐŒÐž ÑÐ²Ð»ÑÑÑÑÑ ÑÐµ ÑÐ»ÐŸÐ²Ð°, ÐºÐŸÑÐŸÑÑÐµ Ñ ÐŽÐ²ÑÑ
+ ÑÑÐŸÑÐŸÐœ ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÑ ÑÐ¿ÐµÑÐžÐ°Ð»ÑÐœÑÐŒÐž Ð·ÐœÐ°ÐºÐ°ÐŒÐž .ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑ
+ ÑÐ²ÐžÐŽÐµÑÑ ÐœÐ° Ð ÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="yourhome_dm"/>.Â ÐÐ°Ð¿ÑÐžÐŒÐµÑ, _httppagehome_ Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑ ÐœÐ° Ð±Ð°Ð·ÐŸÐ²ÑÑ ÑÑÑÐ°ÐœÐžÑÑ, httppagehelp_ Ð¿ÑÐžÐ²ÐŸÐŽÐžÑ Ðº ÑÑÑÐ°ÐœÐžÑÐµ Ð¡Ð¿ÑÐ°Ð²ÐºÐž Ðž Ñ.ÐŽ. Ð ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÑÐ»ÑÑÐ°ÑÑ
+ Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ Ð±ÑÐŽÐµÑ ÑÐºÐ°Ð·Ð°ÑÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, httpquery_&amp;c=demo ÐœÐ°ÑÑÑÐ°ÐžÐ²Ð°ÐµÑ ÑÑÑÐ°ÐœÐžÑÑ Ð¿ÐŸÐžÑÐºÐ° ÐœÐ° ÐÐµÐŒÐŸ-ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ; ÐŽÐ»Ñ ÐŽÑÑÐ³ÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ð²Ñ ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÐŽÐµÑÐµ Ð·Ð°ÐŒÐµÐœÐžÑÑ demo ÐœÐ° ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐµ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="269">ÐÐ°ÐºÑÐŸÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐµ, ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÐŸÐµ _content_,Â Â  ÑÐ²Ð»ÑÐµÑÑÑ Ð¿ÑÐŸÑÑÑÐŒ HTML ÐÑÐ±ÐŸÐ¹ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐ¹ ÐºÐŸÐŽ HTML ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð·Ð°ÐŒÐµÐœÐµÐœ ÐŒÐ°ÐºÑÐŸÂ­ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑÐŒÐž. ÐÐŽÐœÐ°ÐºÐŸ, ÑÐ°ÐºÐžÐµ ÑÐžÐŒÐ²ÐŸÐ»Ñ, ÐºÐ°Ðº '{', '}', 'V, Ðž '_' ÐœÑÐ¶ÐœÐŸ Ð²ÑÐŽÐµÐ»ÑÑÑ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ backslash, ÑÑÐŸÐ±Ñ ÐžÐ·Ð±ÐµÐ¶Ð°ÑÑ ÐžÑ
+ Ð¿ÐµÑÐµÑÐµÑÐ°Ð±ÐŸÑÐºÐž ÐŒÐ°ÐºÑÐŸ ÑÐ·ÑÐºÐŸÐ²ÐŸÐ¹ ÐžÐœÑÐµÑÐ¿ÑÐµÑÐ°ÑÐŸÑ.</Text>
+<Text id="270">ÐÐ°ÐŒÐµÑÑÑÐµ, ÑÑÐŸ ÐŒÐ°ÐºÑÐŸÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐµ _content_ ÐœÐµ ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐœÐžÐºÐ°ÐºÐžÑ
+ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐŸÐ² Ðž footer. ÐÑÐ»Ðž Ð²Ñ Ð¶ÐµÐ»Ð°ÐµÑÐµ ÐžÐ·ÐŒÐµÐœÐžÑÑ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐž ÐžÐ»Ðž footer Ð²Ð°ÑÐµÐ¹ Ð±Ð°Ð·ÐŸÐ²ÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÑ, ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐžÑÑ ÐŒÐ°ÐºÑÐŸÑÑ header_ Ðž/ÐžÐ»Ðž Jooter_, ÐŽÐŸÐ±Ð°Ð²ÐžÐ² ÐžÑ
+ Ð² ÑÐ°Ð¹Ð» yourhome.dm Ð² Ð²ÐžÐŽÐµ:</Text>
+<CodeLine>_macroname_ {</CodeLine>
+<CodeLine>...</CodeLine>
+<CodeLine>}</CodeLine>
+<Text id="271">ÐÐ°Ð¿ÑÐžÐŒÐµÑ, Ð¿ÑÐŸÑÑÐ¶ÐµÐœÐœÑÐ¹ Ð·ÐµÐ»ÐµÐœÑÐ¹ ÑÐžÑÑÐœÐŸÐº, ÐœÐ°Ñ
+ÐŸÐŽÑÑÐžÐ¹ÑÑ Ð² Ð»ÐµÐ²ÐŸÐ¹ ÑÐ°ÑÑÐž ÑÑÑÐ°ÐœÐžÑÑ, ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœ Ð² ÐŒÐ°ÐºÑÐŸÑÐµ _header_, Ðž Ð¿ÑÐž ÑÐŽÐ°Ð»ÐµÐœÐžÐž ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐ³ÐŸ ÑÑÐŸÐ³ÐŸ ÐŒÐ°ÐºÑÐŸÑÐ° ÑÐžÑÑÐœÐŸÐº <CrossRef target="Figure" ref="yourhome_dm"/> ÑÐ±ÐµÑÐµÑÑÑ.</Text>
+</Content>
+</Section>
+<Section id="how_to_make_it_work">
+<Title>
+<Text id="272">Â  Ð§ÑÐŸ ÐœÑÐ¶ÐœÐŸ ÑÐŽÐµÐ»Ð°ÑÑ, ÑÑÐŸÐ±Ñ Ð²ÑÑ Ð·Ð°ÑÐ°Ð±ÐŸÑÐ°Ð»ÐŸ</Text>
+</Title>
+<Content>
+<Text id="273">ÐÐ»Ñ ÑÐŸÐ³ÐŸ ÑÑÐŸÐ±Ñ Ð²Ð°Ñ ÑÐ°Ð¹Ð» yourhome.dm ÐœÐ°ÑÐ°Ð» ÑÐ°Ð±ÐŸÑÐ°ÑÑ, Ð²Ñ ÐŽÐŸÐ»Ð¶ÐœÑ ÑÐºÐ°Ð·Ð°ÑÑ ÐµÐ³ÐŸ Ð² Ð³Ð»Ð°Ð²ÐœÐŸÐŒ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ main.cfg, ÑÐ°Ðº ÐºÐ°Ðº Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÑÑÐžÑÑÐ²ÐµÑ ÐŒÐ°ÐºÑÐŸÑÐ°Ð¹Ð»Ñ, ÑÐºÐ°Ð·Ð°ÐœÐœÑÐµ Ð² ÐœÐµÐŒ.</Text>
+<Text id="274">Ð¢Ð°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ, ÑÑÐŸÐ±Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐœÐ°ÑÐ°Ð»Ð° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð±Ð°Ð·ÐŸÐ²ÑÑ ÑÑÑÐ°ÐœÐžÑÑ, ÑÐŸÐ·ÐŽÐ°ÐœÐœÑÑ Ð²Ð°ÐŒÐž Ð²ÐŒÐµÑÑÐŸ ÐœÐ°ÑÐ°Ð»ÑÐœÐŸÐ¹, Ð²Ñ ÐŽÐŸÐ»Ð¶ÐœÑ Ð¿ÐŸÐŒÐµÑÑÐžÑÑ yourhome.dm Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ macros ÐœÐ° Ð ÐžÑÑÐœÐºÐµ <CrossRef target="Figure" ref="yourhome_dm"/>. ÐÐ°ÑÐµÐŒ Ð² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ main.cfg Ð·Ð°ÐŒÐµÐœÐžÑÐµÂ Â  home.dmÂ Â  ÐœÐ° yourhome.dm Ð² ÑÐ¿ÐžÑÐºÐµ ÐŒÐ°ÐºÑÐŸÑ ÑÐ°Ð¹Ð»ÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÐŽÐŸÐ»Ð¶ÐœÑ Ð·Ð°Ð³ÑÑÐ¶Ð°ÑÑÑÑ Ð¿ÑÐž Ð·Ð°Ð¿ÑÑÐºÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ.</Text>
+</Content>
+</Section>
+<Section id="redirecting_a_url_to_greenstone">
+<Title>
+<Text id="275">ÐÐµÑÐµÐ°ÐŽÑÐµÑÐ°ÑÐžÑ URL Ðº Greenstone</Text>
+</Title>
+<Content>
+<Text id="276">ÐÐ»Ñ Ð°ÐŽÑÐµÑÐŸÐ² Ðº Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐµ cgi Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐŸÐ·ÐŽÐ°ÑÑ Ð±ÐŸÐ»ÐµÐµ ÑÐŽÐŸÐ±ÐœÑÑ Ð¿ÐµÑÐµÐ°ÐŽÑÐµÑÐŸÐ²ÐºÑ(Ð±ÐŸÐ»ÐµÐµ ÐºÐŸÑÐŸÑÐºÐ°Ñ Ðž ÑÐ¶Ð°ÑÐ°Ñ ÑÐŸÑÐŒÐ°). ÐÐ°Ð¿ÑÐžÐŒÐµÑ, Ð°ÐŽÑÐµÑ URL http://nzdl.org (ÑÐŸÐºÑÐ°ÑÐµÐœÐ°ÑÂ Â  ÑÐŸÑÐŒÐ°Â Â  http://nzdl.org/index.html) Ð¿ÐµÑÐµÐ°ÐŽÑÐµÑÐŸÐ²ÑÐ²Ð°ÐµÑÑÑ ÐœÐ° Ð°ÐŽÑÐµÑÂ  http://nzdl.org/cgi-bin/library. Ð¡ÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ Apache Ð²ÑÐ¿ÐŸÐ»ÐœÑÐµÑ ÑÑÐŸ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐŽÐžÑÐµÐºÑÐžÐ²ÑÂ Â  Redirect. ÐÐ°Ðº Ðž ÐŽÑÑÐ³ÐžÐµ ÐŽÐžÑÐµÐºÑÐžÐ²Ñ, ÐŸÐœÐ° ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² C:\Program Files\Apache Group\Apache\conf\httpd.conf. ÐÐ»Ñ Ð¿ÐµÑÐµÐ°ÐŽÑÐµÑÐ°ÑÐžÐžÂ Â Â  URLÂ  http://www.yourserver.com ÐÐ° http:// www.yourserver.com/cgi-bin/libraryÂ Â  Ð²Ð²ÐµÐŽÐžÑÐµ ÑÑÐŸ Ð² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» httpd.conf:</Text>
+<CodeLine>Redirect /index.html http://www.yourserver.com/cgi-bin/library</CodeLine>
+<Text id="277">Ð¢Ð°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ Ð²Ñ Ð¿ÐŸÐ»ÑÑÐžÑÐµ Ð¿ÑÑÐŒÐŸÐ¹ ÐŽÐŸÑÑÑÐ¿ Ðº Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐµ ÑÐµÑÐµÐ· Ð°ÐŽÑÐµÑ http://www.yourserver.com . ÐÑÐ»Ðž Ð²Ñ Ñ
+ÐŸÑÐžÑÐµ, ÑÑÐŸÐ±Ñ Ð°ÐŽÑÐµÑ http:// www.yourserver .com/greenstone Ð¿ÑÐžÐ²ÐŸÐŽÐžÐ» Ð²Ð°Ñ Ðº Â http://www.yourserver.com/ cgi-bin/library Ð²Ð²ÐµÐŽÐžÑÐµ Ð² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ:</Text>
+<CodeLine>Redirect /greenstone http://www.yourserver.com/cgi-bin/library</CodeLine>
+<Text id="278">ÐÑÐ»Ðž Ñ Ð²Ð°ÑÐµÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ° ÐœÐµÑ ÐŽÐŸÐŒÐµÐœÐœÐŸÐ³ÐŸ ÐžÐŒÐµÐœÐž (ÐºÐ°Ðº www.yourserver.com Ð²ÑÑÐµ), Ð¿ÑÐŸÑÑÐŸ Ð·Ð°ÐŒÐµÐœÐžÑÐµ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ www.yourserver.com ÐœÐ° localhost Ð² ÑÑÑÐŸÐºÐ°Ñ
+, ÑÐºÐ°Ð·Ð°ÐœÐœÑÑ
+ Ð²ÑÑÐµ. Ð­ÑÐŸ Ð¿ÑÐžÐ²ÐµÐŽÐµÑ Ðº ÑÐ°ÐºÐŸÐŒÑ Ð¶Ðµ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÑ.</Text>
+<Text id="279">ÐÐŒÐµÑÑÐŸ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ Ð¿ÐŸÐŒÐµÑÐ°ÑÑ ÐŽÐžÑÐµÐºÑÐžÐ²Ñ Ð¿ÐµÑÐµÐ°ÐŽÑÐµÑÐ°ÑÐžÐž Ð² ÑÐ°Ð¹Ð» http.conf, Ð²Ñ ÑÐ°ÐºÐ¶Ðµ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐŸÐŒÐµÑÑÐžÑÑ ÐžÑ
+ Ð² ÑÐ°Ð¹Ð» .htaccess, ÐœÐ°Ñ
+ÐŸÐŽÑÑÐžÐ¹ÑÑ Ð² ÐºÐŸÑÐœÐµÐ²ÐŸÐ¹ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž Ð²Ð°ÑÐµÐ³ÐŸ ÑÐµÑÐ²ÐµÑÐ°. ÐÑÐžÂ  Ð²ÐœÐµÑÐµÐœÐžÐž ÐžÐ·ÐŒÐµÐœÐµÐœÐžÐ¹ Ð² ÑÐ°Ð¹Ð» .htaccess ÐŸÐœÐž Ð²ÑÑÑÐ¿ÑÑ Ð² ÑÐžÐ»Ñ ÐœÐµÐŒÐµÐŽÐ»ÐµÐœÐœÐŸ, ÑÐŸÐ³ÐŽÐ°Â  ÐºÐ°Ðº ÐŽÐ»Ñ ÐœÐ°ÑÐ°Ð»Ð° ÑÐ°Ð±ÐŸÑÑ Ñ ÐžÐ·ÐŒÐµÐœÐµÐœÐœÑÐŒ ÑÐ°Ð¹Ð»ÐŸÐŒ httpd.conf ÐœÑÐ¶ÐœÐŸ Ð¿ÐµÑÐµÐ·Ð°Ð¿ÑÑÑÐžÑÑ Apache. ÐÐŸ- Ð²ÑÐŸÑÑÑ
+, ÑÐ°ÑÑÐŸ Ð² ÑÐžÑÑÐµÐŒÐµ Unix Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ Ð±ÑÑÑ "ÐºÐŸÑÐœÐµÐ²ÑÐŒ" Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐŒ ÐŽÐ»Ñ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ httpd.conf, Ð² ÑÐŸ Ð²ÑÐµÐŒÑ ÐºÐ°Ðº Ð»ÑÐ±ÑÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ðž ÐŒÐŸÐ³ÑÑ ÐžÐ·ÐŒÐµÐœÐžÑÑ .htaccess.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="appendix_associated_software">
+<Title>
+<Text id="280">ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ ÐÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ</Text>
+</Title>
+<Content>
+<Text id="281">Here is how to obtain the software packages mentioned above.</Text>
+<Section id="apache_webserver">
+<Title>
+<Text id="282">Ð¡ÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ Apache</Text>
+</Title>
+<Content>
+<Text id="283">ÐÐ»Ñ ÑÐ°Ð±ÐŸÑÑ Ñ Ð»ÑÐ±ÐŸÐ¹ Ð²ÐµÑÑÐžÐµÐ¹ Greenstone, Ð·Ð° ÐžÑÐºÐ»ÑÑÐµÐœÐžÐµÐŒ ÐÐŸÐºÐ°Ð»ÑÐœÐŸÐ¹ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž, Ð²Ð°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒ ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ. ÐÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ ÑÐžÑÑÐŸÐ²ÑÑ
+ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐº, Ð² ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž ÐŸÐ±ÑÐµÐŒÐœÑÐµ, ÑÐ¶Ðµ ÑÐŸÐŽÐµÑÐ¶Ð°Ñ Ð² ÑÐµÐ±Ðµ Ð²ÑÑÑÐŸÐµÐœÐœÑÐµ ÑÐµÑÐ²ÐµÑÑ. Ð¡ ÑÐ°Ð¹ÑÐ° Www.apache.orgÂ Â  ÐŒÐŸÐ¶ÐœÐŸ Ð±ÑÑÑÑÐŸ Ðž Ð±ÐµÑÐ¿Ð»Ð°ÑÐœÐŸ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ ÑÐµÑÐµÐ²ÐŸÐ¹ ÑÐµÑÐ²ÐµÑ Apache.</Text>
+</Content>
+</Section>
+<Section id="perl">
+<Title>
+<Text id="284">Perl</Text>
+</Title>
+<Content>
+<Text id="285">ÐÐ»ÑÂ Â Â  Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑÂ Â Â  ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹Â Â Â  GreenstoneÂ Â Â  ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÂ Â  ÑÐ·ÑÐº Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ Perl.Â Â  ÐÐµÑÑÐžÑ Greenstone, Ð¿ÑÐµÐŽÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÐ°Ñ ÐŽÐ»Ñ Windows, ÑÐ¶Ðµ Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð² ÑÐµÐ±Ñ Perl. ÐÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ ÑÐžÑÑÐµÐŒ Unix ÑÐ°ÐºÐ¶Ðµ ÐžÐŒÐµÑÑ Perl, ÐœÐŸ ÐµÑÐ»Ðž ÐŸÐœ ÐœÐµ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ, ÑÐŸ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð±ÐµÑÐ¿Ð»Ð°ÑÐœÐŸ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ ÐžÑÑ
+ÐŸÐŽÐœÑÐ¹ Ðž Ð±ÐžÐœÐ°ÑÐœÑÐ¹ ÐºÐŸÐŽ ÑÑÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐŽÐ»Ñ ÑÐ°Ð·ÐœÑÑ
+ Ð²ÐµÑÑÐžÐ¹ Unix Ñ ÑÐ°Ð¹ÑÐ° www.perl.com. ÐÐ°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐ° Ð²ÐµÑÑÐžÑ Perl 5.0 ÐžÐ»Ðž Ð²ÑÑÐµ.</Text>
+</Content>
+</Section>
+<Section id="gcc">
+<Title>
+<Text id="286">GCC</Text>
+</Title>
+<Content>
+<Text id="287">ÐÐµÑÑÐžÑ Greenstone ÐŽÐ»Ñ Unix ÐºÐŸÐŒÐ¿ÐžÐ»ÐžÑÑÐµÑÑÑ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ Gnu C++ compiler (GCC). Greenstone ÑÐ°ÑÑÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÑ ÑÐ°Ð±Ð»ÐŸÐœÐœÑÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÑ C++ (ÐŒÑ ÐŸÐ±ÐœÐ°ÑÑÐ¶ÐžÐ»Ðž, ÑÑÐŸ ÐŸÐœÐ° ÐœÐµ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ ÑÐŸ ÑÑÐ°ÑÑÐŒÐž Ð²ÐµÑÑÐžÑÐŒÐž GCC; Ð¿ÐŸÐ¶Ð°Ð»ÑÐ¹ÑÑÐ°, ÑÐŸÐŸÐ±ÑÐžÑÐµ ÐœÐ°ÐŒ, ÐµÑÐ»Ðž Ñ Ð²Ð°Ñ Ñ ÑÑÐžÐŒ Ð²ÐŸÐ·ÐœÐžÐºÐœÑÑ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÑ). ÐÐ°ÐŒÐµÑÑÑÐµ, ÑÑÐŸ ÑÑÐ° Ð²ÐµÑÑÐžÑ Greenstone ÐœÐµ ÐºÐŸÐŒÐ¿ÐžÐ»ÐžÑÑÐµÑÑÑ Ð² GCC 3.0.</Text>
+</Content>
+</Section>
+<Section id="gdbm">
+<Title>
+<Text id="288">GDBM</Text>
+</Title>
+<Content>
+<Text id="289">ÐÑÐµ Ð²ÐµÑÑÐžÐž Greenstone ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑ Gnu Database Manager, GDBM. ÐÐœÐ° ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÑÐµÑÑÑ Ð²ÐŒÐµÑÑÐµ ÑÐŸ Ð²ÑÐµÐŒÐž Ð²ÐµÑÑÐžÑÐŒÐž Greenstone Ð¿ÐŸÐŽ Windows Ðž ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑÑÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž Ð²ÐŸ Ð²ÑÐµÐŒÑ Ð¿ÑÐŸÑÐµÑÑÐ° ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž. ÐÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ Ð²ÐµÑÑÐžÐ¹ Linux ÑÐ¶Ðµ ÐžÐŒÐµÑÑ GDBM, Ð¿ÐŸÑÑÐŸÐŒÑ ÐŸÐœ ÐœÐµ Ð²ÐºÐ»ÑÑÐµÐœ Ð² ÐŽÐžÑÐº ÐŽÐ»Ñ Greenstone Ð¿ÐŸÐŽ Linux. ÐÐŸ ÐµÑÐ»Ðž Ð²Ð°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒ GDBM, ÑÐŸ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÐµÐ³ÐŸ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ Ñ ÑÐ°Ð¹ÑÐ° Www.gnu.org.</Text>
+</Content>
+</Section>
+<Section id="java_runtime_environment">
+<Title>
+<Text id="290">Java Runtime Environment</Text>
+</Title>
+<Content>
+<Text id="291">Ð§ÑÐŸÐ±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Greenstone, ÐÐ°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐ° Ð¿ÐŸÐŽÑ
+ÐŸÐŽÑÑÐ°Ñ Ð²ÐµÑÑÐžÑ JRE. ÐÑÐ»Ðž ÐÑ ÐµÑÐµ ÐœÐµ ÑÐ°ÑÐ¿ÐŸÐ»Ð°Ð³Ð°ÐµÑÐµ ÐµÑ, Ð¿ÐŸÐŽÑ
+ÐŸÐŽÑÑÐ°Ñ Ð²ÐµÑÑÐžÑ Ð²ÐºÐ»ÑÑÐµÐœÐ° Ð² CD-ROM. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ Ð¿ÐŸÑÐ»ÐµÐŽÐœÑÑ Ð²ÐµÑÑÐžÑ Ñ ÑÐ°Ð¹ÑÐ°http://java.sun.com/j2se/downloads.html. ÐÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐ° Ð²ÐµÑÑÐžÑ 1.4.0 ÐžÐ»Ðž Ð²ÑÑÐµ.</Text>
+</Content>
+</Section>
+<Section id="java_compiler">
+<Title>
+<Text id="292">ÐÐŸÐŒÐ¿ÐžÐ»ÑÑÐŸÑ Java</Text>
+</Title>
+<Content>
+<Text id="293">ÐÐ»Ñ ÐºÐŸÐŒÐ¿ÐžÐ»ÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐžÑÑ
+ÐŸÐŽÐœÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° Greenstone ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ ÑÐœÐ°ÑÐ°Ð»Ð° ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ Java Development Kit. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ J2SE c cÐ°Ð¹ÑÐ°http://java.sun.com/j2se/downloads.html. Ð¢ÑÐµÐ±ÑÐµÑÑÑ Ð²ÐµÑÑÐžÑ 1.4.0 ÐžÐ»Ðž Ð²ÑÑÐµ.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+</Manual>
Index: /tags/start/gsdl-documentation/manuals/xml-source/ru/Paper_ru.xml
===================================================================
--- /tags/start/gsdl-documentation/manuals/xml-source/ru/Paper_ru.xml	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/xml-source/ru/Paper_ru.xml	(revision 13666)
@@ -0,0 +1,1135 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Manual>
+<Heading>
+<Text id="1">ÐŠÐÐ€Ð ÐÐÐÐ¯ ÐÐÐÐÐÐÐ¢ÐÐÐ GREENSTONE</Text>
+</Heading>
+<Title>
+<Text id="2">ÐÐ¢ ÐÐ£ÐÐÐÐ Ð ÐÐÐÐÐÐÐŠÐÐ</Text>
+</Title>
+<Author>
+<Text id="3">Dr Michel Loots, Dan Camarzan and Ian H. Witten</Text>
+</Author>
+<Affiliation>
+<Text id="4">Human Info NGO, BelgiumÂ <br/>Simple Words, RomaniaÂ <br/>Â University of Waikato, New Zealand</Text>
+</Affiliation>
+<Text id="5">ÐÑÐ³Ð°ÐœÐ°Ð¹Ð·ÐµÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð¿ÑÐŸÑÐµ ÐÑÐ³Ð°ÐœÐ°Ð¹Ð·ÐµÑ, ÑÐ²Ð»ÑÐµÑÑÑ ÑÐ²ÐŸÐ±ÐŸÐŽÐœÐŸ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒ Ð¿Ð°ÐºÐµÑÐŸÐŒ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒ, Ð¿ÑÐµÐŽÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÐŒ ÐŽÐ»Ñ Ð¿ÐŸÐŒÐŸÑÐž Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ Ðž ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐŒÐ°ÑÐµÑÐžÐ°Ð», ÑÐ²ÑÐ·Ð°ÐœÐœÑÐ¹ Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹. ÐÐœ ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÑÐ»ÑÑ Ñ Ð±ÐŸÐ»ÐµÐµ ÑÐ°ÐœÐœÐžÐŒÐž Ð²ÐµÑÑÐžÑÐŒÐž Greenstone. ÐÐ³ÐŸ ÑÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž Ð±ÑÐ»Ðž Ð·Ð°ÐŒÐµÐœÐµÐœÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐŒ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐŸÐŒ, ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÐŒ Ð²Â <i>Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ðµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone</i>. Ð­ÑÐŸÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ ÐŸÐ±ÑÐ°ÑÐœÑÑ ÑÐŸÐ²ÐŒÐµÑÑÐžÐŒÐŸÑÑÑ, ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ, ÐºÐ°Ðº ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐÑÐ³Ð°ÐœÐ°Ð¹Ð·ÐµÑ.</Text>
+<Comment>
+<Text id="6">ÐÑ ÐœÐ°ÐŽÐµÐµÐŒÑÑ, ÑÑÐŸ ÑÑÐŸ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ Ñ
+ÐŸÑÐŸÑÐŸ. ÐÐŸÐ¶Ð°Ð»ÑÐ¹ÑÑÐ°, ÑÐŸÐŸÐ±ÑÐžÑÐµ ÐŸ Ð»ÑÐ±ÑÑ
+ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÐ°Ñ
+ Ð¿ÐŸ Ð°ÐŽÑÐµÑÑ:Â <i>greenstone@cs.waikato.ac.nz</i></Text>
+</Comment>
+<Version>
+<Text id="7">Greenstone gsdl-2.50</Text>
+</Version>
+<Date>
+<Text id="8">ÐÐ°ÑÑ 2004</Text>
+</Date>
+<Section id="about_this_manual">
+<Title>
+<Text id="9">ÐÐ± ÑÑÐŸÐ¹ ÐžÐœÑÑÑÑÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="10">Ð­ÑÐ° ÐžÐœÑÑÑÑÐºÑÐžÑ ÐŽÐµÑÐ°Ð»ÑÐœÐŸ ÐŸÐ±ÑÑÑÐœÑÐµÑ, ÐºÐ°Ðº ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ CD-ROM ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐžÐ· Ð±ÑÐŒÐ°Ð¶ÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². ÐÐŽÐµÑÑ ÐŽÐµÑÐ°Ð»ÑÐœÐŸ ÐŸÐ¿ÐžÑÑÐ²Ð°ÑÑÑÑ Ð¿ÑÐŸÑÐµÐŽÑÑÑ Ðž ÑÐºÐŸÐœÐŸÐŒÐžÑÐµÑÐºÐžÐµ ÑÑÐŸÑÐŸÐœÑ Ð¿ÑÐŸÑÐµÑÑÐ° ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ Ðž ÐŸÐ¿ÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°Ð²Ð°ÐœÐžÑ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ² (ÐÐ Ð¡), ÑÐ°Ðº ÑÑÐŸ Ð²Ñ Ð¿ÐµÑÐµÐ²ÐµÐŽÐµÑÐµ ÑÐµÐºÑÑ Ð² Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÑÐ¹ ÑÐŸÑÐŒÐ°Ñ, Ð¿ÑÐžÐŒÐµÐœÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ Greenstone. Ð­ÑÐŸ ÑÐ°ÐºÐ¶Ðµ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ, ÐºÐ°Ðº ÑÐŸÐ·ÐŽÐ°ÑÑ Ðž ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐŒÐ°ÑÐµÑÐžÐ°Ð», ÑÐ²ÑÐ·Ð°ÐœÐœÑÐ¹ Ñ ÑÐŸÐ±ÑÐ°ÐœÐžÐµÐŒ.</Text>
+<Text id="11">Ð ÐœÐ°ÑÐµÐŒ ÐŸÐ±ÑÑÑÐœÐµÐœÐžÐž ÐŒÑ ÑÑÐ°ÑÐ°Ð»ÐžÑÑ Ð±ÑÑÑ ÑÑÐœÑÐŒÐž ÐœÐ°ÑÐºÐŸÐ»ÑÐºÐŸ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ. Ð¡ÑÑÐ»ÐºÐ° ÐœÐ° Ð»ÑÐ±ÑÐµ ÑÐŸÑÐ³ÐŸÐ²ÑÐµ ÐŒÐ°ÑÐºÐž ÐžÐ»Ðž Ð¿ÑÐŸÐŽÑÐºÑÑ ÐºÐŸÐŒÐ¿Ð°ÐœÐžÐž â ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ð»ÐžÑÑ ÐŽÐ»Ñ ÐžÐ»Ð»ÑÑÑÑÐ°ÑÐžÐ²ÐœÑÑ
+ ÑÐµÐ»ÐµÐ¹, Ðž ÐœÐµ Ð¿ÐŸÐŽÑÐ°Ð·ÑÐŒÐµÐ²Ð°ÑÑ, ÑÑÐŸ Ð² ÑÑÐ°Ð²ÐœÐµÐœÐžÐž Ñ Ð»ÑÐ±ÑÐŒ ÐŽÑÑÐ³ÐžÐŒ , ÐŒÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÐŒ ÐžÐ»Ðž ÐŸÐŽÐŸÐ±ÑÑÐµÐŒ ÑÑÐŸ ÐžÐ·ÐŽÐµÐ»ÐžÐµ.</Text>
+</Content>
+</Section>
+<Section id="companion_documents">
+<Title>
+<Text id="12">Ð¡ÐŸÐ¿ÑÑÑÑÐ²ÑÑÑÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ</Text>
+</Title>
+<Content>
+<Text id="13">ÐÐŸÐ»ÐœÑÐ¹ ÐºÐŸÐŒÐ¿Ð»ÐµÐºÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÑÐžÐž Ðº Greenstone ÑÐŸÑÑÐŸÐžÑ ÐžÐ· Ð¿ÑÑÐž ÑÐŸÐŒÐŸÐ²:</Text>
+<BulletList>
+<Bullet>
+<Text id="14">Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ Ð¿ÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐµ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="15">ÐÐœÑÑÑÑÐºÑÐžÑ ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="16">Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐº Ð° ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="17">ÐŠÐžÑÑÐŸÐ²Ð°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Greenstone: ÐŸÑ ÐÑÐŒÐ°Ð³Ðž ÐŽÐŸ ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž (ÑÑÐŸÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ)</Text>
+</Bullet>
+<Bullet>
+<Text id="18">ÐŠÐžÑÑÐŸÐ²Ð°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Greenstone: ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÐÑÐ³Ð°ÐœÐ°Ð¹Ð·ÐµÑÐ°</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Section>
+<Section id="acknowledgements">
+<Title>
+<Text id="19">ÐÐ»Ð°Ð³ÐŸÐŽÐ°ÑÐœÐŸÑÑÑ</Text>
+</Title>
+<Content>
+<Text id="20">ÐÐ¿ÐµÑÐ°ÑÐžÐž ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ Ðž ÐŽÑÑÐ³ÐžÐµ ÐœÐŸÑ-Ñ
+Ð°Ñ ÑÐ²ÑÐ·Ð°ÐœÐœÑÐµ Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµÐŒ ÑÐŸÐ²ÐŒÐµÑÑÐœÑÑ
+ ÐœÐµ ÐºÐŸÐŒÐŒÐµÑÑÐµÑÐºÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ð±ÑÐ»Ðž ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÐ°ÐœÑ ÐÐ°Ð¹ÐºÐ»ÐŸÐŒ ÐÐŸÑÑÐŸÐŒ, ÐÐ ÐÐÐ Ð¥ÑÑÐŒÐ°Ðœ ÐÐœÑÐŸ Ðž Ð¥ÑÑÐŒÐ°ÐœÐ¡Ð, ÐÑÐœÐŸÐŒ ÐÐ°ÐŒÐ°ÑÐ·Ð°ÐœÐŸÐŒ ÐžÐ· Ð¡ÐžÐŒÐ» ÐÐŸÐ»ÐŽ Ðž ÐµÐ³ÐŸ Ð³ÑÑÐ¿Ð¿ÐŸÐ¹ Ð² ÑÐŸÑÑÑÐŽÐœÐžÑÐµÑÑÐ²Ðµ Ñ ÐÑÐ°ÑÐŸÐ², Ð ÑÐŒÑÐœÐžÑ.</Text>
+<Text id="21">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ Greenstone - Ð¿ÑÐŸÐŽÑÐºÑ ÑÐŸÐ²ÐŒÐµÑÑÐœÐŸÐ³ÐŸ ÑÑÑÐŽÐ° ÐŒÐœÐŸÐ¶ÐµÑÑÐ²Ð° Ð»ÑÐŽÐµÐ¹. Rodger McNab Ðž Stefan Boddie Ð¿ÑÐžÐœÑÐžÐ¿ÐžÐ°Ð»ÑÐœÑÐµ ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐž ÑÐžÑÑÐµÐŒÑ. ÐÐµÐŸÑÐµÐœÐžÐŒÑÐ¹ Ð²ÐºÐ»Ð°ÐŽ Ð²ÐœÐµÑÐ»Ðž David Bainbridge, George Buchanan, Hong Chen, Michael Dewsnip, Katherine Don, Elke Duncker, Carl Gutwin, Geoff Holmes, Dana McKay, John McPherson, Craig Nevill-Manning, Dynal Patel, Gordon Paynter, Bernhard Pfahringer, Todd Reed, Bill Rogers, John Thompson, Ðž Stuart Yeates. ÐÑÑÐ°Ð»ÑÐœÑÐµ ÑÐ»ÐµÐœÑ ÐÑÐŸÐµÐºÑÐ° ÐÐŸÐ²ÐŸÐ·ÐµÐ»Ð°ÐœÐŽÑÐºÐŸÐ¹ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐžÂ  ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÐ°Ð»Ðž Ð²ÐŽÐŸÑ
+ÐœÐŸÐ²ÐµÐœÐœÑÐ¹ ÐŽÐžÐ·Ð°Ð¹Ðœ Ð²ÑÐµÐ¹ ÑÐžÑÑÐµÐŒÑ: Mark Apperley, Sally Jo Cunningham, Matt Jones, Steve Jones, Te Taka Keegan, Michel Loots, Malika Mahoui, Gary Marsden, Dave Nichols Ðž Lloyd Smith. ÐÑ ÑÐ°ÐºÐ¶Ðµ Ð²ÑÑÐ°Ð¶Ð°ÐµÐŒ ÑÐ²ÐŸÑ Ð¿ÑÐžÐ·ÐœÐ°ÑÐµÐ»ÑÐœÐŸÑÑÑ Ð²ÑÐµÐŒ ÑÐµÐŒ, ÐºÑÐŸ ÑÑÑÐŽÐžÐ»ÑÑ ÐœÐ°ÐŽ ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµÐŒ Ð¿Ð°ÐºÐµÑÐŸÐ², Ð¿ÐŸÐ¿Ð°ÐŽÐ°ÑÑÐžÑ
+ Ð¿ÐŸÐŽ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ Ð»ÐžÑÐµÐœÐ·ÐžÐžÂ  GNU, Ðž Ð²ÐºÐ»ÑÑÐµÐœÐœÑÑ
+ Ð² ÐŽÐžÑÑÑÐžÐ±ÑÑÐžÐ²: MG, GDBM, PDFTOHTML, PERL, WGET, WVWARE Ðž XLHTML.</Text>
+</Content>
+</Section>
+<Chapter id="introduction">
+<Title>
+<Text id="22">ÐÐ²ÐµÐŽÐµÐœÐžÐµ</Text>
+</Title>
+<Content>
+<Text id="23">ÐÐŽÐœÐ° ÐžÐ· ÑÐµÐ»ÐµÐ¹ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ Greenstone ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸÐ±Ñ Ð¿ÑÐµÐŽÑÑÐ°Ð²ÐžÑÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒ ÐžÐœÑÑÐžÑÑÑÐ°ÐŒ, ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑÐŒ, Ð°Ð³ÐµÐœÑÑÑÐ²Ð°ÐŒ ÐÐÐ, ÐœÐµÐ¿ÑÐ°Ð²ÐžÑÐµÐ»ÑÑÑÐ²ÐµÐœÐœÑÐŒ Ðž ÐœÐµÐºÐŸÐŒÐŒÐµÑÑÐµÑÐºÐžÐŒ ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑÐŒ, Ð° ÑÐ°ÐºÐ¶Ðµ Ð¿ÑÐ°Ð²ÐžÑÐµÐ»ÑÑÑÐ²Ð°ÐŒ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐŸÐœÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ¶ÐœÐŸ ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐžÑÑ ÐºÐ°Ðº Ð² ÐÐœÑÐµÑÐœÐµÑÐµ, ÑÐ°Ðº Ðž ÑÐŸÑ
+ÑÐ°ÐœÐžÑÑ ÐœÐ° CD-ROM.</Text>
+<Text id="24">ÐÐžÐ¶Ðµ ÐŸÐ¿ÐžÑÐ°ÐœÐ° ÐŸÐ±ÑÑÐœÐ°Ñ Ð¿ÑÐŸÑÐµÐŽÑÑÐ° Ð¿ÑÐž ÑÐŸÐ·ÐŽÐ°ÐœÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹: </Text>
+<NumberedList>
+<NumberedItem>
+<Text id="25">ÐÐŸÐŽÐ±ÐŸÑ ÐžÑÑ
+ÐŸÐŽÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="26">ÐÐŸÐ»ÑÑÐµÐœÐžÐµ ÑÐ°Ð·ÑÐµÑÐµÐœÐžÑ Ð²Ð»Ð°ÐŽÐµÐ»ÑÑÐµÐ² Ð°Ð²ÑÐŸÑÑÐºÐžÑ
+ Ð¿ÑÐ°Ð² ÐœÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÑÑÐžÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ².</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="27">Ð¡ÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ðž ÐŸÐ¿ÑÐžÑÐµÑÐºÐŸÐµ ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°Ð²Ð°ÐœÐžÐµ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ² (ÐÐ Ð¡) ÐŒÐ°ÑÐµÑÐžÐ°Ð»ÑÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐŽÐ»Ñ ÐžÑ
+ Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÐœÐžÑ Ð² ÑÐžÑÑÐŸÐ²ÐŸÐ¹ ÑÐŸÑÐŒÐ°Ñ</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="28">ÐÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÐœÐžÐµ Ð²ÑÐµÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð² ÐµÐŽÐžÐœÑÐ¹ ÑÐŸÑÐŒÐ°Ñ, ÐºÐŸÑÐŸÑÑÐ¹ ÐŒÐŸÐ¶ÐœÐŸ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ Ð² Greenstone (Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÐŸ HTML Ðž Microsoft Word, ÐœÐŸ ÐŒÐŸÐ¶ÐœÐŸ ÑÐ°ÐºÐ¶Ðµ Ðž Ð² ÐŽÑÑÐ³ÐžÐµ ÑÐŸÑÐŒÐ°ÑÑ) Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐµÐœÐžÐ¹ Ðº Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐµ "plugin" (ÑÐŒÐŸÑÑÐžÑÐµ ÐÐœÑÑÑÑÐºÑÐžÑ ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="29">ÐÐ°ÑÐºÐžÑÐŸÐ²ÐºÐ° Ð³Ð»Ð°Ð², Ð¿Ð°ÑÐ°Ð³ÑÐ°ÑÐŸÐ² Ðž ÑÐžÑÑÐœÐºÐŸÐ² Ð² ÑÐžÑÑÐŸÐ²ÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°Ñ
+.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="30">ÐÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ð² ÐŸÐ¿ÑÐžÐŒÐ°Ð»ÑÐœÐŸ ÑÑÑÑÐºÑÑÑÐžÑÐŸÐ²Ð°ÐœÐœÑÑ ÑÐžÑÑÐŸÐ²ÑÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÑ.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="31">ÐÐŸÑÑÑÐŸÐµÐœÐžÐµ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="32">ÐÐ°Ð¿ÐžÑÑ Ðž ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐœÐ° CD-ROM Ðž/ÐžÐ»Ðž ÐžÑ
+ Ð¿ÑÐ±Ð»ÐžÐºÐ°ÑÐžÑ Ð² ÐÐœÑÐµÑÐœÐµÑÐµ.</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="33">ÐÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ ÑÐžÑÑÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, Ð²ÑÐµ Ð¿ÑÐ±Ð»ÐžÐºÐ°ÑÐžÐž ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸ ÐœÑÐ¶ÐœÐŸ Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÑÑ Ð² ÑÐžÑÑÐŸÐ²ÐŸÐ¹ ÑÐŸÑÐŒÐ°Ñ. ÐÑÐ»Ðž ÐŽÐŸÑÑÑÐ¿ÐœÑ ÑÐŸÐ»ÑÐºÐŸ ÑÐ²ÐµÑÐŽÑÐµ ÐºÐŸÐ¿ÐžÐž ÐºÐœÐžÐ³, ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÑÐŸ ÐžÑ
+ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑ Ðž Ð¿ÐµÑÐµÐ²ÐµÑÑÐž Ð² ÑÐŸÑÐŒÑ, ÑÑÐžÑÑÐ²Ð°ÐµÐŒÑÑ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐŸÐŒ (Ñ ÑÐ°Ð³). ÐÐ±ÑÑÐœÐŸ ÑÑÐŸ ÐŽÐµÐ»Ð°ÐµÑÑÑ Ð¿ÑÑÐµÐŒ Ð¿ÑÐŸÐ²ÐµÐŽÐµÐœÐžÑ ÐŸÐ¿ÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°Ð²Ð°ÐœÐžÑ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ², Ð² ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÑÐ»ÑÑÐ°ÑÑ
+ - Ð¿ÑÐŸÑÑÑÐŒ Ð¿ÐµÑÐµÐ¿ÐµÑÐ°ÑÑÐ²Ð°ÐœÐžÐµÐŒ. Ð­ÑÐŸÑ Ð¿ÑÐŸÑÐµÑÑ ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°ÐµÑÑÑ Ð² 2-4 Ð³Ð»Ð°Ð²Ð°Ñ
+.</Text>
+<Text id="34">v. ÑÐ°Ð³ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð²ÑÐ±ÐžÑÐ°ÑÑ ÐŸÑÐŽÐµÐ»ÑÐœÑÐµ ÑÐ°ÑÑÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ðž ÑÐ°ÑÐ¿ÐŸÐ»Ð°Ð³Ð°ÑÑ ÐžÑ
+ Ð² ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ Ð² Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐµ, vi ÑÐ°Ð³ Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð² ÑÐµÐ±Ñ Ð¿ÑÐžÑÐ²ÐŸÐµÐœÐžÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ Ð°ÑÑÐžÐ±ÑÑÐŸÐ² ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ, ÑÐ°ÐºÐžÑ
+ ÐºÐ°Ðº ÑÐºÐ°Ð·Ð°ÑÐµÐ»Ðž ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹, ÐºÐ»ÑÑÐµÐ²ÑÐµ ÑÐ»ÐŸÐ²Ð° Ðž Ð±ÐžÐ±Ð»ÐžÐŸÐ³ÑÐ°ÑÐžÑÐµÑÐºÐžÐµ ÐŽÐ°ÐœÐœÑÐµ ÐŽÐ»Ñ ÐŸÑÑÑÐµÑÑÐ²Ð»ÐµÐœÐžÑ Ð·Ð°Ð¿ÑÐŸÑÐ° Ðž Ð¿ÐŸÐžÑÐºÐ° Ð¿ÐŸ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐµ. Ð­ÑÐž ÑÐ°Ð³Ðž ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°ÑÑÑÑ Ð² Ð¿ÑÑÐŸÐ¹ Ð³Ð»Ð°Ð²Ðµ.</Text>
+<Text id="35">Ð­ÑÐ° ÐžÐœÑÑÑÑÐºÑÐžÑ ÑÐ°ÐºÐ¶Ðµ ÐŸÐ±ÑÑÐ¶ÐŽÐ°ÐµÑ ÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐŸ Ð²ÐŸÐ¿ÑÐŸÑÐŸÐ², ÐºÐ°ÑÐ°ÑÑÐžÑ
+ÑÑ Ð¿ÑÐŸÑÐµÑÑÐ° ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÑ Ð¿ÑÐž ÑÐŸÐ·ÐŽÐ°ÐœÐžÐž ÑÐžÑÑÐŸÐ²ÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐžÐ· ÑÐ²ÐµÑÐŽÐŸÐ¹ ÐºÐŸÐ¿ÐžÐž. ÐÐµÑÐµÐŽ ÑÐµÐŒ, ÐºÐ°Ðº Ð¿ÑÐŸÐŽÐŸÐ»Ð¶ÐžÑÑ ÑÑÐµÐœÐžÐµ, ÐŒÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÐŒ Ð²Ð°ÐŒ ÐŸÑÐ²ÐµÑÐžÑÑ ÐœÐ° ÑÐ»ÐµÐŽÑÑÑÐžÐµ Ð²ÐŸÐ¿ÑÐŸÑÑ:</Text>
+<BulletList>
+<Bullet>
+<Text id="36">ÐÐ°ÐºÐŸÐ²Ð° ÑÐµÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ Ð²Ð°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž?</Text>
+</Bullet>
+<Bullet>
+<Text id="37">ÐÐ° ÐºÐ°ÐºÑÑ Ð³ÑÑÐ¿Ð¿Ñ Ð»ÑÐŽÐµÐ¹ ÐŸÐœÐ° ÐŸÑÐžÐµÐœÑÐžÑÐŸÐ²Ð°ÐœÐ°?</Text>
+</Bullet>
+<Bullet>
+<Text id="38">ÐÐ°ÑÐºÐŸÐ»ÑÐºÐŸ ÐŸÐœÐ° ÐŒÐ°ÑÑÑÐ°Ð±ÐœÐ° â Ð»ÐŸÐºÐ°Ð»ÑÐœÐ°, ÑÐµÐ³ÐžÐŸÐœÐ°Ð»ÑÐœÐ° ÐžÐ»Ðž Ð³Ð»ÐŸÐ±Ð°Ð»ÑÐœÐ°?</Text>
+</Bullet>
+<Bullet>
+<Text id="39">Ð¡ÐºÐŸÐ»ÑÐºÐŸ ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²?</Text>
+</Bullet>
+<Bullet>
+<Text id="40">Ð¡ÐºÐŸÐ»ÑÐºÐŸ ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÑÑÑÐ°ÐœÐžÑ?</Text>
+</Bullet>
+<Bullet>
+<Text id="41">Ð¡ÐºÐŸÐ»ÑÐºÐŸ ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ð³ÑÐ°ÑÐžÑÐµÑÐºÐžÑ
+ ÐŸÐ±ÑÐµÐºÑÐŸÐ²?</Text>
+</Bullet>
+<Bullet>
+<Text id="42">ÐÐŒÐµÐµÑ Ð»Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÐ°ÑÑÐž, Ð¿ÑÐµÐŽÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÐµ ÐŽÐ»Ñ ÐŸÐ³ÑÐ°ÐœÐžÑÐµÐœÐœÐŸÐ³ÐŸ ÐºÑÑÐ³Ð° Ð»ÑÐŽÐµÐ¹, Ð° ÐŽÑÑÐ³ÐžÐµ - ÐŽÐ»Ñ Ð²ÑÐµÑ
+ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹?</Text>
+</Bullet>
+<Bullet>
+<Text id="43">ÐÐŸÑÑÑÐ¿ÐœÑ Ð»Ðž ÐžÑÑ
+ÐŸÐŽÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð² ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐŒ ÑÐŸÑÐŒÐ°ÑÐµ?</Text>
+</Bullet>
+<Bullet>
+<Text id="44">ÐÑÐ»Ðž ÐŽÐ°, ÑÐŸ Ð² ÐºÐ°ÐºÐŸÐŒ? (ÐœÑÐ¶ÐœÐŸ ÐŸÑÐŒÐµÑÐžÑÑ, ÑÑÐŸ PDF-ÑÐ°Ð¹Ð»Ñ ÐœÐµ ÑÐ²Ð»ÑÑÑÑÑ ÑÐºÐ²ÐžÐ²Ð°Ð»ÐµÐœÑÐ°ÐŒÐž Ð¿ÐŸÐ»ÐœÐŸÑÐµÐºÑÑÐŸÐ²ÐŸÐ³ÐŸ ÑÐžÑÑÐŸÐ²ÐŸÐ³ÐŸ ÑÐŸÑÐŒÐ°ÑÐ°, ÑÐ°Ðº ÐºÐ°Ðº ÑÐ²Ð»ÑÑÑÑÑ Ð»ÐžÑÑ ÐºÐŸÐ¿ÐžÑÐŒÐž ÑÑÑÐ°ÐœÐžÑ)</Text>
+</Bullet>
+<Bullet>
+<Text id="45">ÐÐ°ÐºÐŸÐ² ÑÑÐ°ÑÑÑ Ð°Ð²ÑÐŸÑÑÐºÐžÑ
+ Ð¿ÑÐ°Ð² ÐžÑÑ
+ÐŸÐŽÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²?</Text>
+</Bullet>
+<Bullet>
+<Text id="46">ÐÑÐŸ Ð²Ð»Ð°ÐŽÐµÐµÑ Ð°Ð²ÑÐŸÑÑÐºÐžÐŒÐž Ð¿ÑÐ°Ð²Ð°ÐŒÐž?</Text>
+</Bullet>
+<Bullet>
+<Text id="47">Ð¡ÑÑÐµÑÑÐ²ÑÑÑ Ð»Ðž ÐŽÑÑÐ³ÐžÐµ ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐž, ÑÐ°ÑÐ¿ÐŸÐ»Ð°Ð³Ð°ÑÑÐžÐµ Ð¿ÑÐŸÐŽÑÐºÑÐŸÐŒ, ÐŸÑÐžÐµÐœÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐŒ ÐœÐ° ÑÑ Ð¶Ðµ ÑÐ°ÐŒÑÑ Ð³ÑÑÐ¿Ð¿Ñ Ð»ÑÐŽÐµÐ¹?</Text>
+</Bullet>
+<Bullet>
+<Text id="48">ÐÐµÐ»Ð°ÐµÑÐµ Ð»Ðž Ð²Ñ ÑÐ°Ð±ÐŸÑÐ°ÑÑ Ð²ÐŒÐµÑÑÐµ Ñ ÐŽÑÑÐ³ÐžÐŒÐž Ð³ÑÑÐ¿Ð¿Ð°ÐŒÐž?</Text>
+</Bullet>
+<Bullet>
+<Text id="49">ÐÐ°ÐºÐŸÐ² Ð±ÑÐŽÐ¶ÐµÑ, Ð²ÑÐŽÐµÐ»ÐµÐœÐœÑÐ¹ ÐœÐ° ÑÑÐŸÑ Ð¿ÑÐŸÐµÐºÑ?</Text>
+</Bullet>
+<Bullet>
+<Text id="50">ÐÐ°ÐºÐžÐµ ÐŽÐŸÑÑÑÐ¿ÐœÑ ÑÐµÐ»ÐŸÐ²ÐµÑÐµÑÐºÐžÐµ ÑÐµÑÑÑÑÑ(Ð² ÑÐµÐ»ÐŸÐ²ÐµÐºÐŸ-ÐŒÐµÑÑÑÐ°Ñ
+) ÐŽÐ»Ñ ÐºÐŸÐŸÑÐŽÐžÐœÐ°ÑÐžÐž, ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÑ, ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ Ðž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ?</Text>
+</Bullet>
+<Bullet>
+<Text id="51">Ð¡ÐºÐŸÐ»ÑÐºÐŸ ÐŽÐŸÑÑÑÐ¿ÐœÐŸ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐŸÐ²?</Text>
+</Bullet>
+<Bullet>
+<Text id="52">Ð¡ÐºÐŸÐ»ÑÐºÐŸ CD-ROM Ð²Ñ Ñ
+ÐŸÑÐžÑÐµ ÑÐŸÐ·ÐŽÐ°ÑÑ?</Text>
+</Bullet>
+<Bullet>
+<Text id="53">ÐÑÐŽÑÑ Ð»Ðž ÐŸÐœÐž Ð±ÐµÑÐ¿Ð»Ð°ÑÐœÑÐŒÐž ÐžÐ»Ðž Ð¿Ð»Ð°ÑÐœÑÐŒÐž?</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Chapter>
+<Chapter id="scanners_and_scanning">
+<Title>
+<Text id="54">Ð¡ÐºÐ°ÐœÐµÑÑ Ðž ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ</Text>
+</Title>
+<Content>
+<Text id="55">ÐÐµÑÐ²ÑÐ¹ ÑÐ°Ð³ ÐŽÐ»Ñ Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÐœÐžÑ Ð±ÑÐŒÐ°Ð¶ÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð² ÑÐžÑÑÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐž Ð²ÑÐµÑ
+ ÑÑÑÐ°ÐœÐžÑ ÐžÑÑ
+ÐŸÐŽÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². Ð¡Ð»ÐµÐŽÑÑÑÐžÐ¹ ÑÐ°Ð³ - ÑÑÐŸ Ð¿ÑÐŸÐ²ÐµÐŽÐµÐœÐžÑ Ð¿ÑÐŸÑÐµÑÑÐ° ÐŸÐ¿ÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°Ð²Ð°ÐœÐžÑ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ² (ÐÐ Ð¡), ÐŽÐ»Ñ ÑÐµÐ³ÐŸ ÐŸÑÐµÐœÑ Ð²Ð°Ð¶ÐœÑ Ð²ÑÑÐŸÐºÐŸÐºÐ°ÑÐµÑÑÐ²ÐµÐœÐœÑÐµ Ðž ÑÐµÑÐºÐžÐµ ÐžÑÑ
+ÐŸÐŽÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ. ÐÑÐŸÑÐµÑÑ Ð¿ÐµÑÐµÐ²ÐŸÐŽÐ° Ð² ÑÐžÑÑÐŸÐ²ÐŸÐ¹ ÑÐŸÑÐŒÐ°Ñ ÐœÑÐ¶ÐŽÐ°ÐµÑÑÑ Ð² ÑÐºÐ°ÐœÐµÑÐµ, ÑÐ¿ÐŸÑÐŸÐ±ÐœÐŸÐŒ ÑÐ°Ð±ÐŸÑÐ°ÑÑ Ð¿ÑÐž ÑÐ°Ð·ÑÐµÑÐµÐœÐžÐž 300 dpi (ÑÐŸÑÐµÐº ÐœÐ° ÐŽÑÐ¹ÐŒ). ÐÐŸÐ»ÑÑÑÑ ÑÐ°ÑÑÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐŒÐŸÐ¶ÐœÐŸ Ð¿ÑÐŸÐžÐ·Ð²ÐµÑÑÐž Ð² ÑÐµÑÐœÐŸ-Ð±ÐµÐ»ÐŸÐŒ ÑÐµÐ¶ÐžÐŒÐµ, ÐœÐŸ Ð¿ÑÐž Ð²ÐºÐ»ÑÑÐµÐœÐžÐž ÑÐ²ÐµÑÐœÑÑ
+ ÐžÐ»Ð»ÑÑÑÑÐ°ÑÐžÐ¹ ÐžÑ
+ ÑÐ»ÐµÐŽÑÐµÑ ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑ ÑÐ²ÐµÑÐœÑÐŒ ÑÐºÐ°ÐœÐµÑÐŸÐŒ. Ð Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²Ðµ ÑÐ»ÑÑÐ°ÐµÐ² ÐŸÐ±Ð»ÐŸÐ¶ÐºÐž ÐºÐœÐžÐ³ ÑÐ²Ð»ÑÑÑÑÑ ÐºÑÐ°ÑÐŸÑÐœÑÐŒÐž Ðž ÐžÑ
+ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑ Ð² ÑÐµÐ¶ÐžÐŒÐµ ÑÐ²ÐµÑÐœÐŸÐ³ÐŸ ÑÐžÑÑÐœÐºÐ°.</Text>
+<Section id="scanners">
+<Title>
+<Text id="56">Ð¡ÐºÐ°ÐœÐµÑÑ</Text>
+</Title>
+<Content>
+<Text id="57">Ð¡ÐºÐ°ÐœÐµÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑ Ð¿ÐŸ ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒ ÑÐµÐœÐ°ÐŒ Ðž ÐžÐŒÐµÑÑÑÑ Ð²ÑÐµÐ²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÑ
+ ÑÐ°Ð·ÐŒÐµÑÐŸÐ² Ðž ÑÐŸÑÐŒ. ÐÑ
+ ÑÐµÐœÐ° ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐŸÑ $ 100 Ð·Ð° ÐŸÐ±ÑÑÐœÑÐ¹ ÐœÐ°ÑÑÐŸÐ»ÑÐœÑÐ¹ ÑÐºÐ°ÐœÐµÑ ÐŽÐŸ $50000 Ð·Ð° ÐŸÐ³ÑÐŸÐŒÐœÑÐµ ÐžÐœÐŽÑÑÑÑÐžÐ°Ð»ÑÐœÑÐµ ÑÐºÐ°ÐœÐµÑÑ ÑÐ°ÐºÐžÑ
+ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÐµÐ»ÐµÐ¹ ÐºÐ°Ðº Bell &amp; Howell<FootnoteRef id="1"/>. Ð¡ÑÑÐµÑÑÐ²ÑÐµÑ ÐŒÐœÐŸÐ³ÐŸ ÑÐ°Ð·ÐœÑÑ
+ ÑÐŸÑÐ³ÐŸÐ²ÑÑ
+ ÐÐœÑÐµÑÐœÐµÑ-ÑÑÑÐ°ÐœÐžÑ, Ð¿ÑÐµÐŽÐ»Ð°Ð³Ð°ÑÑÐžÑ
+ Ð²ÑÐµÐ²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÐµ ÑÐºÐ°ÐœÐµÑÑ. ÐÐ»Ñ Ð¿ÐŸÐžÑÐºÐ° ÑÐºÐ°ÐœÐµÑÐŸÐ² Ð¿ÑÐŸÑÑÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÑÐ°ÐºÐžÐµ Ð¿ÐŸÐžÑÐºÐŸÐ²ÑÐµ ÑÐžÑÑÐµÐŒÑ, ÐºÐ°Ðº Google, Altavista, Yahoo.</Text>
+<Text id="58">ÐÐ±ÑÑÐœÑÐ¹ ÑÐŸÑÐŒÐ°Ñ, Ð² ÐºÐŸÑÐŸÑÐŸÐŒ ÑÐŸÑ
+ÑÐ°ÐœÑÐµÑÑÑ ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ, ÑÑÐŸ TIFF ÐžÐ»Ðž BMP (Bitmap image). Ð¡Ð¶Ð°ÑÐ°Ñ ÑÐŸÑÐŒÐ° TIFF IV ÑÐ²Ð»ÑÐµÑÑÑ Ð»ÑÑÑÐžÐŒ ÑÐŸÑÐŒÐ°ÑÐŸÐŒ ÐŽÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ. Ð¡ÑÐµÐŽÐœÑÑ ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐœÐ°Ñ ÑÑÑÐ°ÐœÐžÑÐ°, Ð¿ÐµÑÐµÐ²ÐµÐŽÐµÐœÐœÐ°Ñ Ð² ÑÑÐŸÑ ÑÐŸÑÐŒÐ°Ñ, Ð·Ð°ÐœÐžÐŒÐ°ÐµÑ Ð²ÑÐµÐ³ÐŸ 50 ÐºÐžÐ»ÐŸÐ±Ð°Ð¹Ñ, Ð¿ÐŸ ÑÑÐ°Ð²ÐœÐµÐœÐžÑ Ñ 2 Mb ÐžÐŽÐµÐœÑÐžÑÐœÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÑ, ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐœÐŸÐ¹ Ð² BMP.</Text>
+<Subsection id="low-cost_flat-bed_scanner)">
+<Title>
+<Text id="59">ÐÐµÐŽÐŸÑÐŸÐ³ÐžÐµ ÐœÐ°ÑÑÐŸÐ»ÑÐœÑÐµ ÑÐºÐ°ÐœÐµÑÑ (flat-based scanners)</Text>
+</Title>
+<Content>
+<Text id="60">ÐÐ°ÑÑÐŸÐ»ÑÐœÑÐµ ÑÐºÐ°ÐœÐµÑÑ ÑÐ²Ð»ÑÑÑÑÑ ÑÐ°ÐŒÑÐŒÐž ÐŽÐµÑÐµÐ²ÑÐŒÐž Ðž ÐœÐ°ÐžÐ±ÐŸÐ»ÐµÐµ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž ÑÐºÐ°ÐœÐµÑÐ°ÐŒÐž. Ð¡ÑÑÐµÑÑÐ²ÑÐµÑ ÐŒÐœÐŸÐ³ÐŸ ÑÐŸÑÐ³ÐŸÐ²ÑÑ
+ ÐŒÐ°ÑÐŸÐº, ÑÐ°ÐºÐžÑ
+ ÐºÐ°Ðº HP, Agfa, Acer Ðž Ñ.ÐŽ. ÐÑ
+ ÑÐµÐœÑ ÐºÐŸÐ»ÐµÐ±Ð»ÑÑÑÑ ÐŸÑ 100 ÐŽÐŸ 300 ÐŽÐŸÐ»Ð»Ð°ÑÐŸÐ². Ð¡ ÐžÑ
+ Ð¿ÐŸÐŒÐŸÑÑÑ ÐŒÐŸÐ¶ÐœÐŸ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑ ÐºÐ°Ðº ÑÐµÑÐœÐŸ-Ð±ÐµÐ»ÑÐµ ÑÐžÑÑÐœÐºÐž, ÑÐ°Ðº Ðž ÑÐ²ÐµÑÐœÑÐµ. ÐÐžÐ·ÐºÐžÐµ ÑÐµÐœÑ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ ÐºÐ°Ð¶ÐŽÐŸÐŒÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐžÐŒÐµÑÑ ÐŸÐŽÐžÐœ ÐžÐ· ÑÐ°ÐºÐžÑ
+ ÑÐºÐ°ÐœÐœÐµÑÐŸÐ².</Text>
+<Text id="61">ÐÑ
+ ÐœÐµÐŽÐŸÑÑÐ°ÑÐºÐž - ÑÑÐŸ ÑÑÐµÐŽÐœÐžÐ¹ ÑÑÐŸÐ²ÐµÐœÑ ÐºÐ°ÑÐµÑÑÐ²Ð°, ÐŒÐµÐŽÐ»ÐµÐœÐœÐŸÐµ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ, ÐœÐµÐœÐ°ÐŽÐµÐ¶ÐœÐŸÑÑÑ Ð¿ÑÐž Ð²ÑÑÐŸÐºÐžÑ
+ ÑÐµÐŒÐ¿ÐµÑÐ°ÑÑÑÐ°Ñ
+ Ðž ÐŸÑÐœÐŸÑÐžÑÐµÐ»ÑÐœÐŸ ÑÐ°ÑÑÑÐµ Ð¿ÐŸÐ»ÐŸÐŒÐºÐž. Ð¡ÑÑÐ°ÐœÐžÑÑ ÐŽÐŸÐ»Ð¶ÐœÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑÑÑ Ð²ÑÑÑÐœÑÑ Ðž ÐºÐ°Ð¶ÐŽÐ°Ñ ÐžÐ· ÑÑÑÐ°ÐœÐžÑ Ð¿ÐŸ ÐŸÑÐŽÐµÐ»ÑÐœÐŸÑÑÐž. ÐÐ°Ð¶ÐŽÑÑ ÑÑÑÐ°ÐœÐžÑÑ ÐœÑÐ¶ÐœÐŸ Ð¿ÐŸÐ»ÐŸÐ¶ÐžÑÑ ÑÐ°Ðº, ÑÑÐŸÐ±Ñ ÐŸÐœÐ° ÑÐ°ÑÐ¿ÐŸÐ»Ð°Ð³Ð°Ð»Ð°ÑÑ Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸ. ÐÑÐŸÐŽÑÐºÑÐžÐ²ÐœÐŸÑÑÑ ÐœÐ° ÑÐ°ÐºÐžÑ
+ ÑÐºÐ°ÐœÐµÑÐ°Ñ
+ ÐŸÑÐµÐœÑ ÐœÐžÐ·ÐºÐ°. ÐÐµÑÐŒÐŸÑÑÑ ÐœÐ° ÑÐŸ, ÑÑÐŸ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÐµÐ»Ðž ÑÑÐ²ÐµÑÐ¶ÐŽÐ°ÑÑ, ÑÑÐŸ ÐŸÐŽÐœÑ ÑÑÑÐ°ÐœÐžÑÑ ÐŒÐŸÐ¶ÐœÐŸ ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑ ÐŒÐµÐœÑÑÐµ, ÑÐµÐŒ Ð·Ð° ÐŸÐŽÐœÑ ÐŒÐžÐœÑÑÑ, ÐœÐ° Ð¿ÑÐ°ÐºÑÐžÐºÐµ ÑÑÑÐŽÐœÐŸ Ð¿ÑÐµÐŸÐŽÐŸÐ»ÐµÑÑ Ð³ÑÐ°ÐœÐžÑÑ Ð² 12 ÑÑÑÐ°ÐœÐžÑ Ð·Ð° ÑÐ°Ñ. Ð ÑÐŸÐŒÑ Ð¶Ðµ Ð¿ÑÐŸÑÐµÑÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ Ð¿ÐŸÐ»ÐœÐŸÑÑÑÑ Ð·Ð°ÐœÐžÐŒÐ°ÐµÑ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐœÑÐµ ÑÐµÑÑÑÑÑ.</Text>
+<Text id="62">Ð¡Ð»ÐµÐŽÐŸÐ²Ð°ÑÐµÐ»ÑÐœÐŸ, ÑÐ°ÐºÐžÐµ ÑÐºÐ°ÐœÐµÑÑ ÑÐŽÐŸÐ±ÐœÑ ÑÐŸÐ»ÑÐºÐŸ ÐŽÐ»Ñ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ ÐœÐµÐ±ÐŸÐ»ÑÑÐžÑ
+ ÑÐ°Ð±ÐŸÑ Ñ ÐœÐµÐ±ÐŸÐ»ÑÑÐžÐŒ ÐœÐ°Ð±ÐŸÑÐŸÐŒ ÑÑÑÐ°ÐœÐžÑ - ÐœÐµ Ð±ÐŸÐ»ÐµÐµ 200-400 Ð² ÐŒÐµÑÑÑ, ÐµÑÐ»Ðž Ð²ÑÐ¿ÐŸÐ»ÐœÑÑÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐµÐ³ÑÐ»ÑÑÐœÐŸ. Ð¢Ðµ, ÐºÑÐŸ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ ÑÐŸ ÑÐºÐ°ÐœÐµÑÐŸÐŒ Ð¿ÐŸÐ»ÐœÑÐ¹ ÐŽÐµÐœÑ, ÑÑÐŸ ÑÐŸÑÑÐ°Ð²Ð»ÑÐµÑ 1000-2000 ÑÑÑÐ°ÐœÐžÑ.</Text>
+</Content>
+</Subsection>
+<Subsection id="low-end_scanner_with_sheet_feeder">
+<Title>
+<Text id="63">Ð¡ÐºÐ°ÐœÐµÑÑ Ñ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐŸÐ¹ Ð¿ÐŸÐŽÐ°ÑÐµÐ¹ Ð±ÑÐŒÐ°Ð³Ðž</Text>
+</Title>
+<Content>
+<Text id="64">Ð¡ÐºÐ°ÐœÐµÑÑ Ñ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐŸÐ¹ Ð¿ÐŸÐŽÐ°ÑÐµÐ¹ Ð±ÑÐŒÐ°Ð³Ðž ÑÑÐŸÑÑ ÐŸÐºÐŸÐ»ÐŸ 500-1200 ÐŽÐŸÐ»Ð»Ð°ÑÐŸÐ². ÐÐŸÐ¶ÐœÐŸ Ð¿ÐŸÐŒÐµÑÐ°ÑÑ ÐŽÐŸ 10-15 ÑÑÑÐ°ÐœÐžÑ Ð² ÑÐºÐ°ÐœÐµÑ Ðž ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑ ÐžÑ
+ ÐŸÐŽÐœÐŸÐ²ÑÐµÐŒÐµÐœÐœÐŸ: ÑÐ»ÐµÐŽÐŸÐ²Ð°ÑÐµÐ»ÑÐœÐŸ, ÐŸÐ¿ÐµÑÐ°ÑÐŸÑÑ ÐœÐµ ÐœÑÐ¶ÐœÐŸ Ð¿ÐŸÑÑÐŸÑÐœÐœÐŸ Ð¿ÐŸÐŽÑ
+ÐŸÐŽÐžÑÑ Ðº Ð°Ð¿Ð¿Ð°ÑÐ°ÑÑ. Ð­ÑÐŸ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÑÐ²ÐµÐ»ÐžÑÐžÑÑ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÐµÐ»ÑÐœÐŸÑÑÑ ÐŽÐŸ 150-200 ÑÑÑÐ°ÐœÐžÑ Ð² ÐŽÐµÐœÑ. Ð­ÑÐž ÑÐºÐ°ÐœÐµÑÑ ÐœÐ°ÐžÐ±ÐŸÐ»ÐµÐµ ÑÑÐŸÐ¹ÐºÐžÐµ Ðž ÐœÐµ ÐœÑÐ¶ÐŽÐ°ÑÑÑÑ Ð² ÑÐµÐŒÐŸÐœÑÐµ Ð² ÑÐµÑÐµÐœÐžÐµ ÐŽÐŸÐ»Ð³ÐŸÐ³ÐŸ Ð²ÑÐµÐŒÐµÐœÐž (Ð¿ÐŸÑÐ»Ðµ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ 30000-50000 ÑÑÑÐ°ÐœÐžÑ).</Text>
+<Text id="65">ÐÑ
+ ÐœÐµÐŽÐŸÑÑÐ°ÑÐŸÐº ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸ ÑÐºÐ°ÐœÐžÑÑÐµÑÑÑ ÑÐŸÐ»ÑÐºÐŸ ÐŸÐŽÐœÐ° ÑÑÐŸÑÐŸÐœÐ° ÑÑÑÐ°ÐœÐžÑÑ; ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑ ÐŽÑÑÐ³ÑÑ ÑÑÐŸÑÐŸÐœÑ, ÑÑÑÐ°ÐœÐžÑÑ ÐœÑÐ¶ÐœÐŸ Ð¿ÐµÑÐµÐ²ÐµÑÐœÑÑÑ. Ð­ÑÐŸ ÑÐ°ÑÑÐŸ ÑÐŸÐ·ÐŽÐ°ÐµÑ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÑ, ÑÐ°Ðº ÐºÐ°Ðº Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐ°Ñ Ð¿ÐŸÐŽÐ°ÑÐ° Ð±ÑÐŒÐ°Ð³ Ð²ÑÐµÐ³ÐŽÐ° Ð¿ÑÐŸÐ±Ð»ÐµÐŒÐ°ÑÐžÑÐœÐ° Ðž ÑÐ°ÑÑÐŸ ÑÑÑÐ°ÐœÐžÑÑ Ð·Ð°ÑÑÑÐµÐ²Ð°ÑÑ.</Text>
+<Text id="66">Ð­ÑÐž ÑÐºÐ°ÐœÐµÑÑ ÑÐŽÐŸÐ±ÐœÑ ÐŽÐ»Ñ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž 1500-3000 ÑÑÑÐ°ÐœÐžÑ Ð² ÐŒÐµÑÑÑ.</Text>
+</Content>
+</Subsection>
+<Subsection id="color_scanners">
+<Title>
+<Text id="67">ÐŠÐ²ÐµÑÐœÑÐµ ÑÐºÐ°ÐœÐµÑÑ</Text>
+</Title>
+<Content>
+<Text id="68">ÐÑÐ±Ð°Ñ ÐŸÐ¿ÐµÑÐ°ÑÐžÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ ÑÑÐ°Ð»ÐºÐžÐ²Ð°ÐµÑÑÑ Ñ ÑÐ²ÐµÑÐœÑÐŒÐž ÑÐžÑÑÐœÐºÐ°ÐŒÐž, Ð¿ÐŸÑÑÐŸÐŒÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÐœÐ°Ð³ÐŸÑÐŸÐ²Ðµ ÐžÐŒÐµÑÑ ÑÐ²ÐµÑÐœÐŸÐ¹ ÑÐºÐ°ÐœÐµÑ. ÐÐ±ÑÑÐœÐŸ ÐŒÐµÐœÐµÐµ 5% Ð»ÑÐ±ÐŸÐ¹ Ð¿ÑÐ±Ð»ÐžÐºÐ°ÑÐžÐž ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐºÐ°ÐºÐžÐµ-Ð»ÐžÐ±ÐŸ ÑÐ²ÐµÑÐœÑÐµ ÑÐžÑÑÐœÐºÐž, Ð²ÐºÐ»ÑÑÐ°Ñ ÐŸÐ±Ð»ÐŸÐ¶ÐºÑ. ÐÐŸÑÑÐŸÐŒÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ ÐžÐŒÐµÑÑ ÐŽÐµÑÐµÐ²ÑÐ¹ ÑÐ²ÐµÑÐœÐŸÐ¹ ÐœÐ°ÑÑÐŸÐ»ÑÐœÑÐ¹ ÑÐºÐ°ÐœÐµÑ. Ð ÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ ÐžÐŒÐµÑÑ ÑÐºÐ°ÐœÐµÑ Ñ ÑÐ°Ð·ÑÐµÑÐµÐœÐžÐµÐŒ ÐœÐµ ÐŒÐµÐœÐµÐµ 600 dpi.</Text>
+</Content>
+</Subsection>
+<Subsection id="professional_duplex_scanners">
+<Title>
+<Text id="69">ÐÑÐŸÑÐµÑÑÐžÐŸÐœÐ°Ð»ÑÐœÑÐµ ÐŽÑÐ¿Ð»ÐµÐºÑÐœÑÐµ ÑÐºÐ°ÐœÐµÑÑ</Text>
+</Title>
+<Content>
+<Text id="70">ÐÑÐŸÑÐµÑÑÐžÐŸÐœÐ°Ð»ÑÐœÑÐµ ÑÐºÐ°ÐœÐµÑÑ ÐœÐ°ÐŽÐµÐ¶ÐœÑ, Ð¿ÑÐŸÑÐœÑ Ðž ÑÐ¿ÐŸÑÐŸÐ±ÐœÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑ ÐŸÐºÐŸÐ»ÐŸ 2000-10000 ÑÑÑÐ°ÐœÐžÑ Ð² ÐŽÐµÐœÑ. ÐÐœÐž ÐžÐŒÐµÑÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÑÑ ÑÐžÑÑÐµÐŒÑ Ð¿ÐŸÐŽÐ°ÑÐž Ð±ÑÐŒÐ°Ð³Ðž, ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑ ÑÑÐŸÐ¿ÐºÐž Ð² 50-200 ÑÑÑÐ°ÐœÐžÑ. Ð¡Ð°ÐŒÑÐµ Ð»ÑÑÑÐžÐµ Ðž Ð±ÑÑÑÑÑÐµ ÑÐºÐ°ÐœÐµÑÑ - ÑÑÐŸ ÐŽÑÐ¿Ð»ÐµÐºÑÐœÑÐµ ÑÐºÐ°ÐœÐµÑÑ, ÐºÐŸÑÐŸÑÑÐµ ÑÐºÐ°ÐœÐžÑÑÑÑ ÐŸÐ±Ðµ ÑÑÐŸÑÐŸÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÐŸÐŽÐœÐŸÐ²ÑÐµÐŒÐµÐœÐœÐŸ.</Text>
+<Text id="71">Ð­ÑÐž ÑÐºÐ°ÐœÐµÑÑ ÐœÑÐ¶ÐŽÐ°ÑÑÑÑ Ð² ÐŒÐŸÑÐœÐŸÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ Ñ Ð¶ÐµÑÑÐºÐžÐŒ ÐŽÐžÑÐºÐŸÐŒ ÐºÐ°Ðº ÐŒÐžÐœÐžÐŒÑÐŒ ÐœÐ° 10-20 Gb. ÐÑ
+ ÑÐµÐœÑ Ð³ÑÐ°ÐœÐžÑÐ°Ñ ÐŸÑ $5000 ÐŽÐŸ $50000. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÐŽÑÐ¿Ð»ÐµÐºÑÐœÑÐ¹ ÑÐºÐ°ÐœÐœÐµÑ Canon DR-6020 ÑÑÐŸÐžÑ 5000 ÐŽÐŸÐ»Ð»Ð°ÑÐŸÐ² Ðž ÐŒÐŸÐ¶ÐµÑ ÑÐ°Ð±ÐŸÑÐ°ÑÑ Ñ ÐŽÐ²ÑÑ
+ÑÑÐŸÑÐŸÐœÐœÐžÐŒÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒÐž. ÐÐœ ÑÐ¿ÐŸÑÐŸÐ±ÐµÐœ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑ ÐŽÐŸ 2000 Ð² ÐŽÐµÐœÑ Ðž ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² ÑÐ°Ð±ÐŸÑÐµÐŒ ÑÐŸÑÑÐŸÑÐœÐžÐž ÐŽÐŸ 600000-800000 ÑÑÑÐ°ÐœÐžÑ. Ð¡ÐºÐ°ÐœÐµÑÑ Bell&amp;Howell and Fujitsu ÑÑÐŸÑÑ ÐŸÑ 10000-50000 ÐŽÐŸÐ»Ð»Ð°ÑÐŸÐ² Ðž ÐŒÐŸÐ³ÑÑ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐ°ÑÑ ÐŒÐžÐ»Ð»ÐžÐŸÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐŽÐŸ Ð¿ÐµÑÐ²ÐŸÐ³ÐŸ ÑÐµÐŒÐŸÐœÑÐ°.</Text>
+<Text id="72">Ð¡ÐºÐ°ÐœÐµÑÑ Micro-fische ÑÑÐŸÑÑ ÐŸÑ $15000 Ð·Ð° Ð¿ÐŸÐ»ÑÐ°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐžÐ¹ ÐœÐ°Ð±ÐŸÑ ÐŽÐŸ $80000, ÑÐ°Ð±ÐŸÑÐ°ÑÑÐžÐ¹ Ð¿ÐŸÐ»ÐœÐŸÑÑÑÑ Ð² Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐŸÐŒ ÑÐµÐ¶ÐžÐŒÐµ.</Text>
+</Content>
+</Subsection>
+<Subsection id="scanning_programs">
+<Title>
+<Text id="73">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐŽÐ»Ñ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ</Text>
+</Title>
+<Content>
+<Text id="74">ÐÐ°Ð¶ÐŽÑÐ¹ ÑÐºÐ°ÐœÐµÑ ÐžÐŒÐµÐµÑ ÑÐ²ÐŸÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ, Ð¿ÐŸÑÑÐŸÐŒÑ ÑÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐœÐ° Ð²Ð°Ñ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑ. ÐÐµÐºÐŸÑÐŸÑÑÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐžÐŒÐµÑÑ computer card, ÐºÐŸÑÐŸÑÑÑ ÐœÑÐ¶ÐœÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐŽÐ»Ñ ÑÑÐºÐŸÑÐµÐœÐžÑ Ð¿ÑÐŸÑÐµÑÑÐ° ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="preparing_the_documents">
+<Title>
+<Text id="75">ÐÐŸÐŽÐ³ÐŸÑÐŸÐ²ÐºÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²</Text>
+</Title>
+<Content>
+<Text id="76">ÐÐŸÐºÑÐŒÐµÐœÑÑ ÐœÑÐ¶ÐœÐŸ Ð¿ÐŸÐŽÐ³ÐŸÑÐŸÐ²ÐžÑÑ Ð·Ð°ÑÐ°ÐœÐµÐµ ÐŽÐŸ ÐžÑ
+ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ. Ð¡ ÐœÐžÑ
+ ÐœÑÐ¶ÐœÐŸ ÑÑÑÑÑ
+ÐœÑÑÑ Ð¿ÑÐ»Ñ, Ð²ÑÑÑÑÐžÑÑ ÐŒÐŸÐºÑÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ, ÑÐœÑÑÑ ÑÐºÑÐµÐ¿ÐºÐž Ðž ÑÐ°ÑÐ¿ÑÐ°Ð²ÐžÑÑ ÑÑÑÐ°ÐœÐžÑÑ.</Text>
+<Text id="77">ÐÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð°ÐºÐºÑÑÐ°ÑÐœÐŸ ÑÐœÑÑÑ ÑÑÐžÐ²ÐºÑ Ñ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÐºÐœÐžÐ³Ðž.</Text>
+<Text id="78">ÐÐœÐŸÐ³ÐžÐµ ÐºÐœÐžÐ³Ðž, ÐºÐŸÑÐŸÑÑÐµ Ð²Ñ Ð±ÑÐŽÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŽÐ»Ñ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ, ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð±ÑÐŽÐµÑ ÑÐœÐŸÐ²Ð° ÑÑÐžÑÑ, Ð¿ÐŸÑÑÐŸÐŒÑ Ð±ÑÐŽÑÑÐµ Ð²ÐœÐžÐŒÐ°ÑÐµÐ»ÑÐœÑ Ð¿ÑÐž ÑÐœÑÑÐžÐž ÑÑÐžÐ²ÐºÐž.</Text>
+<Text id="79">ÐÐ»Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÐžÐŒÐµÑÑÐžÑ
+ ÐŸÐ±ÑÐµÐŒ Ð±ÐŸÐ»ÐµÐµ 20 ÑÑÑÐ°ÐœÐžÑ, ÐŒÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÐŒ Ð¿ÐŸÑÑÑÐžÑÑ Ð·Ð°ÐŽÐ°ÐœÐžÐµ ÐœÐ° ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐ¿ÐµÑÐžÐ°Ð»ÐžÐ·ÐžÑÐŸÐ²Ð°ÐœÐœÑÐŒ ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑÐŒ, ÐžÐŒÐµÑÑÐžÐŒ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐµ ÐŸÐ±ÐŸÑÑÐŽÐŸÐ²Ð°ÐœÐžÐµ.</Text>
+</Content>
+</Section>
+<Section id="the_scanning_process">
+<Title>
+<Text id="80">ÐÑÐŸÑÐµÑÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ </Text>
+</Title>
+<Content>
+<Text id="81">ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÑÐµÐŒÑÑ Ð²ÐŒÐµÑÑÐµ ÑÐŸ ÑÐºÐ°ÐœÐµÑÐŸÐŒ, Ð¿ÐŸÑÐ»Ðµ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ Ð²Ñ Ð¿ÐŸÐ»ÑÑÐžÑÐµ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ Ð² ÑÐŸÑÐŒÐ°ÑÐµ Bitmap ÐžÐ»Ðž TIFF. Ð­ÑÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÐœÑÐ¶ÐœÐŸ ÑÐŸÑ
+ÑÐ°ÐœÐžÑÑ ÐœÐ° Ð¶ÐµÑÑÐºÐŸÐŒ ÐŽÐžÑÐºÐµ Ð¿ÐŸÐŽ Ð»ÑÐ±ÑÐŒ ÐžÐŒÐµÐœÐµÐŒ. The OCR process starts once some or all of a batch of documents have been scanned. It can be undertaken by the person who operates the scanner, or by someone else.</Text>
+<Text id="82">Typically a scanning resolution of 300 dpi is needed, although sometimes 200 dpi is acceptable.</Text>
+<Subsection id="quality_control">
+<Title>
+<Text id="83">ÐÐŸÐœÑÑÐŸÐ»Ñ ÐºÐ°ÑÐµÑÑÐ²Ð°</Text>
+</Title>
+<Content>
+<Text id="84">ÐÐŸÐœÐµÑÐœÐ°Ñ ÑÐµÐ»Ñ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ - ÑÑÐŸ Ð»ÐžÐ±ÐŸ Ð¿ÑÐŸÐ²ÐµÑÑÐž ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÑÐµÑÐµÐ· Ð¿ÑÐŸÑÐµÑÑ ÐŸÐ¿ÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°Ð²Ð°ÐœÐžÑ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ² ÐÐ Ð¡ (optical character recognition) ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÑÐµÐœÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ð² ÑÐŸÑÐŒÐ°ÑÐµ Word ÐžÐ»Ðž HTML, Ð»ÐžÐ±ÐŸ Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð² ÑÐŸÑÐŒÐ°ÑÐµ PDF. Ð Ð»ÑÐ±ÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ ÐºÐ°ÑÐµÑÑÐ²ÐŸ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ ÐžÑÑ
+ÐŸÐŽÐœÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÐŸÑÐµÐœÑ Ð²Ð°Ð¶ÐœÐŸ. ÐÑÐ»Ðž ÐºÐ°ÑÐµÑÑÐ²ÐŸ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ ÐœÐžÐ¶Ðµ ÑÑÐ°ÐœÐŽÐ°ÑÑÐ°, ÑÐŸ ÐŸÐœÐž Ð±ÑÐŽÑÑ Ð²ÑÐ³Ð»ÑÐŽÐµÑÑ ÑÐ°Ð·ÐŒÑÑÐŸ Ðž Ð·Ð°ÐœÐžÐŒÐ°ÑÑ Ð±ÐŸÐ»ÑÑÐµ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐœÐŸÐ¹ Ð¿Ð°ÐŒÑÑÐž. ÐÐ°ÑÐµÑÑÐ²ÐŸ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ ÑÐ°ÐºÐ¶Ðµ ÐŸÑÐµÐœÑ ÑÐžÐ»ÑÐœÐŸ Ð²Ð»ÐžÑÐµÑ ÐœÐ° Ð¿ÑÐŸÑÐµÑÑ ÐŸÐ¿ÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°Ð²Ð°ÐœÐžÑ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ² (ÐŽÐ°Ð»ÐµÐµ ÐÐ Ð¡). ÐÑÐž ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐœÐžÐ¶Ðµ ÐœÐŸÑÐŒÑ ÐµÐ³ÐŸ Ð¿ÑÐŸÐŽÑÐºÑÐžÐ²ÐœÐŸÑÑÑ Ð¿Ð°ÐŽÐ°ÐµÑ ÐœÐ° 40%. ÐÐ Ð¡, ÐºÐ°Ðº Ð¿ÑÐ°Ð²ÐžÐ»ÐŸ, ÑÐŸÑÑÐ°Ð²Ð»ÑÐµÑ 90% ÐŸÑ ÐŸÐ±ÑÐµÐ¹ ÑÑÐŸÐžÐŒÐŸÑÑÐž Ð²ÑÐµÐ³ÐŸ Ð¿ÑÐŸÑÐµÑÑÐ° Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÐœÐžÑ ÑÐ²ÐµÑÐŽÑÑ
+ ÐºÐŸÐ¿ÐžÐ¹ Ð² ÑÐžÑÑÐŸÐ²ÐŸÐ¹ ÑÐŸÑÐŒÐ°Ñ, Ð¿ÐŸÑÑÐŸÐŒÑ ÐºÐ°ÑÐµÑÑÐ²ÐŸ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐŒÐŸÐ¶ÐµÑ ÐŸÑÐµÐœÑ ÑÐžÐ»ÑÐœÐŸ Ð¿ÐŸÐ²Ð»ÐžÑÑÑ ÐœÐ° ÐºÐŸÐœÐµÑÐœÑÐµ Ð·Ð°ÑÑÐ°ÑÑ.</Text>
+<Text id="85">ÐÐ°ÑÐµÑÑÐ²ÐŸ ÑÐ°Ð¹Ð»ÐŸÐ² ÑÐŸÑÐŒÐ°ÑÐ° TIFF ÐŒÐŸÐ¶ÐœÐŸ ÑÐ»ÑÑÑÐžÑÑ Ð¿ÑÑÐµÐŒ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž Ð¿ÑÐŸÑÐµÑÑÐ° ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÐžÐ¿Ð° Ð±ÑÐŒÐ°Ð³Ðž, ÐžÐ·ÐŒÐµÐœÑÑ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž Ð² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐµ. ÐÑÐœÐŸÑÐžÑÐµÐ»ÑÐœÐŸ ÑÐŸÐœÐºÐ°Ñ Ð±ÑÐŒÐ°Ð³Ð° Ð¿ÐŸÑÑÐµÐ±ÑÐµÑ ÐŽÑÑÐ³ÐžÑ
+ ÐœÐ°ÑÑÑÐŸÐµÐº, ÐœÐµÐ¶ÐµÐ»Ðž ÐŽÑÑÐ³Ð°Ñ: ÐºÐŸÐœÑÑÐ°ÑÑ ÐŽÐŸÐ»Ð¶ÐµÐœ Ð±ÑÑÑ ÐœÐ°ÑÑÑÐŸÐµÐœ Ð² Ð·Ð°Ð²ÐžÑÐžÐŒÐŸÑÑÐž ÐŸÑ ÐºÐ°ÑÐµÑÑÐ²Ð° Ð¿ÐµÑÐ°ÑÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, ÐºÐŸÑÐŸÑÑÐ¹ Ð±ÑÐŽÐµÑ ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°Ðœ , Ðž Ñ.ÐŽ.</Text>
+<Text id="86">ÐÐœÐ°ÑÐ°Ð»Ðµ ÑÐ°Ð·ÐŽÐµÐ»ÐžÑÐµ ÐžÑÑ
+ÐŸÐŽÐœÑÐ¹ ÐŒÐ°ÑÐµÑÐžÐ°Ð» ÐœÐ° Ð³ÑÑÐ¿Ð¿Ñ ÑÐŸ ÑÑ
+ÐŸÐ¶ÐžÐŒ ÐºÐ°ÑÐµÑÑÐ²ÐŸÐŒ Ð±ÑÐŒÐ°Ð³Ðž Ðž ÑÑ
+ÐŸÐ¶ÐžÐŒ ÐºÐ°ÑÐµÑÑÐ²ÐŸÐŒ Ð¿ÐµÑÐ°ÑÐž. ÐÑÐŸÐ²ÐµÐŽÐžÑÐµ ÐžÑÐ¿ÑÑÐ°ÐœÐžÐµ ÐÐ Ð¡ ÐœÐ° ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ ÑÐºÐ·ÐµÐŒÐ¿Ð»ÑÑÐ°Ñ
+ Ð±ÑÐŒÐ°Ð³ ÐžÐ· Ð¿ÐµÑÐ²ÐŸÐ¹ Ð³ÑÑÐ¿Ð¿Ñ ÐŽÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÐŸÐ¿ÑÐžÐŒÐ°Ð»ÑÐœÑÑ
+ ÐœÐ°ÑÑÑÐŸÐµÐº. ÐÐ°ÑÐµÐŒ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐŒÐµÐ»ÐŸ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑ Ð²ÐµÑÑ ÐŒÐ°ÑÐµÑÐžÐ°Ð» ÐžÐ· ÑÑÐŸÐ¹ Ð³ÑÑÐ¿Ð¿Ñ.</Text>
+</Content>
+</Subsection>
+<Subsection id="filename_conventions">
+<Title>
+<Text id="87">Ð ÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÐŒÑÐµ Ð¿ÑÐ°Ð²ÐžÐ»Ð° ÐŽÐ»Ñ ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²</Text>
+</Title>
+<Content>
+<Text id="88">ÐÑÐžÑÐ²ÐŸÐ¹ÑÐµ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÐºÐœÐžÐ³Ðµ ÐžÐ»Ðž ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÑÐ²ÐŸÐ¹ ÐœÐŸÐŒÐµÑ ÐžÐ»Ðž ÐºÐŸÐŽ, ÐºÐŸÑÐŸÑÑÐ¹ ÑÑÐ°ÐœÐµÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµÐŒ Ð¿Ð°Ð¿ÐºÐž, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐµÐ¹ Ð²ÑÐµ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ TIFF ÐžÐ· ÑÑÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. Ð Ð·Ð°Ð²ÐžÑÐžÐŒÐŸÑÑÐž ÐŸÑ ÐŸÐ¿ÐµÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÑ (DOS, Windows, UNIX, LINUX Ðž Ñ.ÐŽ.) ÐŒÐŸÐ¶ÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŸÑ 8 ÐŽÐŸ 128 ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ² Ð² ÐœÐ°Ð·Ð²Ð°ÐœÐžÐž ÑÐ°Ð¹Ð»Ð°. ÐÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÐŒ ÐœÐµ Ð¿ÑÐµÐ²ÑÑÐ°ÑÑ 8-16 ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ². ÐÐµÑÐ²ÑÐµ Ð¿ÑÑÑ Ð±ÑÐºÐ² ÐŒÐŸÐ³ÑÑ ÑÐžÐŒÐ²ÐŸÐ»ÐžÐ·ÐžÑÐŸÐ²Ð°ÑÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, ÑÐ»ÐµÐŽÑÑÑÐžÐµ Ð±ÑÐºÐ²Ñ ÑÐ·ÑÐºÐŸÐ²ÐŸÐ¹ ÐºÐŸÐŽ, Ð° ÐŸÑÑÐ°Ð»ÑÐœÑÐµ ÑÐžÑÑÑ -ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ ÑÑÑÐ°ÐœÐžÑÑ). ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµÂ <i>u7548el2.tif</i>Â ÐŒÐŸÐ¶ÐµÑ ÐŸÐ·ÐœÐ°ÑÐ°ÑÑ ÑÐžÑÑÐœÐŸÐº TIFF ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ 12, ÐœÐ°Ð¿ÐžÑÐ°ÐœÐœÐŸÐ¹ ÐœÐ° Ð°ÐœÐ³Ð»ÐžÐ¹ÑÐºÐŸÐŒ ÑÐ·ÑÐºÐµ Ð¿ÐŸÐŽ ÐºÐŸÐŽÐŸÐŒÂ <i>u7548e</i>.</Text>
+<Text id="89">Ð¡ÐŸÐ·ÐŽÐ°Ð¹ÑÐµ ÐŸÐŽÐœÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ ÐœÐ° Ð¶ÐµÑÑÐºÐŸÐŒ ÐŽÐžÑÐºÐµ ÐŽÐ»Ñ ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐœÑÑ
+ ÑÐ°Ð±ÐŸÑ, ÐœÐ°Ð·ÐŸÐ²ÐžÑÐµ, Ðº Ð¿ÑÐžÐŒÐµÑÑ,Â <i>scanjobs</i>. ÐÐ°ÑÐµÐŒ ÑÐŸÐ·ÐŽÐ°Ð¹ÑÐµ Ð¿ÐŸÐŽÐŽÐžÑÐµÐºÑÐŸÑÐžÑ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ Ð·Ð°ÐŽÐ°ÐœÐžÑ. ÐÐœÑÑÑÐž Ð¿ÐŸÐŽÐŽÐžÑÐµÐºÑÐŸÑÐžÐž ÑÐŸÐ·ÐŽÐ°Ð¹ÑÐµ ÐµÑÐµ ÐŸÐŽÐœÑ Ð¿ÐŸÐŽÐŽÐžÑÐµÐºÑÐŸÑÐžÑ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ¹ Ð¿ÑÐ±Ð»ÐžÐºÐ°ÑÐžÐž Ðž ÐºÐœÐžÐ³Ðž - Ðž7548 Ð² Ð¿ÑÐžÐŒÐµÑÐµ, Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐœÐŸÐŒ Ð²ÑÑÐµ. Ð¡ÐŸÑ
+ÑÐ°ÐœÑÐ¹ÑÐµ Ð²ÑÐµ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ TIFF ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, Ð²ÐºÐ»ÑÑÐ°Ñ ÑÐ²ÐµÑÐœÑÐµ ÑÐžÑÑÐœÐºÐž, Ð² ÑÑÐŸÐ¹ Ð¿Ð°Ð¿ÐºÐµ.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="productivity_and_resources">
+<Title>
+<Text id="90">ÐÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÐµÐ»ÑÐœÐŸÑÑÑ Ðž ÑÐµÑÑÑÑÑ</Text>
+</Title>
+<Content>
+<Text id="91">ÐÑ ÐœÐµ ÐŽÐŸÐ»Ð¶ÐœÑ ÐœÐµÐŽÐŸÐŸÑÐµÐœÐžÐ²Ð°ÑÑ Ð²ÐµÑÑ ÐŒÐ°ÑÑÑÐ°Ð± Ð¿ÑÐŸÑÐµÐŽÑÑÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ â Ð² ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž Ð¿ÑÐŸÑÐµÑÑ ÐÐ Ð¡. ÐÑÑÑÐµ Ð²ÑÐµÐ³ÐŸ ÑÑÐžÑÐ°ÑÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ðž ÐÐ Ð¡ ÐºÐ°Ðº Ð¿ÐŸÐ»ÐœÐŸÑÑÑÑ ÐœÐµÐ·Ð°Ð²ÐžÑÐžÐŒÑÐµ ÐŸÐ¿ÐµÑÐ°ÑÐžÐž. ÐÐ¿ÑÐžÐŒÐ°Ð»ÑÐœÐŸÐµ ÑÐµÑÐµÐœÐžÐµ ÐŽÐŸÐ»Ð¶ÐœÐŸ Ð±ÑÑÑ Ð¿ÑÐžÐœÑÑÐŸ Ð¿ÐŸ ÐºÐ°Ð¶ÐŽÐŸÐŒÑ ÐžÐ· ÐœÐžÑ
+ Ð² ÐŸÑÐŽÐµÐ»ÑÐœÐŸÑÑÐž.</Text>
+<Text id="92">ÐÐŸÑ ÐœÐµÐºÐŸÑÐŸÑÑÐµ Ð²ÐµÑÐž, ÐŸ ÐºÐŸÑÐŸÑÑÑ
+ ÑÐ»ÐµÐŽÑÐµÑ Ð¿ÐŸÐŽÑÐŒÐ°ÑÑ Ð¿ÐµÑÐµÐŽ Ð¿ÑÐžÐŸÐ±ÑÐµÑÐµÐœÐžÐµÐŒ ÑÐºÐ°ÐœÐµÑÐŸÐ² Ðž ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐŸÐ²: ÐœÐ°Ð»ÐžÑÐžÐµ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÐ³ÐŸ Ð¿ÐŸÐŒÐµÑÐµÐœÐžÑ Ðž ÑÐ°Ð±ÐŸÑÐµÐ¹ ÑÐžÐ»Ñ, ÐŸÐ±ÑÑÐµÐœÐžÐµ ÑÐ°Ð±ÐŸÑÐžÑ
+; Ð·Ð°ÑÐ¿Ð»Ð°ÑÐ°; ÐŒÐžÐœÐžÐŒÐ°Ð»ÑÐœÐŸÐµ Ðž ÐŒÐ°ÐºÑÐžÐŒÐ°Ð»ÑÐœÐŸÐµ ÑÐžÑÐ»ÐŸ ÑÑÑÐ°ÐœÐžÑ, ÐºÐŸÑÐŸÑÑÐµ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑ; ÑÑÐŸÐºÐž; ÐŒÐŸÐ¶ÐœÐŸ Ð»Ðž ÑÑÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð¿ÐµÑÐµÐŽÐ°Ð²Ð°ÑÑ ÑÑÐµÑÑÐžÐŒ Ð»ÐžÑÐ°ÐŒ.</Text>
+<Subsection id="scanning_costs">
+<Title>
+<Text id="93">Ð¡ÑÐŸÐžÐŒÐŸÑÑÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ</Text>
+</Title>
+<Content>
+<Text id="94">ÐÐ°Ð¶ÐœÐŸÐµ ÑÐµÑÐµÐœÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ ÐœÑÐ¶ÐœÐŸ Ð¿ÑÐžÐœÑÑÑ, - Ð¿ÐŸÐºÑÐ¿Ð°ÑÑ Ð»Ðž ÑÐºÐ°ÐœÐžÑÑÑÑÑÑ Ð°Ð¿Ð¿Ð°ÑÐ°ÑÑÑÑ Ðž Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐ°ÐŒÐžÐŒ, ÐžÐ»Ðž Ð¿ÐŸÑÑÑÐžÑÑ ÑÑÐŸ ÐŽÐµÐ»ÐŸ ÐºÐŸÐŒÐ¿Ð°ÐœÐžÐž, ÑÐ¿ÐµÑÐžÐ°Ð»ÐžÐ·ÐžÑÑÑÑÐµÐ¹ÑÑ ÐœÐ° ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐž. ÐÐŸÑ Ð³Ð»Ð°Ð²ÐœÑÐµ Ð¿ÑÐœÐºÑÑ, ÐœÐ°ÐŽ ÐºÐŸÑÐŸÑÑÐŒÐž ÐœÐ°ÐŽÐŸ Ð¿ÐŸÐŽÑÐŒÐ°ÑÑ:</Text>
+<BulletList>
+<Bullet>
+<Text id="95">ÐÐŸÐœÐµÑÐœÑÐµ ÑÑÐŸÐºÐž ÐŽÐ»Ñ Ð·Ð°Ð²ÐµÑÑÐµÐœÐžÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ</Text>
+</Bullet>
+<Bullet>
+<Text id="96">ÐÐ±ÑÐµÐµ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ ÑÑÑÐ°ÐœÐžÑ</Text>
+</Bullet>
+<Bullet>
+<Text id="97">ÐÐ°ÑÐ¿Ð»Ð°ÑÐ° ÑÐµÑ
+, ÐºÑÐŸ ÑÐŸÐ²ÐµÑÑÐ°ÐµÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ</Text>
+</Bullet>
+</BulletList>
+<Text id="98">ÐÑÐŽÐž, Ð·Ð°ÐœÐžÐŒÐ°ÑÑÐžÐµÑÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµÐŒ, ÐŽÐŸÐ»Ð¶ÐœÑ ÐžÐŒÐµÑÑ Ð²ÑÑÐŸÐºÑÑ ÐŒÐŸÑÐžÐ²Ð°ÑÐžÑ, Ð±ÑÑÑ ÐžÑÐºÑÑÐœÑÐŒÐž Ðž ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÑÐŒÐž Ð·Ð° ÐºÐ°ÑÐµÑÑÐ²ÐŸ ÑÐ°Ð±ÐŸÑÑ.</Text>
+<Text id="99">Ð¡ÑÐµÐŽÐœÑÑ ÑÐµÐœÐ° Ð·Ð° ÐŸÐŽÐœÑ ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐœÑÑ ÑÑÑÐ°ÐœÐžÑÑ Ñ Ð¿ÑÐŸÑÐµÑÑÐžÐŸÐœÐ°Ð»ÑÐœÑÑ
+ ÐºÐŸÐŒÐ¿Ð°ÐœÐžÐ¹ ÑÐŸÑÑÐ°Ð²Ð»ÑÐµÑ $0.06. Ð ÑÑÐŸÐŒÑ ÐœÑÐ¶ÐœÐŸ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÑÑÐŸÐžÐŒÐŸÑÑÑ ÐŽÐŸÑÑÐ°Ð²ÐºÐž, ÐºÐŸÑÐŸÑÐ°Ñ ÐŒÐŸÐ¶ÐµÑ ÐŽÐŸÑÑÐžÐ³Ð°ÑÑ $0.03 Ð·Ð° ÑÑÐ°ÐœÑÐ¿ÐŸÑÑÐžÑÐŸÐ²ÐºÑ ÑÑÑÐ°ÐœÐžÑÑ ÐžÐ· ÑÐ°Ð·Ð²ÐžÐ²Ð°ÑÑÐµÐ¹ÑÑ ÑÑÑÐ°ÐœÑ Ð² ÑÐ°Ð·Ð²ÐžÑÑÑ, Ðž $0.015 - Ð·Ð° ÑÑÑÐ°ÐœÐžÑÑ Ð² ÑÐ°ÐŒÐŸÐ¹ ÑÑÑÐ°ÐœÐµ.</Text>
+<Text id="100">Ð ÑÐ°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="table_scanning_cost"/> Ð¿ÑÐžÐ²ÐµÐŽÐµÐœÐ° ÑÑÐŸÐžÐŒÐŸÑÑÑ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ ÐŸÐ¿ÐµÑÐ°ÑÐžÐž ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ Ð²Ð°ÑÐžÐŒÐž ÑÑÐžÐ»ÐžÑÐŒÐž Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ ÑÐ°Ð·ÐœÑÑ
+ ÑÐžÐ¿ÐŸÐ² ÑÐºÐ°ÐœÐµÑÐŸÐ². ÐÐ°ÐŒÐµÑÑÑÐµ, ÑÑÐŸ Ð²ÑÐµ ÑÐžÑÑÑ Ð¿ÑÐžÐ±Ð»ÐžÐ·ÐžÑÐµÐ»ÑÐœÑ. ÐÐœÐž Ð¿ÑÐžÐŒÐµÑÐœÑ Ðž ÐŸÑÐœÐŸÐ²ÑÐ²Ð°ÑÑÑÑ ÐœÐ° ÐŸÐ¿ÑÑÐµ Ð°Ð²ÑÐŸÑÐŸÐ². ÐÐµÑÐ²ÑÐµ ÑÑÐž ÐºÐŸÐ»ÐŸÐœÐºÐž Ð²ÐºÐ»ÑÑÐ°ÑÑ ÑÑÐŸÐžÐŒÐŸÑÑÑ ÑÐ°Ð±ÐŸÑÐµÐ¹ ÑÐžÐ»Ñ. ÐÐµÑÐ²Ð°Ñ ÐžÐ· ÐœÐžÑ
+ - ÑÑÐŸ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÐµÐ»ÑÐœÐŸÑÑÑ Ð² ÑÑÑÐ°ÐœÐžÑÐ°Ñ
+/ÐŒÐµÑÑÑ Ð¿ÑÐž ÑÐ°Ð±ÐŸÑÐµ ÐœÐ° Ð¿ÐŸÐ»ÐœÑÑ ÑÑÐ°Ð²ÐºÑ. Ð Ð°ÑÑÐµÑ ÑÐµÐ»ÐŸÐ²ÐµÐºÐŸ-ÑÐ°ÑÐŸÐ² ÐœÐ° ÑÑÑÐ°ÐœÐžÑÑ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑÑ Ð¿ÑÑÐµÐŒ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ ÑÐžÑÐ»Ð° ÑÐ°Ð±ÐŸÑÐžÑ
+ ÑÐ°ÑÐŸÐ² Ð² ÐŒÐµÑÑÑÐµ ÐœÐ° Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÐµÐ»ÑÐœÐŸÑÑÑ ÑÑÑÐ°ÐœÐžÑÐ°/ÐŒÐµÑÑÑ Ðž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœ Ð²ÐŸ Ð²ÑÐŸÑÐŸÐ¹ ÐºÐŸÐ»ÐŸÐœÐºÐµ. ÐÑÐž ÑÐ°ÑÑÐµÑÐµ Ð¿ÑÐµÐŽÐ¿ÐŸÐ»Ð°Ð³Ð°ÐµÑÑÑ 180 ÑÐ°Ð±ÐŸÑÐžÑ
+ ÑÐ°ÑÐŸÐ² Ð² ÐŒÐµÑÑÑ.</Text>
+<Table id="table_scanning_cost">
+<Title>
+<Text id="101">Ð¡ÑÐŸÐžÐŒÐŸÑÑÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="104">Â </th>
+<th width="76">
+<Text id="102">ÐÐ±ÑÐµÐŒ (ÑÑÑÐ°ÐœÐžÑ/ÐŒÐµÑÑÑ)</Text>
+</th>
+<th width="66">
+<Text id="103">Ð§Ð°Ñ/ÑÑÑÐ° ÐœÐžÑÐ° (180 ÑÐ°ÑÐŸÐ² Ð² ÐŒÐµÑÑÑ)</Text>
+</th>
+<th width="66">
+<Text id="104">ÐŠÐµÐœÐ°/ÑÑÑ (Ð¿ÑÐµÐŽÐ¿ÐŸ-Ð»Ð°ÑÐ°Ñ $4/ÑÐ°Ñ)</Text>
+</th>
+<th width="66">
+<Text id="105">ÐŠÐµÐœÐ° ÑÐºÐ°ÐœÐµÑÐ°</Text>
+</th>
+<th width="66">
+<Text id="106">Ð Ð°Ð±ÐŸÑÐŸÑÐ¿ÐŸÑÐŸ Ð±ÐœÐŸÑÑÑ ÐŽÐŸ Ð¿ÐµÑÐ²ÐŸÐ³ÐŸ ÑÐµÐŒÐŸÐœÑÐ° (ÑÑÑÐ°ÐœÐžÑ)</Text>
+</th>
+<th width="85">
+<Text id="107">ÐÐ±ÑÐµÐŒ Ð²ÑÐ¿ÐŸÐ»ÐœÑÐµÂ­ÐŒÑÐ¹ Ð¿ÑÐŸÑÐµÑÑÐžÂ­ÐŸÐœÐ°Ð»ÑÐœÐŸÐ¹ ÐºÐŸÐŒÐ¿Ð°ÐœÐžÐµÐ¹ (Ð¿ÑÐž $0,06 Ð·Ð° ÑÑÑÐ°ÐœÐžÑÑ)</Text>
+</th>
+</tr>
+<tr>
+<th width="104">
+<Text id="108">Ð¡ÑÑÐ°ÐœÐžÑÐœÑÐ¹ ÐœÐ°ÑÑÐŸÐ»ÑÐœÑÐ¹</Text>
+</th>
+<th width="76">
+<Text id="109">2,500</Text>
+</th>
+<th width="66">
+<Text id="110">0.072</Text>
+</th>
+<th width="66">
+<Text id="111">$0.288</Text>
+</th>
+<th width="66">
+<Text id="112">$300</Text>
+</th>
+<th width="66">
+<Text id="113">7,000</Text>
+</th>
+<th width="85">
+<Text id="114">5,000</Text>
+</th>
+</tr>
+<tr>
+<th width="104">
+<Text id="115">ÑÐºÐ°ÐœÐµÑ Ð¡ÐºÐ°ÐœÐµÑ Ñ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÂ­ÐºÐŸÐ¹</Text>
+</th>
+<th width="76">
+<Text id="116">8,000</Text>
+</th>
+<th width="66">
+<Text id="117">0.0225</Text>
+</th>
+<th width="66">
+<Text id="118">$0.09</Text>
+</th>
+<th width="66">
+<Text id="119">$800</Text>
+</th>
+<th width="66">
+<Text id="120">30,000</Text>
+</th>
+<th width="85">
+<Text id="121">13,000</Text>
+</th>
+</tr>
+<tr>
+<th width="104">
+<Text id="122">Ð¿ÐŸÐŽÐ°ÑÐµÐ¹ ÑÑÑÐ°ÐœÐžÑ ÐÑÐŸÑÐµÑÑÐžÂ­ÐŸÐœÐ°Ð»ÑÐœÑÐ¹ low end duplex</Text>
+</th>
+<th width="76">
+<Text id="123">40,000</Text>
+</th>
+<th width="66">
+<Text id="124">0.0045</Text>
+</th>
+<th width="66">
+<Text id="125">$0.018</Text>
+</th>
+<th width="66">
+<Text id="126">$6,000</Text>
+</th>
+<th width="66">
+<Text id="127">600,000</Text>
+</th>
+<th width="85">
+<Text id="128">100,000</Text>
+</th>
+</tr>
+<tr>
+<th width="104">
+<Text id="129">ÐÑÐŸÑÐµÑÑÐžÐŸÐœÐ°Â­Ð»ÑÐœÑÐ¹: high-end duplex</Text>
+</th>
+<th width="76">
+<Text id="130">150,000</Text>
+</th>
+<th width="66">
+<Text id="131">0.0012</Text>
+</th>
+<th width="66">
+<Text id="132">$0.0048</Text>
+</th>
+<th width="66">
+<Text id="133">$50,000</Text>
+</th>
+<th width="66">
+<Text id="134">8,000,000</Text>
+</th>
+<th width="85">
+<Text id="135">833,000</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="136">Ð§ÑÐŸÐ±Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÑÐŸÐžÐŒÐŸÑÑÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐŸÐŽÐœÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÑ, ÑÐŒÐœÐŸÐ¶ÑÑÐµ Ð¿ÐŸÐ»ÐœÑÑ ÑÐ°ÑÐŸÐ²ÑÑ Ð·Ð°ÑÐ¿Ð»Ð°ÑÑ ÐœÐ° Ð²ÑÐŸÑÑÑ ÐºÐŸÐ»ÐŸÐœÐºÑ. Ð Ð¿ÑÐžÐŒÐµÑÑ, Ð² ÑÑÐµÑÑÐµÐ¹ ÐºÐŸÐ»ÐŸÐœÐºÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐ° ÑÐµÐœÐ° Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ Ð¿ÑÐž ÐœÐ°Ð¹ÐŒÐµ ÑÑÑÐŽÐ° Ð±ÐµÐ· ÑÑÐµÑÐ° Ð·Ð°ÑÑÐ°Ñ ÐœÐ° ÑÐºÐ°ÐœÐµÑ - $4/ÑÐ°Ñ.</Text>
+<Text id="137">Ð­ÑÐž Ð¿ÐŸÐŽÑÑÐµÑÑ Ð¿ÐŸÐŽÑÐ°Ð·ÑÐŒÐµÐ²Ð°ÑÑ, ÑÑÐŸ ÑÐºÐ°ÐœÐµÑ Ð±ÑÐŽÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ðœ ÐŽÐ»Ñ ÐŽÐŸÑÑÐ°ÑÐŸÑÐœÐŸ Ð±ÐŸÐ»ÑÑÐŸÐ³ÐŸ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²Ð° ÐºÐŸÐ¿ÐžÐ¹, ÑÑÐŸÐ±Ñ ÐŸÐºÑÐ¿ÐžÑÑ ÑÐ²ÐŸÑ ÐœÐ°ÑÐ°Ð»ÑÐœÑÑ ÑÑÐŸÐžÐŒÐŸÑÑÑ. ÐÐŸÑÐ»ÐµÐŽÐœÐžÐµ ÑÑÐž ÐºÐŸÐ»ÐŸÐœÐºÐž ÐŽÐ°ÑÑ Ð±ÐŸÐ»ÑÑÐµ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž ÐŸ ÑÑÐŸÐžÐŒÐŸÑÑÐž ÑÐ°ÐŒÐŸÐ³ÐŸ ÑÐºÐ°ÐœÐµÑÐ°. ÐÐµÑÐ²Ð°Ñ ÐžÐ· ÐœÐžÑ
+ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÑÑÐŸÐžÐŒÐŸÑÑÑ ÑÐºÐ°ÐœÐµÑÐ°, ÑÐ»ÐµÐŽÑÑÑÐ°Ñ Ð¿ÑÐžÐ±Ð»ÐžÐ·ÐžÑÐµÐ»ÑÐœÑÑ Ð¿ÑÐŸÐŽÐŸÐ»Ð¶ÐžÑÐµÐ»ÑÐœÐŸÑÑÑ ÑÐ°Ð±ÐŸÑÐŸÑÐ¿ÐŸÑÐŸÐ±ÐœÐŸÑÑÐž. ÐÐŸÑÐ»ÐµÐŽÐœÑÑ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÑÐžÑÐ»ÐŸ ÑÑÑÐ°ÐœÐžÑ, ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ¶ÐœÐŸ ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑ, ÐœÐ°ÐœÑÐ² ÐºÐŸÐŒÐ¿Ð°ÐœÐžÑ, Ð¿ÑÐž ÑÐµÐœÐµ $0.06/ÑÑÑÐ°ÐœÐžÑÐ°.</Text>
+<Text id="138">ÐÐŸÐœÐµÑÐœÐŸ Ð¶Ðµ ÐœÐ° Ð²ÑÐ±ÐŸÑ ÑÐºÐ°ÐœÐµÑÐ° Ð²Ð»ÐžÑÑÑ Ðž ÐŽÑÑÐ³ÐžÐµ ÑÐ°ÐºÑÐŸÑÑ: ÐœÐ°Ð»ÐžÑÐžÐµ ÐŽÐµÐœÐµÐ³, ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÑ Ð² ÐŒÐžÐœÐžÐŒÐžÐ·Ð°ÑÐžÐž Ð·Ð°Ð²ÐžÑÐžÐŒÐŸÑÑÐž ÐŸÑ ÐŽÑÑÐ³ÐžÑ
+, ÐŽÐŸÐ³ÐŸÐ²ÐŸÑÐµÐœÐœÐŸÑÑÑ Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐŸÐ¹, ÑÐ°Ð·ÑÐµÑÐ°ÑÑÐ°Ñ ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÑÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐºÐœÐžÐ³, ÐœÐµ Ð²ÑÐ²ÐŸÐ·Ñ ÐžÑ
+ Ð·Ð° Ð¿ÑÐµÐŽÐµÐ»Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Ðž Ñ.ÐŽ.</Text>
+<Text id="139">Ð¢Ð°Ð±Ð»ÐžÑÐ° Ð¿ÑÐžÐ²ÐµÐŽÐµÐœÐœÐ°Ñ Ð²ÑÑÐµ, ÐŽÐ°ÐµÑ Ð¿ÑÐžÐŒÐµÑÐœÑÑ ÐŸÑÐµÐœÐºÑ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²Ð° ÑÑÑÐ°ÐœÐžÑ, ÐºÐŸÑÐŸÑÐŸÐµ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑ ÐŽÐ»Ñ ÐŸÐºÑÐ¿Ð°ÐµÐŒÐŸÑÑÐž Ð·Ð°ÑÑÐ°Ñ. ÐÑÐµÐœÑ ÑÐµÐŽÐºÐž ÑÐ»ÑÑÐ°Ðž, ÐºÐŸÐ³ÐŽÐ° ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑ ÐœÑÐ¶ÐŽÐ°ÐµÑÑÑ Ð² ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐž 800000 ÑÑÑÐ°ÐœÐžÑ. ÐÑÐž ÑÐ°ÐºÐŸÐŒ ÐŒÐ°ÑÑÑÐ°Ð±Ðµ Ð¿ÐŸÑÐ²Ð»ÑÑÑÑÑ Ð±ÐŸÐ»ÐµÐµ ÑÐ»ÐŸÐ¶ÐœÑÐµ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÑ, ÑÐ°ÐºÐžÐµ ÐºÐ°Ðº ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ ÐŸÐ±ÐŸÑÑÐŽÐŸÐ²Ð°ÐœÐžÑ Ðž ÐŸÐºÑÐ¿Ð°ÐµÐŒÐŸÑÑÑ Ð·Ð°ÑÑÐ°Ñ Ð¿ÑÑÐµÐŒ ÑÐŽÐ°ÑÐž ÐµÐ³ÐŸ Ð² Ð°ÑÐµÐœÐŽÑ, ÐºÐŸÑÐŸÑÑÐµ ÐœÐµ Ð±ÑÐŽÑÑ ÐŸÐ±ÑÑÐ¶ÐŽÐ°ÑÑÑÑ Ð² ÑÑÐŸÐ¹ ÑÐ°ÑÑÐž.</Text>
+<Text id="140">Ð Ð°Ð·Ð²ÐžÑÐžÐµ Ð±ÐžÐ·ÐœÐµÑÐ° ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐŒÐŸÐ¶ÐµÑ Ð¿ÐŸÐºÐ°Ð·Ð°ÑÑÑÑ ÐŸÑÐµÐœÑ Ð¿ÑÐžÐ²Ð»ÐµÐºÐ°ÑÐµÐ»ÑÐœÐŸÐ¹ ÐºÐŸÐŒÐŒÐµÑÑÐµÑÐºÐŸÐ¹ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑÑ, Ð² ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž Ð² ÑÐ°Ð·Ð²ÐžÐ²Ð°ÑÑÐžÑ
+ÑÑ ÑÑÑÐ°ÐœÐ°Ñ
+. ÐÐŸ Ð¿ÐŸÐŒÐœÐžÑÐµ, Ð§ÑÐŸ Ð¿ÐŸÑÐ»Ðµ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº Ð±ÑÐŽÑÑ ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ, Ð²Ð°ÑÐž ÐºÐ»ÐžÐµÐœÑÑ Ð±ÐŸÐ»ÑÑÐµ ÐœÐžÐºÐŸÐ³ÐŽÐ° ÐœÐµ Ð·Ð°ÐºÐ°Ð¶ÑÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐµÑ
+ Ð¶Ðµ ÑÐ°ÐŒÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² - Ð²ÐœÐµ Ð·Ð°Ð²ÐžÑÐžÐŒÐŸÑÑÐž ÐŸÑ ÑÐŸÐ³ÐŸ, ÐœÐ°ÑÐºÐŸÐ»ÑÐºÐŸ Ñ
+ÐŸÑÐŸÑÐž Ð²Ð°ÑÐž Ñ ÐœÐžÐŒÐž ÐŸÑÐœÐŸÑÐµÐœÐžÑ. Ð¡ ÐºÐŸÐŒÐŒÐµÑÑÐµÑÐºÐŸÐ¹ ÑÐŸÑÐºÐž Ð·ÑÐµÐœÐžÑ ÑÑÐŸÑ Ð±ÐžÐ·ÐœÐµÑ ÐœÑÐ¶ÐŽÐ°ÐµÑÑÑ Ð² ÐžÐœÑÐµÐœÑÐžÐ²ÐœÐŸÐŒ ÐŒÐ°ÑÐºÐµÑÐžÐœÐ³ÐŸÐ²ÐŸÐŒ ÐžÐ·ÑÑÐµÐœÐžÐž. ÐÑ ÐœÐµ ÑÐŸÐ²ÐµÑÑÐµÐŒ ÐœÐµÐ¿ÑÐ°Ð²ÐžÑÐµÐ»ÑÑÑÐ²ÐµÐœÐœÑÐŒ ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑÐŒ Ðž ÐœÐµÐºÐŸÐŒÐŒÐµÑÑÐµÑÐºÐžÐŒ ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑÐŒ Ð·Ð°ÐœÐžÐŒÐ°ÑÑÑÑ ÑÐ°ÐºÐžÐŒ Ð±ÐžÐ·ÐœÐµÑÐŸÐŒ Ð±ÐµÐ· ÐŽÐµÑÐ°Ð»ÑÐœÐŸÐ³ÐŸ ÐžÑÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐžÑ ÑÑÐœÐºÐ° Ðž Ñ
+ÐŸÑÐŸÑÐŸ Ð¿ÑÐŸÐŽÑÐŒÐ°ÐœÐœÐŸÐ³ÐŸ Ð±ÐžÐ·ÐœÐµÑ-Ð¿Ð»Ð°ÐœÐ°.</Text>
+<Text id="141">Ð Ð·Ð°ÐºÐ»ÑÑÐµÐœÐžÐµ ÐŸÑÐŒÐµÑÐžÐŒ, ÑÑÐŸ ÐµÑÐ»Ðž ÐœÑÐ¶ÐœÐŸ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑ ÐŸÑ 10000 ÐŽÐŸ 50000 ÑÑÑÐ°ÐœÐžÑ, Ð»ÑÑÑÐµ Ð¿ÐŸÑÑÑÐžÑÑ ÑÑÑ ÑÐ°Ð±ÐŸÑÑ ÑÐºÐ°ÐœÐžÑÑÑÑÐµÐ¹ ÐºÐŸÐŒÐ¿Ð°ÐœÐžÐž. ÐÑÐŸÑÐµÑÑÐžÐŸÐœÐ°Ð»ÑÐœÑÐ¹ low-end ÑÐºÐ°ÐœÐµÑ Ð±ÑÐŽÐµÑ ÐŸÐºÑÐ¿Ð»ÐµÐœ ÑÐŸÐ»ÑÐºÐŸ Ð² ÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ, ÐµÑÐ»Ðž Ð²Ñ ÐŸÑÑÐºÐ°ÐœÐžÑÑÐµÑÐµ Ð±ÐŸÐ»ÐµÐµ 100000 ÑÑÑÐ°ÐœÐžÑ. ÐÑÐ»Ðž Ð²Ñ ÑÐµÑÐžÐ»Ðž Ð¿ÑÐžÐŸÐ±ÑÐµÑÑÐž ÑÐ°ÐºÐŸÐ¹ ÑÐºÐ°ÐœÐµÑ, ÑÐŸ Ð»ÑÑÑÐµ ÑÑÐŸ ÑÐŽÐµÐ»Ð°ÑÑ ÑÐŸÐ²ÐŒÐµÑÑÐœÐŸ Ñ ÐŽÑÑÐ³ÐŸÐ¹ ÐœÐµÐ¿ÑÐ°Ð²ÐžÑÐµÐ»ÑÑÑÐ²ÐµÐœÐœÐŸÐ¹ ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐµÐ¹ ÐžÐ»Ðž Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐŸÐ¹.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="ocr">
+<Title>
+<Text id="142">ÐÐ Ð¡: ÐŸÐ¿ÑÐžÑÐµÑÐºÐžÐ¹ ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°Ð²Ð°ÑÐµÐ»Ñ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ²</Text>
+</Title>
+<Content>
+<Text id="143">ÐÐ¿ÑÐžÑÐµÑÐºÐžÐ¹ ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°Ð²Ð°ÑÐµÐ»Ñ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ² ÐžÐ»Ðž ÐÐ Ð¡ ÑÑÐ°ÐœÑÑÐŸÑÐŒÐžÑÑÐµÑ ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐœÐŸÐµ ÑÐžÑÑÐŸÐ²ÐŸÐµ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ Ð² ÑÐµÐºÑÑ. ÐÑÑ
+ÐŸÐŽÐœÑÐ¹ ÐŒÐ°ÑÐµÑÐžÐ°Ð» - ÑÑÐŸ ÑÐžÑÑÐŸÐ²ÐŸÐµ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ Ð² ÑÐŸÑÐŒÐ°ÑÐµ TIFF ÐžÐ»Ðž Bitmap â Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÐŸ ÑÑÐŸÐ±Ñ ÐŸÐœ Ð±ÑÐ» Ñ
+ÐŸÑÐŸÑÐµÐ³ÐŸ ÐºÐ°ÑÐµÑÑÐ²Ð°. ÐÐŸÑÐ»Ðµ Ð¿ÑÐŸÑ
+ÐŸÐ¶ÐŽÐµÐœÐžÑ ÑÐµÑÐµÐ· ÐÐ Ð¡ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐŸÐ»ÑÑÐžÑÑ ÑÐ°Ð¹Ð» Ð² ÑÐŸÑÐŒÐ°ÑÐµ RTF, Word, HTML ÐœÐ° Ð²Ð°ÑÐµ ÑÑÐŒÐŸÑÑÐµÐœÐžÐµ.</Text>
+<Text id="144">ÐÐŸÑ ÑÐ°Ð³Ðž, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐµ Ð¿ÑÐž Ð¿ÐµÑÐµÐ²ÐŸÐŽÐµ Ð±ÑÐŒÐ°Ð¶ÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð² ÑÐžÑÑÐŸÐ²ÐŸÐ¹ ÑÐŸÑÐŒÐ°Ñ:</Text>
+<BulletList>
+<Bullet>
+<Text id="145">ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ</Text>
+</Bullet>
+<Bullet>
+<Text id="146">Ð°ÐœÐ°Ð»ÐžÐ·</Text>
+</Bullet>
+<Bullet>
+<Text id="147">ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°Ð²Ð°ÐœÐžÐµ</Text>
+</Bullet>
+<Bullet>
+<Text id="148">ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐ¹ Ðž ÑÐ°Ð±Ð»ÐžÑ. </Text>
+</Bullet>
+</BulletList>
+<Text id="149">Ð¡Ð»ÐµÐŽÑÑ ÐžÐŒ, Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑÑ ÐºÐŸÐœÑÑÐŸÐ»Ñ ÐºÐ°ÑÐµÑÑÐ²Ð° Ð¿ÐŸÐ»ÑÑÐµÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² Ðž ÑÐŸÑ
+ÑÐ°ÐœÑÑÑ ÐžÑ
+ Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐ¹ Ð¿Ð°Ð¿ÐºÐµ.</Text>
+<Text id="150">ÐÐ° ÑÑÐœÐºÐµ ÑÑÑÐµÑÑÐ²ÑÐµÑ ÐŽÐŸÑÑÐ°ÑÐŸÑÐœÐŸ ÐŒÐœÐŸÐ³ÐŸ Ñ
+ÐŸÑÐŸÑÐžÑ
+ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒ ÐÐ Ð¡ ÑÑÐŸÐžÐŒÐŸÑÑÑÑ ÐŸÑ $100-400<FootnoteRef id="2"/>. ÐÐŸÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐžÐ· ÐœÐžÑ
+:</Text>
+<BulletList>
+<Bullet>
+<Text id="151">Read-Iris (http://www.readiris.com/)</Text>
+</Bullet>
+<Bullet>
+<Text id="152">Omnipage (http://www.omnipage.com/)</Text>
+</Bullet>
+<Bullet>
+<Text id="153">Fine-Reader (http://www.finereader.com/)</Text>
+</Bullet>
+</BulletList>
+<Text id="154">ÐÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ, Ð²ÐºÐ»ÑÑÐ°Ñ Ð¿ÐµÑÐµÑÐµÐœÑ ÐŽÐžÑÑÑÐžÐ±ÑÑÑÐµÑÐŸÐ², ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÐœÐ° ÐÐœÑÐµÑÐœÐµÑ ÑÐ°Ð¹ÑÐµ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÐµÐ»ÐµÐ¹. Ð¡ÑÐµÐŽÐž ÐœÐžÑ
+, Ð¿ÐŸ ÐŸÐ¿ÑÑÑ Ð°Ð²ÑÐŸÑÐ°, ÑÐ°ÐŒÑÐµ Ð»ÐµÐ³ÐºÐžÐµ Ð² ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž Fine-Reader Ðž Omnipage. Fine-Reader ÑÐ²Ð»ÑÐµÑÑÑ ÑÐ°ÐŒÑÐŒ ÐŽÐµÑÐµÐ²ÑÐŒ Ðž ÑÑÐŸÐžÑ Ð²ÑÐµÐ³ÐŸ $100. ÐÐœ Ð¿ÑÐµÐŽÐ»Ð°Ð³Ð°ÐµÑ Ð³ÐžÐ±ÐºÐžÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž Ðž ÐœÐ°ÐžÐ±ÐŸÐ»ÑÑÐµÐµ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ ÑÐ°Ð·ÐœÑÑ
+ ÑÐ·ÑÐºÐŸÐ².</Text>
+<Text id="155">ÐÐ°ÐŒ ÐœÑÐ¶ÐœÐŸ ÑÐµÑÐžÑÑ, Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑÑ Ð»Ðž ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ðž ÐÐ Ð¡ ÑÐ²ÐŸÐžÐŒÐž ÑÑÐžÐ»ÐžÑÐŒÐž ÐžÐ»Ðž Ð¿ÐŸÑÑÑÐžÑÑ ÑÑÐŸ ÐºÐŸÐŒÐ¿Ð°ÐœÐžÐž, ÑÐ¿ÐµÑÐžÐ°Ð»ÐžÐ·ÐžÑÑÑÑÐµÐ¹ÑÑ Ð² ÑÑÐŸÐ¹ ÑÑÐµÑÐµ. ÐÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ Ð¿ÑÐŸÐ²ÐµÑÑÐž ÑÑÐŸÑ Ð¿ÑÐŸÑÐµÑÑ ÑÐ²ÐŸÐžÐŒÐž ÑÑÐžÐ»ÐžÑÐŒÐž, Ð²Ð°ÐŒ ÐœÑÐ¶ÐµÐœ ÑÐºÐ°ÐœÐµÑ, Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ ÐÐ Ð¡, ÑÐ°Ð·Ð²ÐžÑÐžÐµ ÐœÐ°Ð²ÑÐºÐŸÐ² Ð² ÑÐ°Ð±ÐŸÑÐµ Ñ ÐÐ Ð¡, ÑÐ°Ð±ÐŸÑÐœÐžÐºÐž, ÐœÐ°ÑÐµÐ»ÐµÐœÐœÑÐµ ÐœÐ° ÐºÐ°ÑÐµÑÑÐ²ÐŸ ÐžÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ ÑÐ°Ð±ÐŸÑÑ.</Text>
+<Section id="the_ocr_process">
+<Title>
+<Text id="156">ÐÑÐŸÑÐµÑÑ ÐÐ Ð¡</Text>
+</Title>
+<Content>
+<Text id="157">ÐÑÐŸÑÐµÑÑ ÐÐ Ð¡ ÑÐ°Ð·Ð»ÐžÑÐ°ÐµÑÑÑ Ð²ÐŸ Ð²ÑÐµÑ
+ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ°Ñ
+ ÐÐ Ð¡, Ðž Ð»ÑÐ±Ð°Ñ ÐžÐ· Ð²ÑÐ±ÑÐ°ÐœÐœÑÑ
+ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒ ÑÑÐµÐ±ÑÐµÑ ÐŽÐŸÐ±ÑÐŸÑÐœÐŸÐ³ÐŸ ÐžÐ·ÑÑÐµÐœÐžÑ. ÐÐœÑÑÑÑÐºÑÐžÑ Ð¿ÐŸ ÑÐºÑÐ¿Ð»ÑÐ°ÑÐ°ÑÐžÐž ÐºÐ°Ð¶ÐŽÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐŸÐ±ÑÑÑÐœÑÐµÑ ÑÑÐŸÑ Ð¿ÑÐŸÑÐµÑÑ Ð² ÐŽÐµÑÐ°Ð»ÑÑ
+. Ð§ÐµÑÑÑÐµ Ð¿ÑÐœÐºÑÐ° Ð¿ÑÐŸÑÐµÑÑÐ° ÐÐ Ð¡ Ð·Ð°ÑÐ»ÑÐ¶ÐžÐ²Ð°ÑÑ ÐŸÑÐŸÐ±ÐŸÐ³ÐŸ Ð²ÐœÐžÐŒÐ°ÐœÐžÑ: ÐºÐŸÐœÑÑÐŸÐ»Ñ ÐºÐ°ÑÐµÑÑÐ²Ð°, ÑÐ°Ð±Ð»ÐžÑÑ, ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ Ðž ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐžÐ¹ ÐŒÐ°ÑÐµÑÐžÐ°Ð» - ÑÐ°ÐºÐŸÐ¹, ÐºÐ°Ðº ÑÐŸÑÐŒÑÐ»Ñ, ÐžÐœÐŸÑÑÑÐ°ÐœÐœÑÐ¹ ÑÐ·ÑÐº Ðž Ñ.ÐŽ.</Text>
+<Subsection id="quality_control_1">
+<Title>
+<Text id="158">ÐÐŸÐœÑÑÐŸÐ»Ñ ÐºÐ°ÑÐµÑÑÐ²Ð°</Text>
+</Title>
+<Content>
+<Text id="159">ÐÑ ÑÐœÐŸÐ²Ð° Ðž ÑÐœÐŸÐ²Ð° Ñ
+ÐŸÑÐžÐŒ Ð·Ð°ÐŸÑÑÑÐžÑÑ Ð²Ð°ÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ ÐœÐ° ÐºÐŸÐœÑÑÐŸÐ»Ðµ ÐºÐ°ÑÐµÑÑÐ²Ð°. ÐÐŸÐœÑÑÐŸÐ»Ñ ÐºÐ°ÑÐµÑÑÐ²Ð° Ð»ÑÑÑÐµ Ð¿ÐŸÑÑÑÐ°ÑÑ Ð»ÑÐŽÑÐŒ, ÑÐµÐ¹ ÑÐŸÐŽÐœÐŸÐ¹ ÑÐ·ÑÐº ÑÐ²Ð»ÑÐµÑÑÑ ÑÐ°ÐºÐžÐŒ, ÐœÐ° ÐºÐŸÑÐŸÑÐŸÐŒ ÐœÐ°Ð¿ÐžÑÐ°Ðœ ÐŽÐŸÐºÑÐŒÐµÐœÑ, ÐžÐ»Ðž ÐŸÐœÐž Ð²Ð»Ð°ÐŽÐµÑÑ ÑÑÐžÐŒ ÑÐ·ÑÐºÐŸÐŒ Ð² ÑÐŸÐ²ÐµÑÑÐµÐœÑÑÐ²Ðµ. ÐÑÑÑÐžÐµ ÑÐ°Ð±ÐŸÑÐœÐžÐºÐž - ÑÑÐŸ ÑÐºÐŸÐ»ÑÐœÐžÐºÐž Ðž ÑÑÑÐŽÐµÐœÑÑ, Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ ÐŒÐŸÐ»ÐŸÐŽÑÐµ Ð»ÑÐŽÐž Ð±ÐŸÐ»ÐµÐµ Ð²ÐœÐžÐŒÐ°ÑÐµÐ»ÑÐœÑ Ðž Ð±ÐŸÐ»ÐµÐµ ÑÐºÐŸÐœÑÐµÐœÑÑÐžÑÐŸÐ²Ð°ÐœÑ Ð¿ÑÐž ÑÐ°ÐºÐŸÐŒ Ð²ÐžÐŽÐµ ÑÐ°Ð±ÐŸÑÑ, ÐœÐµÐ¶ÐµÐ»Ðž Ð¿ÐŸÐ¶ÐžÐ»ÑÐµ Ð»ÑÐŽÐž. </Text>
+<Text id="160">ÐÐ±ÑÑÐœÐŸ ÑÑÑÐµÑÑÐ²ÑÐµÑ ÑÐµÑÑÑÐµ ÑÑÐ°Ð¿Ð° ÐºÐŸÐœÑÑÐŸÐ»Ñ ÐºÐ°ÑÐµÑÑÐ²Ð°.</Text>
+<Text id="161">ÐÐµÑÐ²ÑÐ¹ Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑÑÑ ÐŸÐŽÐœÐŸÐ²ÑÐµÐŒÐµÐœÐœÐŸ Ñ Ð¿ÑÐŸÑÐµÑÑÐŸÐŒ ÐÐ Ð¡. ÐÐ°Ð¶ÐŽÐ°Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐÐ Ð¡ ÐžÐŒÐµÐµÑ Ð²ÑÑÑÐŸÐµÐœÐœÑÑ Ð¿ÑÐŸÐ²ÐµÑÐºÑ ÐŸÑÑÐŸÐ³ÑÐ°ÑÐžÐž, ÐºÐŸÑÐŸÑÐ°Ñ Ð¿ÐŸÐŽÑÐµÑÐºÐžÐ²Ð°ÐµÑ Ð¿ÐŸÐŽÐŸÐ·ÑÐžÑÐµÐ»ÑÐœÑÐµ Ð¿ÐŸ ÐœÐ°Ð¿ÐžÑÐ°ÐœÐžÑ ÑÐ»ÐŸÐ²Ð°.</Text>
+<Text id="162">ÐÑÐŸÑÐŸÐ¹ ÑÑÐ°Ð¿ - ÐŸÐ±ÑÐ°Ñ Ð¿ÑÐŸÐ²ÐµÑÐºÐ° ÑÐµÐºÑÑÐ° Ð¿ÐŸÑÐ»Ðµ Ð·Ð°Ð²ÐµÑÑÐµÐœÐžÑ Ð¿ÑÐŸÑÐµÑÑÐ° ÐÐ Ð¡. ÐÑÐµÐœÑ ÑÐ°ÑÑÐŸ Ð²ÑÑÑÐµÑÐ°ÑÑÑÑ ÑÐ°ÐºÐžÐµ ÐŸÑÐžÐ±ÐºÐž, ÐºÐ°Ðº Ð¿ÑÐŸÐ¿ÑÑÐº ÑÑÑÐ°ÐœÐžÑ, Ð°Ð±Ð·Ð°ÑÐµÐ², ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹ Ð³Ð»Ð°Ð² Ðž Ñ.ÐŽ. ÐÑÐ¶ÐœÐŸ Ð¿ÑÐŸÐ²ÐµÑÑÐž ÐŸÐ±ÑÐžÐ¹ ÐŸÐ±Ð·ÐŸÑ ÐœÐ° ÐœÐ°Ð»ÐžÑÐžÐµ Ð²ÑÐµÑ
+ ÑÑÑÐ°ÐœÐžÑ Ðž Ð¿ÑÐŸÐ²ÐµÑÐºÑ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐŸÐ², ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹ Ð³Ð»Ð°Ð², Ð°Ð±Ð·Ð°ÑÐµÐ² Ðž ÑÐ°Ð±Ð»ÐžÑ.</Text>
+<Text id="163">Ð¢ÑÐµÑÐžÐ¹ ÑÑÐ°Ð¿ - Ð¿ÑÐŸÐ²ÐµÑÐºÐ° ÐŸÑÑÐŸÐ³ÑÐ°ÑÐžÐž Ð² Microsoft Word. Ð Word, ÐºÐ°Ðº Ð¿ÑÐ°Ð²ÐžÐ»ÐŸ, ÐŸÑÑÐŸÐ³ÑÐ°ÑÐžÑÐµÑÐºÐžÐµ ÑÐ»ÐŸÐ²Ð°ÑÐž Ð±ÐŸÐ»ÐµÐµ ÐžÑÑÐµÑÐ¿ÑÐ²Ð°ÑÑÐžÐµ, ÑÐµÐŒ Ð² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ°Ñ
+ ÐÐ Ð¡. ÐÑÑÐµÐŒ ÐžÐŒÐ¿ÐŸÑÑÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ð² Word Ðž Ð¿ÑÐŸÐ²ÐµÐŽÐµÐœÐžÑ ÐŸÑÑÐŸÐ³ÑÐ°ÑÐžÑÐµÑÐºÐŸÐ¹ Ð¿ÑÐŸÐ²ÐµÑÐºÐž ÐŒÐŸÐ¶ÐœÐŸ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ Ðž ÐžÑÐ¿ÑÐ°Ð²ÐžÑÑ Ð±ÐŸÐ»ÑÑÐµÐµ ÑÐžÑÐ»ÐŸ ÐŸÑÐžÐ±ÐŸÐº. ÐÐµ Ð·Ð°Ð±ÑÐŽÑÑÐµ Ð²Ð²ÐµÑÑÐž Ð² Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ Ð¿ÑÐŸÐ²ÐµÑÐºÐž ÐºÐŸÐŒÐ¿Ð»ÐµÐºÑÐœÑÐµ ÑÐ»ÐŸÐ²Ð° Ðž ÑÐµÑÐŒÐžÐœÑ, ÐºÐŸÑÐŸÑÑÐµ Ð¿ÑÐžÑÑÑÐž ÑÐ°ÐºÐŸÐ³ÐŸ ÑÐŸÐŽÐ° ÑÐµÐºÑÑÐ°ÐŒ, ÐœÐ° ÐœÐ°Ð»ÐžÑÐžÐµ Ð² ÐœÐžÑ
+ ÐŸÑÐžÐ±ÐŸÐº.</Text>
+<Text id="164">Ð ÐœÐ°ÐºÐŸÐœÐµÑ, ÐœÐ° ÑÐµÑÐ²ÐµÑÑÐŸÐŒ ÑÑÐ°Ð¿Ðµ Ð·Ð°Ð²ÐµÑÑÐµÐœÐœÑÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ ÐŽÐŸÐ»Ð¶ÐµÐœ Ð±ÑÑÑ Ð¿ÑÐŸÐ²ÐµÑÐµÐœ ÐŽÑÑÐ³ÐžÐŒ ÑÐµÐ»ÐŸÐ²ÐµÐºÐŸÐŒ, Ð·Ð°ÐœÐžÐŒÐ°ÑÑÐžÐŒÑÑ ÑÐŸÑÑÐ°Ð²Ð»ÐµÐœÐžÐµÐŒ Ð¿ÐŸÐ»ÐœÐŸÐ¹ ÐºÐœÐžÐ³Ðž, Ð¿ÑÐŸÐ²ÐµÑÑÑÑÐžÐŒ ÐŸÑÑÐŸÐ³ÑÐ°ÑÐžÑ, ÐœÐ°Ð»ÐžÑÐžÐµ Ð¿ÑÐŸÐ±Ð»ÐµÐŒ Ñ ÑÐ°Ð±Ð»ÐžÑÐ°ÐŒÐž, ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑÐŒÐž Ðž ÐŸÐ±ÑÐžÐŒ Ð²ÐžÐŽÐŸÐŒ Ð·Ð°Ð²ÐµÑÑÐµÐœÐœÐŸÐ³ÐŸ ÑÐµÐºÑÑÐ°. Ð¢ÐŸÐ»ÑÐºÐŸ Ð¿ÐŸÑÐ»Ðµ ÑÑÐŸÐ³ÐŸ ÑÐ»ÐµÐºÑÑÐŸÐœÐœÑÑ ÐºÐœÐžÐ³Ñ ÐŒÐŸÐ¶ÐœÐŸ ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÑÑÑ.</Text>
+</Content>
+</Subsection>
+<Subsection id="tables">
+<Title>
+<Text id="165">Ð¢Ð°Ð±Ð»ÐžÑÑ</Text>
+</Title>
+<Content>
+<Text id="166">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐÐ Ð¡ Ð¿Ð»ÐŸÑ
+ÐŸ ÑÐ¿ÑÐ°Ð²Ð»ÑÑÑÑÑ Ñ ÑÐ°Ð±Ð»ÐžÑÐ°ÐŒÐž. ÐÐŸÐ»ÐµÐµ ÑÐŸÐ³ÐŸ, ÑÐ°Ð±Ð»ÐžÑÑ ÑÑÑÐŽÐœÐŸ Ð¿ÑÐŸÐ²ÐµÑÑÑÑ. ÐÐœÐž ÑÐŸÐŽÐµÑÐ¶Ð°Ñ ÐŒÐœÐŸÐ³ÐŸ ÑÐžÑÑ Ðž ÑÐ°ÐºÐžÐµ ÑÐžÐŒÐ²ÐŸÐ»Ñ, ÐºÐ°Ðº ÑÐŸÑÐºÐž, Ð·Ð°Ð¿ÑÑÑÐµ, ÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸ ÐŸÑÐžÐ±ÐºÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð¿ÐµÑÐµÐœÐµÑÐµÐœÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐŸÐ¹ Ð² ÐŽÑÑÐ³ÐŸÐ¹ ÑÑÐŸÐ»Ð±ÐµÑ ÐžÐ»Ðž ÑÑÑÐŸÐºÑ. ÐÐŸÑÑÐŸÐŒÑ Ð¿ÑÐž Ð¿ÑÐŸÐ²ÐµÑÐºÐµ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ, ÑÐ¿ÐŸÑÐœÐ°Ñ ÑÐ°Ð±ÐŸÑÐ°, ÑÐµÑÐ¿ÐµÐœÐžÐµ Ðž ÐºÐŸÐœÑÑÐŸÐ»Ñ ÐºÐ°ÑÐµÑÑÐ²Ð°. Ð¡ ÐœÐžÐŒÐž ÐŒÐŸÐ¶ÐœÐŸ ÑÐ°Ð±ÐŸÑÐ°ÑÑ ÑÑÐµÐŒÑ ÐŸÐ±ÑÑÐœÑÐŒÐž ÑÐ¿ÐŸÑÐŸÐ±Ð°ÐŒÐž.</Text>
+<Text id="167">ÐÐµÑÐ²ÑÐ¹ ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸ ÐŒÐŸÐ¶ÐœÐŸ ÑÐ°Ð±ÐŸÑÐ°ÑÑ Ñ ÑÐ°Ð±Ð»ÐžÑÐ°ÐŒÐž ÐºÐ°Ðº Ñ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµÐŒ. Ð­ÑÐŸ Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð² ÑÐµÐ±Ñ ÑÐµÑÐœÐŸ-Ð±ÐµÐ»ÐŸÐµ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐ¹ ÑÐ°Ð±Ð»ÐžÑ Ðž Ð¿ÐµÑÐµÐœÐŸÑ ÐžÑ
+ Ð² ÑÑÐŸÐ¹ ÑÐŸÑÐŒÐµ Ð² ÐœÑÐ¶ÐœÐŸÐµ ÐŒÐµÑÑÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. Ð­ÑÐŸ ÑÐ°ÐŒÑÐ¹ Ð»ÐµÐ³ÐºÐžÐ¹ Ð¿ÑÑÑ. ÐÐµ Ð±ÑÐŽÐµÑ ÐœÐžÐºÐ°ÐºÐžÑ
+ ÐŸÑÐžÐ±ÐŸÐº, Ðž Ð²ÑÐµ Ð¿ÐŸÑÑÐ°ÑÐµÐœÐœÐŸÐµ Ð²ÑÐµÐŒÑ ÑÐ¹ÐŽÐµÑ ÑÐŸÐ»ÑÐºÐŸ ÐœÐ° ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ. ÐÐŽÐœÐ°ÐºÐŸ, Ð¿ÐŸÐ»ÑÑÐµÐœÐœÑÐµ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ ÑÐ°Ð±Ð»ÐžÑ Ð±ÑÐŽÑÑ Ð·Ð°ÐœÐžÐŒÐ°ÑÑ Ð±ÐŸÐ»ÑÑÐµ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐœÐŸÐ¹ Ð¿Ð°ÐŒÑÑÐž. Ð¢Ð°ÐºÐ¶Ðµ ÑÐ°Ð·ÑÐµÑÐµÐœÐžÐµ ÑÐºÑÐ°ÐœÐ° ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐ° ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐœÐµÐŽÐŸÑÑÐ°ÑÐŸÑÐœÑÐŒ Ð¿ÑÐž Ð²ÑÐ²ÐŸÐŽÐµ ÐœÐ° ÑÐºÑÐ°Ðœ Ð±ÐŸÐ»ÑÑÐžÑ
+ ÑÐ°Ð±Ð»ÐžÑ. ÐÑÐ»Ðž Ð²Ñ Ð·Ð°Ñ
+ÐŸÑÐžÑÐµ ÑÐ°Ð·ÐŒÐµÑÑÐžÑÑ Ð²ÑÑ ÑÐ°Ð±Ð»ÐžÑÑ ÐœÐ° ÑÐºÑÐ°ÐœÐµ, ÑÐŸ ÑÐ°Ð·ÑÐµÑÐµÐœÐžÐµ ÑÐºÑÐ°ÐœÐ° ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐœÐµÐŽÐŸÑÑÐ°ÑÐŸÑÐœÑÐŒ. ÐÑÐ»Ðž ÑÐ°Ð±Ð»ÐžÑÐ° ÑÐ»ÐžÑÐºÐŸÐŒ ÑÐžÑÐŸÐºÐ°, ÑÐŸ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð¿ÑÐžÐŽÐµÑÑÑ Ð¿ÑÐŸÑÐŒÐ°ÑÑÐžÐ²Ð°ÑÑ Ð²ÑÐµ ÐºÐŸÐ»ÐŸÐœÐºÐž Ðž ÑÑÑÐŸÐºÐž, ÐœÐµ Ð²ÐžÐŽÑ ÐžÑ
+ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹.</Text>
+<Text id="168">ÐÑÐŸÑÐŸÐ¹ ÐŒÐµÑÐŸÐŽ ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐ·ÐŽÐ°ÐœÐžÐž ÑÐ°Ð±Ð»ÐžÑ Ð²ÑÑÑÐœÑÑ, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÐ² ÐœÑÐ¶ÐœÐŸÐµ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ ÑÑÑÐŸÐº Ðž ÑÑÐŸÐ»Ð±ÑÐŸÐ², Ðž Ð²ÑÑÑÐœÑÑ Ð²Ð¿ÐµÑÐ°ÑÐ°ÑÑ Ð² ÐœÐžÑ
+ ÐŽÐ°ÐœÐœÑÐµ.</Text>
+<Text id="169">Ð¢ÑÐµÑÐžÐ¹ ÑÐ¿ÐŸÑÐŸÐ± Ð·Ð°ÐºÐ»ÑÑÐ°ÐµÑÑÑ Ð² ÑÐŸÐŒ, ÑÑÐŸ ÑÐ°Ð±Ð»ÐžÑÑ ÐŒÐŸÐ¶ÐœÐŸ Ð¿ÑÐŸÐ²ÐµÑÑÐž ÑÐµÑÐµÐ· ÐÐ Ð¡. Ð­ÑÐŸ ÑÐŸÑ
+ÑÐ°ÐœÐžÑ Ð±ÐŸÐ»ÑÑÐµ Ð²ÑÐµÐŒÐµÐœÐž, ÑÐµÐŒ Ð²ÑÐŸÑÐŸÐ¹ ÐŒÐµÑÐŸÐŽ, ÐœÐŸ Ð¿ÐŸÑÐµÐœÑÐžÐ°Ð»ÑÐœÐŸÐµ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ ÐŸÑÐžÐ±ÐŸÐº ÑÐ²ÐµÐ»ÐžÑÐžÑÑÑ. ÐÐµÐºÐŸÑÐŸÑÑÐµ ÐºÐŸÐ»ÐŸÐœÐºÐž ÐžÐœÐŸÐ³ÐŽÐ° ÑÐ»ÐžÐ²Ð°ÑÑÑÑ, Ð° ÐžÐœÐŸÐ³ÐŽÐ° Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐœÐµ ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°ÐµÑ ÑÐŸÑÐºÐž Ðž Ð·Ð°Ð¿ÑÑÑÐµ.</Text>
+</Content>
+</Subsection>
+<Subsection id="images">
+<Title>
+<Text id="170">ÐÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ</Text>
+</Title>
+<Content>
+<Text id="171">ÐÐŸÐºÑÐŒÐµÐœÑÑ ÑÐŸÐŽÐµÑÐ¶Ð°Ñ ÑÑÐž ÐŸÑÐœÐŸÐ²ÐœÑÑ
+ Ð²ÐžÐŽÐ° ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐ¹:</Text>
+<BulletList>
+<Bullet>
+<Text id="172">Ð§ÐµÑÐœÐŸ- Ð±ÐµÐ»ÑÐµ ÑÐžÑÑÐœÐºÐž</Text>
+</Bullet>
+<Bullet>
+<Text id="173">Ð§ÐµÑÐœÐŸ-Ð±ÐµÐ»ÑÐµ ÑÐŸÑÐŸÐ³ÑÐ°ÑÐžÐž</Text>
+</Bullet>
+<Bullet>
+<Text id="174">ÐŠÐ²ÐµÑÐœÑÐµ ÑÐŸÑÐŸÐ³ÑÐ°ÑÐžÐž</Text>
+</Bullet>
+</BulletList>
+<Text id="175">Ð§ÐµÑÐœÐŸ-Ð±ÐµÐ»ÑÐµ ÑÐžÑÑÐœÐºÐž ÑÐ»ÐµÐŽÑÐµÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑ Ð² ÑÑÑÐžÑ
+ÐŸÐ²ÐŸÐŒ ÑÐµÐ¶ÐžÐŒÐµ (line art mode) Ðž Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÐŸ ÑÐŸÑ
+ÑÐ°ÐœÑÑÑ Ð² Ð²ÐžÐŽÐµ ÑÐ°Ð¹Ð»ÐŸÐ² GIF ÐžÐ»Ðž PNG. Ð§ÐµÑÐœÐŸÐ±ÐµÐ»ÑÐµ ÑÐŸÑÐŸÐ³ÑÐ°ÑÐžÐž ÑÐ»ÐµÐŽÑÐµÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑ Ð² ÑÐµÐ¶ÐžÐŒÐµ grayscale Ðž ÑÐŸÑ
+ÑÐ°ÐœÑÑÑ ÐºÐ°Ðº ÑÐ°Ð¹Ð»Ñ GIF ÐžÐ»Ðž JPEG. ÐŠÐ²ÐµÑÐœÑÐµ ÑÐŸÑÐŸÐ³ÑÐ°ÑÐžÐž ÐœÑÐ¶ÐœÐŸ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑ Ð² ÑÐ²ÐµÑÐœÐŸÐŒ ÑÐµÐ¶ÐžÐŒÐµ Ðž ÑÐŸÑ
+ÑÐ°ÐœÑÑÑ ÐºÐ°Ðº ÑÐ°Ð¹Ð»Ñ JPEG. ÐÐ±ÑÑÐœÐŸ ÑÐ°Ð¹Ð» JPEG ÑÑÐµÐŽÐœÐµÐ³ÐŸ ÐºÐ°ÑÐµÑÑÐ²Ð° ÐžÐŒÐµÐµÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÐµ ÑÐ°Ð·ÑÐµÑÐµÐœÐžÐµ.</Text>
+<Text id="176">ÐÐœÐŸÐ³ÐžÐµ ÑÐžÑÑÐœÐºÐž Ð·Ð°ÐœÐžÐŒÐ°ÑÑ ÐœÐ°ÐžÐ±ÐŸÐ»ÑÑÐµÐµ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²ÐŸ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐœÐŸÐ¹ ÐœÐ° Ð¶ÐµÑÑÐºÐŸÐŒ ÐŽÐžÑÐºÐµ ÐžÐ»Ðž ÐœÐ° CD-ROM. ÐÐŸÑÑÐŸÐŒÑ ÐŸÑÐµÐœÑ Ð²Ð°Ð¶ÐœÐŸ ÐŸÐ¿ÑÐžÐŒÐžÐ·ÐžÑÐŸÐ²Ð°ÑÑ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ, ÑÐŽÐµÐ»Ð°Ð² ÐµÐ³ÐŸ ÐºÐ°Ðº ÐŒÐŸÐ¶ÐœÐŸ ÑÐ°Ð·Ð±ÐŸÑÑÐžÐ²ÐµÐµ Ðž ÑÐµÑÑÐµ, Ð² ÑÐŸ Ð¶Ðµ Ð²ÑÐµÐŒÑ ÑÐŒÐµÐœÑÑÐ°Ñ ÐµÐ³ÐŸ ÑÐ°Ð·ÐŒÐµÑ. ÐÐ»Ñ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐžÑ ÐŒÐµÑÑÐ° Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐžÑÐµÐ»ÑÐœÐµÐµ ÐœÐµ Ð²ÐºÐ»ÑÑÐ°ÑÑ ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ, ÐœÐµ ÐŸÑÐœÐŸÑÑÑÐžÐµÑÑ Ðº ÑÐµÐºÑÑÑ.</Text>
+<Text id="177">Ð ÐžÑÑÐœÐºÐž ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÑ ÐºÐ°Ð¶ÐŽÑÐ¹ Ð¿ÐŸ ÐŸÑÐŽÐµÐ»ÑÐœÐŸÑÑÐž. ÐÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÐŒ ÐœÐ°Ð·ÑÐ²Ð°ÑÑ ÑÑÐž ÑÐžÑÑÐœÐºÐž Ð¿ÐµÑÐ²ÑÐŒÐž 6 Ð±ÑÐºÐ²Ð°ÐŒÐž ÐœÐ°Ð·Ð²Ð°ÐœÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, Ð° ÐŸÑÑÐ°Ð»ÑÐœÑÐŒÐž ÑÐžÑÑÐ°ÐŒÐž ÐœÐŸÐŒÐµÑ ÑÑÑÐ°ÐœÐžÑÑ, ÐœÐ° ÐºÐŸÑÐŸÑÐŸÐ¹ ÐŸÐœ ÑÐ°ÑÐ¿ÐŸÐ»Ð°Ð³Ð°ÐµÑÑÑ. Ð ÐºÐ°ÑÐµÑÑÐ²Ðµ Ð°Ð»ÑÑÐµÑÐœÐ°ÑÐžÐ²Ñ, Ð¿ÑÐµÐŽÐ¿ÐŸÐ»Ð°Ð³Ð°Ñ, ÑÑÐŸ ÐºÐ°Ð¶ÐŽÑÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² ÑÐ²ÐŸÐµÐ¹ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž, ÐŒÐŸÐ¶ÐœÐŸ Ð¿ÑÐŸÑÑÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð±ÑÐºÐ²Ñ, Ð¿ÐŸÑÐ»Ðµ ÑÐµÐ³ÐŸ ÐžÐŽÐµÑ ÑÑÑÐ°ÐœÐžÑÐ°, ÐœÐ° ÐºÐŸÑÐŸÑÐŸÐ¹ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÑÑÐŸ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ. ÐÑÐ»Ðž ÐœÐ° ÐŸÐŽÐœÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐµ ÑÑÑÐµÑÑÐ²ÑÑÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÐžÑÑÐœÐºÐŸÐ², ÑÐŸ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐŽÑÑÐ³ÐžÐµ Ð±ÑÐºÐ²Ñ ÐŽÐ»Ñ ÐžÑ
+ ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÐžÑ. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÐµÑÐ»Ðž ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ Ð² ÑÐŸÑÐŒÐ°ÑÐµ JPEG Ð¿ÐŸÑÐ²ÐžÑÑÑ ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ 36 Ð¿ÑÐ±Ð»ÐžÐºÐ°ÑÐžÐžÂ <i>u7548Ðµ</i>, ÑÐŸ ÐŸÐœÐŸ Ð±ÑÐŽÐµÑ Ð¿ÐŸÐŒÐµÑÐµÐœÐŸ Ð² ÑÐ°Ð¹Ð» ÐœÐ°Ð·Ð²Ð°ÐœÐœÑÐ¹Â <i>u7548e36.jpg</i>Â ÐžÐ»ÐžÂ <i>p36.jpg</i>.</Text>
+<Text id="178">ÐÐŸÑÐ»Ðµ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÑ, Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÑÐ¿ÐµÑÐžÐ°Ð»ÐžÐ·ÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐŽÐ»Ñ ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÑ ÑÐ°Ð·ÐŒÐµÑÐ° Ðž ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÑ ÑÐžÑÑÐœÐºÐ°.</Text>
+</Content>
+</Subsection>
+<Subsection id="specialized_material">
+<Title>
+<Text id="179">Ð¡Ð¿ÐµÑÐžÐ°Ð»ÐžÐ·ÐžÑÐŸÐ²Ð°ÐœÐœÑÐ¹ ÐŒÐ°ÑÐµÑÐžÐ°Ð»</Text>
+</Title>
+<Content>
+<Text id="180">ÐÐœÐŸÐ³ÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÑÐŸÐŽÐµÑÐ¶Ð°Ñ ÑÐµÑ
+ÐœÐžÑÐµÑÐºÐžÐµ ÑÐµÑÐŒÐžÐœÑ, ÑÐ°ÐºÐžÐµ ÐºÐ°Ðº ÑÐ¿ÐµÑÐžÐ°Ð»ÐžÐ·ÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ ÑÐžÐŒÐ²ÐŸÐ»Ñ, ÑÐŸÑÐŒÑÐ»Ñ Ðž ÐœÐµÑÐ°Ð·Ð±ÐŸÑÑÐžÐ²ÑÐµ ÑÑÑÐ°ÐœÐžÑÑ. Ð­ÑÐž ÑÑÑÐŽÐœÐŸ ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°Ð²Ð°ÐµÐŒÑÐµ ÑÐžÐŒÐ²ÐŸÐ»Ñ, ÐºÐ°Ðº Ð¿ÑÐ°Ð²ÐžÐ»ÐŸ, ÑÐ²ÑÐ·Ð°ÐœÑ Ñ ÑÐ°Ð·ÐœÑÐŒÐž ÑÐ·ÑÐ¿ÑÐ°ÐŒÐž. ÐÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ð²Ð°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð²ÑÐ±ÑÐ°ÑÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐ¹ ÑÐ·ÑÐº Ð² ÐŸÐ¿ÑÐžÑÑ
+ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐÐ Ð¡. Ð€ÐŸÑÐŒÑÐ»Ñ ÐœÑÐ¶ÐœÐŸ Ð±ÑÐŽÐµÑ Ð¿ÐµÑÐµÐ¿ÐµÑÐ°ÑÑÐ²Ð°ÑÑ Ð²ÑÑÑÐœÑÑ, ÑÐ°Ðº ÐºÐ°Ðº Ð²ÐŸ ÐŒÐœÐŸÐ³ÐžÑ
+ ÑÐ»ÑÑÐ°ÑÑ
+ ÐÐ Ð¡ ÐžÑ
+ ÐœÐµ ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°ÐµÑ, Ðž ÐžÑ
+ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð²Ð²ÐŸÐŽÐžÑÑ Ð² Word. ÐÐµÑÐ°Ð·Ð±ÐŸÑÑÐžÐ²ÑÐµ ÑÑÑÐ°ÐœÐžÑÑ ÐŒÐŸÐ³ÑÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑ ÐŒÐ°ÑÐµÑÐžÐ°Ð», ÐºÐŸÑÐŸÑÑÐ¹ ÑÑÑÐŽÐœÐŸ Ð²ÐŸÑÐ¿ÑÐŸÐžÐ·Ð²ÐµÑÑÐž ÐžÐ·-Ð·Ð° ÐºÐ°ÐºÐžÑ
+-Ð»ÐžÐ±ÐŸ Ð¿ÐŸÐ²ÑÐµÐ¶ÐŽÐµÐœÐžÐ¹ Ðž Ñ.ÐŽ., Ð¿ÐŸÑÑÐŸÐŒÑ ÑÐ°ÐºÐžÐµ ÐŒÐµÑÑÐ° Ð¿ÑÐžÐŽÐµÑÑÑ Ð¿ÐµÑÐµÐ¿ÐµÑÐ°ÑÑÐ²Ð°ÑÑ.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="productivity_and_resources_1">
+<Title>
+<Text id="181">ÐÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÐµÐ»ÑÐœÐŸÑÑÑ Ðž ÐŽÐŸÑÑÑÐ¿ÐœÑÐµ ÑÐµÑÑÑÑÑ</Text>
+</Title>
+<Content>
+<Text id="182">ÐÐ°Ðº Ð±ÑÐ»ÐŸ ÑÐ¿ÐŸÐŒÑÐœÑÑÐŸ ÑÐ°ÐœÐµÐµ, Ð²Ñ ÐœÐµ ÐŽÐŸÐ»Ð¶ÐœÑ ÐœÐµÐŽÐŸÐŸÑÐµÐœÐžÐ²Ð°ÑÑ ÑÐ»ÐŸÐ¶ÐœÐŸÑÑÑ Ð¿ÑÐŸÑÐµÑÑÐ° ÐÐ Ð¡. Ð¥ÐŸÑÑ Ð¿ÑÐŸÑÐµÑÑ ÐÐ Ð¡ ÐœÑÐ¶ÐœÐŸ ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°ÑÑ ÐŸÑÐŽÐµÐ»ÑÐœÐŸ ÐŸÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ, ÐŽÐ»Ñ ÐµÐ³ÐŸ ÐŸÑÐµÐœÐºÐž Ð¿ÑÐžÐŒÐµÐœÑÑÑÑÑ ÑÑ
+ÐŸÐ¶ÐžÐµ Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐžÐµ ÑÐµÐºÐŸÐŒÐµÐœÐŽÐ°ÑÐžÐž: ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÑÐµ ÑÐµÑÑÑÑÑ ÐŽÐ»Ñ Ð¿ÑÐžÐŸÐ±ÑÐµÑÐµÐœÐžÑ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐŸÐ², ÐŽÐŸÑÑÑÐ¿ÐœÐŸÑÑÑ ÑÐ°Ð±ÐŸÑÐµÐ¹ ÑÐžÐ»Ñ Ðž ÑÐŒÐµÐœÐžÐµ ÑÑÐºÐŸÐ²ÐŸÐŽÐžÑÑ; Ð·Ð°ÑÐ¿Ð»Ð°ÑÐ°; ÐŸÐ±ÑÐµÐµ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ ÑÑÑÐ°ÐœÐžÑ, ÐœÑÐ¶ÐŽÐ°ÑÑÐžÑ
+ÑÑ Ð² ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐµ; ÐŒÐŸÐ¶ÐœÐŸ Ð»Ðž Ð¿ÐµÑÐµÐŽÐ°Ð²Ð°ÑÑ ÑÑÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÑÑÐµÑÑÐžÐŒ Ð»ÐžÑÐ°ÐŒ.</Text>
+<Text id="183">Ð ÑÐ»ÐµÐŽÑÑÑÐžÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŒÑ Ð¿ÐŸÐŽÐµÐ»ÐžÐŒÑÑ Ñ Ð²Ð°ÐŒÐž ÐœÐ°ÑÐžÐŒ ÐŸÐ¿ÑÑÐŸÐŒ ÑÐ°Ð±ÐŸÑÑ Ñ ÐÐ Ð¡ Ð² ÑÐ°ÐºÐžÑ
+ ÑÑÑÐ°ÐœÐ°Ñ
+, ÐºÐ°Ðº ÐÐµÐ»ÑÐ³ÐžÑ, ÐÐœÐŽÐžÑ Ðž Ð ÑÐŒÑÐœÐžÑ. ÐÑÐµ ÐžÑÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐžÑ, Ð¿ÐŸÐŽÑÑÐµÑÑ Ðž ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÑ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÑ ÐŽÐ»Ñ ÑÐžÐ¿ÐžÑÐœÑÑ
+ ÑÑÐ»ÐŸÐ²ÐžÐ¹ - ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÑÑÐµÐŽÐœÐµÐ¹ ÑÐ»ÐŸÐ¶ÐœÐŸÑÑÐž (Ð²ÐºÐ»ÑÑÐ°Ñ ÑÐ°Ð±Ð»ÐžÑÑ Ðž ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ), ÐºÐŸÑÐŸÑÑÐµ Ð²ÑÑÑÐµÑÐ°ÑÑÑÑ Ð² Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²Ðµ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐº Ðž Ð°ÑÑ
+ÐžÐ²ÐŸÐ², Ð²ÑÑÐŸÐºÐŸÐµ ÐºÐ°ÑÐµÑÑÐ²ÐŸ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐŸÐ² Ðž ÑÑÐµÐŽÐœÑÑ-ÐŽÐŸÐ»Ð³Ð°Ñ ÐŽÐ»ÐžÑÐµÐ»ÑÐœÐŸÑÑÑ ÑÐ°Ð±ÐŸÑÑ.</Text>
+<Subsection id="intensive_ocr">
+<Title>
+<Text id="184">ÐÐœÑÐµÐœÑÐžÐ²ÐœÑÐ¹ ÐÐ Ð¡</Text>
+</Title>
+<Content>
+<Text id="185">ÐÑÐŸÑÐµÑÑ ÐÐ Ð¡ ÑÐ²Ð»ÑÐµÑÑÑ ÑÑÑÐŽÐœÑÐŒ. ÐÐœ ÑÑÐµÐ±ÑÐµÑ Ð±ÐŸÐ»ÑÑÐŸÐ¹ ÐºÐŸÐœÑÐµÐœÑÑÐ°ÑÐžÐž Ð²ÐœÐžÐŒÐ°ÐœÐžÑ Ðž ÑÐŒÐµÐœÐžÑ. ÐÐµÑÐµÐŽ Ð¿ÐŸÐ¿ÑÑÐºÐŸÐ¹ ÐŽÐŸÑÑÐžÐ³ÐœÑÑÑ ÐŒÐ°ÐºÑÐžÐŒÐ°Ð»ÑÐœÑÑ
+ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐŸÐ² ÑÑÐµÐ±ÑÐµÑÑÑ Ð¿ÐŸÑÑÐŽÐºÐ° 6 ÐœÐµÐŽÐµÐ»Ñ ÑÐ°Ð±ÐŸÑÑ, Ð² Ð¿ÑÐŸÑÐµÑÑÐµ ÐºÐŸÑÐŸÑÐŸÐ¹ ÐžÐŽÐµÑ ÐœÐ°ÑÐ°ÑÑÐ°ÐœÐžÐµ ÐŸÐ¿ÑÑÐ°.</Text>
+<Text id="186">ÐÐ±ÑÑÐœÐŸ ÐŒÐ°ÐºÑÐžÐŒÐ°Ð»ÑÐœÐ°Ñ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÐµÐ»ÑÐœÐŸÑÑÑ ÐŽÐŸÑÑÐžÐ³Ð°ÐµÑÑÑ Ð² Ð¿ÐµÑÐ²ÑÐµ ÑÐ°ÑÑ ÐœÐ°ÑÐ°Ð»Ð° ÐŽÐœÑ. ÐÐŸÑÐ»Ðµ ÑÑÐµÑ
+ ÑÐ°ÑÐŸÐ² ÑÐ°Ð±ÐŸÑÑ Ñ ÐÐ Ð¡ ÐŸÐœÐ° ÑÐµÐ·ÐºÐŸ Ð¿Ð°ÐŽÐ°ÐµÑ, Ð¿ÑÐžÐŒÐµÑÐœÐŸ ÐœÐ° 50% ÐŸÑ ÐœÐ°ÑÐ°Ð»ÑÐœÐŸÐ³ÐŸ ÑÑÐŸÐ²ÐœÑ. ÐÐŸÑÐ»Ðµ 6 ÑÐ°ÑÐŸÐ² Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ Ð»ÑÐŽÐµÐ¹ ÐŸÑÐµÐœÑ ÑÑÑÐ°ÑÑ.</Text>
+<Text id="187">Ð¢ÐŸ Ð¶Ðµ ÑÐ°ÐŒÐŸÐµ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ Ð² ÑÐµÑÐµÐœÐžÐµ Ð¿ÐµÑÐ²ÑÑ
+ ÐœÐµÐŽÐµÐ»Ñ ÑÐ°Ð±ÐŸÑÑ. Ð Ð¿ÐµÑÐ²ÑÐµ ÐœÐµÐŽÐµÐ»Ðž Ð¿ÑÐŸÐŽÑÐºÑÐžÐ²ÐœÐŸÑÑÑ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÐœÐ° Ð²ÑÑÐŸÐºÐŸÐŒ ÑÑÐŸÐ²ÐœÐµ, ÐœÐŸ Ð¿ÐŸÑÐ»Ðµ ÑÑÐŸÐ³ÐŸ 2/3 Ð»ÑÐŽÐµÐ¹ ÑÑÑÐ°ÑÑ Ðž ÑÐµÑÑÑÑ ÐžÐœÑÐµÑÐµÑ Ðº ÑÐ°Ð±ÐŸÑÐµ. Ð¢Ð°ÐºÐžÐµ Ð»ÑÐŽÐž Ð»ÐžÐ±ÐŸ ÑÑ
+ÐŸÐŽÑÑ, Ð»ÐžÐ±ÐŸ Ð¿ÑÐŸÐŽÐŸÐ»Ð¶Ð°ÑÑ ÑÐ°Ð±ÐŸÑÐ°ÑÑ ÐœÐ° ÐŸÑÐµÐœÑ ÐœÐžÐ·ÐºÐŸÐŒ ÑÑÐŸÐ²ÐœÐµ, Ð²Ð»ÐžÑÑÑÐµÐŒ ÐœÐ° ÐºÐ°ÑÐµÑÑÐ²ÐŸ Ðž Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÐµÐ»ÑÐœÐŸÑÑÑ. ÐÐ°Ð¶Ðµ ÑÐµ, ÐºÑÐŸ Ð²ÑÑÑÐŸÑÐ» ÐºÑÐžÑÐžÑÐµÑÐºÐžÐµ 1-5 ÐœÐµÐŽÐµÐ»Ñ Ðž ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ ÑÐ°ÑÑÑÑ ÑÐ°Ð±ÐŸÑÐµÐ¹ ÐºÐŸÐŒÐ°ÐœÐŽÑ, ÑÐ°ÑÑÐŸ ÑÑ
+ÐŸÐŽÑÑ Ð² Ð¿ÐŸÐžÑÐºÐ°Ñ
+ Ð»ÑÑÑÐµÐ¹ ÑÐ°Ð±ÐŸÑÑ Ð² Ð¿ÑÐŸÐŒÐµÐ¶ÑÑÐºÐµ 6-12 ÐŒÐµÑÑÑÐµÐ².</Text>
+<Text id="188">ÐÐ°ÐŒÐµÑÐºÐž, ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐ»Ðž ÑÐŽÐµÐ»Ð°ÐœÑ Ð² ÑÐ°ÑÑÐž <CrossRef target="Section" ref="the_ocr_process"/> ÐŸ ÑÐ°Ð±ÐŸÑÐµÐ¹ ÑÐžÐ»Ðµ, ÐŸÑÐœÐŸÑÑÑÑÑ Ð² ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž Ðº ÐžÐœÑÐµÐœÑÐžÐ²ÐœÐŸÐŒÑ ÐÐ Ð¡. ÐÐŸÐœÑÑÐŸÐ»Ñ ÐºÐ°ÑÐµÑÑÐ²Ð° Ð»ÑÑÑÐµ Ð¿ÐŸÑÑÑÐ°ÑÑ Ð»ÑÐŽÑÐŒ, ÑÐµÐ¹ ÑÐŸÐŽÐœÐŸÐ¹ ÑÐ·ÑÐº ÑÐ²Ð»ÑÐµÑÑÑ ÑÐµÐŒ Ð¶Ðµ, ÐœÐ° ÐºÐŸÑÐŸÑÐŸÐŒ ÐœÐ°Ð¿ÐžÑÐ°Ðœ ÐŽÐŸÐºÑÐŒÐµÐœÑ ÐžÐ»Ðž ÐŸÐœÐž Ð²Ð»Ð°ÐŽÐµÑÑ ÑÑÐžÐŒ ÑÐ·ÑÐºÐŸÐŒ Ð² ÑÐŸÐ²ÐµÑÑÐµÐœÑÑÐ²Ðµ. ÐÑÑÑÐžÐµ ÑÐ°Ð±ÐŸÑÐœÐžÐºÐž - ÑÑÐŸ ÑÐºÐŸÐ»ÑÐœÐžÐºÐž Ðž ÑÑÑÐŽÐµÐœÑÑ, Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ ÐŒÐŸÐ»ÐŸÐŽÑÐµ Ð»ÑÐŽÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð±ÐŸÐ»ÐµÐµ Ð²ÐœÐžÐŒÐ°ÑÐµÐ»ÑÐœÑ Ðž Ð±ÐŸÐ»ÐµÐµ ÑÐºÐŸÐœÑÐµÐœÑÑÐžÑÐŸÐ²Ð°ÐœÑ Ð¿ÑÐž ÑÐ°ÐºÐŸÐŒ Ð²ÐžÐŽÐµ ÑÐ°Ð±ÐŸÑÑ, ÐœÐµÐ¶ÐµÐ»Ðž Ð±ÐŸÐ»ÐµÐµ Ð²Ð·ÑÐŸÑÐ»ÐŸÐµ Ð¿ÐŸÐºÐŸÐ»ÐµÐœÐžÐµ Ðž Ð¿ÐŸÐ¶ÐžÐ»ÑÐµ Ð»ÑÐŽÐž. Ð£ÑÐ»ÐŸÐ²ÐœÑÐ¹ ÐºÑÐžÑÐµÑÐžÐ¹ ÐŸÑÐ±ÐŸÑÐ° ÑÐ°ÐºÐŸÐ² - Ð»ÑÐŽÐž Ð² Ð²ÐŸÐ·ÑÐ°ÑÑÐµ ÐŸÑ 18 ÐŽÐŸ 23 Ð»ÐµÑ ÐŸÐ±ÑÑÐœÐŸ Ð»ÑÑÑÐµ Ð¿ÐŸÐŽÑ
+ÐŸÐŽÑÑ ÐœÐ° ÑÐ°ÐºÑÑ ÑÐ°Ð±ÐŸÑÑ, ÐœÐµÐ¶ÐµÐ»Ðž ÑÐµ, ÐºÐŸÐŒÑ Ð±ÐŸÐ»ÑÑÐµ 25.</Text>
+<Text id="189">Ð ÐœÐ°ÐºÐŸÐœÐµÑ, Ð¿ÑÐŸÑÐµÑÑ ÐÐ Ð¡ ÐŸÑÐµÐœÑ ÑÑÑÐžÐœÐµÐœ Ðž ÑÐºÑÑÐµÐœ. ÐÐŸÑÑÐŸÐŒÑ ÐœÑÐ¶ÐœÐŸ ÐºÐ°Ðº-ÑÐŸ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑ ÑÐ°Ð±ÐŸÑÐžÐ¹ ÐŽÑÑ
+, ÐŒÐŸÑÐžÐ²Ð°ÑÐžÑ Ðž Ð¿ÑÐžÐ²ÑÐ·Ð°ÐœÐœÐŸÑÑÑ Ðº ÑÐ°Ð±ÐŸÑÐµ.</Text>
+<Text id="190">ÐÐŸÑ ÐžÑÐŸÐ³ Ð²ÑÑÐµÐ¿ÐµÑÐµÑÐžÑÐ»ÐµÐœÐœÐŸÐ³ÐŸ:</Text>
+<BulletList>
+<Bullet>
+<Text id="191">ÐÐŸÐ»ÐŸÐŽÑÐµ Ð»ÑÐŽÐž Ð² Ð²ÐŸÐ·ÑÐ°ÑÑÐ° 18-25 Ð»ÐµÑ ÑÐ°ÐŒÑÐµ Ð»ÑÑÑÐžÐµ ÐºÐ°ÐœÐŽÐžÐŽÐ°ÑÑ ÐœÐ° ÑÐ°ÐºÑÑ ÑÐ°Ð±ÐŸÑÑ.</Text>
+</Bullet>
+<Bullet>
+<Text id="192">Ð¢Ð°Ðº ÐºÐ°Ðº Ð¿ÐµÑÐ²ÑÐµ ÑÐ°ÑÑ ÑÐ°Ð±ÐŸÑÑ ÑÐ²Ð»ÑÑÑÑÑ ÑÐ°ÐŒÑÐŒÐž Ð¿ÑÐŸÐŽÑÐºÑÐžÐ²ÐœÑÐŒÐž, ÑÐ»ÐµÐŽÑÐµÑ ÐœÐ°ÐœÐžÐŒÐ°ÑÑ ÑÐ°Ð±ÐŸÑÐžÑ
+ ÐœÐ° Ð¿ÐŸÐ»-ÐŽÐœÑ, Ðž ÑÐŸÐ»ÑÐºÐŸ ÑÐ°ÐŒÑÐŒ ÑÑÐµÑÐŽÐœÑÐŒ ÑÐ°Ð±ÐŸÑÐœÐžÐºÐ°ÐŒ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ ÑÐ°Ð±ÐŸÑÐ°ÑÑ ÑÐµÐ»ÑÐ¹ ÑÐ°Ð±ÐŸÑÐžÐ¹ ÐŽÐµÐœÑ.</Text>
+</Bullet>
+<Bullet>
+<Text id="193">ÐÐ²Ðµ ÑÑÐµÑÐž ÑÐ°Ð±ÐŸÑÐœÐžÐºÐŸÐ² Ð¿ÐŸÐºÐžÐŽÐ°ÑÑ ÑÐ°Ð±ÐŸÑÑ ÐŸÑ ÑÑÑÐ°Ð»ÐŸÑÑÐž ÐžÐ»Ðž ÐŸÑ ÑÑÑÐžÐœÑ Ð² ÑÐµÑÐµÐœÐžÐµ 3-5 ÐœÐµÐŽÐµÐ»Ñ, Ð²ÑÐµ ÑÑÐŸ ÐŸÑÑÐ°Ð¶Ð°ÐµÑÑÑ ÐœÐ° ÑÑ
+ÑÐŽÑÐµÐœÐžÐž Ð¿ÑÐŸÐŽÑÐºÑÐžÐ²ÐœÐŸÑÑÐž Ð² ÑÑÐŸÑ Ð¿ÐµÑÐžÐŸÐŽ.</Text>
+</Bullet>
+<Bullet>
+<Text id="194">ÐÑÐ¶ÐµÐœ Ð¿ÐŸÑÑÐŸÑÐœÐœÑÐ¹ Ð¿ÑÐžÑÐŸÐº ÑÐ°Ð±ÐŸÑÐœÐžÐºÐŸÐ² ÐŽÐ»Ñ Ð¿ÐŸÐºÑÑÑÐžÑ Ð·Ð°ÑÑÐ°Ñ ÐœÐ° ÐŸÐ±ÑÑÐµÐœÐžÐµ, Ð¿ÐŸÐŽÐŽÐµÑÐ¶Ð°ÐœÐžÐµ ÑÑÐµÑÐŽÐžÑ Ðž ÑÐ°Ð±ÐŸÑÐµÐ³ÐŸ ÐŽÑÑ
+Ð°.</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Subsection>
+<Subsection id="achievable_productivity">
+<Title>
+<Text id="195">ÐÐŸÑÑÐžÐ¶ÐžÐŒÐ°Ñ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÐµÐ»ÑÐœÐŸÑÑÑ</Text>
+</Title>
+<Content>
+<Table id="table_ocr_productivity">
+<Title>
+<Text id="196">Ð¿ÑÐŸÐŽÑÐºÑÐžÐ²ÐœÐŸÑÑÑ Ð¿ÑÐŸÑÐµÑÑÐ° ÐÐ Ð¡</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="161">Â  </th>
+<th width="132">
+<Text id="197">Ð Ð°Ð±ÐŸÑÐžÐµ ÑÐ°ÑÑ/ÐŽÐµÐœÑ</Text>
+</th>
+<th width="123">
+<Text id="198">Ð¡ÑÑÐ°ÐœÐžÑÑ/ÐŽÐµÐœÑ</Text>
+</th>
+<th width="113">
+<Text id="199">Ð¡ÑÑÐ°ÐœÐžÑÑ/ÐŒÐµÑÑÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="161">
+<Text id="200">ÐÐ°ÑÐ°Ð»ÑÐœÐ°Ñ Ð¿ÐŸÐŽÐ³ÐŸÑÐŸÐ²ÐºÐ°Â <i>(6</i>Â ÐœÐµÐŽÐµÐ»Ñ)</Text>
+</th>
+<th width="132">
+<Text id="201">3</Text>
+</th>
+<th width="123">
+<Text id="202">6</Text>
+</th>
+<th width="113">
+<Text id="203">120</Text>
+</th>
+</tr>
+<tr>
+<th width="161">
+<Text id="204">ÐÐ¿ÑÐžÐŒÐ°Ð»ÑÐœÑÐ¹ ÑÑÐŸÐ²ÐµÐœÑ Ð¿ÑÐŸÐŽÑÐºÑÐžÐ²ÐœÐŸÑÑÐž</Text>
+</th>
+<th width="132">
+<Text id="205">3</Text>
+</th>
+<th width="123">
+<Text id="206">9</Text>
+</th>
+<th width="113">
+<Text id="207">150 to 200</Text>
+</th>
+</tr>
+<tr>
+<th width="161">Â </th>
+<th width="132">
+<Text id="208">7</Text>
+</th>
+<th width="123">
+<Text id="209">28</Text>
+</th>
+<th width="113">
+<Text id="210">500 to 600</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="211">Ð Ð¢Ð°Ð±Ð»ÐžÑÐµ <CrossRef target="Table" ref="table_ocr_productivity"/> Ð¿ÑÐžÐ²ÐµÐŽÐµÐœÑ ÑÑÐµÐŽÐœÐžÐµ ÑÐžÑÑÑ Ð¿ÑÐŸÐŽÑÐºÑÐžÐ²ÐœÐŸÑÑÐž ÑÐ°Ð±ÐŸÑÑ ÐœÐ° ÐÐ Ð¡. ÐÐŸÐºÑÐŒÐµÐœÑÑ Ð¿ÑÐžÑ
+ÐŸÐŽÑÑ ÑÐ°Ð·ÐœÑÐŒÐž Ðž Ð¿ÐŸ ÑÐ°Ð·ÐŒÐµÑÑ, Ðž Ð¿ÐŸ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ. ÐÑÐž ÑÐŸÑÑÐ°Ð²Ð»ÐµÐœÐžÐž ÑÑÐŸÐ¹ ÑÐ°Ð±Ð»ÐžÑÑ Ð±ÑÐ»Ðž ÑÑÑÐµÐœÑ ÑÐ°ÐºÐžÐµ ÑÐ°ÐºÑÐŸÑÑ, ÐºÐ°Ðº ÑÐ°Ð·ÐœÐŸÐŸÐ±ÑÐ°Ð·ÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐžÑ
+ ÑÑÐµÐŽÐœÐµÐµ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐ¹ Ðž ÑÐ°Ð±Ð»ÐžÑ - Ðº Ð¿ÑÐžÐŒÐµÑÑ ÐŸÐŽÐžÐœ ÑÐžÑÑÐœÐŸÐº Ðž ÐŸÐŽÐœÐ° ÑÐ°Ð±Ð»ÐžÑÐ° 5 ÐœÐ° 5 ÐœÐ° ÐºÐ°Ð¶ÐŽÑÐµ Ð²ÐŸÑÐµÐŒÑ ÑÑÑÐ°ÐœÐžÑ. Ð¢Ð°ÐºÐ¶Ðµ Ð¿ÑÐµÐŽÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐŸ, ÑÑÐŸ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ ÑÐ²Ð»ÑÑÑÑÑ ÑÑÐµÐŽÐœÐµÐ³ÐŸ-Ð²ÑÑÐŸÐºÐŸÐ³ÐŸ ÐºÐ°ÑÐµÑÑÐ²Ð°. ÐÐ°ÐŒÐµÑÑÑÐµ, ÐºÐ°Ðº ÑÑÐŸ Ð±ÑÐ»ÐŸ ÑÐ¶Ðµ ÑÐ°ÑÑÐŒÐŸÑÑÐµÐœÐŸ, ÑÑÐŸ ÑÑÐŸ Ð·Ð°Ð²ÐžÑÐžÑ ÐŸÑ ÐºÐ°ÑÐµÑÑÐ²Ð° ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ Ðž ÑÐ°ÐºÐ¶Ðµ ÐŸÑ ÑÐŸÐ³ÐŸ, ÐœÐ°ÑÐºÐŸÐ»ÑÐºÐŸ Ñ
+ÐŸÑÐŸÑÐŸ ÑÐ°Ð±ÐŸÑÐœÐžÐºÐž Ð·ÐœÐ°ÑÑ ÑÐ·ÑÐº, ÐœÐ° ÐºÐŸÑÐŸÑÐŸÐŒ ÐœÐ°Ð¿ÐžÑÐ°ÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ.</Text>
+<Text id="212">Ð ÑÐ°Ð±Ð»ÐžÑÐµ ÑÐ°ÐºÐ¶Ðµ Ð¿ÑÐžÐ²ÐµÐŽÐµÐœÑ ÐŽÐ°ÐœÐœÑÐµ ÐŸ ÑÐµÑ
+, ÐºÑÐŸ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² Ð¿ÑÐŸÑÐµÑÑÐµ ÐŸÐ±ÑÑÐµÐœÐžÑ, Ðž ÑÐµÑ
+, ÐºÐŸÑÐŸÑÑÐµ ÑÐ¶Ðµ ÑÐ°Ð±ÐŸÑÐ°ÑÑ Ð² ÐŸÐ¿ÑÐžÐŒÐ°Ð»ÑÐœÐŸÐŒ ÑÐµÐ¶ÐžÐŒÐµ. ÐÑÐ»Ðž ÑÐ»ÐµÐœ ÑÑÐºÐŸÐ²ÐŸÐŽÑÑÐµÐ¹ ÐºÐŸÐŒÐ°ÐœÐŽÑ ÑÐŽÐµÐ»ÐžÑ ÐŽÐŸ ÑÑÐµÑ
+ ÑÐ°ÑÐŸÐ² Ð² ÐŽÐµÐœÑ ÐœÐ° Ð¿ÑÐŸÑÐµÑÑ ÐÐ Ð¡, ÑÐŸ ÐŸÐœ ÐŒÐŸÐ¶ÐµÑ ÐŽÐŸÑÑÐžÐ³ÐœÑÑÑ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐ° 180-200 ÑÑÑÐ°ÐœÐžÑ Ð² ÐŒÐµÑÑÑ. ÐÐ»Ñ Ð¿ÐŸÑÑÐŸÑÐœÐœÐŸÐ³ÐŸ ÑÐ°Ð±ÐŸÑÐœÐžÐºÐ°, Ð¿ÑÐŸÑÐµÐŽÑÐµÐ³ÐŸ Ñ
+ÐŸÑÐŸÑÑÑ Ð¿ÐŸÐŽÐ³ÐŸÑÐŸÐ²ÐºÑ, Ñ Ð²ÑÑÐŸÐºÐŸÐ¹ Ð²ÐœÐžÐŒÐ°ÑÐµÐ»ÑÐœÐŸÑÑÑÑ Ðž ÐŸÑÐŽÐ°ÑÐµÐ¹ ÐŽÐŸÑÑÐžÐ³ÐœÑÑÑ 500-600 ÑÑÑÐ°ÐœÐžÑ Ð² ÐŒÐµÑÑÑ ÐœÐµ Ð±ÑÐŽÐµÑ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÐŸÐ¹.</Text>
+<Text id="213">Ð¢ÐµÐŒ ÐœÐµ ÐŒÐµÐœÐµÐµ, Ñ ÐœÐµÑÐ°Ð·Ð±ÐŸÑÑÐžÐ²ÑÐŒÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒÐž Ð¿Ð»ÐŸÑ
+ÐŸÐ³ÐŸ ÐºÐ°ÑÐµÑÑÐ²Ð° Ðž ÐžÐ·ÐŸÐ±ÐžÐ»ÐžÐµÐŒ ÑÐ°Ð±Ð»ÐžÑ Ðž ÑÐžÑÑÐœÐºÐŸÐ² ÑÑÐž ÑÐžÑÑÑ Ð±ÑÐŽÑÑ ÐœÐžÐ¶Ðµ â ÐœÐ°Ð²ÐµÑÐœÐŸÐµ 300-400 ÑÑÑÐ°ÐœÐžÑ ÐŽÐ»Ñ Ð¿ÐŸÑÑÐŸÑÐœÐœÐŸÐ³ÐŸ ÑÐ°Ð±ÐŸÑÐœÐžÐºÐ°.</Text>
+<Text id="214">ÐÑÐµÐŽÑÑÐ°Ð²ÑÑÐµ, ÑÑÐŸ Ð·Ð°ÑÐ¿Ð»Ð°ÑÐ° ÐŽÐ»Ñ ÐŒÐŸÑÐžÐ²ÐžÑÐŸÐ²Ð°ÐœÐœÐŸÐ³ÐŸ Ð¿ÐŸÑÑÐŸÑÐœÐœÐŸÐ³ÐŸ ÑÐ°Ð±ÐŸÑÐœÐžÐºÐ° ÑÐŸÑÑÐ°Ð²Ð»ÑÐµÑ $400 Ð² ÐŒÐµÑÑÑ, Ð° Ð·Ð°ÑÑÐ°ÑÑ ÐœÐ° ÐŒÐµÐœÐµÐŽÐ¶ÐŒÐµÐœÑ, ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÑ, Ð°ÑÐµÐœÐŽÑ, ÐºÐŸÐŒÐŒÑÐœÐ°Ð»ÑÐœÑÐµ ÑÑÐ»ÑÐ³Ðž Ðž Ñ.ÐŽ. ÑÑÐŸÐžÑ $300-400 ÐœÐ° ÑÐµÐ»ÐŸÐ²ÐµÐºÐ° Ð² ÐŒÐµÑÑÑ. ÐÐ»Ð°ÑÐ° Ð·Ð° 1 ÑÑÑÐ°ÐœÐžÑÑ ÐÐ Ð¡ $ 1.2-1.6. Ð£ÑÐžÑÑÐ²Ð°Ñ Ð¿ÐŸÐŽÐ³ÐŸÑÐŸÐ²ÐžÑÐµÐ»ÑÐœÑÐ¹ Ð¿ÐµÑÐžÐŸÐŽ, ÐŸÐ±ÑÐžÐ¹ ÐŸÐ±ÑÐµÐŒ, Ð²ÑÐµÐŒÑ, Ð·Ð°ÑÑÐ°ÑÑ ÐœÐ° ÑÐ²ÐŸÐ»ÑÐœÐµÐœÐžÐµ Ð¿ÑÐž Ð·Ð°ÐºÑÑÑÐžÐž Ð±ÐžÐ·ÐœÐµÑÐ°, ÑÑÐž ÑÐžÑÑÑ Ð¿ÐŸÐŽÐœÐžÐŒÑÑÑÑ ÐŽÐŸ $1.5-2.5 Ð·Ð° ÑÑÑÐ°ÐœÐžÑÑ.</Text>
+<Text id="215">Ð¡ÑÐŸÐžÐŒÐŸÑÑÑÐ²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ ÑÐ°Ð±ÐŸÑÑ ÑÐ°ÐŒÐžÐŒ ÐœÑÐ¶ÐœÐŸ ÑÑÐ°Ð²ÐœÐžÐ²Ð°ÑÑ ÑÐŸ ÑÑÐŸÐžÐŒÐŸÑÑÑÑ, ÐµÑÐ»Ðž Ð¿ÐŸÑÑÑÐžÑÑ ÑÑÑ ÑÐ°Ð±ÐŸÑÑ Ð¿ÑÐŸÑÐµÑÑÐžÐŸÐœÐ°Ð»ÑÐœÑÐŒ ÐÐ Ð¡ ÐºÐŸÐŒÐ¿Ð°ÐœÐžÑÐŒ. ÐÐµÐ¿ÑÐ°Ð²ÐžÑÐµÐ»ÑÑÑÐ²ÐµÐœÐœÐ°Ñ ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑ Ð² Ð ÑÐŒÑÐœÐžÐž Ð¿ÑÐµÐŽÐ»Ð°Ð³Ð°ÐµÑ ÑÐ°ÐºÐžÐµ ÑÑÐ»ÑÐ³Ðž, Ðž ÑÐµÐœÐ° ÐŽÐ»Ñ Ð³ÑÐŒÐ°ÐœÐžÑÐ°ÑÐœÑÑ
+ ÐœÐµÐºÐŸÐŒÐŒÐµÑÑÐµÑÐºÐžÑ
+ ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐ¹ ÐœÐžÐ¶Ðµ Ðž Ð³ÑÐ°ÐœÐžÑÐžÑ ÐŸÑ $1.2 ÐŽÐŸ $2 Ð·Ð° ÑÑÑÐ°ÐœÐžÑÑ. ÐÑÐ»Ðž Ñ Ð²Ð°Ñ ÐµÑÑÑ ÐºÐ°ÐºÐžÐµ-Ð»ÐžÐ±ÐŸ Ð²ÐŸÐ¿ÑÐŸÑÑ, Ð¿ÐžÑÐžÑÐµ ÐœÐ°ÐŒ ÐœÐ° scanning@humaninfo.org.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="alternatives_to_ocr">
+<Title>
+<Text id="216">ÐÐ»ÑÑÐµÑÐœÐ°ÑÐžÐ²Ð° ÐÐ Ð¡</Text>
+</Title>
+<Content>
+<Text id="217">Ð¡ÑÑÐµÑÑÐ²ÑÑÑ ÐŽÐ²Ðµ Ð°Ð»ÑÑÐµÑÐœÐ°ÑÐžÐ²Ñ Ð¿ÑÐŸÐ²ÐµÐŽÐµÐœÐžÑ ÐÐ Ð¡.</Text>
+<Subsection id="manual_retyping">
+<Title>
+<Text id="218">Ð ÑÑÐœÐŸÐµ Ð¿ÐµÑÐµÐ¿ÐµÑÐ°ÑÑÐ²Ð°ÐœÐžÐµ</Text>
+</Title>
+<Content>
+<Text id="219">ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÑÑÐŸÑ ÐŒÐµÑÐŸÐŽ, ÐŒÐŸÐ¶ÐœÐŸ ÐœÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÑÐºÐ°ÐœÐµÑ Ð²ÐŸÐŸÐ±ÑÐµ, Ð¿ÑÐžÐŒÐµÐœÐžÐ² Ð¿ÑÐŸÑÑÐŸÐ¹ ÑÐµÐºÑÑÐŸÐ²ÐŸÐ¹ ÑÐµÐŽÐ°ÐºÑÐŸÑ. ÐÐŽÐžÐœÑÑÐ²ÐµÐœÐœÐŸÐµ, ÑÑÐŸ ÐŸÑÑÐ°ÑÑÑÑ ÑÐŽÐµÐ»Ð°ÑÑ, ÑÑÐŸ ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑ ÐŸÐ±Ð»ÐŸÐ¶ÐºÑ Ðž ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ, Ð¿ÐŸÑÑÐŸÐŒÑ ÐŒÐŸÐ¶ÐœÐŸ ÐŸÐ±ÐŸÐ¹ÑÐžÑÑ Ð±ÐµÐ· ÐŽÐŸÑÐŸÐ³ÐžÑ
+ ÑÐºÐ°ÐœÐµÑÐŸÐ² Ðž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒ ÐÐ Ð¡.</Text>
+<Text id="220">ÐÑÐŽÐž, Ð²ÑÑÐŸÐ»ÐœÑÑÑÐžÐµ ÑÑÑ ÑÐ°Ð±ÐŸÑÑ, ÐœÐµ ÐŸÐ±ÑÐ·Ð°ÑÐµÐ»ÑÐœÐŸ ÐŽÐŸÐ»Ð¶ÐœÑ Ð²ÐœÐžÐºÐ°ÑÑ Ð² ÑÑÑÑ ÑÐµÐºÑÑÐ°. ÐÑÐµ, ÑÑÐŸ ÐŸÑ ÐœÐžÑ
+ ÑÑÐµÐ±ÑÐµÑÑÑ, ÑÑÐŸ Ð°ÐºÐºÑÑÐ°ÑÐœÐŸ Ðž Ð±ÐµÐ·ÐŸÑÐžÐ±ÐŸÑÐœÐŸ Ð¿ÐµÑÐ°ÑÐ°ÑÑ ÑÐŸ, ÑÑÐŸ ÐŸÐœÐž Ð²ÐžÐŽÑÑ. Ð¢ÐµÐŒ ÐœÐµ ÐŒÐµÐœÐµÐµ, Ð¿ÐµÑÐµÐ¿ÐµÑÐ°ÑÑÐ²Ð°ÐœÐžÐµ Ð²ÐœÐŸÑÐžÑ ÐŸÑÐžÐ±ÐºÐž, Ð¿ÐŸÑÑÐŸÐŒÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŒÐµÑÐŸÐŽ ÐŽÐ²ÐŸÐ¹ÐœÐŸÐ³ÐŸ ÐœÐ°Ð±ÐŸÑÐ°. ÐÐ²Ð° ÑÐµÐ»ÐŸÐ²ÐµÐºÐ° Ð¿ÐµÑÐµÐ¿ÐµÑÐ°ÑÑÐ²Ð°ÑÑ ÐŸÐŽÐžÐœ Ðž ÑÐŸÑ Ð¶Ðµ ÑÐµÐºÑÑ, Ð¿ÐŸÑÐ»Ðµ ÑÐµÐ³ÐŸ ÑÐ¿ÐµÑÐžÐ°Ð»ÑÐœÐ°Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Ð¿ÑÐŸÐ²ÐµÑÑÐµÑ ÐŸÐ±Ðµ ÑÐ»ÐµÐºÑÑÐŸÐœÐœÑÐµ Ð²ÐµÑÑÐžÐž ÑÑÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, ÑÐ»ÐŸÐ²ÐŸ Ð² ÑÐ»ÐŸÐ²ÐŸ ÑÑÐ°Ð²ÐœÐžÐ²Ð°Ñ ÐµÐ³ÐŸ Ñ ÐŸÑÐžÐ³ÐžÐœÐ°Ð»ÐŸÐŒ. ÐÑÐµÐŽÐ¿ÐŸÐ»Ð°Ð³Ð°ÐµÑÑÑ, ÑÑÐŸ ÑÐ»ÐŸÐ²ÐŸ, ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°ÐœÐœÐŸÐµ ÐŸÐŽÐžÐœÐ°ÐºÐŸÐ²ÐŸ Ð² ÐŸÐ±ÐŸÐžÑ
+ ÑÐ»ÑÑÐ°ÑÑ
+, ÑÐ²Ð»ÑÐµÑÑÑ Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÑÐŒ, Ñ
+ÐŸÑÑ ÑÑÐŸ ÐœÐµ Ð²ÑÐµÐ³ÐŽÐ° ÑÐ°Ðº, Ð¿ÐŸÑÑÐŸÐŒÑ ÑÐ°ÐºÐ¶Ðµ Ð¿ÑÐ°ÐºÑÐžÐºÑÐµÑÑÑ Ðž ÐŒÐµÑÐŸÐŽ ÑÑÐŸÐ¹ÐœÐŸÐ³ÐŸ ÐœÐ°Ð±ÐŸÑÐ°.</Text>
+<Text id="221">ÐÐŸÐ»ÐŸÐ¶ÐžÑÐµÐ»ÑÐœÐŸÐ¹ ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÐŒÐµÑÐŸÐŽÐ° Ð¿ÐµÑÐµÐ¿ÐµÑÐ°ÑÑÐ²Ð°ÐœÐžÑ ÑÐ²Ð»ÑÐµÑÑÑ ÑÐŸ, ÑÑÐŸ ÐŒÐŸÐ¶ÐœÐŸ ÑÐœÐžÐ·ÐžÑÑ Ð·Ð°ÑÑÐ°ÑÑ, ÑÐ°Ðº ÐºÐ°Ðº ÐœÐµÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÐž Ð¿ÑÐžÐŸÐ±ÑÐµÑÐ°ÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐÐ Ð¡ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÑ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð±ÐŸÐ»ÐµÐµ ÑÑÐ°ÑÐŸÐ¹ ÐŒÐŸÐŽÐžÑÐžÐºÐ°ÑÐžÐž ÐžÐ»Ðž Ð±/Ñ, Ð² ÑÐŸ Ð²ÑÐµÐŒÑ ÐºÐ°Ðº ÐŽÐ»Ñ Ð¿ÑÐŸÐ²ÐµÐŽÐµÐœÐžÑ ÐÐ Ð¡ ÐœÑÐ¶ÐœÑ ÐŒÐŸÑÐœÑÐµ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÑ. Ð ÑÐŸÐŒÑ Ð¶Ðµ ÑÐ°Ð±ÐŸÑÐ° ÐŒÐŸÐ¶ÐµÑ Ð²ÑÐ¿ÐŸÐ»ÐœÑÑÑÑÑ ÐŒÐµÐœÐµÐµ ÐºÐ²Ð°Ð»ÐžÑÐžÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐŒÐž ÑÐ°Ð±ÐŸÑÐœÐžÐºÐ°ÐŒÐž. ÐÐŽÐžÐœ ÐœÐµÐŽÐŸÑÑÐ°ÑÐŸÐº ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒ Ð¿ÐŸÐŽÐ³ÐŸÑÐŸÐ²ÐžÑÐµÐ»ÑÐœÑÐ¹ Ð¿ÐµÑÐžÐŸÐŽ, ÐºÐ°Ðº ÐŒÐžÐœÐžÐŒÑÐŒ ÐŽÐŸ ÐŽÐ²ÑÑ
+ ÐŒÐµÑÑÑÐµÐ². ÐÐ°Ð±ÐŸÑ ÐŸÐŽÐœÐžÐŒ ÑÐµÐ»ÐŸÐ²ÐµÐºÐŸÐŒ Ð¿ÑÐžÐ²ÐŸÐŽÐžÑ Ðº ÐŒÐœÐŸÐ¶ÐµÑÑÐ²Ñ ÐŸÑÐžÐ±ÐŸÐº, Ð¿ÐŸÑÑÐŸÐŒÑ Ð¿ÑÐžÑ
+ÐŸÐŽÐžÑÑÑ Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑÑ ÐŽÐ²ÐŸÐ¹ÐœÐŸÐ¹ ÐžÐ»Ðž ÑÑÐŸÐ¹ÐœÐŸÐ¹ ÐœÐ°Ð±ÐŸÑ ÑÐµÐºÑÑÐ°, ÑÑÐŸ ÑÐ²ÑÐ·Ð°ÐœÐŸ Ñ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÑÐŒÐž Ð·Ð°ÑÑÐ°ÑÐ°ÐŒÐž.</Text>
+<Text id="222">ÐÑÐµ ÐžÐ·ÐŽÐµÑÐ¶ÐºÐž Ð·Ð°Ð²ÐžÑÑÑ ÐŸÑ ÑÑÐŸÐ²ÐœÑ Ð·Ð°ÑÐ¿Ð»Ð°ÑÑ. ÐÐ±ÑÑÐœÐŸ Ð»ÑÐŽÐž, Ð·Ð°ÐœÐžÐŒÐ°ÑÑÐžÐµÑÑ Ð¿ÐµÑÐ°ÑÐ°ÐœÐžÐµÐŒ, Ð² ÑÐ°Ð·Ð²ÐžÐ²Ð°ÑÑÐžÑ
+ÑÑ ÑÑÑÐ°ÐœÐ°Ñ
+ Ð¿ÐŸÐ»ÑÑÐ°ÑÑ ÐŸÐºÐŸÐ»ÐŸ $150 Ð² ÐŒÐµÑÑÑ. ÐÑ
+ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÐµÐ»ÑÐœÐŸÑÑÑ ÐŒÐŸÐ¶ÐµÑ ÑÐŸÑÑÐ°Ð²Ð»ÑÑÑ 20-30 ÑÑÑÐ°ÐœÐžÑ Ð² ÐŽÐµÐœÑ, ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸ 400 ÑÑÑÐ°ÐœÐžÑ Ð² ÐŒÐµÑÑÑ, Ð²ÐºÐ»ÑÑÐ°Ñ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ. Ð¡ ÐŽÐ²ÐŸÐ¹ÐœÑÐŒ ÐœÐ°Ð±ÐŸÑÐŸÐŒ ÑÑÐŸ ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ $300 Ð² ÐŒÐµÑÑÑ Ð¿Ð»ÑÑ ÐŽÑÑÐ³ÐžÐµ Ð·Ð°ÑÑÐ°ÑÑ.</Text>
+</Content>
+</Subsection>
+<Subsection id="image_files">
+<Title>
+<Text id="223">Ð€Ð°Ð¹Ð»Ñ ÐÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ</Text>
+</Title>
+<Content>
+<Text id="224">ÐÑÐµÐœÑ ÐŽÐµÑÐµÐ²ÐŸÐ¹ Ð°Ð»ÑÑÐµÑÐœÐ°ÑÐžÐ²ÐŸÐ¹ ÐÐ Ð¡ ÑÐ²Ð»ÑÐµÑÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ Ð¿ÑÐŸÑÑÐŸÐ³ÐŸ ÑÐŸÑÐŒÐ°ÑÐ° PDF ÐŽÐ»Ñ Ð²ÑÐµÑ
+ ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². ÐŠÐµÐœÐ° ÑÐŸÑÑÐ°Ð²Ð»ÑÐµÑ Ð²ÑÐµÐ³ÐŸ Ð»ÐžÑÑ ÑÐ°ÑÑÑ ÐŸÑ ÑÑÐŸÐžÐŒÐŸÑÑÐž ÐÐ Ð¡ â ÐŸÐºÐŸÐ»ÐŸ $0.1 Ð·Ð° ÑÑÑÐ°ÐœÐžÑÑ.</Text>
+<Text id="225">ÐÐŸÑÐ»Ðµ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº Ð·Ð°Ð²ÐµÑÑÐµÐœÐŸ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ðž ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒ ÑÐ°Ð¹Ð»Ñ TIFF, Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐžÐ¹ ÐºÐŸÐœÐ²ÐµÑÑÐµÑ ÐŒÐŸÐ¶ÐµÑ (ÐŸÐ±ÑÑÐœÐŸ Adobe Acrobat, Adobe Photoshop) Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÑÑ Ð²ÑÐµ ÑÐ°Ð¹Ð»Ñ ÑÐŸÑÐŒÐ°ÑÐ° TIFF Ð² ÑÐ°Ð¹Ð»Ñ PDF.</Text>
+<Text id="226">ÐÑÑÐžÑÐ°ÑÐµÐ»ÑÐœÐŸÐ¹ ÑÐµÑÑÐŸÐ¹ ÑÐ°ÐºÐžÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÑÐ²Ð»ÑÐµÑÑÑ ÑÐŸ, ÑÑÐŸ Ð¿ÐŸ ÐœÐžÐŒ ÐœÐµÐ»ÑÐ·Ñ ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÑÑ Ð¿ÐŸÐžÑÐº. Ð ÑÐŸÐŒÑ Ð¶Ðµ ÐŸÐœÐž ÐŽÐŸÐ²ÐŸÐ»ÑÐœÐŸ Ð±ÐŸÐ»ÑÑÐžÑ
+ ÑÐ°Ð·ÐŒÐµÑÐŸÐ², ÐŸÐ±ÑÑÐœÐŸ 50ÐºÐ± ÐœÐ° ÑÑÑÐ°ÐœÐžÑÑ Ð¿Ð»ÑÑ 20% Ð² Ð·Ð°Ð²ÐžÑÐžÐŒÐŸÑÑÐž ÐŸÑ ÐºÐ°ÑÐµÑÑÐ²Ð° ÑÐ°Ð¹Ð»Ð° TIFF.</Text>
+<Text id="227">Ð€Ð°Ð¹Ð»Ñ PDF ÐŸÑÐµÐœÑ ÐŽÐŸÐ»Ð³ÐŸ Ð·Ð°Ð³ÑÑÐ¶Ð°ÑÑÑÑ Ñ ÐÐœÑÐµÑÐœÐµÑÐ° (Ð² ÑÐ°Ð·Ð²ÐžÐ²Ð°ÑÑÐžÑ
+ÑÑ ÑÑÑÐ°ÐœÐ°Ñ
+ ÑÑÐŸ ÐŸÑÐµÐœÑ ÐŽÐŸÑÐŸÐ³ÐŸ Ðž ÐŒÐœÐŸÐ³ÐžÐŒ ÐœÐµ Ð¿ÐŸ ÐºÐ°ÑÐŒÐ°ÐœÑ). ÐÐœÐž ÑÐµÐŽÐºÐŸ Ð¿ÐŸÐŒÐµÑÐ°ÑÑÑÑ ÐœÐ° ÑÐ»ÐŸÐ¿Ð¿Ðž-ÐŽÐžÑÐºÐµ Ðž ÐœÐµ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑ ÑÐ°ÐºÐžÐµ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÑÐµ ÑÑÐœÐºÑÐžÐž, ÐºÐ°Ðº "Ð²ÑÑÐµÐ·Ð°ÑÑ" Ðž "Ð²ÑÑÐ°Ð²ÐžÑÑ".</Text>
+<Text id="228">ÐÑÐžÐ±ÐµÐ³Ð°ÑÑ Ðº ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ PDF-ÑÐ°Ð¹Ð»ÐŸÐ² ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÑÐŸÐ»ÑÐºÐŸ ÑÐŸÐ³ÐŽÐ°, ÐºÐŸÐ³ÐŽÐ° ÐœÐµÑ ÐŽÐµÐœÐµÐ³ ÐœÐ° ÐÐ Ð¡, Ðž ÐŽÐ»Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐŽÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÑ ÐŸÑÐœÐŸÑÐžÑÐµÐ»ÑÐœÐŸ ÐŒÐ°Ð»ÑÐŒ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸÐŒ Ð»ÑÐŽÐµÐ¹, ÐžÐŒÐµÑÑÐžÑ
+ Ð±ÑÑÑÑÑÑ ÐÐœÑÐµÑÐœÐµÑ-ÑÐ²ÑÐ·Ñ.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="combining_scanning_and_ocr">
+<Title>
+<Text id="229">Ð¡ÐŸÐ²ÐŒÐµÑÐµÐœÐžÐµ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ Ñ ÐÐ Ð¡</Text>
+</Title>
+<Content>
+<Text id="230">ÐÑÐ»Ðž ÑÐºÐ°ÐœÐµÑ ÐœÐ°Ð¿ÑÑÐŒÑÑ Ð¿ÐŸÐŽÐºÐ»ÑÑÐµÐœ Ðº ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÑ, ÐœÐ° ÐºÐŸÑÐŸÑÐŸÐŒ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐÐ Ð¡, ÑÐŸ Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ ÑÑÐžÑ
+ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒ ÐŒÐŸÐ¶ÐµÑ Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑÑ Ð¿ÑÐŸÑÐµÑÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ Ðž ÐÐ Ð¡ ÐŸÐŽÐœÐŸÐ²ÑÐµÐŒÐµÐœÐœÐŸ. Ð­ÑÐŸÑ ÐŒÐµÑÐŸÐŽ ÑÐ²Ð»ÑÐµÑÑÑ Ñ
+ÐŸÑÐŸÑÐµÐ¹ ÑÑÑÐ°ÑÐµÐ³ÐžÐµÐ¹, ÐµÑÐ»Ðž Ð²Ñ ÑÐ°Ð±ÐŸÑÐ°ÐµÑÐµ Ñ ÐœÐµÐ±ÐŸÐ»ÑÑÐžÐŒ ÐŸÐ±ÑÐµÐŒÐŸÐŒ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž, ÐœÐŸ Ð·Ð°Ð¹ÐŒÐµÑ ÐŸÑÐµÐœÑ ÐŒÐœÐŸÐ³ÐŸ Ð²ÑÐµÐŒÐµÐœÐž, ÐµÑÐ»Ðž ÐŸÐœ Ð²ÐµÐ»ÐžÐº.</Text>
+<Text id="231">ÐÑÐ»Ðž Ð²Ñ Ð¶ÐµÐ»Ð°ÐµÑÐµ Ð¿ÑÐžÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑÑÑ ÑÐµÐŒÐ¿Ð° 100-150 ÑÑÑÐ°ÐœÐžÑ Ð² ÐŒÐµÑÑÑ, ÑÐŸ ÑÑÐŸÑ ÐŒÐµÑÐŸÐŽ ÐŽÐ»Ñ Ð²Ð°Ñ. ÐÐ»Ñ Ð±ÐŸÐ»ÑÑÐµÐ³ÐŸ ÐŸÐ±ÑÐµÐŒÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð±ÑÑÑÑÐµÐµ Ðž ÑÐŽÐŸÐ±ÐœÐµÐµ ÑÐŸÐ²ÐµÑÑÐ°ÑÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐŸÑÐŽÐµÐ»ÑÐœÐŸ ÐŸÑ ÐÐ Ð¡.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="three_examples">
+<Title>
+<Text id="232">
+<br/>Ð¢ÑÐž Ð¿ÑÐžÐŒÐµÑÐ°: ÐŸÑ 1000 ÐŽÐŸ 100.000 ÑÑÑÐ°ÐœÐžÑ</Text>
+</Title>
+<Content>
+<Section id="typical_small_collection">
+<Title>
+<Text id="233">Â  ÐÐµÐ±ÐŸÐ»ÑÑÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ: ÐŸÑ 500 ÐŽÐŸ 1000 ÑÑÑÐ°ÐœÐžÑ</Text>
+</Title>
+<Content>
+<Text id="234">ÐÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ ÐÐÐ ÐœÑÐ¶ÐŽÐ°ÑÑÑÑ Ð² ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐž ÐŒÐ°ÑÐµÑÐžÐ°Ð»Ð° ÐŸÐ±ÑÐµÐŒÐŸÐŒ 5000-1000 ÑÑÑÐ°ÐœÐžÑ. Ð­ÑÐŸ ÐŒÐŸÐ¶ÐœÐŸ ÐŸÑÑÑÐµÑÑÐ²ÐžÑÑ Ðž Ð¿ÑÐŸÐ²ÐµÑÑÐž Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐÐ Ð¡ Ð±ÐµÐ· ÐŸÑÐŸÐ±ÐŸÐ³ÐŸ ÑÑÑÐŽÐ° Ð¿ÑÐž ÐœÐ°Ð»ÐžÑÐžÐž Ð²ÑÑÐŸÐºÐŸ ÑÐµÐ»ÐµÑÑÑÑÐµÐŒÐ»ÐµÐœÐœÑÑ
+ ÑÐ°Ð±ÐŸÑÐœÐžÐºÐŸÐ².</Text>
+<Part id="scanning">
+<Title>
+<Text id="235">Ð¡ÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ</Text>
+</Title>
+<Content>
+<Text id="236">ÐÐµÑÐ²ÑÐ¹ ÑÐ°Ð³ ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐž ÐŒÐ°ÑÐµÑÐžÐ°Ð»Ð° ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÑÐµÐœÐžÑ ÐµÐ³ÐŸ Ð² ÐºÐ°ÑÐµÑÑÐ²ÐµÐœÐœÐŸÐŒ ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐŒ ÑÐŸÑÐŒÐ°ÑÐµ TIFF - ÐœÐ° ÐºÐ°Ð¶ÐŽÑÑ ÑÑÑÐ°ÐœÐžÑÑ Ð¿ÐŸ ÐŸÐŽÐœÐŸÐŒÑ ÑÐ°Ð¹Ð»Ñ. Ð ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐ°Ñ
+ ÐœÐ°ÐŽÐŸ Ð¿ÐŸÐŽÐ±ÐžÑÐ°ÑÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐµ ÑÐµÐ¶ÐžÐŒÑ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÐžÐ¿Ð° ÑÐžÑÑÐœÐºÐ°. ÐÑÐµÐŽÐ¿ÐŸÐ»ÐŸÐ¶ÐžÐŒ, ÑÑÐŸ Ð·Ð°ÐŽÐ°ÑÐ° ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸÐ±Ñ ÐŸÑÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÑÑ 1000 ÑÑÑÐ°ÐœÐžÑ. Ð­ÑÐŸ ÐŒÐŸÐ¶ÐœÐŸ ÐŸÑÐ³Ð°ÐœÐžÐ·ÐŸÐ²Ð°ÑÑ, ÐœÐ°ÐœÑÐ² ÑÐ°Ð±ÐŸÑÐœÐžÐºÐŸÐ² ÐœÐ° Ð¿ÐŸÐ»ÑÑÐ°Ð²ÐºÐž ÐœÐ° Ð¿ÑÐŸÑÑÐ¶ÐµÐœÐžÐž ÐŒÐµÑÑÑÐ° â ÑÐŸÐ»ÑÐºÐŸ ÐŽÐ»Ñ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ. Ð€Ð°Ð¹Ð»Ñ TIFF Ð·Ð°Ð¹ÐŒÑÑ ÐŸÑ 60 ÐŽÐŸ 80ÐÐ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ð° ÐœÐ° Ð¶ÐµÑÑÐºÐŸÐŒ ÐŽÐžÑÐºÐµ Ðž Ð»ÑÑÑÐµ Ð²ÑÐµÐ³ÐŸ ÑÐ°ÐºÐ¶Ðµ Ð·Ð°Ð¿ÐžÑÐ°ÑÑ ÑÑÐž ÑÐ°Ð¹Ð»Ñ ÐœÐ° ÐºÐŸÐŒÐ¿Ð°ÐºÑ-ÐŽÐžÑÐº (CD-ROM). ÐÐµÐŽÐŸÑÐŸÐ³ÐŸÐ¹ ÐœÐ°ÑÑÐŸÐ»ÑÐœÑÐ¹ ÑÐºÐ°ÐœÐµÑ ÑÐµÐœÐŸÐ¹ $ 100-300 Ð±ÑÐŽÐµÑ ÐŽÐŸÑÑÐ°ÑÐŸÑÐµÐœ ÐŽÐ»Ñ ÑÑÐŸÐ¹ ÑÐ°Ð±ÐŸÑÑ. Ð¡ÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐŒÐŸÐ¶ÐœÐŸ Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑÑ Ð²ÐµÑÐµÑÐŸÐŒ ÐžÐ»Ðž Ð¿ÐŸ Ð²ÑÑ
+ÐŸÐŽÐœÑÐŒ.</Text>
+</Content>
+</Part>
+<Part id="ocr">
+<Title>
+<Text id="237">ÐÐ Ð¡</Text>
+</Title>
+<Content>
+<Text id="238">Ð¡Ð»ÐµÐŽÑÑÑÐžÐ¹ ÑÐ°Ð³ - ÑÑÐŸ Ð¿ÑÐŸÐ²ÐµÑÑÐž Ð¿ÑÐŸÑÐµÑÑ ÐÐ Ð¡ ÐŸÐŽÐœÐžÐŒ ÐžÐ»Ðž ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÐŒÐž ÑÐ°Ð±ÐŸÑÐœÐžÐºÐ°ÐŒÐž, ÐžÐŒÐµÑÑÐžÐŒÐž Ñ
+ÐŸÑÐŸÑÐžÐµ ÑÐ·ÑÐºÐŸÐ²ÑÐµ ÐœÐ°Ð²ÑÐºÐž. Ð€Ð°Ð¹Ð»Ñ TIFF ÐŒÐŸÐ¶ÐœÐŸ ÑÐ°ÑÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ Ð¿ÐŸ ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐ°ÐŒ ÐžÐ»Ðž Ð²ÑÐ¿ÐŸÐ»ÐœÑÑÑ Ð²ÑÑ ÑÐ°Ð±ÐŸÑÑ ÐœÐ° ÐŸÐŽÐœÐŸÐŒ. ÐÐ±ÑÑÐœÐŸ ÑÑÐŸ Ð·Ð°Ð¹ÐŒÐµÑ ÐŸÐºÐŸÐ»ÐŸ Ð¿ÑÑÐž ÐžÐ»Ðž ÑÐµÑÑÐž ÐŒÐµÑÑÑÐµÐ² ÐŽÐ»Ñ ÑÐ°Ð±ÐŸÑÐœÐžÐºÐ° ÐœÐ° Ð¿ÐŸÐ» -ÑÑÐ°Ð²ÐºÐž (Ð¿ÑÐžÐŒÐµÑÐœÐŸ 20 ÑÐ°ÑÐŸÐ² Ð² ÐœÐµÐŽÐµÐ»Ñ) ÐŽÐ»Ñ Ð¿ÐŸÐ»ÐœÐŸÐ¹ Ðž Ð±ÐµÐ·ÐŸÑÐžÐ±ÐŸÑÐœÐŸÐ¹ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐºÐž 1000 ÑÑÑÐ°ÐœÐžÑ Ð² ÑÐ°Ð¹Ð»Ñ Word ÐžÐ»Ðž HTML-ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ².</Text>
+</Content>
+</Part>
+<Part id="outsourcing">
+<Title>
+<Text id="239">ÐÐŸÑÑÑÐµÐœÐžÐµ ÐŽÑÑÐ³ÐžÐŒ</Text>
+</Title>
+<Content>
+<Text id="240">Ð ÐºÐ°ÑÐµÑÑÐ²Ðµ Ð°Ð»ÑÑÐµÑÐœÐ°ÑÐžÐ²Ñ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐŸÑÑÑÐžÑÑ ÑÑÑ ÑÐ°Ð±ÐŸÑÑ Ð¿ÑÐŸÑÐµÑÑÐžÐŸÐœÐ°Ð»ÑÐœÐŸÐ¹ ÐºÐŸÐŒÐ¿Ð°ÐœÐžÐž. Ð­ÑÐŸ Ð±ÑÐŽÐµÑ ÑÑÐŸÐžÑÑ ÐŸÐºÐŸÐ»ÐŸ $1500-$2000 ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÑÐµÐœÐžÑ ÐŸÑÐ»ÐžÑÐœÑÑ
+ Word ÐžÐ»Ðž HTML-ÑÐ°Ð¹Ð»ÐŸÐ².</Text>
+</Content>
+</Part>
+</Content>
+</Section>
+<Section id="all_publications_from_an_organization">
+<Title>
+<Text id="241">ÐÑÐµ Ð¿ÑÐ±Ð»ÐžÐºÐ°ÑÐžÐž ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐž: 5000 ÑÑÑÐ°ÐœÐžÑ</Text>
+</Title>
+<Content>
+<Text id="242">ÐÐœÐŸÐ³ÐžÐµ Ð±ÐŸÐ»ÑÑÐžÐµ ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐž ÐžÐŒÐµÑÑ Ð°ÑÑ
+ÐžÐ²Ñ, ÑÐŸÑÑÐŸÑÑÐžÐµ Ð¿ÑÐžÐŒÐµÑÐœÐŸ ÐžÐ· 5000 ÑÑÑÐ°ÐœÐžÑ ÐžÐ·ÐŽÐ°ÐœÐžÐ¹, ÐºÐœÐžÐ³, ÑÐ°Ð·Ð»ÐžÑÐœÐŸÐ³ÐŸ ÑÐŸÐŽÐ° Ð»ÐžÑÐµÑÐ°ÑÑÑÑ, ÐºÐŸÑÐŸÑÑÐµ ÑÐ¶Ðµ ÐœÐµ ÐžÐ·ÐŽÐ°ÑÑÑÑ.</Text>
+<Part id="scanning_1">
+<Title>
+<Text id="243">Ð¡ÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ</Text>
+</Title>
+<Content>
+<Text id="244">Ð­ÑÐŸ ÑÐ»ÐžÑÐºÐŸÐŒ Ð±ÐŸÐ»ÑÑÐŸÐ¹ ÐŸÐ±ÑÐµÐŒ ÐŽÐ»Ñ Ð¿ÑÐŸÑÑÐŸÐ³ÐŸ ÐœÐ°ÑÑÐŸÐ»ÑÐºÐŸ ÑÐºÐ°ÐœÐµÑÐ°. Ð¡ÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð»ÑÑÑÐµ Ð»ÐžÐ±ÐŸ Ð¿ÐŸÑÑÑÐžÑÑ ÐºÐŸÐŒÐ¿Ð°ÐœÐžÐž (ÐŸÐºÐŸÐ»ÐŸ $400 Ð·Ð° 5000 ÑÑÑÐ°ÐœÐžÑ) ÐžÐ»Ðž Ð¿ÑÐžÐŸÐ±ÑÐµÑÑÐž ÑÐºÐ°ÐœÐµÑ Ñ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐŸÐ¹ Ð¿ÐŸÐŽÐ°ÑÐµÐ¹ ÑÑÑÐ°ÐœÐžÑ (ÐŸÐºÐŸÐ»ÐŸ $900). ÐÐŸÐ¶ÐœÐŸ ÑÐ°ÐºÐ¶Ðµ Ð¿ÑÐžÐŸÐ±ÑÐµÑÑÐž ÑÐºÐ°ÐœÐµÑ ÑÐŸÐ²ÐŒÐµÑÑÐœÐŸ Ñ ÐŽÑÑÐ³ÐžÐŒÐž ÐÐÐ ÐžÐ»Ðž ÐŽÑÑÐ³ÐžÐŒÐž ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑÐŒÐž ($6000 ÑÐ°Ð·ÐŽÐµÐ»ÐžÑÑ ÐœÐ° ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ ÑÐŸÐ²Ð»Ð°ÐŽÐµÐ»ÑÑÐµÐ²). ÐÑÐµ 5000 ÑÑÑÐ°ÐœÐžÑ Ð·Ð°Ð¹ÐŒÑÑ ÐŸÐºÐŸÐ»ÐŸ 300-400 MB, Ðž ÑÐœÐŸÐ²Ð° ÐŒÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÐŒ Ð²Ð°ÐŒ Ð¿Ð°ÑÐ°Ð»Ð»ÐµÐ»ÑÐœÐŸ Ð·Ð°Ð¿ÐžÑÐ°ÑÑ ÑÑÐŸ ÐœÐ° CD.</Text>
+</Content>
+</Part>
+<Part id="ocr_1">
+<Title>
+<Text id="245">ÐÐ Ð¡</Text>
+</Title>
+<Content>
+<Text id="246">Ð ÑÐœÐŸÐ²Ð° Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ Ð¿ÑÐŸÐ¹ÑÐž ÑÐµÑÐµÐ· Ð¿ÑÐŸÑÐµÑÑ ÐÐ Ð¡, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÑÑ
+ÐŸÐ¶ÑÑ ÑÐ°Ð±ÐŸÑÑÑ ÑÐžÐ»Ñ, ÑÑÐŸ Ðž Ð² Ð¿ÑÐµÐŽÑÐŽÑÑÐµÐŒ ÑÐ»ÑÑÐ°Ðµ. ÐÐŸÐ¶ÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŸÐŽÐžÐœ ÐžÐ»Ðž ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐŸÐ². ÐÐ° 5000 ÑÑÑÐ°ÐœÐžÑ ÑÑÐŸ Ð·Ð°Ð¹ÐŒÐµÑ ÐŸÐºÐŸÐ»ÐŸ 25-30 ÐŒÐµÑÑÑÐµÐ² Ð¿ÑÐž ÑÐ°Ð±ÐŸÑÐµ Ð¿ÐŸ 20 ÑÐ°ÑÐŸÐ² Ð² ÐœÐµÐŽÐµÐ»Ñ. ÐÐ° Ð¿ÑÐ°ÐºÑÐžÐºÐµ ÑÑÐŸ ÐŸÑÐµÐœÑ ÐŽÐŸÐ»Ð³ÐžÐ¹ ÑÑÐŸÐº. ÐÑÐ¶ÐµÐœ ÑÐµÐ»ÐŸÐ²ÐµÐº, ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÑÐ¹ Ð·Ð° Ð¿Ð»Ð°ÑÑ ÑÐ°Ð±ÐŸÑÐœÐžÐºÐ°ÐŒ, ÐœÐ°ÐŽÐ·ÐŸÑÐŸÐŒ Ð·Ð° ÐºÐ°ÑÐµÑÑÐ²ÐŸÐŒ, Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÐ³ÐŸ ÐŒÐµÑÑÐ° Ðž Ñ.ÐŽ. ÐŽÐ»Ñ ÐŸÐºÐŸÐœÑÐ°ÐœÐžÑ ÑÐ°Ð±ÐŸÑÑ ÐºÐ°ÑÐµÑÑÐ²ÐµÐœÐœÐŸ Ðž Ð·Ð° ÐŒÐµÐœÐµÐµ ÐºÐŸÑÐŸÑÐºÐžÐ¹ ÑÑÐŸÐº.</Text>
+<Text id="247">ÐÐŸÐ¶ÐœÐŸ ÑÐ°ÐºÐ¶Ðµ ÑÐŸÐ·ÐŽÐ°ÑÑ ÑÐ°Ð¹Ð»Ñ PDF, ÐºÐŸÑÐŸÑÑÐµ Ð·Ð°Ð¹ÐŒÑÑ ÐŸÐºÐŸÐ»ÐŸ 300-400 MB Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ð° Ðž Ð±ÑÐŽÑÑ ÐŸÑÐµÐœÑ ÐŽÐŸÐ»Ð³ÐŸ Ð·Ð°Ð³ÑÑÐ¶Ð°ÑÑÑÑ ÑÐµÑÐµÐ· ÐÐœÑÐµÑÐœÐµÑ.</Text>
+</Content>
+</Part>
+<Part id="outsourcing_1">
+<Title>
+<Text id="248">ÐÐŸÑÑÑÐµÐœÐžÐµ ÐŽÑÑÐ³ÐžÐŒ</Text>
+</Title>
+<Content>
+<Text id="249">ÐÐŸÐ¶ÐœÐŸ Ð¿ÐŸÑÑÑÐžÑÑ ÐŽÑÑÐ³ÐŸÐ¹ ÐºÐŸÐŒÐ¿Ð°ÐœÐžÐž ÐºÐ°Ðº ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ, ÑÐ°Ðº Ðž ÐÐ Ð¡. Ð­ÑÐŸ Ð±ÑÐŽÐµÑ ÑÑÐŸÐžÑÑ ÐŸÑ $7500 ÐŽÐŸ $10000 Ð·Ð° Ð²ÑÑ ÑÐ°Ð±ÐŸÑÑ.</Text>
+</Content>
+</Part>
+</Content>
+</Section>
+<Section id="a_small_library">
+<Title>
+<Text id="250">ÐÐµÐ±ÐŸÐ»ÑÑÐ°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°: 100.000 ÑÑÑÐ°ÐœÐžÑ</Text>
+</Title>
+<Content>
+<Text id="251">Ð Ð°Ð·Ð»ÐžÑÐœÑÐµ ÐºÑÑÐ¿ÐœÑÐµ ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐž, ÑÐœÐžÐ²ÐµÑÑÐžÑÐµÑÑ, Ð¿ÑÐ°Ð²ÐžÑÐµÐ»ÑÑÑÐ²ÐŸ Ðž ÑÐ¿ÐµÑÐžÐ°Ð»ÐžÐ·ÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž ÐŒÐŸÐ³ÑÑ Ð¿ÐŸÐ¶ÐµÐ»Ð°ÑÑ Ð¿ÐµÑÐµÐ²ÐµÑÑÐž Ð²ÑÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÑ Ð² ÑÐžÑÑÐŸÐ²ÐŸÐ¹ ÑÐŸÑÐŒÐ°Ñ â ÐŽÐŸÐ¿ÑÑÑÐžÐŒ 100.000 ÑÑÑÐ°ÐœÐžÑ. ÐÐµÑÐ²Ð°Ñ Ð²ÐµÑÑ, ÐŸ ÐºÐŸÑÐŸÑÐŸÐ¹ ÑÐ»ÐµÐŽÑÐµÑ Ð¿ÐŸÐ·Ð°Ð±ÐŸÑÐžÑÑÑÑ, - ÑÑÐŸ Ð°Ð²ÑÐŸÑÑÐºÐžÐµ Ð¿ÑÐ°Ð²Ð° ÐœÐ° Ð²ÑÐµ ÐžÐ·ÐŽÐ°ÐœÐžÑ. ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ Ð¿ÐŸÐ»ÑÑÐžÑÑ ÑÐ°Ð·ÑÐµÑÐµÐœÐžÐµ Ð²Ð»Ð°ÐŽÐµÐ»ÑÑÐµÐ² ÑÑÐžÑ
+ Ð¿ÑÐ°Ð² Ð¿ÐµÑÐµÐŽ ÑÐµÐŒ, ÐºÐ°Ðº ÐœÐ°ÑÐ°ÑÑ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ. ÐÐ°ÐŒ ÑÐ°ÐºÐ¶Ðµ ÑÐ»ÐµÐŽÑÐµÑ ÑÐ±ÐµÐŽÐžÑÑÑÑ Ð² ÑÐŸÐŒ, ÑÑÐŸ ÑÑÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÐµÑÐµ ÐœÐµ ÑÑÑÐµÑÑÐ²ÑÑÑ Ð² ÑÐžÑÑÐŸÐ²ÐŸÐŒ ÑÐŸÑÐŒÐ°ÑÐµ. </Text>
+<Part id="scanning_2">
+<Title>
+<Text id="252">Ð¡ÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ</Text>
+</Title>
+<Content>
+<Text id="253">Ð¢Ð°ÐºÐŸÐ¹ ÐŸÐ±ÑÐµÐŒ ÑÐ»ÐžÑÐºÐŸÐŒ Ð²ÐµÐ»ÐžÐº ÐŽÐ»Ñ ÑÐºÐ°ÐœÐµÑÐ° Ñ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐŸÐ¹ Ð¿ÐŸÐŽÐ°ÑÐµÐ¹ ÑÑÑÐ°ÐœÐžÑ. Ð­ÑÐŸ ÐœÑÐ¶ÐœÐŸ Ð»ÐžÐ±ÐŸ Ð¿ÐŸÑÑÑÐžÑÑ ÐŽÑÑÐ³ÐžÐŒ ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑÐŒ ($8000 Ð·Ð° 100.000 ÑÑÑÐ°ÐœÐžÑ) ÐžÐ»Ðž Ð¿ÑÐžÐŸÐ±ÑÐµÑÑÐž ÐŽÐŸÑÐŸÐ³ÐŸÐ¹ ÑÐºÐ°ÐœÐµÑ ÑÐŸÐ²ÐŒÐµÑÑÐœÐŸ Ñ ÐŽÑÑÐ³ÐžÐŒÐž ($6000). ÐÐ±ÑÐµÐŒ 100.000 ÑÑÑÐ°ÐœÐžÑ Ð·Ð°Ð¹ÐŒÐµÑ 6-8 GB. Ð¡ÐœÐŸÐ²Ð° Ð²Ð°ÐŒ Ð»ÑÑÑÐµ Ð¿ÐŸÐŒÐµÑÑÐžÑÑ ÐºÐŸÐ¿ÐžÑ Ð² ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐºÐŸÐŒÐ¿Ð°ÐºÑ-ÐŽÐžÑÐºÐŸÐ².</Text>
+</Content>
+</Part>
+<Part id="ocr_2">
+<Title>
+<Text id="254">ÐÐ Ð¡</Text>
+</Title>
+<Content>
+<Text id="255">ÐÑÐŸÑÐŸÐ¹ ÑÐ°Ð³ - ÑÑÐŸ Ð¿ÑÐŸÐ²ÐµÐŽÐµÐœÐžÐµ ÐÐ Ð¡ (ÐžÐ»Ðž ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ PDF-ÑÐ°Ð¹Ð»ÐŸÐ² ÐŽÐ»Ñ ÑÐµÐŽÐºÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²). Ð­ÑÐŸ Ð·Ð°Ð¹ÐŒÐµÑ ÐŸÐºÐŸÐ»ÐŸ 500 - 700 ÐŒÐµÑÑÑÐµÐ² ÐŽÐ»Ñ Ð²ÑÐµÐ³ÐŸ Ð¿ÑÐŸÑÐµÑÑÐ° ÐÐ Ð¡ Ðž Ð¿ÐµÑÐµÐ²ÐŸÐŽÐ° Ð² Word Ðž HTML Ð¿ÑÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž ÑÐ°Ð±ÐŸÑÐœÐžÐºÐŸÐ² ÐœÐ° Ð¿ÐŸÐ»ÑÑÐ°Ð²ÐºÐž. Ð­ÑÐŸ ÐœÐµÑÑÑÐµÐºÑÐžÐ²ÐœÐŸ, Ð¿ÐŸÑÑÐŸÐŒÑ Ð²Ð°ÐŒ Ð»ÑÑÑÐµ Ð¿ÐŸÑÑÑÐžÑÑ ÑÑÑ ÑÐ°Ð±ÐŸÑÑ Ð¿ÑÐŸÑÐµÑÑÐžÐŸÐœÐ°Ð»Ð°ÐŒ.</Text>
+<Text id="256">ÐÐ»Ñ ÑÐœÐžÐ¶ÐµÐœÐžÑ Ð·Ð°ÑÑÐ°Ñ Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ ÑÐµÐŽÐºÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÑ
+ ÑÑÑÐ°ÐœÐžÑ (ÑÐºÐ°Ð¶ÐµÐŒ, 80% ÐžÐ»Ðž 80.000 Ñ.) ÐŒÐŸÐ¶ÐœÐŸ ÐºÐŸÐœÐ²ÐµÑÑÐžÑÐŸÐ²Ð°ÑÑ Ð² ÑÐ°Ð¹Ð»Ñ PDF, Ð° ÐŸÑÑÐ°Ð»ÑÐœÑÐµ 20.000 Ð² Word, HTML. Ð€Ð°Ð¹Ð»Ñ PDF Ð·Ð°ÐœÑÐ»Ðž Ð±Ñ 4-6 GB, ÐŽÐŸÐ»Ð³ÐŸ Ð·Ð°Ð³ÑÑÐ¶Ð°ÐµÐŒÑÑ
+ ÑÐµÑÐµÐ· ÐÐœÑÐµÑÐœÐµÑ, ÐœÐŸ ÑÑÐŸÐžÐ»Ðž Ð±Ñ ÐŸÐœÐž $0.2 Ð·Ð° ÑÑÑÐ°ÐœÐžÑÑ Ñ Ð¿ÑÐŸÑÐµÑÑÐžÐŸÐœÐ°Ð»ÑÐœÐŸÐ¹ ÐºÐŸÐŒÐ¿Ð°ÐœÐžÐž ($16.000 ÐŽÐ»Ñ 80.000 Ñ.). ÐÑÐ»Ðž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐœÐ°ÐµÐŒÐœÑÐ¹ ÑÑÑÐŽ ÐŽÐ»Ñ ÐºÐŸÐœÐ²ÐµÑÑÐ°ÑÐžÐž TIFF Ð² PDF, ÑÐŸ ÑÑÐŸ Ð·Ð°ÐœÑÐ»ÐŸ Ð±Ñ 10-20 ÐŒÐµÑÑÑÐµÐ² ÑÐ°Ð±ÐŸÑÑ ÐœÐ° Ð¿ÐŸÐ»ÑÑÐ°Ð²ÐºÐž.</Text>
+</Content>
+</Part>
+<Part id="outsourcing_2">
+<Title>
+<Text id="257">ÐÐŸÑÑÑÐµÐœÐžÐµ ÐŽÑÑÐ³ÐžÐŒ</Text>
+</Title>
+<Content>
+<Text id="258">ÐÑÐ»Ðž ÑÐŸÑ
+ÑÐ°ÐœÐžÑÑ Ð¿ÑÐŸÐ¿ÐŸÑÑÐžÑ 80% PDF Ðž 20% HTML, Word, ÑÐŸ Ð¿ÐµÑÐ²Ð°Ñ ÑÐ°ÑÑÑ ÑÑÐŸÐžÑ ÐŸÐºÐŸÐ»ÐŸ $16.000, Ð° Ð²ÑÐŸÑÐ°Ñ - ÐŸÐºÐŸÐ»ÐŸ $30.000-$40.000, Ð° Ð² ÑÐµÐ»ÐŸÐŒ ÐŸÐºÐŸÐ»ÐŸ $50,000. ÐÑÐ»Ðž Ð²ÑÐµ Ð¿ÑÐŸÐ²ÐµÑÑÐž ÑÐµÑÐµÐ· ÐÐ Ð¡, ÑÑÐŸ Ð±ÑÐŽÐµÑ ÑÑÐŸÐžÑÑ $150.000-$200.000.</Text>
+</Content>
+</Part>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="creating_an_electronic_collection">
+<Title>
+<Text id="259">ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="260">Ð¡Ð»ÐµÐŽÑÐµÑ ÑÑÐžÑÑÐ²Ð°ÑÑ ÑÑÐž Ð²Ð°Ð¶ÐœÑÐµ Ð²ÐµÑÐž Ð¿ÑÐž Ð¿ÑÐžÐœÑÑÐžÐž ÑÐµÑÐµÐœÐžÑ ÐŸ ÑÐŸÐ·ÐŽÐ°ÐœÐžÐž ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐµÑÐ²ÐŸÐµ, ÐœÑÐ¶ÐœÐŸ ÑÑÐŸÐ±Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð±ÑÐ»Ð° ÐŸÑÐ³Ð°ÐœÐžÐ·ÐŸÐ²Ð°ÐœÐ° Ðž ÐžÐŒÐµÐ»Ð° ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ ÑÑÑÑÐºÑÑÑÑ. Ð§ÐµÐŒ Ð±ÐŸÐ»ÑÑÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ, ÑÐµÐŒ ÑÐ°Ð·ÐœÐŸÐŸÐ±ÑÐ°Ð·ÐœÐµÐµ ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐžÐœÐŽÐµÐºÑÑ Ðž ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐ° ÐŒÐŸÑÐœÐ°Ñ Ð¿ÐŸÐžÑÐºÐŸÐ²Ð°Ñ ÑÐžÑÑÐµÐŒÐ°. ÐÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐŸÐ±ÑÐµÐŒÐŸÐŒ 3000-5000 ÑÑÑÐ°ÐœÐžÑ ÐŸÑÐµÐœÑ Ð²Ð°Ð¶ÐœÐŸ ÐžÐŒÐµÑÑ ÑÑÐµÐ±ÐŸÐ²Ð°ÐœÐžÑ, ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÐµ Ð²ÑÑÐµ. ÐÐŸ-Ð²ÑÐŸÑÑÑ
+, Ð¿ÑÐµÐ¶ÐŽÐµ Ð²ÑÐµÐ³ÐŸ ÑÐ»ÐµÐŽÑÐµÑ ÑÑÐžÑÑÐ²Ð°ÑÑ ÐœÑÐ¶ÐŽÑ ÐºÐŸÐœÐµÑÐœÐŸÐ³ÐŸ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ. Ð¡Ð»ÐµÐŽÑÐµÑ ÑÐµÑÐºÐŸ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ Ð³ÑÑÐ¿Ð¿Ñ Ð»ÑÐŽÐµÐ¹, ÐŽÐ»Ñ ÐºÐŸÑÐŸÑÑÑ
+ ÑÐŸÐ·ÐŽÐ°ÐµÑÑÑ ÑÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, Ðž ÐœÐµÐ¿ÑÐµÐŒÐµÐœÐœÐŸ ÐŸÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÐžÐŒ ÐºÐŸÐœÑÑÐ»ÑÑÐ°ÑÐžÐŸÐœÐœÑÐµ ÑÑÐ»ÑÐ³Ðž. Ð ÐœÐ°ÐºÐŸÐœÐµÑ, ÐœÐ°Ð»ÐžÑÐžÐµ ÑÑÐµÐŽÑÑÐ² ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑ ÐŸÐ±ÑÐµÐŒ Ð¿ÐŸÑÐµÐœÑÐžÐ°Ð»ÑÐœÐŸÐ¹ ÑÐ°Ð±ÐŸÑÑ.</Text>
+<Section id="methods_of_collection_building">
+<Title>
+<Text id="261">Â  ÐÐµÑÐŸÐŽÑ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹</Text>
+</Title>
+<Content>
+<Text id="262">Ð¡ÑÑÐµÑÑÐ²ÑÐµÑ ÐŒÐœÐŸÐ³ÐŸ Ð¿ÑÐžÐŒÐµÑÐŸÐ² Ð¿ÑÐµÐ²ÐŸÑÑ
+ÐŸÐŽÐœÑÑ
+ ÐºÐŸÐŒÐ¿Ð°ÐºÑ-ÐŽÐžÑÐºÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐ·ÐŽÐ°ÐœÑ Ð¿ÐŸ ÐŒÐŸÐŽÐµÐ»Ðž Ð²ÐµÐ±-ÑÑÑÐ°ÐœÐžÑ. HTML, PDF ÐžÐ»Ðž ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Word ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑÑÑÑ Ðž ÑÐ²ÑÐ·ÑÐ²Ð°ÑÑÑÑ Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ Ð³ÐžÐ¿ÐµÑÑÑÑÐ»ÐŸÐº. ÐÐ°Ð²ÐžÐ³Ð°ÑÐžÑ ÑÐŽÐµÐ»Ð°ÐœÐ° Ð¿ÑÐŸÑÑÐŸÐ¹ Ðž Ð¿ÑÐžÐ²Ð»ÐµÐºÐ°ÑÐµÐ»ÑÐœÐŸÐ¹ Ð¿ÑÐž Ð¿ÐŸÐŒÐŸÑÐž Ð³ÐžÐ¿ÐµÑÑÐ²ÑÐ·ÐµÐ¹, ÑÑÐµÐ¹ÐŒÐŸÐ², ÐºÐ»ÑÑÐµÐ²ÑÑ
+ ÑÐ»ÐŸÐ², ÐžÐœÐŽÐµÐºÑÐŸÐ² Ðž Ñ.ÐŽ. Ð¢Ð°ÐºÐžÐµ ÑÐžÑÑÐµÐŒÑ ÑÐ°Ð±ÐŸÑÐ°ÑÑ Ñ
+ÐŸÑÐŸÑÐŸ Ð²Ð¿Ð»ÐŸÑÑ ÐŽÐŸ ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ ÑÑÑÑÑ ÑÑÑÐ°ÐœÐžÑ, ÐœÐŸ Ñ 3000 ÐŽÐŸ 5000 ÑÑÑÐ°ÐœÐžÑ Ð²Ð°Ð¶ÐœÐŸ ÐžÐŒÐµÑÑ Ñ
+ÐŸÑÐŸÑÐŸ ÑÑÑÑÐºÑÑÑÐžÑÐŸÐ²Ð°ÐœÐœÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ðž ÐŒÐŸÑÐœÑÐµ ÑÑÐµÐŽÑÑÐ²Ð° Ð¿ÐŸÐžÑÐºÐ°. ÐÐŒÐµÐœÐœÐŸ Ð² ÑÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ Greenstone ÐŒÐŸÐ¶ÐµÑ ÑÑÑÐµÐºÑÐžÐ²ÐœÐŸ Ð¿ÐŸÐŒÐŸÑÑ.</Text>
+<Text id="263">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ ÐŠÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone ÑÐŸÐ·ÐŽÐ°ÐµÑ ÑÑÑÑÐºÑÑÑÐžÑÐŸÐ²Ð°ÐœÐœÑÑ ÑÐžÑÑÐŸÐ²ÑÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÑ Ðž Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÐŸÑÐµÐœÑ ÐŒÐŸÑÐœÑÐµ Ð¿ÐŸÐžÑÐºÐŸÐ²ÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž Ðž ÑÑÐµÐŽÑÑÐ²Ð° Ð²ÐŸÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐžÑ. ÐÐŸ 150000 ÑÑÑÐ°ÐœÐžÑ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð¿ÑÐŸÐžÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐŸ ÐœÐ° ÐŸÑÐŽÐµÐ»ÑÐœÐŸÐŒ CD-ROM. ÐÐ°Ð¶ÐŽÑÐ¹ CD-ROM ÐŒÐŸÐ¶ÐµÑ ÑÑÐ°ÑÑ ÑÐµÑÐ²ÐµÑÐŸÐŒ ÐÐœÑÐµÑÐœÐµÑÐ°. Greenstone ÑÐ²Ð»ÑÐµÑÑÑ ÐŸÑÐºÑÑÑÑÐŒ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐŒ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµÐŒ Ñ ÐŸÑÐºÑÑÑÐŸÐ¹ ÐžÑÑ
+ÐŸÐŽÐœÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐŸÐ¹ Ðž ÑÐ²ÐŸÐ±ÐŸÐŽÐœÐŸ ÐŽÐŸÑÑÑÐ¿ÐœÐŸ ÑÐŸÐ³Ð»Ð°ÑÐœÐŸ Ð»ÐžÑÐµÐœÐ·ÐžÐž GNU.</Text>
+<Text id="264">Ð¡ÐŸÐ¿ÑÑÑÑÐ²ÑÑÑÐžÐµ ÑÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÐŸÐ¿ÐžÑÑÐ²Ð°ÑÑ, ÐºÐ°Ðº ÑÑÑÐŸÐžÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Greenstone. ÐÑÑÑ Ð¿ÐŸ ÑÑÑÐµÑÑÐ²Ñ ÑÑÐž ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ Ð¿ÑÑÐž ÐžÑ
+ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ:</Text>
+<BulletList>
+<Bullet>
+<Text id="265">ÐÐœÑÐµÑÑÐµÐ¹Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÑÑ </Text>
+</Bullet>
+<Bullet>
+<Text id="266">ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑ</Text>
+</Bullet>
+<Bullet>
+<Text id="267">ÐÐŸÑÑÑÐŸÐµÐœÐžÐµ ÐžÐ· ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐž.</Text>
+</Bullet>
+</BulletList>
+<Text id="268">ÐÐµÑÐ²ÑÐ¹ ÐŒÐµÑÐŸÐŽ - "Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐžÐ¹" ÐžÐœÑÐµÑÑÐµÐ¹Ñ, ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÐ¹ Ð² ÑÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ðµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð¿ÐŸ ÐŠÐžÑÑÐŸÐ²ÐŸÐ¹ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐµ ÐÑÐžÐœÑÑÐŸÑÐœ (ÐÐ»Ð°Ð²Ð° 3, Â«Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐÑÐžÐœÑÑÐŸÑÐœÂ»). Ð­ÑÐŸ - Ð²ÑÐµÑÑÐŸÑÐŸÐœÐœÐµÐµ ÐŽÐžÐ°Ð»ÐŸÐ³ÐŸÐ²ÐŸÐµ ÑÑÐµÐŽÑÑÐ²ÐŸ ÐŽÐ»Ñ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹. Ð¡ ÑÑÐžÐŒ, ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÑÑÐŸÐžÑÑ ÐœÐ°Ð±ÐŸÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐžÐ»Ðž ÐœÐ°Ð·ÐœÐ°ÑÐ°ÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, Ðž ÐŸÐ±ÑÐµÐŽÐžÐœÑÑÑ ÐžÑ
+ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐÑÐžÐœÑÑÐŸÑÐœ. ÐÑÐŸÑÐŸÐ¹Â  ÐŒÐµÑÐŸÐŽ - "ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑ" Ð¿ÐŸÐŽÑÐžÑÑÐµÐŒÐ°, ÐŸÐ¿ÐžÑÐ°ÐœÐœÐ°Ñ Ð² 4 ÐÐ»Ð°Ð²Ðµ Ð² ÑÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ðµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ. Ð­ÑÐŸ â Ð¿ÑÐµÐŽÐžÐŽÑÑÐµÐµ ÑÑÐµÐŽÑÑÐ²ÐŸ, ÐºÐŸÑÐŸÑÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ Ð°Ð»ÑÑÐµÑÐœÐ°ÑÐžÐ²ÐœÑÐ¹ Ð¿ÑÑÑ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ ÑÐµÑÐž ÐžÐ»Ðž ÐŽÑÑÐ³ÐžÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². ÐÐµÐŽÑÑÐµÐµ ÐÐ°Ñ ÑÐµÑÐµÐ· Ð¿ÐŸÑÐ»ÐµÐŽÐŸÐ²Ð°ÑÐµÐ»ÑÐœÐŸÑÑÑ ÐŽÐžÐ°Ð»ÐŸÐ³ÐŸÐ²ÑÑ
+ Ð²ÐµÐ± ÑÑÑÐ°ÐœÐžÑ, ÐºÐŸÑÐŸÑÑÐµ Ð·Ð°Ð¿ÑÐ°ÑÐžÐ²Ð°ÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ. ÐÐŽÐœÐ°ÐºÐŸ, ÑÑÐŸ ÐœÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ, ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðº ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ, Ðž - Ð¿ÐŸÑÐºÐŸÐ»ÑÐºÑ ÑÑÐŸ â Ð²ÐµÐ± ÐžÐœÑÐµÑÑÐµÐ¹Ñ - ÑÑÐŸ ÐœÐµ Ð²ÑÐµÐ³ÐŽÐ° Ð¿ÐŸÐŽÑ
+ÐŸÐŽÑÑÐµÐµ ÑÑÐµÐŽÑÑÐ²ÐŸ ÐŽÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÐºÐŸÑÐŸÑÑÐµ ÑÑÐµÐ±ÑÑÑ Ð±ÐŸÐ»ÑÑÐµ ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ ÐŒÐžÐœÑÑ ÐŽÐ»Ñ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ. Ð¢ÑÐµÑÐžÐ¹ ÐŒÐµÑÐŸÐŽ ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸÐ±Ñ ÑÐ¿ÑÐ°Ð²Ð»ÑÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ°ÐŒÐž ÐŽÐ»Ñ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ ÐžÐ· ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐž; ÑÑÐŸ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² ÑÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ðµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð¿ÐŸ ÐŠÐžÑÑÐŸÐ²ÐŸÐ¹ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐµ ÐÑÐžÐœÑÑÐŸÑÐœ (ÐÐ»Ð°Ð²Ð° 1). Ð­ÑÐŸ ÐŽÐ°ÐµÑ Ð±ÐŸÐ»ÑÑÐµÐµ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ Ð³ÐžÐ±ÐºÐŸÑÑÐž ÐŽÐ»Ñ ÐžÐœÐŽÐžÐ²ÐžÐŽÑÐ°Ð»ÑÐœÐŸÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒ, ÑÐºÐŸÐœÐŸÐŒÑ ÐœÐ° Ð¿ÑÐŸÐŒÐµÐ¶ÑÑÐŸÑÐœÑÑ
+ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐ°Ñ
+, Ðž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÑ ÐŽÐ»Ñ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÐºÐŸÑÐŸÑÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑ ÐŸÑÐµÐœÑ ÐŒÐœÐŸÐ³ÐŸ Ð²ÑÐµÐŒÐµÐœÐž. ÐÐ°ÐŒ Ð±ÑÐŽÐµÑ ÑÐ°ÐºÐ¶Ðµ Ð¿ÐŸÐ»ÐµÐ·ÐœÐŸ Ð¿ÑÐŸÑÐžÑÐ°ÑÑ Ð³Ð»Ð°Ð²Ñ 2 ÐÐžÐŽÐ° ÑÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ðµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÑÑÐŸÐ±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð²ÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐžÂ  ÐÑÐžÐœÑÑÐŸÑÐœ, ÑÑÐŸÐ±Ñ ÑÑÑÐŸÐžÑÑ Ð¿ÑÐŸÐŽÐ²ÐžÐœÑÑÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="269">ÐÑÑÑ ÑÐ°ÐºÐ¶Ðµ ÑÐµÑÐ²ÐµÑÑÑÐ¹ ÐŒÐµÑÐŸÐŽ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ Ðž ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐŒÐ°ÑÐµÑÐžÐ°Ð»ÐŸÐ² Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ, Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÐŸÐ¹ ÐÑÐ³Ð°ÐœÐ°Ð¹Ð·ÐµÑÐŸÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹. ÐÐŽÐœÐ°ÐºÐŸ, ÐµÐµ ÑÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž Ð±ÑÐ» Ð·Ð°ÐŒÐµÐœÐµÐœÑ Ð²ÑÑÐµ ÑÐ¿ÐŸÐŒÑÐœÑÑÑÐŒ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐŸÐŒ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÑÑ. ÐÐ¿ÐžÑÐ°ÐœÐœÑÐŒ Ð² ÐŽÐŸÐºÑÐŒÐµÐœÑÐµ ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÐÑÐ³Ð°ÐœÐ°Ð¹Ð·ÐµÑÐ°.</Text>
+</Content>
+</Section>
+<Section id="getting_started_in_seven_steps_and_15_minutes">
+<Title>
+<Text id="270">ÐÐ±ÑÑÐµÐœÐžÐµ Ð·Ð° 7 ÑÐ°Ð³ÐŸÐ² Ðž 15 ÐŒÐžÐœÑÑ</Text>
+</Title>
+<Content>
+<Text id="271">ÐÑÑÑÐžÐ¹ ÑÐ¿ÐŸÑÐŸÐ± Ð²Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÑ Ð² ÑÑÑÐµÑÑÐ²ÐŸ ÐŽÐµÐ»Ð° â ÑÑÐŸ Ð¿ÐŸÑÐŒÐŸÑÑÐµÑÑ Ðž Ð¿ÑÐŸÑÑÐ²ÑÑÐ²ÐŸÐ²Ð°ÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ. ÐÐœ ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸÐ±Ñ ÑÐ°ÐºÑÐžÑÐµÑÐºÐž ÑÐŸÐ·ÐŽÐ°ÑÑ ÐŒÐ°Ð»ÐµÐœÑÐºÑÑ ÑÐµÑÑÐŸÐ²ÑÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÑ. ÐÑÐ»Ðž ÐÑ ÑÐ°ÑÐ¿ÐŸÐ»Ð°Ð³Ð°ÐµÑÐµ 15-Ñ ÐŒÐžÐœÑÑÐ°ÐŒÐž, Ð¿ÐŸÐ¶Ð°Ð»ÑÐ¹ÑÑÐ°, ÑÐ»ÐµÐŽÑÐ¹ÑÐµ ÑÑÐžÐŒÐž ÑÐ°Ð³Ð°ÐŒÐž, Ðž ÐÑ Ð¿ÐŸÐ¹ÐŒÐµÑÐµ ÑÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐœÐ°ÐŒÐœÐŸÐ³ÐŸ Ð»ÑÑÑÐµ.</Text>
+<Text id="272">ÐÐŸ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº ÐÑ ÐœÐ°ÑÐœÐµÑÐµ ÐŸÐ±ÑÑÐµÐœÐžÐµ, ÑÐœÐ°ÑÐ°Ð»Ð° ÐžÐœÑÑÐ°Ð»Ð»ÐžÑÑÐ¹ÑÐµ Greenstone (ÑÐŒ.Â <i>Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ Ð¿ÐŸ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž Greenstone</i>), ÐºÐŸÑÐŸÑÑÐ¹ Ð²ÐºÐ»ÑÑÐ°ÐµÑÂ <i>ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ</i>Â Ð² ÑÐŸÑÐŒÐ°ÑÐµ DLS Ðž ÐµÐµ ÐžÑÑ
+ÐŸÐŽÐœÑÐµ ÑÐ°Ð¹Ð»Ñ.Â <b>ÐÐ±ÑÐ°ÑÐžÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ ÐœÐ° ÑÐŸ, ÑÑÐŸ ÐµÑÐ»Ðž ÐÑ Ñ
+ÐŸÑÐžÑÐµ ÐžÐŒÐµÑÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑÑ Ðº ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð»ÑÐ±ÐŸÐ¹ ÐžÐ· 140 ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², Ð²Ñ
+ÐŸÐŽÑÑÐžÑ
+ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ DLS (Ð²ÐŒÐµÑÑÐŸ Ð²ÑÐµÐ³ÐŸ Ð»ÐžÑÑ 11 ÐžÐ· ÑÑÐžÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð² ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Greenstone), ÑÐŸ ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ ÐžÐœÑÑÐ°Ð»Ð»ÐžÑÐŸÐ²Ð°ÑÑ DLS Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐŸÐŽÐœÐŸÐ³ÐŸ ÐžÐ· Ð¿ÑÐžÐŒÐµÑÐŸÐ² Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐº Greenstone.</b>Â Â  ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐ°Ñ Ðž DLS ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð±ÑÐŽÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ Ð²Â <i>C:\Program Files\gsdl\gsld\collect</i>Â Ð² ÑÑÐ±ÐŽÐžÑÐµÐºÑÐŸÑÐžÑÑ
+Â <i>demo</i>Â ÐžÂ <i>Â  dls</i>Â cÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸ. ÐÑÐ»Ðž ÐÑ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐžÐ»Ðž Greenstone Ð±ÐµÐ· DLS Ðž Ñ
+ÐŸÑÐžÑÐµ ÐžÐœÑÑÐ°Ð»Ð»ÐžÑÐŸÐ²Ð°ÑÑ ÐµÐµ, ÑÐŸ ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐµÑÐµÐ·Ð°Ð¿ÑÑÑÐžÑÑ CD-ROM Ñ Greenstone Ðž ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÐµÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÐž Ð²ÐœÐ°ÑÐ°Ð»Ðµ ÐŽÐµÐžÐœÑÑÐ°Ð»Ð»ÐžÑÐŸÐ²Ð°ÑÑ Greenstone.</Text>
+<Text id="273">ÐÑ Ð¿ÑÐµÐŽÐ»Ð°Ð³Ð°ÐµÐŒ, ÑÑÐŸÐ±Ñ ÐÑ ÐŸÑÐ¿ÐµÑÐ°ÑÐ°Ð»Ðž ÐžÐœÑÑÑÑÐºÑÐžÐž, ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐœÑÐµ ÐœÐžÐ¶Ðµ, Ðž ÑÐ»ÐµÐŽÐŸÐ²Ð°Ð»Ðž ÐžÐŒ ÑÐ°Ð³ Ð·Ð° ÑÐ°Ð³ÐŸÐŒ: </Text>
+<NumberedList>
+<NumberedItem>
+<Text id="274">ÐÐ°Ð¿ÑÑÑÐžÑÐµ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÐŸÐŽ Windows, Ð²ÑÐ±ÐžÑÐ°ÑÂ <i>Greenstone Digital Library</i>Â ÐžÐ· ÑÐ°Ð·ÐŽÐµÐ»Ð°Â <i>Programs</i>Â Ð² ÐŒÐµÐœÑÂ Â <i>Start</i>Â Ðž Ð² ÐœÐµÐŒÂ <i>Librarian Interface</i>ÐÑÐ»Ðž ÐÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ Unix, ÑÐŸ Ð²ÐŒÐµÑÑÐŸ ÑÑÐŸÐ³ÐŸ ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ</Text>
+<CodeLine>cd ~/gsdl</CodeLine>
+<CodeLine>cd gli</CodeLine>
+<CodeLine>./gli.sh</CodeLine>
+<Text id="275">Ð³ÐŽÐµÂ <i>~/gsdl</i>Â â ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐ°Ñ ÑÐžÑÑÐµÐŒÑ Greenstone.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="276">ÐÑÐ±ÐµÑÐžÑÐµÂ <i>New</i>Â ÐžÐ· ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ³ÐŸ ÐŒÐµÐœÑ Ð² Ð³ÐŸÑÐžÐ·ÐŸÐœÑÐ°Ð»ÑÐœÐŸÐ¹ Ð»ÐžÐœÐµÐ¹ÐºÐµ ÐŒÐµÐœÑ ÐœÐ°Ð²ÐµÑÑ
+Ñ ÐŸÐºÐœÐ°, ÐŽÐ°Ð¹ÑÐµ ÐµÐŒÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ, ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, Â«Â <i>My First Collection</i>Â Â» Ðž Ð·Ð°Ð¿ÐŸÐ»ÐœÐžÑÐµ ÐÐ°Ñ Ð°ÐŽÑÐµÑ ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ Ð¿ÐŸÑÑÑ Ðž ÐºÑÐ°ÑÐºÐŸÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð ÐŒÐµÐœÑ Â«Â <i>ÐÑÐœÐŸÐ²Ð° ÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</i>Â Â» Ð²ÑÐ±ÐµÑÐžÑÐµ Â«Â <i>ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ Ð¿ÑÐžÐŒÐµÑ Greenstone</i>Â Â» ÐžÐ»Ðž Â«Â <i>ÐÐŸÐŽÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐŸ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž ÑÐ°Ð·Ð²ÐžÑÐžÑ</i>Â Â» (ÑÐµÐ·ÑÐ»ÑÑÐ°Ñ Ð±ÑÐŽÐµÑ ÑÐŸÑ Ð¶Ðµ ÑÐ°ÐŒÑÐ¹, Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ ÑÑÐž ÐŽÐ²Ðµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐžÐŒÐµÑÑ ÐŸÐŽÐžÐœÐ°ÐºÐŸÐ²ÑÑ ÑÑÑÑÐºÑÑÑÑ).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="277">Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÐžÐ· ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (ÐžÐ»Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž DLS, ÐµÑÐ»Ðž ÐŸÐœÐ° ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ°) Ð² ÐÐ°ÑÑ ÐœÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÑÐµÐ»ÐºÐœÐžÑÐµ ÐŽÐ²Ð°Ð¶ÐŽÑ ÐœÐ° Ð¿Ð°Ð¿ÐºÐµ Greenstone Ñ Ð»ÐµÐ²ÐŸÐ¹ ÑÑÐŸÑÐŸÐœÑ, Ð·Ð°ÑÐµÐŒ ÐŽÐ²Ð°Ð¶ÐŽÑ - ÐœÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐºÐŸÑÐŸÑÑÑ ÐÑ Ñ
+ÐŸÑÐžÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ. ÐÐŸÐºÑÐŒÐµÐœÑÑ Ð² ÐœÐµÐ¹ Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÑ Ð²ÐœÐžÐ·Ñ. ÐÑÐ±ÐµÑÐžÑÐµ ÐŸÐŽÐžÐœ ÐžÐ· ÐœÐžÑ
+, Ð¿ÐµÑÐµÑÑÐœÐžÑÐµ ÐµÐ³ÐŸ Ðž Ð¿ÐŸÐŒÐµÑÑÐžÑÐµ ÐœÐ° Ð¿Ð°ÐœÐµÐ»Ñ Ñ Ð¿ÑÐ°Ð²ÐŸÐ¹ ÑÑÐŸÑÐŸÐœÑ. Ð­ÑÐ° Ð¿Ð°ÐœÐµÐ»Ñ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐºÐŸÑÐŸÑÑÑ ÐÑ ÑÐŸÐ·ÐŽÐ°ÐµÑÐµ. ÐÑÐ±ÐµÑÐžÑÐµ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ðž Ð¿ÐµÑÐµÑÑÐœÐžÑÐµ ÐžÑ
+ Ð² ÐœÐµÐµ Ð¿ÐŸÑÐ»ÐµÐŽÐŸÐ²Ð°ÑÐµÐ»ÑÐœÐŸ ÐŸÐŽÐžÐœ Ð·Ð° ÐŽÑÑÐ³ÐžÐŒ ÐžÐ»Ðž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐµÐœÐœÑÐ¹ Ð²ÑÐ±ÐŸÑ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐŒ ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐŒ.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="278">ÐÐŸÐ±Ð°Ð²ÑÑÐµ ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÐžÐ· ÐÐ°ÑÐžÑ
+ ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÐœÐµ Ð²Ñ
+ÐŸÐŽÑÑ Ð² ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐžÐ»Ðž DLS-ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÐ°ÐºÑÐŸÐ¹ÑÐµ Ð¿Ð°Ð¿ÐºÑÂ <i>Greenstone Ð¡ollections</i>Â ÐœÐ° Ð»ÐµÐ²ÐŸÐ¹ Ð¿Ð°ÐœÐµÐ»Ðž Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ 2 ÑÐ°Ð·Ð° ÐœÐ° Ð¿Ð°Ð¿ÐºÐµÂ <i>Local Filespace</i>, Ð¿ÐµÑÐµÐ¹ÐŽÐžÑÐµ Ðº ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž, ÐºÐŸÑÐŸÑÐ°Ñ ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐŒÐ°Ð»ÐµÐœÑÐºÐžÐµ ÑÐ°Ð¹Ð»Ñ Word ÐžÐ»Ðž HTML). ÐÐµÑÐµÑÐ°ÑÐžÑÐµ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐžÐ· ÐœÐžÑ
+ Ð² Ð¿ÑÐ°Ð²ÑÑ Ð¿Ð°ÐœÐµÐ»Ñ, ÑÑÐŸÐ±Ñ Ð²ÐºÐ»ÑÑÐžÑÑ ÐžÑ
+ Ð² ÐÐ°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="279">ÐÐŸÐ±Ð°Ð²ÑÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ðº ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ Ð² ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐŸÐºÐ° ÐÑ ÑÐ°Ð±ÐŸÑÐ°Ð»Ðž Ð¿ÐŸÐŽ Ð¿Ð°ÐœÐµÐ»ÑÑÂ <i>Gather</i>, ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÐœÐŸÐ¹ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐŒÂ <i>Gather</i>Â Ð¿ÐŸÐŽ Ð³ÐŸÑÐžÐ·ÐŸÐœÑÐ°Ð»ÑÐœÐŸÐ¹ Ð»ÐžÐœÐµÐ¹ÐºÐŸÐ¹ ÐŒÐµÐœÑ ÐœÐ°Ð²ÐµÑÑ
+Ñ ÐŸÐºÐœÐ°. Ð©ÐµÐ»ÐºÐœÐžÑÐµ ÑÐžÐŒÐ²ÐŸÐ»Â <i>Enrich</i>Â ÐŸÐºÐŸÐ»ÐŸ ÐœÐµÐµ. ÐÐŸÐºÑÐŒÐµÐœÑÑ Ð² ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐµÐ¿ÐµÑÑ Ð¿ÐŸÑÐ²Ð»ÑÑÑÑÑ ÐœÐ° Ð¿Ð°ÐœÐµÐ»Ðž Ñ Ð»ÐµÐ²ÐŸÐ¹ ÑÑÐŸÑÐŸÐœÑ. Ð©ÐµÐ»ÐºÐœÐžÑÐµ ÐŸÐŽÐžÐœ ÑÐ°Ð· Ðž ÐžÑÑÐ»ÐµÐŽÑÐ¹ÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, ÑÐ²ÑÐ·Ð°ÐœÐœÑÐµ Ñ ÐœÐžÐŒÐž, Ð² ÑÐ°Ð±Ð»ÐžÑÐµ Â«Â <i>Ð­Ð»ÐµÐŒÐµÐœÑâŠ ÐÐœÐ°ÑÐµÐœÐžÐµ</i>Â Â» ÐœÐ°Ð²ÐµÑÑ
+Ñ ÑÐ¿ÑÐ°Ð²Ð°. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐœÐžÐ¶ÐœÑÑ Ð¿Ð°ÐœÐµÐ»Ñ, ÑÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐžÐœÐŽÐžÐ²ÐžÐŽÑÐ°Ð»ÑÐœÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ, Ð²ÑÐ±ÐžÑÐ°Ñ Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÑÐ¹Â <i>Ð­Ð»ÐµÐŒÐµÐœÑ</i>Â Ðž ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŽÐ»Ñ ÐœÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° ÐžÐ»Ðž Ð²ÑÐ¿ÐžÑÑÐ²Ð°Ñ ÐœÐŸÐ²ÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ð² Ð¿ÐŸÐ»Ðµ ÐŸÐºÐŸÐ»ÐŸ ÐŸÑÐœÐŸÐ²Ð°ÐœÐžÑ. ÐÐŸÐ±Ð°Ð²ÑÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµÂ <i>ÐÐ°Ð·Ð²Ð°ÐœÐžÑ, ÐÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐž, ÐÐ»ÑÑÐµÐ²ÑÑ
+ ÑÐ»ÐŸÐ²</i>Â Ðº ÐºÐ°Ð¶ÐŽÐŸÐŒÑ ÐžÐ· ÐÐ°ÑÐžÑ
+ ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÐÑ Ð²Ð²ÐµÐ»Ðž Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÐŸÑÐ»Ðµ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº ÐÑ ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð»Ðž ÐºÐ°Ð¶ÐŽÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ, Ð²Ñ ÐŽÐŸÐ»Ð¶ÐœÑ ÑÐµÐ»ÐºÐœÑÑÑÂ <i>Append,</i>Â Â ÑÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÑÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ðº ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒ.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="280">Ð©ÐµÐ»ÐºÐœÐžÑÐµ ÐºÐ»Ð°Ð²ÐžÑÑÂ <i>Create,</i>Â ÑÑÐŸÐ±Ñ Ð¿ÐŸÐºÐžÐœÑÑÑ ÑÐ¿ÐŸÑÐŸÐ±Â <i>Enrich</i>Â Ðž ÑÐŸÐ·ÐŽÐ°ÑÑ ÐÐ°ÑÑ ÐœÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. Ð©ÐµÐ»ÐºÐœÐžÑÐµ ÐºÐœÐŸÐ¿ÐºÑÂ <i>Build Collection</i>Â Ð² ÐŸÑÐœÐŸÐ²Ð°ÐœÐžÐž ÑÐºÑÐ°ÐœÐ°. ÐÐŸ Ð²ÑÐµÐŒÑ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐŸÐŒÂ  ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐÑ Ð±ÑÐŽÐµÑÐµ Ð¿ÐŸÐ»ÑÑÐ°ÑÑ ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÑÐ²ÐµÐŽÐµÐœÐžÑ ÐŸ ÑÐŸÐŒ, ÑÑÐŸ ÐŸÐœ ÐŽÐµÐ»Ð°ÐµÑ.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="281">ÐÐŸÐ³ÐŽÐ° ÑÑÐŸ Ð·Ð°Ð²ÐµÑÑÐµÐœÐŸ, ÑÐµÐ»ÐºÐœÐžÑÐµ ÑÐžÐŒÐ²ÐŸÐ»Â <i>ÐÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÑÐ¹ Ð¿ÑÐŸÑÐŒÐŸÑÑ</i>, ÑÑÐŸÐ±Ñ ÑÐ°ÑÑÐŒÐŸÑÑÐµÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°. ÐÑÐŸÐ²ÐµÑÑÑÐµÂ <i>ÐÐ°Ð·Ð²Ð°ÐœÐžÑ a-z, ÐÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐž</i>, ÑÑÐŸÐ±Ñ ÐžÐŒÐµÑÑ ÑÐ²ÐµÑÐµÐœÐœÐŸÑÑÑ, ÑÑÐŸ ÐÐ°ÑÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð±ÑÐ»Ðž Ð²ÐºÐ»ÑÑÐµÐœÑ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÑÐž Ð¿ÐŸÑÐµÑÐµÐœÐžÐž ÐÐ°ÑÐžÑ
+ ÐŽÐŸÐŒÐ°ÑÐœÐžÑ
+ ÑÑÑÐ°ÐœÐžÑ Greenstone ÐÑ ÑÐ°ÐºÐ¶Ðµ ÐœÐ°Ð¹ÐŽÐµÑÐµ, ÑÑÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð±ÑÐ»Ð° ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° ÐºÐ°Ðº ÐŸÐŽÐœÐ° ÐžÐ· ÐŸÐ±ÑÑÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹.</Text>
+</NumberedItem>
+</NumberedList>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<FootnoteList>
+<Footnote id="1">
+<Text id="282">ÐÑÐµ ÑÐµÐœÑ, ÑÐ¿ÐŸÐŒÑÐœÑÑÑÐµ Ð² ÑÑÐŸÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÐµ, ÐŽÐ°ÐœÑ Ð² ÐŽÐŸÐ»Ð»Ð°ÑÐ°Ñ
+ Ð¡ÐšÐ, 2001 Ð³ÐŸÐŽÐ°.</Text>
+</Footnote>
+<Footnote id="2">
+<Text id="283">Recall that all sums of money are expressed in 2001 US dollars.</Text>
+</Footnote>
+</FootnoteList>
+</Manual>
Index: /tags/start/gsdl-documentation/manuals/xml-source/ru/User_ru.xml
===================================================================
--- /tags/start/gsdl-documentation/manuals/xml-source/ru/User_ru.xml	(revision 13666)
+++ /tags/start/gsdl-documentation/manuals/xml-source/ru/User_ru.xml	(revision 13666)
@@ -0,0 +1,3370 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Manual>
+<Heading>
+<Text id="1">ÐŠÐÐ€Ð ÐÐÐÐ¯ ÐÐÐÐÐÐÐ¢ÐÐÐ GREENSTONE</Text>
+</Heading>
+<Title>
+<Text id="2">ÐÐÐ¡Ð¢Ð Ð£ÐÐŠÐÐ¯ ÐÐÐÐ¬ÐÐÐÐÐ¢ÐÐÐ¯</Text>
+</Title>
+<Author>
+<Text id="3">Ian H. Witten, Stefan Boddie and John Thompson</Text>
+</Author>
+<Affiliation>
+<Text id="4">Department of Computer Science <br/>University of Waikato, New Zealand</Text>
+</Affiliation>
+<Text id="5">Greenstone ÑÐ²Ð»ÑÐµÑÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐŸÐ¹, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐŸÐ¹ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ Ðž ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÐµÐœÐžÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÐœÐ°Ñ
+ÐŸÐŽÑÑÐžÑ
+ÑÑ Ð² ÑÐžÑÑÐŸÐ²ÐŸÐŒ ÑÐŸÑÐŒÐ°ÑÐµ. ÐÐœÐ° Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐœÐŸÐ²ÑÐ¹ ÑÐ¿ÐŸÑÐŸÐ± ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐž Ðž Ð¿ÑÐ±Ð»ÐžÐºÐ°ÑÐžÐž ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž Ð² ÐÐœÑÐµÑÐœÐµÑÐµ ÐžÐ»Ðž ÐœÐ° ÐºÐŸÐŒÐ¿Ð°ÐºÑ-ÐŽÐžÑÐºÐ°Ñ
+ CD-ROM. Greenstone Ð±ÑÐ» ÑÐŸÐ·ÐŽÐ°Ðœ Ð¿ÐŸ Ð¿ÑÐŸÐµÐºÑÑ New Zealand Digital Library Project Ð¿ÑÐž ÑÐœÐžÐ²ÐµÑÑÐžÑÐµÑÐµ ÐÐ°Ð¹ÐºÐ°ÑÐŸ, ÐŽÐŸÑÐ°Ð±ÐŸÑÐ°Ðœ Ðž ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÐµÐœ Ð¿ÑÐž ÑÐŸÐŽÐµÐ¹ÑÑÐ²ÐžÐž Ð®ÐÐÐ¡ÐÐ Ðž ÐœÐµÐ¿ÑÐ°Ð²ÐžÑÐµÐ»ÑÑÑÐ²ÐµÐœÐœÐŸÐ¹ ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐž  Human info. Ð­ÑÐ° Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐŽÐŸÑÑÑÐ¿ÐœÐ° Ð²ÑÐµÐŒ ÐœÐ° ÑÐ°Ð¹ÑÐµ <i>http://greenstone.org</i> ÑÐŸÐŸÑÐ²ÐµÑÑÑÑÐµÑ ÑÑÐ»ÐŸÐ²ÐžÑÐŒ GNU General Public License.</Text>
+<Comment>
+<Text id="6">ÐÑ ÐœÐ°ÐŽÐµÐµÐŒÑÑ, ÑÑÐŸ ÑÑÐŸ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ Ñ
+ÐŸÑÐŸÑÐŸ. ÐÐŸÐ¶Ð°Ð»ÑÐ¹ÑÑÐ°, ÑÐŸÐŸÐ±ÑÐžÑÐµ ÐŸ Ð»ÑÐ±ÑÑ
+ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÐ°Ñ
+ Ð¿ÐŸÐ°ÐŽÑÐµÑÑ: greenstone@cs.waikato.ac.nz</Text>
+</Comment>
+<Version>
+<Text id="7">Greenstone gsdl-2.70</Text>
+</Version>
+<Date>
+<Text id="8">ÐÐ°ÑÑ 2006</Text>
+</Date>
+<Section id="about_this_manual">
+<Title>
+<Text id="9">ÐÐ± ÑÑÐŸÐŒ ÑÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ðµ</Text>
+</Title>
+<Content>
+<Text id="10">Ð­ÑÐŸ ÑÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ð²ÑÐµÑÑÐŸÑÐŸÐœÐœÐµÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ Greenstone ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÑÐµÐœÐžÑ ÐŽÐŸÑÑÑÐ¿Ð° Ðž Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÑÐžÑÑÐŸÐ²ÑÑ
+ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐº. </Text>
+<Text id="11">Ð ÑÐ°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Chapter" ref="overview_of_greenstone"/> Ð¿ÑÐžÐ²ÐŸÐŽÐžÑÑÑ ÐºÑÐ°ÑÐºÐžÐ¹ ÐŸÐ±Ð·ÐŸÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐµÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ. Ð ÑÐ°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Chapter" ref="using_greenstone_collections"/> ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ, ÐºÐ°Ðº ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Greenstone. ÐÐœÑÐµÑÑÐµÐ¹Ñ ÑÐ°ÐŒ Ð¿ÐŸÑÑÐœÑÐµÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÑÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ: Ð»ÑÑÑÐžÐ¹ ÑÐ¿ÐŸÑÐŸÐ± ÐœÐ°ÑÑÐžÑÑÑÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ ÐžÐŒ - ÑÑÐŸ ÐŽÐµÐ»Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ Ð²ÐºÐ»ÑÑÐµÐœÐ° ÐŽÐžÐ°Ð»ÐŸÐ³ÐŸÐ²Ð°Ñ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ Ð¿ÐŸÐŒÐŸÑÐž Ð¿ÑÐž ÑÐŸÐ·ÐŽÐ°ÐœÐžÐž ÑÐžÐ¿ÐžÑÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð ÑÐ°Ð·ÐŽÐµÐ»Ðµ <CrossRef target="Chapter" ref="making_greenstone_collections"/> ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ, ÐºÐ°Ðº ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ ÐÐ°ÑÐž ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÑÐµ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Greenstone. Ð Ð°Ð·ÐŽÐµÐ» <CrossRef target="Chapter" ref="administration"/> Ð²Ð²ÐŸÐŽÐžÑ Ð² ÑÑÐµÐŽÑÑÐ²Ð° Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ, ÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ ÑÐžÑÑÐµÐŒÐœÐŸÐŒÑ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐ°ÑÐŸÑÑ ÑÐ¿ÑÐ°Ð²Ð»ÑÑÑ ÑÐµÐŒ, ÑÑÐŸ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ, Ðž ÑÐµÐŒÐž, ÐºÑÐŸ ÑÐŸÐ·ÐŽÐ°ÐµÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="12">Appendices list the features of the Greenstone software, and give a glossary of terms used throughout the Greenstone documentation.</Text>
+</Content>
+</Section>
+<Section id="companion_documents">
+<Title>
+<Text id="13">Ð¡ÐŸÐ¿ÑÑÑÑÐ²ÑÑÑÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ</Text>
+</Title>
+<Content>
+<Text id="14">ÐÐŸÐ»ÐœÑÐ¹ ÐºÐŸÐŒÐ¿Ð»ÐµÐºÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÑÐžÐž Ðº Greenstone ÑÐŸÑÑÐŸÐžÑ ÐžÐ· 4 ÑÐŸÐŒÐŸÐ²:</Text>
+<BulletList>
+<Bullet>
+<Text id="15">Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ Ð¿ÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐµ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="16">ÐÐœÑÑÑÑÐºÑÐžÑ ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone (ÑÑÐŸÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ)</Text>
+</Bullet>
+<Bullet>
+<Text id="17">Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐº Ð° ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone</Text>
+</Bullet>
+<Bullet>
+<Text id="18">ÐŠÐžÑÑÐŸÐ²Ð°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Greenstone: ÐŸÑ ÐÑÐŒÐ°Ð³Ðž ÐŽÐŸ ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Bullet>
+</BulletList>
+</Content>
+</Section>
+<Section id="acknowledgements">
+<Title>
+<Text id="19">ÐÐ»Ð°Ð³ÐŸÐŽÐ°ÑÐœÐŸÑÑÑ</Text>
+</Title>
+<Content>
+<Text id="20">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ Greenstone - Ð¿ÑÐŸÐŽÑÐºÑ ÑÐŸÐ²ÐŒÐµÑÑÐœÐŸÐ³ÐŸ ÑÑÑÐŽÐ° ÐŒÐœÐŸÐ¶ÐµÑÑÐ²Ð° Ð»ÑÐŽÐµÐ¹. Rodger McNab Ðž Stefan Boddie Ð¿ÑÐžÐœÑÐžÐ¿ÐžÐ°Ð»ÑÐœÑÐµ ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐž ÑÐžÑÑÐµÐŒÑ. ÐÐµÐŸÑÐµÐœÐžÐŒÑÐ¹ Ð²ÐºÐ»Ð°ÐŽ Ð²ÐœÐµÑÐ»Ðž David Bainbridge, George Buchanan, Hong Chen, Michael Dewsnip, Katherine Don, Elke Duncker, Carl Gutwin, Geoff Holmes, Dana McKay, John McPherson, Craig Nevill-Manning, Dynal Patel, Gordon Paynter, Bernhard Pfahringer, Todd Reed, Bill Rogers, John Thompson, Ðž Stuart Yeates. ÐÑÑÐ°Ð»ÑÐœÑÐµ ÑÐ»ÐµÐœÑ ÐÑÐŸÐµÐºÑÐ° ÐÐŸÐ²ÐŸÐ·ÐµÐ»Ð°ÐœÐŽÑÐºÐŸÐ¹ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž  ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÐ°Ð»Ðž Ð²ÐŽÐŸÑ
+ÐœÐŸÐ²ÐµÐœÐœÑÐ¹ ÐŽÐžÐ·Ð°Ð¹Ðœ Ð²ÑÐµÐ¹ ÑÐžÑÑÐµÐŒÑ: Mark Apperley, Sally Jo Cunningham, Matt Jones, Steve Jones, Te Taka Keegan, Michel Loots, Malika Mahoui, Gary Marsden, Dave Nichols Ðž Lloyd Smith. ÐÑ ÑÐ°ÐºÐ¶Ðµ Ð²ÑÑÐ°Ð¶Ð°ÐµÐŒ ÑÐ²ÐŸÑ Ð¿ÑÐžÐ·ÐœÐ°ÑÐµÐ»ÑÐœÐŸÑÑÑ Ð²ÑÐµÐŒ ÑÐµÐŒ, ÐºÑÐŸ ÑÑÑÐŽÐžÐ»ÑÑ ÐœÐ°ÐŽ ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµÐŒ Ð¿Ð°ÐºÐµÑÐŸÐ², Ð¿ÐŸÐ¿Ð°ÐŽÐ°ÑÑÐžÑ
+ Ð¿ÐŸÐŽ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ Ð»ÐžÑÐµÐœÐ·ÐžÐž  GNU, Ðž Ð²ÐºÐ»ÑÑÐµÐœÐœÑÑ
+ Ð² ÐŽÐžÑÑÑÐžÐ±ÑÑÐžÐ²: MG, GDBM, PDFTOHTML, PERL, WGET, WVWARE Ðž XLHTML.</Text>
+</Content>
+</Section>
+<Chapter id="overview_of_greenstone">
+<Title>
+<Text id="21">ÐÐ±Ð·ÐŸÑ Greenstone</Text>
+</Title>
+<Content>
+<Text id="22">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Greenstone - ÑÑÐŸ ÐžÑÑÐµÑÐ¿ÑÐ²Ð°ÑÑÐ°Ñ ÑÐžÑÑÐµÐŒÐ° ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ Ðž Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÑÐŸÑÑÐŸÑÑÐžÑ
+ ÐžÐ· ÐŒÐœÐŸÐ³ÐžÑ
+ ÐŒÐžÐ»Ð»ÐžÐŸÐœÐœÐŸÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², Ð²ÐºÐ»ÑÑÐ°ÑÑÐžÑ
+ ÑÐµÐºÑÑÑ, ÑÐžÑÑÐœÐºÐž, Ð°ÑÐŽÐžÐŸ- Ðž Ð²ÐžÐŽÐµÐŸ-ÑÐ°Ð¹Ð»Ñ.</Text>
+<Section id="collections">
+<Title>
+<Text id="23">ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="24">Ð¢ÐžÐ¿ÐžÑÐœÐ°Ñ ÑÐžÑÑÐŸÐ²Ð°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°, ÑÐŸÐ·ÐŽÐ°ÐœÐœÐ°Ñ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ Greenstone, ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ð² ÑÐµÐ±Ðµ ÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÐŸÑÐ³Ð°ÐœÐžÐ·ÐŸÐ²Ð°ÐœÐœÑÑ
+ Ð¿ÐŸ ÐŸÑÐŽÐµÐ»ÑÐœÐŸÑÑÐž, Ñ
+ÐŸÑÑ ÐŸÐœÐž ÐžÐŒÐµÑÑ ÐŒÐœÐŸÐ³ÐŸ ÑÑ
+ÐŸÐŽÑÑÐ²Ð° ÐŽÑÑÐ³ Ñ ÐŽÑÑÐ³ÐŸÐŒ. ÐÐµÐ³ÐºÐŸ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÐŒÑÐµ, ÑÑÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐµÐœÑ Ðž Ð¿ÐµÑÐµÑÑÑÐŸÐµÐœÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž.</Text>
+<Text id="25">Ð¡ÑÑÐµÑÑÐ²ÑÑÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐ² Ð¿ÐŸÐžÑÐºÐ° ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž Ð²ÐŸ ÐŒÐœÐŸÐ¶ÐµÑÑÐ²Ðµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Greenstone. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÐŒÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑÐºÐ°ÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐµ ÑÐ»ÐŸÐ²Ð°, ÐºÐŸÑÐŸÑÑÐµ Ð²ÑÑÑÐµÑÐ°ÑÑÑÑ Ð² ÑÐµÐºÑÑÐµ ÐžÐ»Ðž Ð² ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÐŸÐ¹ ÑÐ°ÑÑÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÑÐŒÐ°ÑÑÐžÐ²Ð°ÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð¿ÐŸ ÐœÐ°ÐžÐŒÐµÐœÐŸÐ²Ð°ÐœÐžÑ: Ð¿ÑÐŸÑÑÐŸ ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐžÐºÐŸÐœÐºÑ ÐºÐœÐžÐ³Ðž ÐŽÐ»Ñ ÑÑÐµÐœÐžÑ. Ð¢Ð°ÐºÐ¶Ðµ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÑÐŒÐ°ÑÑÐžÐ²Ð°ÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð¿ÐŸ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÐŸÐ¹ ÑÐµÐŒÐ°ÑÐžÐºÐµ. Ð¢ÐµÐŒÑ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÑ Ð² Ð²ÐžÐŽÐµ ÐºÐœÐžÐ¶ÐœÑÑ
+ Ð¿ÐŸÐ»ÐŸÐº: Ð¿ÑÐŸÑÑÐŸ ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐžÐºÐŸÐœÐºÑ ÐºÐœÐžÐ¶ÐœÐŸÐ¹ Ð¿ÐŸÐ»ÐºÐž, ÑÑÐŸÐ±Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ ÐºÐœÐžÐ³Ðž. ÐÑÑÑ ÑÐ°ÐºÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ, Ð² ÐºÐŸÑÐŸÑÑÑ
+ ÐžÐŒÐµÑÑÑÑ ÐŸÐ³Ð»Ð°Ð²Ð»ÐµÐœÐžÑ: Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÐœÐ°Ð¶Ð°ÑÑ ÐœÐ° Ð³Ð»Ð°Ð²Ñ ÐžÐ»Ðž ÐµÐµ ÑÐ°ÑÑÑ ÐŽÐ»Ñ ÐŸÑÐºÑÑÑÐžÑ, Ð° ÑÐ°ÐºÐ¶Ðµ ÐŸÑÐºÑÑÑÑ Ð¿ÐŸÐ»ÐœÐŸÐµ ÐŸÐ³Ð»Ð°Ð²Ð»ÐµÐœÐžÐµ Ð²ÐŸ Ð²ÐµÑÑ ÑÐºÑÐ°Ðœ ÐžÐ»Ðž Ð¿ÐŸÐ»ÐœÐŸÑÑÑÑ Ð¿ÐŸÐŒÐµÑÑÐžÑÑ Ð²ÐµÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ Ð² ÐŸÐºÐœÐŸ Ð²Ð°ÑÐµÐ³ÐŸ Ð±ÑÐ°ÑÐ·ÐµÑÐ° (Ð¿ÐŸÐ»ÐµÐ·ÐœÐŸ Ð¿ÑÐž Ð¿ÐµÑÐ°ÑÐž). ÐÐ° Ð²ÐµÐ±-ÑÐ°Ð¹ÑÐµ New Zealand Digital Library (nzdl.org) ÐŒÐŸÐ¶ÐœÐŸ ÐœÐ°Ð¹ÑÐž ÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐŸ Ð¿ÐŸÐºÐ°Ð·Ð°ÑÐµÐ»ÑÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹.</Text>
+<Text id="26">ÐÐ° Ð²ÐœÐµÑÐœÐµÐ¹ ÑÑÑÐ°ÐœÐžÑÐµ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐœÐ°Ð¿ÐžÑÐ°ÐœÐ° ÑÐµÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ, ÐºÑÐ°ÑÐºÐžÐ¹ ÐŸÐ±Ð·ÐŸÑ Ðž ÐŸÐ±ÑÑÑÐœÐµÐœÐžÐµ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº ÐŸÑÐ³Ð°ÐœÐžÐ·ÐŸÐ²Ð°ÐœÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐŒÐŸÐ¶ÐœÐŸ ÐŸÑÐºÑÑÑÑ Ð¿ÑÑÐµÐŒ Ð¿ÐŸÐžÑÐºÐ° Ðž Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°.   ÐÑÐž Ð¿ÐŸÐžÑÐºÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Greenstone Ð¿ÑÐŸÑÐŒÐ°ÑÑÐžÐ²Ð°ÐµÑ Ð²ÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ, ÐœÐ°Ñ
+ÐŸÐŽÑÑÐžÐµÑÑ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (ÐœÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ "full text search" "Ð¿ÐŸÐžÑÐº Ð¿ÐŸ Ð²ÑÐµÐŒÑ ÑÐµÐºÑÑÑ"). ÐÐŸ ÐŒÐœÐŸÐ³ÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+ ÑÑÑÐµÑÑÐ²ÑÑÑ ÐžÐœÐŽÐµÐºÑÑ, ÑÐ°Ð·Ð±ÐžÐ²Ð°ÑÑÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑ ÐœÐ° ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÐ°ÑÑÐµÐ¹, Ð¿ÐŸ ÐºÐŸÑÐŸÑÑÐŒ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÑÐ°ÐºÐ¶Ðµ ÐŒÐŸÐ¶ÐµÑ ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÑÑ Ð¿ÐŸÐžÑÐº. ÐÐµÐºÐŸÑÐŸÑÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐžÐŒÐµÑÑ ÐžÐœÐŽÐµÐºÑÑ Ð¿ÐŸÐ»ÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÐžÐœÐŽÐµÐºÑÑ Ð¿Ð°ÑÐ°Ð³ÑÐ°ÑÐŸÐ², ÐžÐœÐŽÐµÐºÑÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹, Ð¿ÐŸ ÐºÐ°Ð¶ÐŽÐŸÐŒÑ ÐžÐ· ÐºÐŸÑÐŸÑÑÑ
+ ÐŒÐŸÐ¶ÐœÐŸ ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÑÑ Ð¿ÐŸÐžÑÐº ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ ÑÐ»ÐŸÐ² ÐžÐ»Ðž ÑÑÐ°Ð·. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐžÐœÐŽÐµÐºÑÑ, ÐŒÐŸÐ¶ÐœÐŸ ÐœÐ°Ð¹ÑÐž Ð²ÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐžÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐ¹ ÐœÐ°Ð±ÐŸÑ ÑÐ»ÐŸÐ² (ÑÑÐž ÑÐ»ÐŸÐ²Ð° ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐ°Ð·Ð±ÑÐŸÑÐ°ÐœÑ Ð¿ÐŸ Ð²ÑÐµÐŒÑ ÑÐµÐºÑÑÑ), ÐžÐ»Ðž Ð²ÑÐµ Ð¿Ð°ÑÐ°Ð³ÑÐ°ÑÑ Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐŒ ÐœÐ°Ð±ÐŸÑÐŸÐŒ ÑÐ»ÐŸÐ² (ÐºÐŸÑÐŸÑÑÐµ ÐŽÐŸÐ»Ð¶ÐœÑ Ð²ÑÐµ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑÑ Ð² ÑÑÐŸÐŒ Ð¿Ð°ÑÐ°Ð³ÑÐ°ÑÐµ), ÐžÐ»Ðž Ð²ÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð² ÐœÐ°Ð·Ð²Ð°ÐœÐžÑÑ
+ ÐºÐŸÑÐŸÑÑÑ
+ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑÑ ÑÑÐž ÑÐ»ÐŸÐ²Ð° (Ð²ÑÐµ ÑÐºÐ°Ð·Ð°ÐœÐœÑÐµ ÑÐ»ÐŸÐ²Ð° ÐŽÐŸÐ»Ð¶ÐœÑ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑÑ Ð² ÐœÐ°Ð·Ð²Ð°ÐœÐžÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°). Ð¢Ð°ÐºÐ¶Ðµ ÐŒÐŸÐ³ÑÑ ÑÑÑÐµÑÑÐ²ÐŸÐ²Ð°ÑÑ Ðž ÐŽÑÑÐ³ÐžÐµ ÐžÐœÐŽÐµÐºÑÑ, ÐœÐ°Ð¿ÑÐžÐŒÐµÑ ÐžÐœÐŽÐµÐºÑÑ ÑÐµÐºÑÐžÐ¹ Ðž ÐžÐœÐŽÐµÐºÑÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹ ÑÐµÐºÑÐžÐ¹. ÐÑÐŸÑÐŒÐŸÑÑ Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð² ÑÐµÐ±Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐ¹ Ð¿ÐµÑÐµÑÐµÐœÑ, ÐºÐŸÑÐŸÑÑÐŒ Ð¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ: Ð¿ÐµÑÐµÑÐµÐœÑ Ð°Ð²ÑÐŸÑÐŸÐ², ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹, ÐŽÐ°Ñ, ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐŸÐ¹ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÑÑÑÐºÑÑÑÑ Ðž Ñ.ÐŽ. Ð Ð°Ð·ÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÑÐµÐŽÐ»Ð°Ð³Ð°ÑÑ ÑÐ°Ð·ÐœÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°.</Text>
+</Content>
+</Section>
+<Section id="finding_information">
+<Title>
+<Text id="27">ÐÐŸÐžÑÐº ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="28">Greenstone ÐžÐŒÐµÐµÑ Ð¿ÐŸÐ»ÐœÐŸÑÐµÐºÑÑÐŸÐ²ÑÐµ ÐžÐœÐŽÐµÐºÑÑ- ÑÐµ ÐžÐœÐŽÐµÐºÑÑ, ÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑÑ Ð¿ÐŸÐžÑÐº Ð»ÑÐ±ÑÑ
+ ÑÐ»ÐŸÐ² Ð¿ÐŸ Ð²ÑÐµÐŒÑ ÑÐµÐºÑÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. Ð ÐžÐœÐŽÐµÐºÑÐ°Ñ
+ ÑÐ°ÐºÐ¶Ðµ ÐŒÐŸÐ¶ÐœÐŸ ÐžÑÐºÐ°ÑÑ Ð¿ÐŸ ÐŸÐŽÐœÐŸÐŒÑ ÑÐ»ÐŸÐ²Ñ, ÐœÐ°Ð±ÐŸÑÑ ÑÐ»ÐŸÐ², ÑÑÐ°Ð·, Ð¿ÐŸÑÐ»Ðµ ÑÐµÐ³ÐŸ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÑÑÑÑ Ð² ÑÐ°ÐºÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ, Ð² ÐºÐŸÑÐŸÑÐŸÐŒ ÐŸÐœÐž Ð±ÐŸÐ»ÐµÐµ Ð²Ð°Ð¶ÐœÑ ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ.</Text>
+<Text id="29">ÐÐŸ ÐŒÐœÐŸÐ³ÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+ ÑÐ°ÐºÐžÐµ ÐŽÐ°ÐœÐœÑÐµ, ÐºÐ°Ðº Ð°Ð²ÑÐŸÑ, ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ, ÐŽÐ°ÑÐ°, ÐºÐ»ÑÑÐµÐ²ÑÐµ ÑÐ»ÐŸÐ²Ð°, ÐžÐŒÐµÐµÑ ÐºÐ°Ð¶ÐŽÑÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ. Ð­ÑÐ° ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐœÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž. ÐÐœÐŸÐ³ÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐžÐŒÐµÑÑ Ð¿ÐŸÐ»ÐœÐŸÑÐµÐºÑÑÐŸÐ²ÑÐµ ÐžÐœÐŽÐµÐºÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, Ð²ÐŸ ÐŒÐœÐŸÐ³ÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+ ÐŒÐŸÐ¶ÐœÐŸ ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÑÑ Ð¿ÐŸÐžÑÐº Ð¿ÐŸ ÐžÐœÐŽÐµÐºÑÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ².</Text>
+<Text id="30">ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ðž ÐŒÐŸÐ³ÑÑ Ð¿ÑÐŸÑÐŒÐ°ÑÑÐžÐ²Ð°ÑÑ Ð¿ÐµÑÐµÑÐœÐž Ðž ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐžÐµ ÑÑÑÑÐºÑÑÑÑ. ÐÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐ²Ð»ÑÑÑÑÑ ÐœÐ°ÑÐ°Ð»ÑÐœÑÐŒ Ð¿ÑÐœÐºÑÐŸÐŒ ÐŽÐ»Ñ ÐŸÑÑÑÐµÑÑÐ²Ð»ÐµÐœÐžÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°. Ð Ð°Ð·ÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÑÐµÐŽÐ»Ð°Ð³Ð°ÑÑ ÑÐ°Ð·ÐœÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°. ÐÐœÐŽÐµÐºÑÑ ÐŽÐ»Ñ Ð¿ÐŸÐžÑÐºÐ° Ðž Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÑÐŸÐ·ÐŽÐ°ÑÑÑÑ Ð²ÐŸ Ð²ÑÐµÐŒÑ "building" Ð¿ÑÐŸÑÐµÑÑÐ° Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÑÐ°Ð¹Ð»Ð°, Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐž Ñ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐµÐ¹ Ð² ÐºÐŸÐœÑÐžÐ³-ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="31">Greenstone ÑÐŸÐ·ÐŽÐ°ÐµÑ Ð²ÑÐµ ÐžÐœÐŽÐµÐºÑÐœÑÐµ ÑÑÑÑÐºÑÑÑÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ðž Ð²ÑÐ¿ÐŸÐŒÐŸÐ³Ð°ÑÐµÐ»ÑÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ²: ÐœÐžÑÐµÐ³ÐŸ ÐœÐµ ÐœÑÐ¶ÐœÐŸ ÐŽÐµÐ»Ð°ÑÑ Ð²ÑÑÑÐœÑÑ. ÐÑÐ»Ðž Ð¿ÐŸÑÐ²Ð»ÑÑÑÑÑ ÐœÐŸÐ²ÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð² ÑÐ°ÐºÐŸÐŒ Ð¶Ðµ ÑÐŸÑÐŒÐ°ÑÐµ, ÐŸÐœÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð¿ÑÐžÑÐŸÐµÐŽÐžÐœÐµÐœÑ Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž. ÐÐ»Ñ ÐŒÐœÐŸÐ³ÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÑÑÐž Ð¿ÑÐŸÑÐµÑÑÑ ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÑÑÑÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž, Ð¿ÐŸÐžÑÐº ÐœÐŸÐ²ÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž Ðž Ð¿ÐµÑÐµÑÑÑÐŸÐ¹ÐºÐ° ÐžÐœÐŽÐµÐºÑÐŸÐ² - Ð²ÑÐµ Ð±ÐµÐ· ÑÑÑÐœÐŸÐ¹ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž.</Text>
+</Content>
+</Section>
+<Section id="document_formats">
+<Title>
+<Text id="32">Ð€ÐŸÑÐŒÐ°ÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²</Text>
+</Title>
+<Content>
+<Text id="33">ÐÐŸÐºÑÐŒÐµÐœÑÑ, Ð²Ð¿ÐŸÑÐ»ÐµÐŽÑÑÐ²ÐžÐž ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÐŒÑÐµ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐ°Ð·ÐœÑÑ
+ ÑÐŸÑÐŒÐ°ÑÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ "Ð¿Ð»Ð°Ð³ÐžÐœÐŸÐ²" ("plugins") Ð¿ÐµÑÐµÐ²ÐŸÐŽÑÑÑÑ Ð² ÐŸÐŽÐžÐœ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐ¹ ÑÐŸÑÐŒÐ°Ñ XML. ÐÐ»Ð°Ð³ÐžÐœÑ, ÐºÐŸÑÐŸÑÑÐµ ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÑÑÑÑÑ Ð²ÐŒÐµÑÑÐµ Ñ Greenstone, ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÑÑ Ð¿ÑÐŸÑÑÐŸÐ¹ ÑÐµÐºÑÑ, HTML, ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÑÐŸÑÐŒÐ°ÑÐŸÐ² DOC Ðž PDF, Ð° ÑÐ°ÐºÐ¶Ðµ ÑÐŸÐŸÐ±ÑÐµÐœÐžÑ Usenet Ðž ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ Ð¿ÐŸÑÑÑ (email). ÐÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐŸÐ·ÐŽÐ°ÐœÑ Ðž ÐœÐŸÐ²ÑÐµ Ð¿Ð»Ð°Ð³ÐžÐœÑ ÐŽÐ»Ñ ÐŽÑÑÐ³ÐžÑ
+ Ð²ÐžÐŽÐŸÐ² ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² (ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ ÐžÐ·ÑÑÐžÑÑ Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ ÐŽÐ»Ñ ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ°). ÐÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÑÑÑÑÐºÑÑÑ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð°ÐœÐ°Ð»ÐŸÐ³ÐžÑÐœÐ°Ñ ÑÐžÑÑÐµÐŒÐ° "ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ²". Ð¡ Ð¿ÐŸÐŒÐŸÑÑÑ ÐœÐžÑ
+ ÐŒÐŸÐ¶ÐœÐŸ ÑÐŸÐ·ÐŽÐ°ÑÑ ÑÐ°Ð·ÐœÑÐµ ÐžÐœÐŽÐµÐºÑÑ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°: Ð°Ð»ÑÐ°Ð²ÐžÑÐœÑÐµ ÑÐºÐ°Ð·Ð°ÑÐµÐ»Ðž, ÐŽÐ°ÐœÐœÑÐµ Ðž ÑÐ°Ð·ÐœÐŸÐŸÐ±ÑÐ°Ð·ÐœÑÐµ ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐžÐµ ÑÑÑÑÐºÑÑÑÑ. Ð¢Ð°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ Ð»ÑÐŽÐž, ÑÐŒÐµÑÑÐžÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐžÑÐŸÐ²Ð°ÑÑ Ð² Greenstone, ÐŒÐŸÐ³ÑÑ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ ÐœÐŸÐ²ÑÐµ ÑÑÑÑÐºÑÑÑÑ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°.</Text>
+</Content>
+</Section>
+<Section id="multimedia_and_multilingual_documents">
+<Title>
+<Text id="34">ÐÑÐ»ÑÑÐžÐŒÐµÐŽÐžÐ¹ÐœÑÐµ Ðž ÑÐ°Ð·ÐœÐŸÑÐ·ÑÑÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ</Text>
+</Title>
+<Content>
+<Text id="35">ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐŸÐ³ÑÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑ ÑÐµÐºÑÑ, ÑÐžÑÑÐœÐºÐž, Ð°ÑÐŽÐžÐŸ- Ðž Ð²ÐžÐŽÐµÐŸ ÐŒÐ°ÑÐµÑÐžÐ°Ð»Ñ. ÐÐµÑÐµÐºÑÑÐŸÐ²ÐŸÐ¹ ÐŒÐ°ÑÐµÑÐžÐ°Ð» ÑÐ²ÑÐ·Ð°Ðœ Ñ ÑÐµÐºÑÑÐŸÐ²ÑÐŒ ÑÐ°Ð¹Ð»ÐŸÐŒ Ð»ÐžÐ±ÐŸ ÑÐµÑÐµÐ· ÑÑÑÐ»ÐºÑ, Ð»ÐžÐ±ÐŸ ÐžÐŒÐµÐµÑ ÑÐµÐºÑÑÐŸÐ²ÐŸÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ (ÑÐ°ÐºÐŸÐµ ÐºÐ°Ðº Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº) ÐŽÐ»Ñ ÐŸÐ±Ð»ÐµÐ³ÑÐµÐœÐžÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž Ð¿ÐŸÐ»ÐœÐŸÑÐµÐºÑÑÐŸÐ²ÐŸÐ³ÐŸ Ð¿ÐŸÐžÑÐºÐ° Ðž Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°.</Text>
+<Text id="36">Unicode, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐ²Ð»ÑÐµÑÑÑ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÐŸÐ¹ ÑÑ
+ÐµÐŒÐŸÐ¹ Ð¿ÑÐž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐž ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ², Ð¿ÑÐžÐŒÐµÐœÑÐµÐŒÑÑ
+ Ð² ÐŒÐžÑÐŸÐ²ÑÑ
+ ÑÐ·ÑÐºÐ°Ñ
+, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐµ Greenstone. Ð­ÑÐŸ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð¿ÐµÑÐµÑÐ°Ð±ÐŸÑÐ°ÑÑ ÐœÐ° Ð»ÑÐ±ÐŸÐ¹ ÑÐ·ÑÐº Ðž Ð¿ÐŸÐºÐ°Ð·Ð°ÑÑ ÐµÐ³ÐŸ ÐœÐ° ÑÐºÑÐ°ÐœÐµ Ð² Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸÐ¹ ÑÐŸÑÐŒÐµ Ðž Ð¿ÐŸÑÐ»ÐµÐŽÐŸÐ²Ð°ÑÐµÐ»ÑÐœÐŸÑÑÐž. ÐÑÐ»Ðž ÑÐŸÐ·ÐŽÐ°ÐœÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐžÐµ Ð°ÑÐ°Ð±ÑÐºÐžÐ¹, ÐºÐžÑÐ°Ð¹ÑÐºÐžÐ¹, Ð°ÐœÐ³Ð»ÐžÐ¹ÑÐºÐžÐ¹, ÑÑÐ°ÐœÑÑÐ·ÑÐºÐžÐ¹ Ðž ÐžÑÐ¿Ð°ÐœÑÐºÐžÐ¹ ÑÐ·ÑÐºÐž. ÐÑÐž ÑÐ°Ð±ÐŸÑÐµ Ñ ÑÐ°Ð·ÐœÐŸÑÐ·ÑÑÐœÑÐŒÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒÐž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ ÑÐ·ÑÐº. ÐÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐŽÐŸÑÑÑÐ¿ÐµÐœ ÐœÐ° Ð²ÑÐµÑ
+ Ð²ÑÑÐµÑÐ¿ÐŸÐŒÑÐœÑÑÑÑ
+ ÑÐ·ÑÐºÐ°Ñ
+ Ðž ÐŽÑÑÐ³ÐžÑ
+.</Text>
+</Content>
+</Section>
+<Section id="distributing_greenstone">
+<Title>
+<Text id="37">Ð Ð°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÐµÐœÐžÐµ Greenstone</Text>
+</Title>
+<Content>
+<Text id="38">ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŽÐŸÑÑÑÐ¿ÐœÑ Ð² ÐÐœÑÐµÑÐœÐµÑÐµ ÐžÐ»Ðž Ð¿ÑÐ±Ð»ÐžÐºÑÑÑÑÑ ÐœÐ° ÑÐ°ÐŒÐŸÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÑÑÐžÑ
+ÑÑ ÐºÐŸÐŒÐ¿Ð°ÐºÑ-ÐŽÐžÑÐºÐ°Ñ
+ Ð² ÑÐ°ÐºÐŸÐŒ Ð¶Ðµ Ð²ÐžÐŽÐµ, ÐºÐ°Ðº Ð² ÐžÐœÑÐµÑÐœÐµÑÐµ. ÐÐ»Ñ ÑÐŒÐµÐœÑÑÐµÐœÐžÑ ÐŸÐ±ÑÐµÐŒÐ° ÑÐµÐºÑÑÐ° Ðž ÐžÐœÐŽÐµÐºÑÐŸÐ² ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÑÐ¶Ð°ÑÐžÐµ. ÐÑÐŸÑÐŸÐºÐŸÐ» Corba Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÑ ÑÐ°Ð¿ÑÐŸÑÑÑÐ°ÐœÑÐµÐŒÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð³ÑÐ°ÑÐžÑÐµÑÐºÐžÐµ ÐžÐœÑÐµÑÑÐµÐ¹ÑÑ.</Text>
+<Text id="39">ÐŠÐžÑÑÐŸÐ²Ð°Ñ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° ÐÐŸÐ²ÐŸÐ¹ ÐÐµÐ»Ð°ÐœÐŽÐžÐž (nzdl.org) Ð¿ÑÐµÐŽÐ»Ð°Ð³Ð°ÐµÑ ÐŒÐœÐŸÐ³ÐžÐµ Ð¿ÐŸÐºÐ°Ð·Ð°ÑÐµÐ»ÑÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð²ÐºÐ»ÑÑÐ°ÑÑÐžÐµ ÐžÑÑÐŸÑÐžÑÐµÑÐºÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ, Ð³ÑÐŒÐ°ÐœÐžÑÐ°ÑÐœÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ Ðž ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÑÐ°Ð·Ð²ÐžÑÐžÑ, ÑÐµÑ
+ÐœÐžÑÐµÑÐºÐžÐµ ÐŽÐŸÐºÐ»Ð°ÐŽÑ Ðž Ð±ÐžÐ±Ð»ÐžÐŸÐ³ÑÐ°ÑÐžÐž, Ñ
+ÑÐŽÐŸÐ¶ÐµÑÑÐ²ÐµÐœÐœÑÐµ ÐºÐœÐžÐ³Ðž Ðž Ð¶ÑÑÐœÐ°Ð»Ñ.</Text>
+<Text id="40">ÐÑÐŽÑÑÐž ÐŸÑÐºÑÑÑÑÐŒ ÐžÑÑÐŸÑÐœÐžÐºÐŸÐŒ, Greenstone Ð³ÐŸÑÐŸÐ²Ð° Ðº ÑÐ°Ð·Ð²ÐžÑÐžÑ Ðž ÐžÐ·Ð²Ð»ÐµÐºÐ°ÑÑ Ð²ÑÐ³ÐŸÐŽÑ ÐžÐ· Ð²ÐºÐ»ÑÑÐµÐœÑÑ
+ Ð² GNU-ÐÐžÑÐµÐ·ÐžÑ ÐŒÐŸÐŽÑÐ»ÐµÐ¹ ÐŽÐ»Ñ Ð¿ÐŸÐ»ÐœÐŸÑÐµÐºÑÑÐŸÐ²ÐŸÐ³ÐŸ Ð¿ÐŸÐžÑÐºÐ°, ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ Ð±Ð°Ð·Ð°ÐŒÐž ÐŽÐ°ÐœÐœÑÑ
+, ÐžÐ·Ð²Ð»ÐµÑÐµÐœÐžÑ ÑÐµÐºÑÑÐŸÐ² ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÑÐ¿ÐµÑÐžÑÐžÑÐœÑÑ
+ ÑÐŸÑÐŒÐ°ÑÐŸÐ². Ð¢ÐŸÐ»ÑÐºÐŸ ÑÐµÑÐµÐ· ÑÐŸÐ²ÐŒÐµÑÑÐœÐŸÐµ ÐŒÐµÐ¶ÐŽÑÐœÐ°ÑÐŸÐŽÐœÐŸÐµ ÑÐŸÑÑÑÐŽÐœÐžÑÐµÑÑÐ²ÐŸ ÑÐžÑÑÐŸÐ²ÐŸÐµ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ ÑÑÐ°ÐœÐµÑ ÐŽÐŸÑÑÐ°ÑÐŸÑÐœÐŸ Ð²ÑÐµÑÑÐŸÑÐŸÐœÐœÐžÐŒ, Ð¿ÐŸÐ»ÐœÑÐŒ Ðž Ð³ÐžÐ±ÐºÐžÐŒ, ÑÐŽÐŸÐ²Ð»ÐµÑÐ²ÐŸÑÑÑÑÐžÐŒ ÐŒÐžÑÐŸÐ²ÑÐµ Ð¿ÐŸÑÑÐµÐ±ÐœÐŸÑÑÐž, ÑÑÐŸ Ðž Ð·Ð°ÑÐ»ÑÐ¶ÐžÐ²Ð°ÑÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ðž.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="using_greenstone_collections">
+<Title>
+<Text id="41">ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÐÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Greenstone</Text>
+</Title>
+<Content>
+<Text id="42">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ Greenstone ÑÐŸÐ·ÐŽÐ°ÐœÐŸ Ð¿ÐŸ Ð¿ÑÐžÐœÑÐžÐ¿Ñ Ð¿ÑÐŸÑÑÐŸÑÑ Ð² ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž. ÐÐœÑÐµÑÑÐµÐ¹Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐœÐ° CD-ROM Ðž ÐŽÐŸÑÑÑÐ¿ÐœÑÑ
+ ÑÐµÑÐµÐ· ÐÐœÑÐµÑÐœÐµÑ ÐžÐŽÐµÐœÑÐžÑÐµÐœ. Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐ° Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ Greenstone Ñ CD-ROM ÐœÐ° ÐºÐŸÐŒÐ¿ÑÑÑÐµÑ Ñ ÐÐ¡ Windows ÐžÐ»Ðž Unix ÐœÐ° ÑÐ°ÐŒÐŸÐŒ ÐŽÐµÐ»Ðµ ÐŸÑÐµÐœÑ Ð¿ÑÐŸÑÑÐ°; ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÐ°Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð²ÐŒÐµÑÑÐµ Ñ Ð¿ÑÐµÐŽÐºÐŸÐŒÐ¿ÐžÐ»ÐžÑÐŸÐ²Ð°ÐœÐœÑÐŒ ÐŽÐ²ÐŸÐžÑÐœÑÐŒ ÐºÐŸÐŽÐŸÐŒ. ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐŸÐ³ÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ Ð»ÐŸÐºÐ°Ð»ÑÐœÐŸ ÐœÐ° ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ, Ð³ÐŽÐµ ÐŸÐœÐž Ð±ÑÐ»Ðž ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ. ÐÑÐ»Ðž ÐºÐŸÐŒÐ¿ÑÑÑÐµÑ Ð¿ÐŸÐŽÐºÐ»ÑÑÐµÐœ Ðº ÑÐµÑÐž, Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²ÐžÑ Ð²ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐ°ÐŒ ÑÐµÑÐž ÐŽÐŸÑÑÑÐ¿ Ðº ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÑÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒ.</Text>
+<Text id="43">Ð ÑÐ»ÐµÐŽÑÑÑÐµÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸ ÐŸÐ¿ÐžÑÐ°ÐœÐŸ, ÐºÐ°Ðº ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ Greenstone Ñ CD-ROM. ÐÐ°ÑÐµÐŒ ÐŒÑ ÑÐ°ÑÑÐŒÐŸÑÑÐžÐŒ Ð¿ÐŸÐžÑÐº Ðž Ð¿ÑÐŸÑÐŒÐŸÑÑ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐ³ÐŸ, Ð¿ÑÐµÐŽÐ»Ð°Ð³Ð°ÐµÐŒÑÑ
+ ÐŸÐ±ÑÑÐœÐŸÐ¹ ÐÐŸÐ»Ð»ÐµÐºÑÐžÐ¹. "ÐÐµÐŒÐŸ" ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Greenstone Ð¿ÐŸÑÑÐ°Ð²Ð»ÑÐµÑÑÑ Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐŒ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµÐŒ Greenstone. ÐÑÑÐ³ÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŽÐŸÑÑÐ°ÑÐŸÑÐœÐŸ Ð¿ÑÐŸÑÑÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ. ÐÑÐ»Ðž Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ ÐŸÐŽÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹, ÑÐŸ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ Ð²ÑÐµÐŒÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒÐž. Ð¡Ð»ÐµÐŽÑÑÑÐžÐ¹ ÑÐ°Ð·ÐŽÐµÐ» ÐŸÐ±ÑÑÑÐœÑÐµÑ, ÐºÐ°Ðº ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐž Ñ Ð²Ð°ÑÐžÐŒÐž ÑÑÐµÐ±ÐŸÐ²Ð°ÐœÐžÑÐŒÐž, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Preferences page (ÑÑÑÐ°ÐœÐžÑÑ Ð²ÑÐ±ÐŸÑÐ° Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÐ¹).</Text>
+<Section id="using_a_greenstone_cd-rom">
+<Title>
+<Text id="44">ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ CD-ROM Greenstone</Text>
+</Title>
+<Content>
+<Text id="45">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ ÐŠÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Greenstone Ð¿ÐŸÑÑÐ°Ð²Ð»ÑÐµÑÑÑ ÐœÐ° CD-ROM, Ðž Ð²Ñ ÐžÐ»Ðž Ð²Ð°Ñ ÑÐžÑÑÐµÐŒÐœÑÐ¹ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐ°ÑÐŸÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐµÐ³ÐŸ ÐŽÐ»Ñ Ð²Ð°ÑÐµÐ¹ ÑÐžÑÑÐµÐŒÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐžÐœÑÑÑÑÐºÑÐžÐž, ÐžÐ·Ð»ÐŸÐ¶ÐµÐœÐœÑÐµ Ð² ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÑÐžÐž "ÐŠÐžÑÑÐŸÐ²Ð°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Greenstone: Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ Ð¿ÐŸ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐµ". Ð ÑÐ»ÑÑÐ°Ðµ, ÐµÑÐ»Ðž Greenstone ÑÐ¶Ðµ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° ÐœÐ° Ð²Ð°ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ, Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÐ¿ÑÑÑÐžÑÑ ÐŽÐ°ÐœÐœÑÐ¹ ÑÐ°Ð·ÐŽÐµÐ».</Text>
+<Text id="46">ÐÐµÐºÐŸÑÐŸÑÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Greenstone Ð¿ÐŸÑÑÐ°Ð²Ð»ÑÑÑÑÑ ÐœÐ° CD-ROMe Greenstone, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐœÐ°Ð±ÐŸÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒ, ÐŽÐŸÑÑÐ°ÑÐŸÑÐœÑÐ¹ ÐŽÐ»Ñ Ð·Ð°Ð¿ÑÑÐºÐ° ÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ Ð¿ÑÐŸÑÑÐŸ Ð¿ÐŸÐŒÐµÑÑÐžÑÐµ ÐµÐ³ÐŸ Ð² CD-ROM-ÑÑÐžÑÑÐ²Ð°ÑÑÐµÐµ ÑÑÑÑÐŸÐ¹ÑÑÐ²ÐŸ ÐœÐ° ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ Ñ ÐÐ¡ Windows. ÐÐŸÑÐ»Ðµ ÑÑÐŸÐ³ÐŸ (ÐµÑÐ»Ðž, ÐºÐŸÐœÐµÑÐœÐŸ, ÐœÐ° Ð²Ð°ÑÐµÐŒ PC ÑÐ°Ð·ÑÐµÑÐµÐœÐ° Ð¿ÑÐŸÑÐµÐŽÑÑÐ° Ð°Ð²ÑÐŸÐ·Ð°Ð¿ÑÑÐºÐ°) Ð¿ÐŸÑÐ²ÐžÑÑÑ ÐŸÐºÐœÐŸ Ð¿ÑÐžÐ³Ð»Ð°ÑÐµÐœÐžÑ Ðº ÑÑÑÐ°ÐœÐŸÐ²ÐºÐµ ÐÐ GreenStone. ÐÑÐ»Ðž ÑÑÐŸÐ³ÐŸ ÐœÐµ Ð¿ÑÐŸÐžÐ·ÐŸÑÐ»ÐŸ, ÐœÐ°Ð¹ÐŽÐžÑÐµ CD-ROM ÐœÐ° Ð²Ð°ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ (ÐŽÐ»Ñ ÐÐ¡ Windows Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÐºÐ»ÐžÐºÐœÑÑÑ Ð¿ÐŸ ÐžÐºÐŸÐœÐºÐµ "My Computer/ÐÐŸÐ¹ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑ" ÐœÐ° ÑÐ°Ð±ÐŸÑÐµÐŒ ÑÑÐŸÐ»Ðµ) Ðž ÐŽÐ²Ð°Ð¶ÐŽÑ ÑÐµÐ»ÐºÐœÐžÑÐµ ÐŒÑÑÑÑ Ð¿ÐŸ ÑÐ°Ð¹Ð»Ñ Setup.exe. ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Setup Ð·Ð°Ð¿ÑÑÐºÐ°ÐµÑÑÑ Ðž Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑ Ð²Ð°Ñ ÑÐµÑÐµÐ· Ð¿ÑÐŸÑÐµÐŽÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž. ÐÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ Ð»ÑÐŽÐµÐ¹ ÐŸÑÐ²ÐµÑÐ°ÑÑ Yes/ÐÐ° ÐœÐ° Ð²ÑÐµ Ð²ÐŸÐ¿ÑÐŸÑÑ.</Text>
+<Text id="47">ÐÐŸ ÐŸÐºÐŸÐœÑÐ°ÐœÐžÐž Ð¿ÑÐŸÑÐµÐŽÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ð²Ñ ÐœÐ°Ð¹ÐŽÐµÑÐµ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÑ Ð² ÐŒÐµÐœÑ ÐÐ¡ Windows Start->Programs (ÐÑÑÐº->ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÑ) Ð¿ÐŸÐŽ ÐžÐŒÐµÐœÐµÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, "Development Library" ÐžÐ»Ðž "United Nations UniversityUnited...").</Text>
+<Text id="48">ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐÐ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐŸ, Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Ð±ÑÐŽÐµÑ ÐŸÑÐºÑÑÐ²Ð°ÑÑÑÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÐºÐ°Ð¶ÐŽÑÐ¹ ÑÐ°Ð·, ÐºÐŸÐ³ÐŽÐ° Ð²Ñ Ð²ÑÑÐ°Ð²Ð»ÑÐµÑÐµ CD-ROM, ÐµÑÐ»Ðž, ÐºÐŸÐœÐµÑÐœÐŸ, ÑÐ°Ð·ÑÐµÑÐµÐœÐ° Ð¿ÑÐŸÑÐµÐŽÑÑÐ° Ð°Ð²ÑÐŸÐ·Ð°Ð¿ÑÑÐºÐ°.</Text>
+</Content>
+</Section>
+<Section id="finding_information_1">
+<Title>
+<Text id="49">ÐÐŸÐžÑÐº ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="50">Ð¡Ð°ÐŒÑÐ¹ Ð¿ÑÐŸÑÑÐŸÐ¹ ÑÐ¿ÐŸÑÐŸÐ± ÐœÐ°ÑÑÐžÑÑÑÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒÐž Greenstone - ÑÑÐŸ Ð¿ÑÐŸÑÑÐŸ Ð¿ÐŸÐ¿ÑÐŸÐ±ÐŸÐ²Ð°ÑÑ ÑÐ°Ð±ÐŸÑÐ°ÑÑ Ð² ÐœÐžÑ
+. ÐÐµ Ð²ÐŸÐ»ÐœÑÐ¹ÑÐµÑÑ, Ð²Ñ ÐœÐžÑÐµÐ³ÐŸ ÐœÐµ ÑÐ»ÐŸÐŒÐ°ÐµÑÐµ. ÐÐ°Ð¶ÐžÐŒÐ°Ð¹ÑÐµ ÐœÐ° ÐžÐºÐŸÐœÐºÐž Ð±ÐµÐ· ÐºÐŸÐ»ÐµÐ±Ð°ÐœÐžÐ¹. ÐÑÐ»Ðž Ð²Ñ Ð·Ð°ÐŽÐµÑÐ¶ÐžÑÐµ ÐºÑÑÑÐŸÑ ÐŒÑÑÐž ÐœÐ° ÐžÐºÐŸÐœÐºÐµ ÐœÐ° ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐ¹ Ð¿ÐµÑÐžÐŸÐŽ, ÑÐŸ Ð¿ÐŸÑÐ²ÐžÑÑÑ ÐœÐµÐ±ÐŸÐ»ÑÑÐŸÐµ Ð¿ÐŸÑÑÐœÐµÐœÐžÐµ, Ð² ÐºÐŸÑÐŸÑÐŸÐŒ ÐœÐ°Ð¿ÐžÑÐ°ÐœÐŸ, ÑÑÐŸ ÑÐ»ÑÑÐžÑÑÑ Ð¿ÐŸÑÐ»Ðµ ÐœÐ°Ð¶Ð°ÑÐžÑ.</Text>
+<Text id="51">Ð­ÐºÑÐ¿ÐµÑÐžÐŒÐµÐœÑÐžÑÑÐ¹ÑÐµ! ÐÐ°Ð±ÐžÑÐ°Ð¹ÑÐµ ÑÐ°ÐºÐžÐµ ÑÐŸÑÐ·Ñ ÐºÐ°Ðº "Ðž"Ð² ÐŸÐºÐœÐµ Ð¿ÐŸÐžÑÐºÐ° Ðž Ð¶ÐŒÐžÑÐµ ÐœÐ° Ð¿ÐŸÐžÑÐº, Ð¿ÐŸÑÐ»Ðµ ÑÐµÐ³ÐŸ Ð¿ÐŸÑÐ²ÑÑÑÑ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÑ Ð¿ÐŸÐžÑÐºÐ°. ÐÐ°Ðº Ð²ÐžÐŽÐžÑÐµ, ÐœÐžÑÐµÐ³ÐŸ ÐœÐµ ÑÐ»ÐŸÐŒÐ°Ð»ÐŸÑÑ.</Text>
+<Text id="52">ÐŠÐžÑÑÐŸÐ²ÑÐµ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐµ ÑÐžÑÑÐµÐŒÑ Greenstone, ÐºÐ°Ðº Ð¿ÑÐ°Ð²ÐžÐ»ÐŸ, ÑÐŸÑÑÐŸÑÑ ÐžÐ· ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ - ÑÐ°ÐºÐžÑ
+, ÐºÐ°Ðº ÑÐµÑ
+ÐœÐžÑÐµÐºÐžÐµ ÐŽÐŸÐºÐ»Ð°ÐŽÑ ÐžÐ· ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐœÐŸÐ¹ ÑÑÐµÑÑ, Ñ
+ÑÐŽÐŸÐ¶ÐµÑÑÐ²ÐµÐœÐœÑÐµ ÐºÐœÐžÐ³Ðž, Ð¶ÑÑÐœÐ°Ð»Ñ Ðž Ñ.ÐŽ. Ð¡ÑÑÐµÑÑÐ²ÑÐµÑ WWW-ÑÑÑÐ°ÐœÐžÑÐ° ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÑÐºÑÑÐ²Ð°ÐµÑ ÐŽÐŸÑÑÑÐ¿ Ðº Ð»ÑÐ±ÑÐŒ ÐŸÐ±ÑÐµÐŽÐŸÑÑÑÐ¿ÐœÑÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒ: Ðº ÑÐŸÐŒÑ Ð¶Ðµ ÐºÐ°Ð¶ÐŽÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐžÐŒÐµÐµÑ ÐŸÐ·ÐœÐ°ÐºÐŸÐŒÐžÑÐµÐ»ÑÐœÑÑ ÑÑÑÐ°ÐœÐžÑÐºÑ, Ð² ÐºÐŸÑÐŸÑÐŸÐ¹ ÑÐŸÐŽÐµÑÐ¶ÐžÑÑÑ ÐžÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÑÐŸÐŒ, ÐºÐ°Ðº ÐŸÑÐ³Ð°ÐœÐžÐ·ÐŸÐ²Ð°ÐœÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ðž ÑÑÐŸ Ð² ÐœÐµÐ¹ ÐµÑÑÑ. Ð§ÑÐŸÐ±Ñ Ð²ÐµÑÐœÑÑÑÑÑ ÐœÐ° ÑÑÑ ÑÑÑÐ°ÐœÐžÑÐºÑ Ð² Ð»ÑÐ±ÐŸÐµ Ð²ÑÐµÐŒÑ, Ð¿ÑÐŸÑÑÐŸ ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐžÐºÐŸÐœÐºÑ "ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ", ÐºÐŸÑÐŸÑÐ°Ñ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² Ð²ÐµÑÑ
+ÐœÐµÐŒ Ð»ÐµÐ²ÐŸÐŒ ÑÐ³Ð»Ñ ÑÑÑÐ°ÐœÐžÑÑ.</Text>
+<Text id="53">ÐÐ° Ð ÐžÑÑÐœÐºÐµ 1 ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐ° ÐÐµÐŒÐŸ-ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐºÐŸÑÐŸÑÐ°Ñ Ð²ÐºÐ»ÑÑÐµÐœÐ° Ð² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ Greenstone, ÐŸÐœÐ° ÑÐ²Ð»ÑÐµÑÑÑ ÐŸÑÑÑÐ²ÐºÐŸÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Ð Ð°Ð·Ð²ÐžÑÐžÑ. ÐÑ Ð±ÑÐŽÐµÐŒ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐµÐµ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ Ð¿ÑÐžÐŒÐµÑÐ° ÐŽÐ»Ñ ÑÐ°Ð·ÐœÐŸÐ³ÐŸ Ð²ÐžÐŽÐ° Ð¿ÐŸÐžÑÐºÐ° ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž. ÐÑÐ»Ðž Ð²Ñ ÐœÐµ ÐŒÐŸÐ¶ÐµÑÐµ ÐœÐ°Ð¹ÑÐž ÐÐµÐŒÐŸ-ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÑÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÑ ÑÐ°Ð·Ð²ÐžÑÐžÑ; ÐŸÐœÐž Ð²ÑÐ³Ð»ÑÐŽÑÑ ÐŸÐŽÐžÐœÐ°ÐºÐŸÐ²ÐŸ. ÐÐŸ-Ð¿ÐµÑÐ²ÑÑ
+, Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐž ÐœÐ° Ð²ÑÐµ ÐžÐºÐŸÐœÐºÐž ÐŒÐŸÐ¶ÐœÐŸ ÐœÐ°Ð¶ÐžÐŒÐ°ÑÑ. ÐÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐžÐºÐŸÐœÐŸÐº ÐœÐ°Ñ
+ÐŸÐŽÑÑÑÑ ÐœÐ°Ð²ÐµÑÑ
+Ñ Ð¿ÐŸÑÑÐž ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÑ. Ð¢Ð°Ð±Ð»ÐžÑÐ° 1 Ð³ÐŸÐ²ÐŸÑÐžÑ ÐŸ ÑÐŸÐŒ, ÑÑÐŸ ÐŸÐœÐž ÐŸÐ·ÐœÐ°ÑÐ°ÑÑ.</Text>
+<Figure id="using_the_demo_collection">
+<Title>
+<Text id="54">ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÐÐµÐŒÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<File width="397" height="286" url="images/User_Fig_1.png"/>
+</Figure>
+<Table id="what_the_icons_at_the_top_of_each_page_mean">
+<Title>
+<Text id="55">ÐÐœÐ°ÑÐµÐœÐžÑ ÐžÐºÐŸÐœÐŸÐº, ÐœÐ°Ñ
+ÐŸÐŽÑÑÐžÑ
+ÑÑ ÐœÐ° Ð²ÐµÑÑ
+ÐœÐµÐ¹ Ð¿Ð°ÐœÐµÐ»Ðž</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="132">
+<File width="68" height="32" url="images/User_Icon_1.png"/>
+</th>
+<th width="397">
+<Text id="56">ÐÐœÐ° ÑÐŸÐµÐŽÐžÐœÑÐµÑ Ð²Ð°Ñ ÑÐŸ ÑÑÑÐ°ÐœÐžÑÐµÐ¹ "ÐŸÐ·ÐœÐ°ÐºÐŸÐŒÐ»ÐµÐœÐžÑ" (ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž)</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<File width="36" height="16" url="images/User_Icon_2.png"/>
+</th>
+<th width="397">
+<Text id="57">ÐÐœÐ° Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑ Ð²Ð°Ñ Ðº ÐœÐ°ÑÐ°Ð»ÑÐœÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐµ, Ñ ÐºÐŸÑÐŸÑÐŸÐ¹ ÐŒÐŸÐ¶ÐœÐŸ ÐŸÑÐºÑÑÑÑ ÐŽÑÑÐ³ÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<File width="29" height="16" url="images/User_Icon_3.png"/>
+</th>
+<th width="397">
+<Text id="58">ÐÐŸÑÐ²Ð»ÑÐµÑÑÑ ÑÐµÐºÑÑ, Ð¿ÐŸÑ
+ÐŸÐ¶ÐžÐ¹ ÐœÐ° ÑÐŸÑ, ÑÑÐŸ Ð²Ñ ÑÐžÑÐ°ÐµÑÐµ ÑÐµÐ¹ÑÐ°Ñ</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<File width="70" height="16" url="images/User_Icon_4.png"/>
+</th>
+<th width="397">
+<Text id="59">ÐÐ°ÐµÑ Ð²Ð°ÐŒ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ ÐœÐ°ÑÑÑÐŸÐžÑÑ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ðž ÑÐµÐ¶ÐžÐŒ Ð¿ÐŸÐžÑÐºÐ°, ÐºÐŸÑÐŸÑÑÐ¹ Ð±ÑÐŽÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ðœ</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="60">ÐÐ°ÐœÐµÐ»Ñ "Ð¿ÐŸÐžÑÐº... ÑÐºÐ°Ð·Ð°ÑÐµÐ»Ñ.... ÐœÐ°Ð·Ð²Ð°ÐœÐžÑ Ð°-Ñ..ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐž... ÑÐ¿ÐŸÑÐŸÐ±Ñ" ÐŽÐ°ÐµÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÑÐ°Ð·ÐœÑÐŒ ÑÐµÐ¶ÐžÐŒÐ°ÐŒ Ð¿ÐŸÐžÑÐºÐ° Ðž Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°. Ð¡Ð°ÐŒÐ°Ñ Ð»ÐµÐ²Ð°Ñ ÐžÐºÐŸÐœÐºÐ° Ð¿ÑÐµÐŽÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐ° ÐŽÐ»Ñ Ð¿ÐŸÐžÑÐºÐ°, Ð° ÑÐµÑÑÑÐµ ÑÐ¿ÑÐ°Ð²Ð° -Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÑÑ Ð¿ÑÐŸÑÐŒÐŸÑÑ Ð² ÑÐ°Ð·ÐœÑÑ
+ ÑÐµÐ¶ÐžÐŒÐ°Ñ
+. Ð­ÑÐž Ð¿ÐŸÑÐ»ÐµÐŽÐœÐžÐµ ÑÐµÑÑÑÐµ ÐºÐœÐŸÐ¿ÐºÐž ÐŒÐŸÐ³ÑÑ Ð²Ð°ÑÑÐžÑÐŸÐ²Ð°ÑÑÑÑ ÐŸÑ ÐŸÐŽÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðº ÐŽÑÑÐ³ÐŸÐ¹.</Text>
+<Subsection id="how_to_find_information">
+<Title>
+<Text id="61">ÐÐ°Ðº ÐœÐ°Ð¹ÑÐž ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ</Text>
+</Title>
+<Content>
+<Text id="62">Ð¢Ð°Ð±Ð»ÐžÑÐ° 2 ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ Ð¿ÑÑÑ ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐ² Ð¿ÐŸÐžÑÐºÐ° ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž ÐœÐ° ÐÐµÐŒÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Table id="table_icons_on_the_search_browse_bar">
+<Title>
+<Text id="63">ÐÐœÐ°ÑÐµÐœÐžÑ ÐžÐºÐŸÐœÐŸÐº Ð¿ÐŸÐžÑÐº\Ð¿ÑÐŸÑÐŒÐŸÑÑ</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="123">
+<File width="61" height="11" url="images/User_Icon_5.png"/>
+</th>
+<th width="407">
+<Text id="64">Ð¿ÐŸÐžÑÐº Ð¿ÐŸ ÑÐ¿ÐµÑÐžÐ°Ð»ÑÐœÑÐŒ ÑÐµÑÐŒÐžÐœÐ°ÐŒ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="58" height="11" url="images/User_Icon_6.png"/>
+</th>
+<th width="407">
+<Text id="65">ÐÐ³Ð»Ð°Ð²Ð»ÐµÐœÐžÐµ Ð¿ÐŸ ÐœÐ°Ð·Ð²Ð°ÐœÐžÑ ÑÐ°Ð±ÐŸÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="58" height="11" url="images/User_Icon_7.png"/>
+</th>
+<th width="407">
+<Text id="66">ÐÑÐµÐŽÐŒÐµÑÐœÑÐ¹ ÑÐºÐ°Ð·Ð°ÑÐµÐ»Ñ</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="71" height="11" url="images/User_Icon_8.png"/>
+</th>
+<th width="407">
+<Text id="67">ÐÐ³Ð»Ð°Ð²Ð»ÐµÐœÐžÐµ Ð¿ÐŸ ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑÐŒ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="58" height="11" url="images/User_Icon_9.png"/>
+</th>
+<th width="407">
+<Text id="68">ÐÐ³Ð»Ð°Ð²Ð»ÐµÐœÐžÐµ Ð¿ÐŸ ÑÐ¿ÐŸÑÐŸÐ±Ñ Ð¿ÑÐžÐŒÐµÐœÐµÐœÐžÑ.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="69">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑÐºÐ°ÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐµ ÑÐ»ÐŸÐ²Ð°, ÐœÐ°Ñ
+ÐŸÐŽÑÑÐžÐµÑÑ Ð² ÑÐµÐºÑÑÐµ ÑÐµÑÐµÐ· ÑÑÑÐ°ÐœÐžÑÑ "Ð¿ÐŸÐžÑÐº". ÐÐ° Ð¿ÐŸÐžÑÐºÐŸÐ²ÑÑ ÑÑÑÐ°ÐœÐžÑÑ ÐŒÐŸÐ¶ÐœÐŸ Ð¿ÐŸÐ¿Ð°ÑÑÑ Ñ Ð»ÑÐ±ÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÑ, ÐœÐ°Ð¶Ð°Ð² ÐºÐœÐŸÐ¿ÐºÑ ÐÐŸÐžÑÐº. Ð¢Ð°ÐºÐ¶Ðµ ÐŒÐŸÐ¶ÐœÐŸ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ Ð¿ÑÐ±Ð»ÐžÐºÐ°ÑÐžÐž ÐœÐ° ÑÐµÐŒÑ, ÐœÐ°Ð¶Ð°Ð² ÐœÐ° ÐºÐœÐŸÐ¿ÐºÑ ÑÐºÐ°Ð·Ð°ÑÐµÐ»Ñ. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐŸÑÑÑÐµÑÑÐ²ÐžÑÑ Ð¿ÐŸÐžÑÐº Ð¿ÐŸ ÑÐ¿ÐµÑÐžÐ°Ð»ÑÐœÑÐŒ ÑÐµÑÐŒÐžÐœÐ°ÐŒ ÑÐŸ ÑÑÑÐ°ÐœÐžÑÑ Ð¿ÐŸÐžÑÐºÐ°. Ð­ÑÐ° ÑÑÑÐ°ÐœÐžÑÐ° ÑÐ²Ð»ÑÐµÑÑÑ ÑÑÐ°ÑÑÐŸÐ²ÐŸÐ¹, ÐºÐŸÐ³ÐŽÐ° Ð²Ñ ÐœÐ°ÑÐžÐœÐ°ÐµÑÐµ ÑÐ°Ð±ÐŸÑÐ°ÑÑ Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹, Ðž ÐœÐ° ÐœÐµÐµ ÐŒÐŸÐ¶ÐœÐŸ Ð¿ÐŸÐ¿Ð°ÑÑÑ Ñ Ð»ÑÐ±ÑÑ
+ ÐŽÑÑÐ³ÐžÑ
+ ÑÑÑÐ°ÐœÐžÑ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐœÐ°Ð¶Ð°ÑÐžÑ ÐºÐœÐŸÐ¿ÐºÐž ÐÐŸÐžÑÐº. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐŸÑÐ°Ð±ÐŸÑÐ°ÑÑ Ñ Ð¿ÑÐµÐŽÐŒÐµÑÐœÑÐŒ ÑÐºÐ°Ð·Ð°ÑÐµÐ»ÐµÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž , ÐœÐ°Ð¶Ð°Ð² ÐºÐœÐŸÐ¿ÐºÑ Ð£ÐºÐ°Ð·Ð°ÑÐµÐ»Ñ. ÐÑÐµÐŽÐŒÐµÑÐœÑÐ¹ ÑÐºÐ°Ð·Ð°ÑÐµÐ»Ñ Ð¿ÐŸÑÑÑÐŸÐµÐœ Ð¿ÐŸ ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐŸÐŒÑ Ð¿ÑÐžÐœÑÐžÐ¿Ñ Ðž ÐŽÐ°ÐµÑ ÐœÐ°ÐžÐ±ÐŸÐ»ÐµÐµ Ð¿ÐŸÐ»ÐœÐŸÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐŸÐ³Ð»Ð°Ð²Ð»ÐµÐœÐžÐµ Ð¿ÐŸ ÐœÐ°Ð·Ð²Ð°ÐœÐžÑÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐœÐ°Ð¶Ð°ÑÐžÐµÐŒ ÐºÐœÐŸÐ¿ÐºÐž ÐÐ°Ð·Ð²Ð°ÐœÐžÑ Ð-Ð¯. Ð ÑÑÐŸÐŒ ÐŸÐ³Ð»Ð°Ð²Ð»ÐµÐœÐžÐž Ð²Ñ ÑÐ²ÐžÐŽÐžÑÐµ ÑÐ¿ÐžÑÐŸÐº ÐºÐœÐžÐ³ Ð² Ð°Ð»ÑÐ°Ð²ÐžÑÐœÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐŸÐ³Ð»Ð°Ð²Ð»ÐµÐœÐžÐµ Ð¿ÐŸ ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑÐŒ ÐœÐ°Ð¶Ð°ÑÐžÐµÐŒ ÐºÐœÐŸÐ¿ÐºÐž ÐÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐž. Ð ÑÑÐŸÐŒ ÐŸÐ³Ð»Ð°Ð²Ð»ÐµÐœÐžÐž Ð²Ñ ÑÐ²ÐžÐŽÐžÑÐµ ÑÐ¿ÐžÑÐŸÐº ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐ¹. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐŸÐ³Ð»Ð°Ð²Ð»ÐµÐœÐžÐµ Ð¿ÐŸ ÑÐ¿ÐŸÑÐŸÐ±Ð°ÐŒ Ð¿ÑÐžÐŒÐµÐœÐµÐœÐžÑ ÐœÐ°Ð¶Ð°ÑÐžÐµÐŒ ÐºÐœÐŸÐ¿ÐºÐž Ð¡Ð¿ÐŸÑÐŸÐ±. Ð ÑÑÐŸÐŒ ÐŸÐ³Ð»Ð°Ð²Ð»ÐµÐœÐžÐž Ð²Ñ ÑÐ²ÐžÐŽÐžÑÐµ ÑÐ¿ÐžÑÐŸÐº Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐžÑ
+ ÑÐµÐºÐŸÐŒÐµÐœÐŽÐ°ÑÐžÐ¹, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐžÑ
+ÑÑ Ð² ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°Ñ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. All these buttons are visible in Figure 1.</Text>
+</Content>
+</Subsection>
+<Subsection id="how_to_read_the_documents">
+<Title>
+<Text id="70">ÐÐ°Ðº ÑÐžÑÐ°ÑÑ ÐºÐœÐžÐ³Ðž</Text>
+</Title>
+<Content>
+<Text id="71">ÐÐŸÐ³ÐŽÐ° Ð²Ñ ÐŸÑÐºÑÐŸÐµÑÐµ ÐºÐ°ÐºÑÑ-ÐœÐžÐ±ÑÐŽÑ ÐºÐœÐžÐ³Ñ, Ð²Ñ ÑÐ²ÐžÐŽÐžÑÐµ ÑÐžÑÑÐœÐŸÐº ÐµÐµ ÐŸÐ±Ð»ÐŸÐ¶ÐºÐž Ð² Ð»ÐµÐ²ÐŸÐŒ Ð²ÐµÑÑ
+ÐœÐµÐŒ ÑÐ³Ð»Ñ ÑÑÑÐ°ÐœÐžÑÑ. ÐÑÐŸÐŒÐµ ÑÐžÑÑÐœÐºÐ° ÐŸÐ±Ð»ÐŸÐ¶ÐºÐž, Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÐœÐ°Ð¹ÑÐž ÑÐ°Ð±Ð»ÐžÑÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ. Ð¢Ð°Ð±Ð»ÐžÑÐ° ÐŒÐŸÐ¶ÐµÑ ÑÐ°ÑÑÐžÑÑÑÑÑÑ: ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° Ð¿Ð°Ð¿ÐºÐž, ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ ÑÑÐŸÐ±Ñ ÐŸÑÐºÑÑÑÑ ÐžÐ»Ðž Ð·Ð°ÐºÑÑÑÑ ÐžÑ
+. ÐÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐŸÑÐºÑÑÑÑÑ ÐºÐœÐžÐ³Ñ Ð²Ð²ÐµÑÑ
+Ñ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ, ÑÑÐŸÐ±Ñ Ð·Ð°ÐºÑÑÑÑ ÐµÐµ.</Text>
+<Text id="72">ÐÐžÐ¶Ðµ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÑÐµÐºÑÑ ÑÐµÐºÑÑÐµÐ³ÐŸ ÑÐ°Ð·ÐŽÐµÐ»Ð°. ÐÐŸÑÐ»Ðµ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº Ð²Ñ Ð¿ÑÐŸÑÐžÑÐ°ÐµÑÐµ ÐµÐ³ÐŸ, Ð²ÐœÐžÐ·Ñ Ð²Ñ ÑÐ²ÐžÐŽÐžÑÐµ ÑÑÑÐµÐ»ÐºÐž ÐŽÐ»Ñ Ð¿ÐµÑÐµÑ
+ÐŸÐŽÐ° Ðº ÑÐ»ÐµÐŽÑÑÑÐµÐŒÑ ÐžÐ»Ðž Ð¿ÑÐµÐŽÑÐŽÑÑÐµÐŒÑ ÑÐ°Ð·ÐŽÐµÐ»Ñ.</Text>
+<Text id="73">ÐÐžÐ¶Ðµ ÑÐŸÑÐŸÐ³ÑÐ°ÑÐžÐž ÐœÐ°Ñ
+ÐŸÐŽÑÑÑÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐºÐœÐŸÐ¿ÐŸÐº. ÐÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐÐµÑÑ ÑÐµÐºÑÑ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÐŸÑÐŸÐ±ÑÐ°Ð·ÐžÑÑ ÐœÐ° ÑÐºÑÐ°ÐœÐµ Ð²ÐµÑÑ ÑÐµÐºÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. ÐÑÐ»Ðž ÐºÐœÐžÐ³Ð° ÐŽÐŸÑÑÐ°ÑÐŸÑÐœÐŸ Ð±ÐŸÐ»ÑÑÐ°Ñ, ÑÐŸ ÑÑÐŸ ÐŒÐŸÐ¶ÐµÑ Ð·Ð°ÐœÑÑÑ ÐœÐµÐºÐŸÑÐŸÑÐŸÐµ Ð²ÑÐµÐŒÑ Ðž ÐŒÐœÐŸÐ³ÐŸ Ð¿Ð°ÐŒÑÑÐž. ÐÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐÑÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÐŸÑÐŸÐ±ÑÐ°Ð·ÐžÐ»ÐŸÑÑ Ð²ÑÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ, Ð³ÐŽÐµ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐ²ÐžÐŽÐµÑÑ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐž Ð²ÑÐµÑ
+ Ð³Ð»Ð°Ð² Ðž Ð¿ÐŸÐŽÑÐ°Ð·ÐŽÐµÐ»ÐŸÐ². ÐÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° Ð ÐœÐŸÐ²ÐŸÐŒ ÐŸÐºÐœÐµ ÑÑÐŸÐ±Ñ ÐŸÑÐŸÐ±ÑÐ°Ð·ÐžÑÑ ÐŽÐ°ÐœÐœÑÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ Ð² ÐœÐŸÐ²ÐŸÐŒ ÐŸÐºÐœÐµ. Ð­ÑÐŸ Ð±ÑÐ²Ð°ÐµÑ Ð¿ÐŸÐ»ÐµÐ·ÐœÐŸ, ÐµÑÐ»Ðž Ð²Ñ Ñ
+ÐŸÑÐžÑÐµ ÑÑÐ°Ð²ÐœÐžÑÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐžÐ»Ðž ÑÐžÑÐ°ÑÑ ÑÑÐ°Ð·Ñ ÐŽÐ²Ð°. ÐÐ°ÐºÐŸÐœÐµÑ, ÐµÑÐ»Ðž Ð²Ñ ÐœÐ°ÑÐ»Ðž ÑÑÐŸÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ Ð¿ÐŸ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐŒ ÑÐ»ÐŸÐ²Ð°ÐŒ, ÑÐŸ ÐŸÐœÐž Ð±ÑÐŽÑÑ Ð²ÑÐŽÐµÐ»ÐµÐœÑ Ð² ÑÐµÐºÑÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. ÐÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° Ð¡ÐœÑÑÑ Ð²ÑÐŽÐµÐ»ÐµÐœÐžÐµ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÐžÑÐºÐŸÐŒÑÐµ ÑÐ»ÐŸÐ²Ð° ÐœÐµ Ð²ÑÐŽÐµÐ»ÑÐ»ÐžÑÑ Ð² ÑÐµÐºÑÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°.</Text>
+<Text id="74"></Text>
+<Figure id="a_book_in_the_demo_collection">
+<Title>
+<Text id="75">ÐÐœÐžÐ³Ð° Ð² ÐÐµÐŒÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<File width="397" height="476" url="images/User_Fig_2.png"/>
+</Figure>
+</Content>
+</Subsection>
+<Subsection id="what_the_icons_mean">
+<Title>
+<Text id="76">Ð§ÑÐŸ ÐŸÐ·ÐœÐ°ÑÐ°ÑÑ ÐžÐºÐŸÐœÐºÐž</Text>
+</Title>
+<Content>
+<Text id="77">ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð²Ñ ÑÑÐŸÐ»ÐºÐœÐµÑÐµÑÑ Ñ ÑÐ»ÐµÐŒÐµÐœÑÐ°ÐŒÐž, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐœÑÐŒÐž Ð² Ð¢Ð°Ð±Ð»ÐžÑÐµ 3.</Text>
+</Content>
+</Subsection>
+<Subsection id="how_to_search_for_particular_words">
+<Title>
+<Text id="78">ÐÐ°Ðº ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÑÑ Ð¿ÐŸÐžÑÐº Ð¿ÐŸ ÑÐ¿ÐµÑÐžÐ°Ð»ÑÐœÑÐŒ ÑÐµÑÐŒÐžÐœÐ°ÐŒ</Text>
+</Title>
+<Content>
+<Text id="79">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐŽÐµÐ»Ð°ÑÑ Ð¿ÑÐŸÑÑÐŸÐ¹ Ð·Ð°Ð¿ÑÐŸÑ ÑÐŸ ÑÑÑÐ°ÐœÐžÑÑ Ð¿ÐŸÐžÑÐºÐ°, ÑÐŸÐ³Ð»Ð°ÑÐœÐŸ ÑÐ»ÐµÐŽÑÑÑÐžÑ
+ ÑÐ°Ð³ÐŸÐ²:</Text>
+<BulletList>
+<Bullet>
+<Text id="80">ÐÐ¿ÑÐµÐŽÐµÐ»ÐžÑÐµ ÑÑÐŸ Ð²Ñ Ñ
+ÐŸÑÐžÑÐµ ÐœÐ°Ð¹ÑÐž</Text>
+</Bullet>
+<Bullet>
+<Text id="81">ÐÐ¿ÑÐµÐŽÐµÐ»ÐžÑÐµ, ÐºÐ°Ðº Ð²Ñ ÑÑÐŸ Ñ
+ÐŸÑÐžÑÐµ ÐžÑÐºÐ°ÑÑ: ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÑÑÐ°Ð·Ñ ÐžÐ»Ðž ÐŸÑÐŽÐµÐ»ÑÐœÑÐµ ÑÐ»ÐŸÐ²Ð°</Text>
+</Bullet>
+<Bullet>
+<Text id="82">ÐÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ ÑÐµÐºÑÑ Ð·Ð°Ð¿ÑÐŸÑÐ° Ð² ÑÑÑÐŸÐºÐµ Ð¿ÐŸÐžÑÐºÐ°</Text>
+</Bullet>
+<Bullet>
+<Text id="83">ÐÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐºÐœÐŸÐ¿ÐºÑ ÐÐ°ÑÐ°ÑÑ Ð¿ÐŸÐžÑÐº</Text>
+</Bullet>
+</BulletList>
+<Text id="84">ÐÐŸÑÐ»Ðµ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ Ð·Ð°Ð¿ÑÐŸÑÐ° ÐœÐ° ÑÐºÑÐ°ÐœÐµ Ð¿ÐŸÑÐ²ÐžÑÑÑ 20 ÐœÐ°ÐžÐŒÐµÐœÐŸÐ²Ð°ÐœÐžÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². Ð ÐºÐŸÐœÑÐµ ÑÐ¿ÐžÑÐºÐ° ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÐºÐœÐŸÐ¿ÐºÐ°, Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐºÐŸÑÐŸÑÐŸÐ¹ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐµÑÐµÐ¹ÑÐž Ðº ÑÐ»ÐµÐŽÑÑÑÐžÐŒ 20. ÐÐ° ÑÐ»ÐµÐŽÑÑÑÐžÑ
+ ÑÑÑÐ°ÐœÐžÑÐ°Ñ
+ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐŸÐ² Ð²Ñ ÑÐ²ÐžÐŽÐžÑÐµ ÐºÐœÐŸÐ¿ÐºÐž ÐŽÐ»Ñ Ð¿ÐµÑÐµÑ
+ÐŸÐŽÐ° Ðº ÑÐ»ÐµÐŽÑÑÑÐžÐŒ 20 ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ ÐžÐ»Ðž ÐŸÐ±ÑÐ°ÑÐœÐŸ Ðº Ð¿ÑÐµÐŽÑÐŽÑÑÐžÐŒ Ðž Ñ.ÐŽ. ÐÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ Ð»ÑÐ±ÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÐžÐ»Ðž Ð·ÐœÐ°ÑÐŸÐº Ð¿ÐµÑÐµÐŽ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµÐŒ, ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ ÑÑÐŸÐ±Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ ÐµÐ³ÐŸ. ÐÐ°ÐºÑÐžÐŒÐ°Ð»ÑÐœÐŸÐµ ÑÐžÑÐ»ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐ° Ð¿ÐŸÐžÑÐºÐ° - 100. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÑÑÐŸ ÑÐžÑÐ»ÐŸ ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ ÐœÐ°ÑÑÑÐŸÐµÐº ( ÐºÐœÐŸÐ¿ÐºÐ° ÐÐ°ÑÑÑÐŸÐ¹ÐºÐž Ð²Ð²ÐµÑÑ
+Ñ ÑÑÑÐ°ÐœÐžÑÑ ).</Text>
+<Table id="table_icons_that_you_will_encounter_when_browsing">
+<Title>
+<Text id="85">ÐÐºÐŸÐœÐºÐž, Ñ ÐºÐŸÑÐŸÑÑÐŒÐž Ð²Ñ Ð±ÑÐŽÐµÑÐµ ÑÐ°Ð±ÐŸÑÐ°ÑÑ</Text>
+</Title>
+<TableContent>
+<tr>
+<th width="123">
+<File width="19" height="12" url="images/User_Icon_10.png"/>
+</th>
+<th width="407">
+<Text id="86">ÐÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐžÐºÐŸÐœÐºÑ ÐºÐœÐžÐ³Ðž, ÑÑÐŸÐ±Ñ ÑÐžÑÐ°ÑÑ ÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÑÑ ÐºÐœÐžÐ³Ñ</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="22" height="17" url="images/User_Icon_11.png"/>
+</th>
+<th width="407">
+<Text id="87">ÐÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐžÐºÐŸÐœÐºÑ ÐºÐœÐžÐ¶ÐœÐŸÐ¹ Ð¿ÐŸÐ»ÐºÐž, ÑÑÐŸÐ±Ñ ÑÐŒÐŸÑÑÐµÑÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="25" height="16" url="images/User_Icon_12.png"/>
+</th>
+<th width="407">
+<Text id="88">ÐºÐœÐžÐ³Ðž Ð¿ÐŸ ÑÑÐŸÐ¹ ÑÐµÐŒÐµ. Ð¡ÐŒÐŸÑÑÐµÑÑ ÑÑÐŸÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="25" height="16" url="images/User_Icon_13.png"/>
+</th>
+<th width="407">
+<Text id="89">ÐÑÐºÑÐŸÐ¹ÑÐµ ÑÑÑ Ð¿Ð°Ð¿ÐºÑ Ðž Ð¿ÐŸÑÐŒÐŸÑÑÐžÑÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="29" height="25" url="images/User_Icon_14.png"/>
+</th>
+<th width="407">
+<Text id="90">ÐÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐžÐºÐŸÐœÐºÑ, ÑÑÐŸÐ±Ñ Ð·Ð°ÐºÑÑÑÑ ÐºÐœÐžÐ³Ñ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="25" height="17" url="images/User_Icon_15.png"/>
+</th>
+<th width="407">
+<Text id="91">ÐÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐžÐºÐŸÐœÐºÑ, ÑÑÐŸÐ±Ñ Ð·Ð°ÐºÑÑÑÑ Ð¿Ð°Ð¿ÐºÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="32" height="17" url="images/User_Icon_16.png"/>
+</th>
+<th width="407">
+<Text id="92">ÐÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÑÑÑÐµÐ»ÐºÑ, ÑÑÐŸÐ±Ñ Ð¿ÐµÑÐµÐ¹ÑÐž Ðº ÑÐ»ÐµÐŽÑÑÑÐµÐŒÑ ÑÐ°Ð·ÐŽÐµÐ»Ñ...</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="32" height="17" url="images/User_Icon_17.png"/>
+</th>
+<th width="407">
+<Text id="93">... ÐžÐ»Ðž ÐœÐ°Ð·Ð°ÐŽ  Ðº Ð¿ÑÐµÐŽÑÐŽÑÑÐµÐŒÑ ÑÐ°Ð·ÐŽÐµÐ»Ñ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="49" height="31" url="images/User_Icon_18.png"/>
+</th>
+<th width="407">
+<Text id="94">ÐÑÐºÑÐŸÐžÑÐµ ÑÑÑ ÑÑÑÐ°ÐœÐžÑÑ Ð² ÐœÐŸÐ²ÐŸÐŒ ÐŸÐºÐœÐµ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="61" height="32" url="images/User_Icon_19.png"/>
+</th>
+<th width="407">
+<Text id="95">Ð Ð°Ð·Ð²ÐµÑÐœÑÑÑ ÐŸÐ³Ð»Ð°Ð²Ð»ÐµÐœÐžÐµ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="48" height="32" url="images/User_Icon_20.png"/>
+</th>
+<th width="407">
+<Text id="96">ÐÑÐŸÐ±ÑÐ°Ð·ÐžÑÑ Ð²ÐµÑÑ ÑÐµÐºÑÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<File width="55" height="31" url="images/User_Icon_21.png"/>
+</th>
+<th width="407">
+<Text id="97">ÐÐŸÐŽÑÐ²ÐµÑÐžÑÑ ÑÐµÑÐŒÐžÐœÑ Ð¿ÐŸÐžÑÐºÐ°</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+<Text id="98">ÐÐ»Ñ ÐŸÑÐºÑÑÑÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐµÐ³ÐŸ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐžÐ»Ðž ÐœÐ° ÐžÐºÐŸÐœÐºÑ Ð²ÐŸÐ·Ð»Ðµ ÐœÐµÐ³ÐŸ. ÐÐ° ÐžÐºÐŸÐœÐºÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐ° ÐºÐœÐžÐ³Ð°, Ð¿Ð°Ð¿ÐºÐ° ÐžÐ»Ðž ÑÑÑÐ°ÐœÐžÑÐ°: Ð² ÑÐ»ÑÑÐ°Ðµ ÐºÐœÐžÐ³Ðž ÑÐ°ÐŒ Ð±ÑÐŽÐµÑ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐ° ÐžÐºÐŸÐœÐºÐ° Ñ ÐºÐœÐžÐ³ÐŸÐ¹; Ð² ÐŽÑÑÐ³ÐžÑ
+ ÑÐ»ÑÑÐ°ÑÑ
+ Ð¿ÑÐž Ð¿ÐŸÐžÑÐºÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐ² Ð±ÑÐŽÐµÑ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐ° Ð¿Ð°Ð¿ÐºÐ° ÐžÐ»Ðž ÑÑÑÐ°ÐœÐžÑÐ° Ð² Ð·Ð°Ð²ÐžÑÐžÐŒÐŸÑÑÐž ÐŸÑ ÑÐŸÐ³ÐŸ, ÐžÐŒÐµÐµÑ Ð»Ðž ÐœÐ°Ð¹ÐŽÐµÐœÐœÐ°Ñ ÑÐµÐºÑÐžÑ Ð¿ÐŸÐŽÑÐ°Ð·ÐŽÐµÐ»Ñ.</Text>
+<Part id="search_terms">
+<Title>
+<Text id="99">Ð¡Ð»ÐŸÐ²Ð° ÐŽÐ»Ñ Ð¿ÐŸÐžÑÐºÐ°</Text>
+</Title>
+<Content>
+<Text id="100">Ð¢ÐŸ, ÑÑÐŸ Ð²Ñ Ð²Ð²ÐŸÐŽÐžÑÐµ Ð² ÑÑÑÐŸÐºÐµ Ð·Ð°Ð¿ÑÐŸÑÐ°, ÐœÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ "ÑÐ»ÐŸÐ²Ð°ÐŒÐž ÐŽÐ»Ñ Ð¿ÐŸÐžÑÐºÐ°". ÐÐ°Ð¶ÐŽÐŸÐµ ÑÐ»ÐŸÐ²ÐŸ ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ð±ÑÐºÐ²Ñ Ðž ÑÐžÑÑÑ. Ð¡Ð»ÐŸÐ²Ð° ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÑ Ð¿ÑÐŸÐ±ÐµÐ»Ð°ÐŒÐž. ÐÑÐ»Ðž ÐžÐŒÐµÐµÑÑÑ ÐºÐ°ÐºÐŸÐ¹-Ð»ÐžÐ±ÐŸ ÐŽÑÑÐ³ÐŸÐ¹ Ð·ÐœÐ°Ðº, ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, Ð·ÐœÐ°ÐºÐž Ð¿ÑÐœÐºÑÑÐ°ÑÐžÐž, ÑÐŸ ÐŸÐœÐž ÑÐ»ÑÐ¶Ð°Ñ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÑÐ°Ð·ÐŽÐµÐ»ÐžÑÐµÐ»ÐµÐ¹ ÑÐ»ÐŸÐ², ÐºÐ°Ðº Ðž Ð¿ÑÐŸÐ±ÐµÐ»Ñ, ÑÐŸ ÐµÑÑÑ ÐžÐ³ÐœÐŸÑÐžÑÑÑÑÑÑ. ÐÑ ÐœÐµ ÐŒÐŸÐ¶ÐµÑÐµ ÐŸÑÑÑÐµÑÑÐ²ÐžÑÑ Ð¿ÐŸÐžÑÐº Ð¿ÐŸ ÑÐ»ÐŸÐ²Ð°ÐŒ, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐžÐŒ Ð·ÐœÐ°ÐºÐž Ð¿ÑÐœÐºÑÑÐ°ÑÐžÐž.</Text>
+<Text id="101">ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÐ°ÑÑÐŒÐŸÑÑÐžÐŒ Ð·Ð°Ð¿ÑÐŸÑ</Text>
+<Text type="code" id="102">Ð¡ÐµÐ»ÑÑÐºÐŸ-Ð»ÐµÑÐœÐŸÐµ Ñ
+ÐŸÐ·ÑÐ¹ÑÑÐ²ÐŸ ÐœÐ° ÐŸÑÑÑÐŸÐ²Ð°Ñ
+ Ð¢ÐžÑ
+ÐŸÐ³ÐŸ ÐŸÐºÐµÐ°ÐœÐ°: Ð¡ÐžÑÑÐµÐŒÐ° Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐž (1993)</Text>
+<Text id="103">ÐŸÐœ Ð±ÑÐŽÐµÑ ÑÐ°Ð²ÐœÐŸÑÐžÐ»ÐµÐœ ÑÐ»ÐµÐŽÑÑÑÐµÐŒÑ</Text>
+<Text type="code" id="104">Ð¡ÐµÐ»ÑÑÐºÐŸÐµ Ð»ÐµÑÐœÐŸÐµ Ñ
+ÐŸÐ·ÑÐ¹ÑÑÐ²ÐŸ ÐœÐ° ÐŸÑÑÑÐŸÐ²Ð°Ñ
+ Ð¢ÐžÑ
+ÐŸÐ³ÐŸ ÐŸÐºÐµÐ°ÐœÐ° Ð¡ÐžÑÑÐµÐŒÐ° Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐž 1993</Text>
+</Content>
+</Part>
+<Part id="query_type">
+<Title>
+<Text id="105">Ð¢ÐžÐ¿Ñ Ð·Ð°Ð¿ÑÐŸÑÐŸÐ²</Text>
+</Title>
+<Content>
+<Text id="106">Ð¡ÑÑÐµÑÑÐ²ÑÐµÑ ÐŽÐ²Ð° ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÑÐžÐ¿Ð° Ð·Ð°Ð¿ÑÐŸÑÐ°.</Text>
+<BulletList>
+<Bullet>
+<Text id="107">ÐÐ°Ð¿ÑÐŸÑÑ Ð¿ÐŸ <b>Ð²ÑÐµÐŒ</b> ÑÐ»ÐŸÐ²Ð°ÐŒ. Ð­ÑÐŸ Ð¿ÐŸÐŽÑ
+ÐŸÐŽÐžÑ ÐŽÐ»Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŽÐµÑÐ¶Ð°Ñ Ð²ÑÐµ ÑÐ»ÐŸÐ²Ð°, ÐºÐŸÑÐŸÑÑÐµ Ð²Ñ Ñ
+ÐŸÑÐžÑÐµ Ð²ÐºÐ»ÑÑÐžÑÑ Ð² ÑÑÑÐŸÐºÑ Ð¿ÐŸÐžÑÐºÐ°.ÐÐŸÐºÑÐŒÐµÐœÑÑ, ÑÐŽÐŸÐ²Ð»ÐµÑÐ²ÐŸÑÑÑÑÐžÐµ Ð·Ð°Ð¿ÑÐŸÑÑ, Ð±ÑÐŽÑÑ Ð²ÑÐ²ÐµÐŽÐµÐœÑ Ð² Ð°Ð»ÑÐ°Ð²ÐžÑÐœÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ.</Text>
+</Bullet>
+<Bullet>
+<Text id="108">ÐÐ°Ð¿ÑÐŸÑÑ Ð¿ÐŸ <b>ÐœÐµÐºÐŸÑÐŸÑÑÐŒ</b> ÑÐ»ÐŸÐ²Ð°ÐŒ. ÐÐŸÑÑÐ°ÑÐŸÑÐœÐŸ ÐœÐ°Ð¿ÐžÑÐ°ÑÑ Ð»ÐžÑÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÐ»ÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ, Ð²ÐµÑÐŸÑÑÐœÐŸ, ÐœÐ°Ñ
+ÐŸÐŽÑÑÑÑ Ð² ÑÐµÐºÑÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. ÐÐŸÐºÑÐŒÐµÐœÑÑ Ð±ÑÐŽÑÑ ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÑ Ð² Ð¿ÐŸÑÑÐŽÐºÐµ ÑÐŒÐµÐœÑÑÐµÐœÐžÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÑ Ð·Ð°Ð¿ÑÐŸÑÑ. Ð¡ÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐµ Ð·Ð°Ð¿ÑÐŸÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑÑÑ ÑÐ°Ðº:</Text>
+<BulletList>
+<Bullet>
+<Text id="109">ÑÐµÐŒ Ð±ÐŸÐ»ÑÑÐµ ÐžÑÐºÐŸÐŒÑÑ
+ ÑÐµÑÐŒÐžÐœÐŸÐ² ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ, ÑÐµÐŒ Ð±ÐŸÐ»ÑÑÐµ ÐŸÐœ Ð¿ÐŸÐŽÑ
+ÐŸÐŽÐžÑ;</Text>
+</Bullet>
+<Bullet>
+<Text id="110">ÑÐµÐŽÐºÐžÐµ ÑÐ»ÐŸÐ²Ð° Ð±ÐŸÐ»ÐµÐµ Ð²Ð°Ð¶ÐœÑ, ÑÐµÐŒ ÐŸÐ±ÑÐžÐµ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÑ;</Text>
+</Bullet>
+<Bullet>
+<Text id="111">ÐŒÐ°Ð»ÐµÐœÑÐºÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð¿ÐŸÐŽÑ
+ÐŸÐŽÑÑ Ð»ÑÑÑÐµ, ÑÐµÐŒ Ð±ÐŸÐ»ÑÑÐžÐµ.</Text>
+</Bullet>
+</BulletList>
+</Bullet>
+</BulletList>
+</Content>
+</Part>
+<Text id="112">ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÑÑÐŸÐ»ÑÐºÐŸ ÑÐ»ÐŸÐ² ÐŽÐ»Ñ Ð¿ÐŸÐžÑÐºÐ°, ÑÐºÐŸÐ»ÑÐºÐŸ Ð²Ð°ÐŒ ÑÐ³ÐŸÐŽÐœÐŸ - ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÑÐµÐ»ÐŸÐµ Ð¿ÑÐµÐŽÐ»ÐŸÐ¶ÐµÐœÐžÐµ, ÐžÐ»Ðž Ð¿Ð°ÑÐ°Ð³ÑÐ°Ñ. ÐÑÐ»Ðž Ð²Ñ Ð²Ð²ÐµÐŽÐµÑÐµ ÑÐŸÐ»ÑÐºÐŸ ÐŸÐŽÐœÐŸ ÑÐ»ÐŸÐ²ÐŸ, ÑÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð±ÑÐŽÑÑ ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÑ Ð¿ÐŸ ÑÐ±ÑÐ²Ð°ÐœÐžÑ ÑÐ°ÑÑÐŸÑÑ ÐµÐ³ÐŸ Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÑ.</Text>
+</Content>
+</Subsection>
+<Subsection id="scope_of_queries">
+<Title>
+<Text id="113">ÐÐžÐ°Ð¿Ð°Ð·ÐŸÐœ Ð¿ÐŸÐžÑÐºÐ°</Text>
+</Title>
+<Content>
+<Text id="114">Ð Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²Ðµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÐžÐœÐŽÐµÐºÑÑ ÐŽÐ»Ñ Ð¿ÐŸÐžÑÐºÐ°. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÐžÐœÐŽÐµÐºÑ Ð¿ÐŸ ÐœÐ°Ð·Ð²Ð°ÐœÐžÑÐŒ ÐºÐœÐžÐ³ ÐžÐ»Ðž Ð¿ÐŸ ÑÐ°ÐŒÐžÐ»ÐžÑÐŒ Ð°Ð²ÑÐŸÑÐŸÐ². Ð­ÑÐŸ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐ°ÐºÐ¶Ðµ ÐžÐœÐŽÐµÐºÑÑ Ð¿ÐŸ Ð³Ð»Ð°Ð²Ð°ÐŒ ÐžÐ»Ðž Ð¿ÐŸ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ°ÐŒ ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐ². ÐÑÐ»Ðž Ð²Ñ ÐœÐµ ÑÐºÐ°Ð¶ÐµÑÐµ ÑÑÐµÐ±ÑÐµÐŒÑÐ¹ ÐžÐœÐŽÐµÐºÑ (Ð¿ÐŸ Ð³Ð»Ð°Ð²Ð°ÐŒ ÐžÐ»Ðž Ð¿ÐŸ ÑÐ°Ð·ÐŽÐµÐ»Ð°ÐŒ), ÑÐŸ ÐœÐ° ÑÐºÑÐ°Ðœ Ð±ÑÐŽÐµÑ Ð²ÑÐ²ÐµÐŽÐµÐœ Ð²ÐµÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ.</Text>
+<Text id="115">ÐÑÐ»Ðž ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐŒ ÑÐ²Ð»ÑÐµÑÑÑ ÑÐµÐ»Ð°Ñ ÐºÐœÐžÐ³Ð°, ÑÐŸ ÐŸÐœÐ° Ð±ÑÐŽÐµÑ ÐŸÑÐºÑÑÑÐ° Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐŒ ÐŒÐµÑÑÐµ.</Text>
+</Content>
+</Subsection>
+<Subsection id="advanced_search_features">
+<Title>
+<Text id="116">Ð Ð°ÑÑÐžÑÐµÐœÐžÐµ Ð¿ÐŸÐžÑÐºÐŸÐ²ÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž</Text>
+</Title>
+<Content>
+<Text id="117">Ð¥ÐŸÑÑ Ð²ÑÑÐµÐ¿ÐµÑÐµÑÐžÑÐ»ÐµÐœÐœÐŸÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐŽÐŸÑÑÐ°ÑÐŸÑÐœÑÐŒ ÐŽÐ»Ñ ÐŸÑÑÑÐµÑÑÐ²Ð»ÐµÐœÐžÑ Ð¿ÐŸÐžÑÐºÐ°, ÑÑÑÐµÑÑÐ²ÑÑÑ Ð±ÐŸÐ»ÐµÐµ ÑÐ°ÑÑÐžÑÐµÐœÐœÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž. ÐÑ
+ ÐŒÐŸÐ¶ÐœÐŸ Ð²ÐºÐ»ÑÑÐžÑÑ Ð² ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐ°Ñ
+ <i>(preferences)</i>, ÐœÐ°Ð¶Ð°Ð² ÐœÐ° ÐÐ°ÑÑÑÐŸÐ¹ÐºÐž Ð²Ð²ÐµÑÑ
+Ñ ÑÑÑÐ°ÐœÐžÑÑ â ÑÐŒÐŸÑÑÐžÑÐµ ÑÐ°Ð·ÐŽÐµÐ» 2.3 ÐœÐžÐ¶Ðµ. ÐÐŸÑÐ»Ðµ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ ÐœÐ°ÑÑÑÐŸÐµÐº, ÐœÐµ ÐœÐ°Ð¶ÐžÐŒÐ°Ð¹ÑÐµ ÐœÐ° ÐºÐœÐŸÐ¿ÐºÑ ÐÐ°Ð·Ð°ÐŽ Ð²Ð°ÑÐµÐ³ÐŸ Ð±ÑÐ°ÑÐ·ÐµÑÐ°, ÑÐ°Ðº ÐºÐ°Ðº ÐŸÐœÐŸ Ð²ÐµÑÐœÐµÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð² ÐžÑÑ
+ÐŸÐŽÐœÐŸÐµ Ð¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÐµ. ÐÐŒÐµÑÑÐŸ ÑÑÐŸÐ³ÐŸ ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° Ð»ÑÐ±ÑÑ ÐžÐ· ÐºÐœÐŸÐ¿ÐŸÐº ÐœÐ° Ð¿Ð°ÐœÐµÐ»Ðž Ð¿ÐŸÐžÑÐºÐ°/Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° <i>(search/browse bar)</i></Text>
+<Part id="case_sensitivity_and_stemming">
+<Title>
+<Text id="118">Ð ÐµÐ³ÐžÑÑÑÑ Ðž ÑÑÐµÐŒÐŒÐžÐœÐ³</Text>
+</Title>
+<Content>
+<Text id="119">ÐÐ²Ð° Ð¿ÐµÑÐµÐºÐ»ÑÑÐ°ÑÐµÐ»Ñ ÑÐ¿ÑÐ°Ð²Ð»ÑÑÑ ÑÐŸÑÐœÐŸÑÑÑÑ Ð¿ÐŸÐžÑÐºÐ° ÑÐµÐºÑÑÐ°. ÐÐµÑÐµÐºÐ»ÑÑÐ°ÑÐµÐ»Ñ ("Ð ÐµÐ³ÐžÑÑÑÑ") Ð²ÐºÐ»ÑÑÐ°ÐµÑ/ÐŸÑÐŒÐµÐœÑÐµÑ ÑÑÐµÑ ÑÐµÐ³ÐžÑÑÑÐ°.</Text>
+<Text id="120">ÐÐµÑÐµÐºÐ»ÑÑÐ°ÑÐµÐ»Ñ "ÐÐºÐŸÐœÑÐ°ÐœÐžÑ ÑÐ»ÐŸÐ²" Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐžÐ»Ðž ÐžÐ³ÐœÐŸÑÐžÑÐŸÐ²Ð°ÑÑ ÐŸÐºÐŸÐœÑÐ°ÐœÐžÑ Ñ ÑÐ»ÐŸÐ². ÐÐµÑÐµÐºÐ»ÑÑÐ°ÑÐµÐ»Ñ "Ð Ð°Ð·ÐŒÐµÑ ÐŸÐºÐœÐ° Ð¿ÐŸÐžÑÐºÐ°" Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð²Ð²ÐŸÐŽÐžÑÑ ÑÐµÐ»ÑÐ¹ Ð°Ð±Ð·Ð°Ñ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÑÐµÐºÑÑÐ° Ð·Ð°Ð¿ÑÐŸÑÐ°.</Text>
+<Text id="121">ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÐµÑÐ»Ðž Ð²ÑÐ±ÑÐ°ÐœÐŸ ÐžÐ³ÐœÐŸÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐµÐ³ÐžÑÑÑÑ Ðž ÐžÐ³ÐœÐŸÑÐžÑÐŸÐ²Ð°ÑÑ ÐŸÐºÐŸÐœÑÐ°ÐœÐžÑ ÑÐ»ÐŸÐ²,ÑÐŸ Ð·Ð°Ð¿ÑÐŸÑ</Text>
+<Text type="code" id="122">African building</Text>
+<Text id="123">Ð±ÑÐŽÐµÑ ÑÑÐ°ÐºÑÐŸÐ²Ð°ÑÑÑÑ ÐºÐ°Ðº</Text>
+<Text type="code" id="124">africa builds</Text>
+<Text id="125">Ð¿ÐŸÑÐŸÐŒÑ ÑÑÐŸ Ð±ÑÐºÐ²Ð° Ð²ÐµÑÑ
+ÐœÐµÐ³ÐŸ ÑÐµÐ³ÐžÑÑÑÐ° ÐžÐ· ÑÐ»ÐŸÐ²Ð° "African" Ð±ÑÐŽÐµÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐ° ÐœÐ° Ð±ÑÐºÐ²Ñ ÐœÐžÐ¶ÐœÐµÐ³ÐŸ ÑÐµÐ³ÐžÑÑÑÐ°, Ð° ÑÑÑÑÐžÐºÑÑ "Ð¿" Ðž "ing" Ð±ÑÐŽÑÑ ÑÐŽÐ°Ð»ÐµÐœÑ ÐžÐ· ÑÐ»ÐŸÐ² "African" Ðž "building" (ÑÐ°ÐºÐ¶Ðµ, "s" Ð±ÑÐŽÐµÑ ÑÐŽÐ°Ð»ÐµÐœÐ° ÐžÐ· "builds").</Text>
+<Text id="126">Generally case differences and word endings should be ignored unless you are querying for particular names or acronyms.</Text>
+</Content>
+</Part>
+<Part id="phrase_searching">
+<Title>
+<Text id="127">ÐÐŸÐžÑÐº ÑÑÐ°Ð·</Text>
+</Title>
+<Content>
+<Text id="128">ÐÑÐ»Ðž Ð²Ð°Ñ Ð·Ð°Ð¿ÑÐŸÑ Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð² ÑÐµÐ±Ñ ÑÑÐ°Ð·Ñ Ð² ÐºÐ°Ð²ÑÑÐºÐ°Ñ
+, ÑÐŸ Ð±ÑÐŽÑÑ Ð²ÑÐ²ÐµÐŽÐµÐœÑ ÑÐŸÐ»ÑÐºÐŸ ÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ, ÐºÐŸÑÐŸÑÑÐµ ÐžÐŒÐµÑÑ ÑÑÐ°Ð·Ñ, ÐžÐŽÐµÐœÑÐžÑÐœÑÑ ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°ÐœÐœÐŸÐ¹.</Text>
+<Text id="129">ÐÑÐ»Ðž Ð²Ñ Ð¶ÐµÐ»Ð°ÐµÑÐµ ÐœÐ°ÑÑÐžÑÑÑÑ Ð¿ÐŸÐžÑÐºÑ ÑÑÐ°Ð·, ÑÐŸ ÐœÑÐ¶ÐœÐŸ ÑÑÐŸ ÑÐ°Ð·ÐŸÐ±ÑÐ°ÑÑ. Ð€ÑÐ°Ð·Ñ ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÑÑÑÑ Ð² post-retrieval scan (ÐŽÐ²ÑÑ
+-ÑÐ°Ð·ÐŸÐ²ÐŸÐµ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ). Ð¡ÐœÐ°ÑÐ°Ð»Ð° Ð·Ð°Ð¿ÑÐŸÑ ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑÑÑ ÐŸÐ±ÑÑÐœÑÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ, ÐºÐ°Ð¶ÐŽÐŸÐµ ÐžÐ· ÑÐ»ÐŸÐ² ÑÑÐ°Ð·Ñ ÐžÐœÑÐµÑÐ¿ÑÐµÑÐžÑÑÐµÑÑÑ ÐºÐ°Ðº Ð¿ÐŸÐžÑÐºÐŸÐ²ÐŸÐµ ÑÐ»ÐŸÐ²ÐŸ; Ð·Ð°ÑÐµÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ñ ÑÑÐžÐŒÐž ÑÐ»ÐŸÐ²Ð°ÐŒÐž ÑÐœÐŸÐ²Ð° Ð¿ÑÐŸÑÐŒÐ°ÑÑÐžÐ²Ð°ÑÑÑÑ ÐŽÐ»Ñ ÐŸÑÐ±ÑÐ°ÑÑÐ²Ð°ÐœÐžÑ ÑÐµÑ
+, Ð² ÐºÐŸÑÐŸÑÑÑ
+ ÐœÐµÑ ÑÑÐŸÐ¹ ÑÑÐ°Ð·Ñ.</Text>
+<Text id="130">Ð Ð¿ÑÐŸÑÐµÑÑÐµ ÐŽÐ²ÑÑ
+-ÑÐ°Ð·ÐŸÐ²ÐŸÐ³ÐŸÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ ÑÑÐ°Ð·Ñ Ð¿ÑÐŸÐ²ÐµÑÑÑÑÑÑ ÑÐŸÑÐœÐŸ ÑÐ°Ðº Ð¶Ðµ, ÐºÐ°Ðº ÐŸÐœÐž Ð²Ð²ÐµÐŽÐµÐœÑ, Ð²ÐºÐ»ÑÑÐ°Ñ Ð·ÐœÐ°ÐºÐž Ð¿ÑÐœÐºÑÑÐ°ÑÐžÐž. Ð Ð¿ÑÐžÐŒÐµÑÑ,</Text>
+<Text type="code" id="131">Ð·Ð°Ð¿ÑÐŸÑ Ð§ÑÐŸ ÑÐ°ÐºÐŸÐµ "ÐŽÐ²ÑÑ
+-ÑÐ°Ð·ÐŸÐ²ÐŸÐµ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ?"</Text>
+<Text id="132">ÐÐ° Ð¿ÐµÑÐ²ÐŸÐ¹ ÑÑÐ°ÐŽÐžÐž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑÑ Ð²ÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐžÐµ ÑÐ»ÐŸÐ²Ð°</Text>
+<Text id="779">ÑÑÐŸ ÑÐ°ÐºÐŸÐ¹ ÐŽÐ²Ð° ÑÐ°Ð·Ð° ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ</Text>
+<Text id="133">Ð·Ð°ÑÐµÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ñ ÑÑÐžÐŒÐž ÑÐ»ÐŸÐ²Ð°ÐŒÐž Ð±ÑÐŽÑÑ Ð¿ÑÐŸÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÑ Ð Ð°ÑÑÐžÑÐµÐœÑÐ¹ Ð²ÐžÐŽ Ð·Ð°Ð¿ÑÐŸÑÐ° ÐœÐ° ÐœÐ°Ð»ÐžÑÐžÐµ ÑÑÐ°Ð·Ñ</Text>
+<Text type="code" id="134">ÐŽÐ²ÑÑ
+-ÑÐ°Ð·ÐŸÐ²ÐŸÐµ ÑÐºÐ°ÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ?</Text>
+<Text id="135">ÐÐ°Ð¹ÐŽÐµÐœÐœÑÐµ ÑÑÐ°Ð·Ñ ÐœÐµ Ð±ÑÐŽÑÑ ÑÑÐ²ÑÑÐ²ÐžÑÐµÐ»ÑÐœÑ Ðº ÑÐµÐ³ÐžÑÑÑÐ°ÐŒ, ÐµÑÐ»Ðž ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐŸÐ¿ÑÐžÑ ÐžÐ³ÐœÐŸÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐµÐ³ÐžÑÑÑÑ.</Text>
+</Content>
+</Part>
+<Part id="advanced_query_mode">
+<Title>
+<Text id="136">Ð Ð°ÑÑÐžÑÐµÐœÐœÐ°Ñ ÑÐŸÑÐŒÐ° Ð·Ð°Ð¿ÑÐŸÑÐ°</Text>
+</Title>
+<Content>
+<Text id="137">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐµÑÐµÐºÐ»ÑÑÐžÑÑÑÑ Ð² ÑÐ°ÑÑÐžÑÐµÐœÐœÑÑ ÑÐŸÑÐŒÑ Ð·Ð°Ð¿ÑÐŸÑÐ°, ÐºÐŸÑÐŸÑÐ°Ñ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÑÐŸÑÐµÑÐ°ÑÑ ÑÐ»ÐŸÐ²Ð°, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Ð (&amp;), ÐÐÐ (|), Ð ÐÐ (!). Ð­ÑÐŸ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ Ð±ÐŸÐ»ÐµÐµ ÑÐŸÑÐœÑÐµ Ð·Ð°Ð¿ÑÐŸÑÑ. Ð¢Ð°ÐºÐ¶Ðµ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÐºÐ»ÑÑÐžÑÑ Ð¿ÐŸÐºÐ°Ð· ÐžÑÑÐŸÑÐžÐž Ð·Ð°Ð¿ÑÐŸÑÐ°, ÐºÐŸÐ³ÐŽÐ° Ð±ÑÐŽÑÑ Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÑ Ð¿ÑÐµÐŽÑÐŽÑÑÐžÐµ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÑ Ð¿ÐŸÐžÑÐºÐ°. Ð­ÑÐŸ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ ÑÐ»ÐµÐ³ÐºÐ° ÐžÐ·ÐŒÐµÐœÐµÐœÐœÑÐµ ÑÐŸÑÐŒÑ Ð·Ð°Ð¿ÑÐŸÑÐŸÐ². ÐÐ°ÐºÐŸÐœÐµÑ, Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐµÐ³ÑÐ»ÐžÑÐŸÐ²Ð°ÑÑ ÐŸÐ±ÑÐµÐµ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² - ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐŸÐ² Ð¿ÐŸÐžÑÐºÐ°, Ð° ÑÐ°ÐºÐ¶Ðµ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐœÐ° ÐŸÐŽÐœÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐµ.</Text>
+<Text id="138">If the words AND, OR, and NOT appear in your query they are treated as ordinary search terms, not operators. For operators you must use &amp;, |, and !. In addition, parentheses can be used for grouping.</Text>
+</Content>
+</Part>
+<Part id="using_search_history">
+<Title>
+<Text id="139">ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ Ñ
+ÑÐŸÐœÐŸÐ»ÐŸÐ³ÐžÐž Ð¿ÐŸÐžÑÐºÐ°</Text>
+</Title>
+<Content>
+<Text id="140">ÐÐŸÐ³ÐŽÐ° Ð²Ñ Ð²ÐºÐ»ÑÑÐ°ÐµÑÐµ "Ñ
+ÑÐŸÐœÐŸÐ»ÐŸÐ³ÐžÐž Ð¿ÐŸÐžÑÐºÐ°" ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ Ð²ÑÐ±ÐŸÑÐ° Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÐ¹ (Preferences page), ÑÐŸ Ð²Ð°ÐŒ Ð±ÑÐŽÑÑ Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÑ Ð²Ð°ÑÐž Ð¿ÐŸÑÐ»ÐµÐŽÐœÐžÐµ Ð²Ð°ÑÐžÐ°ÐœÑÑ Ð¿ÐŸÐžÑÐºÐ°, ÐœÐ°ÑÑÐŽÑ Ñ ÐºÑÐ°ÑÐºÐžÐŒÐž ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐ°ÐŒÐž, ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐ»Ðž ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÑ. ÐÐ°Ð¶ÐŒÐžÑÐµ ÐºÐœÐŸÐ¿ÐºÑ ÐŸÐºÐŸÐ»ÐŸ ÐŸÐŽÐœÐŸÐ³ÐŸ ÐžÐ· Ð¿ÑÐµÐŽÑÐŽÑÑÐžÑ
+ Ð²Ð°ÑÐžÐ°ÐœÑÐŸÐ² Ð¿ÐŸÐžÑÐºÐ°, ÑÑÐŸÐ±Ñ ÑÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÑÑ ÑÐµÐºÑÑ Ð² Ð¿ÐŸÐ»Ðµ Ð¿ÐŸÐžÑÐºÐ°. Ð­ÑÐŸ ÐŸÐ±Ð»ÐµÐ³ÑÐžÑ Ð¿ÑÐŸÑÐµÑÑ, ÐµÑÐ»Ðž Ð²Ñ Ð¿ÐŸÐ»ÑÐ·ÑÐµÑÐµÑÑ ÑÐ»ÐµÐ³ÐºÐ° ÐžÐ·ÐŒÐµÐœÐµÐœÐœÐŸÐ¹ Ð²ÐµÑÑÐžÐµÐ¹ Ð¿ÑÐµÐŽÑÐŽÑÑÐžÑ
+ Ð·Ð°Ð¿ÑÐŸÑÐŸÐ².</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="changing_the_preferences">
+<Title>
+<Text id="141">ÐÐ·ÐŒÐµÐœÐµÐœÐžÐµ ÐœÐ°ÑÑÑÐŸÐµÐº</Text>
+</Title>
+<Content>
+<Figure id="the_preferences_page">
+<Title>
+<Text id="142">Ð¡ÑÑÐ°ÐœÐžÑÐ° ÐœÐ°ÑÑÑÐŸÐµÐº</Text>
+</Title>
+<File width="394" height="439" url="images/User_Fig_3.png"/>
+</Figure>
+<Text id="143">ÐÐ° ÑÑÑÐ°ÐœÐžÑÐµ <i>ÐÐ°ÑÑÑÐŸÐ¹ÐºÐž</i> (ÐºÐœÐŸÐ¿ÐºÐ° Ð² Ð²ÐµÑÑ
+ÐœÐµÐ¹ ÑÐ°ÑÑÐž ÑÑÑÐ°ÐœÐžÑÑ) Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐœÐµÐºÐŸÑÐŸÑÑÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°. ÐÑÐµ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž Ð·Ð°Ð²ÐžÑÑÑ ÐŸÑ ÑÐžÐ¿Ð° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž; Ð¿ÑÐžÐŒÐµÑ Ð¿ÐŸÐºÐ°Ð·Ð°Ðœ ÐœÐ° ÑÐžÑÑÐœÐºÐµ 3. ÐÐŸÑÐ»Ðµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐœÐ°ÑÑÑÐŸÐµÐº ÐœÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐºÐœÐŸÐ¿ÐºÑ "ÐÐ°Ð·Ð°ÐŽ" ÐœÐ° Ð±ÑÐ°ÑÐ·ÐµÑÐµ, ÑÐ°Ðº ÐºÐ°Ðº Ð²ÑÐµ ÐœÐ°ÑÑÐŸÐ¹ÐºÐž Ð²ÐµÑÐœÑÑÑÑ Ð² ÐžÑÑ
+ÐŸÐŽÐœÐŸÐµ Ð¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÐµ. ÐÐŒÐµÑÑÐŸ ÑÑÐŸÐ³ÐŸ ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐŸÐŽÐœÑ ÐžÐ· ÐºÐœÐŸÐ¿ÐŸÐº ÐœÐ° Ð¿Ð°ÐœÐµÐ»Ðž Ð²Ð²ÐµÑÑ
+Ñ ÑÐºÑÐ°ÐœÐ°.</Text>
+<Subsection id="collection_preferences">
+<Title>
+<Text id="144">ÐÐ°ÑÑÑÐŸÐ¹ÐºÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹</Text>
+</Title>
+<Content>
+<Text id="145">ÐÐµÐºÐŸÑÐŸÑÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐŸÐŽÐµÑÐ¶Ð°Ñ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ Ð¿ÐŸÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, Ð¿ÐŸÐžÑÐº Ð¿ÐŸ ÐºÐŸÑÐŸÑÑÐŒ ÐŒÐŸÐ¶ÐµÑ ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÑÑÑÑ ÐºÐ°Ðº Ð¿ÐŸ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÐžÐ· ÐœÐžÑ
+, ÑÐ°Ðº Ðž Ð¿ÐŸ Ð²ÑÐµÐŒ Ð²ÐŒÐµÑÑÐµ. ÐÐ° ÑÑÑÐ°ÐœÐžÑÐµ ÐÐ°ÑÑÑÐŸÐ¹ÐºÐž ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ ÑÐµ Ð¿ÐŸÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÐºÐŸÑÐŸÑÑÐµ Ð²Ñ Ñ
+ÐŸÑÐžÑÐµ Ð²ÐºÐ»ÑÑÐžÑÑ Ð² Ð¿ÐŸÐžÑÐº. </Text>
+</Content>
+</Subsection>
+<Subsection id="language_preferences">
+<Title>
+<Text id="146">ÐÐ°ÑÑÑÐŸÐ¹ÐºÐž ÑÐ·ÑÐºÐ°</Text>
+</Title>
+<Content>
+<Text id="147">ÐÐ°Ð¶ÐŽÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐžÐŒÐµÐµÑ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐ¹ ÑÐ·ÑÐº ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°, ÐœÐŸ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ Ð»ÑÐ±ÐŸÐ¹ ÐŽÑÑÐ³ÐŸÐ¹. Ð¢Ð°ÐºÐ¶Ðµ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ ÐŽÑÑÐ³ÑÑ ÐºÐŸÐŽÐžÑÐŸÐ²ÐºÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÑ Ð² ÐŽÐ°ÐœÐœÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐµ, Ð¿ÐŸÐŽÑ
+ÐŸÐŽÑÑÑÑ ÐŽÐ»Ñ Ð²Ð°ÑÐµÐ³ÐŸ Ð±ÑÐ°ÑÐ·ÐµÑÐ° - Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÑÑÐ°Ð²ÐžÑÑÑ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÐ°Ñ, ÐœÐŸ ÐœÐ° ÐœÐµÐºÐŸÑÑÑÑ
+ Ð±ÑÐ°ÑÐ·ÐµÑÐ°Ñ
+ Ð»ÑÑÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ ÐºÐŸÐŽÐžÑÐŸÐ²ÐºÑ Ð²ÑÑÑÐœÑÑ. ÐÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ ÑÐ°ÐºÐ¶Ðµ Ð¿ÐµÑÐµÐ¹ÑÐž ÐŸÑ Ð³ÑÐ°ÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÑÐµÐ¶ÐžÐŒÐ° Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° Ðº ÑÐµÐºÑÑÐŸÐ²ÐŸÐŒÑ, Ðž ÐœÐ°ÐŸÐ±ÐŸÑÐŸÑ.</Text>
+</Content>
+</Subsection>
+<Subsection id="presentation_preferences">
+<Title>
+<Text id="148">ÐÐ°ÑÑÑÐŸÐ¹ÐºÐž ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°</Text>
+</Title>
+<Content>
+<Text id="149">Ð Ð·Ð°Ð²ÐžÑÐžÐŒÐŸÑÑÐž ÐŸÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð² ÐœÐµÐ¹ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÐœÐ°ÑÑÑÐŸÐµÐº ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°. ÐÐŸÐ»Ð»ÐµÐºÑÐžÑ Web-ÑÑÑÐ°ÐœÐžÑ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð¿Ð°ÐœÐµÐ»Ñ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ Ð²Ð²ÐµÑÑ
+Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. Ð¢Ð°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ, Ð¿ÐŸÑÐ»Ðµ Ð¿ÐŸÐžÑÐºÐ° Ð²Ñ ÑÑÐ°Ð·Ñ Ð¿ÐŸÐ¿Ð°ÐŽÐµÑÐµ ÐœÐ° Web-ÑÑÑÐ°ÐœÐžÑÑ Ð±ÐµÐ· Ð²ÑÑÐºÐŸÐ³ÐŸ Greenstone Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ°. Ð§ÑÐŸÐ±Ñ ÑÐŽÐµÐ»Ð°ÑÑ ÐœÐŸÐ²ÑÐ¹ Ð·Ð°Ð¿ÑÐŸÑ, ÐŽÐŸÑÑÐ°ÑÐŸÑÐœÐŸ ÐœÐ°Ð¶Ð°ÑÑ ÐºÐœÐŸÐ¿ÐºÑ "ÐœÐ°Ð·Ð°ÐŽ" Ð² Ð²Ð°ÑÐµÐŒ Ð±ÑÐ°ÑÐ·ÐµÑÐµ. Ð¢Ð°ÐºÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐ°ÐºÐ¶Ðµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ Ð·Ð°Ð¿ÑÐµÑÐ°ÑÑ ÑÐžÑÑÐµÐŒÐœÑÐµ ÐŸÑÐžÐ±ÐºÐž, ÐºÐŸÐ³ÐŽÐ° Ð²Ñ ÐœÐ°Ð¶ÐžÐŒÐ°ÐµÑÐµ ÐœÐ° ÑÑÑÐ»ÐºÐž, Ð²ÑÐ²ÐŸÐŽÑÑÐžÐµ Ð²Ð°Ñ Ð·Ð° ÑÐ°ÐŒÐºÐž ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Ð² WWW</Text>
+</Content>
+</Subsection>
+<Subsection id="search_preferences">
+<Title>
+<Text id="150">ÐÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÑ Ð¿ÐŸÐžÑÐºÐ°</Text>
+</Title>
+<Content>
+<Text id="151">ÐÐ° ÑÐžÑÑÐœÐºÐµ 3 Search preferences (Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÑ Ð¿ÐŸÐžÑÐºÐ°), Ð¿ÐµÑÐ²Ð°Ñ Ð¿Ð°ÑÐ° ÐºÐœÐŸÐ¿ÐŸÐº Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð²Ð°ÐŒ Ð¿ÐŸÐ»ÑÑÐ°ÑÑ Ð±ÐŸÐ»ÑÑÐŸÐµ Ð¿ÐŸÐ»Ðµ Ð·Ð°Ð¿ÑÐŸÑÐ°, ÑÐ°Ðº ÑÑÐŸÐ±Ñ Ð²Ñ ÐŒÐŸÐ³Ð»Ðž Ð»ÐµÐ³ÐºÐŸ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑ Ð¿ÐŸÐžÑÐº Ð¿ÐŸ Ð¿Ð°ÑÐ°Ð³ÑÐ°ÑÐ°ÐŒ. Ð Greenstone ÑÐŽÐžÐ²ÐžÑÐµÐ»ÑÐœÐŸ Ð±ÑÑÑÑÐŸ ÐŒÐŸÐ¶ÐœÐŸ ÐœÐ°Ð¹ÑÐž Ð±ÐŸÐ»ÑÑÐžÐµ Ð¿ÐŸÑÑÐžÐž ÑÐµÐºÑÑÐ°. Ð¡Ð»ÐµÐŽÑÑÑÐžÐµ ÐŽÐ²Ðµ Ð¿Ð°ÑÑ ÐºÐœÐŸÐ¿ÐŸÐº ÑÐ¿ÑÐ°Ð²Ð»ÑÑÑ Ð²ÐžÐŽÐŸÐŒ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÑ ÑÐµÐºÑÑÐ° Ð¿ÑÐž Ð¿ÐŸÐžÑÐºÐµ. ÐÐµÑÐ²ÑÐ¹ ÐœÐ°Ð±ÐŸÑ (Ð¿ÐŸÐŒÐµÑÐµÐœÐœÑÐ¹ ÐºÐ°Ðº "<i>ÑÐ°Ð·Ð»ÐžÑÐœÑÐ¹ ÑÐµÐ³ÐžÑÑÑ</i>") ÑÐ¿ÑÐ°Ð²Ð»ÑÐµÑ ÑÐµÐŒ, ÐŽÐŸÐ»Ð¶ÐµÐœ Ð»Ðž ÑÑÐžÑÑÐ²Ð°ÑÑÑÑ Ð²ÐµÑÑ
+ÐœÐžÐ¹ Ðž ÐœÐžÐ¶ÐœÐžÐ¹ ÑÐµÐ³ÐžÑÑÑ. ÐÑÐŸÑÐŸÐ¹ ("<i>ÐŸÐºÐŸÐœÑÐ°ÐœÐžÑ ÑÐ»ÐŸÐ²</i>") ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ, ÐžÐ³ÐœÐŸÑÐžÑÐŸÐ²Ð°ÑÑ Ð»Ðž ÐŸÐºÐŸÐœÑÐ°ÐœÐžÑ ÑÐ»ÐŸÐ²Ð° ÐžÐ»Ðž ÐœÐµÑ. </Text>
+<Text id="152">ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ ÑÐ»ÐµÐŽÑÑÑÐµÐ¹ Ð¿Ð°ÑÑ ÐºÐœÐŸÐ¿ÐŸÐº ÐŒÐŸÐ¶ÐœÐŸ Ð¿ÐµÑÐµÐºÐ»ÑÑÐžÑÑÑÑ Ð² "ÑÐ°ÑÑÐžÑÐµÐœÐœÑÐ¹" ÑÐ¿ÑÐ°Ð²ÐŸÑÐœÑÐ¹ ÑÐµÐ¶ÐžÐŒ, ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÐ¹ Ð²ÑÑÐµ, ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð²Ð°ÐŒ ÑÐŸÑÑÐ°Ð²Ð»ÑÑÑ Ð±ÐŸÐ»ÐµÐµ ÑÐŸÑÐœÑÐµ Ð·Ð°Ð¿ÑÐŸÑÑ, ÐºÐŸÐŒÐ±ÐžÐœÐžÑÑÑ ÑÐµÑÐŒÐžÐœÑ,ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ <i>AND</i> (&amp;), <i>OR</i>, Ðž <i>NOT</i>. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐµÑÐµÐºÐ»ÑÑÐ°ÑÑ ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž Ñ
+ÑÐŸÐœÐŸÐ»ÐŸÐ³ÐžÐž Ð¿ÐŸÐžÑÐºÐ°, ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÐµ Ð²ÑÑÐµ, ÐœÐ°Ð¶ÐžÐŒÐ°Ñ Ð²ÐºÐ». Ðž Ð²ÑÐºÐ». ÐÐ°ÐºÐŸÐœÐµÑ, ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐ¿ÑÐ°Ð²Ð»ÑÑÑ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸÐŒ ÐœÐ°Ð¶Ð°ÑÐžÐ¹ ÐŽÐ»Ñ Ð²ÐŸÐ·Ð²ÑÐ°ÑÐµÐœÐžÑ, Ðž ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸÐŒ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐœÑÑ
+ ÐœÐ° ÐºÐ°Ð¶ÐŽÐŸÐŒ ÑÐºÑÐ°ÐœÐµ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÐŸÐ² Ð²ÐŸ Ð²ÑÐµÐŒÑ Ð¿ÐŸÑÐ»ÐµÐŽÐœÐµÐ³ÐŸ Ð²Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÑ (ÑÐŒ. ÑÐžÑÑÐœÐŸÐº 3).</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="making_greenstone_collections">
+<Title>
+<Text id="153">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Greenstone</Text>
+</Title>
+<Content>
+<Text id="154">Ð¡Ð°ÐŒÑÐ¹ Ð¿ÑÐŸÑÑÐŸÐ¹ ÑÐ¿ÐŸÑÐŸÐ± ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐœÐŸÐ²ÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸÐ±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Greenstone (GLI). ÐÐœ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐÐ°ÐŒ ÑÐŸÐ±ÐžÑÐ°ÑÑ Ð¿ÐŸÐŽÐ±ÐŸÑÐºÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐžÐ»Ðž Ð·Ð°ÐŽÐ°Ð²Ð°ÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ðž Ð²ÑÑÑÐ°ÐžÐ²Ð°ÑÑ ÐžÑ
+ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Greenstone. ÐÐœ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÑ Ð¿ÑÑÑ ÐŸÑÐœÐŸÐ²ÐœÑÑ
+ ÐŽÐµÐ¹ÑÑÐ²ÐžÐ¹, ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ ÐŒÐµÐœÑÑÑ Ð¿ÐŸÑÑÐŽÐŸÐº, ÐœÐŸ ÐœÐŸÐŒÐžÐœÐ°Ð»ÑÐœÐŸ Ð¿ÑÐµÐŽÐ¿ÑÐžÐœÐžÐŒÐ°ÑÑÑÑ Ð² ÐžÐ·Ð»Ð°Ð³Ð°ÐµÐŒÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="155">ÐÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐžÐ· ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ³ÐŸ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ð° ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐ°, Ð²ÐºÐ»ÑÑÐ°Ñ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð² ÐœÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÑÐ±ÑÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŸÑÑÐ°ÑÑÑÑ Â«Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐœÑÐŒÐžÂ» Ðº ÑÑÐžÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ. ÐÐŸÐºÑÐŒÐµÐœÑÑ ÐŒÐŸÐ³ÑÑ ÑÐ°ÐºÐ¶Ðµ Ð±ÑÑÑ ÑÐŸÐ±ÑÐ°ÐœÑ ÐžÐ· ÐÐœÑÐµÑÐœÐµÑÐ° Ñ Ð¿ÐŸÐŒÐŸÑÑÑ Ð²ÑÑÑÐŸÐµÐœÐœÑÑ
+ Ð·ÐµÑÐºÐ°Ð»ÑÐœÑÑ
+ ÑÑÐµÐŽÑÑÐ².</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="156">ÐÐ°ÑÑÑÐµÐœÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÐµÐŒ ÐœÐŸÐ²ÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðº ÐžÐœÐŽÐžÐ²ÐžÐŽÑÐ°Ð»ÑÐœÑÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ ÐžÐ»Ðž Ð³ÑÑÐ¿Ð¿Ð°ÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². </Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="157">ÐÑÐŸÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑ, ÐºÐ°Ðº ÐŸÐœÐ° ÐŽÐŸÐ»Ð¶ÐœÐ° Ð²ÑÐ³Ð»ÑÐŽÐµÑÑ, Ðž ÑÑÐµÐŽÑÑÐ²Ð° ÐŽÐŸÑÑÑÐ¿Ð°, ÐºÐŸÑÐŸÑÑÐµ ÐŸÐœÐ° ÐŽÐŸÐ»Ð¶ÐœÑ ÐŸÐ±ÑÐ»ÑÐ¶ÐžÐ²Ð°ÑÑ. </Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="158">ÐÐŸÑÑÑÐŸÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ Greenstone.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="159">ÐÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÑÐ¹ Ð¿ÑÐŸÑÐŒÐŸÑÑ Ð²ÐœÐŸÐ²Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐºÐŸÑÐŸÑÐ°Ñ Ð±ÑÐŽÐµÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° ÐœÐ° ÐÐ°ÑÐµÐ¹ ÑÑÐ°ÑÑÐŸÐ²ÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐµ Greenstone Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐŸÐŽÐœÐŸÐ¹ ÐžÐ· ÑÑÐŽÐŸÐ²ÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹.</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="160">ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐÐ°ÐŒ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑÑ Ðº ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ ÑÐŸ, ÑÑÐŸ ÐŸÐ±ÑÑÐœÐŸ ÐœÐ°Ð·ÑÐ²Ð°ÑÑ Â«Ð²ÐœÐµÑÐœÐžÐŒÐžÂ» ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž, ÑÐŸ ÐµÑÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, ÐºÐŸÑÐŸÑÑÐµ Ð¿ÑÐžÐœÐ°ÐŽÐ»ÐµÐ¶Ð°Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð² ÑÐµÐ»ÐŸÐŒ. ÐÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÑÐ°ÑÑÐŸ ÐŽÐŸÐ»Ð¶ÐœÑ Ð¿ÐŸÐŽÑÐ°Ð·ÐŽÐµÐ»ÑÑÑÑÑ Ð¿ÐŸ ÑÐ°Ð·ÐŽÐµÐ»Ð°ÐŒ Ðž Ð¿ÐŸÐŽÑÐ°Ð·ÐŽÐµÐ»Ð°ÐŒ, Ðž Â«Ð²ÐœÑÑÑÐµÐœÐœÐžÐµÂ» ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐ²ÑÐ·Ð°ÐœÑ Ñ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÐµÑ ÑÐ°ÑÑÑÑ. Ð Greenstone  ÐžÑÑ
+ÐŸÐŽÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐœÐ°ÐŽÐµÐ»ÐµÐœÑ ÑÑÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐµÐ¹, Ðž ÐŒÑ ÐŸÐ±ÑÑÑÐœÑÐµÐŒ ÑÑÐŸ Ð² ÑÐ°Ð·ÐŽÐµÐ»Ðµ 3.3.</Text>
+<Text id="161">ÐÐ°ÐºÐŸÐœÐµÑ, Ð°Ð»ÑÑÐµÑÐœÐ°ÑÐžÐ²ÐœÑÐ¹ ÑÐ¿ÐŸÑÐŸÐ± Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑÑÑ ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑÐŸÐŒ, ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐŒÐŸÐ³Ð°ÐµÑ ÐÐ°ÐŒ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ ÐœÐŸÐ²ÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐžÐ·ÐŒÐµÐœÑÑ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ, ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑ Ðº ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐŒ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐœ Ð±ÑÐ» ÑÐŸÐ·ÐŽÐ°Ðœ ÐŽÐŸ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°, Ðž ÐŽÐ»Ñ Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²Ð° Ð¿ÑÐ°ÐºÑÐžÑÐµÑÐºÐžÑ
+ ÑÐµÐ»ÐµÐ¹ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ ÐŽÐŸÐ»Ð¶ÐµÐœ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ Ð²ÐŒÐµÑÑÐŸ ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑÐ°. Ð­ÑÐŸ ÐŸÐ¿ÐžÑÐ°ÐœÐŸ Ð² ÑÐ°Ð·ÐŽÐµÐ»Ðµ 3.4.</Text>
+<Text id="162">Ð§ÑÐŸÐ±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Greenstone ÐœÐ° Ð¿ÐŸÐ»ÐœÑÑ ÐŒÐŸÑÐœÐŸÑÑÑ ÐŽÐ»Ñ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ Ð¿ÑÐŸÐŽÐ²ÐžÐœÑÑÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÐÑ Ð±ÑÐŽÐµÑÐµ ÐŽÐŸÐ»Ð¶ÐœÑ ÑÐ°ÐºÐ¶Ðµ Ð¿ÑÐŸÑÐµÑÑÑ Ð³Ð»Ð°Ð²Ñ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ°.</Text>
+<Section id="the_librarian_interface">
+<Title>
+<Text id="163">ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ</Text>
+</Title>
+<Content>
+<Text id="164">Ð§ÑÐŸÐ±Ñ ÑÐ°Ð·ÑÑÑÐœÐžÑÑ, ÐºÐ°Ðº ÐŽÐµÐ¹ÑÑÐ²ÑÐµÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Greenstone, ÐŒÑ Ð¿ÐŸÐºÐ°Ð¶ÐµÐŒ ÑÑÐŸ ÐœÐ°  Ð¿ÑÐŸÑÑÐŸÐŒ Ð¿ÑÐžÐŒÐµÑÐµ. Ð ÐžÑÑÐœÐºÐž 4-15 â ÑÑÐŸ ÑÐœÐžÐŒÐºÐž ÑÐºÑÐ°ÐœÐ° ÐœÐ° ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÑÑÐ°ÐŽÐžÑÑ
+ Ð² ÑÐµÑÐµÐœÐžÐµ Ð²Ð·Ð°ÐžÐŒÐŸÐŽÐµÐ¹ÑÑÐ²ÐžÑ. Ð ÑÑÐŸÐŒ Ð¿ÑÐžÐŒÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÐžÐ· ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÐŸÐŽÐŒÐœÐŸÐ¶ÐµÑÑÐ²Ð° ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž ÑÐ°Ð·Ð²ÐžÑÐžÑ (DLS), ÐºÐŸÑÐŸÑÐ°Ñ ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÑÐµÑÑÑ Ð²ÐŒÐµÑÑÐµ Ñ Greenstone. ÐÐ»Ñ ÐŸÐ¿ÐžÑÐ°ÑÐµÐ»ÑÐœÑÑ
+ ÑÐµÐ»ÐµÐ¹ ÑÐºÑÐºÑÑÑ Ð¿ÑÐžÐŒÐµÑ Ð²ÐžÐŽ Ð¿ÑÐŸÑ
+ÐŸÐ¶ÐŽÐµÐœÐžÑ ÐŸÑÐŽÐµÐ»ÑÐœÑÑ
+ ÑÑÐ°Ð¿ÐŸÐ², ÑÐ¿ÐŸÐŒÐžÐœÐ°Ð²ÑÐžÑ
+ÑÑ Ð²ÑÑÐµ. ÐÐŸÐ»ÐµÐµ ÑÐµÐ°Ð»ÑÐœÑÐ¹ ÐŸÐ±ÑÐ°Ð·ÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹ ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸÐ±Ñ Ð¿ÐµÑÐµÐºÐ»ÑÑÐ°ÑÑ Ð¿ÑÐŸÑ
+ÐŸÐ¶ÐŽÐµÐœÐžÐµ ÐœÐ°Ð·Ð°ÐŽ Ðž Ð²Ð¿ÐµÑÐµÐŽ ÑÐµÑÐµÐ· ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÑÑÐ°ÐŽÐžÐž Ð¿ÐŸ ÐŒÐµÑÐµ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ Ð·Ð°ÐŽÐ°ÑÐž.</Text>
+<Text id="165">ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð·Ð°Ð¿ÑÑÐµÐœ Ð² ÐŸÐŽÐœÐŸÐŒ ÐžÐ· 4 ÑÐµÐ¶ÐžÐŒÐ°Ñ
+: ÐÐŸÐŒÐŸÑÐœÐžÐº ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÑÑ, ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÑÑ, Ð¡ÐžÑÑÐµÐŒÐœÑÐ¹ ÑÐ¿ÐµÑÐžÐ°Ð»ÐžÑÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž, Ðž Ð­ÐºÑÐ¿ÐµÑÑ. Ð ÐµÐ¶ÐžÐŒÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ ÑÑÐŸÐ²ÐµÐœÑ ÐŽÐµÑÐ°Ð»ÐžÐ·Ð°ÑÐžÐž ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°, Ðž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ ÑÐµÑÐµÐ· ÑÐ°Ð·ÐŽÐµÐ» 'ÐÐ°ÑÑÑÐŸÐ¹ÐºÐž' ÐŒÐµÐœÑ 'Ð€Ð°Ð¹Ð»'. Ð Ð°ÑÑÐºÐ°Ð· ÐŸÐ± ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ Ð¿ÐŸÐŽÑÐ°Ð·ÑÐŒÐµÐ²Ð°ÐµÑ, ÑÑÐŸ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ Ð² ÑÐµÐ¶ÐžÐŒ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ, 'ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÑÑ'.</Text>
+<Subsection id="getting_started">
+<Title>
+<Text id="166">ÐÐ°ÑÐ°Ð»ÑÐœÑÐ¹ ÑÑÐ°Ð¿</Text>
+</Title>
+<Content>
+<Text id="167">ÐÐ°Ð¿ÑÑÑÐžÑÐµ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÐŸÐŽ Windows, Ð²ÑÐ±ÐžÑÐ°Ñ ÐŠÐžÑÑÐŸÐ²Ð°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Greenstone  ÐžÐ· ÑÐ°Ð·ÐŽÐµÐ»Ð° ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐŒÐµÐœÑ Ð¡ÑÐ°ÑÑ Ðž Ð² ÐœÐµÐŒ - ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ.      ÐÑÐ»Ðž ÐÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ Unix, Ð²ÐŒÐµÑÑÐŸ ÑÑÐŸÐ³ÐŸ ÐœÐ°Ð±ÐµÑÐžÑÐµ</Text>
+<CodeLine>cd ~/gsdl</CodeLine>
+<CodeLine>cd gli</CodeLine>
+<CodeLine>./gli.sh</CodeLine>
+<Text id="168">Ð³ÐŽÐµ ~/gsdl  - ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐ°Ñ ÑÐžÑÑÐµÐŒÑ  Greenstone. Ð§ÑÐŸÐ±Ñ ÐœÐ°ÑÐ°ÑÑ ÑÐ°Ð±ÐŸÑÑ, ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ ÐŸÑÐºÑÑÑÑ ÑÑÑÐµÑÑÐ²ÑÑÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐžÐ»Ðž ÐœÐ°ÑÐ°ÑÑ ÐœÐŸÐ²ÑÑ. Ð ÐžÑÑÐœÐŸÐº 4 Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð¿ÑÐŸÑÐµÑÑ ÐœÐ°ÑÐ°Ð»Ð° ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐœ Ð²ÑÐ±ÑÐ°Ð» ÐÐŸÐ²Ð°Ñ ÐžÐ· ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ³ÐŸ ÐŒÐµÐœÑ Ðž ÐœÐ°ÑÐ°Ð» Ð·Ð°Ð¿ÐŸÐ»ÐœÑÑÑ ÐŸÐ±ÑÐžÐµ ÑÐ²ÐµÐŽÐµÐœÐžÑ ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž â ÐµÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ, Ð°ÐŽÑÐµÑ ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ Ð¿ÐŸÑÑÑ Ð»ÐžÑÐ°, ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸÐ³ÐŸ Ð·Ð° ÐœÐµÑ, Ðž ÐºÑÐ°ÑÐºÐŸÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ â Ð² Ð²ÑÐ¿Ð»ÑÐ²Ð°ÑÑÐµÐŒ ÐŸÐºÐœÐµ. ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž â ÑÑÐŸ ÐºÐŸÑÐŸÑÐºÐ°Ñ ÑÑÐ°Ð·Ð°, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ Ð²ÑÑÐŽÑ Ð² ÐŠÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐµ, ÑÑÐŸÐ±Ñ ÐžÐŽÐµÐœÑÐžÑÐžÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð¡ÑÑÐµÑÑÐ²ÑÑÑÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐžÐŒÐµÑÑ ÐžÐŒÐµÐœÐ° ÑÐžÐ¿Ð° ÐÑÐŸÐŽÐŸÐ²ÐŸÐ»ÑÑÑÐ²ÐžÐµ Ðž ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Ð¿ÐžÑÐ°ÐœÐžÑ, ÐÑÐµÐŒÐžÑÐœÐ°Ñ ÑÐºÐŸÐ»ÐŸÐ³ÐžÑÐµÑÐºÐ°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Ðž Ñ.ÐŽ. ÐÐŸÐ³ÐŽÐ° ÐÑ Ð²Ð¿ÐµÑÐ°ÑÐ°Ð»Ðž ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ, ÑÐžÑÑÐµÐŒÐ° ÐœÐ°Ð·ÐœÐ°ÑÐ°ÐµÑ ÑÐœÐžÐºÐ°Ð»ÑÐœÑÐ¹ ÐŒÐœÐµÐŒÐŸÐœÐžÑÐµÑÐºÐžÐ¹ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑ Â«ÐžÐŒÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐžÂ» ÐŽÐ»Ñ Ð²ÐœÑÑÑÐµÐœÐœÐµÐ³ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ (ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐµÐ³ÐŸ, ÐµÑÐ»Ðž Ð·Ð°Ñ
+ÐŸÑÐžÑÐµ). ÐÐŽÑÐµÑ ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ Ð¿ÐŸÑÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ Ð¿ÐµÑÐ²ÑÐ¹ Ð¿ÑÐœÐºÑ ÐºÐŸÐœÑÐ°ÐºÑÐ°  Ð² ÑÐ»ÑÑÐ°Ðµ Ð»ÑÐ±ÑÑ
+ Ð¿ÑÐŸÐ±Ð»ÐµÐŒ, Ñ ÐºÐŸÑÐŸÑÑÐŒÐž ÑÑÐ°Ð»ÐºÐžÐ²Ð°ÑÑÑÑ Ð¿ÑÐž ÑÐŸÐ·ÐŽÐ°ÐœÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="169">ÐÑÐ°ÑÐºÐŸÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ â ÑÑÐŸ Ð¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÐµ, ÐŸÐ¿ÐžÑÑÐ²Ð°ÑÑÐµÐµ Ð¿ÑÐžÐœÑÐžÐ¿Ñ, ÐºÐŸÑÐŸÑÑÐŒÐž ÑÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÑÑÑÑÑ, ÑÑÐŸ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÐœÐŸ Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ Ð¿ÐŸÐŽ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐŸÐŒ ÐÐ± ÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž  ÐœÐ° ÐœÐ°ÑÐ°Ð»ÑÐœÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Figure id="starting_a_new_collection">
+<Title>
+<Text id="170">ÐÐ°ÑÐ°Ð»ÐŸ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<File width="407" height="317" url="images/User_Fig_4.png"/>
+</Figure>
+<Figure id="exploring_the_local_file_space">
+<Title>
+<Text id="171">ÐÑÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐžÐµ Ð»ÐŸÐºÐ°Ð»ÑÐœÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ³ÐŸ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ð°</Text>
+</Title>
+<File width="407" height="318" url="images/User_Fig_5.png"/>
+</Figure>
+<Text id="172">ÐÐ° ÑÑÐŸÐŒ ÑÑÐ°Ð¿Ðµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÑÐµÑÐ°ÐµÑ, ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ Ð»Ðž ÐœÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÐ°ÐºÐŸÐ¹ Ð¶Ðµ ÑÑÑÑÐºÑÑÑÑ, ÑÑÐŸ Ðž ÑÑÑÐµÑÑÐ²ÑÑÑÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐžÐ»Ðž ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ Ð¿ÐŸÐ»ÐœÐŸÑÑÑÑ ÐœÐŸÐ²ÑÐ¹ Ð²ÐžÐŽ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ° ÑÐžÑ.4 ÐŸÐœ Ð²ÑÐ±ÑÐ°Ð» Ð±Ð°Ð·ÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐœÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÐŸÐŽÐŒÐœÐŸÐ¶ÐµÑÑÐ²Ð° ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž ÑÐ°Ð·Ð²ÐžÑÐžÑ (ÐÐÐ ). Ð­ÑÐŸ Ð¿ÐŸÐŽÑÐ°Ð·ÑÐŒÐµÐ²Ð°ÐµÑ, ÑÑÐŸ ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐÐÐ , ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð² ÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð±ÑÐŽÐµÑ Ð¿ÑÐžÐŒÐµÐœÐµÐœ Ðž ÐŽÐ»Ñ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. (Ð€Ð°ÐºÑÐžÑÐµÑÐºÐž, ÑÑÐŸÑ ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ð»ÑÑ ÐŽÐ»Ñ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Greenstone, ÐºÐŸÑÐŸÑÑÐµ ÐžÐŒÐµÑÑ ÐŸÐ±ÑÑÑ ÑÑÑÑÐºÑÑÑÑ Ðž ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑ, ÐœÐŸ ÑÐ°Ð·Ð»ÐžÑÐœÐŸÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ, Ð²ÐºÐ»ÑÑÐ°Ñ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÑ ÑÐ°Ð·Ð²ÐžÑÐžÑ Ðž ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, Ð¿ÐŸÑÑÐ°Ð²Ð»ÑÐµÐŒÑÐµ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐŸÐ±ÑÐ°Ð·ÑÐŸÐ² Ñ Greenstone).</Text>
+<Text id="173">ÐÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ DLS ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÑÐ»ÐµÐŽÑÑÑÐžÐµ Ð¿ÑÐœÐºÑÑ:</Text>
+<BulletList>
+<Bullet>
+<Text id="174">ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ</Text>
+</Bullet>
+<Bullet>
+<Text id="175">ÐÑÐµÐŽÐŒÐµÑ</Text>
+</Bullet>
+<Bullet>
+<Text id="176">Ð¯Ð·ÑÐº</Text>
+</Bullet>
+<Bullet>
+<Text id="177">ÐÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑ</Text>
+</Bullet>
+<Bullet>
+<Text id="178">ÐÐ»ÑÑÐµÐ²ÑÐµ ÑÐ»ÐŸÐ²Ð°</Text>
+</Bullet>
+</BulletList>
+<Text id="179">(ÐÑÐŸÐŒÐµ ÑÐŸÐ³ÐŸ, ÐžÐŒÐµÐµÑÑÑ Ð¿ÑÐœÐºÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÑÐ¹ AZList, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ, ÐºÐ°ÐºÐŸÐ¹ ÑÑÐ°ÑÑÐŸÐº Ð°Ð»ÑÐ°Ð²ÐžÑÐœÐŸÐ³ÐŸ ÑÐ¿ÐžÑÐºÐ° ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑÐŒÐž ÑÐžÐ¿Ð° âÐ-Bâ ÐžÐ»Ðž âC-D-Eâ. Ð­ÑÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÐžÐŒÐµÑÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ ÑÐŸÑÐœÐŸÐ³ÐŸ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ ÑÐ°Ð·ÐŽÐµÐ»Ð°ÐŒÐž ÑÐ¿ÐžÑÐºÐ°. ÐÐ»Ñ Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²Ð° ÐŽÑÑÐ³ÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÑÑÐ° ÐŸÐ¿ÑÐžÑ ÐŸÑÑÑÑÑÑÐ²ÑÐµÑ, Ðž Greenstone  ÐœÐ°Ð·ÐœÐ°ÑÐ°ÐµÑ ÑÐµÐ³ÐŒÐµÐœÑÑ ÑÐ°ÐŒÐŸÑÑÐŸÑÑÐµÐ»ÑÐœÐŸ).</Text>
+<Text id="180">ÐÑÐ»Ðž Ð¶Ðµ ÐœÐ° ÑÑÐŸÐŒ ÑÑÐ°Ð¿Ðµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð²ÑÐ±ÑÐ°Ð» ÐŽÑÑÐ³ÐŸÐ¹ Ð²Ð°ÑÐžÐ°ÐœÑ - Â«ÐÐŸÐ²Ð°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÂ», ÑÐŸ ÐµÐ³ÐŸ Ð¿ÐŸÐ¿ÑÐŸÑÐžÐ»Ðž Ð±Ñ Ð²ÑÐ±ÑÐ°ÑÑ, ÐºÐ°ÐºÐžÐµ ÐœÐ°Ð±ÐŸÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐŸÐ»Ð¶ÐœÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ Ð² ÑÑÐŸÐ¹ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð¢ÑÐž ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÑ
+ ÐœÐ°Ð±ÐŸÑÐ° Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ: Dublin Core, ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ DLS, ÑÐ¿ÐŸÐŒÐžÐœÐ°Ð²ÑÐµÐ¹ÑÑ Ð²ÑÑÐµ, Ðž ÐœÐ°Ð±ÐŸÑ, ÐºÐŸÑÐŸÑÑÐ¹ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÑÐ»ÐµÐŒÐµÐœÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÐžÐ·Ð²Ð»ÐµÑÐµÐœÐœÑÐµ Greenstone Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐŒÐŸÐ¶ÐµÑ ÑÐ°ÐºÐ¶Ðµ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ ÐœÐŸÐ²ÑÐµ ÐœÐ°Ð±ÐŸÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÑÑ Ð¿Ð°ÐœÐµÐ»Ñ, Ð°ÐºÑÐžÐ²ÐžÐ·ÐžÑÐŸÐ²Ð°ÐœÐœÑÑ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐŒÐµÐœÑ Â«ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµÂ».</Text>
+<Text id="181">ÐÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÐœÐ°Ð±ÐŸÑÐŸÐ² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐ²ÑÐ·Ð°ÐœÑ Ñ ÐŸÐŽÐœÐŸÐ¹ Ðž ÑÐŸÐ¹ Ð¶Ðµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹; ÑÐžÑÑÐµÐŒÐ° ÐŽÐµÑÐ¶ÐžÑ ÐžÑ
+ ÐŸÑÐŽÐµÐ»ÑÐœÐŸ, ÑÐ°Ðº ÑÑÐŸ, ÐœÐ°Ð¿ÑÐžÐŒÐµÑ,  ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÐŒÐŸÐ³Ð»Ðž Ð±Ñ ÐžÐŒÐµÑÑ ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐºÐ°Ðº Ð² Dublin Core, ÑÐ°Ðº Ðž Ð² DLS. Ð Ð°Ð·Ð»ÐžÑÐœÑÐµ ÐœÐ°Ð±ÐŸÑÑ ÑÐµÑÐºÐŸ ÐŸÑÐ»ÐžÑÐ°ÑÑÑÑ Ð¿ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÑ. ÐÐµÑÐ²ÐœÐŸ ÐœÐ°Ð±ÐŸÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÑ Ð² XML. </Text>
+</Content>
+</Subsection>
+<Subsection id="assembling_the_source_material">
+<Title>
+<Text id="182">Ð¡Ð±ÐŸÑ ÐžÑÑ
+ÐŸÐŽÐœÐŸÐ³ÐŸ ÐŒÐ°ÑÐµÑÐžÐ°Ð»Ð°</Text>
+</Title>
+<Content>
+<Text id="183">ÐÐŸÑÐ»Ðµ ÑÐµÐ»ÑÐºÐ° ÐºÐœÐŸÐ¿ÐºÐŸÐ¹ ÐÐ Ð² ÐŒÐµÐœÑ Â«ÐÐŸÐ²Ð°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÂ» ÐŸÑÑÐ°ÑÑÐžÐµÑÑ ÑÐ°ÑÑÐž ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°, ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐ»Ðž ÐŽÐŸ ÑÐŸÐ³ÐŸ ÑÐµÑÐŸÐ³ÐŸ ÑÐ²ÐµÑÐ°, ÑÑÐ°ÐœÐŸÐ²ÑÑÑÑ Ð°ÐºÑÐžÐ²ÐœÑÐŒÐž. ÐÐ°ÐœÐµÐ»Ñ Ð¡Ð±ÐŸÑÑÐžÐºÐ°, ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÐ°Ñ ÐºÐ»Ð°Ð²ÐžÑÐµÐ¹ Ñ ÑÐµÐŒ Ð¶Ðµ ÐžÐŒÐµÐœÐµÐŒ ÑÐ²ÐµÑÑ
+Ñ ÐœÐ° ÑÐžÑ.4, Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐ° Ð² Ð¿ÐµÑÐ²ÐŸÐœÐ°ÑÐ°Ð»ÑÐœÐŸÐŒ Ð²ÐžÐŽÐµ. Ð­ÑÐŸ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð»ÐŸÐºÐ°Ð»ÑÐœÐŸÐµ ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐµ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²ÐŸ Ðž ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐŸÐ±ÐžÑÐ°Ñ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÐŽÐ»Ñ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ°ÐœÐµÐ»Ñ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐ° ÐœÐ° ÐŽÐ²Ðµ ÑÐ°ÑÑÐž, Ð»ÐµÐ²Ð°Ñ ÐžÐ· ÐºÐŸÑÐŸÑÑÑ
+ Ð¿ÑÐµÐŽÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐ° ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ ÑÑÑÑÐºÑÑÑÑ, Ð° Ð¿ÑÐ°Ð²Ð°Ñ â ÐŽÐ»Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="184">ÐÐµÐ¹ÑÑÐ²ÐžÑ, ÐŽÐŸÑÑÑÐ¿ÐœÑÐµ ÐœÐ° ÑÑÐŸÐŒ ÑÑÐ°Ð¿Ðµ, Ð²ÐºÐ»ÑÑÐ°ÑÑ:</Text>
+<BulletList>
+<Bullet>
+<Text id="185">ÐÐ°Ð²ÐžÐ³Ð°ÑÐžÑ Ð¿ÐŸ ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐ¹ ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐŸÐ¹ ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ¹ ÑÑÑÑÐºÑÑÑÐµ Ðž Ð¿ÐŸ ÑÐŸÐ·ÐŽÐ°ÐœÐœÐŸÐ¹ ÑÑÑÑÐºÑÑÑÐµ, ÐŽÐµÐ¹ÑÑÐ²ÑÑ ÐŸÐ±ÑÑÐœÑÐŒ ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐŒ.</Text>
+</Bullet>
+<Bullet>
+<Text id="186">ÐÐµÑÐµÐŒÐµÑÐµÐœÐžÐµ Ðž Ð²Ð²ÐŸÐŽ ÑÐ°Ð¹Ð»ÐŸÐ² Ð² ÐœÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ.</Text>
+</Bullet>
+<Bullet>
+<Text id="187">ÐÐœÐŸÐ¶ÐµÑÑÐ²ÐµÐœÐœÑÐ¹ Ð²ÑÐ±ÐŸÑ ÑÐ°Ð¹Ð»ÐŸÐ².</Text>
+</Bullet>
+<Bullet>
+<Text id="188">ÐÐµÑÐµÐŒÐµÑÐµÐœÐžÐµ Ðž Ð²Ð²ÐŸÐŽ Ð¿ÐŸÐ»ÐœÑÑ
+ Ð¿ÐŸÐŽÐžÐµÑÐ°ÑÑ
+ÐžÐ¹.</Text>
+</Bullet>
+<Bullet>
+<Text id="189">Ð£ÐŽÐ°Ð»ÐµÐœÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐžÐ· Ð²ÐŸÐ·ÐœÐžÐºÐ°ÑÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+</Bullet>
+<Bullet>
+<Text id="190">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐœÐŸÐ²ÑÑ
+ Ð¿ÐŸÐŽÐžÐµÑÐ°ÑÑ
+ÐžÐ¹ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+</Bullet>
+<Bullet>
+<Text id="191">Ð€ÐžÐ»ÑÑÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐ°Ð¹Ð»ÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÑÐ²Ð»ÑÑÑÑÑ Ð²ÐžÐŽÐžÐŒÑÐŒÐž, Ðž Ð² Ð»ÐŸÐºÐ°Ð»ÑÐœÐŸÐ¹ ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ¹ ÑÐžÑÑÐµÐŒÐµ, Ðž Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐŸÑÐœÐŸÐ²Ð°ÐœÐœÐŸÐ¹ ÐœÐ° Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ Ð³ÑÑÐ¿Ð¿Ð°Ñ
+ ÐžÐ»Ðž ÐœÐ° ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ, Ð¿ÐŸÐŽÑ
+ÐŸÐŽÑÑÐžÑ
+ ÑÐµÑÐŒÐžÐœÐŸÐ².</Text>
+</Bullet>
+<Bullet>
+<Text id="192">ÐÐ°Ð¿ÑÑÐº ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐŽÐ»Ñ Ð¿ÐŸÐºÐ°Ð·Ð° ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð° ÐŽÐ²ÐŸÐ¹ÐœÑÐŒ ÑÐµÐ»ÑÐºÐŸÐŒ ÐœÐ° ÐœÑÐŒ.</Text>
+</Bullet>
+</BulletList>
+<Text id="193">ÐÑÐµÐŽÐ¿ÑÐžÐœÑÑÑ ÐŒÐµÑÑ Ð¿ÑÐµÐŽÐŸÑÑÐŸÑÐŸÐ¶ÐœÐŸÑÑÐž, ÐºÐŸÐ³ÐŽÐ° ÐžÐŒÐµÑÑ ÐŽÐµÐ»ÐŸ ÑÐŸ ÑÑÐŸÐ»ÐºÐœÐŸÐ²ÐµÐœÐžÑÐŒÐž ÐžÐŒÑÐœ, ÐµÑÐ»Ðž ÑÐ°Ð¹Ð»Ñ Ñ ÐŸÐŽÐžÐœÐ°ÐºÐŸÐ²ÑÐŒ ÐžÐŒÐµÐœÐµÐŒ Ð² ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÑÐ°ÑÑÑÑ
+ ÑÑÑÑÐºÑÑÑÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐ° ÑÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÑ Ð² ÐŸÐŽÐœÑ Ð¿Ð°Ð¿ÐºÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="194">ÐÐ° ÑÐžÑÑÐœÐºÐµ 5 Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÐžÐœÑÐµÑÐ°ÐºÑÐžÐ²ÐœÑÐ¹ Ð¿ÐŸÐºÐ°Ð· ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ³ÐŸ ÐŽÐµÑÐµÐ²Ð° ÐŽÐ»Ñ ÐžÑÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐžÑ Ð»ÐŸÐºÐ°Ð»ÑÐœÐŸÐ¹ ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ¹ ÑÐžÑÑÐµÐŒÑ. ÐÐ° ÑÑÐŸÐ¹ ÑÑÐ°ÐŽÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÐ¿ÑÐ°Ð²Ð° Ð¿ÑÑÑÐ°, Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐœÐ°Ð¿ÐŸÐ»ÐœÑÐµÑ ÐµÐµ, Ð¿ÐµÑÐµÑÑÐ³ÐžÐ²Ð°Ñ Ðž Ð¿ÑÐŸÐ¿ÑÑÐºÐ°Ñ ÐžÐœÑÐµÑÐµÑÑÑÑÐžÐµ ÐµÐ³ÐŸ ÑÐ°Ð¹Ð»Ñ Ñ Ð»ÐµÐ²ÐŸÐ¹ ÐœÐ° Ð¿ÑÐ°Ð²ÑÑ ÑÐ°ÑÑÑ Ð¿Ð°ÐœÐµÐ»Ðž. Ð¢Ð°ÐºÐžÐµ ÑÐ°Ð¹Ð»Ñ ÑÐºÐŸÑÐµÐµ Â«ÑÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÑÂ», ÑÐµÐŒ Â«Ð¿ÐµÑÐµÐŒÐµÑÐµÐœÑÂ», ÑÑÐŸÐ±Ñ ÐœÐµ ÐœÐ°ÑÑÑÐ°ÑÑ Ð¿ÐµÑÐ²ÐŸÐœÐ°ÑÐ°Ð»ÑÐœÑÑ ÑÐ°Ð¹Ð»ÐŸÐ²ÑÑ ÑÐžÑÑÐµÐŒÑ. ÐÐ±ÑÑÐœÑÐµ ÐŒÐµÑÐŸÐŽÑ Ð²ÑÐ±ÐŸÑÐ° ÐŽÐ»Ñ ÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐµÐœÐœÐŸÐ³ÐŸ Ð¿ÐµÑÐµÐŒÐµÑÐµÐœÐžÑ Ðž Ð²Ð²ÐŸÐŽÐ°, ÑÑÑÑÐºÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÑÑÐµÐŒ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ Ð¿ÐŸÐŽÐŽÐžÑÐµÐºÑÐŸÑÐžÐ¹ (Â«Ð¿Ð°Ð¿ÐŸÐºÂ»), Ð° ÑÐ°ÐºÐ¶Ðµ ÑÐŽÐ°Ð»ÐµÐœÐžÑ ÑÐ°Ð¹Ð»ÐŸÐ² ÐžÐ· ÐœÐžÑ
+, Ð¿ÐµÑÐµÐŒÐµÑÐ°Ñ ÐžÑ
+ Ð² ÐºÐŸÑÐ·ÐžÐœÑ, Ð²ÑÐµ ÐŸÐœÐž ÑÐ²Ð»ÑÑÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž. </Text>
+<Text id="195">Ð¡ÑÑÐµÑÑÐ²ÑÑÑÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÑ Ð¿ÐŸÐŽÐŽÐžÑÐµÐºÑÐŸÑÐžÐµÐ¹ ÑÐ»ÐµÐ²Ð°, ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÐŸÐ¹ Â«ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž GreenstoneÂ», ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŸÑÐºÑÑÑÑ Ðž ÐžÑÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÑ Ð¿ÐŸÐŽÐŸÐ±ÐœÐŸ Ð»ÑÐ±ÐŸÐ¹ ÐŽÑÑÐ³ÐŸÐ¹ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž. ÐÐŽÐœÐ°ÐºÐŸ, ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð² ÐœÐµÐ¹ ÐŸÑÐ»ÐžÑÐ°ÑÑÑÑ ÐŸÑ ÐŸÐ±ÑÑÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² ÑÐµÐŒ, ÑÑÐŸ ÐŸÐœÐž ÑÐ¶Ðµ ÐžÐŒÐµÑÑ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐœÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÑ
+ÑÐ°ÐœÑÑÑÑÑ Ð¿ÑÐž Ð¿ÐµÑÐµÐŒÐµÑÐµÐœÐžÐž Ð² ÐœÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÐŸÐœÑÐ»ÐžÐºÑÑ ÐŒÐŸÐ³ÑÑ Ð²ÐŸÐ·ÐœÐžÐºÐœÑÑÑ ÐžÐ·-Ð·Ð° ÑÐŸÐ³ÐŸ, ÑÑÐŸ ÐžÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ, Ð±ÑÐ»Ðž Ð·Ð°ÐŽÐ°ÐœÑ Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÐœÐ°Ð±ÐŸÑÐŸÐ² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, Ð¿ÑÐžÐŒÐµÐœÐµÐœÐœÑÑ
+ ÐŽÐ»Ñ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐŽÐŸÐ»Ð¶ÐµÐœ ÑÐ°Ð·ÑÐµÑÐžÑÑ ÑÑÐž ÐºÐŸÐœÑÐ»ÐžÐºÑÑ. ÐÐ° ÑÐžÑÑÐœÐºÐµ 6 Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð²ÑÐ±ÑÐ°Ð» ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÐžÐ· ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð¿ÐµÑÐµÑÑÐœÑÐ» ÐžÑ
+ Ð² ÐœÐŸÐ²ÑÑ. ÐÑÐ¿Ð»ÑÐ²Ð°ÑÑÐµÐµ ÐŸÐºÐœÐŸ ÐŸÐ±ÑÑÑÐœÑÐµÑ, ÑÑÐŸ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑ ÐœÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°Ðœ, Ðž Ð¿ÑÐµÐŽÐ»Ð°Ð³Ð°ÐµÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐžÐ»Ðž Ð²ÑÐ±ÑÐ°ÑÑ ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðž ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°ÑÑ ÐÐŸÐ±Ð°Ð²ÐžÑÑ, ÑÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÑÑÐŸÑ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðº ÐŽÐ°ÐœÐœÐŸÐŒÑ ÐœÐ°Ð±ÐŸÑÑ<FootnoteRef id="1"/>, ÐžÐ»Ðž Ð²ÑÐ±ÑÐ°ÑÑ ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, Ð° Ð·Ð°ÑÐµÐŒ ÑÐ»ÐµÐŒÐµÐœÑ Ðž ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°ÑÑ Ð¡Ð»ÐžÑÑ, ÑÑÐŸÐ±Ñ ÑÑÑÐµÐºÑÐžÐ²ÐœÐŸ Ð¿ÐµÑÐµÐžÐŒÐµÐœÐŸÐ²Ð°ÑÑ ÑÑÐ°ÑÑÐ¹ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐœÐ° ÐœÐŸÐ²ÑÐ¹, ÐŸÐ±ÑÐµÐŽÐžÐœÑÑ ÐžÑ
+. ÐÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð² Ð¿ÐŸÑÐ»ÐµÐŽÑÑÑÐžÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°Ñ
+ ÐžÐ· ÑÐŸÐ¹ Ð¶Ðµ ÑÐ°ÐŒÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð±ÑÐŽÑÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÐŸÐ±ÑÐ°Ð±ÐŸÑÐ°ÐœÑ ÑÐµÐŒ Ð¶Ðµ ÑÐ°ÐŒÑÐŒ ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐŒ.</Text>
+<Text id="196">ÐÐŸÐ³ÐŽÐ° ÐŸÑÐŸÐ±ÑÐ°ÐœÑ Ð±ÐŸÐ»ÑÑÐžÐµ ÐœÐ°Ð±ÐŸÑÑ Ð¿ÐµÑÐµÑÑÐ³ÐžÐ²Ð°ÐœÐžÐµÐŒ Ðž Ð²Ð²ÐµÐŽÐµÐœÐžÐµÐŒ ÐžÑ
+ Ð² ÐœÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐŽÐµÐ¹ÑÑÐ²ÐžÑ Ð¿ÐŸ ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐŒÐŸÐ³ÑÑ Ð·Ð°ÐœÑÑÑ ÐœÐµÐºÐŸÑÐŸÑÐŸÐµ Ð²ÑÐµÐŒÑ, ÐŸÑÐŸÐ±ÐµÐœÐœÐŸ ÐµÑÐ»Ðž Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. Ð§ÑÐŸÐ±Ñ ÐŸÑÑÐ°Ð·ÐžÑÑ Ð¿ÑÐŸÐŽÐ²ÐžÐ¶ÐµÐœÐžÐµ Ð¿ÑÐŸÑÐµÑÑÐ°, ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ, ÐºÐ°ÐºÐŸÐ¹ ÑÐ°Ð¹Ð» Ð² ÐŽÐ°ÐœÐœÐŸÐµ Ð²ÑÐµÐŒÑ ÐºÐŸÐ¿ÐžÑÑÐµÑÑÑ Ðž ÐºÐ°ÐºÐŸÐ¹ Ð¿ÑÐŸÑÐµÐœÑ ÑÐ°Ð¹Ð»ÐŸÐ² ÑÐ¶Ðµ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐ°Ðœ.</Text>
+<Text id="197">ÐÑÐµÐŽÑÑÐŒÐŸÑÑÐµÐœÑ ÑÐ¿ÐµÑÐžÐ°Ð»ÑÐœÑÐµ ÑÑÐµÐŽÑÑÐ²Ð° ÐŸÐ±ÑÐ»ÑÐ¶ÐžÐ²Ð°ÐœÐžÑ, ÐºÐŸÐ³ÐŽÐ° ÐžÐŒÐµÑÑ ÐŽÐµÐ»ÐŸ Ñ Ð±ÐŸÐ»ÑÑÐžÐŒÐž ÐœÐ°Ð±ÐŸÑÐ°ÐŒÐž ÑÐ°Ð¹Ð»ÐŸÐ². ÐÐ°Ð¿ÑÐžÐŒÐµÑ, Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐŒÐŸÐ¶ÐµÑ Ð²ÑÐ±ÑÐ°ÑÑ ÑÐžÐ»ÑÑÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ³ÐŸ ÐŽÐµÑÐµÐ²Ð°, ÑÑÐŸÐ±Ñ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÑÐŸÐ»ÑÐºÐŸ ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÑÐ°Ð¹Ð»Ñ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Ð¿ÐŸÐœÐžÐ¶Ð°ÑÑÐžÐµÑÑ ÐŒÐµÐœÑ ÑÐžÐ¿ÐŸÐ² ÑÐ°Ð¹Ð»ÐŸÐ², Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐœÑÑ
+ Ð¿ÐŸÐŽ ÐŽÐµÑÐµÐ²ÑÑÐŒÐž. ÐÐ° ÑÐžÑÑÐœÐºÐµ 7 Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÑ ÑÐŸÐ»ÑÐºÐŸ ÑÐ°Ð¹Ð»Ñ ÐÐ¢Ð Ðž ÐÐ¢ÐL (Ðž ÑÐŸÐ»ÑÐºÐŸ ÑÑÐž ÑÐ°Ð¹Ð»Ñ Ð±ÑÐŽÑÑ ÑÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÑ Ð¿ÑÑÐµÐŒ Ð¿ÐµÑÐµÐŒÐµÑÐµÐœÐžÑ Ðž ÐŸÑÑÐ°ÐœÐŸÐ²ÐºÐž).</Text>
+</Content>
+</Subsection>
+<Subsection id="enriching_the_documents">
+<Title>
+<Text id="198">ÐÐ°Ð¿ÐŸÐ»ÐœÐµÐœÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²</Text>
+</Title>
+<Content>
+<Text id="199">Ð¡Ð»ÐµÐŽÑÑÑÐ°Ñ ÑÑÐ°ÐŽÐžÑ Ð² ÑÐŸÐ·ÐŽÐ°ÐœÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŽÐŸÐ»Ð¶ÐœÐ° ÐœÐ°Ð¿ÐŸÐ»ÐœÐžÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ  ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÐµÐŒ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. ÐÐ»Ð°Ð²ÐžÑÐ° Â«ÐÐ±ÐŸÐ³Ð°ÑÐžÑÑÂ» Ð²ÑÐ²ÐŸÐŽÐžÑ ÐœÐŸÐ²ÑÑ Ð¿Ð°ÐœÐµÐ»Ñ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž (ÑÐžÑÑÐœÐŸÐº 8), ÐºÐŸÑÐŸÑÐ°Ñ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐŽÐµÑÐµÐ²ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÐ»ÐµÐ²Ð°, Ð° ÑÐ¿ÑÐ°Ð²Ð° â Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ðº ÐžÐœÐŽÐžÐ²ÐžÐŽÑÐ°Ð»ÑÐœÑÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ ÐžÐ»Ðž Ðº Ð³ÑÑÐ¿Ð¿Ðµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ².</Text>
+<Text id="200">ÐÐŸÐºÑÐŒÐµÐœÑÑ, ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐ»Ðž ÑÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÑ Ð² Ñ
+ÐŸÐŽÐµ Ð¿ÐµÑÐ²ÐŸÐ³ÐŸ ÑÑÐ°Ð¿Ð°, ÐžÐŽÑÑ Ñ Ð»ÑÐ±ÑÐŒÐž Ð¿ÑÐžÐŒÐµÐœÐžÐŒÑÐŒÐž Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐœÑÐŒÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž. ÐÑÐ»Ðž ÐŽÐŸÐºÑÐŒÐµÐœÑ ÑÐ²Ð»ÑÐµÑÑÑ ÑÐ°ÑÑÑÑ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+, ÑÐŸ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð¿ÐµÑÐµÐœÐŸÑÑÑÑÑ Ð² ÐœÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÐŸÐœÐµÑÐœÐŸ, ÑÑÐ° ÐœÐŸÐ²Ð°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐŒÐŸÐ¶ÐµÑ ÐžÐŒÐµÑÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÐœÐ°Ð±ÐŸÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐžÐ»Ðž Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ ÑÐŸÐ»ÑÐºÐŸ ÑÐ°ÑÑÑ ÐœÐ°Ð±ÐŸÑÐ° ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, Ðž ÑÐŸÐ»ÑÐºÐŸ ÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, ÐºÐŸÑÐŸÑÑÐµ Ð¿ÑÐžÐœÐ°ÐŽÐ»ÐµÐ¶Ð°Ñ ÐœÐ°Ð±ÐŸÑÑ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð¿ÐµÑÐµÐœÐŸÑÑÑÑÑ. Ð Ð°Ð·ÑÐµÑÐµÐœÐžÐµ ÑÐ°ÐºÐžÑ
+ ÐºÐŸÐœÑÐ»ÐžÐºÑÐŸÐ² ÐŒÐŸÐ¶ÐµÑ Ð¿ÐŸÑÑÐµÐ±ÐŸÐ²Ð°ÑÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÑÐºÐŸÐ³ÐŸ Ð²ÐŒÐµÑÐ°ÑÐµÐ»ÑÑÑÐ²Ð° ÑÐµÑÐµÐ· ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÑÐ¹ ÐŽÐžÐ°Ð»ÐŸÐ³ (ÑÐžÑÑÐœÐŸÐº 6). ÐÑÐ±ÑÐµ ÑÐŽÐµÐ»Ð°ÐœÐœÑÐµ Ð²ÑÐ±ÐŸÑÑ Ð·Ð°Ð¿ÐŸÐŒÐžÐœÐ°ÑÑÑÑ ÐŽÐ»Ñ Ð¿ÐŸÑÐ»ÐµÐŽÑÑÑÐžÑ
+ ÐºÐŸÐ¿ÐžÐ¹ ÑÐ°Ð¹Ð»ÐŸÐ². </Text>
+<Text id="201">ÐÐ°ÐœÐµÐ»Ñ Â«ÐÐ±ÐŸÐ³Ð°ÑÐžÑÑÂ» Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð·Ð°ÐŽÐ°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðº ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÐœÐŸÐ²ÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŒÐŸÐ¶ÐœÐŸ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ Ðº ÐœÐ°Ð±ÐŸÑÑ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÑ
+ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ ÐŽÐ»Ñ ÑÐ»ÐµÐŒÐµÐœÑÐ°. ÐÑÐ»Ðž Ð·ÐœÐ°ÑÐµÐœÐžÑ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÐžÐŒÐµÑÑ ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÑÑ ÑÑÑÑÐºÑÑÑÑ, ÐžÐµÑÐ°ÑÑ
+ÐžÑ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÑÐ°ÑÑÐžÑÐµÐœÐ° ÑÐµÐŒ Ð¶Ðµ ÑÐ°ÐŒÑÐŒ ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐŒ.</Text>
+<Figure id="importing_existing_metadata">
+<Title>
+<Text id="202">ÐÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Text>
+</Title>
+<File width="407" height="317" url="images/User_Fig_6.png"/>
+</Figure>
+<Figure id="filtering_the_file_trees">
+<Title>
+<Text id="203">Ð€ÐžÐ»ÑÑÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐ°Ð¹Ð»ÐŸÐ²ÑÑ
+ ÐŽÐµÑÐµÐ²ÑÐµÐ²</Text>
+</Title>
+<File width="407" height="318" url="images/User_Fig_7.png"/>
+</Figure>
+<Figure id="assigning_metadata_using_enrich_view">
+<Title>
+<Text id="204">ÐÐ°ÐŽÐ°ÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ</Text>
+</Title>
+<File width="407" height="318" url="images/User_Fig_8.png"/>
+</Figure>
+<Figure id="viewing_all_metadata_for_selected_files">
+<Title>
+<Text id="205">ÐÑÐŸÑÐŒÐŸÑÑ Ð²ÑÐµÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+  ÐŽÐ»Ñ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ²</Text>
+</Title>
+<File width="407" height="317" url="images/User_Fig_9.png"/>
+</Figure>
+<Text id="206">ÐÐœÐ°ÑÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐŸÐ³ÑÑ ÑÐ°ÐºÐ¶Ðµ Ð±ÑÑÑ Ð·Ð°ÐŽÐ°ÐœÑ ÐŽÐ»Ñ Ð¿Ð°Ð¿ÐŸÐº ÑÐµÐŒ Ð¶Ðµ ÑÐ°ÐŒÑÐŒ ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐŒ. ÐÐŸÐºÑÐŒÐµÐœÑÑ Ð² ÑÑÐžÑ
+ Ð¿Ð°Ð¿ÐºÐ°Ñ
+, ÐŽÐ»Ñ ÐºÐŸÑÐŸÑÑÑ
+ ÑÑÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐœÐµ ÑÐºÐ°Ð·Ð°ÐœÑ, ÐœÐ°ÑÐ»ÐµÐŽÑÑÑ ÑÑÐž Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. ÐÐŽÐœÐ°ÐºÐŸ ÐŸÐœÐž ÐŒÐŸÐ³ÑÑ Ð²Ð¿ÐŸÑÐ»ÐµÐŽÑÑÐ²ÐžÐž Ð±ÑÑÑ Ð¿ÐµÑÐµÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÑ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÐµÐœÐžÐµÐŒ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ.</Text>
+<Text id="207">ÐÐµÐ¹ÑÑÐ²ÐžÐµ ÐœÐ° ÑÑÐŸÐ¹ ÑÑÐ°ÐŽÐžÐž Ð²ÐºÐ»ÑÑÐ°ÑÑ:</Text>
+<BulletList>
+<Bullet>
+<Text id="208">ÐÐ°Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐœÐŸÐ²ÑÑ
+ Ðž ÑÑÑÐµÑÑÐ²ÑÑÑÐžÑ
+ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ².</Text>
+</Bullet>
+<Bullet>
+<Text id="209">ÐÐ°Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðº ÐžÐœÐŽÐžÐ²ÐžÐŽÑÐ°Ð»ÑÐœÐŸÐŒÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ.</Text>
+</Bullet>
+<Bullet>
+<Text id="210">ÐÐ°Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðº Ð¿Ð°Ð¿ÐºÐµ (ÐŸÐœÐž ÐœÐ°ÑÐ»ÐµÐŽÑÑÑÑÑ Ð²ÑÐµÐŒÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒÐž Ð² Ð¿Ð°Ð¿ÐºÐµ, Ð²ÐºÐ»ÑÑÐ°Ñ ÐœÐ°Ñ
+ÐŸÐŽÑÑÐžÐµÑÑ Ð²ÐŸ Ð²Ð»ÐŸÐ¶ÐµÐœÐœÑÑ
+ Ð¿Ð°Ð¿ÐºÐ°Ñ
+).</Text>
+</Bullet>
+<Bullet>
+<Text id="211">ÐÐ°Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐžÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÑÑ ÑÑÑÑÐºÑÑÑÐ° ÐŒÐŸÐ¶ÐµÑ ÐŽÐžÐœÐ°ÐŒÐžÑÐµÑÐºÐž ÐŸÐ±ÐœÐŸÐ²Ð»ÑÑÑÑÑ, ÐµÑÐ»Ðž ÑÑÐŸ ÑÑÐµÐ±ÑÐµÑÑÑ.</Text>
+</Bullet>
+<Bullet>
+<Text id="212">Ð ÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐžÐ»Ðž ÐŸÐ±ÐœÐŸÐ²Ð»ÐµÐœÐžÐµ ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+.</Text>
+</Bullet>
+<Bullet>
+<Text id="213">Ð Ð°ÑÑÐŒÐŸÑÑÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÑ
+ Ðº Ð²ÑÐ±ÑÐ°ÐœÐœÑÐŒ ÑÐ°Ð¹Ð»Ð°ÐŒ Ðž ÐŽÐžÑÐµÐºÑÐŸÑÐžÑÐŒ.</Text>
+</Bullet>
+</BulletList>
+<Text id="214">ÐÐ»Ñ ÐœÐ°ÑÐµÐ³ÐŸ Ð¿ÑÐžÐŒÐµÑÐ° ÐœÐ° ÑÐžÑÑÐœÐºÐµ 8 Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð²ÑÐ±ÑÐ°Ð» Ð¿Ð°Ð¿ÐºÑ ÐµÑ121Ðµ Ðž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÐ» Â«EC CourierÂ» Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐž. ÐÐœÐŸÐ¿ÐºÐž ÐŽÐ»Ñ ÐŸÐ±ÐœÐŸÐ²Ð»ÐµÐœÐžÑ Ðž ÑÐŽÐ°Ð»ÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÑÑÐ°ÐœÐŸÐ²ÑÑÑÑ Ð°ÐºÑÐžÐ²ÐœÑÐŒÐž Ð² Ð·Ð°Ð²ÐžÑÐžÐŒÐŸÑÑÐž ÐŸÑ ÑÐŸÐ³ÐŸ, ÐºÐ°ÐºÐŸÐ¹ Ð²ÑÐ±ÐŸÑ Ð±ÑÐ» ÑÐŽÐµÐ»Ð°Ðœ.</Text>
+<Text id="215">Ð ÑÐµÑÐµÐœÐžÐµ ÑÑÐ°Ð¿Ð° ÐœÐ°Ð¿ÐŸÐ»ÐœÐµÐœÐžÑ ÐžÐ»Ðž Ð² ÑÐ»ÑÑÐ°Ðµ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÐž Ð² Ð»ÑÐ±ÐŸÐµ ÐŽÑÑÐ³ÐŸÐµ Ð²ÑÐµÐŒÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐŒÐŸÐ¶ÐµÑ Ð·Ð°Ñ
+ÐŸÑÐµÑÑ ÑÐ°ÑÑÐŒÐŸÑÑÐµÑÑ Ð²ÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐ»Ðž Ð·Ð°ÐŽÐ°ÐœÑ ÐŽÐ»Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð­ÑÐŸ ÐŽÐµÐ»Ð°ÐµÑÑÑ Ð¿ÑÑÐµÐŒ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÐœÐ°Ð±ÐŸÑÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ðž Ð²ÑÐ±ÐŸÑÐ° ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Â«ÐÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµÂ» Ð² ÐŒÐµÐœÑ, ÐºÐŸÑÐŸÑÐŸÐµ Ð¿ÑÐžÐœÐŸÑÐžÑ Ð²ÑÐ¿Ð»ÑÐ²Ð°ÑÑÐµÐµ ÐŸÐºÐœÐŸ, ÐºÐ°Ðº ÐœÐ° ÑÐžÑÑÐœÐºÐµ 9, ÐºÐŸÑÐŸÑÐŸÐµ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð² ÑÐŸÑÐŒÐµ ÐºÑÑÐ¿ÐœÐŸÑÐŸÑÐŒÐ°ÑÐœÐŸÐ¹ ÑÐ°Ð±Ð»ÐžÑÑ. ÐÐ»Ñ Ð±ÐŸÐ»ÑÑÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ð¿ÐŸÐ»ÐµÐ·ÐœÐŸ ÐžÐŒÐµÑÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÐ²ÑÐ·Ð°ÐœÐœÑÑ
+ ÑÐŸÐ»ÑÐºÐŸ Ñ ÐŸÑÐŽÐµÐ»ÑÐœÑÐŒ ÑÐžÐ¿ÐŸÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, Ðž ÐµÑÐ»Ðž Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÐ» ÑÐžÐ»ÑÑÑ ÑÐ°Ð¹Ð»Ð°, ÐºÐ°Ðº Ð±ÑÐ»ÐŸ ÑÐ¿ÐŸÐŒÑÐœÑÑÐŸ Ð²ÑÑÐµ, ÑÐŸ  ÑÐŸÐ»ÑÐºÐŸ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÑÑÐ°ÑÑÐ²ÑÑÑ Ð² Ð¿ÐŸÐºÐ°Ð·Ðµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+.</Text>
+<Text id="216">ÐÐ°ÐœÐµÐ»Ñ ÐœÐ° ÑÐžÑÑÐœÐºÐµ 10 Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐœÐ°Ð±ÐŸÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. ÐÐŽÐµÑÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°ÐµÑ ÑÐ»ÐµÐŒÐµÐœÑ ÐÑÐµÐŽÐŒÐµÑ ÐžÐ· DLS. ÐÐœÐ°ÑÐµÐœÐžÑ ÑÑÐŸÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÑÐŸÑÐŒÐžÑÑÑÑ ÐžÐµÑÐ°ÑÑ
+ÐžÑ, Ðž Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐžÑÑÐ»ÐµÐŽÑÐµÑ, Ð° Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ Ðž ÐžÐ·ÐŒÐµÐœÑÐµÑ, ÑÐ¿ÐžÑÐŸÐº Ð·ÐœÐ°ÑÐµÐœÐžÐ¹, Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ°. Ð¢Ð° Ð¶Ðµ ÑÐ°ÐŒÐ°Ñ Ð¿Ð°ÐœÐµÐ»Ñ ÑÐ°ÐºÐ¶Ðµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐÐ°ÐŒ ÐžÐ·ÐŒÐµÐœÑÑÑ Â«Ð¿ÑÐŸÑÐžÐ»ÑÂ» ÐŽÐ»Ñ ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² ÐŸÐŽÐœÐŸÐ³ÐŸ ÐœÐ°Ð±ÐŸÑÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐœÐ° ÐŽÑÑÐ³ÐŸÐ¹. Ð­ÑÐŸÑ Ð¿ÑÐŸÑÐžÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐµÑÑÑ Ð¿ÑÐž ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐžÐ· ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÐºÐŸÑÐŸÑÑÐµ ÐžÐŒÐµÑÑ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ. </Text>
+<Figure id="editing_the_metadata_set">
+<Title>
+<Text id="217">Ð ÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐœÐ°Ð±ÐŸÑÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Text>
+</Title>
+<File width="407" height="317" url="images/User_Fig_10.png"/>
+</Figure>
+<Figure id="designing_the_collection">
+<Title>
+<Text id="218">ÐÑÐŸÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<File width="407" height="318" url="images/User_Fig_11.png"/>
+</Figure>
+<Figure id="specifying_which_plug-ins_to_use">
+<Title>
+<Text id="219">ÐÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐµ, ÐºÐ°ÐºÐžÐµ Ð¿Ð»Ð°Ð³ÐžÐœÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ</Text>
+</Title>
+<File width="407" height="318" url="images/User_Fig_12.png"/>
+</Figure>
+<Figure id="configuring_arguments_to_a_plug-in">
+<Title>
+<Text id="220">ÐÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ² ÐŽÐ»Ñ Ð¿Ð»Ð°Ð³ÐžÐœÐŸÐ²</Text>
+</Title>
+<File width="407" height="317" url="images/User_Fig_13.png"/>
+</Figure>
+</Content>
+</Subsection>
+<Subsection id="designing_the_collection_1">
+<Title>
+<Text id="221">ÐÑÐŸÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="222">ÐÐ°ÐœÐµÐ»Ñ Â«ÐÑÐŸÐµÐºÑÂ» (ÑÐžÑÑÐœÐŸÐº 11-13) Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ ÑÑÑÑÐºÑÑÑÑ, ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÑ Ðž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÐµÐŒÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ°Ðº ÐŸÑÐŒÐµÑÐ°Ð»ÐŸÑÑ Ð²ÑÑÐµ, ÑÐµÐ·ÑÐ»ÑÑÐ°Ñ ÑÑÐŸÐ³ÐŸ Ð¿ÑÐŸÑÐµÑÑÐ° Ð·Ð°Ð¿ÐžÑÐ°Ðœ Ð² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐºÐŸÑÐŸÑÑÐ¹  Ð² Greenstone ÑÐ²Ð»ÑÐµÑÑÑ ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐŒ ÐŸÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ ÑÑÐµÐŽÑÑÐ² ÐŸÐ±ÑÐ»ÑÐ¶ÐžÐ²Ð°ÐœÐžÑ, ÑÑÐµÐ±ÑÐµÐŒÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹. Ð­ÑÐŸÑ ÑÑÐ°Ð¿ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÑÐµÑÐžÑ ÐŸÑÐŽÐµÐ»ÑÐœÑÑ
+ ÑÐºÑÐ°ÐœÐŸÐ² Ð²Ð·Ð°ÐžÐŒÐŸÐŽÐµÐ¹ÑÑÐ²ÐžÑ, ÐºÐ°Ð¶ÐŽÑÐ¹ ÐžÐ· ÐºÐŸÑÐŸÑÑÑ
+ ÐžÐŒÐµÐµÑ ÐŽÐµÐ»ÐŸ Ñ ÐŸÐŽÐœÐžÐŒ Ð°ÑÐ¿ÐµÐºÑÐŸÐŒ Ð¿ÑÐŸÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð ÐŽÐµÐ¹ÑÑÐ²ÐžÑÐµÐ»ÑÐœÐŸÑÑÐž, ÐŸÐœ ÑÐ»ÑÐ¶ÐžÑ Ð³ÑÐ°ÑÐžÑÐµÑÐºÐžÐŒ ÑÐºÐ²ÐžÐ²Ð°Ð»ÐµÐœÑÐŸÐŒ ÐŸÐ±ÑÑÐœÐŸÐ³ÐŸ Ð¿ÑÐŸÑÐµÑÑÐ° ÑÑÑÐœÐŸÐ³ÐŸ ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð°.</Text>
+<Text id="223">ÐÐµÐ¹ÑÑÐ²ÐžÑ Ð²ÐºÐ»ÑÑÐ°ÑÑ:</Text>
+<BulletList>
+<Bullet>
+<Text id="224">ÐÑÐŸÑÐŒÐŸÑÑ Ðž ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐžÐ¿Ð° ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ, ÐÐ²ÑÐŸÑ Ðž ÐÐ±ÑÐµÐŽÐŸÑÑÑÐ¿ÐœÐŸÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+</Bullet>
+<Bullet>
+<Text id="225">ÐÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐµ ÑÐŸÐ³ÐŸ, ÐºÐ°ÐºÐžÐµ ÐžÐœÐŽÐµÐºÑÑ Ð¿ÐŸÐ»ÐœÐŸÐ³ÐŸ ÑÐµÐºÑÑÐ°  ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÑÐŸÐ·ÐŽÐ°ÐœÑ.</Text>
+</Bullet>
+<Bullet>
+<Text id="226">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ðž ÐžÐœÐŽÐµÐºÑÐŸÐ² ÐŽÐ»Ñ ÐœÐžÑ
+.</Text>
+</Bullet>
+<Bullet>
+<Text id="227">ÐÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÐµ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÐµÐœÐžÐµ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐºÐž ÐŽÐ»Ñ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ ÑÐ·ÑÐºÐŸÐ² ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°.</Text>
+</Bullet>
+<Bullet>
+<Text id="228">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÑÐ¿ÐžÑÐºÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÑ
+ Ð¿Ð»Ð°Ð³ÐžÐœÐŸÐ² Ðž ÐžÑ
+ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ².</Text>
+</Bullet>
+<Bullet>
+<Text id="229">ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÑÐ¿ÐžÑÐºÐ° ÐŽÐ»Ñ ÐŸÐ±Ð·ÐŸÑÐ° Ðž ÐŒÐŸÐŽÐžÑÐžÐºÐ°ÑÐžÐž.</Text>
+</Bullet>
+<Bullet>
+<Text id="230">ÐÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐžÐœÐŽÐžÐ²ÐžÐŽÑÐ°Ð»ÑÐœÑÑ
+ Ð¿Ð»Ð°Ð³ÐžÐœÐŸÐ².</Text>
+</Bullet>
+<Bullet>
+<Text id="231">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÑÐ¿ÐžÑÐºÐ° Â«ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ²Â», ÐžÑ
+ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ², ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ Ðž ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž.</Text>
+</Bullet>
+<Bullet>
+<Text id="232">ÐÐ°Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÑÑÑÐŸÐº ÑÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐŽÐ»Ñ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ Ð²ÐžÐŽÐŸÐ² ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐžÐ·ÐŒÐµÐœÑÑ ÑÐ°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ ÐµÑ Ð²ÐžÐŽ.</Text>
+</Bullet>
+<Bullet>
+<Text id="233">ÐÑÐŸÑÐŒÐŸÑÑ ÐœÐ°Ð±ÐŸÑÐŸÐ² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðž ÐžÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ², ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÑ
+ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+</Bullet>
+</BulletList>
+<Text id="234">ÐÐ° ÑÐžÑ.11 Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÑÐµÐ»ÐºÐœÑÐ» ÐºÐ»Ð°Ð²ÐžÑÑ Â«ÐÑÐŸÐµÐºÑÂ» Ðž ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°ÐµÑ ÐŸÐ±ÑÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð²Ð²ÐµÐŽÐµÐœÐœÑÑ Ð¿ÑÐž ÑÐŸÐ·ÐŽÐ°ÐœÐžÐž ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð¡Ð»ÐµÐ²Ð° Ð² ÑÐ¿ÐžÑÐŸÐº Ð²ÐœÐµÑÐµÐœÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ Ð°ÑÐ¿ÐµÐºÑÑ, ÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐŒÐŸÐ¶ÐµÑ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÑÑ: ÐÐ±ÑÐµÐµ, ÐÐ»Ð°Ð³ÐžÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, ÐÐžÐŽÑ Ð¿ÐŸÐžÑÐºÐ°, ÐÐœÐŽÐµÐºÑÑ Ð¿ÐŸÐžÑÐºÐ°, ÐÐœÐŽÐµÐºÑÑ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ, ÐÐµÑÐµÑÐµÐºÐ°ÑÑÐžÐ¹ÑÑ Ð¿ÐŸÐžÑÐº, ÐÑÐŸÑÐŒÐŸÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ², Ð¡Ð²ÐŸÐ¹ÑÑÐ²Ð° ÑÐŸÑÐŒÐ°ÑÐ°, ÐÐµÑÐµÐ²ÐŸÐŽ ÑÐµÐºÑÑÐ°, ÐÐ°Ð±ÐŸÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. ÐÐžÐŽ Ðž ÑÑÐœÐºÑÐžÐŸÐœÐ°Ð»ÑÐœÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐžÐ·ÐŒÐµÐœÑÑÑÑÑ Ð² Ð·Ð°Ð²ÐžÑÐžÐŒÐŸÑÑÐž ÐŸÑ ÐœÐžÑ
+. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÐµÐ»ÐºÐ°Ñ ÐºÐœÐŸÐ¿ÐºÑ Â«ÐÐ»Ð°Ð³ÐžÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°Â», ÐŒÐŸÐ¶ÐœÐŸ Ð²ÑÐ·Ð²Ð°ÑÑ ÑÐºÑÐ°Ðœ, Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐœÑÐ¹ ÐœÐ° ÑÐžÑ.12, ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐÐ°ÐŒ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑÑ, ÑÐŽÐ°Ð»ÑÑÑ ÐžÐ»Ðž ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÑÑ Ð¿Ð»Ð°Ð³ÐžÐœÑ Ðž ÐžÐ·ÐŒÐµÐœÑÑÑ Ð¿ÐŸÑÑÐŽÐŸÐº, Ð² ÐºÐŸÑÐŸÑÐŸÐŒ ÐŸÐœÐž Ð¿ÑÐžÐŒÐµÐœÐµÐœÑ Ðº ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ.</Text>
+<Text id="235">ÐÐ»Ð°Ð³ÐžÐœÑ Ðž ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ ÐžÐŒÐµÑÑ ÐŒÐœÐŸÐ³ÐŸ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ² ÐžÐ»Ðž Â«Ð²Ð°ÑÐžÐ°ÐœÑÐŸÐ²Â», ÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐŒÐŸÐ¶ÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ. ÐÐžÐ°Ð»ÐŸÐ³ÐŸÐ²ÐŸÐµ ÐŸÐºÐœÐŸ ÐœÐ° ÑÐžÑ.13 Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð·Ð°ÐŽÐ°ÐœÐœÑÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ ÐŽÐ»Ñ ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÐžÐ· Ð¿Ð»Ð°Ð³ÐžÐœÐŸÐ². Ð¡ÐµÑÑÐµ Ð¿ÐŸÐ»Ñ ÑÑÐ°ÐœÐŸÐ²ÑÑÑÑ Ð°ÐºÑÐžÐ²ÐœÑÐŒÐž, ÐºÐŸÐ³ÐŽÐ° Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑ ÐŸÐ¿ÑÐžÐž, ÑÐµÐ»ÐºÐ°Ñ ÐŸÐºÐŸÐ»ÐŸ ÐŒÐžÐ³Ð°ÑÑÐµÐ³ÐŸ Ð¿ÐŸÐ»Ñ. ÐÐŸÑÐºÐŸÐ»ÑÐºÑ Greenstone ÑÐ²Ð»ÑÐµÑÑÑ ÐœÐµÐ¿ÑÐµÑÑÐ²ÐœÐŸ ÑÐ°Ð·Ð²ÐžÐ²Ð°ÑÑÐµÐ¹ÑÑ  ÐŸÑÐºÑÑÑÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÐŸÐ¹, ÑÐžÑÐ»ÐŸ Ð²Ð°ÑÐžÐ°ÐœÑÐŸÐ² ÐžÐŒÐµÐµÑ ÑÐµÐœÐŽÐµÐœÑÐžÑ Ðº ÑÐ²ÐµÐ»ÐžÑÐµÐœÐžÑ, ÑÐ°Ðº ÐºÐ°Ðº ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐž ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑÑ ÐœÐŸÐ²ÑÐµ ÑÑÐµÐŽÑÑÐ²Ð° ÐŸÐ±ÑÐ»ÑÐ¶ÐžÐ²Ð°ÐœÐžÑ. Ð§ÑÐŸÐ±Ñ Ð¿ÐŸÐŒÐŸÑÑ ÑÐ¿ÑÐ°Ð²ÐžÑÑÑÑ Ñ ÑÑÐžÐŒ, Greenstone ÐžÐŒÐµÐµÑ Ð¿Ð»Ð°Ð³ÐžÐœ Â«ÐÐœÑÐŸÑÐŒÐ°ÑÐžÑÂ» - ÑÐµÑÐ²ÐžÑÐœÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, ÐºÐŸÑÐŸÑÐ°Ñ Ð²ÐœÐŸÑÐžÑ Ð² ÑÐ¿ÐžÑÐŸÐº ÐŽÐŸÑÑÑÐ¿ÐœÑÐµ ÐŸÐ¿ÑÐžÐž ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ Ð¿Ð»Ð°Ð³ÐžÐœÐ°, Ð° ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž Ð²ÑÐ·ÑÐ²Ð°ÐµÑ ÐµÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ, ÐºÐ°ÐºÐžÐµ Ð²Ð°ÑÐžÐ°ÐœÑÑ Ð¿ÐŸÐºÐ°Ð·Ð°ÑÑ. Ð­ÑÐŸ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐŽÐžÐ°Ð»ÐŸÐ³ÐŸÐ²ÐŸÐŒÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÑÐºÐŸÐŒÑ ÐžÐœÑÐµÑÑÐµÐ¹ÑÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÐžÐŽÑÐž Ð² ÐœÐŸÐ³Ñ Ñ ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ°ÐŒÐž Ð² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐŒ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐž.</Text>
+<Figure id="getting_ready_to_create_new_collection">
+<Title>
+<Text id="236">ÐÐŸÐŽÐ³ÐŸÑÐŸÐ²ÐºÐ° Ðº ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<File width="407" height="318" url="images/User_Fig_14.png"/>
+</Figure>
+<Figure id="previewing_the_newly_built_collection">
+<Title>
+<Text id="237">ÐÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÑÐ¹ Ð¿ÑÐŸÑÐŒÐŸÑÑ ÐœÐµÐŽÐ°Ð²ÐœÐŸ ÑÐŸÐ·ÐŽÐ°ÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<File width="407" height="291" url="images/User_Fig_15.png"/>
+</Figure>
+</Content>
+</Subsection>
+<Subsection id="building_the_collection">
+<Title>
+<Text id="238">ÐÐŸÑÑÑÐŸÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="239">ÐÐ°ÐœÐµÐ»Ñ Â«Ð¡ÐŸÐ·ÐŽÐ°ÑÑÂ» (ÑÐžÑ.14) ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐŸÑÐœÐŸÐ²Ð°ÐœÐœÐŸÐ¹ ÐœÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°Ñ
+ Ðž Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. ÐÐ»Ð°Ð²ÐœÑÑ ÐœÐ°Ð³ÑÑÐ·ÐºÑ Ð² ÑÑÐŸÐ¹ ÑÐ°Ð±ÐŸÑÐµ ÐœÐµÑÐµÑ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Greenstone. ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÑÐ¿ÑÐ°Ð²Ð»ÑÐµÑ ÑÑÐžÐŒ Ð²ÐœÐµÑÐœÐžÐŒ Ð¿ÑÐŸÑÐµÑÑÐŸÐŒ ÑÐµÑÐµÐ· Ð¿ÐŸÑÐ»ÐµÐŽÐŸÐ²Ð°ÑÐµÐ»ÑÐœÑÐ¹ ÑÑÐŽ ÑÐºÑÐ°ÐœÐŸÐ², ÐºÐ°Ð¶ÐŽÑÐ¹ ÐžÐ· ÐºÐŸÑÐŸÑÑÑ
+ ÐžÐŒÐµÐµÑ ÐŽÐµÐ»ÐŸ Ñ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐ°ÐŒÐž, ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÑÑÐžÐŒÐž ÐŸÑÐŽÐµÐ»ÑÐœÑÐµ ÑÑÐ°Ð¿Ñ Ð¿ÑÐŸÑÐµÑÑÐ° ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ.</Text>
+<Text id="240">ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐœÐ°Ð±Ð»ÑÐŽÐ°ÐµÑ Ð¿ÑÐŸÑÐµÑÑ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ, Ñ
+ÐŸÑÑ ÐŸÐºÐœÐŸ, ÐºÐŸÑÐŸÑÐŸÐµ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐœÐµ ÑÐŸÐ»ÑÐºÐŸ ÑÐµÐºÑÑÐŸÐ²ÑÑ Ð¿ÑÐŸÐŽÑÐºÑÐžÑ, ÑÐŸÐ·ÐŽÐ°ÐœÐœÑÑ Greenstone Ð¿ÑÑÐµÐŒ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ Ðž ÑÐºÑÐžÐ¿ÑÐŸÐ², ÑÑÑÐŸÑÑÐžÑ
+ ÐžÐœÐŽÐµÐºÑ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ, ÐœÐŸ ÑÐ°ÐºÐ¶Ðµ Ðž Ð»ÐžÐœÐµÐ¹ÐºÐž Ð¿ÑÐŸÐŽÐ²ÐžÐ¶ÐµÐœÐžÑ, ÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÑÑÐµÐ¿ÐµÐœÑ Ð·Ð°Ð²ÐµÑÑÐµÐœÐœÐŸÑÑÐž ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÐºÑÐžÐ¿ÑÐ°.</Text>
+<Text id="241">ÐÐ° ÑÐžÑ.14 Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœ Ð²ÐžÐŽ Â«Ð¡ÐŸÐ·ÐŽÐ°ÑÑÂ». Ð¡Ð²ÐµÑÑ
+Ñ Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐŸÐ¿ÑÐžÐ¹, ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð¿ÑÐžÐŒÐµÐœÐµÐœÑ Ð² Ð¿ÑÐŸÑÐµÑÑÐµ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ. ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð²ÑÐ±ÐžÑÐ°ÐµÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŽÐ»Ñ Ð²ÑÐ±ÑÐ°ÐœÐœÐŸÐ³ÐŸ Ð²Ð°ÑÐžÐ°ÐœÑÐ°. Ð­ÑÐŸÑ ÑÐžÑÑÐœÐŸÐº ÐžÐ»Ð»ÑÑÑÑÐžÑÑÐµÑ Ð²ÑÐ¿Ð»ÑÐ²Ð°ÑÑÐžÐµ Â«ÐžÐœÑÑÑÑÐŒÐµÐœÑÑ Ð¿ÐŸÐŽÑÐºÐ°Ð·ÐºÐžÂ», ÐºÐŸÑÐŸÑÑÐµ ÑÐ²Ð»ÑÑÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž Ð¿ÐŸ Ð²ÑÐµÐŒÑ ÐžÐœÑÐµÑÑÐµÐ¹ÑÑ, ÑÑÐŸÐ±Ñ ÐŸÐ±ÑÑÑÐœÐžÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐ°. Ð ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°ÐµÐŒÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð²ÑÐ±ÐžÑÐ°ÐµÑ ÑÑÐŸÐ²ÐµÐœÑ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸÑÑÐž ÐŽÐ»Ñ Ð¿ÑÐŸÑÐµÑÑÐ° ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž,  Ðž ÐžÐœÑÑÑÑÐŒÐµÐœÑ Ð¿ÐŸÐŽÑÐºÐ°Ð·ÐºÐž ÑÐŸÐŸÐ±ÑÐ°ÐµÑ, ÑÑÐŸ ÐŸÐœ ÑÐ²Ð»ÑÐµÑÑÑ ÑÐžÑÐ»ÐŸÐŒ ÐŒÐµÐ¶ÐŽÑ 0 Ðž 3, ÐºÐŸÑÐŸÑÑÐµ ÐžÐœÑÐŸÑÐŒÐžÑÑÑÑ ÐŸ ÑÐŸÐŒ, ÐºÐ°Ðº ÐŒÐœÐŸÐ³ÐŸ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž ÐŸ Ð¿ÑÐŸÑÐµÑÑÐµ ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°ÐœÐŸ Ð² ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÐŸÐŒ Ð¿ÐŸÑÐŸÐºÐµ: Â«0Â» ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ ÐœÐµÐŒÐœÐŸÐ³ÐŸ, Ð° Â«3Â» - Ð±ÐŸÐ»ÑÑÐŸÐµ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ.</Text>
+<Text id="242">ÐÑÐ»Ðž Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÑÐŽÐŸÐ²Ð»ÐµÑÐ²ÐŸÑÐµÐœ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐ°ÐŒÐž, ÐŸÐœ ÑÐµÐ»ÐºÐ°ÐµÑ ÐœÐ° Â«Ð¡ÐŸÐ·ÐŽÐ°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÂ». Greenstone ÐœÐµÐ¿ÑÐµÑÑÐ²ÐœÐŸ Ð²ÑÐŽÐ°ÐµÑ ÑÐµÐºÑÑ, ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð¿ÑÐŸÐŽÐ²ÐžÐ¶ÐµÐœÐžÐµ, Ðž ÐŸÐœ ÐžÐŽÐµÑ ÐœÐ°ÑÑÐŽÑ Ñ Ð±ÐŸÐ»ÐµÐµ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐ²ÐœÐŸÐ¹ Ð»ÐžÐœÐµÐ¹ÐºÐŸÐ¹ Ð¿ÑÐŸÐŽÐ²ÐžÐ¶ÐµÐœÐžÑ.</Text>
+</Content>
+</Subsection>
+<Subsection id="previewing">
+<Title>
+<Text id="243">ÐÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÑÐ¹ Ð¿ÑÐŸÑÐŒÐŸÑÑ</Text>
+</Title>
+<Content>
+<Text id="244">ÐºÐœÐŸÐ¿ÐºÐ° <i>ÐÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸÐ³ÐŸ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°</i> (ÑÐžÑ.14) ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐºÐŸÑÐŸÑÐ°Ñ Ð±ÑÐ»Ð° ÑÐŸÐ·ÐŽÐ°ÐœÐ°. ÐÑÐž ÐœÐ°Ð¶Ð°ÑÐžÐž ÐœÐ° ÑÑÑ ÐºÐœÐŸÐ¿ÐºÑ ÐŸÑÐºÑÑÐ²Ð°ÐµÑÑÑ Ð²ÐµÐ±-Ð±ÑÐ°ÑÐ·ÐµÑ Ñ ÐŽÐŸÐŒÐ°ÑÐœÐµÐ¹ ÑÑÑÐ°ÐœÐžÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (Ð ÐžÑÑÐœÐŸÐº 15).  ÐÑÐ°ÐºÑÐžÑÐµÑÐºÐž, Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÑÐ¹ Ð¿ÑÐŸÑÐŒÐŸÑÑ ÑÐ°ÑÑÐŸ ÐŸÐ±ÐœÐ°ÑÑÐ¶ÐžÐ²Ð°ÐµÑ ÐœÐµÐŽÐŸÑÑÐ°ÑÐºÐž Ð² Ð¿ÑÐŸÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐžÐ»Ðž Ð² ÐžÐœÐŽÐžÐ²ÐžÐŽÑÐ°Ð»ÑÐœÑÑ
+ Ð·ÐœÐ°ÑÐµÐœÐžÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, Ðž Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÑÐ°ÑÑÐŸ Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑÑÑ Ðº Ð±ÐŸÐ»ÐµÐµ ÑÐ°ÐœÐœÐžÐŒ ÑÑÐ°Ð¿Ð°ÐŒ ÐŽÐ»Ñ ÐžÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐžÑ
+. Ð­ÑÐ° ÐºÐœÐŸÐ¿ÐºÐ° ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ Ð°ÐºÑÐžÐ²ÐœÐŸÐ¹, ÐºÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð±ÑÐ»Ð° ÑÐŸÐ·ÐŽÐ°ÐœÐ°. ÐÐµÐŽÐ°Ð²ÐœÐŸ ÑÐŸÐ·ÐŽÐ°ÐœÐœÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð±ÑÐŽÐµÑ ÑÐ°ÐºÐ¶Ðµ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° ÐœÐ° ÐÐ°ÑÐµÐ¹ ÑÑÐ°ÑÑÐŸÐ²ÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐµ Greenstone ÐºÐ°Ðº ÐŸÐŽÐœÐ° ÐžÐ· ÐŸÐ±ÑÑÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹.</Text>
+</Content>
+</Subsection>
+<Subsection id="help">
+<Title>
+<Text id="245">ÐÐŸÐŒÐŸÑÑ</Text>
+</Title>
+<Content>
+<Text id="246">ÐÐžÐ°Ð»ÐŸÐ³ÐŸÐ²Ð°Ñ Ð¿ÐŸÐŒÐŸÑÑ Ð²ÑÐµÐ³ÐŽÐ° ÐŽÐŸÑÑÑÐ¿ÐœÐ°. ÐÐœÐ° Ð·Ð°Ð¿ÑÑÐºÐ°ÐµÑÑÑ Ð¿ÑÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž Ð¿ÑÐœÐºÑÐ° Â«ÐÐŸÐŒÐŸÑÑÂ» Ð² Ð¿ÑÐ°Ð²ÐŸÐ¹ ÑÑÐŸÑÐŸÐœÐµ Ð³Ð»Ð°Ð²ÐœÐŸÐ¹ Ð»ÐžÐœÐµÐ¹ÐºÐž ÐŒÐµÐœÑ ÐœÐ°Ð²ÐµÑÑ
+Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÐžÑÑÐœÐºÐ°. ÐÐœÐ° ÐŸÑÐºÑÑÐ²Ð°ÐµÑ ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐž ÑÑÑÑÐºÑÑÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐ¹ ÑÐµÐºÑÑÐŸÐ²ÑÐ¹ ÑÐ°Ð¹Ð» Ð¿ÐŸÐŒÐŸÑÐž; ÐŸÐ±ÑÑÑÐœÐµÐœÐžÐµ Ð²ÑÑÐµÐºÐ°ÐµÑ ÐžÐ· ÑÐµÐºÑÑÐµÐ³ÐŸ ÐºÐŸÐœÑÐµÐºÑÑÐ° Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð¿ÑÐž Ð¿ÐŸÐŽÑÐ²ÐµÑÐžÐ²Ð°ÐœÐžÐž ÑÐ°Ð·ÐŽÐµÐ»Ð°, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ ÑÐµÐºÑÑÐµÐ¹ ÑÑÐ°ÐŽÐžÐž Ð²Ð·Ð°ÐžÐŒÐŸÐŽÐµÐ¹ÑÑÐ²ÐžÑ. ÐÑÐŸÐŒÐµ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº ÐŸÑÐŒÐµÑÐµÐœÐŸ Ð²ÑÑÐµ, Ð²ÑÑÐºÐžÐ¹ ÑÐ°Ð·, ÐºÐŸÐ³ÐŽÐ° ÐŒÑÑÑ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÐœÐ°ÐŽ Ð»ÑÐ±ÑÐŒ ÐŽÐžÐ°Ð»ÐŸÐ³ÐŸÐ²ÑÐŒ ÐŸÐ±ÑÐµÐºÑÐŸÐŒ, Ð²ÑÐ¿Ð»ÑÐ²Ð°ÐµÑ ÐŒÐ°Ð»ÐµÐœÑÐºÐŸÐµ ÐŸÐºÐœÐŸ, ÑÑÐŸÐ±Ñ ÐŽÐ°ÑÑ ÑÐµÐºÑÑ Ð¿ÐŸÐŽÑÐºÐ°Ð·ÐºÐž, ÐºÐ°Ðº ÑÑÐŸ Ð±ÑÐ»ÐŸ ÐžÐ»Ð»ÑÑÑÑÐžÑÐŸÐ²Ð°ÐœÐŸ ÐŸÐºÐŸÐ»ÐŸ ÐŸÑÐœÐŸÐ²Ð°ÐœÐžÑ ÐœÐ° ÑÐžÑ.14.</Text>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="librarian_interface_user_guide">
+<Title>
+<Text id="247">Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÑÑ</Text>
+</Title>
+<Content>
+<Subsection id="starting_off">
+<Title>
+<Text id="248">ÐÐŸ ÑÑÐ°ÑÑÐ°</Text>
+</Title>
+<Content>
+<Text id="249">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÑÐ°ÑÑÐºÐ°Ð·Ð°ÐœÐŸ, ÐºÐ°Ðº ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ, Ð·Ð°Ð³ÑÑÐ¶Ð°ÑÑ Ðž ÑÐŽÐ°Ð»ÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. </Text>
+<Part id="creating_a_new_collection">
+<Title>
+<Text id="250">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="251">Ð§ÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐœÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐŸÑÐºÑÐŸÐ¹ÑÐµ ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»" Ðž Ð²ÑÐ±ÐµÑÐžÑÐµ Ð² ÐœÑÐŒ Ð¿ÑÐœÐºÑ "ÐÐŸÐ²ÑÐ¹...". ÐÐµÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐ»Ñ ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐŸÐ±ÑÐ·Ð°ÑÐµÐ»ÑÐœÐŸ Ð·Ð°Ð¿ÐŸÐ»ÐœÐµÐœÑ, ÐœÐŸ ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð·Ð°ÐŒÐµÐœÐžÑÑ ÐžÑ
+ Ð·ÐœÐ°ÑÐµÐœÐžÑ Ð¿ÐŸÐ·Ð¶Ðµ, ÐµÑÐ»Ðž ÐÑ Ð² ÑÑÐŸÐŒ ÐœÑÐ¶ÐŽÐ°ÐµÑÐµÑÑ Ñ ÑÐŸÑÐºÐž Ð·ÑÐµÐœÐžÑ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°. </Text>
+<Text id="252">ÐÐ°Ð³Ð»Ð°Ð²ÐžÐµ "ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ/Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž" - ÑÑÐŸ ÑÐµÐºÑÑ, ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐœÑÐ¹ ÐœÐ°Ð²ÐµÑÑ
+Ñ ÐŽÐŸÐŒÐ°ÑÐœÐµÐ¹ ÑÑÑÐ°ÐœÐžÑÑ ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐœÐŸ ÐŒÐŸÐ¶ÐµÑ ÐžÐŒÐµÑÑ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐ»ÑÐœÑÑ ÐŽÐ»ÐžÐœÑ. </Text>
+<Text id="253">"ÐÐ¿ÐžÑÐ°ÐœÐžÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ" ÐŽÐŸÐ»Ð¶ÐœÐŸ Ð¿ÑÐµÐŽÑÑÐ°Ð²ÐžÑÑ ÐºÐ°Ðº ÐŒÐŸÐ¶ÐœÐŸ ÐŽÐµÑÐ°Ð»ÑÐœÐµÐµ ÑÐŸ,ÐŸ ÑÑÐŒ ÑÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐºÐ»Ð°Ð²ÐžÑÑ [Enter] ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ,ÑÑÐŸÐ±Ñ ÑÐ°Ð·Ð±ÐžÑÑ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÐœÐ° Ð¿Ð°ÑÐ°Ð³ÑÐ°ÑÑ. </Text>
+<Text id="254">ÐÐ°ÐºÐŸÐœÐµÑ ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ, ÐŽÐŸÐ»Ð¶ÐœÐ° Ð»Ðž ÐœÐŸÐ²Ð°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐžÐŒÐµÑÑ ÑÐŸÑ Ð¶Ðµ ÑÐ°ÐŒÑÐ¹ Ð²ÐžÐŽ Ðž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÑÐŸ Ðž ÑÑÑÐµÑÑÐ²ÑÑÑÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐžÐ»Ðž Ð¶Ðµ ÐœÐ°ÑÐ°ÑÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ "ÐÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ". </Text>
+<Text id="255">Ð©ÐµÐ»ÐºÐœÐžÑÐµ "OK", ÑÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÑÐ»Ðž ÐÑ Ð²ÑÐ±ÑÐ°Ð»Ðž "ÐÐŸÐ²Ð°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ", ÑÐŸ ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ Ð²Ð²ÐµÑÑÐž ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÑÐŸÐ±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐžÑ
+ Ð² ÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ Ð±ÐŸÐ»ÑÑÐµ,ÑÐµÐŒ ÐŸÐŽÐœÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ, Ð° ÐŒÐŸÐ¶ÐµÑÐµ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐŽÑÑÐ³ÐžÐµ Ð¿ÐŸÐ·Ð¶Ðµ.</Text>
+<Text id="256">ÐÐ°Ð¶Ð°ÑÐžÐµ ÐºÐ»Ð°Ð²ÐžÑÐž "ÐÑÐŒÐµÐœÐžÑÑ" ÐœÐµÐŒÐµÐŽÐ»ÐµÐœÐœÐŸ Ð²ÐŸÐ·Ð²ÑÐ°ÑÐ°ÐµÑ ÐÐ°Ñ Ðº Ð³Ð»Ð°Ð²ÐœÐŸÐŒÑ ÑÐºÑÐ°ÐœÑ.</Text>
+</Content>
+</Part>
+<Part id="saving_the_collection">
+<Title>
+<Text id="257">Ð¡ÐŸÑ
+ÑÐ°ÐœÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="258">Ð¡ÐŸÑ
+ÑÐ°ÐœÑÐ¹ÑÐµ ÐÐ°ÑÑ ÑÐ°Ð±ÐŸÑÑ ÑÐµÐ³ÑÐ»ÑÑÐœÐŸ, ÐŸÑÐºÑÑÐ²Ð°Ñ ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»" Ðž Ð²ÑÐ±ÐžÑÐ°Ñ Ð² ÐœÑÐŒ Ð¿ÑÐœÐºÑ "Ð¡ÐŸÑ
+ÑÐ°ÐœÐžÑÑ". Ð¡ÐŸÑ
+ÑÐ°ÐœÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž - ÑÑÐŸ ÐœÐµ ÑÐŸ Ð¶Ðµ ÑÐ°ÐŒÐŸÐµ, ÐºÐ°Ðº ÑÐŽÐµÐ»Ð°ÑÑ ÐµÑ Ð³ÐŸÑÐŸÐ²ÐŸÐ¹ Ðº ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ Ð² Greenstone. (see Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž).</Text>
+<Text id="259">ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð·Ð°ÑÐžÑÐ°ÐµÑ ÐÐ°ÑÑ ÑÐ°Ð±ÐŸÑÑ Ð¿ÑÑÑÐŒ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐžÑ ÐµÑ Ð²ÑÑÐºÐžÐ¹ ÑÐ°Ð·, ÐºÐŸÐ³ÐŽÐ° ÐÑ Ð²ÑÑ
+ÐŸÐŽÐžÑÐµ ÐžÐ· Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐžÐ»Ðž Ð·Ð°Ð³ÑÑÐ¶Ð°ÐµÑÐµ ÐŽÑÑÐ³ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ.</Text>
+<Text id="260">Ð¡ÐŸÑ
+ÑÐ°ÐœÐµÐœÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð·Ð°Ð¿ÐžÑÑÐ²Ð°ÑÑÑÑ Ð² ÑÐ°Ð¹Ð», ÐžÐŒÐµÑÑÐžÐ¹ ÑÐŸ Ð¶Ðµ ÐžÐŒÑ, ÑÑÐŸ Ðž ÐžÐŒÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ñ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµÐŒ ".col", Ðž ÑÐ°ÑÐ¿ÐŸÐ»Ð°Ð³Ð°ÐµÑÑÑ Ð² Ð¿Ð°Ð¿ÐºÐµ ÑÐŸÐ³ÐŸ Ð¶Ðµ ÐœÐ°ÐžÐŒÐµÐœÐŸÐ²Ð°ÐœÐžÑ, ÑÑÐŸ Ðž Ð¿Ð°Ð¿ÐºÐ° "collect" Ð¿ÑÐž ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž Greenstone.</Text>
+</Content>
+</Part>
+<Part id="opening_an_existing_collection">
+<Title>
+<Text id="261">ÐÑÐºÑÑÑÐžÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="262">ÐÐ»Ñ ÑÐŸÐ³ÐŸ ÑÑÐŸÐ±Ñ ÐŸÑÐºÑÑÑÑ ÑÑÑÐµÑÑÐ²ÑÑÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, Ð²ÑÐ±ÐµÑÐžÑÐµ "ÐÑÐºÑÑÑÑ" Ð² ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»",ÑÑÐŸÐ±Ñ Ð±ÑÑÑÑÐŸ Ð¿ÐµÑÐµÐ¹ÑÐž Ðº ÐÑÐºÑÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐŸÑÐ²Ð»ÑÐµÑÑÑ ÑÐ¿ÐžÑÐŸÐº ÐÐ°ÑÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ð² Greenstone. ÐÑÐ±ÐµÑÐžÑÐµ ÐŸÐŽÐœÑ,ÑÑÐŸÐ±Ñ ÑÐ²ÐžÐŽÐµÑÑ ÐµÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ,Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "OÑÐºÑÑÑÑ", ÑÑÐŸÐ±Ñ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ ÐµÐµ. ÐÑÐ»Ðž ÐÑ ÐžÑÐžÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð²ÐœÐµ Ð¿Ð°Ð¿ÐºÐž "Ð¡ollect Greenstone",ÑÐŸ ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð Ð°ÑÑÐŒÐŸÑÑÐµÑÑ" ÐŽÐ»Ñ Ð²ÑÐ·ÐŸÐ²Ð° ÐŽÐžÐ°Ð»ÐŸÐ³ÐŸÐ²ÐŸÐ¹ ÑÐžÑÑÐµÐŒÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÑÐ°Ð¹Ð»ÐŸÐ².</Text>
+<Text id="263">Ð ÑÐ»ÑÑÐ°Ðµ, ÐµÑÐ»Ðž Ð±ÐŸÐ»ÑÑÐµ ÑÐµÐŒ ÐŸÐŽÐœÐ° Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° Greenstone Ð²Ð²ÐŸÐŽÐžÑÑÑ ÐŸÐŽÐœÐŸÐ²ÑÐµÐŒÐµÐœÐœÐŸ, ÑÐµÐ»ÐµÐ²Ð°ÐœÑÐœÑÐµ ÐŽÐžÑÐµÐºÑÑÐžÐž "Ð·Ð°ÐºÑÑÑÑ",ÑÑÐŸÐ±Ñ Ð¿ÑÐµÐŽÐŸÑÐ²ÑÐ°ÑÐžÑÑ ÐœÐ°Ð»ÐŸÐ¶ÐµÐœÐžÐµ.ÐÑÐž ÐŸÑÐºÑÑÑÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐœÐµÐ±ÐŸÐ»ÑÑÐŸÐ¹ Ð²ÑÐµÐŒÐµÐœÐœÑÐ¹ Ð±Ð»ÐŸÐºÐžÑÑÑÑÐžÐ¹ ÑÐ°Ð¹Ð» ÑÐŸÐ·ÐŽÐ°ÐµÑÑÑ Ð² ÐµÑ Ð¿Ð°Ð¿ÐºÐµ.ÐÐµÑÐµÐŽ ÐŸÑÐºÑÑÑÐžÐµÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑ Ð¿ÑÐŸÐ²ÐµÑÐºÑ,ÑÑÐŸÐ±Ñ ÑÐ±ÐµÐŽÐžÑÑÑÑ,ÑÑÐŸ ÐœÐžÐºÐ°ÐºÐžÑ
+ Ð±Ð»ÐŸÐºÐžÑÑÑÑÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² ÐœÐµ ÑÑÑÐµÑÑÐ²ÑÐµÑ. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐºÐ°Ð·Ð°ÑÑ,Ð·Ð°ÐºÑÑÑÐ° Ð»Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, Ð¿ÐŸ ÑÐ²ÐµÑÑ ÐµÑ ÐžÐºÐŸÐœÐºÐž:Ð·ÐµÐ»ÑÐœÑÐ¹ - ÐŽÐ»Ñ ÐœÐŸÑÐŒÐ°Ð»ÑÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž,ÐºÑÐ°ÑÐœÑÐ¹ - ÐŽÐ»Ñ Ð·Ð°ÐºÑÑÑÐŸÐ¹. ÐÐŽÐœÐ°ÐºÐŸ,ÐºÐŸÐ³ÐŽÐ° ÐžÐ· ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° Ð²ÑÑ
+ÐŸÐŽÑÑ Ð¿ÑÐµÐ¶ÐŽÐµÐ²ÑÐµÐŒÐµÐœÐœÐŸ, Ð±Ð»ÐŸÐºÐžÑÑÑÑÐžÐ¹ ÑÐ°Ð¹Ð» ÐžÐœÐŸÐ³ÐŽÐ° ÐŸÑÑÐ°ÐµÑÑÑ ÐœÐ° ÐŒÐµÑÑÐµ. ÐÐŸÐ³ÐŽÐ° ÐÑ ÐŸÑÐºÑÑÐ²Ð°ÐµÑÐµ ÑÐ°ÐºÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Ð·Ð°Ð¿ÑÐ°ÑÐžÐ²Ð°ÐµÑ,Ñ
+ÐŸÑÐžÑÐµ Ð»Ðž ÐÑ "ÑÐºÑÐ°ÑÑÑ" ÐµÐ³ÐŸ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ. ÐÐžÐºÐŸÐ³ÐŽÐ° ÐœÐµ ÐŽÐµÐ»Ð°Ð¹ÑÐµ ÑÑÐŸÐ³ÐŸ,ÐµÑÐ»Ðž ÐºÑÐŸ-ÑÐŸ ÐµÑÐµ Ð² ÑÐŸ Ð¶Ðµ ÑÐ°ÐŒÐŸÐµ Ð²ÑÐµÐŒÑ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ. </Text>
+<Text id="264">ÐÐŸÐ³ÐŽÐ° ÐÑ ÐŸÑÐºÑÑÐ²Ð°ÐµÑÐµ ÐºÐŸÐ»ÐµÐºÑÐžÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐ° ÐœÐµ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° Greenstone, ÐÐ°Ñ Ð¿ÐŸÐ¿ÑÐŸÑÑÑ Ð²ÑÐ±ÑÐ°ÑÑ ÐœÐ°Ð±ÐŸÑ (ÐžÐ»Ðž ÐœÐ°Ð±ÐŸÑÑ) ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. ÐÑÐ»Ðž ÐœÐž ÐŸÐŽÐžÐœ ÐœÐµ ÐŸÑÐŸÐ±ÑÐ°Ðœ, Ð»ÑÐ±ÑÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð±ÑÐŽÑÑ ÐžÐ³ÐœÐŸÑÐžÑÐŸÐ²Ð°ÑÑÑÑ. ÐÐœÐ°ÑÐµ, ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð±ÑÐŽÑÑ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÑ ÑÐ°Ðº Ð¶Ðµ, ÐºÐ°Ðº Ðž ÐºÐŸÐ³ÐŽÐ° ÐÑ Ð¿ÐµÑÐµÑÑÐ³ÐžÐ²Ð°ÐµÑÐµ Ð² ÑÐ°Ð¹Ð»Ñ Ñ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐŒÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž. ÐÑÐŸÑÐµÑÑ ÐŸÐ¿ÐžÑÐ°Ðœ Ð² ÐÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐž Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð²ÑÐ±ÑÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. </Text>
+</Content>
+</Part>
+<Part id="deleting_collections">
+<Title>
+<Text id="265">Ð£ÐŽÐ°Ð»ÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹</Text>
+</Title>
+<Content>
+<Text id="266">ÐÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÐœÐµÐžÐ·ÐŒÐµÐœÐœÐŸ ÑÐŽÐ°Ð»ÐžÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐžÐ· ÐžÐœÑÑÐ°Ð»ÑÑÐžÐŸÐœÐœÐŸÐ¹ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž Greenstone, Ð²ÑÐ±ÐµÑÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ..." ÐžÐ· ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»". ÐÑÐºÑÐŸÐµÑÑÑ ÑÐ¿ÐžÑÐŸÐº Ð²ÑÐµÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Greenstone. ÐÑÐ±ÐµÑÐžÑÐµ ÐœÑÐ¶ÐœÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÐ° ÐµÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ, Ð¿ÐŸÑÐ»Ðµ ÑÑÐŸÐ³ÐŸ Ð¿ÐŸÑÑÐ°Ð²ÑÐµ Ð³Ð°Ð»ÐŸÑÐºÑ Ð² Ð¿ÑÐœÐºÑÐµ Ð²ÐœÐžÐ·Ñ ÐŽÐžÐ°Ð»ÐŸÐ³Ð° Ðž ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° "Ð£ÐŽÐ°Ð»ÐžÑÑ", ÑÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. Ð­ÑÐ° ÐŸÐ¿ÐµÑÐ°ÑÐžÑ Ð±ÐµÐ·Ð²ÐŸÐ·Ð²ÑÐ°ÑÐœÐ°, Ð¿ÐŸÑÑÐŸÐŒÑ Ð¿ÑÐŸÐ²ÐµÑÑÑÐµ Ð²ÐœÐžÐŒÐ°ÑÐµÐ»ÑÐœÐŸ, ÐŽÐµÐ¹ÑÑÐ²ÐžÑÐµÐ»ÑÐœÐŸ Ð»Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐœÐµÐœÑÐ¶ÐœÐ°! </Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="downloading_files_from_the_internet">
+<Title>
+<Text id="267">ÐÐ°Ð³ÑÑÐ·ÐžÑÑ ÑÐ°Ð¹Ð»Ñ ÐžÐ· ÐžÐœÑÐµÑÐœÐµÑ</Text>
+</Title>
+<Content>
+<Text id="268">ÐÐžÐŽ "ÐÐµÑÐºÐ°Ð»ÐŸ" Ð¿ÐŸÐŒÐŸÐ¶ÐµÑ Ð²Ð°ÐŒ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐžÐ· ÐÐœÑÐµÑÐœÐµÑÐ°. ÐÐ°ÐœÐœÐ°Ñ ÑÐµÐºÑÐžÑ ÐŸÐ±ÑÑÑÐœÑÐµÑ Ð¿ÑÐŸÑÐµÑÑ Ð·ÐµÑÐºÐ°Ð»ÐžÑÐŸÐ²Ð°ÐœÐžÑ Ð² ÐÐœÑÐµÑÑÐµÐ¹ÑÐµ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÑÑ. </Text>
+<Part id="the_download_view">
+<Title>
+<Text id="269">ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐÐ°Ð³ÑÑÐ·ÐžÑÑ</Text>
+</Title>
+<Content>
+<Text id="270">Ð­ÑÐ° ÑÐµÐºÑÐžÑ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ ÐºÐ°Ðº ÐºÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÑÑ Ð·Ð°ÐŽÐ°ÑÑ Ðž ÐºÐŸÐœÑÑÐŸÐ»Ñ Ð¿ÑÐŸÑÐµÑÑÐ° Ð·Ð°Ð³ÑÑÐ·ÐºÐž. ÐÐŸÑÑÑÐ¿ Ðº Ð¿ÑÐŸÑÐŒÐŸÑÑÑ "ÐÐ°Ð³ÑÑÐ·ÐžÑÑ" ÐœÐ°Ð¶Ð°ÑÐµÐŒ ÑÑÐŸÐ¹ Ð·Ð°ÐºÐ»Ð°ÐŽÐºÐž. ÐÐµÑÑ
+ÐœÑÑ Ð¿ÐŸÐ»ÐŸÐ²ÐžÐœÐ° ÑÐºÑÐ°ÐœÐ° Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐºÐŸÐœÑÑÐŸÐ»Ñ Ð·Ð°Ð³ÑÑÐ·ÐºÐž. ÐÐžÐ¶ÐœÑÑ Ð¿ÐŸÐ»ÐŸÐ²ÐžÐœÐ° Ð² ÐœÐ°ÑÐ°Ð»Ðµ Ð¿ÑÑÑÐ°, ÐŸÐŽÐœÐ°ÐºÐŸ Ð¿ÐŸÐºÐ°Ð¶ÐµÑ Ð¿ÐµÑÐµÑÐµÐœÑ ÐŸÐ¶ÐžÐŽÐ°ÐµÐŒÑÑ
+ Ðž Ð·Ð°ÐºÐŸÐœÑÐµÐœÐœÑÑ
+ Ð·Ð°Ð³ÑÑÐ·ÐŸÐº. </Text>
+<Text id="271">Ð€Ð°Ð¹Ð»Ñ Ð·Ð°Ð³ÑÑÐ¶ÐµÐœÐœÑÐµ Ð² Ð¿Ð°Ð¿ÐºÑ ÑÐ°Ð±ÐŸÑÐµÐ³ÐŸ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ð° ÐœÐ°Ð·ÑÐ²Ð°ÑÑÑÑ "ÐÐ°Ð³ÑÑÐ¶Ð°ÐµÐŒÑÐµ ÑÐ°Ð¹Ð»Ñ", Ðž ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐ° Ð²ÑÐµÐŒÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒÐž Ð¿ÐŸÑÑÑÐŸÐµÐœÐœÑÐŒÐž Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐÐœÑÐµÑÑÐµÐ¹ÑÐ° ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÑÑ. Ð€Ð°Ð¹Ð»Ñ Ð² ÑÑÐŸÐ¹ ÐŸÐ±Ð»Ð°ÑÑÐžÐžÐŒÐµÐœÑÑÑÑÑ Ð¿ÐŸ ÐžÑ
+ Ð¿ÐŸÐ»ÐœÐŸÐŒÑ URL Ð°ÐŽÑÐµÑÑ. Ð¡ÐŸÐ·ÐŽÐ°ÐµÑÑÑ ÐœÐŸÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ° ÐœÐ° ÐºÐ°Ð¶ÐŽÐŸÐŒ Ñ
+ÐŸÑÑÐµ, ÐœÐ°ÑÐ»ÐµÐŽÑÐµÐŒÐ°Ñ ÐŽÑÑÐ³ÐžÐŒÐž ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÑÐ°Ð³ÐŒÐµÐœÑÐ° Ð¿ÑÑÐž. Ð­ÑÐŸ Ð³Ð°ÑÐ°ÐœÑÐžÑÑÐµÑ ÐŸÑÐ»ÐžÑÐžÐµ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð°. </Text>
+<Text id="272">ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ Ð¿ÐµÑÐ²ÑÐ¹ ÐžÐ· ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÑÐµÐŒÑÑ
+ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐ¹ Ð·Ð°Ð³ÑÑÐ·ÐŸÐº, "ÐÑÑ
+ÐŸÐŽÐœÑÐ¹ URL", ÑÑÐŸÐ±Ñ Ð²Ð²ÐµÑÑÐž URL Ð°ÐŽÑÐµÑ Ð² ÑÐµÐ»ÐµÐ²ÐŸÐ¹ ÑÐµÑÑÑÑ. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐºÐŸÐœÑÑÐŸÐ»Ñ "ÐÐ»ÑÐ±ÐžÐœÑ ÐÐ°Ð³ÑÑÐ·ÐºÐž" ÐŽÐ»Ñ ÐŸÐ³ÑÐ°ÐœÐžÑÐµÐœÐžÑ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²Ð° Ð³ÐžÐ¿ÐµÑÑÑÑÐ»ÐŸÐº ÐŽÐ»Ñ Ð·Ð°Ð³ÑÑÐ·ÐºÐž: Ð£ÑÑÐ°ÐœÐŸÐ²ÐžÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ 0 ÐŽÐ»Ñ Ð·Ð°Ð³ÑÑÐ·ÐºÐž ÐŸÐŽÐœÐŸÐ¹ Ð²ÐµÐ± ÑÑÑÐ°ÐœÐžÑÑ; Ð·ÐœÐ°ÑÐµÐœÐžÐµ 1 ÑÑÐŸÐ±Ñ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ ÐŸÐŽÐœÑ ÑÑÑÐ°ÐœÐžÑÑ Ðž Ð²ÑÐµ ÑÑÑÐ°ÐœÐžÑÑ ÑÐ²ÑÐ·Ð°ÐœÐœÑÐµ Ñ ÐœÐµÐ¹ . Ð¿ÑÐµÐŽÐµÐ» Ð³Ð»ÑÐ±ÐžÐœÑ ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÑÐµÑÑÑ ÑÐŸÐ»ÑÐºÐŸ ÐœÐ° html ÑÑÑÐ°ÐœÐžÑÑ. Ð¡Ð»ÐµÐŽÑÐ¹ÑÐµÐµ, Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐ° ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ° ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ "Ð³Ð°Ð»ÐŸÑÐµÐº", ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ, ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ ÑÑÐŸÐ±Ñ ÑÑÐŸÐ±Ñ Ð²ÐºÐ»ÑÑÐžÑÑ ÑÐºÐ°Ð·Ð°ÐœÐœÑÑ ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÑ ÐºÐŸÐœÐºÑÐµÑÐœÐŸÐ¹ Ð·Ð°Ð³ÑÑÐ·ÐºÐž. ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐ°, ÐœÐ°Ð¶ÐŒÐžÑÐµ "ÐÐ°Ð³ÑÑÐ·ÐºÐ°", ÑÑÐŸÐ±Ñ ÐœÐ°ÑÐ°ÑÑ ÐœÐŸÐ²ÑÑ Ð·Ð°Ð³ÑÑÐ·ÐºÑ. ÐÑÑÑ ÐŽÐ²Ðµ ÐŽÑÑÐ³ÐžÑ
+ ÐºÐœÐŸÐ¿ÐºÐž: Ð² ÑÐ°Ð·ÐŽÐµÐ»Ðµ "ÐÐ°ÑÑÑÐŸÐ¹ÐºÐž", ÐºÐŸÑÐŸÑÑÐµ ÑÐ²ÑÐ·Ð°ÐœÑ Ñ ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐŒ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž ÑÐ²ÑÐ·Ðž, Ð³ÐŽÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ Ð¿ÑÐŸÐºÑÐž ÑÐµÑÐ²ÐµÑÐ° ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐžÐ·ÐŒÐµÐœÐµÐœÑ; Ðž "ÐÑÐžÑÑÐºÐ° ÐÑÑ", ÐºÐŸÑÐŸÑÐ°Ñ ÑÐŽÐ°Ð»ÑÐµÑ Ð²ÑÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°Ð³ÑÑÐ¶ÐµÐœÐœÑÐµ ÑÐ°Ð¹Ð»Ñ. </Text>
+<Text id="273">Ð¡Ð¿ÐžÑÐŸÐº Ð·Ð°Ð³ÑÑÐ·ÐºÐž ÐžÐŒÐµÐµÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ¹ Ð·Ð°Ð³ÑÑÐ¶Ð°ÐµÐŒÐŸÐ¹ Ð²ÐµÐ± ÑÑÑÐ°ÐœÐžÑÑ. ÐÐ°Ð¶ÐŽÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐŒÐµÐµÑ ÑÐµÐºÑÑ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÑÑÐžÐ¹ ÐŽÐµÑÐ°Ð»Ðž Ð·Ð°ÐŽÐ°ÑÐž Ð²ÐŒÐµÑÑÐµ Ñ ÐžÐœÐŽÐžÐºÐ°ÑÐŸÑÐŸÐŒ Ð¿ÑÐŸÐ³ÑÐµÑÑÐ° ÐŽÐµÐŒÐŸÐœÑÑÑÐžÑÑÑÑÐžÐŒ ÑÐµÐºÑÑÑÑ ÐŽÐµÑÑÐµÐ»ÑÐœÐŸÑÑÑ. Ð¢ÑÐž ÐºÐœÐŸÐ¿ÐºÐž Ð¿ÐŸÑÐ²Ð»ÑÑÑÑÑ ÑÐ»ÐµÐ²Ð° ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ. "ÐÐ°ÑÐ·Ð°" ÐŽÐ»Ñ Ð¿ÑÐžÐŸÑÑÐ°ÐœÐŸÐ²ÐºÐž Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ ÑÐµÐºÑÑÐµÐ³ÐŸ Ð¿ÑÐŸÑÐµÑÑÐ°. "Ð¡ÐŒÐŸÑÑÐµÑÑ ÐÐŸÐ³Ðž" ÐŸÑÐºÑÑÐ²Ð°ÐµÑ ÐŸÐºÐœÐŸ ÑÐ°Ð¹Ð»Ð° Ð·Ð°Ð³ÑÑÐ·ÐºÐž. "ÐÐ°ÐºÑÑÑÑ" Ð·Ð°Ð²ÐµÑÑÐ°ÐµÑ Ð·Ð°Ð³ÑÑÐ·ÐºÑ Ð·Ð°ÐŽÐ°ÑÐž ÐžÐ· ÑÐ¿ÐžÑÐºÐ°. </Text>
+<Text id="274">Ð¡ÐµÐºÑÐžÑ ÐÐ°ÑÑÑÐŸÐµÐº ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ ÐºÐ°Ðº ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐžÐœÑÐµÑÐœÐµÑ ÑÐŸÐµÐŽÐžÐœÐµÐœÐžÐµ ÑÐµÑÐµÐ· Ð¿ÑÐŸÐºÑÐž ÑÐµÑÐ²ÐµÑ. ÐÑÐ»Ðž ÐœÑÐ¶ÐœÐ° ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐ°Ñ Ð°ÑÑÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÑ, Ð¿ÑÐŸÐºÑÐž ÑÐµÑÐ²ÐµÑ Ð·Ð°Ð¿ÑÐŸÑÐžÑ ÐžÐŒÑ Ðž Ð¿Ð°ÑÐŸÐ»Ñ. ÐÐœÑÐµÑÑÐµÐ¹Ñ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÑÑ ÐœÐµ ÑÐŸÐ·ÑÐ°ÐœÑÐµÑ Ð¿Ð°ÑÐŸÐ»Ðž ÐŒÐµÐ¶ÐŽÑ ÑÐµÑÑÐžÑÐŒÐž.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="collecting_files_for_your_collection">
+<Title>
+<Text id="275">Ð¡Ð±ÐŸÑ ÑÐ°Ð¹Ð»ÐŸÐ² ÐŽÐ»Ñ ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="276">ÐÑÐ»Ðž ÐÑ ÑÐŸÐ·ÐŽÐ°ÐµÑÐµ ÐœÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ,ÑÐŸ Ð²ÐŸÐ·ÐœÐžÐºÐ°ÐµÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÑ Ð²Ð²ÐŸÐŽÐ° Ð² ÐœÐµÐµ ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ².ÐÐœÐž ÐŒÐŸÐ³ÑÑ Ð¿ÐŸÑÑÑÐ¿ÐžÑÑ ÐžÐ· Ð²Ð°ÑÐµÐ³ÐŸ ÐŸÐ±ÑÑÐœÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ³ÐŸ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ð° ÐžÐ· ÐŽÑÑÐ³ÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Greenstone. ÐÐµÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ ÑÐ¶Ðµ ÐžÐŒÐµÑÑ Ð¿ÑÐžÑÐŸÐµÐŽÐžÐœÐµÐœÐœÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ.Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑÑÑ,ÐºÐ°Ðº ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐ°Ð¹Ð»Ñ. </Text>
+<Part id="the_gather_view">
+<Title>
+<Text id="277">ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐœÐ°ÐºÐŸÐ¿ÐžÑÐµÐ»Ñ</Text>
+</Title>
+<Content>
+<Text id="278">Ð­ÑÐŸÑ ÑÐ°Ð·ÐŽÐµÐ» Ð²Ð²ÐŸÐŽÐžÑ Ð² ÐŸÐ±Ð»Ð°ÑÑÑ ÐœÐ°ÐºÐŸÐ¿Ð»ÐµÐœÐžÑ,ÐºÐŸÑÐŸÑÑÑ ÐÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ,ÑÑÐŸÐ±Ñ Ð²ÑÐ±ÑÐ°ÑÑ,ÐºÐ°ÐºÐžÐµ ÑÐ°Ð¹Ð»Ñ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð² ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÐµÐŒÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ ÐœÐ°ÑÐžÐœÐ°ÐµÑÑÑ Ñ ÐŸÐ±Ð·ÐŸÑÐ° ÐœÐ°ÐºÐŸÐ¿Ð»ÐµÐœÐžÑ. Ð§ÑÐŸÐ±Ñ Ð²ÐµÑÐœÑÑÑÑÑ Ðº ÑÑÐŸÐŒÑ ÐŸÐ±Ð·ÐŸÑÑ Ð¿ÐŸÐ·Ð¶Ðµ,ÑÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° ÑÐžÐŒÐ²ÐŸÐ»Ðµ "Gather", ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐœÑÐŒ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ ÐœÐžÐ¶Ðµ Ð»ÐžÐœÐµÐ¹ÐºÐž ÐŒÐµÐœÑ.</Text>
+<Text id="279">ÐÐ²Ðµ Ð±ÐŸÐ»ÑÑÐžÐµ ÐŸÐ±Ð»Ð°ÑÑÐž,ÐœÐ°Ð·Ð²Ð°ÐœÐœÑÐµ "Ð Ð°Ð±ÐŸÑÐµÐµ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²ÐŸ" Ðž "ÐoÐ»Ð»ÐµÐºÑÐžÑ" ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐ»Ñ ÑÐŸÐ³ÐŸ,ÑÑÐŸÐ±Ñ Ð¿ÐµÑÐµÐŒÐµÑÑÐžÑÑ ÑÐ°Ð¹Ð»Ñ Ð² ÐÐ°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÐœÐž Ð²ÐºÐ»ÑÑÐ°ÑÑ "ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐµ ÐŽÐµÑÐµÐ²ÐŸ",Ð³ÑÐ°ÑÐžÑÐµÑÐºÐžÐµ ÑÑÑÑÐºÑÑÑÑ,ÐºÐŸÑÐŸÑÑÐµ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶Ð°ÑÑ ÑÐ°Ð¹Ð»Ñ Ðž Ð¿Ð°Ð¿ÐºÐž.</Text>
+<Text id="280">ÐÑÐ±ÐµÑÐžÑÐµ ÑÐ»ÐµÐŒÐµÐœÑ ÐŽÐµÑÐµÐ²Ð°, ÐœÐ°Ð¶Ð°Ð² ÐœÐ° ÐœÐµÐ³ÐŸ Ð»ÐµÐ²ÐŸÐ¹ ÐºÐ»Ð°Ð²ÐžÑÐµÐ¹ ÐŒÑÑÐž. (Ð¢ÐŸ Ð¶Ðµ ÑÐ°ÐŒÐŸÐµ ÐŒÐŸÐ¶ÐœÐŸ ÑÐŽÐµÐ»Ð°ÑÑ ÐžÐœÐ°ÑÐµ, ÑÐŒ. ÐœÐžÐ¶Ðµ). ÐÐ²ÐŸÐ¹ÐœÑÐŒ ÑÐµÐ»ÑÐºÐŸÐŒ Ð²ÑÐ±ÐµÑÐžÑÐµ Ð¿Ð°Ð¿ÐºÑ, ÐžÐ»Ðž ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÑÐžÐŒÐ²ÐŸÐ» ÑÑÐŽÐŸÐŒ Ñ ÐœÐµÐ¹, ÑÑÐŸÐ±Ñ ÑÐ°Ð·Ð²ÐµÑÐœÑÑÑ (ÐžÐ»Ðž ÑÐ²ÐµÑÐœÑÑÑ) ÐµÐµ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ. ÐÐ²ÐŸÐ¹ÐœÑÐŒ ÑÐµÐ»ÑÐºÐŸÐŒ ÐœÐ° ÐœÑÐ¶ÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ ÐŸÑÐºÑÐŸÐ¹ÑÐµ ÐµÐ³ÐŸ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÐŸÐ¹ ÐŽÐ°ÐœÐœÐŸÐŒÑ ÑÐžÐ¿Ñ ÑÐ°Ð¹Ð»ÐŸÐ² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ (ÑÐŒ.ÐÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ).</Text>
+<Text id="281">ÐÐµÑÐµÐ²ÐŸ ÑÐ°Ð±ÐŸÑÐµÐ³ÐŸ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ð° Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐžÑÑÐŸÑÐœÐžÐºÐž ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐŸÑÑÑÐ¿ÐœÑÑ
+ Ð² ÐÐœÑÐµÑÑÐµÐ¹ÑÐµ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°ÑÑ -- ÑÐµÐºÑÑÑÑ ÑÐ°Ð¹Ð»ÐŸÐ²ÑÑ ÑÐžÑÑÐµÐŒÑ (Ð²ÐºÐ»ÑÑÐ°Ñ ÐŽÐžÑÐºÐŸÐ²ÐŸÐŽ Ðž CD-ROM), ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐÑÐžÐœÑÑÐŸÑÐœ, Ðž ÐºÑÑ Ð·Ð°Ð³ÑÑÐ¶ÐµÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ². ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÐžÐŽÐµÑÑ Ðž ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÑÑ ÑÑÐž ÑÐ°Ð¹Ð»Ñ, ÐŸÐŽÐœÐ°ÐºÐŸ ÐœÐµ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐµÑÐµÐœÐŸÑÐžÑÑ, ÑÐŽÐ°Ð»ÑÑÑ, ÐžÐ»Ðž ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐžÑ
+, Ð·Ð° ÐžÑÐºÐ»ÑÑÐµÐœÐžÐµÐŒ ÑÐ¶Ðµ Ð·Ð°Ð³ÑÑÐ¶ÐµÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐŽÐ°Ð»ÐµÐœÑ. ÐÑÑÑÐµÑÑÐ²Ð»ÑÑÑ ÐœÐ°Ð²ÐžÐ³Ð°ÑÐžÑ Ð² ÑÑÐŸÐŒ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ðµ ÑÑÐŸÐ±Ñ ÐœÐ°Ð¹ÑÐž ÑÐ°Ð¹Ð»Ñ ÐºÐŸÑÐŸÑÑÐµ Ð²Ñ Ñ
+ÐŸÑÐžÑÐµ Ð²ÐºÐ»ÑÑÐžÑÑ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ.</Text>
+<Text id="282">Ð€Ð°Ð¹Ð»ÐŸÐ²ÐŸÐµ ÐŽÐµÑÐµÐ²ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÑ Ð¿ÐŸÐ»ÐœÐŸÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐµÑÐ²ÐŸÐœÐ°ÑÐ°Ð»ÑÐœÐŸ ÐŸÐœÐŸ Ð¿ÑÑÑÐŸ.</Text>
+<Text id="283">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÑÐ°Ð·ÐŒÐµÑÑ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ð°, Ð¿ÐµÑÐµÐŽÐ²ÐžÐ³Ð°Ñ ÐŒÑÑÑ Ð¿ÐŸ ÑÐµÑÐŸÐ¹ Ð»ÐžÐœÐµÐ¹ÐºÐµ, ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÑÐŽÐµÐ»ÑÐµÑ ÐŽÐµÑÐµÐ²ÑÑ (ÑÐŸÑÐŒÐ° ÑÐºÐ°Ð·Ð°ÑÐµÐ»Ñ ÐžÐ·ÐŒÐµÐœÑÐµÑÑÑ),Ðž Ð±ÑÐºÑÐžÑÑÑ ÐžÑ
+.</Text>
+<Text id="284">ÐÐœÐžÐ·Ñ ÐŸÐºÐœÐ° ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐ° ÑÑÐ°ÑÑÑÐœÐ°Ñ ÐŸÐ±Ð»Ð°ÑÑÑ, ÐºÐŸÑÐŸÑÐ°Ñ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð¿ÑÐŸÐ³ÑÐµÑÑ ÐŸÐ¿ÐµÑÐ°ÑÐžÐ¹ ÐœÐ°ÐŽ ÑÐ°Ð¹Ð»Ð°ÐŒÐž (ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÐžÐµ, Ð¿ÐµÑÐµÐŒÐµÑÐµÐœÐžÐµ, ÑÐŽÐ°Ð»ÐµÐœÐžÐµ). ÐÐœÐž ÐŒÐŸÐ³ÑÑ Ð·Ð°ÐœÑÑÑ ÐºÐ°ÐºÐŸÐµ-ÑÐŸ Ð²ÑÐµÐŒÑ. ÐÐœÐŸÐ¿ÐºÐ° "Ð¡ÑÐŸÐ¿" ÐŸÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑ Ð»ÑÐ±ÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ Ð² ÐœÐ°ÑÑÐŸÑÑÐµÐµ Ð²ÑÐµÐŒÑ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ.</Text>
+<Text id="285">ÐÐ²Ðµ Ð±ÐŸÐ»ÑÑÐžÐµ ÐºÐœÐŸÐ¿ÐºÐž Ð·Ð°ÐœÐžÐŒÐ°ÑÑ ÐœÐžÐ¶ÐœÐžÐ¹ Ð¿ÑÐ°Ð²ÑÐ¹ ÑÐ³ÐŸÐ» ÑÐºÑÐ°ÐœÐ°."ÐÐŸÐ²Ð°Ñ ÐÐ°Ð¿ÐºÐ°",Ñ ÐºÐ°ÑÑÐžÐœÐŸÐ¹ Ð¿Ð°Ð¿ÐºÐž, ÑÐŸÐ·ÐŽÐ°ÑÑ ÐœÐŸÐ²ÑÐµ Ð¿Ð°Ð¿ÐºÐž (ÑÐŒ. Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ Ð¿Ð°Ð¿ÐŸÐº). ÐÐœÐŸÐ¿ÐºÐ° "Ð£ÐŽÐ°Ð»ÐžÑÑ"ÑÐŽÐ°Ð»ÑÐµÑ ÑÐ°Ð¹Ð»Ñ Ñ ÐœÐµÐœÑÐ¶ÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐµÐ¹.Ð©ÐµÐ»ÑÐŸÐº ÐœÐ° ÐºÐœÐŸÐ¿ÐºÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ" ÑÐŽÐ°Ð»ÐžÑ Ð»ÑÐ±ÑÐµ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÐµ ÑÐ°Ð¹Ð»Ñ ÐžÐ· ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ³ÐŸ ÐŽÐµÑÐµÐ²Ð° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ»ÑÑÐµÑÐœÐ°ÑÐžÐ²ÐœÐŸ, ÑÐ°Ð¹Ð»Ñ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐŽÐ°Ð»ÐµÐœÑ Ð¿ÑÑÐµÐŒ Ð¿ÐµÑÐµÑÑÐ³ÐžÐ²Ð°ÐœÐžÑ ÐžÑ
+ ÐœÐ° ÐºÐœÐŸÐ¿ÐºÑ "Ð£ÐŽÐ°Ð»ÐžÑÑ".</Text>
+<Text id="286">Ð§ÑÐŸÐ±Ñ ÐŸÑÐŸÐ±ÑÐ°ÑÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ Ð¿ÐŸÑÐ»ÐµÐŽÐŸÐ²Ð°ÑÐµÐ»ÑÐœÑÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ²,Ð²ÑÐ±ÐµÑÐžÑÐµ Ð¿ÐµÑÐ²ÑÐ¹ Ðž Ð·Ð°ÑÐµÐŒ ÑÐŽÐµÑÐ¶ÐžÐ²Ð°Ñ [Shift],ÑÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° Ð¿ÐŸÑÐ»ÐµÐŽÐœÐµÐŒ - Ð¿ÑÐž ÑÑÐŸÐŒ Ð±ÑÐŽÑÑ ÐŸÑÐŸÐ±ÑÐ°ÐœÑ Ð²ÑÐµ ÐŸÑ
+Ð²Ð°ÑÐµÐœÐœÑÐµ ÑÐ»ÐµÐŒÐµÐœÑÑ.ÐÑÐ±ÐŸÑ ÐœÐµ ÑÐ»ÐµÐŽÑÑÑÐžÑ
+ ÐŸÐŽÐžÐœ Ð·Ð° ÐŽÑÑÐ³ÐžÐŒ ÑÐ°Ð¹Ð»ÐŸÐ² Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑÑ Ð¿ÑÐž ÐœÐ°Ð¶Ð°ÑÐŸÐ¹ ÐºÐ»Ð°Ð²ÐžÑÐµ [Ctrl] Ðž ÑÐµÐ»ÑÐºÐµ ÐœÐ° Ð²ÑÐ±ÐžÑÐ°ÐµÐŒÑÑ
+ ÑÐ°Ð¹Ð»Ð°Ñ
+. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÑÑÐž ÐŽÐ²Ð° ÐŒÐµÑÐŸÐŽÐ° Ð²ÐŒÐµÑÑÐµ ÐŽÐ»Ñ Ð³ÑÑÐ¿Ð¿Ñ ÐœÐµÑÐŒÐµÐ¶ÐœÑÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ².</Text>
+<Text id="287">ÐÐµÐºÐŸÑÐŸÑÑÐµ Ð¿Ð°Ð¿ÐºÐž - ÑÐžÐ¿Ð° ÑÐµÑ
+,ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŽÐµÑÐ¶Ð°Ñ ÐÐ°ÑÐž ÑÐŸÐ±ÑÑÐ²ÐµÐœÐœÑÐµ Ð²ÐµÐ±-ÑÑÑÐ°ÐœÐžÑÑ - ÐžÐœÐŸÐ³ÐŽÐ° ÐžÐŒÐµÑÑ ÐŸÑÐŸÐ±ÑÑ Ð²Ð°Ð¶ÐœÐŸÑÑÑ.ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð¿ÐµÑÐµÐœÐµÑÑÐž ÑÐ°ÐºÐžÐµ Ð¿Ð°Ð¿ÐºÐž ÐœÐ° Ð¿ÐµÑÐ²ÑÐ¹ ÑÑÐŸÐ²ÐµÐœÑ ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ³ÐŸ ÐŽÐµÑÐµÐ²Ð°. Ð§ÑÐŸÐ±Ñ ÑÐŽÐµÐ»Ð°ÑÑ ÑÑÐŸ, ÑÐµÐ»ÐºÐœÐžÑÐµ Ð¿ÑÐ°Ð²ÐŸÐ¹ ÐºÐœÐŸÐ¿ÐºÐŸÐ¹ ÐŒÑÑÐž ÐœÐ° Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÐŸÐ¹ Ð¿Ð°Ð¿ÐºÐµ. ÐÑÐ±ÐµÑÐžÑÐµ "Ð¡ÐŸÐ·ÐŽÐ°ÑÑ ÑÐŸÐºÑÐ°ÑÐµÐœÐžÐµ" Ðž Ð²Ð²ÐµÐŽÐžÑÐµ ÐžÐŒÑ ÐŽÐ»Ñ Ð¿Ð°Ð¿ÐºÐž. ÐÐ»Ñ ÑÐŽÐ°Ð»ÐµÐœÐžÑ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÑÐµÐ»ÐºÐœÐžÑÐµ Ð¿ÑÐ°Ð²ÐŸÐ¹ ÐºÐœÐŸÐ¿ÐºÐŸÐ¹ ÐŒÑÑÐž ÐœÐ° Ð¿ÐŸÐŒÐµÑÐµÐœÐœÐŸÐ¹ Ð¿Ð°Ð¿ÐºÐµ Ðž Ð²ÑÐ±ÐµÑÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÑÐŸÐºÑÐ°ÑÐµÐœÐžÑ".</Text>
+</Content>
+</Part>
+<Part id="creating_folders">
+<Title>
+<Text id="288">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ Ð¿Ð°Ð¿ÐŸÐº</Text>
+</Title>
+<Content>
+<Text id="289">ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ "ÐÐ°Ð¿ÐºÐž" Ð² ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐŒ ÐŽÐµÑÐµÐ²Ðµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÑÐŸÐ±Ñ Ð³ÑÑÐ¿Ð¿ÐžÑÐŸÐ²Ð°ÑÑ Ð²ÐŒÐµÑÑÐµ Ðž Ð±ÐŸÐ»ÐµÐµ Ð»ÐµÐ³ÐºÐŸ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑ ÐžÑ
+. ÐÐ°Ð¿ÐºÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð¿ÐŸÐŒÐµÑÐµÐœÑ Ð²ÐœÑÑÑÐž Ð¿Ð°Ð¿ÐŸÐº. Ð€Ð°ÐºÑÐžÑÐµÑÐºÐž ÐœÐµÑ ÐŸÐ³ÑÐ°ÐœÐžÑÐµÐœÐžÑ ÐœÐ° ÑÐŸ,ÑÐºÐŸÐ»ÑÐºÐŸ Ð¿Ð°Ð¿ÐŸÐº ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÐŒÐµÑÑ ÐžÐ»Ðž ÐºÐ°Ðº Ð³Ð»ÑÐ±ÐŸÐºÐŸ ÐŸÐœÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð²Ð»ÐŸÐ¶ÐµÐœÑ. </Text>
+<Text id="290">Ð§ÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐœÐŸÐ²ÑÑ Ð¿Ð°Ð¿ÐºÑ, Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐ»ÑÐœÐŸ Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÑÑ Ð¿Ð°Ð¿ÐºÑ Ð² ÐÐµÑÐµÐ²Ðµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° ÐºÐœÐŸÐ¿ÐºÐµ "ÐÐŸÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°". ÐÐŸÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ° Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÐŸÐ³ÐŸ ÐžÐ»Ðž ÐœÐ° Ð²ÑÑÑÐµÐŒ ÑÑÐŸÐ²ÐœÐµ,ÐµÑÐ»Ðž ÐœÐž ÐŸÐŽÐœÐ° ÐœÐµ ÐŸÑÐŸÐ±ÑÐ°ÐœÐ°.ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ Ð¿ÑÐŸÑÐ²ÐŸÐžÑÑ Ð¿Ð°Ð¿ÐºÐµ ÐžÐŒÑ (Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ "ÐÐŸÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°").</Text>
+<Text id="291">ÐÐ°Ð¿ÐºÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐ°ÐºÐ¶Ðµ ÑÐŸÐ·ÐŽÐ°ÐœÑ ÑÐµÐ»ÑÐºÐŸÐŒ Ð¿ÑÐ°Ð²ÐŸÐ¹ ÐºÐœÐŸÐ¿ÐºÐž ÐŒÑÑÐž Ð¿ÐŸ Ð¿Ð°Ð¿ÐºÐµ,Ð²ÑÐ±ÐžÑÐ°Ñ "ÐÐŸÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°" Ðž ÐŽÐµÐ¹ÑÑÐ²ÑÑ,ÐºÐ°Ðº ÑÐºÐ°Ð·Ð·Ð°ÐœÐŸ Ð²ÑÑÐµ.</Text>
+</Content>
+</Part>
+<Part id="adding_files">
+<Title>
+<Text id="292">ÐÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÐµ ÑÐ°Ð¹Ð»ÐŸÐ²</Text>
+</Title>
+<Content>
+<Text id="293">Ð€Ð°Ð¹Ð»Ñ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÑ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐŒÑÑÑÑ Ð¿ÑÑÐµÐŒ ÐžÑ
+ Ð¿ÐµÑÐµÑÑÐ³ÐžÐ²Ð°ÐœÐžÑ Ðž ÐŸÑÐ¿ÑÑÐºÐ°ÐœÐžÑ. Ð£ÐºÐ°Ð·Ð°ÑÐµÐ»Ñ ÐŒÑÑÐž ÐŸÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑÑÑ ÐœÐ°ÐŽ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÐŒ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐŒ ÐžÐ»Ðž, ÐµÑÐ»Ðž Ð²ÑÐ±ÐžÑÐ°ÐµÑÑÑ Ð±ÐŸÐ»ÑÑÐµ,ÑÐµÐŒ ÐŸÐŽÐžÐœ,ÐœÐ°ÐŽ ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÐŒÐž. ÐÑÐŸÐ¿ÑÑÑÐžÑÐµ Ð²ÑÐ±ÑÐ°ÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» Ð² ÐÐµÑÐµÐ²ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÑÐŸÐ±Ñ Ð·ÐŽÐµÑÑ ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÑÑ ÑÐ°Ð¹Ð»Ñ (ÐµÑÐ»Ðž ÐžÑÑÐŸÑÐœÐžÐºÐŸÐŒ Ð±ÑÐ»ÐŸ ÐÐµÑÐµÐ²ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž).</Text>
+<Text id="294">ÐÑÐž ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÐžÐž ÐŒÐœÐŸÐ¶ÐµÑÑÐ²ÐµÐœÐœÑÑ
+(ÑÐŸÑÑÐ°Ð²ÐœÑÑ
+) ÑÐ°Ð¹Ð»ÐŸÐ²,Ð²ÑÐµ ÐŸÐœÐž Ð¿ÐµÑÐµÐŒÐµÑÐ°ÑÑÑÑ Ð² ÑÐµÐ»ÐµÐ²ÑÑ Ð¿Ð°Ð¿ÐºÑ ÐœÐ° ÑÐŸÑ Ð¶Ðµ ÑÐ°ÐŒÑÐ¹ ÑÑÐŸÐ²ÐµÐœÑ,ÐœÐµÐ·Ð°Ð²ÐžÑÐžÐŒÐŸ ÐŸÑ ÑÑÑÑÐºÑÑÑÑ Ð¿Ð°Ð¿ÐºÐž,ÐºÐŸÑÐŸÑÑÑ ÐŸÐœÐž Ð·Ð°ÐœÐžÐŒÐ°Ð»Ðž Ð¿ÐµÑÐ²ÐŸÐœÐ°ÑÐ°Ð»ÑÐœÐŸ. ÐÐŸÐ³ÐŽÐ° ÐÑ ÐºÐŸÐ¿ÐžÑÑÐµÑÐµ Ð²ÑÐŸÑÐŸÐ¹ ÑÐ°Ð¹Ð» Ñ ÑÐµÐŒ Ð¶Ðµ ÑÐ°ÐŒÑÐŒ ÐžÐŒÐµÐœÐµÐŒ Ð² ÑÑ Ð¶Ðµ ÑÐ°ÐŒÑÑ Ð¿Ð°Ð¿ÐºÑ, ÐÐ°Ñ Ð·Ð°Ð¿ÑÐŸÑÑÑ, Ð·Ð°ÑÐµÑÐµÑÑ Ð»Ðž Ð¿ÐµÑÐ²ÑÐ¹. ÐÑÐ²ÐµÑÑÑÐµ "ÐÐµÑ" Ðž ÑÑÐŸÑ ÑÐ°Ð¹Ð» ÐœÐµ Ð±ÑÐŽÐµÑ ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÑÑÑÑ,ÐœÐŸ ÐŽÑÑÐ³ÐžÐµ Ð±ÑÐŽÑÑ. Ð§ÑÐŸÐ±Ñ ÐŸÑÐŒÐµÐœÐžÑÑ Ð²ÑÐµ ÐŸÑÑÐ°ÑÑÐžÐµÑÑ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ Ð¿ÐŸ ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÐžÑ,ÑÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° ÐºÐœÐŸÐ¿ÐºÐµ "Ð¡ÑÐŸÐ¿".</Text>
+<Text id="295">Ð¢ÐŸÐ»ÑÐºÐŸ "ÑÐ°ÐŒÑÐµ Ð²ÑÑÐŸÐºÐžÐµ"ÐžÐ· ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² Ð±ÑÐŽÑÑ Ð¿ÐµÑÐµÐŒÐµÑÐµÐœÑ. ÐÐ°Ð¿ÐºÐ° Ð²ÑÑÐµ, ÑÐµÐŒ ÐµÑ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐœÑÐµ. ÐÑ ÐœÐµ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ ÑÐ°Ð¹Ð»Ñ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ Ð¿Ð°Ð¿ÐºÐž,Ð° ÑÐ°ÐºÐ¶Ðµ ÑÐ°ÐŒÑ Ð¿Ð°Ð¿ÐºÑ ÐœÐµÐ¿ÐŸÑÑÐµÐŽÑÑÐ²ÐµÐœÐœÐŸ.</Text>
+<Text id="296">ÐÐŸÐ³ÐŽÐ° ÐÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÐµ ÑÐ°Ð¹Ð», ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑ Ð¿ÐŸÐžÑÐº Ð² ÐžÑÑ
+ÐŸÐŽÐœÑÑ
+ Ð¿Ð°Ð¿ÐºÐ°Ñ
+ Ð²ÑÐ¿ÐŸÐŒÐŸÐ³Ð°ÑÐµÐ»ÑÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ², ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐžÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ Ðº ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÐŒÐŸÐŒÑ ÑÐ°Ð¹Ð»Ñ,Ðž ÐµÑÐ»Ðž ÐŸÐœ ÐœÐ°Ñ
+ÐŸÐŽÐžÑ ÐµÐ³ÐŸ,ÑÐŸ ÐœÐ°ÑÐžÐœÐ°ÐµÑ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÑÑÐž ÐŽÐ°ÐœÐœÑÐµ. ÐÑÐ»Ðž Ð¿ÑÐŸÑÐµÑÑ Ð¿ÑÐŸÐŽÐŸÐ»Ð¶Ð°ÐµÑÑÑ,ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð±ÑÑÑ Ð·Ð°Ð¿ÑÐŸÑÐµÐœÑ (Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÐ°Ð·) ÐŸ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž,ÑÑÐŸÐ±Ñ ÐŽÐŸÑÑÐžÑÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÑ ÐžÐŒÐ¿ÐŸÑÑÐžÑÑÐµÐŒÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ñ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž,ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐœÑÐŒÐž Ð² ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð­ÑÐŸÑ Ð¿ÑÐŸÑÐµÑÑ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÐŒÐœÐŸÐ³ÐžÐµ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ Ð·Ð°Ð¿ÑÐŸÑÑ, ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÐµ Ð² ÑÐ°Ð·ÐŽÐµÐ»ÐµÐÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+.ÐÐ»Ñ Ð±ÐŸÐ»ÐµÐµ ÐŽÐµÑÐ°Ð»ÑÐœÐŸÐ³ÐŸ ÐŸÐ±ÑÑÑÐœÐµÐœÐžÑ Ð°ÑÑÐŸÑÐžÐžÑÐŸÐ²Ð°ÐœÐœÑÑ
+ Ñ ÑÐ°Ð¹Ð»Ð°ÐŒÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÑÐžÑÐ°Ð¹ÑÐµ ÐÐ»Ð°Ð²Ñ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone - ÐÐ·Ð²Ð»ÐµÑÐµÐœÐžÐµ Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²Ð° Ð²Ð°ÑÐžÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². </Text>
+</Content>
+</Part>
+<Part id="removing_files">
+<Title>
+<Text id="297">Ð£ÐŽÐ°Ð»ÐµÐœÐžÐµ ÑÐ°Ð¹Ð»ÐŸÐ²</Text>
+</Title>
+<Content>
+<Text id="298">Ð¡ÑÑÐµÑÑÐ²ÑÐµÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐŒÐµÑÐŸÐŽÐŸÐ² ÑÐŽÐ°Ð»ÐµÐœÐžÑ ÑÐ°Ð¹Ð»ÐŸÐ² Ðž Ð¿Ð°Ð¿ÐŸÐº. ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ ÑÐœÐ°ÑÐ°Ð»Ð° ÑÐºÐ°Ð·Ð°ÑÑ,ÐºÐ°ÐºÐžÐµ ÐžÐ· ÐœÐžÑ
+ ÑÐŽÐ°Ð»ÑÑÑ, Ð²ÑÐ±ÐžÑÐ°Ñ ÐŸÐŽÐžÐœ ÐžÐ»Ðž Ð±ÐŸÐ»ÐµÐµ ÑÐ°Ð¹Ð»ÐŸÐ² Ðž Ð¿Ð°Ð¿ÐŸÐº, ÐºÐ°Ðº ÐŸÐ¿ÐžÑÐ°ÐœÐŸ Ð² ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐœÐ°ÐºÐŸÐ¿Ð»ÐµÐœÐžÐ¹.</Text>
+<Text id="299">ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÑÐ°Ð¹Ð»Ñ ÐŸÑÐŸÐ±ÑÐ°ÐœÑ, ÐŽÐ»Ñ ÐžÑ
+ ÑÐŽÐ°Ð»ÐµÐœÐžÑ ÑÐµÐ»ÐºÐ°ÑÑ ÐºÐœÐŸÐ¿ÐºÑ "Ð£ÐŽÐ°Ð»ÐžÑÑ"ÐžÐ»Ðž ÐœÐ°Ð¶ÐžÐŒÐ°ÑÑ ÐºÐºÐ»Ð°Ð²ÐžÑÑ [Ð£ÐŽÐ°Ð»ÐžÑÑ] ÐœÐ° ÐºÐ»Ð°Ð²ÐžÐ°ÑÑÑÐµ, ÐžÐ»Ðž Ð¶Ðµ ÑÑÐœÑÑ ÐžÑ
+ ÐžÐ· ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŽÐŸ ÐºÐœÐŸÐ¿ÐºÐž "Ð£ÐŽÐ°Ð»ÐžÑÑ" Ðž ÑÐ°ÐŒ ÐŸÑÐ¿ÑÑÐºÐ°ÑÑ.</Text>
+</Content>
+</Part>
+<Part id="filtering_the_tree">
+<Title>
+<Text id="300">Ð€ÐžÐ»ÑÑÑÐŸÐ²Ð°ÐœÐžÐµ ÐŽÐµÑÐµÐ²Ð°</Text>
+</Title>
+<Content>
+<Text id="301">"Ð€ÐžÐ»ÑÑÑÐŸÐ²Ð°ÐœÐžÐµ" ÐŽÐµÑÐµÐ²Ð° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐÐ°ÐŒ ÑÑÐ¶Ð°ÑÑ Ð¿ÐŸÐžÑÐº ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ².</Text>
+<Text id="302">ÐÑÐœÐºÑ "ÐÐŸÐºÐ°Ð·Ð°ÑÑ ÑÐ°Ð¹Ð»Ñ" Ð² ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐŒ ÐŒÐµÐœÑ Ð¿ÐŸÐŽ ÐºÐ°Ð¶ÐŽÑÐŒ ÐŽÐµÑÐµÐ²ÐŸÐŒ Ð²ÑÐ²ÐŸÐŽÐžÑ ÑÐ¿ÐžÑÐŸÐº Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÑÑ
+ ÑÐžÐ»ÑÑÑÐŸÐ² ÑÐžÐ¿Ð° "Images".ÐÑÐ±ÐµÑÐžÑÐµ Ðž Ð²ÑÐµ Ð²ÑÐµÐŒÐµÐœÐœÐŸ ÑÐºÑÑÑÑÐµ ÑÐ°Ð¹Ð»Ñ Ð² ÐŽÐµÑÐµÐ²Ðµ.Ð§ÑÐŸÐ±Ñ Ð²ÐŸÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐŽÐµÑÐµÐ²ÐŸ,Ð·Ð°ÐŒÐµÐœÐžÑÐµ ÑÐžÐ»ÑÑÑ ÑÐœÐŸÐ²Ð° ÐœÐ° "ÐÑÐµ ÑÐ°Ð¹Ð»Ñ".Ð­ÑÐž ÐŽÐµÐ¹ÑÑÐ²ÐžÑ ÐœÐµ ÐžÐ·ÐŒÐµÐœÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð¿ÑÐž ÑÑÐŸÐŒ ÐŸÐœÐž ÐœÐµ Ð·Ð°ÑÑÐ°Ð³ÐžÐ²Ð°ÑÑ Ð¿Ð°Ð¿ÐºÐž Ð² ÐŽÐµÑÐµÐ²Ðµ.</Text>
+<Text id="303">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð·Ð°ÐŽÐ°ÑÑ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÑ ÑÐžÐ»ÑÑÑÐ°,ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð² Ð² ÑÑ
+ÐµÐŒÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐµ ÑÐ°Ð¹Ð»ÐŸÐ² (Ð¢ÐŸÐ»ÑÐºÐŸ ÐŽÐ»Ñ ÑÐµÐ¶ÐžÐŒÐŸÐ² Ð¡Ð¿ÐµÑÐžÐ°Ð»ÐžÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÑ
+ Ð¡ÐžÑÑÐµÐŒ Ðž Ð­ÐºÑÐ¿ÐµÑÑ).ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐµ Ð°Ð±Ð±ÑÐµÐ²ÐžÐ°ÑÑÑÑ ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ¹ ÑÐžÑÑÐµÐŒÑ ÑÐžÐ¿Ð° "*.*" ÐžÐ»Ðž "*.doc" ("*" ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ Ð»ÑÐ±ÑÐŒ ÑÐžÐŒÐ²ÐŸÐ»Ð°ÐŒ).</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="enriching_the_collection_with_metadata">
+<Title>
+<Text id="304">ÐÐ±ÐŸÐ³Ð°ÑÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž</Text>
+</Title>
+<Content>
+<Text id="305">ÐÐŒÐµÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐœÐ°ÐºÐŸÐ¿Ð»ÐµÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž,ÐœÐ°Ð¿ÐŸÐ»ÐœÐžÑÐµ ÐžÑ
+ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐµÐ¹,ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÐŸÐ¹ "ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ".Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ, ÐºÐ°Ðº ÑÐŸÐ·ÐŽÐ°ÑÑÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ,ÐºÐ°Ðº ÐŸÐœÐž ÑÐµÐŽÐ°ÐºÑÐžÑÑÑÑÑÑ, ÐœÐ°Ð·ÐœÐ°ÑÐ°ÑÑÑÑ Ðž Ð²ÐŸÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÑÑÑÑ,Ð° ÑÐ°ÐºÐ¶Ðµ ÐºÐ°Ðº ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ Ð²ÐœÐµÑÐœÐžÐµ ÐžÑÑÐŸÑÐœÐžÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ (ÑÐ°ÐºÐ¶Ðµ ÑÐŒ.ÐÐ»Ð°Ð²Ñ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone - ÐÐŸÐ»ÑÑÐµÐœÐžÐµ Ð±ÐŸÐ»ÑÑÐµÐ¹ ÑÐ°ÑÑÐž ÐžÐ· Ð²Ð°ÑÐžÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²).</Text>
+<Part id="the_enrich_view">
+<Title>
+<Text id="306">ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐŸÐ±ÐŸÐ³Ð°ÑÐµÐœÐžÑ</Text>
+</Title>
+<Content>
+<Text id="307">ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐŸÐ±ÐŸÐ³Ð°ÑÐµÐœÐžÑ ÐŽÐ»Ñ Ð·Ð°ÐŽÐ°ÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ - ÑÑÐŸ ÐŽÐ°ÐœÐœÑÐµ ÐŸ ÐŽÐ°ÐœÐœÑÑ
+ - ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ,ÐÐ²ÑÐŸÑ,ÐÐ°ÑÐ° ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ Ðž Ñ.ÐŽ. ÐÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ - ÑÑÐŸ ÐŽÐ°ÐœÐœÑÐµ ÐŸ ÐŽÐ°ÐœÐœÑÑ
+, ÐŸÐ±ÑÑÐœÐŸ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ, Ð°Ð²ÑÐŸÑ, ÐŽÐ°ÑÐ° ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ðž.Ñ.Ð¿. ÐÐ°Ð¶ÐŽÑÐ¹ Ð¿ÑÐµÐŽÐŒÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÑÐŸÑÑÐŸÐžÑ ÐžÐ· ÐŽÐ²ÑÑ
+ ÑÐ°ÑÑÐµÐ¹: "ÑÐ»ÐµÐŒÐµÐœÑ" ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ, ÐºÐ°ÐºÐŸÐ¹ Ð¿ÑÐµÐŽÐŒÐµÑ ÐžÐŒÐµÐµÑÑÑ Ð²Ð²ÐžÐŽÑ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, Ð°Ð²ÑÐŸÑ), Ð° "Ð·ÐœÐ°ÑÐµÐœÐžÐµ" Ð¿ÑÐžÑÐ²Ð°ÐžÐ²Ð°ÐµÑ ÑÑÐŸÐŒÑ ÑÐ»ÐµÐŒÐµÐœÑÑ ÐµÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐžÐŒÑ Ð°Ð²ÑÐŸÑÐ°).</Text>
+<Text id="308">Ð "ÑÐ°ÑÑÐžÑÐµÐœÐœÐŸÐŒ" Ð²ÐžÐŽÐµ ÑÐ»ÐµÐ²Ð° ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÐÐµÑÐµÐ²ÐŸ ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐ¿ÑÐ°Ð²Ð° Ð¢Ð°Ð±Ð»ÐžÑÐ° ÐÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÐºÐŸÑÐŸÑÐ°Ñ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ Ð²ÑÐ±ÑÐ°ÐœÐœÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð° ÐžÐ»Ðž Ð¿Ð°Ð¿ÐºÐž ÐžÐ· ÐÐµÑÐµÐ²Ð° ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð¡ÑÐŸÐ»Ð±ÑÑ ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÑ ÑÐµÑÑÐŒ ÑÐ²ÐµÑÐŸÐŒ Ð²Ð²ÐµÑÑ
+Ñ Ðž ÐžÑ
+ ÑÐ°Ð·ÐŒÐµÑ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐžÐ·ÐŒÐµÐœÑÐœ Ð¿ÑÑÑÐŒ Ð¿ÐµÑÐµÐŽÐ²ÐžÐ¶ÐµÐœÐžÑ Ð»ÐžÐœÐžÐž ÑÐ°Ð·ÐŽÐµÐ»Ð°. ÐÐ°Ð¶Ð°Ð² ÐœÐ° Ð»ÑÐ±ÐŸÐ¹ ÑÑÐŽ Ð² ÑÐ°Ð±Ð»ÐžÑÐµ, Ð²Ñ ÑÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ Ðž ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐŽÐµÑÐ°Ð»Ðž ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+ Ð² ÐœÐžÐ¶ÐœÐµÐ¹ ÑÐµÐºÑÐžÐž ÐŸÐºÐœÐ°. Ð§ÐµÑÐœÑÐ¹ ÑÐµÐºÑÑ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ, ÑÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÑÐ²Ð»ÑÐµÑÑÑ ÐŸÐ±ÑÐžÐŒ ÐŽÐ»Ñ Ð²ÑÐµÑ
+ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ²,ÑÐŸÐ³ÐŽÐ° ÐºÐ°Ðº ÑÐµÑÑÐ¹ ÑÐµÐºÑÑ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ,ÑÑÐŸ ÑÑÐŸ - ÐœÐµ ÑÐ°Ðº.Ð§ÐµÑÐœÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŸÐ±ÐœÐŸÐ²Ð»ÐµÐœÑ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÐµÐœÑ, Ð² ÑÐŸ Ð²ÑÐµÐŒÑ ÐºÐ°Ðº ÑÐµÑÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐŽÐ°Ð»ÐµÐœÑ ÐžÐ· ÑÐµÑ
+,ÐºÐŸÑÐŸÑÑÐµ ÐžÐŒÐµÑÑ ÐžÑ
+,ÐžÐ»Ðž ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÑ Ðº ÐŽÑÑÐ³ÐžÐŒ.</Text>
+<Text id="309">ÐÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ Ð¿Ð°Ð¿ÐºÐž ÐŒÐŸÐ¶ÐµÑ Ð¿ÐŸÑÐ²Ð»ÑÑÑÑÑ ÐŸÐºÐŸÐ»ÐŸ ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ Ð²Ñ
+ÐŸÐŽÐŸÐ² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+.Ð­ÑÐŸ ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐœÐ° ÑÐŸ,ÑÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÑÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÑ ÐŸÑ Ð¿Ð°Ð¿ÐŸÐº ÑÐŸÐŽÐžÑÐµÐ»ÐµÐ¹ (ÐžÐ»Ðž Ð¿ÑÐµÐŽÐºÐŸÐ²). Ð£ÐœÐ°ÑÐ»ÐµÐŽÐŸÐ²Ð°ÐœÐœÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐœÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÑ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÐµÐœÑ, Ð° ÑÐŸÐ»ÑÐºÐŸ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÑ Ð² ÐºÐŸÐœÐµÑ ÑÐ¿ÐžÑÐºÐ° ÐžÐ»Ðž Ð¿ÐµÑÐµÐ¿ÐžÑÐ°ÐœÑ.Ð©ÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐž Ð¿Ð°Ð¿ÐºÐž,ÑÑÐŸÐ±Ñ ÐœÐµÐŒÐµÐŽÐ»ÐµÐœÐœÐŸ Ð¿ÐµÑÐµÐ¹ÑÐž Ð² ÑÑ Ð¿Ð°Ð¿ÐºÑ, Ð³ÐŽÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð·Ð°ÐŽÐ°ÐœÑ.</Text>
+<Text id="310">ÐÑÐ±ÐµÑÐžÑÐµ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð² ÑÐ°Ð±Ð»ÐžÑÐµ, ÑÑÐŸÐ±Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ° Ð² ÐŸÐ±Ð»Ð°ÑÑÐž "Ð¡ÑÑÐµÑÑÐ²ÑÑÑÐžÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŽÐ»Ñ ...", ÐœÐ°Ñ
+ÐŸÐŽÑÑÐµÐ¹ÑÑ Ð²ÐœÐžÐ·Ñ ÑÐ°Ð±Ð»ÐžÑÑ. ÐÐµÑÐµÐ²ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ ÐŒÐŸÐ¶ÐµÑ ÑÐ°ÑÑÐžÑÑÑÑÑÑ Ðž ÑÐ°Ð·ÑÑÑÐ°ÑÑÑÑ. ÐÐ±ÑÑÐœÐŸ ÑÑÐŸ - ÑÐ¿ÐžÑÐŸÐº, ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð²ÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ, Ð²Ð²ÐµÐŽÐµÐœÐœÑÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ ÐŽÐ»Ñ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÐŸÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ°. Ð©ÐµÐ»ÑÐŸÐº ÐœÐ° Ð²Ñ
+ÐŸÐŽÐµ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÑÐ°Ð·ÐŒÐµÑÐ°ÐµÑ ÐµÐ³ÐŸ Ð² Ð¿ÐŸÐ»Ðµ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹. Ð¡ ÐŽÑÑÐ³ÐŸÐ¹ ÑÑÐŸÑÐŸÐœÑ,Ð¿ÑÐž ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°ÐœÐœÐŸÐŒ Ð·ÐœÐ°ÑÐµÐœÐžÐž Ð² ÑÐµÐºÑÑÐŸÐ²ÐŸÐŒ Ð¿ÐŸÐ»Ðµ Ð²ÑÐ±ÐŸÑÐºÐž ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² ÐÐµÑÐµÐ²Ð° Ð·ÐœÐ°ÑÐµÐœÐžÐ¹, ÑÐžÑÑÐµÐŒÐ° ÐœÐ°ÑÐžÐœÐ°ÐµÑ ÑÐ°Ð±ÐŸÑÑ Ñ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÐÑ Ð²Ð²ÐµÐ»Ðž. ÐÐ°Ð¶Ð°ÑÐžÐµ [Tab] Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž Ð·Ð°Ð²ÐµÑÑÐ°ÐµÑ Ð¿ÐµÑÐ°ÑÐ°ÐœÐžÐµ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÐŸÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ.</Text>
+<Text id="311">ÐÐœÐ°ÑÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŸÑÐ³Ð°ÐœÐžÐ·ÐŸÐ²Ð°ÐœÑ Ð² ÐžÐµÑÐ°ÑÑ
+ÐžÑ. Ð­ÑÐŸ Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐŸ Ð² ÐÐµÑÐµÐ²Ðµ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Ð¿Ð°Ð¿ÐºÐž ÐŽÐ»Ñ Ð²ÐœÑÑÑÐµÐœÐœÐžÑ
+ ÑÑÐŸÐ²ÐœÐµÐ¹. ÐÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÐžÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð²Ð²ÐµÐŽÐµÐœÑ,ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Ð·ÐœÐ°Ðº "|" ÐŽÐ»Ñ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ ÑÑÐŸÐ²ÐœÐµÐ¹. ÐÐ°Ð¿ÑÐžÐŒÐµÑ,"Cards|Red|Diamonds|Seven" ÐŒÐŸÐ³ Ð±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ Ð² ÐžÐµÑÐ°ÑÑ
+ÐžÐž, Ð¿ÑÐžÐŒÐµÑÐŸÐŒ ÐºÐŸÑÐŸÑÐŸÐ¹ ÑÐ²Ð»ÑÐµÑÑÑ Ð¿Ð°ÐºÐµÑ ÐžÐ³ÑÑ Ð² ÐºÐ°ÑÑÑ.Ð­ÑÐŸ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð³ÑÑÐ¿Ð¿ÐžÑÐŸÐ²Ð°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ Ð²ÐŒÐµÑÑÐµ. ÐÑÑÐ¿Ð¿Ñ ÐŒÐŸÐ³ÑÑ ÑÐ°ÐºÐ¶Ðµ ÐœÐ°Ð·ÐœÐ°ÑÐ°ÑÑÑÑ ÐºÐ°Ðº ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ðº ÑÐ°Ð¹Ð»Ð°ÐŒ.</Text>
+<Text id="312">Greenstone Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÐžÐ·Ð²Ð»ÐµÐºÐ°ÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð² ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÐ»ÐµÐŒÐµÐœÑÑ ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ ÐžÐŒÐµÑÑ Ð¿ÑÐµÑÐžÐºÑ "ex.". Ð­ÑÐŸ ÐœÐµ ÐžÐŒÐµÐµÑ ÐœÐžÐºÐ°ÐºÐŸÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŽÐµÑÐµÐ²Ð° Ðž ÐœÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐŸ.</Text>
+</Content>
+</Part>
+<Part id="selecting_metadata_sets">
+<Title>
+<Text id="313">ÐÑÐ±ÐŸÑ ÐœÐ°Ð±ÐŸÑÐŸÐ² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Text>
+</Title>
+<Content>
+<Text id="314">Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐ° ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ² Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐžÐ·Ð²ÐµÑÑÐœÐ° ÐºÐ°Ðº "ÐœÐ°Ð±ÐŸÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+". ÐÑÐžÐŒÐµÑÐŸÐŒ ÑÐ²Ð»ÑÐµÑÑÑ ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Dublin Core. ÐÐŸÐ³ÐŽÐ° ÐÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÐµ ÐºÐŸÐŒÐ¿Ð»ÐµÐºÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðº ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐŸ ÐµÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÑ ÑÑÐ°ÐœÐŸÐ²ÑÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž ÐŽÐ»Ñ Ð²ÑÐ±ÐŸÑÐ°. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÐŒÐµÑÑ Ð±ÐŸÐ»ÑÑÐµ,ÑÐµÐŒ ÐŸÐŽÐžÐœ ÐœÐ°Ð±ÐŸÑ. ÐÐ»Ñ Ð¿ÑÐµÐŽÐŸÑÐ²ÑÐ°ÑÐµÐœÐžÑ ÑÑÐŸÐ»ÐºÐœÐŸÐ²ÐµÐœÐžÑ ÐŸÐŽÐžÐœÐ°ÐºÐŸÐ²ÑÑ
+ ÐžÐŒÑÐœ Ðº ÐœÐ°Ð·Ð²Ð°ÐœÐžÑ ÑÐ»ÐµÐŒÐµÐœÑÐ° Ð¿ÑÐžÑÐŸÐµÐŽÐžÐœÑÐµÑÑÑ ÐºÐŸÑÐŸÑÐºÐžÐ¹ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐŸÑ,ÐºÐŸÑÐŸÑÑÐ¹ Ð²ÑÐŽÐµÐ»ÑÐµÑ ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÑÐ»ÐµÐŒÐµÐœÑ Dublin Core "Creator" ÑÑÐ°ÐœÐµÑ "dc.Creator".ÐÐ°Ð±ÐŸÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ñ
+ÑÐ°ÐœÑÑÑÑ Ð² ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° Ðž ÐžÐŒÐµÑÑ ÑÑÑÑÐžÐºÑ ".mds". </Text>
+<Text id="315">Ð§ÑÐŸÐ±Ñ ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÐŸÐ²Ð°ÑÑ ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÑ
+ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð²ÑÐ±ÐµÑÐžÑÐµ "ÐÐ°Ð±ÐŸÑ ÐÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+" Ð² Ð¿ÑÐŸÑÐŒÐŸÑÑÐµ "ÐÐžÐ·Ð°Ð¹Ðœ".</Text>
+</Content>
+</Part>
+<Part id="appending_new_metadata">
+<Title>
+<Text id="316">ÐÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Text>
+</Title>
+<Content>
+<Text id="317">Ð¢ÐµÐ¿ÐµÑÑ ÐŒÑ ÐŽÐŸÐ±Ð°Ð²ÐžÐŒ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ - Ðž ÑÐ°ÐŒ ÑÐ»ÐµÐŒÐµÐœÑ,Ðž ÐµÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ - Ðº ÑÐ°Ð¹Ð»Ñ. Ð¡ÐœÐ°ÑÐ°Ð»Ð° Ð²ÑÐ±ÐµÑÐµÐŒ ÑÐ°Ð¹Ð» ÐžÐ· ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ³ÐŸ ÐŽÐµÑÐµÐ²Ð° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.Ð¢Ð°ÐºÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ Ð²ÑÐ·ÑÐ²Ð°ÐµÑ Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÐµ Ð»ÑÐ±ÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ ÑÐ²ÑÐ·Ð°ÐœÐœÑÑ
+ Ñ ÑÑÐžÐŒ ÑÐ°Ð¹Ð»ÐŸÐŒ,Ð² ÑÐ°Ð±Ð»ÐžÑÐµ ÑÐ¿ÑÐ°Ð²Ð°.</Text>
+<Text id="318">ÐÐ°ÑÐµÐŒ Ð²ÑÐ±ÐµÑÐµÐŒ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,ÐºÐŸÑÐŸÑÑÐ¹ Ñ
+ÐŸÑÐžÐŒ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ,Ð¿ÑÑÐµÐŒ ÑÐµÐ»ÑÐºÐ° ÑÑÐŽÐŸÐŒ Ñ ÐœÐžÐŒ Ð² ÑÐ°Ð±Ð»ÐžÑÐµ.</Text>
+<Text id="319">ÐÐ¿ÐžÑÐžÑÐµ ÑÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ð² Ð¿ÐŸÐ»Ðµ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ Ð·ÐœÐ°Ðº "|", ÑÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÑÑÑÑÐºÑÑÑÑ, ÐºÐ°Ðº ÐŸÐ¿ÐžÑÐ°ÐœÐŸ Ð² ÑÐµÐºÑÐžÐž Ð Ð°ÑÑÐžÑÐžÑÑ ÐÐžÐŽ. ÐÐ°Ð¶Ð°Ð² ÐºÐ»Ð°Ð²ÐžÑÐž [ÐÐ²ÐµÑÑ
+] ÐžÐ»Ðž [ÐÐœÐžÐ·], ÐÑ ÑÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ ÑÑÐµÐ±ÑÐµÐŒÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ. ÐÐ°Ð¶Ð°Ð² ÐºÐ»Ð°Ð²ÐžÑÑ [Enter], ÐÑ ÑÐŒÐŸÐ¶ÐµÑÐµ ÑÐŸÑ
+ÑÐ°ÐœÐžÑÑ Ð²ÑÐ±ÑÐ°ÐœÐœÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðž ÑÐŸÐ·ÐŽÐ°ÑÑ ÐœÐŸÐ²ÐŸÐµ ÐœÐµÐ·Ð°Ð¿ÐŸÐ»ÐœÐµÐœÐœÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŽÐ»Ñ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, Ð¿ÐŸÐ·Ð²ÐŸÐ»ÐžÐ² ÐÐ°ÐŒ ÐŸÐ¿ÑÐµÐŽÐžÐ»ÐžÑÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ ÐŽÐ»Ñ ÐŸÐŽÐœÐŸÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ°.</Text>
+<Text id="320">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐ°ÐºÐ¶Ðµ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ðº Ð¿Ð°Ð¿ÐºÐµ ÐžÐ»Ðž ÑÑÐ°Ð·Ñ Ðº ÐœÐµÐºÐŸÑÐŸÑÐŸÐŒÑ ÐŒÐœÐŸÐ¶ÐµÑÑÐ²Ñ ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ². Ð­ÑÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÑÑ ÐºÐŸ Ð²ÑÐµÐŒ ÑÐ°Ð¹Ð»Ð°ÐŒ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ Ð¿Ð°Ð¿ÐºÐž ÐžÐ»Ðž Ðº ÐŸÑÐŸÐ±ÑÐ°ÐœÐœÑÐŒ Ðž Ðº Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐœÑÐŒ Ð¿Ð°Ð¿ÐºÐ°ÐŒ. ÐÐŒÐµÐ¹ÑÐµ Ð² Ð²ÐžÐŽÑ,ÑÑÐŸ ÐµÑÐ»Ðž ÐÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÐ»Ðž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ðº Ð¿Ð°Ð¿ÐºÐµ, ÑÐŸ Ð»ÑÐ±ÑÐµ ÐœÐŸÐ²ÑÐµ ÑÐ°Ð¹Ð»Ñ Ð² ÐœÐµÐ¹ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÑÐœÐ°ÑÐ»ÐµÐŽÑÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐžÐ· ÑÑÐŸÐ¹ Ð¿Ð°Ð¿ÐºÐž.</Text>
+</Content>
+</Part>
+<Part id="adding_previously_defined_metadata">
+<Title>
+<Text id="321">ÐÐŸÐ±Ð°Ð²Ð»ÐœÐžÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Text>
+</Title>
+<Content>
+<Text id="322">Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŽÐµÑÐ¶Ð°Ñ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ, ÑÐœÐ°ÑÐ°Ð»Ð° Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÐ°Ð¹Ð», Ð·Ð°ÑÐµÐŒ ÑÑÐµÐ±ÑÐµÐŒÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐžÐ· ÐŽÐµÑÐµÐ²Ð° Ð·ÐœÐ°ÑÐµÐœÐžÐ¹, ÑÐ°ÑÑÐžÑÑÑ Ð¿Ð°Ð¿ÐºÐž ÐžÐµÑÐ°ÑÑ
+ÐžÐž Ð¿ÐŸ ÐŒÐµÑÐµ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÐž. ÐÑÐ±ÑÐ°ÐœÐœÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ Ð² Ð¿ÐŸÐ»Ðµ ÑÐµÐºÑÑÐ° (Ð°Ð»ÑÑÐµÑÐœÐ°ÑÐžÐ²ÐœÐŸ ÐŒÐŸÐ¶ÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð°Ð²ÑÐŸÐ²ÑÐ±ÐŸÑ Ð² ÐŽÐµÑÐµÐ²Ðµ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ Ðž ÑÑÐµÐŽÑÑÐ² Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐŸÐ³ÐŸ Ð·Ð°Ð²ÐµÑÑÐµÐœÐžÑ).</Text>
+<Text id="323">ÐÑÐŸÑÐµÑÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ñ ÑÐ¶Ðµ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐŒÐž Ð·ÐœÐ°ÑÐµÐœÐžÑÐŒÐž Ðº Ð¿Ð°Ð¿ÐºÐ°ÐŒ ÐžÐ»Ðž ÐŒÐœÐŸÐ¶ÐµÑÑÐ²Ñ ÑÐ°Ð¹Ð»ÐŸÐ² ÑÐ°ÐºÐŸÐ¹ Ð¶Ðµ.</Text>
+</Content>
+</Part>
+<Part id="editing_or_removing_metadata">
+<Title>
+<Text id="324">ÐÐ·ÐŒÐµÐœÐžÑÑ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÐžÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ</Text>
+</Title>
+<Content>
+<Text id="325">Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÐžÑÑ ÑÐ°ÑÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÐœÐ°ÑÐ°Ð»Ð° Ð²ÑÐ±ÐµÑÐžÑÐµ Ð¿ÐŸÐŽÑ
+ÐŸÐŽÑÑÐžÐ¹ ÑÐ°Ð¹Ð», Ð° Ð¿ÐŸÑÐŸÐŒ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð² ÑÐ°Ð»Ð±ÐžÑÑ. Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÐŽÐ°Ð»ÐžÑÐµ ÑÐµÐºÑÑ ÐµÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÑ.</Text>
+<Text id="326">ÐÑÐŸÑÐµÑÑ ÐŸÐ±ÐœÐŸÐ²Ð»ÐµÐœÐžÑ ÐŽÐ°ÐœÐœÑÑ
+ Ð¿Ð°Ð¿ÐºÐž Ñ Ð¿ÐŸÐŽÐ¿Ð°Ð¿ÐºÐ°ÐŒÐž ÐžÐ»Ðž ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² ÑÐŸÑ Ð¶Ðµ ÑÐ°ÐŒÑÐ¹, ÐœÐŸ Ð²Ñ ÑÐŒÐŸÐ¶ÐµÑÐµ ÐŸÐ±ÐœÐŸÐ²ÐžÑÑ ÑÐŸÐ»ÑÐºÐŸ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÐµ, ÐŸÐ±ÑÐžÐµ ÐŽÐ»Ñ Ð²ÑÐµÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ²/Ð¿Ð°Ð¿ÐŸÐº.</Text>
+<Text id="327">ÐÐµÑÐµÐ²ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð²ÑÐµ ÑÐµÐºÑÑÐžÐµ Ð¿ÑÐžÐ·ÐœÐ°ÑÐµÐœÐœÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ, Ð° ÑÐ°ÐºÐ¶Ðµ Ð²ÑÐµ Ð¿ÑÐµÐŽÑÐŽÑÑÐžÐµ ÐžÐ· ÑÐµÐºÑÑÐµÐ³ÐŸ ÑÐµÐ°ÐœÑÐ°, ÑÐ°Ðº ÑÑÐŸ ÐžÐ·ÐŒÐµÐœÐµÐœÐœÑÐµ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÐµÐœÐœÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŸÑÑÐ°ÑÑÑÑ Ð² ÐŽÐµÑÐµÐ²Ðµ. ÐÐ°ÐºÑÑÐ² Ðž Ð²ÐœÐŸÐ²Ñ ÐŸÑÐºÑÑÐ² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐÑ ÑÐŽÐ°Ð»ÐžÑÐµ Ð²ÑÐµ ÑÐ°ÐœÐµÐµ Ð¿ÑÐžÐ·ÐœÐ°ÑÐµÐœÐœÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ.</Text>
+</Content>
+</Part>
+<Part id="reviewing_assigned_metadata">
+<Title>
+<Text id="328">ÐÑÐŸÑÐŒÐŸÑÑ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Text>
+</Title>
+<Content>
+<Text id="329">ÐÐœÐŸÐ³ÐŽÐ° ÐÐ°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ,Ð·Ð°ÐŽÐ°ÐœÐœÑÐµ ÐŽÐ»Ñ ÐŒÐœÐŸÐ³ÐžÑ
+ ÐžÐ»Ðž Ð²ÑÐµÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² ÑÑÐ°Ð·Ñ - ÐœÐ°Ð¿ÑÐžÐŒÐµÑ,ÑÑÐŸÐ±Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ,ÑÐºÐŸÐ»ÑÐºÐŸ ÑÐ°Ð¹Ð»ÐŸÐ² ÐŸÑÑÐ°ÑÑÑÑ ÐŽÐ»Ñ Ð²ÐŸÐ·ÐŽÐµÐ¹ÑÑÐ²ÐžÑ ÐžÐ»Ðž Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÐžÐŽÐµÐž ÐŸÑÐœÐŸÑÐžÑÐµÐ»ÑÐœÐŸ ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÐµÐœÐžÑ ÐŽÐ°ÐœÐœÑÑ
+.</Text>
+<Text id="330">ÐÑÐ±ÐµÑÐžÑÐµ ÑÐ°Ð¹Ð»Ñ, ÐºÐŸÑÐŸÑÑÐµ Ð²Ñ Ñ
+ÐŸÑÐžÑÐµ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ, Ð¿ÐŸÑÐŸÐŒ ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° Ð¿ÑÐ°Ð²ÑÑ ÐºÐœÐŸÐ¿ÐºÑ ÐŒÑÑÐž Ðž Ð²ÑÐ±ÐµÑÐžÑÐµ "ÐÐ°Ð·ÐœÐ°ÑÐµÐœÑÐµ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÐµ...". ÐÐŸÑÐ²Ð»ÑÐµÑÑÑ ÐŸÐºÐœÐŸ,ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÐŸÐµ "ÐÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ", Ð·Ð°ÐœÑÑÐŸÐµ Ð±ÐŸÐ»ÑÑÐŸÐ¹ ÑÐ°Ð±Ð»ÐžÑÐµÐ¹,ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐµÐ¹ ÐŒÐœÐŸÐ³ÐŸ ÐºÐŸÐ»ÐŸÐœÐŸÐº.ÐÐµÑÐ²Ð°Ñ ÐºÐŸÐ»ÐŸÐœÐºÐž Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐžÐŒÐµÐœÐ° ÑÐ°Ð¹Ð»ÐŸÐ²;ÑÑÑÐŸÐºÐž Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÑÑ Ð²ÑÐµ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐ»Ñ ÑÑÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ².</Text>
+<Text id="331">Ð ÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÑÐ°Ð±Ð»ÐžÑÑ ÐŒÐŸÐ¶ÐµÑ Ð·Ð°ÐœÑÑÑ ÐœÐµÐºÐŸÑÐŸÑÐŸÐµ Ð²ÑÐµÐŒÑ,ÐµÑÐ»Ðž Ð²ÑÐ¿Ð°Ð»ÐŸ ÐŒÐœÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»ÐŸÐ².ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÐŽÐŸÐ»Ð¶Ð°ÑÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐŒ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐŸÐŒ Ð¿ÑÐž ÐŸÑÐºÑÑÑÐŸÐŒ ÐŸÐºÐœÐµ "ÐÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ".</Text>
+<Text id="332">ÐÐŸÐ³ÐŽÐ° ÐŸÐœÐ° ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ ÑÐ»ÐžÑÐºÐŸÐŒ Ð±ÐŸÐ»ÑÑÐŸÐ¹,ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐŸÑÑÐžÐ»ÑÑÑÐŸÐ²Ð°ÑÑ ÑÐ°Ð±Ð»ÐžÑÑ "ÐÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ",Ð¿ÑÐžÐŒÐµÐœÑÑ ÑÐžÐ»ÑÑÑÑ Ðº ÐºÐŸÐ»ÐŸÐœÐºÐ°ÐŒ.ÐÐŸÑÐºÐŸÐ»ÑÐºÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÑ ÐœÐŸÐ²ÑÐµ ÑÐžÐ»ÑÑÑÑ, ÑÐŸÐ»ÑÐºÐŸ ÑÐµ ÑÑÑÐŸÐºÐž,ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑ ÐžÐŒ,ÐŸÑÑÐ°ÑÑÑÑ Ð²ÐžÐŽÐžÐŒÑÐŒÐž.Ð§ÑÐŸÐ±Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ,ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐžÐ»Ðž ÐŸÑÐžÑÑÐžÑÑ ÑÐžÐ»ÑÑÑ,ÑÐµÐ»ÐºÐœÐžÑÐµ Ð¿ÐŸ ÐžÐºÐŸÐœÐºÐµ "ÐÐŸÑÐŸÐœÐºÐ°" ÐœÐ°Ð²ÐµÑÑ
+Ñ ÐºÐŸÐ»ÐŸÐœÐºÐž. Ð£ Ð²Ð°Ñ Ð±ÑÐŽÐµÑ Ð·Ð°Ð¿ÑÐŸÑÐµÐœÐ° ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÑÐžÐ»ÑÑÑÐµ. ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÑÐžÐ»ÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ,ÐžÐ·ÐŒÐµÐœÑÐµÑÑÑ ÑÐ²ÐµÑ ÐºÐŸÐ»ÐŸÐœÐºÐž.</Text>
+<Text id="333">ÐÐ°Ð¿ÑÐŸÑ ÐžÐŒÐµÐµÑ ÑÐžÐŒÐ²ÐŸÐ»Ñ "ÐÑÐŸÑÑÐŸÐ¹" Ðž "ÐÑÐŸÐŽÐ²ÐžÐœÑÑÑÐ¹".ÐÑÐŸÑÑÐ°Ñ Ð²ÐµÑÑÐžÑ ÑÐžÐ»ÑÑÑÑÐµÑ ÐºÐŸÐ»ÐŸÐœÐºÐž ÑÐ°Ðº,ÑÑÐŸ ÐŸÐœÐž Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÑÐŸÐ»ÑÐºÐŸ ÑÑÑÐŸÐºÐž, ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŽÐµÑÐ¶Ð°Ñ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ("*" ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ Ð²ÑÐµÐŒ Ð·ÐœÐ°ÑÐµÐœÐžÑÐŒ).ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐžÐ· ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐ³ÐŸ ÑÐ¿ÐžÑÐºÐ°.ÐÑÐŸÐŽÐ²ÐžÐœÑÑÐ°Ñ Ð²ÐµÑÑÐžÑ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð²ÑÐ¿ÐŸÐ»ÐœÑÑÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ:ÐÐŸÐ»Ð¶ÐµÐœ ÐœÐ°ÑÐ°ÑÑÑÑ Ñ,ÐÐµ ÑÐŸÐŽÐµÑÐ¶ÐžÑ,Ð Ð°Ð»ÑÐ°Ð²ÐžÑÐœÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ,ÐÐµÐœÑÑÐµ ÑÐµÐŒ, Ð­ÐºÐ²ÐžÐ²Ð°Ð»ÐµÐœÑÐµÐœ. ÐÐœÐ°ÑÐµÐœÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ Ð±ÑÐŽÐµÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐŸÐ²Ð°ÑÑ, ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐŸ ÑÐ°Ðº,ÑÑÐŸÐ±Ñ Ð±ÑÑÑ Ð»ÑÐ±ÐŸÐ¹ ÑÑÑÐŸÐºÐŸÐ¹,Ð²ÐºÐ»ÑÑÐ°Ñ "*". ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ,ÐŽÐŸÐ»Ð¶ÐœÐŸ Ð»Ðž ÑÑÐŸ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐµ Ð±ÑÑÑ ÐœÐµ ÑÑÐ²ÑÑÐ²ÐžÑÐµÐ»ÑÐœÑÐŒ ÑÐ»ÑÑÐ°ÐµÐŒ. ÐÐ°ÐºÐŸÐœÐµÑ,ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ Ð²ÑÐŸÑÐŸÐµ ÑÑÐ»ÐŸÐ²ÐžÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÑ,ÐºÐŸÑÐŸÑÐŸÐµ ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŽÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÑÐ°ÐœÐ³Ð° Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ (Ð²ÑÐ±ÐžÑÐ°Ñ Ð Ð±ÐŸÐ»ÑÑÐŸÐµ) ÐžÐ»Ðž Ð°Ð»ÑÑÐµÑÐœÐ°ÑÐžÐ²ÐœÑÑ
+ Ð·ÐœÐ°ÑÐµÐœÐžÐ¹ (Ð²ÑÐ±ÐžÑÐ°Ñ ÐÐÐ).ÐÐžÐ¶Ðµ ÑÑÐŸÐ¹ ÐŸÐ±Ð»Ð°ÑÑÐž ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð¿ÐŸÐ»Ðµ, ÐºÐŸÑÐŸÑÐŸÐµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐÐ°ÐŒ ÐžÐ·ÐŒÐµÐœÑÑÑ Ð¿ÐŸÑÑÐŽÐŸÐº ÑÐŸÑÑÐžÑÐŸÐ²ÐºÐž (Ð²ÐŸÐ·ÑÐ°ÑÑÐ°ÑÑÐžÐ¹ ÐžÐ»Ðž Ð¿ÐŸÐœÐžÐ¶Ð°ÑÐžÐ¹ÑÑ).ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐÑ Ð·Ð°ÐºÐŸÐœÑÐžÑÐµ,ÐœÐ°Ð¶ÐŒÐžÑÐµ "Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐ° ÑÐžÐ»ÑÑÑÐ°",ÑÑÐŸÐ±Ñ Ð¿ÑÐžÐŒÐµÐœÐžÑÑ ÐœÐŸÐ²ÑÐ¹ ÑÐžÐ»ÑÑÑ Ðº ÐºÐŸÐ»ÐŸÐœÐºÐµ.ÐÐ°Ð¶ÐŒÐžÑÐµ "ÐÑÐžÑÑÐžÑÑ ÑÐžÐ»ÑÑÑ",ÑÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÑÐµÐºÑÑÐžÐ¹ ÑÐžÐ»ÑÑÑ.ÐÐ±ÑÐ°ÑÐžÑÐµ Ð²ÐœÐžÐŒÐ°ÐœÐžÐµ ÐœÐ° ÑÐŸ,ÑÑÐŸ ÐŽÐµÑÐ°Ð»Ðž ÑÐžÐ»ÑÑÑÐ° ÑÐŸÑ
+ÑÐ°ÐœÑÑÑÑÑ, ÐŽÐ°Ð¶Ðµ ÐºÐŸÐ³ÐŽÐ° ÑÐžÐ»ÑÑÑ ÐŸÑÐžÑÐµÐœ.</Text>
+<Text id="334">ÐÐ°Ð¿ÑÐžÐŒÐµÑ,ÑÑÐŸÐ±Ñ ÐŸÑÑÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÑÐ°Ð±Ð»ÐžÑÑ "ÐÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ",Ð²ÑÐ±ÐµÑÐžÑÐµ ÐºÐŸÐ»ÐŸÐœÐºÑ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÑ ÑÐžÐ»ÑÑÑÐ° Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ (Ð¿ÑÐŸÑÑÐŸÐ¹ ÑÐžÐ»ÑÑÑ ÐœÐ° "*") Ðž Ð²ÐŸÐ·ÑÐ°ÑÑÐ°ÑÑÐžÐ¹ ÐžÐ»Ðž Ð¿ÐŸÐœÐžÐ¶Ð°ÑÑÐžÐ¹ÑÑ Ð¿ÐŸÑÑÐŽÐŸÐº.</Text>
+</Content>
+</Part>
+<Part id="importing_previously_assigned_metadata">
+<Title>
+<Text id="335">ÐÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Text>
+</Title>
+<Content>
+<Text id="336">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÑÐ°ÑÑÐºÐ°Ð·Ð°ÐœÐŸ, ÐºÐ°Ðº ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÐµ ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÐµ ÑÐ°ÐœÑÑÐµ. Ð ÐµÑÑ ÐžÐŽÐµÑ ÐŸ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+, ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐ»Ðž ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÑ Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐ°ÐœÑÑÐµ.</Text>
+<Text id="337">ÐÑÐ»Ðž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð² ÑÐŸÑÐŒÐµ,ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°Ð²Ð°ÐµÐŒÐŸÐ¹ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐŒ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐŸÐŒ,Ð±ÑÐ»Ðž Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÑ ÑÐ°Ð¹Ð»Ñ - ÐœÐ°Ð¿ÑÐžÐŒÐµÑ,ÐºÐŸÐ³ÐŽÐ° ÐÑ Ð²ÑÐ±ÐžÑÐ°ÐµÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÐžÐ· ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Greenstone - ÐŸÐœÐž ÐžÐŒÐ¿ÐŸÑÑÐžÑÑÑÑÑÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž,ÐºÐŸÐ³ÐŽÐ° ÐÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÐµ ÑÐ°Ð¹Ð».Ð§ÑÐŸÐ±Ñ ÑÐŽÐµÐ»Ð°ÑÑ ÑÑÐŸ, ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÑ Ð² ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ°Ñ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,ÐŽÐŸÑÑÑÐ¿ÐœÑÑ
+ Ð² ÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="338">ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð·Ð°Ð¿ÑÐ°ÑÐžÐ²Ð°ÐµÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ.ÐÐ°Ð¿ÑÐŸÑ ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐºÑÐ°ÑÐºÐžÐµ ÐžÐœÑÑÑÑÐºÑÐžÐž Ðž Ð·Ð°ÑÐµÐŒ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐžÐŒÑ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,ÐºÐŸÑÐŸÑÑÐµ ÐžÐŒÐ¿ÐŸÑÑÐžÑÑÑÑÑÑ,ÐºÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐŸÐœ Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ Ð² ÐžÑÑ
+ÐŸÐŽÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ.Ð­ÑÐŸ Ð¿ÐŸÐ»Ðµ ÐœÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐŸ ÐžÐ»Ðž ÐžÐ·ÐŒÐµÐœÐµÐœÐŸ.ÐÐ°ÑÐµÐŒ ÐÑ Ð²ÑÐ±ÐžÑÐ°ÐµÑÐµ,ÐºÐ°ÐºÐžÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐœÐŸÐ²ÐŸÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ° ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÑ,Ð° Ð·Ð°ÑÐµÐŒ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐ¹ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð² ÑÑÐžÑ
+ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ°Ñ
+.Ð¡ÐžÑÑÐµÐŒÐ° Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž Ð²ÑÐ±ÐžÑÐ°ÐµÑ ÑÐ°ÐŒÐŸÐµ Ð±Ð»ÐžÐ·ÐºÐŸÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐµ Ð² ÑÐµÑÐŒÐžÐœÐ°Ñ
+ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ðž ÑÐ»ÐµÐŒÐµÐœÑÐ° ÐŽÐ»Ñ ÐœÐŸÐ²ÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+.</Text>
+<Text id="339">ÐÑÐŸÐ²ÐµÑÐžÐ² ÑÑÐž ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÐžÑ,ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÑÐ°ÑÑ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ",ÑÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐœÐŸÐ²ÑÐ¹ ÑÐ»ÐµÐŒÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ðº Ð²ÑÐ±ÑÐ°ÐœÐœÑÐŒ ÐœÐ°Ð±ÐŸÑÐ°ÐŒ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+.Ð­ÑÐŸ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ ÑÐŸÐ»ÑÐºÐŸ ÑÐŸÐ³ÐŽÐ°,ÐºÐŸÐ³ÐŽÐ° ÐŸÑÑÑÑÑÑÐ²ÑÐµÑ ÑÐ»ÐµÐŒÐµÐœÑ Ñ ÑÐµÐŒ Ð¶Ðµ ÑÐ°ÐŒÑÐŒ ÐžÐŒÐµÐœÐµÐŒ Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ Ð²ÑÐ±ÑÐ°ÐœÐœÑÑ
+ ÑÑÑÐ°ÐœÐŸÐ²ÐŸÐº; "ÐÐ±ÑÐµÐŽÐžÐœÐžÑÑ" ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ Ð¿ÑÐžÑÐŸÐµÐŽÐžÐœÐµÐœÐžÐµ ÐœÐŸÐ²ÐŸÐ³ÐŸ ÑÐ»ÐµÐŒÐµÐœÑÐ° Ðº ÑÐ¶Ðµ ÑÐ°ÐœÐµÐµ Ð²ÑÐ±ÑÐ°ÐœÐœÐŸÐŒÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐŒ;ÐœÐ°ÐºÐŸÐœÐµÑ, "ÐÐµ ÑÑÐžÑÑÐ²Ð°ÑÑ", ÑÑÐŸÐ±Ñ ÐœÐµ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐœÐžÐºÐ°ÐºÐžÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ñ ÑÑÐžÐŒ ÐžÐŒÐµÐœÐµÐŒ ÑÐ»ÐµÐŒÐµÐœÑÐ°. ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÐ»Ðž,ÐºÐ°Ðº ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐœÐµÐºÐŸÑÐŸÑÑÑ ÑÐ°ÑÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, Ð·Ð°Ð¿ÐžÑÐ°ÐœÐœÐ°Ñ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÑÐŸÑ
+ÑÐ°ÐœÑÐµÑÑÑ ÐœÐ° Ð²ÑÐµÐŒÑ ÑÑÑÐµÑÑÐ²ÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="340">ÐÐ»Ñ ÐŽÐµÑÐ°Ð»ÐµÐ¹ ÐŸÑÐœÐŸÑÐžÑÐµÐ»ÑÐœÐŸ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð² metadata.xml, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð² Greenstone ÐŽÐ»Ñ Ñ
+ÑÐ°ÐœÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÐŒ.Ð³Ð»Ð°Ð²Ñ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="designing_your_collection_appearance">
+<Title>
+<Text id="341">ÐÑÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="342">ÐÐŸÐ³ÐŽÐ° ÐÐ°ÑÐž ÑÐ°Ð¹Ð»Ñ ÑÐœÐ°Ð±Ð¶ÐµÐœÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž,ÐŽÐ°Ð»ÐµÐµ ÐÑ ÑÐµÑÐ°ÐµÑÐµ,Ð² ÐºÐ°ÐºÐŸÐŒ Ð²ÐžÐŽÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Greenstone ÐŽÐŸÐ»Ð¶ÐœÐ° Ð±ÑÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐ° Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÐŒ.ÐÐ°ÐºÐŸÐ³ÐŸ Ð²ÐžÐŽÐ° ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŽÐŸÑÑÑÐ¿ÐœÐ° ÐŽÐ»Ñ Ð¿ÐŸÐžÑÐºÐ°? ÐÐ°ÐºÐžÐµ Ð¿ÑÑÐž Ð¿ÑÐµÐŽÑÑÐŒÐŸÑÑÐµÐœÑ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°? ÐÐ°ÐºÐžÐµ ÑÐ·ÑÐºÐž Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑÑÑ? ÐÐŽÐµ ÑÐ°Ð·ÐŒÐµÑÑÐžÑÑ ÐºÐœÐŸÐ¿ÐºÐž ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ? Ð­ÑÐž Ð²ÐµÑÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐœÐ°ÑÑÑÐŸÐµÐœÑ;Ð² ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑÑÑ,ÐºÐ°Ðº ÑÑÐŸ ÑÐŽÐµÐ»Ð°ÑÑ.</Text>
+<Part id="the_design_view">
+<Title>
+<Text id="343">ÐÐžÐŽ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°</Text>
+</Title>
+<Content>
+<Text id="344">Ð­ÑÐŸÑ ÑÐ°Ð·ÐŽÐµÐ» Ð²Ð²ÐŸÐŽÐžÑ ÐÐ°Ñ Ð² ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°ÐµÐŒÑÐ¹ Ð¿ÑÐŸÐµÐºÑ Ðž ÐŸÐ±ÑÑÑÐœÑÐµÑ,ÐºÐ°Ðº Ð²ÑÐ±ÑÐ°ÑÑ ÐŒÐµÐ¶ÐŽÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒÐž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑÐŒÐž Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ Ð°ÐºÑÐžÐ²ÐœÐŸÐ¹ ÑÐ°ÑÑÐž ÐŸÐºÐœÐ°.</Text>
+<Text id="345">ÐÑÐž Ð¿ÐŸÐŒÐŸÑÐž ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÑÑ Ð²ÐžÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÐµÐŒÐŸÐ¹ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ.ÐÐ°ÑÐžÐ°ÐœÑÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÑ ÐœÐ° ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÑÐ°Ð·ÐŽÐµÐ»Ñ, ÐºÐ°Ð¶ÐŽÑÐ¹ ÐžÐ· ÐºÐŸÑÐŸÑÑÑ
+ ÑÐ²ÑÐ·Ð°Ðœ ÑÐŸ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐŸÐ¹ ÑÑÐ°ÐŽÐžÐµÐ¹ ÐœÐ°Ð²ÐžÐ³Ð°ÑÐžÐž ÐžÐ»Ðž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž.</Text>
+<Text id="346">Ð¡Ð»ÐµÐ²Ð° ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÑÐ¿ÐžÑÐŸÐº ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐ¹,Ð° ÑÐ¿ÑÐ°Ð²Ð° - ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÑÐµÐºÑÑÐžÐŒ ÑÐ¿ÐžÑÐºÐŸÐŒ.Ð§ÑÐŸÐ±Ñ Ð¿ÐµÑÐµÐ¹ÑÐž ÐœÐ° Ð²ÑÐ±ÑÐ°ÐœÐœÐŸÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ,ÑÐµÐ»ÐºÐœÐžÑÐµ ÐµÐ³ÐŸ ÐžÐŒÑ Ð² ÑÐ¿ÐžÑÐºÐµ.</Text>
+<Text id="347">Ð§ÑÐŸÐ±Ñ Ð¿ÐŸÐœÐžÐŒÐ°ÑÑ ÑÑÐ°ÐŽÐžÐž Ðž ÑÐµÑÐŒÐžÐœÑ,ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐµ Ð¿ÑÐž Ð¿ÑÐŸÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐœÐ°ÑÐ°Ð»Ð° Ð¿ÑÐŸÑÑÐžÑÐµ Ð³Ð»Ð°Ð²Ñ 1 Ðž 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone.</Text>
+</Content>
+</Part>
+<Part id="general">
+<Title>
+<Text id="348">ÐÐ±ÑÐµÐµ</Text>
+</Title>
+<Content>
+<Text id="349">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ,ÐºÐ°Ðº Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ Ðž ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐŸÐ±ÑÐžÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž, ÐŸÑÐœÐŸÑÑÑÐžÐµÑÑ Ðº ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.Ð¡ÐœÐ°ÑÐ°Ð»Ð° Ð² "Ð Ð°Ð·ÐŽÐµÐ»Ð°Ñ
+ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ±ÑÐžÐµ".</Text>
+<Text id="350">ÐÐŽÐµÑÑ Ð·ÐœÐ°ÑÐµÐœÐžÑ,Ð¿ÑÐµÐŽÑÑÐŒÐŸÑÑÐµÐœÐœÑÐµ Ð¿ÑÐž ÑÐŸÐ·ÐŽÐ°ÐœÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž,ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐžÐ·ÐŒÐµÐœÐµÐœÑ.</Text>
+<Text id="351">Ð¡ÐœÐ°ÑÐ°Ð»Ð° ÐžÐŽÑÑ ÐºÐŸÐœÑÐ°ÐºÑÐœÑÐµ Ð°ÐŽÑÐµÑÐ° ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ Ð¿ÐŸÑÑÑ ÑÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑÐµÐ³ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð»ÐžÑÐ°. Ð¡Ð»ÐµÐŽÑÑÑÐµÐµ Ð¿ÐŸÐ»Ðµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐÐ°ÐŒ ÐžÐ·ÐŒÐµÐœÑÑÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð¡Ð»ÐµÐŽÑÑÐµÐµ ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð¿Ð°Ð¿ÐºÑ, Ð² ÐºÐŸÑÐŸÑÐŸÐ¹ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐœÐŸ ÐœÐµ Ð¿ÐŸÐŽÐ»ÐµÐ¶ÐžÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑÐŒ. Ð¡Ð»ÐµÐŽÑÑÑÐµÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑ (Ð² ÑÐŸÑÐŒÐµ URL) ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÐµ,ÑÑÐŸÐ±Ñ Ð¿ÐŸÐºÐ°Ð·Ð°ÑÑ ÐœÐ°Ð²ÐµÑÑ
+Ñ ÑÐ»ÐµÐ²Ð° ÐŸÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÑÑÐ°ÐœÐžÑÑ ÐŸ ÐœÐµÐ¹, Ðž ÑÐ»ÐµÐŽÑÑÑÐµÐµ - ÐžÐºÐŸÐœÐºÐ°, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ Ð² Greenstone ÑÑÑÐ°ÐœÐžÑÐ° ÐŽÐ»Ñ ÑÐ²ÑÐ·Ðž Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹. ÐÐŸÑÐ»Ðµ ÑÑÐŸÐ³ÐŸ, Ð²Ñ ÑÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐŽÐµÐ»ÐžÑÑ Ð¿ÑÐœÐºÑ Ð³Ð°Ð»ÐŸÑÐºÐŸÐ¹, ÑÐºÐ°Ð·Ð°Ð², ÐŽÐŸÑÑÑÐ¿ÐœÐ° Ð»Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐŽÑÑÐ³ÐžÐŒ. ÐÐ°ÐºÐŸÐœÐµÑ, ÑÐ»ÐµÐŽÑÐµÑ ÐŸÐ±Ð»Ð°ÑÑÑ ÑÐµÐºÑÑÐ° "ÐÐ¿ÐžÑÐ°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž",Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐœÐ°Ñ ÑÐ°ÐœÐµÐµ Ð² Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+</Content>
+</Part>
+<Part id="document_plugins">
+<Title>
+<Text id="352">ÐÐ»Ð°Ð³ÐžÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°</Text>
+</Title>
+<Content>
+<Text id="353">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ¿ÐžÑÐ°ÐœÐŸ,ÐºÐ°Ðº ÑÐŸÑÐŒÐžÑÐŸÐ²Ð°ÑÑ Ð¿Ð»Ð°Ð³ÐžÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÐŽÐ»Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹.Ð ÐœÑÐŒ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ,ÐºÐ°Ðº ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ,ÐºÐ°ÐºÐžÐµ Ð¿Ð»Ð°Ð³ÐžÐœÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ, ÐºÐ°ÐºÐžÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ Ð¿ÐµÑÐµÐŽÐ°Ð²Ð°ÑÑ Ðº ÐœÐžÐŒ Ðž Ð² ÐºÐ°ÐºÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ ÐŸÐœÐž Ð²Ñ
+ÐŸÐŽÑÑ. Ð©ÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ»Ð°Ð³ÐžÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²" Ð² Ð¿ÑÐœÐºÑÐµ "Ð Ð°Ð·ÐŽÐµÐ»Ñ Ð¿ÑÐŸÐµÐºÑÐ°".</Text>
+<Text id="354">Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÑÑ Ð¿Ð»Ð°Ð³ÐžÐœ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ,ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ "ÐÑÐ±ÐŸÑ Ð¿Ð»Ð°Ð³ÐžÐœÐ° ÐŽÐ»Ñ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ" Ð² ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐŒ ÑÐ¿ÐžÑÐºÐµ ÐŸÐºÐŸÐ»ÐŸ ÐŸÑÐœÐŸÐ²Ð°ÐœÐžÑ,Ðž Ð·Ð°ÑÐµÐŒ ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ Ð¿Ð»Ð°Ð³ÐžÐœ". ÐÐŸÑÐ²Ð»ÑÐµÑÑÑ ÐŸÐºÐœÐŸ Ñ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµÐŒ "ÐÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ²";ÐŸÐœÐŸ ÐŸÐ¿ÐžÑÐ°ÐœÐŸ ÐœÐžÐ¶Ðµ. ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐÑ ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°Ð»Ðž ÐœÐŸÐ²ÑÐ¹ Ð¿Ð»Ð°Ð³ÐžÐœ, ÐŸÐœ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÑÑ Ð² ÐºÐŸÐœÐµÑ ÑÐ¿ÐžÑÐºÐ° "Ð£ÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐœÑÐµ ÑÐµÐºÑÑÐžÐµ Ð¿Ð»Ð°Ð³ÐžÐœÑ". ÐÐ°ÐŒÐµÑÑÑÐµ, ÑÑÐŸ, ÐºÑÐŸÐŒÐµ UnknownPlug, ÐºÐ°Ð¶ÐŽÑÐ¹ Ð¿Ð»Ð°Ð³ÐžÐœ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð²ÑÐ²ÐµÐŽÐµÐœ ÑÐŸÐ»ÑÐºÐŸ ÐŸÐŽÐžÐœ ÑÐ°Ð· Ð² ÑÐ¿ÐžÑÐºÐµ.</Text>
+<Text id="355">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ Ð¿Ð»Ð°Ð³ÐžÐœ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ Ð² ÑÐ¿ÐžÑÐºÐµ Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ Ð¿Ð»Ð°Ð³ÐžÐœ".</Text>
+<Text id="356">ÐÐ»Ð°Ð³ÐžÐœÑ ÑÐŸÑÐŒÐžÑÑÑÑÑÑ Ð¿ÑÑÐµÐŒ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÐµÐœÐžÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ². Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐžÑ
+, Ð²ÑÐ±ÐµÑÐžÑÐµ Ð¿Ð»Ð°Ð³ÐžÐœ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð€ÐŸÑÐŒÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿Ð»Ð°Ð³ÐžÐœÐŸÐ²"(ÐžÐ»Ðž ÐŽÐ²ÐŸÐ¹ÐœÑÐŒ ÑÐµÐ»ÑÐºÐŸÐŒ ÐœÐ° Ð¿Ð»Ð°Ð³ÐžÐœÐµ). ÐÐžÐ°Ð»ÐŸÐ³ "ÐÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐµ ÐÑÐ³ÑÐŒÐµÐœÑÑ" Ð²ÐŸÐ·ÐœÐžÐºÐ°ÐµÑ Ñ ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒÐž ÐŸÐ¿ÑÐžÑÐŒÐž ÐŽÐ»Ñ ÑÐºÐ°Ð·Ð°ÐœÐžÑ Ð°ÑÐ³ÑÐŒÐµÐœÑÐŸÐ².</Text>
+<Text id="357">Ð¡ÑÑÐµÑÑÐ²ÑÑÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ Ð²ÐžÐŽÑ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ. ÐÐµÐºÐŸÑÐŸÑÑÐµ ÑÐ²Ð»ÑÑÑÑÑ ÐœÐµÐ·Ð°Ð²ÐžÑÐžÐŒÑÐŒÐž ÐºÐœÐŸÐ¿ÐºÐ°ÐŒÐž Ðž ÑÐµÐ»ÑÐŸÐº ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÑÑ ÐŸÐ¿ÑÐžÑ Ðº Ð¿Ð»Ð°Ð³ÐžÐœÑ. ÐÑÑÐ³ÐžÐµ Ð²ÑÑÑÑÐ¿Ð°ÑÑ Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ ÑÑÑÐŸÐºÐž ÑÐµÐºÑÑÐ° Ñ ÐœÐµÐ·Ð°Ð²ÐžÑÐžÐŒÐŸÐ¹ ÐºÐœÐŸÐ¿ÐºÐŸÐ¹ Ðž ÐŸÐ±Ð»Ð°ÑÑÑÑ ÑÐµÐºÑÑÐ°. Ð©ÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° Ð¿ÐŸÐ»Ðµ,ÑÑÐŸÐ±Ñ Ð²ÑÐ·Ð²Ð°ÑÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑ,Ð·Ð°ÑÐµÐŒ ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°Ð¹ÑÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐ¹ ÑÐµÐºÑÑ (Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸÐµ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÐµ,Ð¿ÑÑÑ ÑÐ°Ð¹Ð»Ð° Ðž Ñ.ÐŽ.) Ð² Ð¿ÐŸÐ»Ðµ. ÐÑÑÐ³ÐžÐµ - ÑÑÐŸ ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐžÐµ ÐŒÐµÐœÑ,Ð² ÐºÐŸÑÐŸÑÑÑ
+ ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÑÐ±ÐžÑÐ°ÑÑ ÐœÑÐ¶ÐœÐŸÐµ ÐžÐ· Ð·Ð°ÐŽÐ°ÐœÐœÐŸÐ³ÐŸ ÐœÐ°Ð±ÐŸÑÐ° Ð·ÐœÐ°ÑÐµÐœÐžÐ¹. Ð§ÑÐŸÐ±Ñ Ð¿ÐŸÐœÑÑÑ,ÑÑÐŸ ÐŽÐµÐ»Ð°ÐµÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑ, ÐŽÐ°Ð¹ÑÐµ ÐŒÑÑÐž ÐœÐ° ÐŒÐ³ÐœÐŸÐ²ÐµÐœÐžÐµ Ð¿ÑÐŸÐ¹ÑÐž Ð¿ÐŸ ÐµÐ³ÐŸ ÐœÐ°Ð·Ð²Ð°ÐœÐžÑ Ðž ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ Ð¿ÐŸÑÐ²ÐžÑÑÑ.</Text>
+<Text id="358">ÐÐŸÐ³ÐŽÐ° ÐÑ ÐžÐ·ÐŒÐµÐœÐžÐ»Ðž ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÑ,ÐœÐ°Ð¶ÐŒÐžÑÐµ "ÐÐ", ÑÑÐŸÐ±Ñ Ð¿ÑÐžÐœÑÑÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ðž Ð·Ð°ÐºÑÑÑÑ ÐŽÐžÐ°Ð»ÐŸÐ³,ÐžÐ»Ðž "ÐÑÐŒÐµÐœÐžÑÑ",ÑÑÐŸÐ±Ñ Ð·Ð°ÐºÑÑÑÑ ÐŽÐžÐ°Ð»ÐŸÐ³ Ð±ÐµÐ· ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð»ÑÐ±ÑÑ
+ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ² Ð¿Ð»Ð°Ð³ÐžÐœÐ°.</Text>
+<Text id="359">ÐÐ»Ð°Ð³ÐžÐœÑ Ð² ÑÐ¿ÐžÑÐºÐµ ÑÐ°ÑÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÑ Ð² ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÐŸÐŒ Ð¿ÐŸÑÑÐŽÐºÐµ,ÑÐ°Ðº ÐºÐ°Ðº ÑÐ¿ÐŸÑÑÐŽÐŸÑÐµÐœÐžÐµ ÐžÐœÐŸÐ³ÐŽÐ° Ð²Ð°Ð¶ÐœÐŸ. ÐÐŸÑÑÐŽÐŸÐº ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÑÑ
+ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÑ
+ ÐŒÐŸÐŽÑÐ»ÐµÐ¹ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐžÐ·ÐŒÐµÐœÐµÐœ ÑÐŸÐ»ÑÐºÐŸ Ð² ÑÐµÐ¶ÐžÐŒÐ°Ñ
+ Ð¡Ð¿ÐµÑÐžÐ°Ð»ÐžÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÑ
+ Ð¡ÐžÑÑÐµÐŒ Ðž Ð­ÐºÑÐ¿ÐµÑÑ (ÑÐŒ. ÐÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÑ).</Text>
+</Content>
+</Part>
+<Part id="search_types">
+<Title>
+<Text id="360">ÐÐžÐŽÑ Ð¿ÐŸÐžÑÐºÐ°</Text>
+</Title>
+<Content>
+<Text id="361">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ,ÐºÐ°Ðº ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž ÐœÐŸÐ²ÐŸÐ³ÐŸ ÐŽÐžÐ·Ð°Ð¹ÐœÐ° Ð² Greenstone; Ð²ÐžÐŽÑ Ð¿ÐŸÐžÑÐºÐ°,ÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑÑ Ð¿ÐŸÐžÑÐº Ð¿ÐŸ Ð¿ÐŸÐ»ÑÐŒ. ÐÐžÐŽÑ Ð¿ÐŸÐžÑÐºÐ° ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ, ÐºÐ°ÐºÐŸÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÐŸÐžÑÐºÐ° ÐŽÐŸÐ»Ð¶ÐµÐœ Ð±ÑÑÑ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœ: ÑÐŸÑÐŒÐ° ÐŽÐ»Ñ Ð¿ÐŸÐ»ÐµÐ¹ Ð¿ÐŸÐžÑÐºÐ° Ðž/ÐžÐ»Ðž Ð¿ÑÐŸÑÑÐŸÐ¹ ÐŽÐ»Ñ ÑÐµÐ³ÑÐ»ÑÑÐœÐŸÐ³ÐŸ Ð¿ÐŸÐžÑÐºÐ°. Ð©ÐµÐ»ÐºÐœÐžÑÐµ Ð²ÐžÐŽÑ Ð¿ÐŸÐžÑÐºÐ° Ð² "Ð Ð°Ð·ÐŽÐµÐ»Ð°Ñ
+ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°".</Text>
+<Text id="362">ÐÐŸÐ³ÐŽÐ° ÐÑ ÐœÐ°ÑÐžÐœÐ°ÐµÑÐµ Ð¿ÑÐŸÑÐŒÐŸÑÑ Ð²ÐžÐŽÐŸÐ² Ð¿ÐŸÐžÑÐºÐ°, ÑÐœÐ°ÑÐ°Ð»Ð° Ð²ÑÐ±ÐµÑÐžÑÐµ "ÐÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ ÑÐ°ÑÑÐžÑÐµÐœÐœÐŸÐ³ÐŸ Ð¿ÐŸÐžÑÐºÐ°",ÐºÐŸÑÐŸÑÑÐ¹ Ð°ÐºÑÐžÐ²ÐžÐ·ÐžÑÑÐµÑ ÐŽÑÑÐ³ÐžÐµ ÑÑÐµÐŽÑÑÐ²Ð° ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ. ÐÑÐž ÑÑÐŸÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð±ÑÐŽÐµÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐ°: ÐžÐœÐŽÐµÐºÑÐžÑÑÑÑÐžÐ¹ ÐŒÐµÑ
+Ð°ÐœÐžÐ·ÐŒ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÐžÑ Ð¿ÑÐŸÐ²ÐµÑÑÐž Ð¿ÐŸÐžÑÐº Ñ ÐžÑÐ¿ÐŸÐ»ÐžÐ·ÐŸÐ²Ð°ÐœÐžÐµÐŒ Ð¿ÐŸÐžÑÐºÐŸÐ²ÑÑ
+ Ð¿ÐŸÐ»ÐµÐ¹. Ð¡Ð¿ÐµÑÐžÑÐžÐºÐ°ÑÐžÑ ÐžÐœÐŽÐµÐºÑÐ° Ð² ÑÑÐŸÐŒ ÑÐµÐ¶ÐžÐŒÐµ ÐœÐµÐŒÐœÐŸÐ³ÐŸ ÐžÐ·ÐŒÐµÐœÐµÐœÐ°. (ÐÑÐž Ð¿ÐµÑÐµÐºÐ»ÑÑÐµÐœÐžÐž ÐŒÐµÐ¶ÐŽÑ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐŒ Ðž Ð¿ÑÐŸÐŽÐ²ÐžÐœÑÑÑÐŒ Ð¿ÑÐžÑÐºÐŸÐŒ ÐÐÐ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑ ÐºÐŸÐœÐ²ÐµÑÑÐžÐ²ÐŸÐ²Ð°ÐœÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ ÐžÐœÐŸÐ³ÐŽÐ° ÐœÐµ ÐŽÐŸÑÑÐ°ÑÐŸÑÐœÐŸ ÑÐŸÑÐœÐŸ.)</Text>
+<Text id="363">Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ°,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° "ÐÐžÐŽÑ Ð¿ÐŸÐžÑÐºÐ°" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ°".ÐÐ°Ð¶ÐŽÑÐ¹ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ° ÐŒÐŸÐ¶ÐµÑ Ð¿ÐŸÑÐ²ÐžÑÑÑÑ Ð² ÑÐ¿ÐžÑÐºÐµ ÑÐŸÐ»ÑÐºÐŸ ÐŸÐŽÐžÐœ ÑÐ°Ð·. ÐÐµÑÐ²ÑÐ¹ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ° Ð±ÑÐŽÐµÑ Ð¿ÐŸ-ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ Ðž ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑÑ ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ Ð¿ÐŸÐžÑÐºÐ° ÑÐŸÐ·ÐŽÐ°ÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÐµ ÐŸÑÑÐ°Ð»ÑÐœÑÐµ Ð²ÐžÐŽÑ ÐŒÐŸÐ¶ÐœÐŸ Ð±ÑÐŽÐµÑ Ð²ÑÐ±ÑÐ°ÑÑ ÐœÐ° ÑÑÑÐ°ÐœÐžÑÐµ ÐŸÐ¿ÑÐžÐ¹.</Text>
+<Text id="364">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ°, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° "Ð¢ÐµÐºÑÑÐžÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ Ð²ÐžÐŽÐŸÐ² Ð¿ÐŸÐžÑÐºÐ°" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ°".Ð¡Ð¿ÐžÑÐŸÐº ÐŽÐŸÐ»Ð¶ÐµÐœ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑ Ð¿ÐŸ ÐºÑÐ°Ð¹ÐœÐµÐ¹ ÐŒÐµÑÐµ ÐŸÐŽÐžÐœ Ð²ÐžÐŽ Ð¿ÐŸÐžÑÐºÐ°.</Text>
+</Content>
+</Part>
+<Part id="search_indexes">
+<Title>
+<Text id="365">ÐÐœÐŽÐµÐºÑÑ Ð¿ÐŸÐžÑÐºÐ°</Text>
+</Title>
+<Content>
+<Text id="366">ÐÐœÐŽÐµÐºÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ,ÐºÐ°ÐºÐžÐµ ÑÐ°ÑÑÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐ²Ð»ÑÑÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž ÐŽÐ»Ñ Ð¿ÐŸÐžÑÐºÐ°. Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ,ÐºÐ°Ðº ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ Ðž ÑÐŽÐ°Ð»ÐžÑÑ ÐžÐœÐŽÐµÐºÑÑ,Ð° ÑÐ°ÐºÐ¶Ðµ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐžÐœÐŽÐµÐºÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ.ÐÐŸÐŽ "Ð Ð°Ð·ÐŽÐµÐ»Ð°ÐŒÐž ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ ÐžÐœÐŽÐµÐºÑÑ Ð¿ÐŸÐžÑÐºÐ°.</Text>
+<Text id="367">Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐžÐœÐŽÐµÐºÑ,Ð²Ð²ÐµÐŽÐžÑÐµ ÐžÐŒÑ ÐŽÐ»Ñ ÐœÐµÐ³ÐŸ Ð² Ð¿ÐŸÐ»Ðµ "ÐÐŒÑ ÐžÐœÐŽÐµÐºÑÐ°".ÐÑÐ±ÐµÑÐžÑÐµ, ÐºÐ°ÐºÐžÐµ ÐžÐ· Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÑ
+ ÐžÑÑÐŸÑÐœÐžÐºÐŸÐ² ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž Ð¿ÑÐžÑÐŸÐµÐŽÐžÐœÐžÑÑ Ðº ÐžÐœÐŽÐµÐºÑÑ, ÑÐµÐ»ÐºÐ°Ñ ÐœÐ° Ð¿ÐŸÐ»Ðµ ÐŸÐºÐŸÐ»ÐŸ ÐœÐžÑ
+. Ð¡Ð¿ÐžÑÐŸÐº Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð²ÑÐµ Ð·Ð°ÐŽÐ°ÐœÐœÑÐµ ÑÐ»ÐµÐŒÐµÐœÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, Ð° ÑÐ°ÐºÐ¶Ðµ Ð¿ÐŸÐ»ÐœÑÐ¹ ÑÐµÐºÑÑ. Ð Ð°ÑÐ¿ÐŸÐ»Ð°Ð³Ð°Ñ Ð²ÑÐ±ÑÐ°ÐœÐœÑÐŒÐž ÐžÑÑÐŸÑÐœÐžÐºÐ°ÐŒÐž ÐŽÐ°ÐœÐœÑÑ
+, Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÑÐµÐ¿ÐµÐœÑ ÐŽÐµÑÐ°Ð»ÐžÐ·Ð°ÑÐžÐž ÐžÐœÐŽÐµÐºÑÐ°, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐŒÐµÐœÑ "ÐÐ° ÑÑÐŸÐ²ÐœÐµ". ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÑÑÐž ÐŽÐµÑÐ°Ð»Ðž ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÑ,Ð¿ÑÐœÐºÑ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÐžÐœÐŽÐµÐºÑ" ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ Ð°ÐºÑÐžÐ²ÐœÑÐŒ (ÐµÑÐ»Ðž ÐœÐµÑ ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐ³ÐŸ ÐžÐœÐŽÐµÐºÑÐ° Ñ ÑÐµÐŒÐž Ð¶Ðµ ÑÐ°ÐŒÑÐŒÐž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ°ÐŒÐž).Ð©ÐµÐºÐœÐžÑÐµ ÐœÐ° ÐœÑÐŒ, ÑÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐœÐŸÐ²ÑÐ¹ ÐžÐœÐŽÐµÐºÑ.</Text>
+<Text id="368">Ð§ÑÐŸÐ±Ñ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐžÐœÐŽÐµÐºÑ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ Ðž ÐžÐ·ÐŒÐµÐœÐžÑÐµ ÐŽÐµÑÐ°Ð»Ðž. ÐÐŸÐŽÑÐ²ÐµÑÐŽÐžÑÐµ, ÐœÐ°Ð¶Ð°Ð² ÐœÐ° "ÐÐ°ÐŒÐµÐœÐžÑÑ ÐžÐœÐŽÐµÐºÑ".</Text>
+<Text id="369">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÐžÐœÐŽÐµÐºÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÑ
+ ÐžÐœÐŽÐµÐºÑÐŸÐ² Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÐžÐœÐŽÐµÐºÑ".</Text>
+<Text id="370">Ð§ÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐžÐœÐŽÐµÐºÑ ÐžÐ· ÑÐºÐŸÐœÐ²ÐµÑÑÐžÑÐŸÐ²Ð°ÐœÐœÐŸÐ³ÐŸ ÑÐµÐºÑÑÐ° Ðž Ð²ÑÐµÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÐœÐ°Ð¶ÐŒÐžÑÐµ "ÐÑÐ±ÑÐ°ÑÑ ÐÑÐµ".</Text>
+<Text id="371">ÐÐœÐŽÐµÐºÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ - ÑÐŸÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐœÐ° Ð¿ÐŸÐžÑÐºÐŸÐ²ÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž,Ð¿ÐŸÐŒÐµÑÐµÐœ ÑÑÐ³Ð°ÐŒÐž "[ÐÐœÐŽÐµÐºÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ]" Ð² ÑÐ¿ÐžÑÐºÐµ "ÐÐ°ÐŽÐ°ÐœÐœÑÐµ ÐžÐœÐŽÐµÐºÑÑ".Ð§ÑÐŸÐ±Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐµÐ³ÐŸ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐžÐœÐŽÐµÐºÑ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÑÑÐ°ÐœÐŸÐ²ÐžÑÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ".</Text>
+<Text id="372">ÐÑÐ»Ðž Ð¿ÐŸÐ·Ð²ÐŸÐ»ÐµÐœ ÑÐ°ÑÑÐžÑÐµÐœÐœÑÐ¹ Ð¿ÐŸÐžÑÐº (ÑÐµÑÐµÐ· Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ Ð²ÐžÐŽÐŸÐ² Ð¿ÐŸÐžÑÐºÐ°), ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐžÐœÐŽÐµÐºÑÐŸÐŒ ÐŸÑÐ»ÐžÑÐ°ÐµÑÑÑ. ÐÐŒÐµÐµÑÑÑ ÐœÐŸÐ²ÑÐ¹ ÐžÑÑÐŸÑÐœÐžÐº Ð¿ÑÐµÐ²ÐŽÐŸÐŽÐ°ÐœÐœÑÑ
+ "Ð²ÑÐµ Ð¿ÐŸÐ»Ñ",ÐºÐŸÑÐŸÑÑÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÑÑ Ð¿ÐŸÐžÑÐº Ð¿ÐŸ Ð²ÑÐµÐŒ ÑÐºÐ°Ð·Ð°ÐœÐœÑÐŒ ÐžÐœÐŽÐµÐºÑÐ°ÐŒ ÑÑÐ°Ð·Ñ.Ð£ÑÐŸÐ²ÐœÐž ÐœÐµ Ð¿ÑÐžÐ²ÑÐ·Ð°ÐœÑ Ðº ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐŸÐŒÑ ÐžÐœÐŽÐµÐºÑÑ,Ð° Ð¿ÑÐžÐŒÐµÐœÑÑÑÑÑ ÐºÐŸ Ð²ÑÐµÐŒ ÐžÐœÐŽÐµÐºÑÐ°ÐŒ.Ð¢Ð°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ,ÐžÐœÐŽÐµÐºÑÑ Ðž ÑÑÐŸÐ²ÐœÐž ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑÑÑÑ ÐŸÑÐŽÐµÐ»ÑÐœÐŸ. "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÐÑÐµ" ÑÐŸÐ·ÐŽÐ°ÐµÑ ÐŸÑÐŽÐµÐ»ÑÐœÑÐ¹ ÐžÐœÐŽÐµÐºÑ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ Ð¿ÐŸÐ»Ñ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ Ð² ÑÑÐŸÐŒ ÑÐµÐ¶ÐžÐŒÐµ. </Text>
+<Text id="373">ÐÐŒÑ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÐžÐœÐŽÐµÐºÑÐ° Ð±ÑÐŽÐµÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÑÐ²ÑÐ·Ð°ÐœÐŸ Ñ ÐžÐŒÐµÐœÐµÐŒ ÐžÑÑÐŸÑÐœÐžÐºÐ°.Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐžÐŒÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐžÐœÐŽÐµÐºÑ,ÐžÐ·ÐŒÐµÐœÐžÑÐµ ÐµÐ³ÐŸ ÐŽÐµÑÐ°Ð»Ðž Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ°ÐŒÐµÐœÐžÑÑ ÐžÐœÐŽÐµÐºÑ".</Text>
+</Content>
+</Part>
+<Part id="partition_indexes">
+<Title>
+<Text id="374">ÐÐœÐŽÐµÐºÑÑ ÑÐ°Ð·Ð±ÐžÐµÐœÐžÑ</Text>
+</Title>
+<Content>
+<Text id="375">ÐÐœÐŽÐµÐºÑÑ Ð¿ÐŸÑÑÑÐŸÐµÐœÑ ÐœÐ° ÐŽÐµÑÐ°Ð»ÑÐœÐŸÐŒ ÑÐµÐºÑÑÐµ ÐžÐ»Ðž ÐžÑÑÐŸÑÐœÐžÐºÐ°Ñ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. ÐÐµÑÑÐŸ Ð¿ÐŸÐžÑÐºÐ° ÐŒÐŸÐ¶ÐµÑ Ð² ÐŽÐ°Ð»ÑÐœÐµÐ¹ÑÐµÐŒ ÑÐ¿ÑÐ°Ð²Ð»ÑÑÑÑÑ Ð¿ÑÑÑÐŒ ÑÐ°Ð·Ð±ÐžÐµÐœÐžÑ ÐžÐœÐŽÐµÐºÑÐŸÐ² Ð»ÐžÐ±ÐŸ Ð¿ÐŸ ÑÐ·ÑÐºÑ ÐžÐ»Ðž Ð¿ÐŸ ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÐŒ ÑÐžÐ»ÑÑÑÐ°ÐŒ.Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑÑÑ,ÐºÐ°Ðº ÑÑÐŸ ÑÐŽÐµÐ»Ð°ÑÑ. ÐÐœÑÑÑÐž "Ð Ð°Ð·ÐŽÐµÐ»ÐŸÐ² ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐœÐŽÐµÐºÑÑ ÑÐ°Ð·Ð±ÐžÐµÐœÐžÑ".</Text>
+<Text id="376">ÐÐžÐŽ "ÐÐœÐŽÐµÐºÑÑ ÑÐ°Ð·Ð±ÐžÐµÐœÐžÑ" ÐžÐŒÐµÐµÑ ÑÑÐž Ð·ÐœÐ°ÑÐµÐœÐžÑ:"ÐÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐžÐ»ÑÑÑÑ","ÐÐ°Ð·ÐœÐ°ÑÐžÑÑ ÑÐ°Ð·Ð±ÐžÐµÐœÐžÐµ" Ðž "ÐÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐ·ÑÐºÐž". ÐÐ»Ñ ÑÐŸÐ³ÐŸ ÑÑÐŸÐ±Ñ Ð±ÐŸÐ»ÑÑÐµ ÑÐ·ÐœÐ°ÑÑ ÐŸ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐž, ÑÐžÑÐ°Ð¹ÑÐµ ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+ Ðž Ð¿ÐŸÐŽÐžÐœÐŽÐµÐºÑÐ°Ñ
+ Ð² Ð³Ð»Ð°Ð²Ðµ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone.</Text>
+<Text id="377">Ð­ÐºÑÐ°Ðœ ÐÐœÐŽÐµÐºÑÐŸÐ² Ð Ð°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐµÐœ ÑÐŸÐ»ÑÐºÐŸ Ð² ÑÐµÐ¶ÐžÐŒÐ°Ñ
+ Ð¡Ð¿ÐµÑÐžÐ°Ð»ÐžÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÑ
+ Ð¡ÐžÑÑÐµÐŒ Ðž Ð­ÐºÑÐ¿ÐµÑÑ (ÑÐŒ. ÐÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÑ). ÐÐ°ÐŒÐµÑÑÑÐµ, ÑÑÐŸ ÐŸÐ±ÑÐµÐµ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ Ð¿ÑÐŸÐžÐ·Ð²ÐµÐŽÐµÐœÐœÑÑ
+ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐ¹ ÑÐ²Ð»ÑÐµÑÑÑ ÐºÐŸÐŒÐ±ÐžÐœÐ°ÑÐžÐµÐ¹ Ð²ÑÐµÑ
+ ÐžÐœÐŽÐµÐºÑÐŸÐ², ÑÐžÐ»ÑÑÑÐŸÐ² ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð²ÑÐ±ÑÐ°ÐœÐœÑÑ
+ ÑÐ·ÑÐºÐŸÐ². ÐÐ²Ð° ÐžÐœÐŽÐµÐºÑÐ° Ñ ÐŽÐ²ÑÐŒÑ ÑÐžÐ»ÑÑÑÐ°ÐŒÐž ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÐŸ ÐŽÐ²ÑÐŒ ÑÐ·ÑÐºÐ°ÐŒ Ð¿ÑÐžÐ²ÐµÐ»ÐŸ Ð±Ñ Ðº Ð²ÐŸÑÑÐŒÐž ÐžÐœÐŽÐµÐºÑÐ°ÐŒ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ.</Text>
+</Content>
+</Part>
+<Part id="define_filters">
+<Title>
+<Text id="378">ÐÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐžÐ»ÑÑÑÑ</Text>
+</Title>
+<Content>
+<Text id="379">Ð€ÐžÐ»ÑÑÑÑ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ ÐÐ°ÐŒ Ð³ÑÑÐ¿Ð¿ÐžÑÐŸÐ²Ð°ÑÑ Ð² Ð¿ÐŸÐŽÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð²ÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð¿ÐŸ ÐžÐœÐŽÐµÐºÑÑ,ÐŽÐ»Ñ ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ Ð·Ð°ÐŽÐ°ÐœÐœÐŸÐ¹ ÐŒÐŸÐŽÐµÐ»Ðž.</Text>
+<Text id="380">Ð§ÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ ÑÐžÐ»ÑÑÑ,ÑÐµÐ»ÐºÐœÐžÑÐµ ÐºÐ»Ð°Ð²ÐžÑÑ "ÐÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐžÐ»ÑÑÑÑ" Ðž Ð²Ð²ÐµÐŽÐžÑÐµ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐŽÐ»Ñ ÐœÐŸÐ²ÐŸÐ³ÐŸ ÑÐžÐ»ÑÑÑÐ° Ð² Ð¿ÐŸÐ»Ðµ "ÐÐŒÑ ÑÐžÐ»ÑÑÑÐ° ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž:".ÐÐ°ÑÐµÐŒ Ð²ÑÐ±ÐµÑÐžÑÐµ Ñ
+Ð°ÑÐ°ÐºÑÐµÑÐœÑÐµ Ð¿ÑÐžÐ·ÐœÐ°ÐºÐž ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°, ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐµ ÐžÐ»Ðž ÑÐ»ÐµÐŒÐµÐœÑÐ°ÐŒ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,ÐžÐ»Ðž ÐœÐ°Ð·Ð²Ð°ÐœÐžÑ ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°ÐµÐŒÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð°.ÐÐ²ÐµÐŽÐžÑÐµ Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸÐµ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÐµ,ÑÑÐŸÐ±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð² ÑÐµÑÐµÐœÐžÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ ÑÑÐŸÐ³ÐŸ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÑ.ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐµÑÐµÐºÐ»ÑÑÐ°ÑÑ "ÐÐºÐ»ÑÑÐµÐœÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²", ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑ ÑÐžÐ»ÑÑÑÑ, ÐžÐ»Ðž "ÐÑÐºÐ»ÑÑÐµÐœÐžÐµ" ÐžÑ
+.ÐÐ°ÐºÐŸÐœÐµÑ,ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ Ð»ÑÐ±ÐŸÐ¹ ÑÑÐ°ÐœÐŽÐ°ÑÑ PERL, Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÑÐµ ÑÐ»Ð°Ð³Ðž Ð²ÑÑÐ°Ð¶ÐµÐœÐžÑ,ÑÑÐŸÐ±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð¿ÑÐž ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐž (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ("i" ÐŽÐ»Ñ ÑÐ»ÑÑÐ°Ñ ÐœÐµÑÑÐ²ÑÑÐ²ÐžÑÐµÐ»ÑÐœÐŸÐ³ÐŸ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÑ),ÐÐ°ÐºÐŸÐœÐµÑ,ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÑÐžÐ»ÑÑÑ",ÑÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÑÐžÐ»ÑÑÑ Ðº ÑÐ¿ÐžÑÐºÑ "Ð€ÐžÐ»ÑÑÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹".</Text>
+<Text id="381">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÑÐžÐ»ÑÑÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÑÐžÐ»ÑÑÑ".</Text>
+<Text id="382">Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÑÐžÐ»ÑÑÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ°,Ð·Ð°ÐŒÐµÐœÐžÑÐµ Ð»ÑÐ±ÐŸÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ, ÐºÐŸÑÐŸÑÐŸÐµ Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ Ð² ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐž ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµÐŒ Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ°ÐŒÐµÐœÐžÑÑ ÑÐžÐ»ÑÑÑ",ÑÑÐŸÐ±Ñ Ð·Ð°ÐºÑÐµÐ¿ÐžÑÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ.</Text>
+</Content>
+</Part>
+<Part id="assign_partitions">
+<Title>
+<Text id="383">ÐÐ°Ð·ÐœÐ°ÑÐµÐœÐžÐµ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ</Text>
+</Title>
+<Content>
+<Text id="384">ÐÐŒÐµÑ Ð·Ð°ÐŽÐ°ÐœÐœÑÐ¹ ÑÐžÐ»ÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐºÐ»Ð°Ð²ÐžÑÑ "ÐÐ°Ð·ÐœÐ°ÑÐžÑÑ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ" ÐŽÐ»Ñ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐžÐœÐŽÐµÐºÑÐŸÐ² ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ ÐžÐ»Ðž ÐŽÐ»Ñ Ð³ÑÑÐ¿Ð¿Ñ ÑÐžÐ»ÑÑÑÐŸÐ². ÐÑÐ±ÐµÑÐžÑÐµ Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÑÐ¹ ÑÐžÐ»ÑÑÑ (ÐžÐ»Ðž ÑÐžÐ»ÑÑÑÑ) ÐžÐ· ÑÐ¿ÐžÑÐºÐ° "ÐÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐžÐ»ÑÑÑÑ ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž", Ð²Ð²ÐµÐŽÐžÑÐµ ÐžÐŒÑ ÐŽÐ»Ñ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ Ð² Ð¿ÐŸÐ»Ðµ "ÐÐŒÑ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐµ".</Text>
+<Text id="385">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐµ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐµ".</Text>
+<Text id="386">Ð§ÑÐŸÐ±Ñ Ð¿ÑÐŸÐžÐ·Ð²ÐµÑÑÐž ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐµ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÑÑÐ°ÐœÐŸÐ²ÐžÑÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ".</Text>
+</Content>
+</Part>
+<Part id="assign_languages">
+<Title>
+<Text id="387">ÐÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐ·ÑÐºÐž</Text>
+</Title>
+<Content>
+<Text id="388">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŽÐµÑÐ°Ð»ÐžÐ·ÐžÑÐŸÐ²Ð°ÐœÐŸ,ÐºÐ°Ðº ÐŸÐ³ÑÐ°ÐœÐžÑÐžÑÑ ÐžÐœÐŽÐµÐºÑÑ Ð¿ÐŸÐžÑÐºÐ° ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐžÐŒÐž ÑÐ·ÑÐºÐ°ÐŒÐž. ÐÑ ÑÐŸÐ²ÐµÑÑÐ°ÐµÑÐµ ÑÑÐŸ Ð¿ÑÐž ÑÐµÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐžÐž ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ,ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐºÐ»Ð°Ð²ÐžÑÑ "ÐÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐ·ÑÐºÐž" Ð² Ð¿ÐµÑÐµÑÐœÐµ "ÐÐœÐŽÐµÐºÑÑ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ".</Text>
+<Text id="389">Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐœÐŸÐ²ÑÐ¹ ÑÐ·ÑÐº ÐŽÐ»Ñ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐºÐ»Ð°Ð²ÐžÑÑ "ÐÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐ·ÑÐºÐž" ÐŽÐ»Ñ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐžÐœÐŽÐµÐºÑÐ° ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ. ÐÑÐ±ÐµÑÐžÑÐµ Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÑÐ¹ ÑÐ·ÑÐº ÐžÐ· ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐ³ÐŸ ÑÐ¿ÐžÑÐºÐ° "Ð¯Ð·ÑÐºÐž ÐŽÐ»Ñ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÑÐ·ÑÐº".</Text>
+<Text id="390">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÑÐ·ÑÐº,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° "ÐÑÐ±ÐŸÑÑ ÑÐ·ÑÐºÐ°" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÑÐ·ÑÐº".</Text>
+<Text id="391">Ð§ÑÐŸÐ±Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÑÐ·ÑÐº Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐ° Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ".</Text>
+</Content>
+</Part>
+<Part id="cross-collection_search">
+<Title>
+<Text id="392">ÐÐŸÐžÑÐº Ð² Ð¿ÐµÑÐµÑÐµÐºÐ°ÑÑÐžÑ
+ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+</Text>
+</Title>
+<Content>
+<Text id="393">Greenstone Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑ Ð¿ÐŸÐžÑÐº Ð² ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+, ÐºÐ°Ðº ÐµÑÐ»Ðž Ð±Ñ ÐŸÐœÐž Ð±ÑÐ»Ðž ÐŸÐ±ÑÐµÐŽÐžÐœÐµÐœÑ. Ð­ÑÐŸ ÑÐŽÐµÐ»Ð°ÐœÐŸ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÑÐºÐ°Ð·Ð°ÐœÐžÑ ÑÐ¿ÐžÑÐºÐ° ÐŽÑÑÐ³ÐžÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, Ð² ÐºÐŸÑÐŸÑÑÑ
+ ÐŽÐŸÐ»Ð¶ÐœÐ° Ð±ÑÑÑ Ð¿ÑÐŸÐ²ÐµÐŽÐµÐœ Ð¿ÐŸÐžÑÐº Ð²ÐŒÐµÑÑÐµ Ñ ÐœÐ°ÑÑÐŸÑÑÐµÐ¹. Ð "Ð Ð°Ð·ÐŽÐµÐ»Ð°Ñ
+ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐžÑÐº Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+".</Text>
+<Text id="394">ÐÐµÐ¶ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐŸÐœÐœÑÐ¹ Ð¿ÐŸÐžÑÐº Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐºÐŸÐœÑÑÐŸÐ»ÑÐœÑÐ¹ ÑÐ¿ÐžÑÐŸÐº ÐŽÐŸÑÑÑÐ¿ÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹.Ð¢ÐµÐºÑÑÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð¿ÐŸÐŒÐµÑÐµÐœÑ Ðž ÐœÐµ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐŸÑÑÐµÑÐœÐ°. Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐŽÑÑÐ³ÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð² ÐºÐŸÑÐŸÑÑÑ
+ Ð¿ÐŸÐžÑÐº Ð±ÑÐŽÐµÑ Ð¿ÑÐŸÐ²ÐŸÐŽÐžÑÑÑÑ Ð¿Ð°ÑÐ°Ð»Ð»ÐµÐ»ÑÐœÐŸ, ÑÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° ÐœÐžÑ
+ Ð² ÑÐ¿ÐžÑÐºÐµ (ÑÐµÐ»ÐºÐœÐžÑÐµ ÑÐœÐŸÐ²Ð°, ÑÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÐžÑ
+). ÐÑÐ»Ðž ÐŸÑÐŸÐ±ÑÐ°ÐœÐ° ÑÐŸÐ»ÑÐºÐŸ ÐŸÐŽÐœÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÑÐŸ ÐŒÐµÐ¶ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐŸÐœÐœÑÐ¹ Ð¿ÐŸÐžÑÐº ÐœÐµÐ²ÐŸÐ·ÐŒÐŸÐ¶ÐµÐœ.</Text>
+<Text id="395">ÐÑÐ»Ðž ÐžÐœÐŽÐžÐ²ÐžÐŽÑÐ°Ð»ÑÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐœÐµ ÐžÐŒÐµÑÑ ÐŸÐŽÐžÐœÐ°ÐºÐŸÐ²ÑÑ
+ ÐžÐœÐŽÐµÐºÑÐŸÐ² (Ð²ÐºÐ»ÑÑÐ°Ñ ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÑ ÐœÐ° ÑÑÐ±ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž ÑÐ°Ð·ÐŽÐµÐ»ÐµÐœÐžÐµ Ð¿ÐŸ ÑÐ·ÑÐºÐ°ÐŒ) Ñ ÐŽÑÑÐ³ÐžÐŒÐž, ÑÐŸ Ð¿ÐµÑÐµÐºÑÐµÑÑÐœÑÐ¹ Ð¿ÐŸÐžÑÐº ÐœÐµ Ð±ÑÐŽÐµÑ ÑÐ°Ð±ÐŸÑÐ°ÑÑ ÐŽÐŸÐ»Ð¶ÐœÑÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ. ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð±ÑÐŽÐµÑ ÑÐŸÐ»ÑÐºÐŸ ÑÐ¿ÐŸÑÐŸÐ±ÐµÐœ Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑ Ð¿ÐŸÐžÑÐº, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐžÐœÐŽÐµÐºÑÑ, ÐŸÐ±ÑÐžÐµ ÐŽÐ»Ñ Ð²ÑÐµÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹.</Text>
+<Text id="396">ÐÐ»Ñ ÐŽÐ°Ð»ÑÐœÐµÐ¹ÑÐžÑ
+ ÐŽÐµÑÐ°Ð»ÐµÐ¹ ÑÐŒ.Ð³Ð»Ð°Ð²Ñ 1 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone.</Text>
+</Content>
+</Part>
+<Part id="browsing_classifiers">
+<Title>
+<Text id="397">ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°</Text>
+</Title>
+<Content>
+<Text id="398">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ,ÐºÐ°Ðº ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐºÐŸÑÐŸÑÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°. Ð "Ð Ð°Ð·ÐŽÐµÐ»Ð°Ñ
+ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÑÐŸÑÐŒÐŸÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ²".</Text>
+<Text id="399">Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ,ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐžÐ¹ ÑÐ¿ÐžÑÐŸÐº "ÐÑÐ±ÐŸÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ° ÐŽÐ»Ñ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ" Ð²ÐœÐžÐ·Ñ ÐŸÐºÐœÐ°,Ðž Ð·Ð°ÑÐµÐŒ ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÑÑÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ". ÐÐŸÑÐ²Ð»ÑÐµÑÑÑ ÐŸÐºÐœÐŸ, ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÐŸÐµ "ÐÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ²".ÐÐœÑÑÑÑÐºÑÐžÐž ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ ÐŽÐžÐ°Ð»ÐŸÐ³Ð° ÑÐµ Ð¶Ðµ ÑÐ°ÐŒÑÐµ,ÑÑÐŸ ÐºÐ°ÑÐ°ÑÑÑÑ Ð¿Ð»Ð°Ð³ÐžÐœÐŸÐ² (ÐÐ»Ð°Ð³ÐžÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°).ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐÑ ÑÑÐŸÑÐŒÐžÑÐŸÐ²Ð°Ð»Ðž ÐœÐŸÐ²ÑÐ¹ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ, ÐŸÐœ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÑÑ Ð² ÐºÐŸÐœÐµÑ ÑÐ¿ÐžÑÐºÐ° "Ð¢ÐµÐºÑÑÐžÐµ Ð·Ð°ÐŽÐ°ÐœÐœÑÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ".</Text>
+<Text id="400">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ".</Text>
+<Text id="401">Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐ°, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐœÑÐžÐ³ÑÑÐžÑÑÐ¹ÑÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ." (ÐžÐ»Ðž ÑÐµÐ»ÐºÐœÑÑÑ ÐŽÐ²Ð° ÑÐ°Ð·Ð° ÐœÐ° ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐµ Ð² ÑÐ¿ÐžÑÐºÐµ).</Text>
+<Text id="402">ÐÐŸÑÑÐŽÐŸÐº ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ² Ð² ÐœÐ°Ð²ÐžÐ³Ð°ÑÐžÐŸÐœÐœÐŸÐ¹ Ð»ÐžÐœÐµÐ¹ÐºÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐž ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÐµÑ ÑÐŸÐŒÑ,ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐºÐ°Ð·Ð°Ðœ Ð·ÐŽÐµÑÑ.Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ Ð¿ÐŸÑÑÐŽÐŸÐº,Ð²ÑÐ±ÐµÑÐžÑÐµ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÐÑ Ñ
+ÐŸÑÐžÑÐµ Ð¿ÐµÑÐµÐŒÐµÑÑÐžÑÑ, Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ²ÐžÐ³Ð°ÑÑÑÑ Ð²Ð²ÐµÑÑ
+" ÐžÐ»Ðž "ÐÐ²ÐžÐ³Ð°ÑÑÑÑ Ð²ÐœÐžÐ·".</Text>
+<Text id="403">ÐÐ»Ñ ÐŽÐ°Ð»ÑÐœÐµÐ¹ÑÐµÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž ÐŸÑÐœÐŸÑÐžÑÐµÐ»ÑÐœÐŸ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐ² ÑÐžÑÐ°Ð¹ÑÐµ Ð³Ð»Ð°Ð²Ñ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone.</Text>
+</Content>
+</Part>
+<Part id="format_features">
+<Title>
+<Text id="404">ÐÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž ÑÐŸÑÐŒÐ°ÑÐ°</Text>
+</Title>
+<Content>
+<Text id="405">ÐÐµÐ±-ÑÑÑÐ°ÐœÐžÑÑ, ÐºÐŸÑÐŸÑÑÐµ ÐÑ Ð²ÐžÐŽÐžÑÐµ, ÐºÐŸÐ³ÐŽÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ Greenstone, ÐœÐµ ÑÐ²Ð»ÑÑÑÑÑ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÐœÑÐŒÐž, Ð° ÑÐŸÐ·ÐŽÐ°ÑÑÑÑ "ÐœÐ° Ð»ÐµÑÑ", ÐºÐŸÐ³ÐŽÐ° Ð² ÐœÐžÑ
+ ÐµÑÑÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÑÑÑ. ÐÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐ»Ñ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÑ ÑÑÐžÑ
+ ÑÐ³ÐµÐœÐµÑÐžÑÐŸÐ²Ð°ÐœÐœÑÑ
+ ÑÑÑÐ°ÐœÐžÑ. ÐÐœÐž Ð·Ð°ÑÑÐ°Ð³ÐžÐ²Ð°ÑÑ ÑÐ°ÐºÐžÐµ Ð²ÐµÑÐž,ÐºÐ°Ðº ÐŒÐµÑÑÐŸ Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÑ ÐºÐœÐŸÐ¿ÐºÐž,ÐºÐŸÐ³ÐŽÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ,Ðž ÐºÐ°ÐºÐžÐµ ÑÐ²ÑÐ·Ðž ÐŸÑÐŸÐ±ÑÐ°Ð¶Ð°ÑÑÑÑ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÐŸÐŒ DateList. ÐÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ° ÐœÐµ Ð»ÐµÐ³ÐºÐŸ ÑÐ°Ð·ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÑÑ,Ðž ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ Ð¿ÑÐŸÑÐžÑÐ°ÑÑ Ð³Ð»Ð°Ð²Ñ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone. Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÐ¶ÐŽÐ°ÑÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÑÐŸÑÐŒÐ°ÑÐ° Ðž ÑÐŸ, ÐºÐ°Ðº ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÐµÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÐœÐžÐŒ. Ð "Ð Ð°Ð·ÐŽÐµÐ»Ð°Ñ
+ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž ÑÐŸÑÐŒÐ°ÑÐ°".</Text>
+<Text id="406">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐžÐŒÐµÐœÐžÑÑ ÐºÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ° Ðº ÑÐµÐŒÑ-ÐœÐžÐ±ÑÐŽÑ Ð² ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐŒ ÑÐ¿ÐžÑÐºÐµ "ÐÑÐ±ÐŸÑ ÑÑÐµÐŽÑÑÐ²",ÐºÐŸÑÐŸÑÑÐ¹ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÐºÐ°Ð¶ÐŽÑÐ¹ ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ Ðž Ð²ÑÑÑÐŸÐµÐœÐœÑÐ¹ ÑÐ¿ÐžÑÐŸÐº ÑÑÐµÐŽÑÑÐ². ÐÐŸÐ³ÐŽÐ° ÐÑ Ð²ÑÐ±ÐžÑÐ°ÐµÑÐµ ÑÑÐµÐŽÑÑÐ²Ð°, ÐµÑÑÑ ÐŽÐ²Ð° ÑÐžÐ¿Ð° ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ. ÐÐµÐºÐŸÑÐŸÑÑÐµ ÑÑÐµÐŽÑÑÐ²Ð° ÑÐ²Ð»ÑÑÑÑÑ Ð¿ÑÐŸÑÑÐŸ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž ÐžÐ»Ðž ÐœÐµÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž,ÐŸÐœÐž ÑÐ¿ÑÐ°Ð²Ð»ÑÑÑÑÑ ÐºÐœÐŸÐ¿ÐºÐ°ÐŒÐž. ÐÑÑÐ³ÐžÐµ ÑÑÐµÐ±ÑÑÑ, ÑÑÐŸÐ±Ñ Ð±ÑÐ»Ð° ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐ° ÑÐŸÑÐŒÐ°ÑÐœÐ°Ñ ÑÑÑÐŸÐºÐ°. ÐÐ»Ñ ÐœÐžÑ
+ ÐžÐŒÐµÐµÑÑÑ ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐžÐ¹ ÑÐ¿ÐžÑÐŸÐº "ÐÐŸÐ·ÐŽÐµÐ¹ÑÑÐ²ÑÑÑÐžÐ¹ ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑ", ÑÑÐŸÐ±Ñ Ð²ÑÐ±ÑÐ°ÑÑ, Ðº ÐºÐ°ÐºÐŸÐ¹ ÑÐ°ÑÑÐž ÑÑÐµÐŽÑÑÐ² ÑÑÑÐŸÐºÐ° ÐŸÐ±ÑÐ°ÑÐ°ÐµÑÑÑ,ÐµÑÐ»Ðž ÑÑÐŸ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ, ÐŸÐ±Ð»Ð°ÑÑÑ ÑÐµÐºÑÑÐ° ("Ð¡ÑÑÐŸÐºÐ° ÑÐŸÑÐŒÐ°ÑÐ° HTML") ÐŽÐ»Ñ Ð²Ð²ÐŸÐŽÐ° ÑÑÑÐŸÐºÐž, Ðž Ð²ÑÐ±ÐŸÑ Ð·Ð°ÐŽÐ°ÐœÐœÑÑ
+ "ÐÐµÑÐµÐŒÐµÐœÐœÑÑ
+". Ð§ÑÐŸÐ±Ñ Ð²ÑÑÐ°Ð²ÐžÑÑ Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÑ Ð² ÑÐµÐºÑÑÑÑ Ð¿ÐŸÐ·ÐžÑÐžÑ Ð² ÑÐŸÑÐŒÐ°ÑÐœÑÑ ÑÑÑÐŸÐºÑ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÑ ÐžÐ· ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐ³ÐŸ ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÑÑÐ°Ð²ÐžÑÑ".</Text>
+<Text id="407">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐŸÑÐŒÐ°Ñ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÐŽÐ»Ñ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐŸÐ³ÐŸ ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑÐ°, Ð²ÑÐ±ÐžÑÐ°Ñ Ð±Ð»Ð°ÐœÐº ÑÐ²ÐŸÐ¹ÑÑÐ². Ð­ÑÐŸÑ ÑÐŸÑÐŒÐ°Ñ Ð·Ð°ÑÐµÐŒ Ð¿ÑÐžÐŒÐµÐœÑÐµÑÑÑ ÐºÐŸ Ð²ÑÐµÐŒ Ð¿ÑÐžÐŒÐµÐœÐžÐŒÑÐŒ ÑÐ²ÐŸÐ¹ÑÑÐ²Ð°ÐŒ, ÐµÑÐ»Ðž ÐŽÑÑÐ³ÐŸÐµ ÐœÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐŸ.</Text>
+<Text id="408">Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐœÐŸÐ²ÑÑ ÐºÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ°,Ð²ÐœÐµÑÐžÑÐµ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ,ÐºÐ°Ðº ÐŸÐ±ÑÑÑÐœÐµÐœÐŸ Ð²ÑÑÐµ, Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÑÐŸÑÐŒÐ°Ñ".ÐÐŸÐ²Ð°Ñ ÐºÐŸÐŒÐ°ÐœÐŽÐ° ÑÐŸÑÐŒÐ°ÑÐ° Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ Ð² ÑÐ¿ÐžÑÐºÐµ "Ð¢ÐµÐºÑÑÐžÐµ Ð·Ð°ÐŽÐ°ÐœÐœÑÐµ ÐºÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ°".Ð¢ÐŸÐ»ÑÐºÐŸ ÐŸÐŽÐœÐ° ÐºÐŸÐŒÐ°ÐœÐŽÐ° ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÑÐ²ÑÐ·Ð°ÐœÐ° Ñ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÐºÐŸÐŒÐ±ÐžÐœÐ°ÑÐžÐµÐ¹ ÑÐ²ÐŸÐ¹ÑÑÐ²ÐŸ/ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑ.</Text>
+<Text id="409">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÐºÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ°, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÑ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ ÑÐŸÑÐŒÐ°Ñ".</Text>
+<Text id="410">Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐºÐŸÐŒÐ°ÐœÐŽÑ ÑÐŸÑÐŒÐ°ÑÐ°, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÑ ÐŒÐ· ÑÐ¿ÐžÑÐºÐ°, ÐžÐ·ÐŒÐµÐœÐžÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ°ÐŒÐµÐœÐžÑÑ ÑÐŸÑÐŒÐ°Ñ".</Text>
+<Text id="411">ÐÐ° ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐµÐ¹ ÐŸ Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÑ
+ Ðž ÐºÐŸÐŒÐ¿ÐŸÐœÐµÐœÑÐ°Ñ
+ ÑÑÐµÐŽÑÑÐ² ÐŸÐ±ÑÐ°ÑÐžÑÐµÑÑ Ðº Ð³Ð»Ð°Ð²Ðµ 2 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone.</Text>
+<Text id="412">ÐÑÐ»Ðž ÐºÐœÐŸÐ¿ÐºÐ° "ÐÐŸÐ·Ð²ÐŸÐ»ÐµÐœÐœÑÐµ ÑÐ°ÑÑÐžÑÐµÐœÐœÑÐµ Ð²Ð°ÑÐžÐ°ÐœÑÑ" Ð¿ÐŸÐŒÐµÑÐµÐœÐ°,ÑÐŸ ÑÐ°Ð·ÑÐµÑÐµÐœÑ ÐœÐµÐºÐŸÑÐŸÑÑÐµ Ð¿ÑÐŸÐŽÐ²ÐžÐœÑÑÑÐµ Ð²Ð°ÑÐžÐ°ÐœÑÑ ÑÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÐžÑ . Ð¡Ð¿ÐžÑÐŸÐº ÑÑÐµÐŽÑÑÐ², ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÑ, ÐœÐµÐŒÐœÐŸÐ³ÐŸ ÐžÐ·ÐŒÐµÐœÐµÐœ Ðž Ð±ÐŸÐ»ÑÑÐµÐµ ÑÐžÑÐ»ÐŸ Ð¿ÐµÑÐµÐŒÐµÐœÐœÑÑ
+ ÐŽÐŸÑÑÑÐ¿ÐœÐŸ ÐŽÐ»Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐŒÐ°ÐœÐŽÐŸÐ¹ ÑÐŸÑÐŒÐ°ÑÐ°, ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°Ñ Ð±ÐŸÐ»ÑÑÐµÐµ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÑÑÑÐ°ÐœÐžÑÐµÐ¹ ÐŸÑÐžÐ³ÐžÐœÐ°Ð»-ÐŒÐ°ÐºÐµÑÐ°.</Text>
+</Content>
+</Part>
+<Part id="translate_text">
+<Title>
+<Text id="413">ÐÐµÑÐµÐ²ÐŸÐŽ ÑÐµÐºÑÑÐ°</Text>
+</Title>
+<Content>
+<Text id="414">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ Ð¿ÐµÑÐµÐ²ÐŸÐŽÐ°, Ð³ÐŽÐµ ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ ÑÐ·ÑÐº ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ ÑÑÐ°Ð³ÐŒÐµÐœÑÐŸÐ² ÑÐµÐºÑÑÐ° ÐŽÐ»Ñ ÑÐ°ÑÑÐµÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð "Ð Ð°Ð·ÐŽÐµÐ»Ðµ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐµÑÐµÐ²ÐµÑÑÐž ÑÐµÐºÑÑ".</Text>
+<Text id="415">Ð¡ÐœÐ°ÑÐ°Ð»Ð° Ð²ÑÐ±ÐµÑÐžÑÐµ Ð²Ñ
+ÐŸÐŽ Ð² ÑÐ¿ÐžÑÐŸÐº "Ð¡Ð²ÐŸÐ¹ÑÑÐ²Ð°". ÐÐžÐ¶Ðµ Ð¿ÐŸÑÐ²ÑÑÑÑ ÑÑÑÐŸÐºÐž ÑÐ¿ÐµÑÐžÑÐžÑÐœÐŸÐ³ÐŸ ÑÐ·ÑÐºÐ°, ÑÐ²ÑÐ·Ð°ÐœÐœÑÐµ Ñ ÑÑÐžÐŒ ÑÐ²ÐŸÐ¹ÑÑÐ²ÐŸÐŒ. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐžÐ¹ ÑÐ¿ÐžÑÐŸÐº "Ð¯Ð·ÑÐº Ð¿ÐµÑÐµÐ²ÐŸÐŽÐ°",ÑÑÐŸÐ±Ñ Ð²ÑÐ±ÑÐ°ÑÑ ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÐ¹ ÑÐ·ÑÐº Ðž Ð²Ð²ÐµÑÑÐž Ð¿ÐµÑÐµÐ²ÐµÐŽÐµÐœÐœÑÐ¹ ÑÐµÐºÑÑ Ð² ÐŸÐ±Ð»Ð°ÑÑÑ ÑÐµÐºÑÑÐ°, ÐŸÐ±ÑÐ°ÑÐ°ÑÑÑ Ðº "ÐÐ°ÑÐ°Ð»ÑÐœÐŸÐŒÑ ÑÑÐ°Ð³ÐŒÐµÐœÑÑ ÑÐµÐºÑÑÐ°",ÐµÑÐ»Ðž ÑÑÐŸ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ. ÐÐŸ ÐŸÐºÐŸÐœÑÐ°ÐœÐžÐž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ Ð¿ÐµÑÐµÐ²ÐŸÐŽ".</Text>
+<Text id="416">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐ¹ Ð¿ÐµÑÐµÐ²ÐŸÐŽ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ Ð² ÑÐ°Ð±Ð»ÐžÑÐµ "ÐÐ°ÐŽÐ°ÐœÐœÑÐµ Ð¿ÐµÑÐµÐ²ÐŸÐŽÑ" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ Ð¿ÐµÑÐµÐ²ÐŸÐŽ".</Text>
+<Text id="417">Ð§ÑÐŸÐ±Ñ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ Ð¿ÐµÑÐµÐ²ÐŸÐŽ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ, ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÑÐ¹ÑÐµ Ð² ÑÐµÐºÑÑÐŸÐ²ÐŸÐ¹ ÐŸÐ±Ð»Ð°ÑÑÐž "ÐÐµÑÐµÐ²ÐµÐŽÐµÐœÐœÑÐ¹ ÑÐµÐºÑÑ" Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ°ÐŒÐµÐœÐžÑÑ Ð¿ÐµÑÐµÐ²ÐŸÐŽ".</Text>
+</Content>
+</Part>
+<Part id="metadata_sets">
+<Title>
+<Text id="418">Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Text>
+</Title>
+<Content>
+<Text id="419">Ð­ÑÐŸÑ ÑÐ°Ð·ÐŽÐµÐ» ÐŸÐ±ÑÑÑÐœÑÐµÑ ÐŸÐ±Ð·ÐŸÑÐœÑÑ Ð¿Ð°ÐœÐµÐ»Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+. Ð "Ð Ð°Ð·ÐŽÐµÐ»Ðµ ÐŽÐžÐ·Ð°Ð¹ÐœÐ°" ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+". </Text>
+<Text id="420">Ð­ÑÐŸ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ,ÑÑÐŸÐ±Ñ ÑÐ°ÑÑÐŒÐŸÑÑÐµÑÑ ÐœÐ°Ð±ÐŸÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+,ÐºÐŸÑÐŸÑÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹,Ðž ÑÐ»ÐµÐŒÐµÐœÑÑ,ÐºÐŸÑÐŸÑÑÐµ ÑÐ²Ð»ÑÑÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž Ð² Ð¿ÑÐµÐŽÐµÐ»Ð°Ñ
+ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÐœÐ°Ð±ÐŸÑÐ°. ÐÑÐ±ÐµÑÐžÑÐµ ÐžÐ· ÑÐ¿ÐžÑÐºÐ° "ÐÐŸÑÑÑÐ¿ÐœÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+",ÑÑÐŸÐ±Ñ Ð²ÐžÐŽÐµÑÑ ÐŽÐµÑÐ°Ð»Ðž ÐžÑ
+ ÑÐ»ÐµÐŒÐµÐœÑÐŸÐ².</Text>
+<Text id="421">Ð§ÑÐŸÐ±Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŽÑÑÐ³ÐŸÐ¹ ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐ»Ñ Ð·Ð°Ð³ÑÑÐ¶ÐµÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° "ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÐÐ°Ð±ÐŸÑ ÐÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+" Ðž Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÐ°Ð¹Ð» Ñ ÐœÐ°Ð±ÐŸÑÐŸÐŒ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+ (.mds).</Text>
+<Text id="422">Ð ÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐœÐ°Ð±ÐŸÑÐ° ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐŸ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ Greenstone Editor for Metadata Sets (GEMS). ÐÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐºÐœÐŸÐ¿ÐºÑ "Ð ÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐÐ°Ð±ÐŸÑ ÐÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+", ÑÑÐŸÐ±Ñ Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ GEMS.</Text>
+<Text id="423">ÐÑÐ»Ðž ÐœÐ°Ð±ÐŸÑ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+ Ð²Ð°ÐŒ Ð±ÐŸÐ»ÑÑÐµ ÐœÐµ ÐœÑÐ¶ÐµÐœ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÐµÐ³ÐŸ Ðž ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° "Ð£ÐŽÐ°Ð»ÐžÑÑ ÐÐ°Ð±ÐŸÑ ÐÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+". ÐÑÐ»Ðž Ð²Ñ ÐœÐ°Ð·ÐœÐ°ÑÐžÐ»Ðž ÐºÐ°ÐºÐžÐµ-Ð»ÐžÐ±ÐŸ ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÐµ Ðº ÑÐ»ÐµÐŒÐµÐœÑÐ°ÐŒ Ð² ÑÐŽÐ°Ð»ÐµÐœÐœÐŸÐŒ ÐœÐ°Ð±ÐŸÑÐµ, Ñ Ð²Ð°Ñ ÑÐ¿ÑÐŸÑÑÑ ÐºÐ°Ðº Ñ ÐœÐžÐŒÐž Ð¿ÐŸÑÑÑÐ¿ÐžÑÑ Ð¿ÑÐž ÑÐ»ÐµÐŽÑÑÐµÐ¹ Ð·Ð°Ð³ÑÑÐ·ÐºÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="producing_your_collection">
+<Title>
+<Text id="424">ÐÐŸÑÑÑÐŸÐµÐœÐžÐµ ÐÐ°ÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="425">ÐÐŒÐµÑ ÑÐŸÐ±ÑÐ°ÐœÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÐŽÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð°ÐœÐœÐŸÑÐžÑÐŸÐ²Ð°Ð² ÐžÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž Ðž ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÐ°Ð² ÐŽÐžÐ·Ð°Ð¹Ðœ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž,ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐµÐ¿ÐµÑÑ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Greenstone. Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ,ÐºÐ°Ðº ÑÑÐŸ ÑÐŽÐµÐ»Ð°ÑÑ.</Text>
+<Part id="the_create_view">
+<Title>
+<Text id="426">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ</Text>
+</Title>
+<Content>
+<Text id="427">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ,ÑÑÐŸÐ±Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ,Ð²ÑÐ¿ÐŸÐ»ÐœÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐµ ÑÑÐµÐœÐ°ÑÐžÐž Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Greenstone ÐžÐ· ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž, ÐºÐŸÑÐŸÑÑÑ ÐÑ Ð¿ÐŸÐŽÐ³ÐŸÑÐŸÐ²ÐžÐ»Ðž. Ð©ÐµÐ»ÑÐŸÐº ÐœÐ° "ÐÐŸÑÑÑÐŸÐµÐœÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž" ÐœÐ°ÑÐžÐœÐ°ÐµÑ Ð¿ÑÐŸÑÐµÑÑ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÐµÐŒÑ, ÐºÐŸÑÐŸÑÐŸÐµ ÐŽÐ»Ñ ÑÑÐŸÐ³ÐŸ Ð¿ÐŸÑÑÐµÐ±ÑÐµÑÑÑ, Ð·Ð°Ð²ÐžÑÐžÑ ÐŸÑ ÑÐ°Ð·ÐŒÐµÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž ÑÐžÑÐ»Ð° ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÐµÐŒÑÑ
+ ÐžÐœÐŽÐµÐºÑÐŸÐ² (ÐŽÐ»Ñ ÐŸÐ³ÑÐŸÐŒÐœÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÑÑÐŸ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐ°ÑÑ). ÐÐœÐŽÐžÐºÐ°ÑÐŸÑ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ, ÐœÐ°ÑÐºÐŸÐ»ÑÐºÐŸ Ð²ÑÐ¿ÐŸÐ»ÐœÐµÐœ Ð¿ÑÐŸÑÐµÑÑ. Ð§ÑÐŸÐ±Ñ ÐŸÑÐŒÐµÐœÐžÑÑ Ð¿ÑÐŸÑÐµÑÑ Ð² Ð»ÑÐ±ÐŸÐµ Ð²ÑÐµÐŒÑ, ÐœÐ°Ð¶ÐŒÐžÑÐµ "ÐÑÐŒÐµÐœÐ° Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ".</Text>
+<Text id="428">ÐÐ°Ð¶Ð°Ð² ÐœÐ° "ÐÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÑÐ¹ Ð¿ÑÐŸÑÐŒÐŸÑÑ" Ð¿ÐŸÑÐ»Ðµ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð±ÑÐ»Ð° ÑÑÐ¿ÐµÑÐœÐŸ ÑÐŸÐ±ÑÐ°ÐœÐ°, ÐŒÐŸÐ¶ÐœÐŸ ÐŸÑÐºÑÑÑÑ Ð²ÐµÐ±-Ð±ÑÐ°ÑÐ·ÐµÑ Ñ Ð³Ð»Ð°Ð²ÐœÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="429">Ð ÐŒÐŸÐŽÑÑÐµ Ð­ÐºÑÐ¿ÐµÑÑ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ Ð·Ð°Ð¿ÐžÑÑ "ÐÐŸÐ³ Ð¡ÐŸÐŸÐ±ÑÐµÐœÐžÐ¹" ÑÐ»ÐµÐ²Ð°, ÑÑÐŸÐ±Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ, Ð±ÑÐ»Ðž Ð»Ðž Ð¿ÑÐµÐŽÑÐŽÑÑÐžÐµ Ð¿ÐŸÐ¿ÑÑÐºÐž ÑÐºÐŸÐœÑÑÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÑÐ¿ÐµÑÐœÑ ÐžÐ»Ðž ÐœÐµÑ. ÐÑÐ±ÐµÑÐžÑÐµ Ð¶ÐµÐ»Ð°ÐµÐŒÑÑ Ð·Ð°Ð¿ÐžÑÑ,ÑÐµÐ»ÐºÐ°Ñ Ð¿ÐŸ Ð²ÑÐ±ÑÐ°ÐœÐœÐŸÐ¹ ÐŽÐ°ÑÐµ Ð² ÑÐ¿ÐžÑÐºÐµ "ÐÑÑÐŸÑÐžÑ Ð·Ð°Ð¿ÐžÑÐž".</Text>
+</Content>
+</Part>
+<Part id="import_and_build_settings">
+<Title>
+<Text id="430">ÐÐŒÐ¿ÐŸÑÑ Ðž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ</Text>
+</Title>
+<Content>
+<Text id="431">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ, ÐºÐ°Ðº Ð¿ÐŸÐ»ÑÑÐžÑÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑÐŒ ÐžÐŒÐ¿ÐŸÑÑÐ° Ðž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ°ÐŒ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ. ÐÐ° ÐŽÐŸÐ¿ÐŸÐ»ÐœÐžÑÐµÐ»ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐµÐ¹ Ð¿ÐŸ ÐžÐŒÐ¿ÐŸÑÑÑ Ðž Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÑÐžÑÐ°Ð¹ÑÐµ Ð³Ð»Ð°Ð²Ñ 1 Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ð° ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° Greenstone.</Text>
+<Text id="432">Ð£Ð¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒÐž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ°ÐŒÐž ÑÐŽÐµÐ»Ð°ÐœÐŸ Ð¿ÐŸÐŽÐŸÐ±ÐœÐŸ ÑÐŸÐŒÑ ÑÐ¿ÐŸÑÐŸÐ±Ñ, ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÐ¿ÐžÑÐ°Ðœ Ð¿ÑÐž "ÐÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐž Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ²" Ð² ÐÐ»Ð°Ð³ÐžÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°. ÐÐµÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐ»Ñ ÑÑÐµÐ±ÑÑÑ ÑÐžÑÐ»ÐµÐœÐœÑÑ
+ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ². ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑ
+ ÐžÐ»Ðž ÐœÐ°Ð¿ÐµÑÐ°ÑÐ°ÑÑ ÐžÐ»Ðž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÑÑÑÐµÐ»ÐºÐž Ð²Ð²ÐµÑÑ
+ Ðž Ð²ÐœÐžÐ·, ÑÑÐŸÐ±Ñ ÑÐ²ÐµÐ»ÐžÑÐžÑÑ ÐžÐ»Ðž ÑÐŒÐµÐœÑÑÐžÑÑ ÑÐµÐºÑÑÐµÐµ Ð·ÐœÐ°ÑÐµÐœÐžÐµ (Ð² ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÑÐ»ÑÑÐ°ÑÑ
+ ÐžÐœÑÐµÑÑÐµÐ¹Ñ ÐŸÐ³ÑÐ°ÐœÐžÑÐžÐ²Ð°ÐµÑ ÐŽÐžÐ°Ð¿Ð°Ð·ÐŸÐœ, Ð² ÐºÐŸÑÐŸÑÑÐ¹ ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÐŸÐ¹ÑÐž). ÐÑÑÐ³ÐžÐµ Ð¿ÐŸÐ»Ñ ÑÐ²Ð»ÑÑÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž Ð¿ÑÐž ÑÐµÐ»ÑÐºÐµ Ð¿ÐŸ ÐºÐœÐŸÐ¿ÐºÐµ (ÐÐŸÐ²ÑÐŸÑÐœÑÐ¹ ÑÐµÐ»ÑÐŸÐº ÐŽÐµÐ»Ð°ÐµÑ ÐžÑ
+ ÐœÐµÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž).</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="miscellaneous">
+<Title>
+<Text id="433">Ð Ð°Ð·ÐœÐŸÐµ</Text>
+</Title>
+<Content>
+<Text id="434">Ð­ÑÐŸÑ ÑÐ°Ð·ÐŽÐµÐ» ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÑ ÐŸÑÐŸÐ±ÐµÐœÐœÐŸÑÑÐž ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°,ÐºÐŸÑÐŸÑÑÐµ ÐœÐµ ÑÐ²ÑÐ·Ð°ÐœÑ ÐœÐž Ñ ÐºÐ°ÐºÐžÐŒ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐžÐŒ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµÐŒ.</Text>
+<Part id="preferences">
+<Title>
+<Text id="435">ÐÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÑ</Text>
+</Title>
+<Content>
+<Text id="436">Ð ÑÑÐŸÐŒ ÑÐ°Ð·ÐŽÐµÐ»Ðµ ÐŸÐ±ÑÑÑÐœÑÐµÑÑÑ ÐŽÐžÐ°Ð»ÐŸÐ³ Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÐ¹,ÐŽÐŸÑÑÑÐ¿ÐœÑÐ¹ Ð¿ÑÐž ÐŸÑÐºÑÑÑÐžÐž "Ð€Ð°Ð¹Ð»Ð°", Ð° Ð·Ð°ÑÐµÐŒ "ÐÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÐ¹".</Text>
+<Text id="437">ÐÐµÑÐ²Ð°Ñ ÐŸÐ¿ÑÐžÑ "ÐÐ±ÑÐµÐµ" - ÑÑÐŸ ÑÐµÐºÑÑÐŸÐ²ÐŸÐµ Ð¿ÐŸÐ»Ðµ ÐŽÐ»Ñ Ð²Ð²ÐµÐŽÐµÐœÐžÑ Ð°ÐŽÑÐµÑÐ° Ð²Ð°ÑÐµÐ¹ ÑÐ»ÐµÐºÑÑÐŸÐœÐœÐŸÐ¹ Ð¿ÐŸÑÑÑ. ÐÐœ Ð±ÑÐŽÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ðœ Ð² Ð·ÐœÐ°ÑÐµÐœÐžÐž ÐŒÐµÑÐ°-ÐŽÐ°ÐœÐœÑÑ
+ "Ð¡ÐŸÐ·ÐŽÐ°ÑÐµÐ»Ñ" Ðž "ÐÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÑÐ¹". Ð¡Ð»ÐµÐŽÑÑÐ°Ñ ÐŸÐ¿ÑÐžÑ - ÑÑÐŸ Ð²ÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐµ ÐŒÐµÐœÑ Ñ ÑÐ·ÑÐºÐ°ÐŒÐž, Ð² ÐºÐŸÑÐŸÑÑÑ
+ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐÐœÑÐµÑÑÐµÐ¹Ñ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœ. ÐÑÐ»Ðž ÐÑ ÐžÐ·ÐŒÐµÐœÑÐµÑÐµ ÑÐ»ÐŸÐ²Ð°ÑÑ, Ð²ÑÐ±ÐžÑÐ°Ñ ÐºÐ°ÐºÐŸÐ¹-Ð»ÐžÐ±ÐŸ ÐžÐ· ÑÐ¿ÐžÑÐºÐ°, ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ Ð¿ÐµÑÐµÐ·Ð°Ð³ÑÑÐ·ÐžÑÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ, ÑÑÐŸÐ±Ñ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ ÐœÐŸÐ²ÑÐµ ÑÑÑÐŸÐºÐž ÑÐ·ÑÐºÐ° ÐžÐ· ÑÑÐŸÐ³ÐŸ ÑÐ»ÐŸÐ²Ð°ÑÑ.</Text>
+<Text id="438">ÐÑÐ»Ðž Ð²ÑÐ±ÑÐ°ÐœÐ° "ÐÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐžÐ·Ð²Ð»ÐµÐºÐ°ÐµÐŒÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+", ÑÐ°Ð·Ð»ÐžÑÐœÐŸÐµ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÐµ, ÑÐ²ÑÐ·Ð°ÐœÐœÐŸÐµ Ñ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐŒÐž, Ð²ÑÐµÐ³ÐŽÐ° Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð²ÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐ»Ðž Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÐžÐ·Ð²Ð»ÐµÑÐµÐœÑ ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². ÐÑÐŒÐµÐœÐ° ÑÑÐŸÐ³ÐŸ Ð²ÑÐ±ÐŸÑÐ° ÑÐºÑÑÐ²Ð°ÐµÑ ÑÑÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, Ñ
+ÐŸÑÑ ÐŸÐœÐž Ð²ÑÑ ÐµÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑ Ð² ÑÐµÑÐµÐœÐžÐµ ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÐºÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð² ÑÐ°ÐŒÐºÐ°Ñ
+ ÐŸÐºÐŸÐœÑÐ°ÑÐµÐ»ÑÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Greenstone. ÐÑÐ»Ðž Ð²ÑÐ±ÑÐ°ÐœÐŸ "ÐÐŸÐºÐ°Ð·Ð°ÑÑ ÑÐ°Ð·ÐŒÐµÑÑ ÑÐ°Ð¹Ð»Ð°", ÑÐŸ ÑÐ°Ð·ÐŒÐµÑ ÑÐ°Ð¹Ð»Ð° Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ ÑÑÐŽÐŸÐŒ Ñ ÐºÐ°Ð¶ÐŽÑÐŒ ÑÐ°Ð¹Ð»ÐŸÐŒ Ð² ÑÐ°Ð±ÐŸÑÐµÐŒ Ð¿ÑÐŸÑÑÑÐ°ÐœÑÑÐ²Ðµ, Ð° ÑÐ°ÐºÐ¶Ðµ Ð² ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐŒ ÐŽÐµÑÐµÐ²Ðµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð² Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑÑ
+ Gather Ðž Enrich.</Text>
+<Text id="439">ÐÐ°ÐœÐµÐ»Ñ "Ð¡Ð¿ÐŸÑÐŸÐ±" ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÑÐ¿ÑÐ°Ð²Ð»ÐµÐœÐžÑ ÑÑÐŸÐ²ÐœÐµÐŒ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸÑÑÐµÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°. ÐÐ° ÑÐ°ÐŒÐŸÐŒ ÐœÐžÐ¶ÐœÐµÐŒ ÑÑÐŸÐ²ÐœÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐŸÐº ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ "ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ Ð¿ÐŸÐŒÐŸÑÐœÐžÐº", Ð¿ÑÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ Ð¿ÑÐŸÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð±Ð»ÐŸÐºÐžÑÐŸÐ²Ð°ÐœÐŸ, Ð¿Ð°ÑÐ°ÐŒÐµÑÑÑ, ÑÑÐµÐ±ÑÑÑÐžÐµ Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸÐ³ÐŸ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÑ, ÑÐºÑÑÑÑ Ðž Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÑÐŸÐžÐ·Ð²ÐŸÐŽÐžÑÑÑ ÐŒÐžÐœÐžÐŒÐ°Ð»ÑÐœÐŸ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÐŒ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸÐŒ Ð·Ð°Ð¿ÐžÑÐµÐ¹. ÐÐ°ÐŸÐ±ÐŸÑÐŸÑ, ÐœÐ°ÐžÐ²ÑÑÑÐ°Ñ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐ° "Ð­ÐºÑÐ¿ÐµÑÑ" ÐŸÐ±ÐµÑÐ¿ÐµÑÐžÐ²Ð°ÐµÑ ÐŽÐŸÑÑÑÐ¿ ÐºÐŸ Ð²ÑÐµÐŒ ÑÑÐµÐŽÑÑÐ²Ð°ÐŒ Ð¿ÑÐŸÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÑ, Ð²ÐºÐ»ÑÑÐ°Ñ Ð¿ÐŸÐ·ÐžÑÐžÐŸÐœÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿Ð»Ð°Ð³ÐžÐœÐŸÐ² Ðž Ð¿ÑÐ°Ð²ÐžÐ»ÑÐœÐŸÐµ Ð²ÑÑÐ°Ð¶ÐµÐœÐžÐµ Ð¿Ð°ÑÐ°ÐŒÐµÑÑÐŸÐ², Ð° ÑÐ°ÐºÐ¶Ðµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð¿ÐŸÐ»ÐœÑÐ¹ Ð²ÑÑ
+ÐŸÐŽ ÐžÐ· Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÑÐŸÐ±Ñ Ð·Ð°ÑÐžÐºÑÐžÑÐŸÐ²Ð°ÑÑ Ð² Ð¶ÑÑÐœÐ°Ð»Ðµ Ð·Ð°Ð¿ÐžÑÐµÐ¹. Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐžÐ»Ðž Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ ÑÐ¿ÐŸÑÐŸÐ±Ñ, ÐºÐ»ÐžÐºÐœÐžÑÐµ ÑÐ°ÐŽÐžÐŸ-ÐºÐœÐŸÐ¿ÐºÑ, ÑÐ»ÐµÐŽÑÑÑÑÑ Ð·Ð° ÑÐ¿ÐŸÑÐŸÐ±ÐŸÐŒ, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÐœÑÐµÑÐµÑÑÐµÑ ÐÐ°Ñ. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð±ÑÑÑÑÐŸ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ, ÐºÐ°ÐºÐŸÐ¹ ÑÐ¿ÐŸÑÐŸÐ± ÐÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ, ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°Ñ Ð»ÐžÐœÐµÐ¹ÐºÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹ Ð² ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐŒ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐµ.</Text>
+<Text id="440">ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ ÐŒÐŸÐ¶ÐµÑ Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÑÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÑÐµÑ
+ÐœÐŸÐ»ÐŸÐ³ÐžÑÐµÑÐºÐžÐµ Ð¿ÑÐŸÑÐµÑÑÑ Ð¿ÑÐž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐž, ÐºÐ°ÐºÐžÐµ ÐžÐ· ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÐ¹ ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ² ÑÐ²Ð»ÑÑÑÑÑ Ð²ÐžÐŽÐžÐŒÑÐŒÐž. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÐºÐ»Ð°Ð²ÐžÑÑ "Ð¢ÐµÑ
+ÐœÐŸÐ»ÐŸÐ³ÐžÑÐµÑÐºÐžÐµ Ð¿ÑÐŸÑÐµÑÑÑ", ÑÑÐŸÐ±Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ, ÐºÐ°ÐºÐžÐµ Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÑÐ²Ð»ÑÑÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž, Ð¿ÑÐŸÐ²ÐµÑÑÑ Ð¿ÐŸÐ»Ñ ÑÑÐŽÐŸÐŒ Ñ ÑÐµÐŒÐž Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÐµÐœÐžÑÐŒÐž, ÐºÐŸÑÐŸÑÑÐµ ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒÐž. ÐÐŒÐµÑÑÐŸ ÑÑÐŸÐ³ÐŸ ÐŒÐŸÐ¶ÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐžÐ¹ ÑÐ¿ÐžÑÐŸÐº Ð²ÐœÐžÐ·Ñ ÑÐºÑÐ°ÐœÐ°,ÑÑÐŸÐ±Ñ Ð²ÑÐ±ÑÐ°ÑÑ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸ Ð·Ð°ÐŽÐ°ÐœÐœÑÐµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž. ÐÐ°ÐºÑÑÑÐžÐµ ÐŽÐžÐ°Ð»ÐŸÐ³Ð° Ð¿ÑÐµÐŽÐ¿ÐŸÑÑÐµÐœÐžÐ¹ Ð·Ð°ÐºÑÐµÐ¿Ð»ÑÐµÑ ÑÑÐž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž ÑÐµÑ
+ÐœÐŸÐ»ÐŸÐ³ÐžÑÐµÑÐºÐŸÐ³ÐŸ Ð¿ÑÐŸÑÐµÑÑÐ°. Ð­ÑÐž ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž Ñ
+ÑÐ°ÐœÑÑÑÑ Ð²ÐŒÐµÑÑÐµ Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹,Ð° ÐœÐµ Ð² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°.</Text>
+<Text id="441">ÐÐ»Ð°Ð²ÐžÑÐ° "Ð¡ÐŸÐµÐŽÐžÐœÐµÐœÐžÐµ" Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐÐ°ÐŒ ÐžÐ·ÐŒÐµÐœÑÑÑ Ð¿ÑÑÑ Ðº Ð»ÐŸÐºÐ°Ð»ÑÐœÐŸÐŒÑ ÑÐµÑÐ²ÐµÑÑ Greenstone, ÐºÐŸÑÐŸÑÑÐ¹ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ Ð¿ÑÐµÐŽÐ²Ð°ÑÐžÑÐµÐ»ÑÐœÐŸÐ³ÐŸ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÐŸÐŒÐµ ÑÐŸÐ³ÐŸ ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐžÑÑ ÐŒÐŸÐŽÑÐ»Ñ ÐŽÐŸÑÑÑÐ¿Ð° Ðº ÐÐœÑÐµÑÐœÐµÑÑ Ð¿ÑÐŸÐºÑÐž (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, ÐŽÐ»Ñ Ð·Ð°Ð³ÑÑÐ·ÐºÐž ÑÐ°Ð¹Ð»ÐŸÐ²; ÑÐŒÐŸÑÑÐž ÑÐ°Ð·ÐŽÐµÐ» ÐÐ°Ð³ÑÑÐ¶Ð°ÑÑ Ð€Ð°Ð¹Ð»Ñ ÐžÐ· ÐÐœÑÐµÑÐœÐµÑÐ° ÐŽÐ»Ñ Ð¿ÐŸÐŽÑÐŸÐ±ÐœÐŸÑÑÐµÐ¹). ÐÐŸÐŒÐµÑÑÑÐµ ÑÐ»Ð°Ð³ÐŸÐ²ÑÑ ÐºÐœÐŸÐ¿ÐºÑ, ÑÑÐŸÐ±Ñ Ð²ÐºÐ»ÑÑÐžÑÑ ÐŒÐŸÐŽÑÐ»Ñ ÐŽÐŸÑÑÑÐ¿Ð°, Ðž ÑÐºÐ°Ð¶ÐžÑÐµ ÐŽÐµÑÐ°Ð»Ðž Ð°ÐŽÑÐµÑÐ° ÑÐµÑÐ²ÐµÑÐ° Ð¿ÑÐŸÐºÑÐž Ðž ÐœÐŸÐŒÐµÑ Ð¿ÐŸÑÑÐ°. ÐÐŸÐŽÑÐ»Ñ ÐŽÐŸÑÑÑÐ¿Ð° Ð±ÑÐŽÐµÑ Ð°ÐºÑÐžÐ²ÐžÑÐŸÐ²Ð°Ðœ Ð¿ÑÐž Ð·Ð°ÐºÑÑÑÐžÐž ÐŽÐžÐ°Ð»ÐŸÐ³ÐŸÐ²ÐŸÐ³ÐŸ ÐŸÐºÐœÐ° ÐÐ¿ÑÐžÐ¹.</Text>
+<Text id="442">Ð ÑÐµÑÐµÐœÐžÐµ ÑÐµÑÑÐžÐž ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ ÐŒÐŸÐ¶ÐµÑ ÐŽÐ°Ð²Ð°ÑÑ Ð¿ÑÐµÐŽÑÐ¿ÑÐµÐŽÐžÑÐµÐ»ÑÐœÑÐµ ÑÐŸÐŸÐ±ÑÐµÐœÐžÑ, ÐºÐŸÑÐŸÑÑÐµ ÐžÐœÑÐŸÑÐŒÐžÑÑÑÑ ÐÐ°Ñ ÐŸ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÑ
+ ÐœÐµÐ¿ÑÐµÐŽÐ²ÐžÐŽÐµÐœÐœÑÑ
+ Ð¿ÐŸÑÐ»ÐµÐŽÑÑÐ²ÐžÑÑ
+ ÐÐ°ÑÐžÑ
+ ÐŽÐµÐ¹ÑÑÐ²ÐžÐ¹. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð·Ð°Ð±Ð»ÐŸÐºÐžÑÐŸÐ²Ð°ÑÑ ÑÐŸÐŸÐ±ÑÐµÐœÐžÐµ, Ð²ÑÐ±ÐžÑÐ°Ñ Ð¿ÐŸÐ»Ðµ "ÐÐµ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÑÑÐŸ Ð¿ÑÐµÐŽÑÐ¿ÑÐµÐ¶ÐŽÐµÐœÐžÐµ ÑÐœÐŸÐ²Ð°". ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÐŸÐ·ÐŸÐ±ÐœÐŸÐ²ÐžÑÑ Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÐµ Ð¿ÑÐµÐŽÑÐ¿ÑÐµÐ¶ÐŽÐ°ÑÑÐžÑ
+ ÑÐŸÐŸÐ±ÑÐµÐœÐžÐ¹,ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ ÐºÐ»Ð°Ð²ÐžÑÑ "ÐÑÐµÐŽÑÐ¿ÑÐµÐ¶ÐŽÐµÐœÐžÐµ". ÐÑÐ±ÐµÑÐžÑÐµ Ð¿ÐŸÐ»Ðµ ÑÑÐŽÐŸÐŒ Ñ Ð¿ÑÐµÐŽÑÐ¿ÑÐµÐ¶ÐŽÐ°ÑÑÐžÐŒÐž ÑÐŸÐŸÐ±ÑÐµÐœÐžÑÐŒÐž, ÐµÑÐ»Ðž ÐÑ Ñ
+ÐŸÑÐžÑÐµ ÑÐœÐŸÐ²Ð° Ð¿ÐŸÐ»ÑÑÐ°ÑÑ ÐžÑ
+.</Text>
+</Content>
+</Part>
+<Part id="file_associations">
+<Title>
+<Text id="443">ÐÑÑÐŸÑÐžÐ°ÑÐžÐž ÑÐ°Ð¹Ð»Ð°</Text>
+</Title>
+<Content>
+<Text id="444">ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐ¹ ÐÐœÑÐµÑÑÐµÐ¹Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÑÐ¿ÐµÑÐžÑÐžÑÐµÑÐºÐžÐµ Ð¿ÑÐžÐºÐ»Ð°ÐŽÐœÑÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, ÑÑÐŸÐ±Ñ ÐŸÑÐºÑÑÐ²Ð°ÑÑ ÑÐ¿ÐµÑÐžÑÐžÑÐœÑÐµ ÑÐžÐ¿Ñ ÑÐ°Ð¹Ð»ÐŸÐ². Ð§ÑÐŸÐ±Ñ ÐžÐ·ÐŒÐµÐœÐžÑÑ Ð°ÑÑÐŸÑÐžÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ ÑÐ°Ð¹Ð»Ñ ÐŸÑÐºÑÑÐ²Ð°ÑÑ ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»" Ðž ÑÐµÐ»ÐºÐ°ÑÑ "ÐÑÑÐŸÑÐžÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ ÑÐ°Ð¹Ð»Ñ".</Text>
+<Text id="445">Ð§ÑÐŸÐ±Ñ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ Ð°ÑÑÐŸÑÐžÐ°ÑÐžÐž, Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÐµÐ»ÐµÐ²ÐŸÐµ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµ ÑÐ°Ð¹Ð»Ð° ÐžÐ· ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐ³ÐŸ ÑÐ¿ÐžÑÐºÐ° ÐžÐ»Ðž ÐœÐ°Ð¿ÐžÑÐžÑÐµ ÐœÐŸÐ²ÐŸÐµ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµ (ÐœÐµ Ð²ÐºÐ»ÑÑÐ°Ñ "."). ÐÐ°ÑÐµÐŒ ÐžÐ»Ðž ÐœÐ°Ð¿ÐžÑÐžÑÐµ Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐµÐŒ Ð¿ÐŸÐ»Ðµ ÐºÐŸÐŒÐ°ÐœÐŽÑ,Ð·Ð°Ð¿ÑÑÐºÐ°ÑÑÑÑ Ð¶ÐµÐ»Ð°ÑÐµÐ»ÑÐœÐŸÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ,ÐžÐ»Ðž Ð²ÑÐ±ÐµÑÐžÑÐµ Ð¿ÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ ÐžÐ· ÐŽÐžÐ°Ð»ÐŸÐ³ÐŸÐ²ÐŸÐ³ÐŸ ÐŸÐºÐœÐ° "ÐÑÐŸÑÐŒÐŸÑÑ". ".%1" ÐŒÐŸÐ¶ÐµÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑÑÑ Ð² ÐºÐŸÐŒÐ°ÐœÐŽÐµ Ð·Ð°Ð¿ÑÑÐºÐ°, ÑÑÐŸÐ±Ñ Ð²ÑÑÐ°Ð²ÐžÑÑ ÐžÐŒÑ ÑÐ°Ð¹Ð»Ð°, ÐºÐŸÑÐŸÑÑÐ¹ ÐŽÐŸÐ»Ð¶ÐµÐœ ÐŸÑÐºÑÑÑÑÑÑ. ÐÐ°Ðº ÑÐŸÐ»ÑÐºÐŸ ÐŸÐœÐž Ð·Ð°Ð¿ÐŸÐ»ÐœÐµÐœÑ,Ð¿ÑÐœÐºÑ "ÐÐŸÐ±Ð°Ð²ÐžÑÑ" ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒ Ðž ÐŒÐŸÐ¶ÐœÐŸ ÑÐµÐ»ÑÐºÐŸÐŒ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ Ð°ÑÑÐŸÑÐžÐ°ÑÐžÑ.</Text>
+<Text id="446">Ð§ÑÐŸÐ±Ñ ÐŸÑÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ Ð°ÑÑÐŸÑÐžÐ°ÑÐžÑ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐµ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµ ÑÐ°Ð¹Ð»Ð°. ÐÑÐ±Ð°Ñ ÑÑÑÐµÑÑÐ²ÑÑÑÐ°Ñ ÐºÐŸÐŒÐ°ÐœÐŽÐ° ÑÐ²ÑÐ·Ðž Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ Ð² Ð¿ÐŸÐ»Ðµ Ð·Ð°Ð¿ÑÑÐºÐ° ÐºÐŸÐŒÐ°ÐœÐŽ. ÐÑÑÐµÐŽÐ°ÐºÑÐžÑÑÐ¹ÑÐµ ÐµÐµ Ðž Ð·Ð°ÑÐµÐŒ ÑÐµÐ»ÐºÐœÐžÑÐµ "ÐÐ°ÐŒÐµÐœÐžÑÑ".</Text>
+<Text id="447">Ð§ÑÐŸÐ±Ñ ÑÐŽÐ°Ð»ÐžÑÑ Ð°ÑÑÐŸÑÐžÐ°ÑÐžÑ, Ð²ÑÐ±ÐµÑÐžÑÐµ ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐµ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµ ÑÐ°Ð¹Ð»Ð° Ðž ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð£ÐŽÐ°Ð»ÐžÑÑ".(Ð Ð°ÑÑÐžÑÐµÐœÐžÐµ ÑÐ°Ð¹Ð»Ð° ÐŸÑÑÐ°ÐµÑÑÑ Ð² ÐœÐžÑÐ¿Ð°ÐŽÐ°ÑÑÐµÐŒ ÑÐ¿ÐžÑÐºÐµ "ÐÐ»Ñ ÐŸÐºÐŸÐœÑÐ°ÐœÐžÑ ÑÐ°Ð¹Ð»ÐŸÐ²").</Text>
+<Text id="448">ÐÑÐŸÑÐžÐ°ÑÐžÐ²ÐœÑÐµ ÑÐ°Ð¹Ð»Ñ Ñ
+ÑÐ°ÐœÑÑÑÑ Ð² Ð³Ð»Ð°Ð²ÐœÐŸÐ¹ Ð¿Ð°Ð¿ÐºÐµ ÐÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÐŸÐ³ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°, Ð² ÑÐ°Ð¹Ð»Ðµ, ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÐŸÐŒ "associations.xml".</Text>
+</Content>
+</Part>
+<Part id="exporting_collections_to_cddvd">
+<Title>
+<Text id="449">Ð­ÐºÑÐ¿ÐŸÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐœÐ° CD/DVD</Text>
+</Title>
+<Content>
+<Text id="450">Greenstone ÐŒÐŸÐ¶ÐµÑ ÑÐºÑÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐŸÐŽÐœÑ ÐžÐ»Ðž Ð±ÐŸÐ»ÐµÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ð² ÑÐ°ÐŒÐŸÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÑÑÐžÐ¹ÑÑ CD/DVD Ð¿ÐŸÐŽ Windows. Ð§ÑÐŸÐ±Ñ ÑÑÐŸ ÑÐŽÐµÐ»Ð°ÑÑ, ÐŽÐŸÐ»Ð¶ÐµÐœ Ð±ÑÑÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ Ð¿Ð°ÐºÐµÑ "Ð­ÐºÑÐ¿ÐŸÑÑ Ð² CD-ROM". ÐÐœ ÐœÐµ Ð²ÐºÐ»ÑÑÐµÐœ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ, Ð¿ÐŸÑÑÐŸÐŒÑ ÐÑ ÐŽÐŸÐ»Ð¶ÐœÑ ÐžÐ·ÐŒÐµÐœÐžÑÑ ÐÐ°ÑÑ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÑ, ÑÑÐŸÐ±Ñ ÐµÐ³ÐŸ Ð²ÐºÐ»ÑÑÐžÑÑ.</Text>
+<Text id="451">Ð§ÑÐŸÐ±Ñ ÑÐºÑÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐŸÑÐºÑÐŸÐ¹ÑÐµ ÐŒÐµÐœÑ "Ð€Ð°Ð¹Ð»" Ðž Ð²ÑÐ±ÐµÑÐžÑÐµ "Ð­ÐºÑÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÑÑ Ð² CD-ROM/DVD...". ÐÐŸÑÐ²Ð»ÑÐµÑÑÑ ÑÐ¿ÐžÑÐŸÐº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÑÐŸÐ±ÑÐ°ÐœÐžÐ¹ Greenstone; ÑÐµÐ»ÐºÐœÐžÑÐµ ÐœÐ° Ð»ÑÐ±ÐŸÐ¹, ÑÑÐŸÐ±Ñ ÑÐ²ÐžÐŽÐµÑÑ ÐµÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ. ÐÐŸÐŒÐµÑÑÑÐµ Ð²ÑÐ±ÑÐ°ÐœÐœÑÐµ Ð¿ÐŸÐ»Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐŽÐ»Ñ ÑÐºÑÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²Ð²ÐµÑÑÐž ÐžÐŒÑ CD/DVD Ð² Ð¿ÐŸÐ»Ðµ: ÑÑÐŸ ÑÐŸ, ÑÑÐŸ Ð¿ÐŸÑÐ²ÐžÑÑÑ Ð² ÑÑÐ°ÑÑÐŸÐ²ÐŸÐŒ ÐŒÐµÐœÑ, ÐºÐŸÐ³ÐŽÐ° CD/DVD Ð±ÑÐŽÐµÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ. ÐÐ°ÑÐµÐŒ ÑÐµÐ»ÐºÐœÐžÑÐµ "Ð­ÐºÑÐ¿ÐŸÑÑ". ÐÑÐŸÑÐµÑÑ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐŒÐœÐŸÐ³ÐžÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ² Ðž ÐŒÐŸÐ¶ÐµÑ Ð·Ð°ÐœÑÑÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐŒÐžÐœÑÑ.</Text>
+<Text id="452">ÐÐŸÑÐ»Ðµ ÐŸÐºÐŸÐœÑÐ°ÐœÐžÑ Greenstone Ð¿ÐŸÐºÐ°Ð¶ÐµÑ ÐžÐŒÑ Ð¿Ð°Ð¿ÐºÐž, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐµÐ¹ ÑÐºÑÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ Ð¿ÐžÑÑÑÐžÐ¹ ÐºÐŸÐŒÐ¿Ð°ÐºÑ-ÐŽÐžÑÐº ÐŽÐ»Ñ ÐºÐŸÐ¿ÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐµÐ³ÐŸ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÐœÐ° ÑÐžÑÑÑÐ¹ CD/DVD.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+</Content>
+</Section>
+<Section id="tagging_document_files">
+<Title>
+<Text id="453">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÑÑÐ³ÐŸÐ² Ðº ÑÐ°Ð¹Ð»Ð°ÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ</Text>
+</Title>
+<Content>
+<Text id="454">ÐÑÐ»Ðž ÐžÑÑ
+ÐŸÐŽÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐºÐŸÑÐŸÑÑÑ Ð¶ÐµÐ»Ð°ÐµÑÐµ Ð¿ÐŸÑÑÑÐŸÐžÑÑ, ÐŸÑÐ³Ð°ÐœÐžÐ·ÐŸÐ²Ð°ÐœÑ Ð² ÑÐ°Ð·ÐŽÐµÐ»Ñ Ðž Ð¿ÐŸÐŽÑÐ°Ð·ÐŽÐµÐ»Ñ, ÑÐŸ Ð²Ð°ÐŒ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÑÐºÐ°Ð·Ð°ÑÑ ÑÑÐŸ Ð² ÐžÑÑ
+ÐŸÐŽÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ (source files), ÑÐ°Ðº ÑÑÐŸÐ±Ñ Greenstone Ð¿ÑÐž ÑÐŸÐ·ÐŽÐ°ÐœÐžÐž ÐÐ³Ð»Ð°Ð²Ð»ÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐŸÐ³ ÑÐŸÐ·ÐŽÐ°ÑÑ ÑÑÑÐ»ÐºÐž (active links) Ðº ÐºÐ°Ð¶ÐŽÐŸÐŒÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ. Ð­ÑÐŸ ÐŽÐµÐ»Ð°ÐµÑÑÑ Ð¿ÑÑÐµÐŒ ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ â Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ° Ðž Ð¿ÐŸÐŽÐ·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ° ÑÐ°Ð·ÐŽÐµÐ»Ð° Ðž Ð¿ÐŸÐŽÑÐ°Ð·ÐŽÐµÐ»Ð°.</Text>
+<Text id="455">ÐÑÑ
+ÐŸÐŽÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ - ÑÑÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ, ÐºÐ°Ðº Ð¿ÑÐ°Ð²ÐžÐ»ÐŸ Ð¿ÐŸÐ»ÑÑÐµÐœÐœÑÐµ Ð¿ÐŸÑÐ»Ðµ Ð¿ÑÐŸÑÐµÑÑÐ° ÐÐ Ð¡, Ðž ÑÐ²Ð»ÑÑÑÐžÐµÑÑ ÐœÐ°Ð±ÐŸÑÐŸÐŒ ÑÐµÐºÑÑÐŸÐ²ÑÑ
+ ÑÐ°Ð»ÐŸÐ² Word, Ð²ÐºÐ»ÑÑÐ°Ñ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐžÑ. ÐÑÐ»Ðž ÐŸÐœÐž ÑÐ²Ð»ÑÑÑÑÑ ÑÐ°Ð¹Ð»Ð°ÐŒÐž Word, ÑÐŸ ÐŸÐœÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÑ Ð² Greenstone Ñ Ð¿ÐŸÐŒÐŸÑÑÑ Word plugin. ÐÐ°Ðº Ð°Ð»ÑÑÐµÑÐœÐ°ÑÐžÐ²Ð° , ÐŸÐœÐž ÑÐ°Ðº Ð¶Ðµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÐœÑ Ð² ÑÐŸÑÐŒÐ°Ñ HTML, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ HTML plugin.</Text>
+<Text id="456">Ð Ð»ÑÐ±ÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ, ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŸ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ°Ñ
+ Ðž Ð¿ÐŸÐŽÐ·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐ°Ñ
+ ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÑÐºÐ°Ð·Ð°ÐœÑ ÑÑÐ³Ð°ÐŒÐž Ð² ÑÐµÐºÑÑÐµ ÑÐ»ÐµÐŽÑÑÑÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ:</Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>&lt;Description&gt;</CodeLine>
+<Text type="code" id="457">&lt;Metadata name="Title"&gt;Realizing human rights for poor people: Strategies for achieving the international development targets&lt;/Metadata&gt;</Text>
+<CodeLine>&lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="458"><i>(text of section goes here)</i></Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="459">ÐÐ°ÑÐºÐµÑÑ &lt;!â...â&gt; ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ, ÑÐ°Ðº ÐºÐ°Ðº ÐŸÐœÐž ÑÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÐºÐŸÐŒÐŒÐµÐœÑÐ°ÑÐžÐž Ð² HTML; ÑÐ°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ, ÑÑÐž ÑÑÐ³Ðž ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐ² ÐœÐµ Ð±ÑÐŽÑÑ Ð²Ð»ÐžÑÑÑ ÐœÐ° ÑÐŸÑÐŒÐ°ÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°.</Text>
+<Text id="460">Ð ÐŸÐ±Ð»Ð°ÑÑÐž Description (ÐŒÐµÐ¶ÐŽÑ ÑÑÐ³Ð°ÐŒÐž &lt;Description&gt;, &lt;/Description&gt; ÐŒÐŸÐ¶ÐœÐŸ ÑÐºÐ°Ð·Ð°ÑÑ ÐŽÑÑÐ³ÐžÐµ Ð²ÐžÐŽÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÐœÐŸ ÐŽÐ»Ñ ÑÐ°ÐºÐŸÐ³ÐŸ ÑÐŸÐŽÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÐºÐŸÑÐŸÑÑÐµ ÐŒÑ ÐŸÐ¿ÐžÑÑÐ²Ð°ÐµÐŒ, ÐŸÐœÐž ÐœÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ). Ð Ð°Ð·ÐŽÐµÐ»Ñ ÐŒÐŸÐ³ÑÑ ÐžÐŒÐµÑÑ Ðž Ð¿ÐŸÐŽÑÐ°Ð·ÐŽÐµÐ»Ñ ÐºÐ°Ðº Ð¿ÑÐŸÐŽÐŸÐ»Ð¶ÐµÐœÐžÐµ ÑÐ»ÑÑÐ°Ñ, ÐŸÐ¿ÐžÑÐ°ÐœÐœÐŸÐ³ÐŸ Ð²ÑÑÐµ.</Text>
+<Text id="461">ÐÑÐ»Ðž Ð²Ñ When you Ð²ÑÑÐ°Ð²ÐžÐ»Ðž ÑÐµÐºÑÐžÑ ÑÐµÐ³ÐŸÐ² Ð² Ð²Ð°Ñ ÐŽÐŸÐºÑÐŒÐµÐœÑ, Ð·Ð°Ð¿ÐŸÐŒÐœÐžÑÐµ ÑÑÐŸ Ð²Ñ ÑÐŸÐ·ÐŽÐ°Ð»Ðž ÐžÐµÑÐ°ÑÑ
+ÐžÑÐµÑÐºÑÑ ÑÐ°Ð±Ð»ÐžÑÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ. Ð­ÑÐŸ ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ ÑÑÐŸ ÑÐµÐºÑÐžÐž ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑÑ Ð²ÐœÑÑÑÐž ÐŽÑÑÐ³ÐžÑ
+ ÑÐµÐºÑÐžÐ¹. Ð€Ð°ÐºÑÐžÑÐµÑÐºÐž, Ð²ÑÐµ ÑÐµÐºÑÐžÐž ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ Ð²ÐºÐ»ÑÑÐµÐœÑ Ð² ÐŸÐŽÐœÑ Ð·Ð°ÐºÐ»ÑÑÐžÑÐµÐ»ÑÐœÑÑ ÑÐµÐºÑÐžÑ ÐºÐŸÑÐŸÑÐ°Ñ Ð·Ð°ÐºÐ»ÑÑÐ°ÐµÑ Ð²ÐµÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ.</Text>
+<Text id="462">Ð¡Ð»ÐµÐŽÑÑÑÐžÐ¹ Ð¿ÑÐžÐŒÐµÑ ÐŽÐµÐŒÐŸÐœÑÑÑÐžÑÑÐµÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ Ñ ÐŽÐ²ÑÐŒÑ Ð³Ð»Ð°Ð²Ð°ÐŒÐž, Ð²ÑÐŸÑÐ°Ñ ÐžÐ· ÐºÐŸÑÐŸÑÑÑ
+ ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÐŽÐ²Ðµ Ð¿ÐŸÐŽÑÐµÐºÑÐžÐž. ÐÐ»Ñ ÑÐµÐ°Ð»ÑÐœÐŸÐ³ÐŸ Ð¿ÑÐžÐŒÐµÑÐ° Ð¿ÐµÑÐ²ÐŸÐžÑÑÐŸÑÐœÐžÐºÐž ÐŸÑÐŸÑÐŒÐ»ÐµÐœÑ ÑÐµÐ³Ð°ÐŒÐž ÑÐ°Ðº ÑÑÐŸÐ±Ñ ÐŸÐœÐž Ð²ÑÐ³Ð»ÑÐŽÐµÐ»Ðž ÐºÐ°Ðº ÐŽÐŸÐºÑÐŒÐµÐœÑ ÐŽÐ»Ñ ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐžÐ»Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž .</Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>&lt;Description&gt;</CodeLine>
+<CodeLine>&lt;Metadata name="Title"&gt;My Document&lt;/Metadata&gt;</CodeLine>
+<CodeLine>&lt;/Description&gt;</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>&lt;Description&gt;</CodeLine>
+<CodeLine>&lt;Metadata name="Title"&gt;Chapter 1&lt;/Metadata&gt;</CodeLine>
+<CodeLine>&lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text type="code" id="463">(text of chapter 1 goes here)</Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>&lt;Description&gt;</CodeLine>
+<CodeLine>&lt;Metadata name="Title"&gt;Chapter 2&lt;/Metadata&gt;</CodeLine>
+<CodeLine>&lt;/Description&gt;</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>&lt;Description&gt;</CodeLine>
+<CodeLine>&lt;Metadata name="Title"&gt;Subsection 1&lt;/Metadata&gt;</CodeLine>
+<CodeLine>&lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text type="code" id="464">(text of sub-section 1 goes here)</Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>&lt;Section&gt;</CodeLine>
+<CodeLine>&lt;Description&gt;</CodeLine>
+<CodeLine>&lt;Metadata name="Title"&gt;Subsection 2&lt;/Metadata&gt;</CodeLine>
+<CodeLine>&lt;/Description&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text type="code" id="465">(text of sub-section 2 goes here)</Text>
+<CodeLine>&lt;!--</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>&lt;/Section&gt;</CodeLine>
+<CodeLine>--&gt;</CodeLine>
+<Text id="466">ÐÐŒÐµÐ¹ÑÐµ Ð²Ð²ÐžÐŽÑ ÑÑÐŸ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐœÐ°Ð·ÐœÐ°ÑÐµÐœÐœÑÐµ Ð² ÑÐµÐºÑÐžÐž ÑÐµÐ³ÐŸÐ² Ð² ÐŽÐŸÐºÑÐŒÐµÐœÑÐµ Ð¿ÐµÑÐ²ÐŸÐžÑÑÐŸÑÐœÐžÐºÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ Ð²ÐµÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ. Ð­ÑÐŸ ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ ÑÑÐŸ ÐÐ°ÐŒ ÐœÐµ ÑÐ»ÐµÐŽÑÐµÑ ÐŽÐµÑÐ°Ð»ÑÐœÐŸ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐÐ°Ð·Ð²Ð°ÐœÐžÑ ÐŽÐ»Ñ ÑÐµÐºÑÐžÐž Ð²ÐµÑÑ
+ÐœÐµÐ³ÐŸ ÑÑÐŸÐ²ÐœÑ, ÐµÑÐ»Ðž Ð²Ñ ÐœÐµ Ñ
+ÐŸÑÐžÑÐµ Ð¿ÐµÑÐµÑÐŸÐ·ÐŽÐ°ÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐµ ÑÐ°ÐœÐµÐµ.  Ð Ð²ÑÑÐµÑÐºÐ°Ð·Ð°ÐœÐœÐŸÐŒ Ð¿ÑÐžÐŒÐµÑÐµ ÐºÐ°Ðº ÐŒÐžÐœÐžÐŒÑÐŒ ÐµÑÐ»Ðž Ð²Ñ Ñ
+ÐŸÑÐžÑÐµ Ð¿ÐµÑÐµÑÐŸÐ·ÐŽÐ°ÑÑ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐŸÐº ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ð²Ð°ÐŒ ÑÐ»ÐµÐŽÑÐµÑ Ð¿ÑÐŸÐ¿ÑÑÑÐžÑÑ ÑÑÑÐŸÐºÑ ÐºÐŸÑÐŸÑÑÑ Ð²Ñ ÑÐµÐ¹ÑÐ°Ñ ÑÐžÑÐ°ÐµÑÐµ</Text>
+<CodeLine>&lt;Metadata name="Title"&gt;My Document&lt;/Metadata&gt;</CodeLine>
+</Content>
+</Section>
+<Section id="the_collector">
+<Title>
+<Text id="467">ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑ</Text>
+</Title>
+<Content>
+<Text id="468">ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð²Ð°ÐŒ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ ÐœÐŸÐ²ÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð° ÑÐ°ÐºÐ¶Ðµ ÐžÐ·ÐŒÐµÐœÑÑÑ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÑÑÑ. ÐÐ»Ñ ÑÑÐŸÐ³ÐŸ ÐŒÑ Ð¿ÑÐŸÐ¹ÐŽÐµÐŒ ÑÐµÑÐµÐ· ÑÑÐŽ Ð²ÐµÐ±-ÑÑÑÐ°ÐœÐžÑ, ÐºÐŸÑÐŸÑÑÐµ ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°ÑÑ ÑÑÐŸÑ Ð¿ÑÐŸÑÐµÑÑ. Ð ÐºÐ°ÑÐµÑÑÐ²Ðµ Ð°Ð»ÑÑÐµÑÐœÐ°ÑÐžÐ² ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑÑ Ð²Ñ ÑÐ°ÐºÐ¶Ðµ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐºÐŸÐŒÐ°ÐœÐŽÐœÐŸÐ¹ ÑÑÑÐŸÐºÐž - Ð¿ÐµÑÐ²ÑÐµ ÑÑÑÐ°ÐœÐžÑÑ ÐÐœÑÑÑÑÐºÑÐžÐž Ð Ð°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ° ÐŽÐµÑÐ°Ð»ÑÐœÐŸ ÑÐ°ÑÑÐŒÐ°ÑÑÐžÐ²Ð°ÑÑ ÑÑÐŸÑ Ð²ÐŸÐ¿ÑÐŸÑ.</Text>
+<Text id="469">Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ Ðž ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÐµÐœÐžÐµ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÑ
+ Ð²Ð»ÐµÑÐµÑ Ð·Ð° ÑÐŸÐ±ÐŸÐ¹ ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐŸÑÑÑ, ÐºÐŸÑÐŸÑÑÑ ÑÐ»ÐµÐŽÑÐµÑ ÑÑÐµÑÑÑ Ð¿ÐµÑÐµÐŽ ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµÐŒ. Ð¡ÑÑÐµÑÑÐ²ÑÑÑ Ð°Ð²ÑÐŸÑÑÐºÐžÐµ Ð¿ÑÐ°Ð²Ð°: ÐžÐŒÐµÑÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ ÐœÐµ ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ, ÑÑÐŸ Ð²Ð°ÐŒ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÐµÐœÐŸ ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÑÑÑ ÐµÐµ ÐŽÐ»Ñ ÐŽÑÑÐ³ÐžÑ
+. Ð¡ÑÑÐµÑÑÐ²ÑÑÑ ÑÐ°ÐºÐ¶Ðµ Ð²ÐŸÐ¿ÑÐŸÑÑ ÑÑÐžÐºÐž: Ðº ÐœÐµÐºÐŸÑÐŸÑÑÐŒ Ð²ÐµÑÑÐŒ Ð¿ÑÐŸÑÑÐŸ ÐœÑÐ¶ÐœÐŸ ÐŸÐ³ÑÐ°ÐœÐžÑÐžÑÑ ÐŽÐŸÑÑÑÐ¿. ÐÐµÑÐŸ ÐŸÑÑÑÐµÐµ ÐŒÐµÑÐ°! ÐÑÐŽÑÑÐµ ÐŸÑÑÐŸÑÐŸÐ¶ÐœÑ Ðž ÑÐŒÐµÐ»ÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ ÑÐžÐ»Ñ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž.</Text>
+<Text id="470">ÐÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÑÑ ÑÑÑÐ»ÐºÑ (Collector) Ð² ÑÑÐ°ÑÑÐŸÐ²ÐŸÐŒ ÐŸÐºÐœÐµ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž.</Text>
+<Text id="471">Ð Greenstone ÑÑÑÑÐºÑÑÑÐ° ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŸÐ¿ÑÐµÐŽÐµÐ»ÑÐµÑÑÑ Ð² Ð¿ÑÐŸÑÐµÑÑÐµ ÐµÐµ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ. Ð­ÑÐŸ Ð²ÐºÐ»ÑÑÐ°ÐµÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÐµ ÑÐŸÑÐŒÐ°ÑÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÐžÑ
+ Ð²ÑÐ²ÐŸÐŽ ÐœÐ° ÑÐºÑÐ°Ðœ, ÐžÑÑÐŸÑÐœÐžÐº ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÐºÐ°ÐºÐžÐµ Ð¿ÑÐµÐŽÐŒÐµÑÐœÑÐµ ÑÐºÐ°Ð·Ð°ÑÐµÐ»Ðž ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ Ð²ÐºÐ»ÑÑÐµÐœÑ, ÐºÐ°ÐºÐžÐµ Ð¿ÐŸÐ»ÐœÐŸÑÐµÐºÑÑÐŸÐ²ÑÐµ ÐžÐœÐŽÐµÐºÑÑ ÑÐ»ÐµÐŽÑÐµÑ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²ÐžÑÑ Ðž ÐºÐ°Ðº ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÑ ÑÐµÐ·ÑÐ»ÑÑÐ°ÑÑ Ð¿ÐŸÐžÑÐºÐ°. ÐÐŸÑÐ»Ðµ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÐŸÐ·ÐŽÐ°ÐœÐ°, Ð² ÐœÐµÐµ Ð»ÐµÐ³ÐºÐŸ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐœÐŸÐ²ÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð¿ÑÐž ÑÑÐ»ÐŸÐ²ÐžÐž, ÑÑÐŸ ÐŸÐœÐž ÑÐŸÐ³ÐŸ Ð¶Ðµ ÑÐŸÑÐŒÐ°ÑÐ°, ÑÑÐŸ Ðž ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ, Ðž ÐžÐŒÐµÑÑ ÑÑ
+ÐŸÐ¶ÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ.</Text>
+<Text id="472">ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑ Ð²ÑÐ¿ÐŸÐ»ÐœÑÐµÑ ÑÐ»ÐµÐŽÑÑÑÐžÐµ ÐŸÑÐœÐŸÐ²ÐœÑÐµ ÑÑÐœÐºÑÐžÐž:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="473">ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐžÐŒÐµÑÑÐµÐ¹ ÑÐ°ÐºÑÑ Ð¶Ðµ ÑÑÑÑÐºÑÑÑÑ, ÐºÐ°Ðº Ðž ÑÑÑÐµÑÑÐ²ÑÑÑÐ°Ñ;</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="474">ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐžÐŒÐµÑÑÐµÐ¹ ÐŽÑÑÐ³ÑÑ ÑÑÑÑÐºÑÑÑÑ, ÐœÐµÐ¶ÐµÐ»Ðž ÑÑÑÐµÑÑÐ²ÑÑÑÐ°Ñ;</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="475">ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐœÐŸÐ²ÑÐ¹ ÐŒÐ°ÑÐµÑÐžÐ°Ð» Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž;</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="476">ÐžÐ·ÐŒÐµÐœÐžÑÑ ÑÑÑÑÐºÑÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž;</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="477">ÑÐŽÐ°Ð»ÐžÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ;</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="478">Ð·Ð°Ð¿ÐžÑÐ°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐœÐ° ÑÐ°ÐŒÐŸÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÑÑÐžÐ¹ÑÑ CD-ROM</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="479">Ð ÐžÑÑÐœÐŸÐº 16 Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐ¹ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð² ÑÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ ÐžÐ· ÐœÐ°Ð±ÐŸÑÐ° ÑÐ°Ð¹Ð»ÐŸÐ² ÑÐŸÑÐŒÐ°ÑÐ° HTML. ÐÑÐµÐ¶ÐŽÐµ Ð²ÑÐµÐ³ÐŸ Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ ÑÐµÑÐžÑÑ, Ñ
+ÐŸÑÐžÑÐµ Ð»Ðž Ð²Ñ ÑÐ°Ð±ÐŸÑÐ°ÑÑ Ñ ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹ ÐžÐ»Ðž ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ ÐœÐŸÐ²ÑÑ. ÐÐµÑÐ²Ð°Ñ ÐºÐ°ÑÐ°ÐµÑÑÑ Ð¿ÑÐœÐºÑÐŸÐ² 3-6, Ð° Ð¿ÐŸÑÐ»ÐµÐŽÐœÑÑ 1-2.</Text>
+<Figure id="using_the_collector_to_build_a_new_collection">
+<Title>
+<Text id="480">ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑÐ° ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (Ð¿ÑÐŸÐŽÐŸÐ»Ð¶ÐµÐœÐžÐµ ÐœÐ° ÑÐ»ÐµÐŽÑÑÑÐµÐ¹ ÑÑÑÐ°ÐœÐžÑÐµ)</Text>
+<SubTitle>
+<Text id="481">(a)</Text>
+</SubTitle>
+</Title>
+<File width="369" height="440" url="images/User_Fig_16a.png"/>
+</Figure>
+<Subsection id="logging_in">
+<Title>
+<Text id="482">ÐÑ
+ÐŸÐŽ</Text>
+</Title>
+<Content>
+<Text id="483">Ð Ð»ÑÐ±ÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ Ð²Ð°ÐŒ Ð¿ÑÐµÐ¶ÐŽÐµ Ð²ÑÐµÐ³ÐŸ ÐœÑÐ¶ÐœÐŸ Ð²ÐŸÐ¹ÑÐž Ð² ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑ. ÐÐ°ÐŒÐµÑÑÑÐµ, ÑÑÐŸ ÐŸÐ±ÑÑÐœÐŸ, ÑÐµÑÐµÐ· ÑÐ²ÐŸÐž ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÑ Ð»ÑÐŽÐž ÐžÐŒÐµÑÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÑÐ¿ÐµÑÐžÐ°Ð»ÐžÐ·ÐžÑÐŸÐ²Ð°ÐœÐœÐŸÐŒÑ ÐŸÑÐŽÐ°Ð»ÐµÐœÐœÐŸÐŒÑ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÑ Ð² ÑÐµÑÐž, ÐžÐŒÐµÑÑÐµÐŒÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹. ÐÐŸÐœÐµÑÐœÐŸ Ð¶Ðµ ÐŒÑ ÐœÐµ ÐŒÐŸÐ¶ÐµÐŒ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÐžÑÑ ÐºÐ°Ð¶ÐŽÐŸÐŒÑ ÐžÐŒÐµÑÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÑÐ°ÐºÐžÐŒ ÑÐµÑÐ²ÐµÑÐ°ÐŒ Ðž ÑÑÑÐŸÐžÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð¿ÐŸÑÑÐŸÐŒÑ Greenstone ÐžÐŒÐµÐµÑ ÑÐžÑÑÐµÐŒÑ Ð±ÐµÐ·ÐŸÐ¿Ð°ÑÐœÐŸÑÑÐž, Ð³ÐŽÐµ Ð²Ñ ÐŽÐŸÐ»Ð¶ÐœÑ Ð²Ð²ÐµÑÑÐž ÑÐ²ÐŸÐ¹ ID Ðž Ð¿Ð°ÑÐŸÐ»Ñ. Ð¢Ð°Ðº Ð¶Ðµ, ÐµÑÐ»Ðž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ Greenstone ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐŸ Ñ Ð²Ð°Ñ ÐœÐ° ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ, Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐœÐ° ÐœÐµÐŒ. Ð¢ÐµÐŒ ÐœÐµ ÐŒÐµÐœÐµÐµ, Ð²Ñ ÑÐ°ÐºÐ¶Ðµ ÐŽÐŸÐ»Ð¶ÐœÑ Ð²Ð²ÐµÑÑÐž ID Ðž Ð¿Ð°ÑÐŸÐ»Ñ, ÑÑÐŸÐ±Ñ ÐŸÐ³ÑÐ°ÐŽÐžÑÑ Ð¿ÐŸÑÑÐŸÑÐŸÐœÐœÐžÑ
+ Ð»ÑÐŽÐµÐ¹ ÐŸÑ Ð²Ñ
+ÐŸÐŽÐ° Ð² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Ð±ÐµÐ· ÑÐ°Ð·ÑÐµÑÐµÐœÐžÑ.</Text>
+</Content>
+</Subsection>
+<Subsection id="dialog_structure">
+<Title>
+<Text id="484">ÐÐžÐ°Ð»ÐŸÐ³ÐŸÐ²Ð°Ñ ÑÑÑÑÐºÑÑÑÐ°</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_1">
+<Title>
+<Text id="485">ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑÐ° ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (ÐÑÐŸÐŽÐŸÐ»Ð¶)</Text>
+<SubTitle>
+<Text id="486">(b)</Text>
+</SubTitle>
+</Title>
+<File width="369" height="435" url="images/User_Fig_16b.png"/>
+</Figure>
+<Text id="487">ÐÐŸÑÐ»Ðµ Ð²Ñ
+ÐŸÐŽÐ° ÐœÐ° ÑÐºÑÐ°ÐœÐµ Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ ÑÑÑÐ°ÐœÐžÑÐ°, ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐœÐ°Ñ ÐœÐ° ÑÐžÑÑÐœÐºÐµ 16b. ÐÐ° ÐœÐµÐ¹ Ð¿ÐŸÐºÐ°Ð·Ð°Ðœ Ð¿ÐµÑÐµÑÐµÐœÑ ÑÐ°Ð³ÐŸÐ², ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐ¹ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð­ÑÐŸ:</Text>
+<NumberedList>
+<NumberedItem>
+<Text id="488">Ð¡Ð±ÐŸÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="489">Ð£ÐºÐ°Ð·Ð°ÐœÐžÐµ ÐžÑÑÐŸÑÐœÐžÐºÐŸÐ²</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="490">ÐÐ°ÑÑÑÐŸÐ¹ÐºÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="491">ÐÐŸÑÑÑÐŸÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="492">ÐÑÐŸÑÐŒÐŸÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</NumberedItem>
+</NumberedList>
+<Text id="493">Ð Ð¿ÐµÑÐ²ÐŸÐŒ ÑÐ°Ð³Ðµ ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž ÑÐŸÐ¿ÑÑÑÑÐ²ÑÑÑÐ°Ñ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ. ÐÑÐŸÑÐŸÐ¹ ÑÐ°Ð³ - ÑÐºÐ°Ð·Ð°ÑÑ, ÐŸÑÐºÑÐŽÐ° ÑÐºÐ°ÑÐžÐ²Ð°ÑÑ Ðž Ð¿ÐŸÐ»ÑÑÐ°ÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ. ÐÐ°ÑÐµÐŒ ÑÐ»ÐµÐŽÑÐµÑ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐ° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð­ÑÐŸ ÑÐ°Ð³, ÐºÐŸÑÐŸÑÑÐ¹ ÑÑÐ°ÐœÐŸÐ²ÐžÑÑÑ Ð±ÐŸÐ»ÐµÐµ Ð²Ð°Ð¶ÐœÑÐŒ Ñ Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÐµÐŒ Ð²ÑÐµ Ð±ÐŸÐ»ÑÑÐµÐ³ÐŸ ÐŸÐ¿ÑÑÐ° ÑÐ°Ð±ÐŸÑÑ Ñ Greenstone. Ð§ÐµÑÐ²ÐµÑÑÑÐ¹ ÑÐ°Ð³ - ÑÑÐŸ ÑÐ°ÐŒ, Ð³ÐŽÐµ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ ÑÐ±ÐŸÑÐºÐ° Ðž ÑÐ°Ð±ÐŸÑÐ°. Ð Ð¿ÑÐŸÑÐµÑÑÐµ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÑÐŸÐ·ÐŽÐ°ÐµÑ Ð²ÑÐµ ÐžÐœÐŽÐµÐºÑÑ Ðž ÑÐŸÐ±ÐžÑÐ°ÐµÑ Ð²ÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ, ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÑÑ ÐŽÐ»Ñ ÑÑÐœÐºÑÐžÐŸÐœÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÑÑÐ¹ ÑÐ°Ð³ - ÑÑÐŸ Ð¿ÑÐŸÑÐŒÐŸÑÑ ÑÐŸÐ·ÐŽÐ°ÐœÐœÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. </Text>
+<Text id="494">Ð­ÑÐž Ð¿ÑÑÑ ÑÐ°Ð³ÐŸÐ² ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÑ Ð² Ð²ÐžÐŽÐµ Ð»ÐžÐœÐµÐ¹ÐœÐŸÐ¹ Ð¿ÐŸÑÐ»ÐµÐŽÐŸÐ²Ð°ÑÐµÐ»ÑÐœÐŸÑÑÐž ÑÐµÑÑÑ
+ ÐºÐœÐŸÐ¿ÐŸÐº Ð²ÐœÐžÐ·Ñ ÑÑÑÐ°ÐœÐžÑÑ ÐœÐ° Ð ÐžÑÑÐœÐºÐµ 16b Ðž Ð²ÐœÐžÐ·Ñ Ð²ÑÐµÑ
+ ÑÑÑÐ°ÐœÐžÑ, ÑÐŸÐ·ÐŽÐ°ÐœÐœÑÑ
+ Ð² ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑÐµ. Ð­ÑÐ° Ð¿Ð°ÐœÐµÐ»Ñ ÐºÐœÐŸÐ¿ÐŸÐº Ð¿ÐŸÐŒÐŸÐ¶ÐµÑ Ð²Ð°ÐŒ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÑ, ÐœÐ° ÐºÐ°ÐºÐŸÐ¹ ÑÑÐ°ÐŽÐžÐž Ð¿ÑÐŸÑÐµÑÑÐ° Ð²Ñ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÐµÑÑ. ÐÐœÐŸÐ¿ÐºÐ°, ÐœÐ° ÐºÐŸÑÐŸÑÑÑ ÐœÑÐ¶ÐœÐŸ ÐœÐ°Ð¶Ð°ÑÑ ÐŽÐ»Ñ Ð¿ÑÐŸÐŽÐŸÐ»Ð¶ÐµÐœÐžÑ Ð¿ÑÐŸÑÐµÑÑÐ°, ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐ° Ð·ÐµÐ»ÐµÐœÑÐŒ ÑÐ²ÐµÑÐŸÐŒ (collection information ÐœÐ° ÑÐžÑÑÐœÐºÐµ 16b). ÐÐœÐŸÐ¿ÐºÐž ÑÐµÑÐŸÐ³ÐŸ ÑÐ²ÐµÑÐ° (Ð²ÑÐµ ÐŸÑÑÐ°Ð»ÑÐœÑÐµ ÐœÐ° Ð ÐžÑÑÐœÐºÐµ 16b) ÑÐ²Ð»ÑÑÑÑÑ ÐœÐµÐ°ÐºÑÐžÐ²ÐœÑÐŒÐž. ÐÐœÐŸÐ¿ÐºÐž ÐŒÐµÐœÑÑÑ ÑÐ²ÐµÑ ÐœÐ° Ð¶ÐµÐ»ÑÑÐ¹ Ð² Ð¿ÑÐŸÑÐµÑÑÐµ Ð¿ÐµÑÐµÑ
+ÐŸÐŽÐ°. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð²ÐµÑÐœÑÑÑÑÑ Ðº Ð¿ÑÐµÐŽÑÐŽÑÑÐµÐŒÑ ÑÐ°Ð³Ñ, ÐœÐ°Ð¶Ð°Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÑÑ Ð¶ÐµÐ»ÑÑÑ ÐºÐœÐŸÐ¿ÐºÑ. Ð­ÑÐŸÑ Ð²ÐžÐŽ ÐŽÐžÑÐ¿Ð»ÐµÑ ÑÐŒÐŸÐŽÐµÐ»ÐžÑÐŸÐ²Ð°Ðœ ÐœÐ°Ð¿ÐŸÐŽÐŸÐ±ÐžÐµ âÐ¿ÑÑÐµÐ²ÐŸÐŽÐžÑÐµÐ»ÐµÐ¹, ÐŒÐ°ÑÑÐµÑÐŸÐ²â (wizards) ÐºÐŸÑÐŸÑÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ Ð² ÐŽÑÑÐ³ÐžÑ
+ ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÐµÐœÐœÑÑ
+ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÑ
+ ÑÑÐµÐŽÑÑÐ²Ð°Ñ
+, ÑÑÐµÐ±ÑÐµÐŒÑÑ
+ ÐŽÐ»Ñ Ð¿ÑÐŸÐ²ÐµÐŽÐµÐœÐžÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹ ÑÐµÑÐµÐ· Ð¿ÑÐŸÑÐµÑÑ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ.</Text>
+</Content>
+</Subsection>
+<Subsection id="collection_information">
+<Title>
+<Text id="495">ÐÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_2">
+<Title>
+<Text id="496">ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑÐ° ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (ÐÑÐŸÐŽÐŸÐ»Ð¶)</Text>
+<SubTitle>
+<Text id="497">(c)</Text>
+</SubTitle>
+</Title>
+<File width="369" height="504" url="images/User_Fig_16c.png"/>
+</Figure>
+<Text id="498">ÐÐµÑÐ²ÑÐ¹ ÑÐ°Ð³ Ð² Ð¿ÑÐŸÑÐµÑÑÐµ - ÑÑÐŸ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐœÐ°Ñ ÐœÐ° ÑÐžÑÑÐœÐºÐµ 16Ñ. ÐÑÐž ÐµÐµ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ Ð²Ð²ÐµÑÑÐž:</Text>
+<BulletList>
+<Bullet>
+<Text id="499">ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ</Text>
+</Bullet>
+<Bullet>
+<Text id="500">ÐÐŸÐœÑÐ°ÐºÑÐœÑÐ¹ e-mail Ð°ÐŽÑÐµÑ</Text>
+</Bullet>
+<Bullet>
+<Text id="501">ÐÑÐ°ÑÐºÐŸÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ</Text>
+</Bullet>
+</BulletList>
+<Text id="502">ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž - ÑÑÐŸ ÐºÐŸÑÐŸÑÐºÐ°Ñ ÑÑÐ°Ð·Ð°, Ð¿ÐŸÐ²ÑÐµÐŒÐµÑÑÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ Ð² ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐµ ÐŽÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð¢ÐžÐ¿ÐžÑÐœÑÐµ ÐœÐ°Ð·Ð²Ð°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹: ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Ð¿ÐžÑÐž Ðž Ð¿ÐžÑÐ°ÑÐµÐ»ÑÐœÑÑ
+ Ð²ÐµÑÐµÑÑÐ², ÐÐžÑÐŸÐ²Ð°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° ÐŸÐºÑÑÐ¶Ð°ÑÑÐµÐ¹ ÑÑÐµÐŽÑ, ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° ÑÐ°Ð·Ð²ÐžÑÐžÑ Ðž Ñ.ÐŽ. Ð­Ð»ÐµÐºÑÑÐŸÐœÐœÑÐ¹ Ð°ÐŽÑÐµÑ Ð¿ÑÐµÐŽÐœÐ°Ð·ÐœÐ°ÑÐµÐœ ÐŽÐ»Ñ ÐœÐµÐŒÐµÐŽÐ»ÐµÐœÐœÐŸÐ³ÐŸ ÐºÐŸÐœÑÐ°ÐºÑÐ° Ñ ÑÐŸÐ·ÐŽÐ°ÑÐµÐ»ÐµÐŒ Ð¿ÑÐž Ð²ÐŸÐ·ÐœÐžÐºÐœÐŸÐ²ÐµÐœÐžÐž Ð¿ÑÐŸÐ±Ð»ÐµÐŒ Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹. ÐÑÐž ÐŸÐ±ÐœÐ°ÑÑÐ¶ÐµÐœÐžÐž Ð¿ÑÐŸÐ±Ð»ÐµÐŒ ÐžÐ»Ðž ÐŸÑÐžÐ±ÐºÐž, Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Greenstone</Text>
+<Text id="503">ÐŒÐŸÐ¶ÐµÑ Ð¿ÐŸÑÐ»Ð°ÑÑ ÐŸÑÑÐµÑ ÐŸ ÐŽÐžÐ°Ð³ÐœÐŸÑÑÐžÐºÐµ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÑ ÐœÐ° ÑÑÐŸÑ Ð°ÐŽÑÐµÑ. Ð ÐœÐ°ÐºÐŸÐœÐµÑ, ÐºÑÐ°ÑÐºÐŸÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ - ÑÑÐŸ ÐœÐµÐ±ÐŸÐ»ÑÑÐžÐµ Ð¿ÑÐµÐŽÐ»ÐŸÐ¶ÐµÐœÐžÑ, ÐŸÐ¿ÐžÑÑÐ²Ð°ÑÑÐžÐµ, ÐºÐ°Ðº ÑÑÑÑÐŸÐµÐœÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÐœÐŸ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð¿ÐŸÐŽ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐŸÐŒ About this collection (ÐÐ± ÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž) ÐœÐ° Ð¿ÐµÑÐ²ÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐµÑÑÐŸ ÐœÐ°Ñ
+ÐŸÐ¶ÐŽÐµÐœÐžÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð² Ð¿ÑÐŸÑÐµÑÑÐµ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŸÑÐŸÐ±ÑÐ°Ð¶Ð°ÐµÑÑÑ ÑÑÑÐµÐ»ÐºÐŸÐ¹, ÐºÐŸÑÐŸÑÐ°Ñ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÐœÐ° ÐŽÐžÑÐ¿Ð»ÐµÐµ Ð²ÐœÐžÐ·Ñ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÑ. ÐÐ° ÑÐžÑÑÐœÐºÐµ 16Ñ, collection information stage (ÑÑÐ°ÐŽÐžÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž). ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð¿ÑÐŸÐŽÐ²ÐžÐ³Ð°ÐµÑÑÑ Ðº Ð ÐžÑÑÐœÐºÑ 16d, ÐœÐ°Ð¶Ð°Ð² ÐœÐ° Ð·ÐµÐ»ÐµÐœÑÑ ÐºÐœÐŸÐ¿ÐºÑ.</Text>
+</Content>
+</Subsection>
+<Subsection id="source_data">
+<Title>
+<Text id="504">ÐÑÑÐŸÑÐœÐžÐºÐž ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_3">
+<Title>
+<Text id="505">ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑÐ° ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (ÐÑÐŸÐŽÐŸÐ»Ð¶)</Text>
+<SubTitle>
+<Text id="506">(d)</Text>
+</SubTitle>
+</Title>
+<File width="368" height="532" url="images/User_Fig_16d.png"/>
+</Figure>
+<Text id="507">ÐÐ°ÑÐžÐœÐ°Ñ Ñ Ð ÐžÑÑÐœÐºÐ° 16d, Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐŽÐŸÐ»Ð¶ÐµÐœ ÑÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÑÐµÐºÑÑÐŸÐ²ÑÐµ ÐžÑÑÐŸÑÐœÐžÐºÐž, ÑÐŸÑÑÐ°Ð²Ð»ÑÑÑÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐŸÐ·ÐŽÐ°ÑÑ Ð²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð»ÐžÐ±ÐŸ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÑÑÑÑÐºÑÑÑÑ, ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐœÐŸÐ¹ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, Ð»ÐžÐ±ÐŸ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÑÑÑÑÐºÑÑÑÑ, ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐ¹ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="508">ÐÑÐ»Ðž Ð²Ñ Ð²ÑÐ±ÐµÑÐµÑÐµ ÑÑÑÑÐºÑÑÑÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ, ÐœÐŸÐ²Ð°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐŒÐŸÐ¶ÐµÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÑÐŸÑÐŒÐ°ÑÐ° HTML (ÑÐ°Ð¹Ð»Ñ, ÐžÐŒÐµÑÑÐžÐµ ÑÐ°ÑÑÐžÑÐµÐœÐžÐµ .htm, .html) ÐžÐ»Ðž Ð¿ÑÐŸÑÑÑÐµ ÑÐµÐºÑÑÐŸÐ²ÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ (.txt, .text), ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Microsoft Word (.doc), PDF (.pdf) ÐžÐ»Ðž ÐŽÐŸÐºÑÐŒÐµÐœÑÑ e-mail (.email). ÐÐŸÐ»ÑÑÐµ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž ÐŸ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÑÐŸÑÐŒÐ°ÑÐ°Ñ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÑÐŸÐŽÐµÑÐ¶ÐžÑÑÑ ÐœÐžÐ¶Ðµ Ð² ÑÐ°ÑÑÐž âÐ€ÐŸÑÐŒÐ°ÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²â.</Text>
+<Text id="509">ÐÑÐ»Ðž Ð²Ñ ÑÐŸÐ·ÐŽÐ°ÐµÑÐµ ÐœÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐœÐ° ÐŸÑÐœÐŸÐ²Ðµ ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐŸ ÑÐ°Ð¹Ð»Ñ Ð² ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÐŸÐ±ÑÐ·Ð°ÑÐµÐ»ÑÐœÐŸ ÑÐŸÐ³ÐŸ Ð¶Ðµ ÑÐ°ÐŒÐŸÐ³ÐŸ ÑÐŸÑÐŒÐ°ÑÐ°, ÐºÐŸÑÐŸÑÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°Ð»ÐžÑÑ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ°ÐŒÐµÑÑÑÐµ, ÑÑÐŸ ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑ ÐœÐµÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐµ ÑÐŸÑÐŒÐ°ÑÑ ÐžÑÑ
+ÐŸÐŽÐœÑÑ
+ ÑÐ°Ð¹Ð»ÐŸÐ², Ð² ÑÐŸ Ð²ÑÐµÐŒÑ ÐºÐ°Ðº ÐŽÑÑÐ³ÐžÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ, ÐœÐ°Ñ
+ÐŸÐŽÑÑÐžÐµÑÑ Ð²ÐŸ Ð²ÑÐ¿ÐŸÐŒÐŸÐ³Ð°ÑÐµÐ»ÑÐœÑÑ
+ ÑÐ°Ð¹Ð»Ð°Ñ
+. ÐÑÐ»Ðž Ð²Ð°ÑÐž ÐžÑÑ
+ÐŸÐŽÐœÑÐµ ÐŽÐ°ÐœÐœÑÐµ ÐœÐµ ÐžÐŒÐµÑÑ ÑÑÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž, ÑÐŸ ÐœÐµÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐžÑÐºÐŸÐ²ÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž ÐœÐµ Ð±ÑÐŽÑÑ ÑÐ°Ð±ÐŸÑÐ°ÑÑ ÐœÐŸÑÐŒÐ°Ð»ÑÐœÐŸ. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÐµÑÐ»Ðž Ð²Ñ âÐºÐ»ÐŸÐœÐžÑÑÐµÑÐµâ ÐÐµÐŒÐŸ-ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÑÐŸ Ð·Ð°ÐŒÐµÑÐžÑÐµ, ÑÑÐŸ ÑÐºÐ°Ð·Ð°ÑÐµÐ»Ðž âÐœÐ°Ð·Ð²Ð°ÐœÐžÑ Ð°-Ñâ, âÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐžâ Ðž âÑÐ¿ÐŸÑÐŸÐ±Ñâ ÐœÐµ Ð±ÑÐŽÑÑ ÑÐ°Ð±ÐŸÑÐ°ÑÑ. Ð ÑÐ¿ÐµÑÐžÐ°Ð»ÑÐœÑÑ
+ ÐŸÐºÐœÐ°Ñ
+ ÑÐ»ÐµÐŽÑÐµÑ ÑÐºÐ°Ð·Ð°ÑÑ ÐŒÐµÑÑÐŸÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÐµ ÐžÑÑÐŸÑÐœÐžÐºÐŸÐ² ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ².</Text>
+<Text id="510">ÐÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐºÐ°Ð·Ð°ÐœÐŸ ÐŽÐŸ ÑÑÐµÑ
+ ÐŸÑÐŽÐµÐ»ÑÐœÑÑ
+ ÐžÑÑ
+ÐŸÐŽÐœÑÑ
+ ÐžÑÑÐŸÑÐœÐžÐºÐŸÐ², ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐœÑÑ
+ ÐœÐ° ÑÐžÑÑÐœÐºÐµ 16d. ÐÑÐ»Ðž Ð²Ð°ÐŒ ÐœÑÐ¶ÐœÐŸ Ð±ÐŸÐ»ÑÑÐµ, Ð¿ÑÐŸÑÑÐŸ
+ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÐºÐœÐŸÐ¿ÐºÑ âmore sourcesâ (Ð±ÐŸÐ»ÑÑÐµ ÐžÑÑÐŸÑÐœÐžÐºÐŸÐ²) </Text>
+<Text id="511">Ð¡ÑÑÐµÑÑÐ²ÑÐµÑ ÑÑÐž Ð²ÐžÐŽÐ° ÑÐºÐ°Ð·Ð°ÐœÐžÐ¹:</Text>
+<BulletList>
+<Bullet>
+<Text id="512">ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž Ð² ÑÐžÑÑÐµÐŒÐµ ÑÐµÑÐ²ÐµÑÐ° Greenstone (ÐœÐ°ÑÐžÐœÐ°ÐµÑÑÑ Ñ âfile://â)</Text>
+</Bullet>
+<Bullet>
+<Text id="513">ÐÐŽÑÐµÑ, ÐœÐ°ÑÐžÐœÐ°ÑÑÐžÐ¹ÑÑ Ñ âhttp://â ÐŽÐ»Ñ ÑÐ°Ð¹Ð»ÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÐœÑÐ¶ÐœÐŸ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ Ñ ÐÐœÑÐµÑÐœÐµÑÐ°</Text>
+</Bullet>
+<Bullet>
+<Text id="514">ÐÐŽÑÐµÑ, ÐœÐ°ÑÐžÐœÐ°ÑÑÐžÐ¹ÑÑ Ñ âftp://â ÐŽÐ»Ñ ÑÐ°Ð¹Ð»ÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ¶ÐœÐŸ Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑ Ð°ÐœÐŸÐœÐžÐŒÐœÑÐ¹ FTP.</Text>
+</Bullet>
+</BulletList>
+<Text id="515">ÐÑÐ»Ðž Ð²Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ file:// ÐžÐ»Ðž ftp:// ÐŽÐ»Ñ ÑÐºÐ°Ð·Ð°ÐœÐžÑ ÑÐ°Ð¹Ð»Ð°, ÑÐŸ Ð±ÑÐŽÐµÑ Ð·Ð°Ð³ÑÑÐ¶ÐµÐœ ÑÑÐŸÑ ÑÐ°Ð¹Ð».</Text>
+<Text id="516">ÐÑÐ»Ðž Ð²Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ http://, ÑÐŸ ÑÐµÐ·ÑÐ»ÑÑÐ°Ñ Ð·Ð°Ð²ÐžÑÐžÑ ÐŸÑ ÑÐŸÐ³ÐŸ, Ð²ÑÐŽÐ°ÐµÑ Ð»Ðž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐŸÐ±ÑÑÐœÑÑ ÐžÐœÑÐµÑÐœÐµÑ ÑÑÑÐ°ÐœÐžÑÐºÑ ÐœÐ° ÑÐºÑÐ°Ðœ ÐžÐ»Ðž ÑÐ¿ÐžÑÐŸÐº ÑÐ°Ð¹Ð»ÐŸÐ². ÐÑÐ»Ðž ÑÑÑÐ°ÐœÐžÑÐºÑ, ÑÐŸ ÐŸÐœÐ° Ð±ÑÐŽÐµÑ Ð·Ð°Ð³ÑÑÐ¶ÐµÐœÐ° â ÐºÐ°Ðº Ðž Ð²ÑÐµ ÑÑÑÐ°ÐœÐžÑÑ, ÐœÐ° ÐºÐŸÑÐŸÑÑÐµ ÑÑÑÐµÑÑÐ²ÑÑÑ ÑÑÑÐ»ÐºÐž Ñ ÑÑÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐºÐž Ðž Ñ.ÐŽ. Ð¿ÑÐž ÑÑÐ»ÐŸÐ²ÐžÐž, ÑÑÐŸ ÐŸÐœÐž ÐœÐ°Ñ
+ÐŸÐŽÑÑÑÑ ÐœÐ° ÐŸÐŽÐœÐŸÐŒ Ð²ÐµÐ±-ÑÐ°Ð¹ÑÐµ.</Text>
+<Text id="517">ÐÑÐ»Ðž Ð²Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÐµ file:// ÐžÐ»Ðž ftp:// ÐŽÐ»Ñ ÑÐºÐ°Ð·Ð°ÐœÐžÑ Ð¿Ð°Ð¿ÐºÐž ÐžÐ»Ðž ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž ÐžÐ»Ðž Ð²Ð²ÐµÐŽÐµÑÐµ http:// Ð°ÐŽÑÐµÑ, ÐºÐŸÑÐŸÑÑÐ¹ Ð²ÐµÐŽÐµÑ Ðº ÑÐ¿ÐžÑÐºÑ ÑÐ°Ð¹Ð»ÐŸÐ², ÑÐŸ Ð²ÑÐµ ÑÑÐŸ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² Ð¿Ð°Ð¿ÐºÐµ Ðž Ð²ÑÐµ Ð¿ÐŸÐŽÐ¿Ð°Ð¿ÐºÐž Ð±ÑÐŽÑÑ Ð²ÐºÐ»ÑÑÐµÐœÑ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ.</Text>
+<Text id="518">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ ÑÐºÐ°Ð·Ð°ÑÑ ÐžÑÑÐŸÑÐœÐžÐºÐž ÐŽÑÑÐ³ÐžÑ
+ Ð²ÐžÐŽÐŸÐ².</Text>
+<Text id="519">Ð ÑÐ°ÐºÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ (Ð ÐžÑÑÐœÐŸÐº 16d) ÐœÐŸÐ²Ð°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð±ÑÐŽÐµÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ, Ð²Ð·ÑÑÑÐµ ÐºÐ°Ðº ÐžÐ· Ð»ÐŸÐºÐ°Ð»ÑÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÑ, ÑÐ°Ðº Ðž Ñ ÐŸÑÐŽÐ°Ð»ÐµÐœÐœÐŸÐ³ÐŸ ÐÐœÑÐµÑÐœÐµÑ-ÑÐµÑÑÑÑÐ°, ÐºÐŸÑÐŸÑÑÐ¹ Ð±ÑÐŽÐµÑ ÑÐºÐ°Ð·Ð°Ðœ Ð² Ð¿ÑÐŸÑÐµÑÑÐµ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ.</Text>
+<Text id="520">ÐÐŸÐ³ÐŽÐ° Ð²Ñ ÐœÐ°Ð¶ÐŒÐµÑÐµ ÐœÐ° configure collection (ÐºÐŸÐœÑÐžÐ³ÑÑÐžÑÐŸÐ²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ) ÐŽÐ»Ñ Ð¿ÑÐŸÐŽÐŸÐ»Ð¶ÐµÐœÐžÑ Ð¿ÑÐŸÑÐµÑÑÐ° Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ , ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑ Ð¿ÑÐŸÐ²ÐµÑÐžÑ, ÐŽÐŸÑÑÑÐ¿ÐœÑ Ð»Ðž Ð²ÑÐµ ÐžÑÑÐŸÑÐœÐžÐºÐž, ÐºÐŸÑÐŸÑÑÐµ Ð²Ñ ÑÐºÐ°Ð·Ð°Ð»Ðž. Ð­ÑÐŸ ÐŒÐŸÐ¶ÐµÑ Ð·Ð°ÐœÑÑÑ ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÐµÐºÑÐœÐŽ ÐžÐ»Ðž ÐŽÐ°Ð¶Ðµ ÐŒÐžÐœÑÑ, ÐµÑÐ»Ðž Ð²Ñ ÑÐºÐ°Ð·Ð°Ð»Ðž
+ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÐžÑÑÐŸÑÐœÐžÐºÐŸÐ². ÐÑÐ»Ðž ÐŸÐŽÐžÐœ ÐžÐ»Ðž ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ ÑÐºÐ°Ð·Ð°ÐœÐœÑÑ
+ Ð²Ð°ÐŒÐž ÐžÑÑÐŸÑÐœÐžÐºÐŸÐ² ÐœÐµÐŽÐŸÑÑÑÐ¿ÐœÑ, ÑÐŸ Ð¿ÐŸÑÐ²ÐžÑÑÑ ÑÑÑÐ°ÐœÐžÑÐ°, ÑÑ
+ÐŸÐ¶Ð°Ñ Ñ Ð ÐžÑÑÐœÐºÐŸÐŒ 16Ðµ, Ð³ÐŽÐµ ÑÐºÐ°Ð·Ð°ÐœÑ ÐœÐµÐŽÐŸÑÑÑÐ¿ÐœÑÐµ ÐžÑÑÐŸÑÐœÐžÐºÐž (Ð² ÑÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ ÐŸÐ±Ð°).</Text>
+<Figure id="using_the_collector_to_build_a_new_collection_4">
+<Title>
+<Text id="521">ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑÐ° ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (ÐÑÐŸÐŽÐŸÐ»Ð¶)</Text>
+<SubTitle>
+<Text id="522">(e)</Text>
+</SubTitle>
+</Title>
+<File width="368" height="531" url="images/User_Fig_16e.png"/>
+</Figure>
+<Text id="523">ÐÑÑÐŸÑÐœÐžÐºÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐœÐµÐŽÐŸÑÑÑÐ¿ÐœÑ Ð¿ÐŸ ÑÐ»ÐµÐŽÑÑÑÐžÐŒ Ð¿ÑÐžÑÐžÐœÐ°ÐŒ:</Text>
+<BulletList>
+<Bullet>
+<Text id="524">Ð€Ð°Ð¹Ð», ÑÐ°Ð¹Ñ FTP ÐžÐ»Ðž URL ÐœÐµ ÑÑÑÐµÑÑÐ²ÑÑÑ</Text>
+</Bullet>
+<Bullet>
+<Text id="525">ÐÐ°ÐŒ ÐœÑÐ¶ÐœÐŸ Ð¿ÐŸÐŽÐºÐ»ÑÑÐžÑÑÑÑ Ðº ÐžÐœÑÐµÑÐœÐµÑÑ</Text>
+</Bullet>
+<Bullet>
+<Text id="526">ÐÑ Ð¿ÑÑÐ°ÐµÑÐµÑÑ Ð¿ÐŸÐ¿Ð°ÑÑÑ ÐœÐ° Ð·Ð°Ð±Ð»ÐŸÐºÐžÑÐŸÐ²Ð°ÐœÐœÑÐ¹ Ð°ÐŽÑÐµÑ.</Text>
+</Bullet>
+</BulletList>
+<Text id="527">ÐÐŸÑÐ»ÐµÐŽÐœÐžÐ¹ ÐžÐ· ÑÐ»ÑÑÐ°ÐµÐ² ÑÐ°ÐŒÑÐ¹ ÐœÐµÐ¿ÐŸÐœÑÑÐœÑÐ¹. ÐÐœ ÑÐ»ÑÑÐ°ÐµÑÑÑ ÑÐŸÐ³ÐŽÐ°, ÐºÐŸÐ³ÐŽÐ° Ð²Ñ ÐžÐŒÐµÐµÑÐµ ÐŽÐŸÑÑÑÐ¿ Ðº ÐžÐœÑÐµÑÐœÐµÑÑ Ð¿ÐŸ ÑÐµÐ»ÐµÑÐŸÐœÐœÐŸÐ¹ Ð»ÐžÐœÐžÐž (dial-up). ÐÐœÐŸÐ³ÐŽÐ° Ð±ÑÐ²Ð°ÐµÑ ÑÐ°Ðº, ÑÑÐŸ Ð²Ñ Ð²ÐžÐŽÐžÑÐµ Ð²ÐµÐ±-ÑÑÑÐ°ÐœÐžÑÑ, ÐœÐ°Ð±ÑÐ°Ð² Ð°ÐŽÑÐµÑ Ð² Ð±ÑÐ°ÑÐ·ÐµÑÐµ, Ð° ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑ ÐŸÑÐ²ÐµÑÐ°ÐµÑ, ÑÑÐŸ ÑÑÑÐ°ÐœÐžÑÐ° ÐœÐµÐŽÐŸÑÑÑÐ¿ÐœÐ°. ÐÐ±ÑÑÑÐœÐµÐœÐžÐµ ÑÑÐŸÐ³ÐŸ ÑÐŸÑÑÐŸÐžÑ Ð² ÑÐŸÐŒ, ÑÑÐŸ ÑÑÑÐ°ÐœÐžÑÐ° ÐŒÐŸÐ¶ÐµÑ ÐžÑÑ
+ÐŸÐŽÐžÑÑ ÐžÐ· locally cashed copy. Ð ÑÐŸÐ¶Ð°Ð»ÐµÐœÐžÑ, locally cashed copy ÑÐ²Ð»ÑÑÑÑÑ ÐœÐµÐ²ÐžÐŽÐžÐŒÑÐŒÐž ÐŽÐ»Ñ ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑÐ°. Ð ÑÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ ÐŒÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÐŒ ÑÐœÐ°ÑÐ°Ð»Ð° Ð·Ð°Ð³ÑÑÐ·ÐžÑÑ ÑÑÐž ÑÑÑÐ°ÐœÐžÑÑ ÐžÐ· ÐÐœÑÐµÑÐœÐµÑÐ°.</Text>
+</Content>
+</Subsection>
+<Subsection id="configuring_the_collection">
+<Title>
+<Text id="528">ÐÐ°ÑÑÑÐŸÐ¹ÐºÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_5">
+<Title>
+<Text id="529">ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑÐ° ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (ÐÑÐŸÐŽÐŸÐ»Ð¶)</Text>
+<SubTitle>
+<Text id="530">(f)</Text>
+</SubTitle>
+</Title>
+<File width="369" height="467" url="images/User_Fig_16f.png"/>
+</Figure>
+<Text id="531">ÐÐ° Ð ÐžÑÑÐœÐºÐµ 16f ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐ° ÑÐ»ÐµÐŽÑÑÑÐ°Ñ ÑÑÐ°ÐŽÐžÑ. Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ Ðž Ð¿ÐŸÐºÐ°Ð· Ð²ÑÐµÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐºÐŸÐœÑÑÐŸÐ»ÐžÑÑÐµÑÑÑ ÐŸÑÐŽÐµÐ»ÑÐœÑÐŒ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐŒ ÑÐ°Ð¹Ð»ÐŸÐŒ (ÑÐŒÐŸÑÑÐžÑÐµ ÐœÐžÐ¶Ðµ). ÐÐŸÐ»ÐµÐµ ÐŸÐ¿ÑÑÐœÑÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ðž ÐŒÐŸÐ³ÑÑ ÑÐ°Ð±ÐŸÑÐ°ÑÑ Ñ ÑÑÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐµÐ¹ ÐŽÐ»Ñ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÑ
+ ÐœÐ°ÑÑÑÐŸÐµÐº. ÐÐŽÐœÐ°ÐºÐŸ, Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹ ÑÑÐ°Ð·Ñ Ð¶Ðµ Ð¿ÐµÑÐµÐ¹ÐŽÑÑ Ðº Ð·Ð°Ð²ÐµÑÑÐ°ÑÑÐµÐ¹ ÑÑÐ°ÐŽÐžÐž. ÐÐ° Ð ÐžÑÑÐœÐºÐµ 16d ÐºÐœÐŸÐ¿ÐºÐž configure collection (ÐœÐ°ÑÑÑÐŸÐžÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ) Ðž build collection (Ð¿ÐŸÑÑÑÐŸÐžÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ) ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÑ Ð·ÐµÐ»ÐµÐœÑÐŒ ÑÐ²ÐµÑÐŸÐŒ, ÐŸÐ·ÐœÐ°ÑÐ°Ñ, ÑÑÐŸ ÑÑÐµÑÑÑ ÑÑÐ°ÐŽÐžÑ ÐŒÐŸÐ¶ÐœÐŸ Ð¿ÑÐŸÑÑÐŸ Ð¿ÑÐŸÐ¿ÑÑÑÐžÑÑ.</Text>
+<Text id="532">Ð ÐœÐ°ÑÐµÐŒ Ð¿ÑÐžÐŒÐµÑÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð²ÐœÐµÑ ÐœÐµÐ±ÐŸÐ»ÑÑÐžÐµ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ð² ÐœÐ°ÑÐ°Ð»ÑÐœÑÑ Ð²ÐµÑÑÐžÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž, ÐŽÐŸÐ±Ð°Ð²ÐžÐ² ÑÐ»Ð°Ð³ file_is_url Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐŒ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµÐŒ (plugin) HTML. Ð­ÑÐŸÑ ÑÐ»Ð°Ð¶ÐŸÐº Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð²ÑÑÐ°Ð²Ð»ÑÑÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐžÐœÑÐµÑÐœÐµÑ-Ð°ÐŽÑÐµÑÐŸÐ² Ð² ÐºÐ°Ð¶ÐŽÑÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐž Ñ ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ¹ ÐºÐŸÐœÐ²ÐµÐœÑÐžÐµÐ¹, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐŸÐ¹. Ð­ÑÐž ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÐŒ ÑÐµÑÐµÐ· ÑÑÑÐ»ÐºÑ ÑÐŸÐµÐŽÐžÐœÑÑÑÑÑ Ñ ÐŸÑÐžÐ³ÐžÐœÐ°Ð»ÐŸÐŒ, ÐºÐŸÑÐŸÑÑÐ¹ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² ÐÐœÑÐµÑÐœÐµÑÐµ, Ð° ÐœÐµ Ñ ÐºÐŸÐ¿ÐžÐµÐ¹, ÐœÐ°Ñ
+ÐŸÐŽÑÑÐµÐ¹ÑÑ Ð² ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ.</Text>
+</Content>
+</Subsection>
+<Subsection id="building_the_collection_1">
+<Title>
+<Text id="533">ÐÐŸÑÑÑÐŸÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Figure id="using_the_collector_to_build_a_new_collection_6">
+<Title>
+<Text id="534">ÐÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐµ ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑÐ° ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (ÐÑÐŸÐŽÐŸÐ»Ð¶)</Text>
+<SubTitle>
+<Text id="535">(g)</Text>
+</SubTitle>
+</Title>
+<File width="369" height="304" url="images/User_Fig_16g.png"/>
+</Figure>
+<Text id="536">Ð ÐžÑÑÐœÐŸÐº 16g Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÑÑÐ°ÐŽÐžÑ âÐ¿ÐŸÑÑÑÐŸÐµÐœÐžÑâ. ÐÐ° ÑÑÐŸÐ¹ ÑÑÐ°ÐŽÐžÐž Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ ÑÐ°ÐŒÐŸ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. </Text>
+<Text id="537">ÐÐŸ Ð²ÑÐµÐŒÑ ÑÑÐŸÐ³ÐŸ Ð¿ÑÐŸÑÐµÑÑÐ° ÑÐŸÐ·ÐŽÐ°ÑÑÑÑ ÐžÐœÐŽÐµÐºÑÑ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° Ðž Ð¿ÐŸÐžÑÐºÐ° Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐž Ñ ÑÐµÐŒ, ÑÑÐŸ Ð²Ñ Ð²Ð²ÐµÐ»Ðž Ð² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð». ÐÑÐŸÑÐµÑÑ Ð·Ð°ÐœÐžÐŒÐ°ÐµÑ ÐœÐµÐºÐŸÑÐŸÑÐŸÐµ Ð²ÑÐµÐŒÑ: ÐŸÑ ÐŒÐžÐœÑÑ ÐŽÐŸ ÑÐ°ÑÐŸÐ² Ð² Ð·Ð°Ð²ÐžÑÐžÐŒÐŸÑÑÐž ÐŸÑ ÑÐ°Ð·ÐŒÐµÑÐŸÐ² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð±ÑÑÑÑÐŸÐŽÐµÐ¹ÑÑÐ²ÐžÑ Ð²Ð°ÑÐµÐ³ÐŸ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐ°. ÐÐµÐºÐŸÑÐŸÑÑÐµ ÐŸÐ±ÑÐµÐŒÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð·Ð°ÐœÐžÐŒÐ°ÑÑ ÐŽÐ°Ð¶Ðµ ÑÐµÐ»ÑÐ¹ ÐŽÐµÐœÑ.</Text>
+<Text id="538">ÐÐŸÐ³ÐŽÐ° Ð²Ñ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÐµÑÑ ÐœÐ° ÑÑÐŸÐ¹ ÑÑÐ°ÐŽÐžÐž, Ð²ÐœÐžÐ·Ñ ÑÑÑÐ°ÐœÐžÑÑ ÑÐ¿ÐµÑÐžÐ°Ð»ÑÐœÐ°Ñ Ð¿Ð°ÐœÐµÐ»Ñ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ, ÐºÐ°Ðº Ð¿ÑÐŸÑ
+ÐŸÐŽÐžÑ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÐµ, ÐŸÐ±ÐœÐŸÐ²Ð»ÑÑÑÑ ÑÐµÑÐµÐ· ÐºÐ°Ð¶ÐŽÑÐµ Ð¿ÑÑÑ ÑÐµÐºÑÐœÐŽ.</Text>
+<Text id="539">Ð ÑÐ»ÑÑÐ°Ðµ, ÐºÐŸÐ³ÐŽÐ° ÑÐºÐ°Ð·Ð°ÐœÑÐµ ÐžÑÑ
+ÐŸÐŽÐœÑÐµ ÑÐ°Ð¹Ð»Ñ ÐžÐ»Ðž ÐžÐœÑÐµÑÐœÐµÑ-Ð°ÐŽÑÐµÑÐ° ÐœÐµ ÑÑÑÐµÑÑÐ²ÑÑÑ ÐžÐ»Ðž ÐŸÐœÐž ÐµÑÑÑ, ÐœÐŸ ÐŸÑÑÑÑÑÑÐ²ÑÐµÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐœÐŸÐµ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ (plugin), ÐºÐŸÑÐŸÑÐŸÐµ ÐŒÐŸÐ³Ð»ÐŸ Ð±Ñ ÐžÑ
+ ÐŸÐ±ÑÐ°Ð±ÐŸÑÐ°ÑÑ, ÐžÐ»Ðž plugin ÐœÐµ ÐŒÐŸÐ¶ÐµÑ ÐœÐ°Ð¹ÑÐž ÑÐŸÐ¿ÑÑÑÑÐ²ÑÑÑÐžÐ¹ ÑÐ°Ð¹Ð», ÑÐ°ÐºÐŸÐ¹ ÐºÐ°Ðº ÑÐžÑÑÐœÐŸÐº, ÐœÐ°Ñ
+ÐŸÐŽÑÑÐžÐ¹ÑÑ Ð² ÐŽÐŸÐºÑÐŒÐµÐœÑÐµ ÑÐŸÑÐŒÐ°ÑÐ° HTML ÑÐŸ Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ Ð¿ÑÐµÐŽÑÐ¿ÑÐµÐ¶ÐŽÐ°ÑÑÐµÐµ ÑÐŸÐŸÐ±ÑÐµÐœÐžÐµ. Ð­ÑÐŸ ÑÐŽÐµÐ»Ð°ÐœÐŸ Ñ ÑÐŸÐ¹ ÑÐµÐ»ÑÑ ÑÑÐŸÐ±Ñ Ð²Ñ ÐŒÐŸÐ³Ð»Ðž ÐœÐ°Ð±Ð»ÑÐŽÐ°ÑÑ Ð·Ð° Ð¿ÑÐŸÑÐµÑÑÐŸÐŒ. ÐÑÐ»Ðž Ð¿ÑÐŸÐžÐ·ÐŸÐ¹ÐŽÑÑ ÐºÐ°ÐºÐžÐµ-Ð»ÐžÐ±ÐŸ ÑÐ±ÐŸÐž ÐžÐ»Ðž ÐŸÑÐžÐ±ÐºÐž, ÐºÐŸÑÐŸÑÑÐµ ÐŸÑÐŒÐµÐœÑÑ Ð¿ÑÐŸÑÐµÑÑ, ÐŸÐœÐž Ð±ÑÐŽÑÑ Ð²ÑÐ²ÐµÐŽÐµÐœÑ Ð² ÑÑÐŸÐŒ ÐŸÐºÐœÐµ.</Text>
+<Text id="540">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐµÐºÑÐ°ÑÐžÑÑ Ð¿ÑÐŸÑÐµÑÑ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ Ð² Ð»ÑÐ±ÐŸÐµ Ð²ÑÐµÐŒÑ, ÐœÐ°Ð¶Ð°Ð² ÐœÐ° ÐºÐœÐŸÐ¿ÐºÑ stop building (Ð¿ÑÐµÐºÑÐ°ÑÐžÑÑ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÐµ), ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐœÐŸÐ¹ ÐœÐ° Ð ÐžÑÑÐœÐºÐµ 16g. ÐÑÐ»Ðž Ð²Ñ ÐœÐµ Ð²ÐŒÐµÑÐ°ÐµÑÐµÑÑ Ð² Ð¿ÑÐŸÑÐµÑÑ, ÑÐŸ ÐŸÐœ Ð¿ÑÐŸÐŽÐŸÐ»Ð¶ÐžÑÑÑ, Ðž ÐœÐŸÐ²Ð°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð±ÑÐŽÐµÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° Ðž ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐ° Ð¿ÐŸÑÐ»Ðµ Ð·Ð°Ð²ÐµÑÑÐµÐœÐžÑ Ð¿ÑÐŸÑÐµÑÑÐ°.</Text>
+</Content>
+</Subsection>
+<Subsection id="viewing_the_collection">
+<Title>
+<Text id="541">ÐÑÐŸÑÐŒÐŸÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="542">ÐÐŸÑÐ»Ðµ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ Ðž ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð² Ð ÐžÑÑÐœÐºÐµ 16g ÐœÐ° ÐœÐžÐ¶ÐœÐµÐ¹ Ð¿Ð°ÐœÐµÐ»Ðž Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ ÑÑÐŽ ÐºÐœÐŸÐ¿ÐŸÐº, ÐºÐŸÑÐŸÑÑÐµ Ð±ÑÐ»Ðž ÐœÐ° Ð ÐžÑÑÐœÐºÐ°Ñ
+  16b-f Ñ Ð°ÐºÑÐžÐ²ÐœÐŸÐ¹ ÐºÐœÐŸÐ¿ÐºÐŸÐ¹ View (ÐÑÐŸÑÐŒÐŸÑÑ). ÐÐ°Ð¶Ð°Ð² ÐœÐ° ÐœÐµÐµ Ð²Ñ ÑÑÐ°Ð·Ñ Ð¿ÐŸÐ¿Ð°ÐŽÐµÑÐµ Ð² ÐœÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ.</Text>
+<Text id="543">Ð ÐœÐ°ÐºÐŸÐœÐµÑ ÑÑÑÐµÑÑÐ²ÑÐµÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ Ð¿ÐŸÑÐ»Ð°ÑÑ ÑÐ»ÐµÐºÑÑÐŸÐœÐœÑÑ Ð¿ÐŸÑÑÑ ÑÐžÑÑÐµÐŒÐœÐŸÐŒÑ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐ°ÑÐŸÑÑ ÑÑÐ°Ð·Ñ Ð¶Ðµ Ð¿ÐŸÑÐ»Ðµ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (ÐžÐ»Ðž ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ). Ð­ÑÐŸ Ð¿ÐŸÐŒÐŸÐ³Ð°ÐµÑ Ð»ÐžÑÐ°ÐŒ, ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÑÐŒ Ð·Ð° ÑÐžÑÑÐµÐŒÑ, Ð±ÑÑÑ ÐŸÑÐ²ÐµÐŽÐŸÐŒÐ»ÐµÐœÐœÑÐŒÐž ÐŸ Ð²ÑÐµÑ
+ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑÑ
+ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÑÑÐžÑ
+ Ð² ÑÐžÑÑÐµÐŒÐµ. ÐÐ²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐ°Ñ ÐŸÑÑÑÐ»ÐºÐ° email Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ Ð²ÑÐºÐ»ÑÑÐµÐœÐ°, ÐœÐŸ Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÐµÐµ Ð°ÐºÑÐžÐ²ÐžÑÐŸÐ²Ð°ÑÑ, ÐœÐ°ÑÑÑÐŸÐžÐ² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» main.cfg (Ð¡ÐŒÐŸÑÑÐžÑÐµ ÑÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ°, ÑÐ°ÑÑÑ <CrossRef target="Chapter" external="Develop" lang="ru" ref="configuring_your_greenstone_site"/>).</Text>
+</Content>
+</Subsection>
+<Subsection id="working_with_existing_collections">
+<Title>
+<Text id="544">Ð Ð°Ð±ÐŸÑÐ° Ñ ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐŒÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒÐž</Text>
+</Title>
+<Content>
+<Text id="545">ÐÑÐž Ð²Ñ
+ÐŸÐŽÐµ Ð² ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑ Ð²Ñ ÐŽÐŸÐ»Ð¶ÐœÑ ÑÐºÐ°Ð·Ð°ÑÑ, Ñ
+ÐŸÑÐžÑÐµ Ð»Ðž Ð²Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ Ð¿ÐŸÐ»ÐœÐŸÑÑÑÑ ÐœÐŸÐ²ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐžÐ»Ðž ÑÐ°Ð±ÐŸÑÐ°ÑÑ Ñ ÑÑÑÐµÑÑÐ²ÑÑÑÐµÐ¹, ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑ ÐžÐ»Ðž ÑÐŽÐ°Ð»ÑÑ ÐŽÐ°ÐœÐœÑÐµ. Ð¡ÐŸÐ·ÐŽÐ°Ð²Ð°Ñ Ð²ÑÐµÐ²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÐµ ÑÑÑÑÐºÑÑÑÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž, Greenstone Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ñ Ð»ÐµÐ³ÐºÐŸÑÑÑÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑÑ ÐœÐŸÐ²ÑÐµ ÐŽÐ°ÐœÐœÑÐµ Ð² ÑÑÑÐµÑÑÐ²ÑÑÑÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="546">ÐÐ»Ñ ÑÐ°Ð±ÐŸÑÑ ÑÐŸ ÑÑÐ°ÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹ Ð²Ñ ÑÐœÐ°ÑÐ°Ð»Ð° ÐŽÐŸÐ»Ð¶ÐœÑ Ð²ÑÐ±ÑÐ°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐžÐ· Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÐµÐœÐœÐŸÐ³ÐŸ ÑÐ¿ÐžÑÐºÐ°. ÐÐµÐºÐŸÑÐŸÑÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐžÐ·Ð°ÑÐžÑÐµÐœÑ ÐŸÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÐ¹: ÑÐ°ÐºÐžÐµ ÐœÐµ Ð¿ÐŸÑÐ²Ð»ÑÑÑÑÑ Ð² ÑÐ¿ÐžÑÐºÐµ. Ð¡ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐµÐ¹ Ð²Ñ ÑÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÑÐŸÐ²ÐµÑÑÐž ÑÐ»ÐµÐŽÑÑÑÐžÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ:</Text>
+<BulletList>
+<Bullet>
+<Text id="547">ÐÐŸÐ±Ð°Ð²ÐžÑÑ ÐœÐŸÐ²ÑÐµ ÐŽÐ°ÐœÐœÑÐµ Ðž Ð¿ÐµÑÐµÑÑÑÐŸÐžÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ</Text>
+</Bullet>
+<Bullet>
+<Text id="548">Ð ÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</Bullet>
+<Bullet>
+<Text id="549">ÐÐŸÐ»ÐœÐŸÑÑÑÑ ÑÐŽÐ°Ð»ÐžÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ</Text>
+</Bullet>
+<Bullet>
+<Text id="550">ÐÐµÑÐµÐ¿ÐžÑÐ°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐœÐ° CD-ROM</Text>
+</Bullet>
+</BulletList>
+<Part id="add_new_data">
+<Title>
+<Text id="551">ÐÐŸÐ±Ð°Ð²Ð»ÐµÐœÐžÐµ ÐœÐŸÐ²ÑÑ
+ ÐŽÐ°ÐœÐœÑÑ
+ </Text>
+</Title>
+<Content>
+<Text id="552">Ð€Ð°Ð¹Ð»Ñ, ÑÐºÐ°Ð·Ð°ÐœÐœÑÐµ Ð²Ð°ÐŒÐž, Ð±ÑÐŽÑÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÐµÐœÑ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. ÐÐ°ÐŒ ÑÐ»ÐµÐŽÑÐµÑ ÑÐ±ÐµÐŽÐžÑÑÑÑ Ð² ÑÐŸÐŒ, ÑÑÐŸÐ±Ñ ÑÐºÐ°Ð·Ð°ÐœÐœÑÐ¹ Ð²Ð°ÐŒÐž ÑÐ°Ð¹Ð» ÐœÐµ Ð±ÑÐ» ÑÐ¶Ðµ Ð² ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÐžÐœÐ°ÑÐµ ÑÐ°ÐŒ Ð±ÑÐŽÑÑ ÐŽÐ²Ðµ ÐºÐŸÐ¿ÐžÐž ÐŸÐŽÐœÐŸÐ³ÐŸ Ðž ÑÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð°. Ð€Ð°Ð¹Ð»Ñ ÐœÑÐ¶ÐœÐŸ ÑÐºÐ°Ð·ÑÐ²Ð°ÑÑ Ð¿ÐŸ Ð¿ÐŸÐ»ÐœÑÐŒ ÐœÐ°Ð·Ð²Ð°ÐœÐžÑÐŒ (pathname), Ð° Ð²ÑÐ±-ÑÑÑÐ°ÐœÐžÑÑ ÐžÑ
+ Ð¿ÐŸÐ»ÐœÑÐŒÐž www-Ð°ÐŽÑÐµÑÐ°ÐŒÐž. Ð¢ÐŸÑÐœÐŸ ÑÐ°Ðº Ð¶Ðµ Ð²Ñ ÐŽÐŸÐ»Ð¶ÐœÑ ÑÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž Ðž ÑÐ°Ð¹Ð»Ñ Ð¿ÑÐž Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÐž ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="553">ÐÑÐ»Ðž Ð²Ñ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑÐµ ÐŽÐ°ÐœÐœÑÐµ Ðº ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð¿ÐŸ ÐºÐ°ÐºÐŸÐ¹-ÑÐŸ Ð¿ÑÐžÑÐžÐœÐµ Ð¿ÑÐŸÑÐµÑÑ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐŸÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑÑÑ, ÑÐŸ ÑÑÐ°ÑÐ°Ñ Ð²ÐµÑÑÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŸÑÑÐ°ÐµÑÑÑ Ð±ÐµÐ· ÐžÐ·ÐŒÐµÐœÐµÐœÐžÐ¹.</Text>
+</Content>
+</Part>
+<Part id="edit_configuration_file">
+<Title>
+<Text id="554">Ð ÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð°</Text>
+</Title>
+<Content>
+<Text id="555">ÐÐ¿ÑÑÐœÑÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ðž ÐŒÐŸÐ³ÑÑ ÑÐµÐŽÐ°ÐºÑÐžÑÐŸÐ²Ð°ÑÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð ÑÐµÑÐ²ÐµÑÑÐŸÐ¹ ÑÐ°ÑÑÐž ÐŸÐ¿ÐžÑÐ°ÐœÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐµ ÑÑÑÐ°ÐœÐŸÐ²ÐºÐž.</Text>
+</Content>
+</Part>
+<Part id="delete_the_collection">
+<Title>
+<Text id="556">Ð£ÐŽÐ°Ð»ÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹</Text>
+</Title>
+<Content>
+<Text id="557">ÐÑÐž ÑÐŽÐ°Ð»ÐµÐœÐžÐž Ð²Ð°Ñ Ð¿ÐŸÐ¿ÑÐŸÑÑÑ Ð¿ÐŸÐŽÑÐ²ÐµÑÐŽÐžÑÑ ÑÐŽÐ°Ð»ÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐ°Ð¿ÐŸÐŒÐœÐžÑÐµ, ÑÑÐŸ Ð¿ÐŸÑÐ»Ðµ ÑÐŽÐ°Ð»ÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐœÐµ Ð²ÐŸÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÑÑÑÑ.</Text>
+</Content>
+</Part>
+<Part id="export_the_collection">
+<Title>
+<Text id="558">ÐÐµÑÐµÐŒÐµÑÐµÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹</Text>
+</Title>
+<Content>
+<Text id="559">ÐÑ ÐŒÐŸÐ¶ÐµÑÐµ Ð¿ÐµÑÐµÐœÐµÑÑÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð² ÑÐŸÑÐŒÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ Ð·Ð°Ð¿ÐžÑÐ°ÐœÐ° ÐœÐ° Ð°Ð²ÑÐŸÐœÐŸÐŒÐœÑÐ¹, ÑÐ°ÐŒÐŸÐ·Ð°Ð¿ÐžÑÑÐ²Ð°ÑÑÐžÐ¹ÑÑ CD-ROM, ÑÐ°Ð±ÐŸÑÐ°ÑÑÐžÐ¹ Ð² Windows. Ð¢Ð°Ðº ÐºÐ°Ðº ÐŽÑÑÐ³ÐžÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ, Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑÐžÐµ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ ÑÐ°ÐŒÐŸ-ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÑÑÐžÐµÑÑ CD-ROM, ÐŽÐŸÑÐŸÐ³Ðž, Ð² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐµ ÑÑÑÐµÑÑÐ²ÑÐµÑ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐŸÐœÐœÑÐ¹ ÐŒÐŸÐŽÑÐ»Ñ.</Text>
+<Text id="560">ÐÐŸÑÐ»Ðµ ÑÐŸÐ³ÐŸ, ÐºÐ°Ðº Ð²Ñ Ð¿ÐµÑÐµÐŒÐµÑÑÐžÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, Ð² ÐŽÐžÐ°Ð»ÐŸÐ³ÐŸÐ²ÐŸÐŒ ÐŸÐºÐœÐµ Ð²ÑÑÐ²ÐµÑÐžÑÑÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ, Ð² ÐºÐŸÑÐŸÑÑÑ ÐŸÐœÐ° Ð¿ÐµÑÐµÐœÐµÑÐµÐœÐ°. ÐÑÐž Ð·Ð°Ð¿ÐžÑÐž Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÑÑÑÑÐŸÐ¹ÑÑÐ²Ð° ÐŽÐ»Ñ Ð·Ð°Ð¿ÐžÑÐž CD (CD-Writer) ÐœÑÐ¶ÐœÐŸ ÑÐ±ÐµÐŽÐžÑÑÑÑ, ÑÑÐŸ Ð²ÑÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ Ð±ÑÐ»Ð° Ð·Ð°Ð¿ÐžÑÐ°ÐœÐ° ÐœÐ° ÐŽÐžÑÐº.</Text>
+<Text id="561">ÐÑ ÐœÐµ ÑÐŒÐŸÐ³Ð»Ðž ÐŽÐŸ ÐºÐŸÐœÑÐ° Ð¿ÑÐŸÐ²ÐµÑÐžÑÑ Ðž Ð¿ÑÐŸÑÐµÑÑÐžÑÐŸÐ²Ð°ÑÑ Greenstone Installer Ð¿ÑÐž Ð²ÑÐµÐ²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÑ
+ ÑÑÐ»ÐŸÐ²ÐžÑÑ
+ Ð² ÑÐ²ÑÐ·Ðž Ñ ÐŸÑÐµÐœÑ Ð±ÐŸÐ»ÑÑÐžÐŒ ÑÐ°Ð·ÐœÐŸÐŸÐ±ÑÐ°Ð·ÐžÐµÐŒ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐ¹ Windows. Ð¥ÐŸÑÑ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐŸÑ ÐŒÐŸÐ¶ÐµÑ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ CD-ROMÑ, ÑÐ°Ð±ÐŸÑÐ°ÑÑÐžÐµ Ð² ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÑÑ
+ Windows, ÐŸÐœ Ð²ÑÐµ ÐµÑÐµ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² ÑÑÐ°ÐŽÐžÐž ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÐºÐž. ÐÑÐ»Ðž Ð²Ñ ÑÑÐŸÐ»ÐºÐœÐµÑÐµÑÑ Ñ ÐºÐ°ÐºÐžÐŒÐž-Ð»ÐžÐ±ÐŸ Ð¿ÑÐŸÐ±Ð»ÐµÐŒÐ°ÐŒÐž Ðž Ð±ÑÐŽÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐºÐŸÐŒÐŒÐµÑÑÐµÑÐºÐžÐµ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐŸÐœÐœÑÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ (ÑÐ°ÐºÐžÐµ, ÐºÐ°Ðº InstallShield) ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ Ð¡D, Ð²Ñ ÐŒÐŸÐ¶ÐµÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ, Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÐµÐœÐœÑÑ Greenstone. ÐÑÑÐµÑÐ¿ÐŸÐŒÑÐœÑÑÐ°Ñ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ, ÐºÑÐŽÐ° Ð¿ÐµÑÐµÐŒÐµÑÐ°ÑÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐŸÐŽÐµÑÐ¶ÐžÑ ÑÐµÑÑÑÐµ ÑÐ°Ð¹Ð»Ð°, ÐŸÑÐœÐŸÑÑÑÐžÐµÑÑ Ðº ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐŸÐœÐœÐŸÐŒÑ Ð¿ÑÐŸÑÐµÑÑÑ, Ðž ÑÑÐž Ð¿ÐŸÐŽÐŽÐžÑÐµÐºÑÐŸÑÐžÐž, ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐŽÐµÑÐ¶Ð°Ñ Ð·Ð°ÐºÐŸÐœÑÐµÐœÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ðž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ. Ð£ÐŽÐ°Ð»ÐžÑÐµ ÑÑÐž ÑÐµÑÑÑÐµ ÑÐ°Ð¹Ð»Ð° Ðž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐ¹ÑÐµ InstallShield ÐŽÐ»Ñ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž ÑÑÐžÑ
+ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐ¹ Ðž ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÑÑÐ»ÑÐºÐ° Ðº Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐµ gsdl\server.exe.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+<Subsection id="document_formats_1">
+<Title>
+<Text id="562">Ð€ÐŸÑÐŒÐ°ÑÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² </Text>
+</Title>
+<Content>
+<Text id="563">ÐÑÐž Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑ ÐºÐ°Ð¶ÐŽÑÐ¹ ÑÐŸÑÐŒÐ°Ñ ÐžÑÑ
+ÐŸÐŽÐœÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° Ð¿ÑÑÐµÐŒ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐµÐœÐžÐ¹ Ðº Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐµ (ÐŽÐ°Ð»ÐµÐµ ÐžÐŒÐµÐœÑÐµÑÑÑ - Ð¿Ð»Ð°Ð³ÐžÐœ), ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³Ð»Ðž Ð±Ñ ÑÐ°Ð±ÐŸÑÐ°ÑÑ Ñ ÐºÐ°Ð¶ÐŽÑÐŒ ÑÐŸÑÐŒÐ°ÑÐŸÐŒ Ð¿ÐŸ ÐŸÑÐŽÐµÐ»ÑÐœÐŸÑÑÐž. ÐÐ»Ð°Ð³ÐžÐœÑ ÑÐºÐ°Ð·Ð°ÐœÑ Ð² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Greenstone ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÑÐ°ÑÑÐžÑÐµÐœÐžÐ¹ ÐŽÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ ÑÐŸÑÐŒÐ°ÑÐŸÐ² ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², â ÐœÐ°Ð¿ÑÐžÐŒÐµÑ, foo.txt ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑÑÑ ÐºÐ°Ðº ÑÐµÐºÑÑÐŸÐ²ÐŸÐ¹ ÑÐ°Ð¹Ð», foo.html ÐºÐ°Ðº HTML, Ð° foo.doc ÐºÐ°Ðº ÐŽÐŸÐºÑÐŒÐµÐœÑ Word.</Text>
+<Text id="564">ÐÐžÐ¶Ðµ Ð²Ñ ÑÐ²ÐžÐŽÐžÑÐµ ÑÐ¿ÐžÑÐŸÐº Ð¿Ð»Ð°Ð³ÐžÐœÐŸÐ², ÐŽÐŸÑÑÑÐ¿ÐœÑÑ
+ ÐŽÐ»Ñ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ Ð²ÐžÐŽÐŸÐ² ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². ÐÐŸÐ»ÐµÐµ ÐŽÐµÑÐ°Ð»ÑÐœÐŸÐµ ÐŸÐ±ÑÑÑÐœÐµÐœÐžÐµ ÐŸ ÐœÐžÑ
+ Ðž ÐŽÑÑÐ³ÐžÑ
+ Ð²ÐžÐŽÐ°Ñ
+ ÑÐµÐŽÐºÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÑ
+ ÑÐŸÑÐŒÐ°ÑÐŸÐ² ÐŒÐŸÐ¶ÐœÐŸ ÐœÐ°Ð¹ÑÐž Ð² Ð ÑÐŸÐ²ÐŸÐŽÑÑÐ²Ðµ Ð Ð°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ°.</Text>
+<Part id="textplug">
+<Title>
+<Text id="565">TEXTPlug (*.txt, *.text)</Text>
+</Title>
+<Content>
+<Text id="566">TEXTPlug ÑÐ°ÑÐ¿ÐŸÐ·ÐœÐ°ÐµÑ Ð¿ÑÐŸÑÑÐŸÐ¹ ÑÐµÐºÑÑÐŸÐ²ÐŸÐ¹ ÑÐ°Ð¹Ð» ÐºÐ°Ðº ÐŸÐ±ÑÑÐœÑÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ. ÐÐœ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ, ÐŸÑÐœÐŸÐ²ÑÐ²Ð°ÑÑÑ ÐœÐ° Ð¿ÐµÑÐ²ÐŸÐ¹ ÑÑÑÐŸÐºÐµ ÑÐ°Ð¹Ð»Ð°. </Text>
+</Content>
+</Part>
+<Part id="htmlplug_(*.htm,_*.html;_also_.shtml,_.shm,_.asp,_.php,_.cgi)">
+<Title>
+<Text id="567">HTMLPlug (*.htm, *.html; also .shtml, .shm, .asp, .php, .cgi)</Text>
+</Title>
+<Content>
+<Text id="568">HTMLPlug ÐŸÐ±ÑÐ°Ð±Ð°ÑÑÐ²Ð°ÐµÑ HTML-ÑÐ°Ð¹Ð»Ñ. ÐÐœ Ð¿ÐŸÐ»ÑÑÐ°ÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ, ÐŸÑÐœÐŸÐ²ÑÐ²Ð°ÑÑÑ ÐœÐ° ÑÑÐ³Ðµ &lt;title&gt; (ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ), ÐŽÑÑÐ³ÐžÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐ°ÐºÐ¶Ðµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð¿ÐŸÐ»ÑÑÐµÐœÑ Ð¿ÑÐž Ð¿ÐŸÐŒÐŸÑÐž ÑÐžÐœÑÐµÐºÑÐ° ÐŒÐµÑÐ°ÑÑÐ³ÐŸÐ² HTML (HTMLâs metatag syntex) . Ð¡ÑÑÐµÑÑÐ²ÑÑÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž Ð¿ÑÐž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž ÑÑÐŸÐ³ÐŸ Ð¿Ð»Ð°Ð³ÐžÐœÐ°, ÐŸÐ¿ÐžÑÐ°ÐœÐœÑÐµ Ð² Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ðµ Ð Ð°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ°.</Text>
+</Content>
+</Part>
+<Part id="wordplug_(*.doc)">
+<Title>
+<Text id="569">WORDPlug (*.doc)</Text>
+</Title>
+<Content>
+<Text id="570">WORDPlug ÐžÐŒÐ¿ÐŸÑÑÐžÑÑÐµÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Microsoft Word. Ð¡ÑÑÐµÑÑÐ²ÑÐµÑ ÐŒÐœÐŸÐ³ÐŸ ÑÐ°Ð·ÐœÑÑ
+ Ð²ÐµÑÑÐžÐ¹ ÑÐŸÑÐŒÐ°ÑÐ° Word, Ðž ÐŽÐ°Ð¶Ðµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Microsoft ÑÐ°ÑÑÐŸ ÑÐŸÐ²ÐµÑÑÐ°ÑÑ ÐŸÑÐžÐ±ÐºÐž Ð¿ÑÐž Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÐœÐžÐž. Greenstone ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÐœÐµÐ·Ð°Ð²ÐžÑÐžÐŒÑÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ ÐŽÐ»Ñ Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÐœÐžÑ ÑÐ°Ð¹Ð»ÐŸÐ² Word Ð² ÑÐŸÑÐŒÐ°Ñ HTML. ÐÐ»Ñ ÐœÐµÐºÐŸÑÐŸÑÑÑ
+ ÑÑÐ°ÑÑÑ
+ ÑÐŸÑÐŒÐ°ÑÐŸÐ² Word Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ Ð¿ÑÐŸÑÑÐŸÐ¹ Ð°Ð»Ð³ÐŸÑÐžÑÐŒ ÐžÐ·Ð²Ð»ÐµÑÐµÐœÐžÑ (extraction algorithm), ÐºÐŸÑÐŸÑÑÐ¹ ÐœÐ°Ñ
+ÐŸÐŽÐžÑ Ð²ÑÐµ ÑÐµÐºÑÑÐŸÐ²ÑÐµ ÑÑÑÐŸÐºÐž Ð² ÐžÑÑ
+ÐŸÐŽÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ.</Text>
+</Content>
+</Part>
+<Part id="pdfplug_(*.pdf)">
+<Title>
+<Text id="571">PDFPlug (*.pdf)</Text>
+</Title>
+<Content>
+<Text id="572">PDFPlug ÐžÐŒÐ¿ÐŸÑÑÐžÑÑÐµÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ Ð² ÑÐŸÑÐŒÐ°ÑÐµ PDF. Ð¢Ð°Ðº Ð¶Ðµ, ÐºÐ°Ðº Ðž WORDPlug, ÐŸÐœ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÐœÐµÐ·Ð°Ð²ÐžÑÐžÐŒÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, Ð² ÑÑÐŸÐŒ ÑÐ»ÑÑÐ°Ðµ pdftohtml, ÐŽÐ»Ñ Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÐœÐžÑ PDF ÑÐ°Ð¹Ð»ÐŸÐ² Ð² HTML.</Text>
+<Text id="573">ÐÐ°Ðº Ðž Ð² ÑÐ»ÑÑÐ°Ðµ Ñ WORDPlug, Ð¿ÑÐž ÐœÐ°Ð¶Ð°ÑÐžÐž ÐœÐ° ÐžÐºÐŸÐœÐºÑ document ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ Ð±ÑÐŽÐµÑ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÑÐ°Ð¹Ð», ÑÐºÐ²ÐžÐ²Ð°Ð»ÐµÐœÑÐœÑÐ¹ HTML; ÑÐµÐŒ ÐœÐµ ÐŒÐµÐœÐµÐµ, ÑÑÑÐŸÐºÐž ÑÐŸÑÐŒÐ°ÑÐ° Ð² ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐœÐ°ÑÑÑÐŸÐµÐœÑ ÑÐ°Ðº, ÑÑÐŸÐ±Ñ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÐžÑÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐžÐŒÐµÑÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÐœÐ°ÑÐ°Ð»ÑÐœÐŸÐŒÑ PDF-ÑÐ°Ð¹Ð»Ñ, Ðž ÐŒÑ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÐŒ Ð²Ð°ÐŒ ÑÐŽÐµÐ»Ð°ÑÑ ÐžÐŒÐµÐœÐœÐŸ ÑÐ°Ðº. Ð¡ÐœÐŸÐ²Ð° Ð¿ÑÐŸÑÑÐŸ Ð·Ð°ÐŒÐµÐœÐžÑÐµ ÑÑÐ³Ðž <i>&lt;link&gt; âŠ &lt;/link&gt;</i> ÐœÐ° <i>&lt;srclink&gt; âŠ &lt;/srclink&gt;</i>.</Text>
+<Text id="574">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° pdftohtml ÐœÐµ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ Ñ ÐœÐµÐºÐŸÑÐŸÑÑÐŒÐž PDF-ÑÐ°Ð¹Ð»Ð°ÐŒÐž. ÐÐµÐ»ÐŸ Ð² ÑÐŸÐŒ, ÑÑÐŸ Ð¿ÑÐŸÑÐµÑÑ Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÐœÐžÑ Ð·Ð°ÐœÐžÐŒÐ°ÐµÑ ÐŸÑÐµÐœÑ ÐŒÐœÐŸÐ³ÐŸ Ð²ÑÐµÐŒÐµÐœÐž, Ðž ÑÐ°ÑÑÐŸ Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ ÑÐŸÐŸÐ±ÑÐµÐœÐžÑ ÐŸ ÑÐ±ÐŸÐµ, ÑÐ²ÑÐ·Ð°ÐœÐœÐŸÐŒ Ñ Ð¿ÑÐŸÑÐµÑÑÐŸÐŒ Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÐœÐžÑ. ÐÑÐ»Ðž ÑÑÐŸ ÑÐ°Ðº, ÑÐŸ ÐµÐŽÐžÐœÑÑÐ²ÐµÐœÐœÐŸÐµ ÑÐµÑÐµÐœÐžÐµ - ÑÑÐŸ ÑÐŽÐ°Ð»ÐžÑÑ ÑÑÐŸÑ ÐŽÐŸÐºÑÐŒÐµÐœÑ ÐžÐ· ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. Ð¢Ð°Ðº Ð¶Ðµ PDFPlug ÐœÐµ ÐŒÐŸÐ¶ÐµÑ ÑÐ¿ÑÐ°Ð²ÐžÑÑÑÑ Ñ Ð·Ð°ÑÐžÑÑÐŸÐ²Ð°ÐœÐœÑÐŒÐž ÑÐ°Ð¹Ð»Ð°ÐŒÐž PDF.</Text>
+</Content>
+</Part>
+<Part id="psplug_(*.ps)">
+<Title>
+<Text id="575">PSPlug (*.ps)</Text>
+</Title>
+<Content>
+<Text id="576">PSPlug ÐžÐŒÐ¿ÐŸÑÑÐžÑÑÐµÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÑÐŸÑÐŒÐ°ÑÐ° PostScript. ÐÑÑÑÐµ Ð²ÑÐµÐ³ÐŸ ÐŸÐœ ÑÐ°Ð±ÐŸÑÐ°ÐµÑ, ÐµÑÐ»Ðž ÐœÐ° Ð²Ð°ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÐ°Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Linux, ÐºÐŸÑÐŸÑÐ°Ñ ÐœÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ ps2ascii. ÐÐœÐ° ÐŽÐŸÑÑÑÐ¿ÐœÐ° Ð² Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²Ðµ Linux-ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑÑ
+, ÐœÐŸ ÐœÐµ Ð² Windows. ÐÑÐ»Ðž ÑÑÐ° Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐœÐµÐŽÐŸÑÑÑÐ¿ÐœÐ°, PSPlug ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ Ð¿ÑÐŸÑÑÐŸÐ¹ Ð°Ð»Ð³ÐŸÑÐžÑÐŒ ÑÐµÐºÑÑÐŸÐ²ÐŸÐ³ÐŸ ÐžÐ·Ð²Ð»ÐµÑÐµÐœÐžÑ.</Text>
+</Content>
+</Part>
+<Part id="emailplug_(*.email)">
+<Title>
+<Text id="577">EMAILPlug (*.email)</Text>
+</Title>
+<Content>
+<Text id="578">EMAILPlug ÐžÐŒÐ¿ÐŸÑÑÐžÑÑÐµÑ ÑÐ°Ð¹Ð»Ñ, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐžÐµ ÑÐ»ÐµÐºÑÑÐŸÐœÐœÑÑ Ð¿ÐŸÑÑÑ, Ðž ÑÐ°Ð±ÐŸÑÐ°ÐµÑ Ñ Ð¿ÑÐžÐ²ÑÑÐœÑÐŒÐž E-mail ÑÐŸÑÐŒÐ°ÑÐ°ÐŒÐž, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐŒÐž Ð² Netscape, Eudora, Unix. ÐÐ°Ð¶ÐŽÑÐ¹ ÐžÑÑ
+ÐŸÐŽÐœÑÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ Ð¿ÑÐŸÐ²ÐµÑÑÐµÑÑÑ ÐœÐ° ÐœÐ°Ð»ÐžÑÐžÐµ ÐŸÐŽÐœÐŸÐ¹ ÐžÐ»Ðž ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÑ
+ ÑÐ»ÐµÐºÑÑÐŸÐœÐœÑÑ
+ Ð¿ÐŸÑÑ, ÑÐŸÐµÐŽÐžÐœÐµÐœÐœÑÑ
+ Ð² ÐŸÐŽÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ, Ðž Ð¿ÑÐµÐŸÐ±ÑÐ°Ð·ÐŸÐ²ÑÐ²Ð°ÐµÑ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐµ. ÐÐ»Ð°Ð³ÐžÐœ ÐžÐ·Ð²Ð»ÐµÐºÐ°ÐµÑ ÐºÐ°Ð¶ÐŽÑÐ¹ Ð²ÐžÐŽ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+, ÑÐ°ÐºÐžÑ
+ ÐºÐ°Ðº Ð¢ÐµÐŒÐ°, ÐÐŸÐŒÑ, ÐÑ ÐºÐŸÐ³ÐŸ, ÐÐ°ÑÐ°. Ð¢ÐµÐŒ ÐœÐµ ÐŒÐµÐœÐµÐµ, ÑÑÐŸÑ Ð¿Ð»Ð°Ð³ÐžÐœ ÐµÑÐµ ÐœÐµ ÐŒÐŸÐ¶ÐµÑ Ð¿ÐŸÐ»ÐœÐŸÑÑÑÑ ÑÐ°Ð±ÐŸÑÐ°ÑÑ Ñ Ð¿ÐŸÑÑÐŸÐ¹, ÐºÐŸÐŽÐžÑÐŸÐ²Ð°ÐœÐœÐŸÐ¹ Ð² MIME.</Text>
+</Content>
+</Part>
+<Part id="zipplug_(.gz,_.z,_.tgz,_.taz,_.bz,_.zip,_.tar)">
+<Title>
+<Text id="579">ZIPPlug (.gz, .z, .tgz, .taz, .bz, .zip, .tar)</Text>
+</Title>
+<Content>
+<Text id="580">ÐÐ»Ð°Ð³ÐžÐœ ZIPPlug ÑÐ°Ð±ÐŸÑÐ°ÐµÑ ÑÐŸ ÑÐ¶Ð°ÑÑÐŒÐž ÐžÐ»Ðž Ð·Ð°Ð°ÑÑ
+ÐžÐ²ÐžÑÐŸÐ²Ð°ÐœÐœÑÐŒÐž ÐžÑÑ
+ÐŸÐŽÐœÑÐŒÐž ÑÐŸÑÐŒÐ°ÑÐ°ÐŒÐž: gzip(.gz,.z,.tgz,.taz), bzip (.bz), zip (zip, .jar)
+and tar (.tar). ÐÐœ Ð±Ð°Ð·ÐžÑÑÐµÑÑÑ ÐœÐ° ÑÐ°ÐºÐžÑ
+ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ°Ñ
+, ÐºÐ°Ðº gunzip, bunzip,unzip Ðž bar, ÐºÐŸÑÐŸÑÑÐµ ÑÐ²Ð»ÑÑÑÑÑ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐŒÐž Linux-ÑÑÐžÐ»ÐžÑÐ°ÐŒÐž. Ð Windows ZIPPlug ÐŸÑÐºÐ»ÑÑÐµÐœ.</Text>
+</Content>
+</Part>
+</Content>
+</Subsection>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="administration">
+<Title>
+<Text id="581">ÐÐŽÐŒÐžÐœÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ</Text>
+</Title>
+<Content>
+<Text id="582">Ð¡ÑÐµÐŽÑÑÐ²ÐŸ ÐŽÐ»Ñ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ Ð²ÐºÐ»ÑÑÐµÐœÐŸ Ð²ÐŸ Ð²ÑÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ Greenstone. Ð§ÑÐŸÐ±Ñ ÐŸÑÐºÑÑÑÑ ÑÑÐŸ ÑÑÐµÐŽÑÑÐ²ÐŸ, Ð¿ÑÐŸÑÑÐŸ ÐœÐ°Ð¶ÐŒÐžÑÐµ ÐœÐ° ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÑÑ ÑÑÑÐ»ÐºÑ ÐœÐ° ÑÑÐ°ÑÑÐŸÐ²ÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐµ.</Text>
+<Text id="583">ÐÐ°ÑÐ°Ð»ÑÐœÐ°Ñ ÑÑÑÐ°ÐœÐžÑÐ°, Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐ°Ñ ÐœÐ° Ð ÐžÑÑÐœÐºÐµ 17, ÐŽÐ°ÐµÑ ÐŸÐ±Ð·ÐŸÑ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÐžÐ· ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÐœÐ°Ñ
+ÐŸÐŽÑÑÐžÑ
+ÑÑ Ð² ÑÐžÑÑÐµÐŒÐµ. ÐÐ°ÐŒÐµÑÑÑÐµ, ÑÑÐŸ ÑÑÐŽÐ° Ð²ÐºÐ»ÑÑÐµÐœÑ Ð²ÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž â ÑÐ°Ðº ÐºÐ°Ðº ÐŒÐŸÐ³ÑÑ ÑÑÑÐµÑÑÐ²ÐŸÐ²Ð°ÑÑ "ÑÐ°ÑÑÐœÑÐµ", ÐºÐŸÑÐŸÑÑÐµ ÐœÐµ Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÑ ÐœÐ° ÑÑÐ°ÑÑÐŸÐ²ÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐµ Greenstone. ÐÐœÐž Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÑ Ð²ÐœÐµ Ð·Ð°Ð²ÐžÑÐžÐŒÐŸÑÑÐž ÐŸÑ ÑÐŸÐ³ÐŸ, ÐžÐŒÐµÑÑ Ð»Ðž ÐŸÐœÐž ÑÐŸÐºÑÐ°ÑÐµÐœÐœÐŸÐµ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐžÐ»Ðž Ð¿ÐŸÐ»ÐœÐŸÐµ, ÐŸÐ³ÑÐ°ÐœÐžÑÐµÐœÑ Ð»Ðž Ð² ÐŽÐŸÑÑÑÐ¿Ðµ, Ð² ÑÐ°Ð±ÐŸÑÐµÐŒ ÑÐŸÑÑÐŸÑÐœÐžÐž ÐžÐ»Ðž ÐœÐµÑ. ÐÑÐžÐœÐ°Ð¶Ð°ÑÐžÐž ÐœÐ° ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÑÑ Ð°Ð±Ð±ÑÐµÐ²ÐžÐ°ÑÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (Ð¿ÐµÑÐ²Ð°Ñ ÐºÐŸÐ»ÐŸÐœÐºÐ° ÑÑÑÐ»ÐŸÐº ÐœÐ° ÑÐžÑÑÐœÐºÐµ 17) Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Ð²ÑÐ²ÐŸÐŽÐžÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð¿ÐŸÐ»ÑÑÐµÐœÐœÑÑ ÐžÐ· ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ³ÐŸ ÑÐ°Ð¹Ð»Ð° Ðž ÐžÐ· ÐŽÑÑÐ³ÐžÑ
+ Ð²ÐœÑÑÑÐµÐœÐœÐžÑ
+ ÑÑÑÑÐºÑÑÑ ÑÐŸÐ·ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐ»Ñ ÑÑÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÑÐ»Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ ÑÐ²Ð»ÑÐµÑÑÑ ÐŸÐ±ÑÐµÐŽÐŸÑÑÑÐ¿ÐœÐŸÐ¹ Ðž ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² ÑÐ°Ð±ÐŸÑÐµÐŒ ÑÐŸÑÑÐŸÑÐœÐžÐž, ÐœÐ°Ð¶Ð°ÑÐžÐµ ÐœÐ° Ð¿ÐŸÐ»ÐœÐŸÐµ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (Ð²ÑÐŸÑÐ°Ñ ÑÑÑÐ»ÐºÐ°) Ð¿ÑÐžÐ²ÐµÐŽÐµÑ Ð²Ð°Ñ Ðº ÑÐ°ÐŒÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="584">ÐÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐºÐŸÑÐŸÑÑÑ ÐŒÑ Ð¿ÐŸÑÑÑÐŸÐžÐ»Ðž Ð² ÑÐ°Ð·ÐŽÐµÐ»Ðµ 3.2-3.6, ÐŒÑ ÐœÐ°Ð·Ð²Ð°Ð»Ðž wohiex, ÐžÐ· ÐŸÑÑÑÐ²ÐºÐ° Women's History Excerpt, Ðž ÐŸÐœÐ° Ð²ÐžÐŽÐœÐ° Ð²ÐœÐžÐ·Ñ Ð ÐžÑÑÐœÐºÐ° 17. ÐÐ° Ð ÐžÑÑÐœÐºÐµ 18 ÐžÐ·ÐŸÐ±ÑÐ°Ð¶ÐµÐœÐ° ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ, ÐºÐŸÑÐŸÑÐ°Ñ Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ Ð¿ÑÐž ÐœÐ°Ð¶Ð°ÑÐžÐž ÐœÐ° ÑÑÑ ÑÑÑÐ»ÐºÑ. Ð Ð¿ÐµÑÐ²ÐŸÐ¹ ÑÐ°ÑÑÐž ÐµÑÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ Ðž ÑÐ°Ð·ÐŒÐµÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž (ÐŸÐºÐŸÐ»ÐŸ 1000 ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÐŸÐºÐŸÐ»ÐŸ 1 ÐŒÐžÐ»Ð»ÐžÐŸÐœÐ° ÑÐ»ÐŸÐ² ÑÐ°Ð·ÐŒÐµÑÐŸÐŒ Ð² 6 mb). Ð¡Ð»ÐµÐŽÑÑÑÐ°Ñ ÑÐ°ÑÑÑ ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ð²ÐœÑÑÑÐµÐœÐœÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ, ÐŸÑÐœÐŸÑÑÑÑÑÑÑ Ðº Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ñ ÑÐ²ÑÐ·Ðž, ÑÐµÑÐµÐ· ÐºÐŸÑÐŸÑÑÐ¹ ÐŸÑÐºÑÑÐ²Ð°ÐµÑÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ. Ð Ð¿ÑÐžÐŒÐµÑÑ, ÐŸÐ¿ÑÐžÐž ÑÐžÐ»ÑÑÑÐ°ÑÐžÐž (filter options) ÐŽÐ»Ñ ÑÐžÐ»ÑÑÑÐ° Ð·Ð°Ð¿ÑÐŸÑÐ° (query filter) Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÐŸÐ¿ÑÐžÐž Ðž Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÐµ ÑÑÐ»ÐŸÐ²ÐžÑ, ÐºÐŸÑÐŸÑÑÐµ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÑ Ð¿ÑÐž Ð¿ÐŸÑÑÐ°ÐœÐŸÐ²ÐºÐµ Ð·Ð°Ð¿ÑÐŸÑÐ° Ð² Ð¿ÑÐŸÑÐµÑÑÐµ Ð¿ÐŸÐžÑÐºÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+<Text id="585">ÐÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ ÑÐ°ÐºÐ¶Ðµ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÐµÑ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸÐ± ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž Ðž Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐµÐµ ÐŒÐŸÐŽÐžÑÐžÑÐžÑÐŸÐ²Ð°ÑÑ. ÐÐœÐ° Ð¿ÐŸÐŒÐŸÐ³Ð°ÐµÑ Ð°ÐœÐ°Ð»ÐžÐ·ÐžÐ·ÐžÑÐŸÐ²Ð°ÑÑ ÑÐ°Ð¹Ð»Ñ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐžÐž (logs), ÐŽÐ°Ð²ÑÐžÐµ Ð²ÐœÑÑÑÐµÐœÐœÐžÐ¹ ÑÐ±ÐŸÐ¹, Ðž Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÑÐºÐžÐµ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐžÐŸÐœÐœÑÐµ ÑÐ°Ð¹Ð»Ñ (user logs), ÐºÐŸÑÐŸÑÑÐµ Ð·Ð°Ð¿ÐžÑÑÐ²Ð°ÑÑ Ð²ÑÐµ ÐŸÐ¿ÐµÑÐ°ÑÐžÐž, ÑÐŸÐ²ÐµÑÑÐ°ÐµÐŒÑÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÐŒÐž. ÐÐœÐ° ÑÐ°ÐºÐ¶Ðµ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÐŸÑÐŽÐµÐ»ÑÐœÐŸÐŒÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ (ÐžÐ»Ðž Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÐŒ) Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÑÑ ÐŽÐŸÑÑÑÐ¿ ÐŽÑÑÐ³ÐžÐŒ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ðž ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑÑ ÐœÐŸÐ²ÑÐ¹ ÐŒÐ°ÑÐµÑÐžÐ°Ð» Ðº Ð³ÐŸÑÐŸÐ²ÑÐŒ ÐŒÐ°ÑÐµÑÐžÐ°Ð»Ð°ÐŒ. ÐÑÐµ ÑÑÐž ÑÑÐµÐŽÑÑÐ²Ð° ÐŽÐŸÑÑÑÐ¿ÐœÑ ÐžÐ· ÐŒÐµÐœÑ Ð² Ð»ÐµÐ²ÐŸÐ¹ ÑÐ°ÑÑÐž Ð ÐžÑÑÐœÐºÐ° 5. </Text>
+<Figure id="greenstone_administration_facility">
+<Title>
+<Text id="586">Ð¡ÑÐµÐŽÑÑÐ²Ð° Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ Greenstone</Text>
+</Title>
+<File width="335" height="699" url="images/User_Fig_17.png"/>
+</Figure>
+<Figure id="information_about_the_women's_history_excerpt_collection">
+<Title>
+<Text id="587">ÐÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Women's History Excerpt</Text>
+</Title>
+<File width="331" height="699" url="images/User_Fig_18a.png"/>
+<File width="331" height="699" url="images/User_Fig_18b.png"/>
+</Figure>
+<Section id="configuration_files">
+<Title>
+<Text id="588">ÐÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐµ ÑÐ°Ð¹Ð»Ñ</Text>
+</Title>
+<Content>
+<Text id="589">Ð¡ÑÑÐµÑÑÐ²ÑÐµÑ ÐŽÐ²Ð° ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÑ
+ ÑÐ°Ð¹Ð»Ð°, ÐºÐŸÑÐŸÑÑÐµ ÐŸÑÐ²ÐµÑÐ°ÑÑ Ð·Ð° ÑÐ°Ð±ÐŸÑÐµÐµ ÑÐŸÑÑÐŸÑÐœÐžÐµ Greenstone: ÑÐ°Ð¹Ð» ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐž ÐŒÐµÑÑÐŸÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÑ (site configuration) gsdlsite.cfg Ðž Ð³Ð»Ð°Ð²ÐœÑÐ¹ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» main.cfg.</Text>
+<Text id="590">ÐÐŸÐœÑÐžÐ³-ÑÐ°Ð¹Ð» gsdlsite.cfg ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž ÐŒÐµÑÑÐŸÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÑ, ÐºÑÐŽÐ° Ð±ÑÐŽÐµÑ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ°. ÐÐœ ÑÐ¿ÑÐŸÐµÐºÑÐžÑÐŸÐ²Ð°Ðœ ÑÐ°ÐºÐžÐŒ ÐŸÐ±ÑÐ°Ð·ÐŸÐŒ, ÑÑÐŸÐ±Ñ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐµ ÐŸÐ¿ÑÐžÐž ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐŸÐ²Ð°Ð»Ðž ÑÐŸÐ»ÑÐºÐŸ ÑÑÐŸÐŒÑ ÐŒÐµÑÑÐŸÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÑ. Ð Ð¿ÑÐžÐŒÐµÑÑ, ÑÑÐŸ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž, ÐºÑÐŽÐ° ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐ° Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ°, HTTP-Ð°ÐŽÑÐµÑ ÑÐžÑÑÐµÐŒÑ Greenstone, Ðž ÐœÐ°Ð»ÐžÑÐžÐµ Ð² ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž ÑÑÐµÐŽÑÑÐ²Ð° fastcgi. ÐÐŸÐœÑÑÐžÑ, ÑÐ¿ÐŸÐŒÑÐœÑÑÑÐµ Ð² ÑÑÐŸÐŒ Ð¿Ð°ÑÐ°Ð³ÑÐ°ÑÐµ, Ð±ÐŸÐ»ÐµÐµ ÐŽÐµÑÐ°Ð»ÑÐœÐŸ ÑÐ°Ð·ÐŸÐ±ÑÐ°ÐœÑ Ð² Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²Ðµ Ð¿ÐŸ Ð£ÑÑÐ°ÐœÐŸÐ²ÐºÐµ.</Text>
+<Text id="591">Ð ÑÐ°Ð¹Ð»Ðµ Main.cfg ÑÐŸÐŽÐµÑÐ¶ÐžÑÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ, ÐºÐŸÑÐŸÑÐ°Ñ Ð¿ÑÐžÑÑÑÐ° Ð²ÑÐµÐŒ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°ÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÑÐŸÐ·ÐŽÐ°ÐœÐœÑÑ
+ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ Greenstone. ÐÐœ Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð² ÑÐµÐ±Ñ Ð°ÐŽÑÐµÑ E-mail ÑÐžÑÑÐµÐŒÐœÐŸÐ³ÐŸ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐžÑÑÐ°, ÑÐ°ÐºÐžÐµ ÐŸÐ¿ÑÐžÐž, ÐºÐŸÑÐŸÑÑÐµ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÑÑ, Ð²ÐºÐ»ÑÑÐµÐœÑ Ð»Ðž ÑÑÐ°ÑÑÑÐœÑÐµ Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐŸÑÐœÑÐµ ÑÑÑÐ°ÐœÐžÑÑ, ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÑ Ð»Ðž ÑÐµÐ³ÐžÑÑÑÐ°ÑÐžÐŸÐœÐœÑÐµ ÑÐ°Ð¹Ð»Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹, Ðž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ Ð»Ðž ÐÐœÑÐµÑÐœÐµÑ-cookies ÐŽÐ»Ñ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐž Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹.</Text>
+</Content>
+</Section>
+<Section id="logs">
+<Title>
+<Text id="592">Ð€Ð°Ð¹Ð»Ñ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐžÐž</Text>
+</Title>
+<Content>
+<Text id="593">Ð¡ÑÑÐµÑÑÐ²ÑÐµÑ ÑÑÐž Ð²ÐžÐŽÐ° ÑÐ°Ð¹Ð»ÐŸÐ² ÑÐµÐ³ÐžÑÑÑÐ°ÑÐžÐž, Ñ ÐºÐŸÑÐŸÑÑÐŒÐž Ð²Ñ ÑÑÐ°Ð»ÐºÐœÐµÑÐµÑÑ Ð² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐµ: Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÑÐºÐžÐµ Ð»ÐŸÐ³Ðž, Ð»ÐŸÐ³Ðž ÐŸÑÐžÐ±ÐŸÐº Ðž ÐžÐœÐžÑÐžÐ°Ð»ÐžÐ·Ð°ÑÐžÐž. ÐÐŸÑÐ»ÐµÐŽÐœÐžÐµ ÐŽÐ²Ð° ÐœÐ°Ð²ÐµÑÐœÑÐºÐ° Ð±ÑÐŽÑÑ Ð¿ÐŸÐ»ÐµÐ·ÐœÑ ÑÐŸÐ»ÑÐºÐŸ ÐŽÐ»Ñ Ð»ÑÐŽÐµÐ¹, Ð·Ð°ÐœÐžÐŒÐ°ÑÑÐžÑ
+ÑÑ ÑÐµÑ
+ÐœÐžÑÐµÑÐºÐžÐŒ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµÐŒ ÑÑÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ.</Text>
+<Text id="594">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ Greenstone ÐŒÐŸÐ¶ÐµÑ ÑÐŸÑ
+ÑÐ°ÐœÑÑÑ Ðž Ð·Ð°Ð¿ÐžÑÑÐ²Ð°ÑÑ Ð²ÑÐµ ÐŸÐ¿ÐµÑÐ°ÑÐžÐž, ÑÐŸÐ²ÐµÑÑÐ°ÐµÐŒÑÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐŒ ÐœÐ° ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÑÑÑÐ°ÐœÐžÑÐµ, ÐºÐŸÑÐŸÑÑÑ ÐŸÐœ Ð¿ÐŸÑÐµÑÐžÐ», Ð±ÐµÐ· ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÑ ÐœÐžÐºÐ°ÐºÐžÑ
+ Ð»ÐžÑÐœÑÑ
+. Ð ÐµÐ³ÐžÑÑÑÐ°ÑÐžÐŸÐœÐœÑÐµ ÑÐ°Ð¹Ð»Ñ, Ð¿ÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ Ð²ÑÐºÐ»ÑÑÐµÐœÐœÑÐµ, ÐŒÐŸÐ¶ÐœÐŸ Ð°ÐºÑÐžÐ²ÐžÑÐŸÐ²Ð°ÑÑ, ÐŽÐŸÐ±Ð°Ð²ÐžÐ² ÑÐ»ÐµÐŽÑÑÑÑÑ ÑÑÑÐŸÐºÑ Ð² Ð³Ð»Ð°Ð²ÐœÐŸÐŒ ÑÐžÑÑÐµÐŒÐœÐŸÐŒ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ:</Text>
+<CodeLine>logcgiargs true</CodeLine>
+<CodeLine>usecookies true</CodeLine>
+<Text id="595">ÐÐŸ ÑÐŒÐŸÐ»ÑÐ°ÐœÐžÑ ÐŸÐœÐž Ð²ÑÐºÐ»ÑÑÐµÐœÑ Ðž Ð¿ÐŸÑÑÐŸÐŒÑ ÐœÐµ Ð¿ÑÐŸÐžÑÑ
+ÐŸÐŽÐžÑ ÐœÐžÐºÐ°ÐºÐŸÐ¹ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐžÐž ÐŽÐŸ ÐžÑ
+ Ð²ÐºÐ»ÑÑÐµÐœÐžÑ. Ð¡ÑÑÐŸÐºÐ° logcgiargs Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ðž Ð²ÑÐºÐ»ÑÑÐ°ÐµÑ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐžÑ. ÐÐºÑÐžÐ²ÐžÑÐŸÐ²Ð°Ð² usecookies, ÐºÐ°Ð¶ÐŽÐŸÐŒÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð¿ÑÐžÑÐ²Ð°ÐžÐ²Ð°ÐµÑÑÑ ÐŸÑÐŸÐ±ÑÐ¹ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÐºÐŸÐŽ, ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð¿ÑÐŸÑÐ»ÐµÐŽÐžÑÑ Ð·Ð° ÐŽÐµÐ¹ÑÑÐ²ÐžÑÐŒÐž ÐŸÑÐŽÐµÐ»ÑÐœÐŸÐ³ÐŸ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÑÐµÑÐµÐ· ÑÐµÐ³ÐžÑÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð».</Text>
+<Text id="596">ÐÐ°Ð¶ÐŽÐ°Ñ ÑÑÑÐŸÐºÐ° Ð² Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÑÐºÐŸÐŒ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ Ð·Ð°Ð¿ÐžÑÑÐ²Ð°ÐµÑ Ð¿ÐŸÑÐµÑÐµÐœÐœÑÑ, ÑÑÑÐ°ÐœÐžÑÑ. ÐÐœ ÑÐŸÐŽÐµÑÐ¶ÐžÑ (a) IP Ð°ÐŽÑÐµÑ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐ° Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ, (Ðª) Ð²ÑÐµÐŒÑ Ð¿ÑÐŸÐ²ÐµÐŽÐµÐœÐœÐŸÐµ ÑÐ°ÐŒ, (Ñ) Ð°ÑÐ³ÑÐŒÐµÐœÑÑ CGI Ð² ÑÐºÐŸÐ±ÐºÐ°Ñ
+ Ðž (d) ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ Ð±ÑÐ°ÑÐ·ÐµÑÐ° Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ (ÐœÐ°Ð¿ÑÐžÐŒÐµÑ Netscape ÐœÐ°Ð·ÑÐ²Ð°ÐµÑÑÑ "Mozilla"). ÐÐžÐ¶Ðµ Ð¿ÑÐžÐ²ÐµÐŽÐµÐœÐ° ÐŽÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐ°Ñ Ð»ÐžÐœÐžÑ, ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐ°Ñ ÐºÐ°Ð¶ÐŽÑÐ¹ ÐžÐ· ÐŸÐ¿ÐžÑÐ°ÐœÑÑ
+ Ð¿ÐŸÐŽÐ¿ÑÐœÐºÑÐŸÐ²:</Text>
+<CodeLine>/fast-cgi-bin/niupepalibrary</CodeLine>
+<CodeLine>(a) its-www1.massey.ac.nz</CodeLine>
+<CodeLine>(b) [ Thu Dec07 23:47:00 NZDT2000]</CodeLine>
+<CodeLine>(c) (a=p, b=0, bcp=, beu=, c=niupepa, cc=, ccp=0, ccs=0, cl=, cm=, cq2=, d=, e=, er=, f=0, fc=1, gc=0, gg=text, gt=0, h=, h2=, hl=1, hp=, il=l, j=, j2=, k=1, ky=, l=en, m=50, n=, n2=, o=20, p=home, pw=, q=, q2=, r=1, s=0, sp=frameset, t=1, ua=, uan=, ug=, uma=listusers, umc=, umnpw1=, umnpw2=, umpw=, umug=, umun=, umus=, un=, us=invalid, v=0, w=w, x=0, z=130.123.128.4-950647871)</CodeLine>
+<CodeLine>(d) âMozilla/4.08 [en] (Win95; I ;Nav)â</CodeLine>
+<Text id="597">ÐÐŸÑÐ»ÐµÐŽÐœÐžÐ¹ CGI Ð°ÑÐ³ÑÐŒÐµÐœÑ "z" ÑÐ²Ð»ÑÐµÑÑÑ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÑÐŒ ÐºÐŸÐŽÐŸÐŒ ÐžÐ»Ðž "cookie", ÐŸÐ±ÑÐ°Ð·ÐŸÐ²Ð°ÐœÐœÑÐŒ Ð±ÑÐ°ÑÐ·ÐµÑÐŸÐŒ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ: ÐŸÐœ ÑÐŸÑÑÐŸÐžÑ ÐžÐ· IP-Ð°ÐŽÑÐµÑÐ° Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ, Ð¿ÐŸÑÐ»Ðµ ÑÐµÐ³ÐŸ ÐžÐŽÐµÑ ÑÐºÐ°Ð·Ð°ÐœÐžÐµ ÑÐŸÐ³ÐŸ Ð²ÑÐµÐŒÐµÐœÐž, ÐºÐŸÐ³ÐŽÐ° ÐŸÐœ Ð²Ð¿ÐµÑÐ²ÑÐµ Ð²ÐŸÑÐµÐ» Ð² Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÑ.</Text>
+<Text id="598">Ð ÐµÐ³ÐžÑÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» usage.txt Ð¿ÐŸÐŒÐµÑÐµÐœ Ð² ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ etc Ð² ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ¹ ÑÑÑÑÐºÑÑÑÐµ Greenstone (ÑÐŒ. Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ Ð Ð°Ð·ÑÐ°Ð±ÐŸÑÑÐžÐºÐ°). ÐÐŸÐ³ÐŽÐ° Ð²ÐºÐ»ÑÑÐµÐœÐ° ÑÐµÐ³ÐžÑÑÑÐ°ÑÐžÑ, ÐºÐ°Ð¶ÐŽÐŸÐµ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ Ð²ÑÐµÑ
+ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹ Ð·Ð°Ð¿ÐžÑÑÐ²Ð°ÐµÑÑÑ, ÐœÐŸ Ð² ÑÐµÐ³ÐžÑÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐŒ ÑÐ°Ð¹Ð»Ðµ Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÑ Ð»ÐžÑÑ Ð¿ÐŸÑÐ»ÐµÐŽÐœÐžÐµ 100 ÑÐµÐ³ÐžÑÑÑÐ°ÑÐžÐž Ð¿ÑÐž Ð¿ÐŸÐŒÐŸÑÐž ÑÐŸÐµÐŽÐžÐœÐµÐœÐžÑ usage link ÐœÐ° Ð ÐžÑÑÐœÐºÐµ 17.</Text>
+</Content>
+</Section>
+<Section id="user_management">
+<Title>
+<Text id="599">ÐÐŽÐŒÐžÐœÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹</Text>
+</Title>
+<Content>
+<Text id="600">Greenstone ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÑÑ
+ÐµÐŒÑ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐž, ÐºÐŸÑÐŸÑÑÑ ÐŒÐŸÐ¶ÐœÐŸ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐŽÐ»Ñ ÐŸÐ³ÑÐ°ÐœÐžÑÐµÐœÐžÑ Ðž ÐºÐŸÐœÑÑÐŸÐ»Ñ ÐŽÐŸÑÑÑÐ¿Ð°ÐŒ Ðº ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐŒ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑÐŒ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ. ÐÐ° ÐŽÐ°ÐœÐœÑÐ¹ ÐŒÐŸÐŒÐµÐœÑ ÐŸÐœ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÑÐŸÐ»ÑÐºÐŸ ÐŽÐ»Ñ ÐŸÐ³ÑÐ°ÐœÐžÑÐµÐœÐžÑ ÐŽÐŸÑÑÑÐ¿Ð° Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹ Ðº ÐÐŸÐ»Ð»ÐµÐºÑÐŸÑÑ Ðž ÐœÐµÐºÐŸÑÐŸÑÑÐŒ ÑÑÐœÐºÑÐžÑÐŒ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ. ÐÑÐ»Ðž ÐœÐµÐŸÐ±Ñ
+ÐŸÐŽÐžÐŒÐŸ ÐžÐŽÐµÐœÑÐžÑÐžÑÐžÑÐŸÐ²Ð°ÑÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð¿ÐµÑÐµÐŽ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÐµÐœÐžÐµÐŒ ÐµÐŒÑ ÐŽÐŸÑÑÑÐ¿Ð° Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒ, ÑÐŸ ÑÑÐŸ ÑÐ°ÐºÐ¶Ðµ ÐŸÑÑÑÐµÑÑÐ²ÐžÐŒÐŸ. Ð Ð¿ÑÐžÐŒÐµÑÑ, ÐŽÐŸÑÑÑÐ¿ Ðº ÐœÐµÐºÐŸÑÐŸÑÑÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐŸÑÑÑÐµÑÑÐ²Ð»ÐµÐœ ÑÐŸÐ»ÑÐºÐŸ Ð·Ð°ÑÐµÐ³ÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐŒÐž Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÐŒÐž Ð¿ÑÑÐµÐŒ Ð²Ð²ÐŸÐŽÐ° ÐÐ Ðž Ð¿Ð°ÑÐŸÐ»Ñ (Ñ
+ÐŸÑÑ ÑÑÐŸ Ð¿ÐŸÐºÐ° ÐœÐµ Ð¿ÑÐ°ÐºÑÐžÐºÑÐµÑÑÑ). Ð­ÑÐŸ Ð¿ÐŸÐºÐ°Ð·Ð°ÐœÐŸ ÐœÐ° Ð ÐžÑÑÐœÐºÐµ 16Ð°.</Text>
+<Text id="601">ÐÐ° ÑÑÑÐ°ÐœÐžÑÐµ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐŒÐŸÐ¶ÐœÐŸ Ð¿ÑÐŸÑÐŒÐŸÑÑÐµÑÑ ÑÐ¿ÐžÑÐŸÐº Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹, ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ ÐœÐŸÐ²ÑÑ
+ Ðž ÑÐŽÐ°Ð»ÐžÑÑ ÑÑÐ°ÑÑÑ
+. ÐÐŸÑÑÑÐ¿ Ðº ÑÑÐŸÐ¹ ÑÑÐœÐºÑÐžÐž ÐºÐŸÐœÐµÑÐœÐŸ Ð¶Ðµ ÐŸÐ³ÑÐ°ÐœÐžÑÐµÐœ: ÑÐŸÐ»ÑÐºÐŸ ÑÐ¿ÐŸÐ»ÐœÐŸÐŒÐŸÑÐµÐœÐœÑÐŒ Ð»ÐžÑÐ°ÐŒ ÑÐ°Ð·ÑÐµÑÐµÐœÐ° ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑÑ ÐœÐŸÐ²ÑÑ
+ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹. ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ðž ÐŒÐŸÐ³ÑÑ Ð¿ÑÐžÐœÐ°ÐŽÐ»ÐµÐ¶Ð°ÑÑ Ðº ÐœÐµÑÐºÐŸÐ»ÑÐºÐžÐŒ Ð³ÑÑÐ¿Ð¿Ð°ÐŒ. ÐÐ° ÐŽÐ°ÐœÐœÑÐ¹ ÐŒÐŸÐŒÐµÐœÑ ÑÑÑÐµÑÑÐ²ÑÐµÑ ÑÐŸÐ»ÑÐºÐŸ ÐŽÐ²Ðµ Ð³ÑÑÐ¿Ð¿Ñ "Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐ°ÑÐŸÑÑ" Ðž "colbuilder". Ð§Ð»ÐµÐœÑ Ð¿ÐµÑÐ²ÐŸÐ¹ Ð³ÑÑÐ¿Ð¿Ñ ÐŒÐŸÐ³ÑÑ ÐŽÐŸÐ±Ð°Ð²Ð»ÑÑÑ Ðž ÑÐŽÐ°Ð»ÑÑÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÐµÐ¹ Ðž ÐžÐ·ÐŒÐµÐœÑÑÑ ÐžÑ
+ Ð³ÑÑÐ¿Ð¿Ñ. Ð§Ð»ÐµÐœÑ Ð²ÑÐŸÑÐŸÐ¹ Ð³ÑÑÐ¿Ð¿Ñ ÐžÐŒÐµÑÑ ÐŽÐŸÑÑÑÐ¿ Ðº Ð²ÑÑÐµÐŸÐ¿ÐžÑÐ°ÐœÐœÑÐŒ ÑÑÐµÐŽÑÑÐ²Ð°ÐŒ ÐŽÐ»Ñ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐœÐŸÐ²ÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ðž ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ (ÑÐŽÐ°Ð»ÐµÐœÐžÑ) ÑÑÑÐµÑÑÐ²ÑÑÑÐžÑ
+.</Text>
+<Text id="602">ÐÐŸÑÐ»Ðµ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Ð¿ÐŸÑÐ²Ð»ÑÐµÑÑÑ ÐŸÐŽÐžÐœ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ admin, ÐºÐŸÑÐŸÑÑÐ¹ Ð¿ÑÐžÐœÐ°ÐŽÐ»ÐµÐ¶ÐžÑ ÐŸÐ±ÐµÐžÐŒ Ð³ÑÑÐ¿Ð¿Ð°ÐŒ. ÐÐ°ÑÐŸÐ»Ñ ÑÑÐŸÐ³ÐŸ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ Ð²Ð²ÐŸÐŽÐžÑÑÑ ÐµÑÐµ Ð² Ð¿ÑÐŸÑÐµÑÑÐµ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž. Ð­ÑÐŸÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐŒÐŸÐ¶ÐµÑ ÑÐŸÐ·ÐŽÐ°Ð²Ð°ÑÑ ÐžÐŒÐµÐœÐ° Ðž Ð¿Ð°ÑÐŸÐ»Ðž ÐŽÐ»Ñ Ð»ÑÐŽÐµÐ¹,Ð¿ÑÐžÐœÐ°ÐŽÐ»ÐµÐ¶Ð°ÑÐžÑ
+ Ðº Ð³ÑÑÐ¿Ð¿Ðµ colbuilder. ÐÐŒÐµÐœÐœÐŸ ÑÐ°ÐºÐŸÐ¹ ÐŒÐµÑÐŸÐŽ ÑÐµÐºÐŸÐŒÐµÐœÐŽÑÐµÑÑÑ ÐŽÐ»Ñ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐŽÐŸÑÑÑÐ¿Ð° ÐŽÑÑÐ³ÐžÐŒ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÐŒ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹. ÐÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ðµ Ð·Ð°Ð¿ÐžÑÑÐ²Ð°ÐµÑÑÑ Ð² ÐŽÐ²Ðµ Ð±Ð°Ð·Ñ ÐŽÐ°ÐœÐœÑÑ
+, ÐºÐŸÑÐŸÑÑÐµ ÐœÐ°Ñ
+ÐŸÐŽÑÑÑÑ Ð² ÑÐ°Ð¹Ð»ÐŸÐ²ÐŸÐ¹ ÑÑÑÑÐºÑÑÑÐµ Greenstone (ÑÐŒ. Ð ÑÐºÐŸÐ²ÐŸÐŽÑÑÐ²ÐŸ Ð Ð°Ð·ÑÐŸÐ±ÐŸÑÑÐžÐºÐ°).</Text>
+</Content>
+</Section>
+<Section id="technical_information">
+<Title>
+<Text id="603">Ð¢ÐµÑ
+ÐœÐžÑÐµÑÐºÐ°Ñ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ</Text>
+</Title>
+<Content>
+<Text id="604">Ð¡ÑÑÐ»ÐºÐž Ð¿ÐŸÐŽ Ð·Ð°Ð³ÐŸÐ»ÐŸÐ²ÐºÐŸÐŒ <i>Technical information</i> Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÑÑ ÐŽÐ°Ð»ÑÐœÐµÐ¹ÑÑÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ Ð¿ÑÐŸÑÐµÑÑÐµ ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž. Ð¡ÑÑÐ»ÐºÐ° <i>general</i> ÐŽÐ°ÐµÑ ÐŽÐŸÑÑÑÐ¿ Ðº ÑÐµÑ
+ÐœÐžÑÐµÑÐºÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž, Ð²ÐºÐ»ÑÑÐ°Ñ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž, Ð² ÐºÐŸÑÐŸÑÑÑ
+ Ð²ÑÐµ ÑÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœÐŸ. ÐÐµÐœÑ <i>protocol</i>, ÐŽÐ»Ñ Ð»ÑÐ±ÐŸÐ³ÐŸ Ð²ÐžÐŽÐ° Ð¿ÑÐŸÑÐŸÐºÐŸÐ»Ð°, ÐŽÐ°ÐµÑ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ ÐŸ ÐºÐ°Ð¶ÐŽÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÐŒÐŸÐ¹ ÑÑÐžÐŒ Ð¿ÑÐŸÑÐŸÐºÐŸÐ»ÐŸÐŒ.</Text>
+<Text id="605">Ð ÐœÐ°ÐºÐŸÐœÐµÑ, Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÑÐºÐžÐ¹ ÐºÐŸÐŽ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ° (user interface code), ÐœÐ°Ð·ÑÐ²Ð°ÐµÐŒÑÐ¹ "receptionist", ("ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑ" ) ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÐŽÐµÐ¹ÑÑÐ²ÐžÑ ÐŽÐ»Ñ Ð¿ÐµÑÐµÐŽÐ°ÑÐž ÐœÐ°ÐŒÐµÑÐµÐœÐžÐ¹ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ. Ð­ÑÐž ÐŽÐµÐ¹ÑÑÐ²ÐžÑ ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑ Ð°ÑÐ³ÑÐŒÐµÐœÑÑ CGI, ÐœÐ°Ð·Ð²Ð°ÐœÐœÑÐŒ Ð°. ÐÐ°Ð¿ÑÐžÐŒÐµÑ, ÐµÑÐ»Ðž a=status, ÑÐŸ ÑÐµÐ³ÐžÑÑÑÐ°ÑÐŸÑ Ð°ÐºÑÐžÐ²ÐžÐ·ÐžÑÑÐµÑ ÐŽÐµÐ¹ÑÑÐ²ÐžÐµ status, ÐºÐŸÑÐŸÑÐ°Ñ Ð¿ÐŸÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÑÑÐ°ÑÑÑÐœÑÑ ÑÑÑÐ°ÐœÐžÑÑ. Ð­Ð»ÐµÐŒÐµÐœÑ ÐŒÐµÐœÑ ÐŽÐ°ÐµÑ ÐŽÐŸÑÑÑÐ¿ Ðº Ð¿ÐµÑÐµÑÐœÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐµÐ¹, Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÐŒÑÑ
+ ÑÐžÑÑÐµÐŒÐŸÐ¹, Ð° ÐŽÑÑÐ³ÐŸÐ¹ Ð²ÐµÐŽÐµÑ Ðº Ð°ÑÐ³ÑÐŒÐµÐœÑÐ°ÐŒ, Ðº ÐºÐŸÑÐŸÑÑÐŒ Ð¿ÑÐžÐ±ÐµÐ³Ð°ÑÑ ÑÑÐž ÐŽÐµÐ¹ÑÑÐ²ÐžÑ.</Text>
+</Content>
+</Section>
+</Content>
+</Chapter>
+<Chapter id="appendix_a_software_features">
+<Title>
+<Text id="606">ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ Ð ÐÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ</Text>
+</Title>
+<Content>
+<Table class="hidden" id="table_appendixa">
+<Title/>
+<TableContent>
+<tr>
+<th width="132">
+<Text id="607">ÐŽÐŸÑÑÑÐ¿ÐœÑÐ¹ ÑÐµÑÐµÐ· Ð²ÐµÐ± Ð±ÑÐ°ÑÐ·ÐµÑ</Text>
+</th>
+<th width="397">
+<Text id="608">ÐÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŸÑÐºÑÑÐ²Ð°ÑÑÑÑ Ð² ÐŸÐºÐœÐµ ÑÑÐ°ÐœÐŽÐ°ÑÑÐœÐŸÐ³ÐŸ Ð²ÐµÐ±-Ð±ÑÐ°ÑÐ·ÐµÑÐ° (Netscape ÐžÐ»Ðž Internet Explorer) Ðž ÑÐŸÐ²ÐŒÐµÑÐ°ÑÑ Ð»ÐµÐ³ÐºÐŸÑÑÑ Ð² ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž Ñ ÐŒÐœÐŸÐ³ÐŸÑÑÐŸÑÐŸÐœÐœÐžÐŒÐž Ð¿ÐŸÐžÑÐºÐŸÐ²ÑÐŒÐž Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑÐŒÐž</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="609">ÐÐŸÐ»ÐœÐŸ-ÑÐµÐºÑÑÐŸÐ²ÐŸÐ¹ Ðž ÑÐ°Ð·ÐŽÐµÐ»ÑÐœÑÐ¹ Ð¿ÐŸÐžÑÐºÐž</Text>
+</th>
+<th width="397">
+<Text id="610">ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐŒÐŸÐ¶ÐµÑ ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÑÑ Ð¿ÐŸÐžÑÐº Ð¿ÐŸ Ð²ÑÐµÐŒÑ ÑÐµÐºÑÑÑ ÐžÐ»Ðž Ð¿ÐŸ ÐžÐœÐŽÐµÐºÑÐ°ÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÑÐ°Ð·ÐŽÐµÐ»ÐŸÐ², ÐžÐœÐŽÐµÐºÑÐ°ÐŒ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐ¹, Ð°Ð²ÑÐŸÑÐŸÐ², Ð² ÐºÐ°Ð¶ÐŽÐŸÐŒ ÐžÐ· ÐºÐŸÑÐŸÑÑÑ
+ ÐŒÐŸÐ¶ÐœÐŸ ÐžÑÐºÐ°ÑÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐµ ÑÐ»ÐŸÐ²Ð° ÐžÐ»Ðž ÑÑÐ°Ð·Ñ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="611">Ð³ÐžÐ±ÐºÐžÐµ ÑÑÐµÐŽÑÑÐ²Ð° Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°</Text>
+</th>
+<th width="397">
+<Text id="612">ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»Ñ ÐŒÐŸÐ¶ÐµÑ Ð¿ÑÐŸÑÐŒÐ°ÑÑÐžÐ²Ð°ÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÐŸ ÑÐ°ÐºÐžÐŒ ÐžÐœÐŽÐµÐºÑÐ°ÐŒ, ÐºÐ°Ðº Ð°Ð²ÑÐŸÑ, ÑÐºÐ°Ð·Ð°ÑÐµÐ»Ðž, ÐŽÐ°ÑÐ° Ðž Ñ.ÐŽ. ÐÐ°Ð¶ÐŽÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð¿ÑÐµÐŽÐ»Ð°Ð³Ð°ÐµÑ ÑÐ²ÐŸÐž ÑÑÑÑÐŸÐ¹ÑÑÐ²Ð° ÐŽÐ»Ñ ÐŸÑÑÑÐµÑÑÐ²Ð»ÐµÐœÐžÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° Ðž ÐŽÐ°Ð¶Ðµ Ð²ÐœÑÑÑÐž ÑÐ°ÐŒÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÑÑÐµÑÑÐ²ÑÐµÑ Ð±ÐŸÐ»ÑÑÐŸÐµ ÐºÐŸÐ»ÐžÑÐµÑÑÐ²ÐŸ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐŸÐ² ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°. ÐÐœÑÐµÑÑÐµÐ¹ÑÑ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° Ðž Ð¿ÐŸÐžÑÐºÐ° ÑÐŸÐ·ÐŽÐ°ÑÑÑÑ Ð²ÐŸ Ð²ÑÐµÐŒÑ Ð¿ÑÐŸÑÐµÑÑÐ° Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ Ð² ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÐžÐž Ñ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐµÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="613">Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÑÐµÐºÐž ÑÐŸÐ·ÐŽÐ°ÐµÑ ÑÑÑÑÐºÑÑÑÑ ÐŽÐŸÑÑÑÐ¿Ð°</Text>
+</th>
+<th width="397">
+<Text id="614">ÐÐœÑÐŸÑÐŒÐ°ÑÐžÐŸÐœÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, ÑÐŸÐ·ÐŽÐ°ÐœÐœÑÐµ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ Greenstone, Ð»ÐµÐ³ÐºÐž Ð² ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž. ÐÑÐµ Ð¿ÐŸÐžÑÐºÐŸÐ²ÑÐµ ÑÑÑÑÐºÑÑÑÑ Ðž ÑÑÑÑÐºÑÑÑÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÑÐŸÐ·ÐŽÐ°ÑÑÑÑ Ð¿ÑÑÐŒÐŸ ÐžÐ· ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². ÐÑÐ»Ðž Ð¿ÐŸÑÐ²Ð»ÑÑÑÑÑ ÐœÐŸÐ²ÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÑÑ
+ÐŸÐ¶ÐµÐ³ÐŸ ÑÐŸÑÐŒÐ°ÑÐ°, ÑÐŸ ÐŸÐœÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž Ð¿ÑÐžÑÐŸÐµÐŽÐžÐœÐµÐœÑ Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž. ÐÐµÐºÐŸÑÐŸÑÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐ°Ðº Ðž ÐŽÐµÐ»Ð°ÑÑ. Ð§ÐµÑÐµÐ· ÐºÐ°ÐºÐŸÐ¹-ÑÐŸ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÐ¹ Ð¿ÑÐŸÐŒÐµÐ¶ÑÑÐŸÐº Ð²ÑÐµÐŒÐµÐœÐž ÐŸÐœÐž ÐœÐ°ÑÐžÐœÐ°ÑÑ Ð¿ÐŸÐžÑÐº ÐœÐŸÐ²ÐŸÐ³ÐŸ ÐŒÐ°ÑÐµÑÐžÐ°Ð»Ð° Ðž Ð¿ÐµÑÐµÑÑÑÐ°ÐžÐ²Ð°ÑÑ ÐžÐœÐŽÐµÐºÑÑ â Ð²ÑÐµ Ð±ÐµÐ· ÑÑÑÐœÐŸÐ³ÐŸ Ð²ÐŒÐµÑÐ°ÑÐµÐ»ÑÑÑÐ²Ð°.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="615">ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ ÐŽÐŸÑÑÑÐ¿ÐœÑÐµ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ</Text>
+</th>
+<th width="397">
+<Text id="616">ÐÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ - ÑÑÐŸ ÑÐ°ÐºÐ°Ñ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ, ÐºÐ°Ðº Ð°Ð²ÑÐŸÑ, ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ, ÐŽÐ°ÑÐ°, ÐºÐ»ÑÑÐµÐ²ÑÐµ ÑÐ»ÐŸÐ²Ð° Ðž Ñ.ÐŽ.. ÐÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÑÐ»ÑÐ¶Ð°Ñ ÐŸÑÐœÐŸÐ²ÐŸÐ¹ ÐŽÐ»Ñ ÐžÐœÐŽÐµÐºÑÐŸÐ² Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°. ÐÐœÐž ÐŽÐŸÐ»Ð¶ÐœÑ Ð±ÑÑÑ ÑÐºÐ°Ð·Ð°ÐœÑ Ð»ÐžÐ±ÐŸ Ð¿ÐŸÐ»ÑÑÐµÐœÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÐžÐ· ÐžÑÑ
+ÐŸÐŽÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². Ð¡Ñ
+ÐµÐŒÐ° Dublin Core metadata ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²Ð° ÑÐ»ÐµÐºÑÑÐŸÐœÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², Ñ
+ÐŸÑÑ ÐŒÐŸÐ¶ÐœÐŸ Ð¿ÑÐžÐŒÐµÐœÑÑÑ Ðž ÐŽÑÑÐ³ÐžÐµ ÑÑ
+ÐµÐŒÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="617">ÐÐŸÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ Ðº Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐµ ÑÐ°ÑÑÐžÑÑÑÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž ÑÐžÑÑÐµÐŒÑ</Text>
+</th>
+<th width="397">
+<Text id="618">ÐÐ»Ñ ÑÐŸÐ³ÐŸ, ÑÑÐŸÐ±Ñ ÑÐ°Ð±ÐŸÑÐ°ÑÑ ÑÐŸ Ð²ÑÐµÐ²ÐŸÐ·ÐŒÐŸÐ¶ÐœÑÐŒÐž Ð²ÐžÐŽÐ°ÐŒÐž ÐžÑÑ
+ÐŸÐŽÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÑÐ°ÑÑÐžÑÐžÑÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž Ð¿ÑÑÐµÐŒ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐµÐœÐžÐ¹ ÐŽÐ»Ñ ÐœÐŸÐ²ÑÑ
+ ÑÐŸÑÐŒÐ°ÑÐŸÐ² ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐµ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ ÐœÐ° ÐŽÐ°ÐœÐœÑÐ¹ ÐŒÐŸÐŒÐµÐœÑ ÑÑÑÐµÑÑÐ²ÑÑÑ ÐŽÐ»Ñ ÑÐ»ÐµÐŽÑÑÑÐžÑ
+ ÑÐŸÑÐŒÐ°ÑÐŸÐ²: ÑÐµÐºÑÑÐŸÐ²ÑÑ
+, HTML, Word, PDF, PostScript, E-mail. ÐÐŸÐ»Ð»ÐµÐºÑÐžÑ ÐŒÐŸÐ¶ÐµÑ ÐžÐŒÐµÑÑ ÐžÑÑ
+ÐŸÐŽÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÑÐ°Ð·ÐœÑÑ
+ ÑÐŸÑÐŒÐ°ÑÐŸÐ². ÐÐ»Ñ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐžÐœÐŽÐµÐºÑÐŸÐ² Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÐžÐ· ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÑÑ
+ÐµÐŒÐ° "Ñ1Ð°Ð·Ð·Ð1ÐµÐ³8"(ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ): ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ ÑÐŸÐ·ÐŽÐ°ÑÑ ÐžÐœÐŽÐµÐºÑÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° ÑÐ°Ð·ÐœÑÑ
+ Ð²ÐžÐŽÐŸÐ², ÐŸÑÐœÐŸÐ²Ð°ÐœÐœÑÑ
+ ÐœÐ° ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="619">Ð¡Ð¿ÑÐŸÐµÐºÑÐžÑÐŸÐ²Ð°Ðœ ÐŽÐ»Ñ ÐŒÑÐ»ÑÑÐžÐ³ÐžÐ³Ð°Ð±Ð°Ð¹ÑÐœÑÑ
+ (ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹)</Text>
+</th>
+<th width="397">
+<Text id="620">ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐŸÐ³ÑÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑ ÐŒÐžÐ»Ð»ÐžÐŸÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÑÐžÑÑÐµÐŒÑ Greenstone ÐŽÐ»Ñ ÑÐ°Ð±ÐŸÑÑ Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒÐž ÑÐ°Ð·ÐŒÐµÑÐŸÐŒ Ð² ÐœÐµÑÐºÐŸÐ»ÑÐºÐŸ Ð³ÐžÐ³Ð°Ð±Ð°Ð¹Ñ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="621">ÐÐŸÐºÑÐŒÐµÐœÑÑ ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐœÐ° Ð»ÑÐ±ÐŸÐŒ ÑÐ·ÑÐºÐµ</Text>
+</th>
+<th width="397">
+<Text id="622">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ Unicode, Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑ ÐžÑÐ¿ÑÐ°Ð²ÐœÐŸ ÑÐ°Ð±ÐŸÑÐ°ÑÑ ÐœÐ° Ð»ÑÐ±ÐŸÐŒ ÑÐ·ÑÐºÐµ. ÐÐ° ÑÑÐŸÑ ÐŒÐŸÐŒÐµÐœÑ ÑÐŸÐ·ÐŽÐ°ÐœÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐœÐ° Ð°ÑÐ°Ð±ÑÐºÐŸÐŒ, ÑÑÐ°ÐœÑÑÐ·ÐºÐŸÐŒ, ÐºÐžÑÐ°Ð¹ÑÐºÐŸÐŒ, Ð³ÐŸÐ»Ð»Ð°ÐœÐŽÑÐºÐŸÐŒ, Ð°ÐœÐ³Ð»ÐžÐ¹ÑÐºÐŸÐŒ, ÐžÑÐ¿Ð°ÐœÑÐºÐŸÐŒ, ÐŒÐ°Ð¹ÐŸÑÑÐºÐŸÐŒ ÑÐ·ÑÐºÐ°Ñ
+. ÐÐµÑÐµÐ²ÐŸÐŽ ÐœÐ° Ð»ÐµÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ ÐŽÐ»Ñ Ð¿ÐµÑÐµÐ²ÐŸÐŽÐ° Unicode Ð² Ð°Ð»ÑÐ°Ð²ÐžÑÐœÑÑ ÑÐŸÑÐŒÑ, Ð¿ÐŸÐŽÐŽÐµÑÐ¶ÐžÐ²Ð°ÐµÐŒÑÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÑÐºÐžÐŒ Ð±ÑÐ°ÑÐ·ÐµÑÐŸÐŒ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="623">ÐÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÑÐºÐžÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ ÐŽÐŸÑÑÑÐ¿ÐµÐœ ÐœÐ° ÑÐ°Ð·ÐœÑÑ
+ ÑÐ·ÑÐºÐ°Ñ
+</Text>
+</th>
+<th width="397">
+<Text id="624">ÐÐœÑÐµÑÑÐµÐ¹Ñ ÐŽÐŸÑÑÑÐ¿ÐµÐœ ÐœÐ° ÑÐ°Ð·ÐœÑÑ
+ ÑÐ·ÑÐºÐ°Ñ
+. ÐÐ° ÐŽÐ°ÐœÐœÑÐ¹ ÐŒÐŸÐŒÐµÐœÑ ÐžÐœÑÐµÑÑÐµÐ¹Ñ ÐŽÐŸÑÑÑÐ¿ÐµÐœ ÐœÐ° ÑÐ»ÐµÐŽÑÑÑÐžÑ
+ ÑÐ·ÑÐºÐ°Ñ
+: Ð°ÑÐ°Ð±ÑÐºÐŸÐŒ, ÑÑÐ°ÐœÑÑÐ·ÐºÐŸÐŒ, ÐºÐžÑÐ°Ð¹ÑÐºÐŸÐŒ, Ð³ÐŸÐ»Ð»Ð°ÐœÐŽÑÐºÐŸÐŒ, Ð°ÐœÐ³Ð»ÐžÐ¹ÑÐºÐŸÐŒ, ÐžÑÐ¿Ð°ÐœÑÐºÐŸÐŒ, ÐŒÐ°Ð¹ÐŸÑÑÐºÐŸÐŒ, Ð¿ÐŸÑÑÑÐ³Ð°Ð»ÑÑÐºÐŸÐŒ. ÐÐŸÐ²ÑÐµ ÑÐ·ÑÐºÐž ÐŒÐŸÐ¶ÐœÐŸ Ð»ÐµÐ³ÐºÐŸ ÐŽÐŸÐ±Ð°Ð²ÐžÑÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="625">ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐŸÐ³ÑÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑ ÑÐµÐºÑÑ, ÑÐžÑÑÐœÐºÐž, Ð°ÑÐŽÐžÐŸ Ðž Ð²ÐžÐŽÐµÐŸ</Text>
+</th>
+<th width="397">
+<Text id="626">ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐŸÐ³ÑÑ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑ ÑÐµÐºÑÑ, ÑÐžÑÑÐœÐºÐž, Ð°ÑÐŽÐžÐŸ Ðž Ð²ÐžÐŽÐµÐŸ ÐºÐ»ÐžÐ¿Ñ. ÐÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ ÐœÐµÑÐµÐºÑÑÐŸÐ²ÐŸÐ³ÐŸ ÐŒÐ°ÑÐµÑÐžÐ°Ð»Ð° Ð»ÐžÐ±ÐŸ ÑÐŸÐµÐŽÐžÐœÐµÐœÐŸ Ñ ÑÐµÐºÑÑÐŸÐ²ÑÐŒ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐŒ ÑÑÑÐ»ÐºÐŸÐ¹, Ð»ÐžÐ±ÐŸ ÐœÐ° ÐžÑ
+ ÐŒÐµÑÑÐµ ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ ÑÐµÐºÑÑÐŸÐ²ÐŸÐµ ÐŸÐ¿ÐžÑÐ°ÐœÐžÐµ ÐžÐ»Ðž ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÑÐžÑÑÐœÐºÐ° ÐŽÐ»Ñ ÐŸÐ±Ð»ÐµÐ³ÑÐµÐœÐžÑ Ð¿ÐŸÐ»ÐœÐŸÑÐµÐºÑÑÐŸÐ²ÐŸÐ³ÐŸ Ð¿ÐŸÐžÑÐºÐ° Ðž Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°. ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð¿ÑÐžÐŒÐµÐœÑÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐµ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ Ðž ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ ÐŽÐ°Ð¶Ðµ ÐŽÐ»Ñ ÐœÐµÑÐµÐºÑÑÐŸÐ²ÑÑ
+ ÐŽÐ°ÐœÐœÑÑ
+.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="627">ÐÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑ Ð¿ÑÐŸÐŽÐ²ÐžÐœÑÑÑÐµ ÑÐµÑ
+ÐœÐŸÐ»ÐŸÐ³ÐžÐž ÑÐ¶Ð°ÑÐžÑ</Text>
+</th>
+<th width="397">
+<Text id="628">Ð¢ÐµÑ
+ÐœÐŸÐ»ÐŸÐ³ÐžÐž ÑÐ¶Ð°ÑÐžÑ Ð¿ÑÐžÐŒÐµÐœÑÑÑÑÑ ÐŽÐ»Ñ ÑÐŒÐµÐœÑÑÐµÐœÐžÑ ÑÐ°ÐŒÐµÑÐŸÐ² ÐžÐœÐŽÐµÐºÑÐŸÐ² Ðž ÑÐµÐºÑÑÐ°. Ð£ÐŒÐµÐœÑÑÐµÐœÐžÐµ ÑÐ°Ð·ÐŒÐµÑÐŸÐ² ÑÐµÐºÑÑÐ° Ðº ÑÐŸÐŒÑ Ð¶Ðµ ÑÐ²ÐµÐ»ÐžÑÐžÐ²Ð°ÐµÑ ÑÐºÐŸÑÐŸÑÑÑ ÐŸÐ±ÐœÐ°ÑÑÐ¶ÐµÐœÐžÑ Ðž ÐžÐ·Ð²Ð»ÐµÑÐµÐœÐžÑ ÑÐµÐºÑÑÐ°.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="629">ÐÐŸÑÑÑÐ¿ÐœÐ° ÑÑÐœÐºÑÐžÑ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ</Text>
+</th>
+<th width="397">
+<Text id="630">Ð€ÑÐœÐºÑÐžÑ Ð°ÐŽÐŒÐžÐœÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐœÐ°ÐŽÐµÐ»ÑÐµÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐœÑÑ
+ Ð»ÐžÑ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑÑ ÑÐ°Ð·ÑÐµÑÐ°ÑÑ ÐœÐŸÐ²ÑÐŒ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÐŒ ÑÑÑÐŸÐžÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž, Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÑÑÑ ÐœÐµÐºÐŸÑÐŸÑÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ ÑÐŸÐ»ÑÐºÐŸ Ð·Ð°ÑÐµÐ³ÐžÑÑÑÐžÑÐŸÐ²Ð°ÐœÐœÑÐŒ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÐŒ, Ð¿ÑÐŸÐ²ÐµÑÑÑÑ ÑÐŸÑÑÐ°Ð² Ð²ÑÐµÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ðž Ñ.ÐŽ.  Ð ÐµÐ³ÐžÑÑÑÐ°ÑÐžÐŸÐœÐœÑÐµ ÑÐ°Ð¹Ð»Ñ (logs) ÐŒÐŸÐ³ÑÑ Ð·Ð°Ð¿ÐžÑÑÐ²Ð°ÑÑ Ð²ÑÐµ Ð·Ð°Ð¿ÑÐŸÑÑ, ÑÐŽÐµÐ»Ð°ÐœÐœÑÐµ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÐŒÐž.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="631">ÐÑÑÑÑÐŸÐµ Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÐµ ÐœÐŸÐ²ÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹</Text>
+</th>
+<th width="397">
+<Text id="632">ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐµÐœÑ Ðž ÑÐŸÐ·ÐŽÐ°ÐœÑ Ð² Ð»ÑÐ±ÐŸÐµ Ð²ÑÐµÐŒÑ Ð±ÐµÐ· Ð¿ÐµÑÐµÐ³ÑÑÐ·ÐºÐž ÑÐžÑÑÐµÐŒÑ. ÐÑÐž Ð¿ÐŸÑÐ²Ð»ÐµÐœÐžÐž ÐœÐŸÐ²ÑÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐŸÐœÐž Ð¿ÐŸÑÐ²Ð»ÑÑÑÑÑ Ð² ÐžÐœÑÐµÑÑÐµÐ¹ÑÐµ Ð³Ð»Ð°Ð²ÐœÐŸÐ³ÐŸ ÐŒÐµÐœÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="633"><i>Collections can be published on the Internet or on CD-ROM</i></Text>
+</th>
+<th width="397">
+<Text id="634">The software can be used to serve collections over the World-Wide Web. Greenstone collections can be made available, in precisely the same form, on CD-ROM. The user interface is through a standard web browser (Netscape is provided on each disk), and the interaction is identical to accessing the collection on the webâexcept that response times are more predictable. The CD-ROMs run under all versions of the Windows operating system.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="635">ÐÐŸÐ»Ð»ÐµÐºÑÐžÐž ÐŒÐŸÐ³ÑÑ Ð±ÑÑÑ ÑÐ°ÑÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÑ ÑÑÐµÐŽÐž ÑÐ°Ð·ÐœÑÑ
+ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐŸÐ²</Text>
+</th>
+<th width="397">
+<Text id="636">ÐÐžÐ±ÐºÐ°Ñ ÑÑÑÑÐºÑÑÑÐ° Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ ÑÐ°Ð·ÐœÑÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐ°ÐŒ ÑÐ°Ð±ÐŸÑÐ°ÑÑ Ñ ÑÐ°Ð·ÐœÑÐŒÐž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒÐž, Ð² ÑÐŸ Ð¶Ðµ ÑÐ°ÐŒÐŸÐµ Ð²ÑÐµÐŒÑ Ð²ÑÑ
+ÐŸÐŽÑ ÐœÐ° ÑÐºÑÐ°Ðœ Ð² ÐŸÐŽÐœÐŸÐŒ ÑÐžÐ¿Ðµ, ÐœÐ° ÐŸÐŽÐœÐŸÐ¹ Ð²ÑÐ±-ÑÑÑÐ°ÐœÐžÑÐµ, ÐºÐ°Ðº ÑÐ°ÑÑÑ ÐŸÐŽÐœÐŸÐ¹ Ðž ÑÐŸÐ¹ Ð¶Ðµ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="637">Ð Ð°Ð±ÐŸÑÐ°ÐµÑ ÐºÐ°Ðº Ð² Unix, ÑÐ°Ðº Ðž Ð² Windows</Text>
+</th>
+<th width="397">
+<Text id="638">Greenstone ÑÐ°Ð±ÐŸÑÐ°ÐµÑ Ðž Ð² Windows (3.1/3.11,95/98/ME,NT/2000) Ðž Unix (Linux Ðž SunOS). ÐÑÐ±Ð°Ñ ÐžÐ· ÑÑÐžÑ
+ ÑÐžÑÑÐµÐŒ ÐŒÐŸÐ¶ÐµÑ Ð±ÑÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐ° Ð² ÐºÐ°ÑÐµÑÑÐ²Ðµ Ð²ÐµÐ±-ÑÐµÑÐ²ÐµÑÐ°. Ð¡ÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ ÐœÐµÐ²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸ ÐœÐ° ÑÑÑÐ°ÑÐµÐ²ÑÐžÑ
+ ÑÐžÑÑÐµÐŒÐ°Ñ
+ Windows 3.1/3.11, ÐœÐŸ ÐŸÐœÐž ÐŒÐŸÐ³ÑÑ ÑÑÐžÑÑÐ²Ð°ÑÑ Ð³ÐŸÑÐŸÐ²ÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž.</Text>
+</th>
+</tr>
+<tr>
+<th width="132">
+<Text id="639">Ð§ÑÐŸ Ð²Ñ Ð¿ÐŸÐ»ÑÑÐ°ÐµÑÐµ Ñ Greenstone</Text>
+</th>
+<th width="397">
+<Text id="640">Greenstone Digital Library ÑÐ²Ð»ÑÐµÑÑÑ ÐŸÐ±ÑÐµÐŽÐŸÑÑÑÐ¿ÐœÑÐŒ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐŒ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµÐŒ, ÐŽÐŸÑÑÑÐ¿ÐœÑÐŒ ÐœÐ° Ð²ÐµÐ±-ÑÐ°Ð¹ÑÐµ New Zealand Digital Library (nzdl.org), ÑÐŸÐŸÑÐ²ÐµÑÑÑÐ²ÑÑÑÐžÐŒ GNU General Public License. ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð² ÑÐµÐ±Ñ Ð²ÑÐµ, ÑÑÐŸ Ð±ÑÐ»ÐŸ ÐŸÐ¿ÐžÑÐ°ÐœÐŸ Ð²ÑÑÐµ: Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÑ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ CD, ÑÐŸÐ·ÐŽÐ°ÐœÐžÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÐŒÐœÐŸÐ³ÐŸÑÐ·ÑÐºÐŸÐ²ÑÐµ Ð²ÐŸÐ·ÐŒÐŸÐ¶ÐœÐŸÑÑÐž, ÐŽÐŸÐ¿ÐŸÐ»ÐœÐµÐœÐžÑ Ðº Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐµ Ðž ÐºÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑÑ ÐŽÐ»Ñ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÐžÑÑ
+ÐŸÐŽÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ². ÐÑÐž ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑÑÑ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž ÐºÐ°Ðº Ð² Windows, ÑÐ°Ðº Ðž Ð² Unix. Ð¢Ð°Ðº ÐºÐ°Ðº ÑÑÐ° Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÐŸÐ±ÑÐµÐŽÐŸÑÑÑÐ¿ÐœÐ°, ÐŒÑ Ð±ÑÐ»Ðž Ð±Ñ ÑÐ°ÐŽÑ Ð²Ð°ÑÐžÐŒ Ð¿ÑÐµÐŽÐ»ÐŸÐ¶ÐµÐœÐžÑÐŒ Ð¿ÐŸ ÐµÑ ÐžÐ·ÐŒÐµÐœÐµÐœÐžÑ Ðž ÑÐ»ÑÑÑÐµÐœÐžÑ.</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Chapter>
+<Chapter id="appendix_b_glossary_of_terms">
+<Title>
+<Text id="641">ÐÑÐžÐ»ÐŸÐ¶ÐµÐœÐžÐµ Ð ÐÐ»ÐŸÑÑÐ°ÑÐžÐ¹ Ð¿ÐŸÐœÑÑÐžÐ¹</Text>
+</Title>
+<Content>
+<Table id="table_appendixa" class="hidden">
+<Title/>
+<TableContent>
+<tr>
+<th width="123">
+<Text id="642"><b>ÐÐŸÐœÑÐžÐµ</b></Text>
+</th>
+<th width="406">
+<Text id="643"><b>ÐÐœÐ°ÑÐµÐœÐžÐµ</b></Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="644"><i>autoconf</i></Text>
+</th>
+<th width="406">
+<Text id="645">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Ð² Unix, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ ÐŽÐ»Ñ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž ÐžÐœÑÑÐ°Ð»Ð»ÑÑÐžÐŸÐœÐœÐŸÐ³ÐŸ Ð¿Ð°ÐºÐµÑÐ° Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Greenstone ÐŽÐ»Ñ ÑÐ°Ð±ÐŸÑÑ ÐœÐ° Ð²Ð°ÑÐµÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="646"><i>Autorun</i> ÐÐ²ÑÐŸÐ·Ð°Ð³ÑÑÐ·ÐºÐ°</Text>
+</th>
+<th width="406">
+<Text id="647">Ð­ÑÐŸ ÐŸÐŽÐœÐŸ ÐžÐ· ÑÑÐµÐŽÑÑÐ² Windows, ÐºÐŸÑÐŸÑÐŸÐµ Ð°Ð²ÑÐŸÐŒÐ°ÑÐžÑÐµÑÐºÐž Ð·Ð°Ð¿ÑÑÐºÐ°ÐµÑ Ð»ÑÐ±ÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Ð¿ÐŸÑÐ»Ðµ Ð²ÑÑÐ°Ð²ÐºÐž CD-ROM Ð² ÐŽÐžÑÐºÐŸÐ²ÐŸÐŽ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="648">Boolean query ÐÑÐ»ÐµÐ² Ð·Ð°Ð¿ÑÐŸÑ</Text>
+</th>
+<th width="406">
+<Text id="649">ÐÐ°Ð¿ÑÐŸÑ Ðº ÑÐžÑÑÐµÐŒÐµ Ð¿ÐŸÐžÑÐºÐ° ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž, ÐºÐŸÑÐŸÑÑÐ¹ ÐŒÐŸÐ¶ÐµÑ ÑÐŸÑÑÐŸÑÑÑ ÐžÐ· ÑÐŸÑÐ·ÐŸÐ² Ð, ÐÐÐ Ðž ÑÐ»ÐŸÐ²Ð° ÐÐÐ¢.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="650">Browsing ÐÑÐŸÑÐŒÐŸÑÑ, ÐŸÐ±Ð·ÐŸÑ</Text>
+</th>
+<th width="406">
+<Text id="651">ÐÐŸÑÑÑÐ¿ Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÑÑÐµÐŒ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° Ð¿ÐµÑÐµÑÐœÑ ÑÐ°Ð·Ð»ÐžÑÐœÑÑ
+ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ (Ð°Ð²ÑÐŸÑ, ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ, ÐŽÐ°ÑÐ°, ÐºÐ»ÑÑÐµÐ²ÑÐµ ÑÐ»ÐŸÐ²Ð°)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="652"><i>buildcol.pl</i></Text>
+</th>
+<th width="406">
+<Text id="653">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Greenstone, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ ÐŽÐ»Ñ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="654">Building ÐÐŸÑÑÑÐŸÐµÐœÐžÐµ</Text>
+</th>
+<th width="406">
+<Text id="655">ÐÑÐŸÑÐµÑÑ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐžÐœÐŽÐµÐºÑÐœÑÑ
+ ÑÑÑÑÐºÑÑÑ Ðž ÑÑÑÑÐºÑÑÑ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°, ÐºÐŸÑÐŸÑÑÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑÑÑ ÐŽÐ»Ñ ÐŽÐŸÑÑÑÐ¿Ð° Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑÐŒ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="656">C++</Text>
+</th>
+<th width="406">
+<Text id="657">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÑÐ¹ ÑÐ·ÑÐº, Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ ÐœÐ°Ð¿ÐžÑÐ°ÐœÐŸ Ð±ÐŸÐ»ÑÑÐžÐœÑÑÐ²ÐŸ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ Greenstone ÐÐ°Ð»ÑÐµ Ðž Ð±ÐŸÐ»ÑÑÐžÐµ ÑÐµÐ³ÐžÑÑÑÑ Ð²ÑÐ³Ð»ÑÐŽÑÑ ÐŸÐŽÐžÐœÐ°ÐºÐŸÐ²ÐŸ ÐŽÐ»Ñ ÑÐ¿ÑÐŸÑÐµÐœÐžÑ Ð¿ÐŸÐžÑÐºÐ°.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="658">Casefolding</Text>
+</th>
+<th width="406">
+<Text id="659">Making uppercase and lowercase words look the same, for searching purposes</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="660">CGI (Common Gateway Interface)</Text>
+</th>
+<th width="406">
+<Text id="661">Ð¡Ñ
+ÐµÐŒÐ°, ÐºÐŸÑÐŸÑÐ°Ñ Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÐµÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÐŒ ÑÐ°Ð±ÐŸÑÐ°ÑÑ Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ°ÐŒÐž ÐœÐ° Ð³Ð»Ð°Ð²ÐœÐŸÐŒ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐµ Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÑÐ°Ð±ÐŸÑÑ Ñ Ð²ÐµÐ±-ÑÑÑÐ°ÐœÐžÑÐ°ÐŒÐž.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="662">Ð¡ÐºÑÐžÐ¿Ñ CGI</Text>
+</th>
+<th width="406">
+<Text id="663">ÐÐŸÐŽ, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐ²ÑÐ·Ð°Ðœ Ñ ÐºÐœÐŸÐ¿ÐºÐŸÐ¹, ÐŒÐµÐœÑ ÐžÐ»Ðž ÑÑÑÐ»ÐºÐŸÐ¹ ÐœÐ° Ð²ÐµÐ±Â¬ÑÑÑÐ°ÐœÐžÑÐµ, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ, ÑÑÐŸ ÐŽÐŸÐ»Ð¶ÐµÐœ ÑÐŽÐµÐ»Ð°ÑÑ Ð³Ð»Ð°Ð²ÐœÑÐ¹ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑ Ð¿ÑÐž ÐœÐ°Ð¶Ð°ÑÐžÐž ÐœÐ° ÐœÐµÐµ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="664"><i>cgi-bin</i></Text>
+</th>
+<th width="406">
+<Text id="665">ÐÐžÑÐµÐºÑÐŸÑÐžÑ, Ð² ÐºÐŸÑÐŸÑÐŸÐ¹ ÑÐŸÑ
+ÑÐ°ÐœÐµÐœÑ ÑÐºÑÐžÐ¿ÑÑ CGI.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="666">Classifier ÐÐ»Ð°ÑÑÐžÑÐžÐºÐ°ÑÐŸÑ</Text>
+</th>
+<th width="406">
+<Text id="667">ÐÐŸÐŽÐŸÐ²ÑÐ¹ ÐŒÐŸÐŽÑÐ»Ñ, ÐºÐŸÑÐŸÑÑÐ¹ Ð°ÐœÐ°Ð»ÐžÐ·ÐžÑÑÐµÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ° ÐŽÐ»Ñ ÑÐŸÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐžÐœÐŽÐµÐºÑÐŸÐ² ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="668">Collection ÐÐŸÐ»Ð»ÐµÐºÑÐžÑ</Text>
+</th>
+<th width="406">
+<Text id="669">ÐÐ°Ð±ÐŸÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ², ÐºÐŸÑÐŸÑÑÐµ ÑÐŸÐ±ÑÐ°ÐœÑ Ð²ÐŒÐµÑÑÐµ Ð¿ÐŸÐŽ ÐŸÐŽÐœÐžÐŒ Ð¿ÐŸÐžÑÐºÐŸÐ²ÑÐŒ Ðž Ð¿ÑÐŸÑÐŒÐŸÑÑ ÐžÐœÑÐµÑÑÐµÐ¹ÑÐŸÐŒ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="670">Collection configuration file ÐÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</th>
+<th width="406">
+<Text id="671">Ð€Ð°Ð¹Ð», ÐºÐŸÑÐŸÑÑÐ¹, ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ, ÐºÐ°Ðº ÐŽÐŸÐ»Ð¶ÐœÐ° Ð±ÑÑÑ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÂ¬Ð²Ð°ÐœÐ° Ðž Ð¿ÐŸÑÑÑÐŸÐµÐœÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ, ÐºÐ°ÐºÐžÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÑ ÐžÐœÐŽÐµÐºÑÑ Ðž ÑÐ·ÑÐº ÐžÐœÑÐµÑÑÐµÐ¹ÑÐ°.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="672">Collection server Ð¡ÐµÑÐ²ÐµÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</th>
+<th width="406">
+<Text id="673">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ°, ÐŸÑÐ²ÐµÑÑÑÐ²ÐµÐœÐœÐ°Ñ Ð·Ð° Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÐµÐœÐžÐµ ÐŽÐŸÑÑÑÐ¿Ð° Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Ð¿ÑÐž ÐµÐµ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÐœÐžÐž</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="674">Configuration file ÐÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð»</Text>
+</th>
+<th width="406">
+<Text id="675">Ð¡ÐŒÐŸÑÑÐžÑÐµ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» ÐºÐŸÐ»ÐµÐºÑÐžÐž, Ð³Ð»Ð°Ð²ÐœÑÐ¹ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð», ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð» ÐŒÐµÑÑÐŸÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="676">CVS (Concurrent Versioning System)</Text>
+</th>
+<th width="406">
+<Text id="677">Ð¡Ñ
+ÐµÐŒÐ° ÐŽÐ»Ñ Ð¿ÐŸÐŽÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÐžÑÑ
+ÐŸÐŽÐœÐŸÐ³ÐŸ ÐºÐŸÐŽÐ°, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ Ð²
+Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="678"><i>db2txt</i></Text>
+</th>
+<th width="406">
+<Text id="679">Ð¡ÑÐµÐŽÑÑÐ²ÐŸ ÐŽÐ»Ñ Ð¿ÑÐŸÑÐŒÐŸÑÑÐ° Ð±Ð°Ð· ÐŽÐ°ÐœÐœÑÑ
+ GDBM Ð² ÑÐµÐºÑÑÐŸÐ²ÐŸÐŒ ÑÐµÐ¶ÐžÐŒÐµ (ÑÐŒÐŸÑÑÐžÑÐµ GDBM)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="680">Demo collection ÐÐµÐŒÐŸÐœÑÑÑÐ°ÑÐžÐŸÐœÐœÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ</Text>
+</th>
+<th width="406">
+<Text id="681">ÐÐŸÐŽÑÐ°Ð·ÐŽÐµÐ» ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž Humanities Development Library, ÑÐ°Ð¿ÑÐŸÑÑÑÐ°ÐœÑÐµÐŒÑÐ¹ Ñ ÑÑÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐŸÐ¹ Ðž ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐ¹ ÐŽÐ»Ñ ÐžÐ»Ð»ÑÑÑÑÐ°ÑÐžÐž Ðž ÐŸÐ±ÑÑÐµÐœÐžÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="682">Digital library ÐŠÐžÑÑÐŸÐ²Ð°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° DL</Text>
+</th>
+<th width="406">
+<Text id="683">ÐÐ°Ð±ÐŸÑ ÑÐžÑÑÐŸÐ²ÑÑ
+ ÐŸÐ±ÑÐµÐºÑÐŸÐ² (ÑÐµÐºÑÑÐŸÐ²ÑÑ
+, Ð°ÑÐŽÐžÐŸ Ðž Ð²ÐžÐŽÐµÐŸ) Ð²ÐŒÐµÑÑÐµ ÑÐŸ ÑÑÐµÐŽÑÑÐ²Ð°ÐŒÐž ÐŽÐŸÑÑÑÐ¿Ð° Ðž ÐžÐ·Ð²Ð»ÐµÑÐµÐœÐžÑ, Ð²ÑÐ±ÐŸÑÐ°, ÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐž Ðž Ð¿ÐŸÐŽÐŽÐµÑÐ¶Ð°ÐœÐžÑ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Ð Ð°Ð·Ð²ÐžÑÐžÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ Ð³ÑÐŒÐ°ÐœÐžÑÐ°ÑÐœÐŸÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž ÐŽÐ»Ñ ÑÐ°Ð·Ð²ÐžÐ²Ð°ÑÑÐžÑ
+ÑÑ ÑÑÑÐ°Ðœ</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="684">DL</Text>
+</th>
+<th width="406">
+<Text id="685">Development Library, A Greenstone collection of humanitarian information for developing countries</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="686">Document ÐÐŸÐºÑÐŒÐµÐœÑ</Text>
+</th>
+<th width="406">
+<Text id="687">ÐÑÐœÐŸÐ²ÐœÐŸÐ¹ ÑÐ»ÐµÐŒÐµÐœÑ, ÐžÐ· ÐºÐŸÑÐŸÑÐŸÐ³ÐŸ ÑÐŸÑÑÐŸÑÑ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÑÐœÑÐµ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž: ÐŒÐŸÐ¶ÐµÑ Ð²ÐºÐ»ÑÑÐ°ÑÑ Ð² ÑÐµÐ±Ñ ÑÐµÐºÑÑ, Ð³ÑÐ°ÑÐžÐºÑ, Ð·Ð²ÑÐº Ðž Ð²ÐžÐŽÐµÐŸ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="688">Dublin core</Text>
+</th>
+<th width="406">
+<Text id="689">Ð¡ÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐ¹ ÐŒÐµÑÐŸÐŽ ÐŸÐ¿ÐžÑÐ°ÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="690">Fast CGI</Text>
+</th>
+<th width="406">
+<Text id="691">Ð¡ÑÐµÐŽÑÑÐ²ÐŸ, Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑÐµÐµ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑ ÑÐºÑÐžÐ¿ÑÑ CGI Ð² Ð°ÐºÑÐžÐ²ÐœÐŸÑÑÐž, ÑÑÐŸÐ±Ñ Ð¿ÑÐž Ð¿ÐŸÐ²ÑÐŸÑÐœÐŸÐŒ Ð²ÐºÐ»ÑÑÐµÐœÐžÐž ÐžÑ
+ Ð·Ð°ÐœÐŸÐ²ÐŸ ÐœÐµ Ð·Ð°Ð¿ÑÑÐºÐ°ÑÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="692">Filter program ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÑÐžÐ»ÑÑÑÐ°ÑÐžÐž</Text>
+</th>
+<th width="406">
+<Text id="693">Ð¢Ð° ÑÐ°ÑÑÑ ÑÐµÑÐ²ÐµÑÐ° ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹, ÐºÐŸÑÐŸÑÐ°Ñ Ð²ÑÐ¿ÐŸÐ»ÐœÑÐµÑ ÐŸÐ¿ÐµÑÐ°ÑÐžÐž Ð·Ð°Ð¿ÑÐŸÑÐ° Ðž Ð¿ÑÐŸÑÐŒÐŸÑÑÐ°</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="694">Format string Ð€ÐŸÑÐŒÐ°ÑÐœÐ°Ñ ÑÑÑÐŸÐºÐ°</Text>
+</th>
+<th width="406">
+<Text id="695">Ð¡ÑÑÐŸÐºÐ°, ÐºÐŸÑÐŸÑÐ°Ñ ÑÐºÐ°Ð·ÑÐ²Ð°ÐµÑ, ÐºÐ°Ðº Ð²ÑÐ¿ÐŸÐ»ÐœÑÑÑ Ð¿ÐŸÐºÐ°Ð· ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ð² Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="696">GB-encoding</Text>
+</th>
+<th width="406">
+<Text id="697">Ð¡ÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐ¹ ÐŒÐµÑÐŸÐŽ ÐºÐŸÐŽÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐºÐžÑÐ°Ð¹ÑÐºÐŸÐ³ÐŸ ÑÐ·ÑÐºÐ°</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="698">GDBM ÐÐµÐœÐµÐŽÐ¶ÐµÑ Ð±Ð°Ð· ÐŽÐ°ÐœÐœÑÑ
+ GNU</Text>
+</th>
+<th width="406">
+<Text id="699">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ°, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ Ð² Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐŒ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐž Greenstone ÐŽÐ»Ñ Ñ
+ÑÐ°ÐœÐµÐœÐžÑ ÐŒÐµÑÐ°ÐŽÐ°ÐœÐœÑÑ
+ ÐŽÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="700">GIMP</Text>
+</th>
+<th width="406">
+<Text id="701">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° (Ð² Linux), ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐžÐºÐŸÐœÐŸÐº Ð² Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="702">GML (Greenstone Markup Language)</Text>
+</th>
+<th width="406">
+<Text id="703">XML-ÑÐŸÐ²ÐŒÐµÑÑÐžÐŒÑÐ¹ ÑÐŸÑÐŒÐ°Ñ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐ¹ ÐŽÐ»Ñ Ð²ÐœÑÑÑÐµÐœÐœÐµÐ³ÐŸ Ñ
+ÑÐ°ÐœÐµÐœÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ².</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="704">Gnu license (ÐÐžÑÐµÐœÐ·ÐžÑ GNU)</Text>
+</th>
+<th width="406">
+<Text id="705">ÐÐžÑÐµÐœÐ·ÐžÑ, Ð¿ÐŸÐ·Ð²ÐŸÐ»ÑÑÑÐ°Ñ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÐŒ ÑÐ²ÐŸÐ±ÐŸÐŽÐœÐŸ Ð¿ÐµÑÐµÐ¿ÐžÑÑÐ²Ð°ÑÑ Ðž ÑÐ°ÑÐ¿ÑÐŸÑÑÑÐ°ÐœÑÑÑ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ, Ð° ÑÐ°ÐºÐ¶Ðµ ÐŒÐŸÐŽÐžÑÐžÑÐžÑÐŸÐ²Ð°ÑÑ ÐµÐµ Ð¿ÑÐž ÑÑÐ»ÐŸÐ²ÐžÐž, ÑÑÐŸ ÐŒÐŸÐŽÐžÑÐžÐºÐ°ÑÐžÑ ÑÐ°ÐºÐ¶Ðµ Ð±ÑÐŽÐµÑ ÐŸÐ±ÑÐµÐŽÐŸÑÑÑÐ¿ÐœÐ°.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="706">Greenstone</Text>
+</th>
+<th width="406">
+<Text id="707">ÐÐ°Ð·Ð²Ð°ÐœÐžÐµ ÐŽÐ°ÐœÐœÐŸÐ¹ ÑÐžÑÑÐŸÐ²ÐŸÐ¹ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="708">GSDL Greenstone Digital Library</Text>
+</th>
+<th width="406">
+<Text id="709">ÐÐ±Ð±ÑÐµÐ²ÐžÐ°ÑÑÑÐ° ÐœÐ°Ð·Ð²Ð°ÐœÐžÑ ÐŠÐžÑÑÐŸÐ²Ð°Ñ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="710"><i>%GSDLHOME%</i></Text>
+</th>
+<th width="406">
+<Text id="711">ÐÐµÑÐµÐŒÐµÐœÐœÐ°Ñ ÐŸÐ¿ÐµÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ cÐžÑÑÐµÐŒÑ, Ð¿ÑÐµÐŽÑÑÐ°Ð²Ð»ÑÑÑÐ°Ñ ÐŽÐžÑÐµÐºÑÐŸÑÐžÑ Ð²ÑÑÑÐµÐ³ÐŸ ÑÑÐŸÐ²ÐœÑ, Ð² ÐºÐŸÑÐŸÑÐŸÐ¹ ÑÐŸÐŽÐµÑÐ¶Ð°ÑÑÑ Ð²ÑÐµ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÑ Ðž ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž Greenstone (Ð² Unix ÑÑÐŸ SGSDLHOME).</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="712"><i>%GSDLOS%</i></Text>
+</th>
+<th width="406">
+<Text id="713">ÐÐµÑÐµÐŒÐµÐœÐœÐ°Ñ ÐŸÐ¿ÐµÑÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐ°ÐµÑ ÑÑ ÐŸÐ¿ÐµÑÐ°ÑÐžÐŸÐœÐœÑÑ ÑÐžÑÑÐµÐŒÑ, ÐºÐŸÑÐŸÑÐ°Ñ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÑÑÑ Ð² ÐŽÐ°ÐœÐœÑÐ¹ ÐŒÐŸÐŒÐµÐœÑ.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="714"><i>hashfile</i></Text>
+</th>
+<th width="406">
+<Text id="715">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Ð² Greenstone, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ Ð¿ÑÐž ÐžÐŒÐ¿ÐŸÑÑÐµ Ðž Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÐž ÐŽÐ»Ñ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐžÑÐµÐ»Ñ ÐºÐ°Ð¶ÐŽÐŸÐ³ÐŸ ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="716">HTML</Text>
+</th>
+<th width="406">
+<Text id="717">Ð¯Ð·ÑÐº Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ, Ð² ÐºÐŸÑÐŸÑÐŸÐŒ ÐœÐ°Ð¿ÐžÑÐ°ÐœÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð² Ð²ÐµÐ±-ÑÑÑÐ°ÐœÐžÑÐ°Ñ
+ </Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="718"><i>import.pl</i></Text>
+</th>
+<th width="406">
+<Text id="719">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Greenstone, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ ÐŽÐ»Ñ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ²</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="720">Importing ÐÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ</Text>
+</th>
+<th width="406">
+<Text id="721">ÐÑÐŸÑÐµÑÑ Ð¿ÐµÑÐµÐœÐŸÑÐ° ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² ÐžÐ·Ð²ÐœÐµ Ð² ÑÐžÑÑÐµÐŒÑ Greenstone</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="722">Index ÐÐœÐŽÐµÐºÑ</Text>
+</th>
+<th width="406">
+<Text id="723">ÐÐ°ÑÐ°ÐŒÐµÑÑ, Ð¿ÐŸ ÐºÐŸÑÐŸÑÐŸÐŒÑ ÐŸÑÑÑÐµÑÑÐ²Ð»ÑÐµÑÑÑ Ð¿ÐŸÐžÑÐº Ðž Ð¿ÑÐŸÑÐŒÐŸÑÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="724">InstallShield</Text>
+</th>
+<th width="406">
+<Text id="725">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Windows, Ñ Ð¿ÐŸÐŒÐŸÑÑÑ ÐºÐŸÑÐŸÑÐŸÐ¹ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° ÑÑÑÐ°ÐœÐ°Ð²Ð»ÐžÐ²Ð°ÐµÑÑÑ ÐœÐ° Ð¶ÐµÑÑÐºÐžÐ¹ ÐŽÐžÑÐº Ñ CD-ROM</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="726">Main configuration file ÐÐ»Ð°Ð²ÐœÑÐ¹ ÐºÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÑÐ°Ð¹Ð»</Text>
+</th>
+<th width="406">
+<Text id="727">Ð€Ð°Ð¹Ð», ÑÐŸÐŽÐµÑÐ¶Ð°ÑÐžÐ¹ ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÑ Ðž ÑÐºÐ°Ð·Ð°ÐœÐžÑ, ÑÐžÐ¿ÐžÑÐœÑÐµ ÐŽÐ»Ñ Ð²ÑÐµÑ
+ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="728">Metadata ÐÐµÑÐ°ÐŽÐ°ÐœÐœÑÐµ</Text>
+</th>
+<th width="406">
+<Text id="729">ÐÐ¿ÐžÑÐ°ÑÐµÐ»ÑÐœÑÐµ ÐŽÐ°ÐœÐœÑÐµ, ÑÐ°ÐºÐžÐµ ÐºÐ°Ðº Ð°Ð²ÑÐŸÑ, ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ, ÐŽÐ°ÑÐ°, ÐºÐ»ÑÑÐµÐ²ÑÐµ ÑÐ»ÐŸÐ²Ð° Ðž Ñ.ÐŽ., ÐºÐŸÑÐŸÑÑÐµ ÐžÐŒÐµÐµÑ ÐºÐ°Ð¶ÐŽÑÐ¹ ÐŽÐŸÐºÑÐŒÐµÐœÑ (ÐžÐ»Ðž ÐŽÐŸÐºÑÐŒÐµÐœÑÐ°Ð»ÑÐœÐ°Ñ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÑ)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="730">MG</Text>
+</th>
+<th width="406">
+<Text id="731">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ°, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ Greenstone ÐŽÐ»Ñ Ð¿ÐŸÐ»ÐœÐŸÑÐµÐºÑÑÐŸÐ²ÐŸÐ³ÐŸ ÐžÐœÐŽÐµÐºÑÐžÑÐŸÐ²Ð°ÐœÐžÑ, ÐºÐŸÑÐŸÑÐ°Ñ Ð²ÐºÐ»ÑÑÐ°ÐµÑ Ð² ÑÐµÐ±Ñ ÑÐ°Ð·Ð»ÐžÑÐœÑÐµ ÐŒÐµÑÐŸÐŽÑ ÑÐ¶Ð°ÑÐžÑ (ÑÐŒÐŸÑÑÐžÑÐµ Witten, I.H., Morrat, A. Bell, T. Managing Gigabytesrcompressing and indexing documents and images, Morgan Kaufman, Ð²ÑÐŸÑÐŸÐµ ÐžÐ·ÐŽÐ°ÐœÐžÐµ, 1999)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="732"><i>mgbuild</i></Text>
+</th>
+<th width="406">
+<Text id="733">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° MG ÐŽÐ»Ñ Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ ÑÐ¶Ð°ÑÑÑ
+ Ð¿ÐŸÐ»ÐœÐŸÑÐµÐºÑÑÐŸÐ²ÑÑ
+ ÐžÐœÐŽÐµÐºÑÐŸÐ²</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="734"><i>mgquery</i></Text>
+</th>
+<th width="406">
+<Text id="735">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° MG ÐŽÐ»Ñ Ð·Ð°Ð¿ÑÐŸÑÐ° ÑÐ¶Ð°ÑÑÑ
+ Ð¿ÐŸÐ»ÐœÐŸÑÐµÐºÑÑÐŸÐ²ÑÑ
+ ÐžÐœÐŽÐµÐºÑÐŸÐ²</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="736"><i>mkcol.pl</i></Text>
+</th>
+<th width="406">
+<Text id="737">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Greenstone, ÐºÐŸÑÐŸÑÐ°Ñ ÑÐŸÐ·ÐŽÐ°ÑÑ Ðž ÐžÐœÐžÑÐžÐžÑÑÐµÑ ÑÑÑÑÐºÑÑÑÑ ÐŽÐžÑÐµÐºÑÐŸÑÐžÐž ÐŽÐ»Ñ ÐœÐŸÐ²ÐŸÐ¹ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="738">New ZealandÂ Digital Library Project ÐÑÐŸÐµÐºÑ ÐŠÐžÑÑÐŸÐ²ÐŸÐ¹ ÐÐžÐ±Ð»ÐžÐŸÑÐµÐºÐž ÐÐŸÐ²ÐŸÐ¹ ÐÐµÐ»Ð°ÐœÐŽÐžÐž</Text>
+</th>
+<th width="406">
+<Text id="739">ÐÑÑÐ»ÐµÐŽÐŸÐ²Ð°ÑÐµÐ»ÑÑÐºÐžÐ¹ Ð¿ÑÐŸÐµÐºÑ ÐŽÐµÐ¿Ð°ÑÑÐ°ÐŒÐµÐœÑÐ° ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÐœÐŸÐ³ÐŸ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ ÑÐœÐžÐ²ÐµÑÑÐžÑÐµÑÐ° ÐÐ°Ð¹ÐºÐ°ÑÐŸ, ÐÐŸÐ²Ð°Ñ ÐÐµÐ»Ð°ÐœÐŽÐžÑ, ÐºÐŸÑÐŸÑÑÐ¹ ÑÐŸÐ·ÐŽÐ°Ð» Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÐµ Greenstone (nzdl.org)</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="740">OID (Object Identifier) ÐÐ¿ÑÐµÐŽÐµÐ»ÐžÑÐµÐ»Ñ ÐŸÐ±ÑÐµÐºÑÐ°</Text>
+</th>
+<th width="406">
+<Text id="741">Ð£ÐœÐžÐºÐ°Ð»ÑÐœÑÐ¹ ÐžÐŽÐµÐœÑÐžÑÐžÐºÐ°ÑÐžÐŸÐœÐœÑÐ¹ ÐºÐŸÐŽ, Ð¿ÑÐžÑÐ²Ð°ÐžÐ²Ð°ÐµÐŒÑÐ¹ ÐºÐ°Ð¶ÐŽÐŸÐŒÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="742">Perl</Text>
+</th>
+<th width="406">
+<Text id="743">Ð¯Ð·ÑÐº Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐžÑÐŸÐ²Ð°ÐœÐžÑ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐ¹ ÐŽÐ»Ñ ÐŸÐ¿ÐµÑÐ°ÑÐžÐ¹ Ð¿ÑÐŸÑÐµÑÑÐ° Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="744">Ping</Text>
+</th>
+<th width="406">
+<Text id="745">Ð¡ÐŸÐŸÐ±ÑÐµÐœÐžÐµ, Ð¿ÐŸÑÐ»Ð°ÐœÐœÐŸÐµ Ð² ÑÐžÑÑÐµÐŒÑ ÐŽÐ»Ñ ÐŸÐ¿ÑÐµÐŽÐµÐ»ÐµÐœÐžÑ,
+ÑÐ°Ð±ÐŸÑÐ°ÐµÑ ÐŸÐœÐ° ÐžÐ»Ðž ÐœÐµÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="746">Plugin ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐµ ÐŽÐŸÐ¿ÐŸÐ»ÐœÐµÐœÐžÐµ</Text>
+</th>
+<th width="406">
+<Text id="747">ÐÐŸÐŽÑÐ»ÑÐœÑÐ¹ ÐºÐŸÐŽ ÐŽÐ»Ñ ÑÐ°Ð±ÐŸÑÑ Ñ ÑÐ°Ð·Ð»ÐžÑÐœÑÐŒÐž ÑÐŸÑÐŒÐ°ÑÐ°ÐŒÐž, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐ¹ Ð²ÐŸ Ð²ÑÐµÐŒÑ ÐžÐŒÐ¿ÐŸÑÑÐžÑÐŸÐ²Ð°ÐœÐžÑ Ðž Ð¿ÐŸÑÑÑÐŸÐµÐœÐžÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="748">Protocol ÐÑÐŸÑÐŸÐºÐŸÐ»</Text>
+</th>
+<th width="406">
+<Text id="749">ÐÐ°Ð±ÐŸÑ ÑÑÐ»ÐŸÐ²ÐœÑÑ
+ ÐŸÐ±ÐŸÐ·ÐœÐ°ÑÐµÐœÐžÐ¹, Ð¿ÑÐž Ð¿ÐŸÐŒÐŸÑÐž ÐºÐŸÑÐŸÑÑÑ
+ Greenstone receptionist ÑÐ°Ð±ÐŸÑÐ°ÐµÑ Ñ ÑÐµÑÐ²ÐµÑÐŸÐŒ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="750">Ð Ð°ÐœÐ¶ÐžÑÐŸÐ²Ð°ÐœÐœÑÐ¹ Ð·Ð°Ð¿ÑÐŸÑ</Text>
+</th>
+<th width="406">
+<Text id="751">ÐÐ°Ð¿ÑÐŸÑ Ðº ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐŸÐœÐœÐŸÐ¹ ÑÐžÑÑÐµÐŒÐµ ÐžÐ·Ð²Ð»ÐµÑÐµÐœÐžÑ, ÐºÐŸÑÐŸÑÐ°Ñ Ð²ÑÐŽÐ°ÐµÑ ÐŽÐŸÐºÑÐŒÐµÐœÑÑ Ð¿ÐŸ ÑÑÐµÐ¿ÐµÐœÐž Ð²Ð°Ð¶ÐœÐŸÑÑÐž.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="752">Receptionist</Text>
+</th>
+<th width="406">
+<Text id="753">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ°, ÐºÐŸÑÐŸÑÐ°Ñ ÐŸÑÐ³Ð°ÐœÐžÐ·ÐŸÐ²ÑÐ²Ð°ÐµÑ Ð¿ÐŸÐ»ÑÐ·ÐŸÐ²Ð°ÑÐµÐ»ÑÑÐºÐžÐ¹ ÐžÐœÑÐµÑÑÐµÐ¹Ñ Greenstone.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="754">RTF</Text>
+</th>
+<th width="406">
+<Text id="755">Ð¡ÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐ¹ ÑÐŸÑÐŒÐ°Ñ ÐŽÐ»Ñ Ð²Ð·Ð°ÐžÐŒÐŸÐŸÐ±ÐŒÐµÐœÐ° ÑÐµÐºÑÑÐŸÐ²ÑÐŒÐž ÐÐŸÐºÑÐŒÐµÐœÑÐ°ÐŒÐž</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="756">Searching ÐÐŸÐžÑÐº</Text>
+</th>
+<th width="406">
+<Text id="757">ÐÐŸÑÑÑÐ¿ Ðº ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐž ÑÐµÑÐµÐ· Ð¿ÐŸÐ»ÐœÐŸÑÐµÐºÑÑÐŸÐ²ÐŸÐ¹ Ð¿ÐŸÐžÑÐº ÐµÐ³ÐŸ ÑÐŸÐŽÐµÑÐ¶ÐžÐŒÐŸÐ³ÐŸ</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="758">Server Ð¡ÐµÑÐ²ÐµÑ</Text>
+</th>
+<th width="406">
+<Text id="759">Ð¡ÐŒÐŸÑÑÐžÑÐµ ÑÐµÑÐ²ÐµÑ ÐºÐŸÐ»Ð»ÐµÐºÑÐžÐ¹ Ðž Ð²ÐµÐ±-ÑÐµÑÐ²ÐµÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="760"><i>setup.bat, setup.sh, setup.csh</i></Text>
+</th>
+<th width="406">
+<Text id="761">Ð¡ÐºÑÐžÐ¿Ñ, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÐ¹ ÐŽÐ»Ñ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž Ðž ÑÐµÐŸÑÐ³Ð°ÐœÐžÐ·Ð°ÑÐžÐž Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐœÐŸÐ³ÐŸ ÐŸÐ±ÐµÑÐ¿ÐµÑÐµÐœÐžÑ Greenstone Ð¿ÐŸ Ð²Ð°ÑÐµÐŒÑ Ð¶ÐµÐ»Ð°ÐœÐžÑ</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="762">Site configuration ÐÐŸÐœÑÐžÐ³ÑÑÐ°ÑÐžÑ ÐŒÐµÑÑÐŸÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÑ</Text>
+</th>
+<th width="406">
+<Text id="763">Ð€Ð°Ð¹Ð», ÐºÐŸÑÐŸÑÑÐ¹ ÑÐŸÐŽÐµÑÐ¶ÐžÑ Ð²ÑÐµ ÑÐºÐ°Ð·Ð°ÐœÐžÑ ÐŽÐ»Ñ ÐœÐ°ÑÑÑÐŸÐ¹ÐºÐž Greenstone Ðº ÐŒÐµÑÑÐŸÐ¿ÐŸÐ»ÐŸÐ¶ÐµÐœÐžÑ, ÐœÐ° ÐºÐŸÑÐŸÑÐŸÐµ ÐŸÐœ Ð±ÑÐŽÐµÑ Ð£ÑÑÐ°ÐœÐŸÐ²Ð»ÐµÐœ</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="764">Stemming</Text>
+</th>
+<th width="406">
+<Text id="765">ÐÐ³ÐœÐŸÑÐžÑÐŸÐ²Ð°ÐœÐžÐµ ÐŸÐºÐŸÐœÑÐ°ÐœÐžÐ¹ ÑÐ»ÐŸÐ² ÐŽÐ»Ñ ÑÐ°ÑÑÐžÑÐµÐœÐžÑ
+ÐŸÐ±ÐŸÐ±ÑÐµÐœÐžÑ Ð·Ð°Ð¿ÑÐŸÑÐ°</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="766">STL</Text>
+</th>
+<th width="406">
+<Text id="767">Ð¡ÑÐ°ÐœÐŽÐ°ÑÑÐœÐ°Ñ ÑÐ°Ð±Ð»ÐŸÐœÐœÐ°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ°, ÑÐžÑÐŸÐºÐŸÐŽÐŸÑÑÑÐ¿ÐœÐ°Ñ Ð±ÐžÐ±Ð»ÐžÐŸÑÐµÐºÐ° ÐºÐŸÐŽÐ° C++, ÑÐ°Ð·ÑÐ°Ð±ÐŸÑÐ°ÐœÐœÐ°Ñ Silicon Graphics</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="768">txt2db</Text>
+</th>
+<th width="406">
+<Text id="769">ÐÑÐŸÐ³ÑÐ°ÐŒÐŒÐ° Greenstone, ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÐ°Ñ Ð² Ð¿ÑÐŸÑÐµÑÑÐµ ÑÐŸÐ·ÐŽÐ°ÐœÐžÑ Ð±Ð°Ð·Ñ ÐŽÐ°ÐœÐœÑÑ
+ GDBM</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="770">Unicode Ð£ÐœÐžÐºÐŸÐŽ</Text>
+</th>
+<th width="406">
+<Text id="771">Ð¡ÑÐ°ÐœÐŽÐ°ÑÑÐœÐ°Ñ ÑÑ
+ÐµÐŒÐ° ÐŽÐ»Ñ Ð¿ÐŸÐºÐ°Ð·Ð° ÑÐžÐŒÐ²ÐŸÐ»ÐŸÐ², ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÐµÐŒÑÑ
+ ÐŒÐžÑÐŸÐ²ÑÐŒÐž ÑÐ·ÑÐºÐ°ÐŒÐž </Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="772">UNU</Text>
+</th>
+<th width="406">
+<Text id="773">Ð£ÐœÐžÐ²ÐµÑÑÐžÑÐµÑ ÐÐÐ</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="774">Web server ÐÐµÐ±-ÑÐµÑÐ²ÐµÑ</Text>
+</th>
+<th width="406">
+<Text id="775">Ð¡ÑÐ°ÐœÐŽÐ°ÑÑÐœÐ°Ñ Ð¿ÑÐŸÐ³ÑÐ°ÐŒÐŒÐ°, ÐºÐŸÑÐŸÑÑÑ ÐžÑÐ¿ÐŸÐ»ÑÐ·ÑÑÑ ÐºÐŸÐŒÐ¿ÑÑÑÐµÑÑ ÐŽÐ»Ñ Ð¿ÑÐµÐŽÐŸÑÑÐ°Ð²Ð»ÐµÐœÐžÑ ÐŽÐŸÑÑÑÐ¿Ð° Ðº ÐžÐœÑÐŸÑÐŒÐ°ÑÐžÐž ÑÐµÑÐµÐ· WWW.</Text>
+</th>
+</tr>
+<tr>
+<th width="123">
+<Text id="776">XML</Text>
+</th>
+<th width="406">
+<Text id="777">Ð¡ÑÐ°ÐœÐŽÐ°ÑÑÐœÑÐ¹ ÑÐŸÑÐŒÐ°Ñ ÐŽÐ»Ñ ÑÑÑÑÐºÑÑÑÐžÑÐŸÐ²Ð°ÐœÐœÑÑ
+ ÐŽÐŸÐºÑÐŒÐµÐœÑÐŸÐ² Ðž ÐŽÐ°ÐœÐœÑÑ
+ Ð² ÐÐœÑÐµÑÐœÐµÑÐµ (Greenstone Markup Language ÐœÐ°Ñ
+ÐŸÐŽÐžÑÑÑ Ð² XML ÑÐŸÐ²ÐŒÐµÑÑÐžÐŒÐŸÐŒ ÑÐŸÑÐŒÐ°ÑÐµ)</Text>
+</th>
+</tr>
+</TableContent>
+</Table>
+</Content>
+</Chapter>
+<FootnoteList>
+<Footnote id="1">
+<Text id="778">ÑÑÐ° ÐŸÐ¿ÑÐžÑ Ð¿ÐŸÐ²ÑÐµÐ¶ÐŽÐ°ÐµÑÑÑ, ÐµÑÐ»Ðž ÑÐ»ÐµÐŒÐµÐœÑ Ñ ÑÐµÐŒ Ð¶Ðµ ÑÐ°ÐŒÑÐŒ ÐžÐŒÐµÐœÐµÐŒ ÑÐ¶Ðµ ÑÑÑÐµÑÑÐ²ÑÐµÑ</Text>
+</Footnote>
+</FootnoteList>
+</Manual>
Index: /tags/start/gsdl-documentation/shared/ApplyXSLT.java
===================================================================
--- /tags/start/gsdl-documentation/shared/ApplyXSLT.java	(revision 13666)
+++ /tags/start/gsdl-documentation/shared/ApplyXSLT.java	(revision 13666)
@@ -0,0 +1,93 @@
+/**
+ *#########################################################################
+ *
+ * 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: Michael Dewsnip 
+ *         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.
+ *########################################################################
+ */
+
+import java.io.*;
+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.stream.StreamResult;
+
+/** Any class that wants to act as the owner of an AppendLineOnlyFileDocument has to implement this.
+ * @author Michael Dewsnip, Greenstone Project, New Zealand Digital Library, University of Waikato
+ * @version 2.41 final
+ */
+public class ApplyXSLT
+{
+    static public void main(String[] args)
+    {
+	if (args.length < 2) {
+	    System.err.println("Usage: ApplyXSLT <XSLfile> <XMLfile>");
+	    System.exit(1);
+	}
+
+	System.setProperty("javax.xml.transform.TransformerFactory",
+			   "org.apache.xalan.processor.TransformerFactoryImpl");
+	TransformerFactory t_factory = null;
+	try {
+	    t_factory = org.apache.xalan.processor.TransformerFactoryImpl.newInstance();
+	}
+	catch (Exception ex) {
+	    System.err.println("XMLTransformer() exception " + ex.getMessage());
+	    System.exit(1);
+	}
+
+	String stylesheet = args[0];
+	String xml_in = args[1];
+	try {
+	    // Use the TransformerFactory to process the stylesheet Source and generate a Transformer
+	    Transformer transformer = t_factory.newTransformer(new StreamSource(stylesheet));
+
+	    // Use the Transformer to transform an XML Source and send the output to a Result object
+	    StreamSource input = (xml_in.equals("-") ? new StreamSource(System.in) : new StreamSource(xml_in));
+	    OutputStreamWriter output = new OutputStreamWriter(System.out, "UTF-8");
+	    transformer.transform(input, new StreamResult(output));
+	}
+	catch (TransformerConfigurationException ex) {
+	    //System.err.println("XMLTransformer: couldn't create transformer object: " + ex.getMessageAndLocation());
+	    //System.err.println(ex.getLocationAsString());  
+	    ex.printStackTrace();
+	    System.exit(1);
+	}
+	catch (Exception ex) {
+	    //System.err.println("XMLTransformer: couldn't transform the source: " + ex.getMessage());
+	    ex.printStackTrace();
+	    System.exit(1);
+	}
+    }
+
+
+    static public String replaceAll(String source_string, String match_regexp, String replace_string)
+    {
+	return source_string.replaceAll(match_regexp, replace_string);
+    }
+}
Index: /tags/start/gsdl-documentation/shared/Dictionary.java
===================================================================
--- /tags/start/gsdl-documentation/shared/Dictionary.java	(revision 13666)
+++ /tags/start/gsdl-documentation/shared/Dictionary.java	(revision 13666)
@@ -0,0 +1,439 @@
+
+import java.util.ResourceBundle;
+import java.util.Locale;
+import java.util.HashMap;
+import java.net.URL;
+import java.io.File;
+import java.io.InputStream;
+import java.io.FileInputStream;
+import java.io.Reader;
+import java.io.FileReader;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+//import org.apache.xerces.parsers.DOMParser;
+import org.xml.sax.InputSource;
+//import org.xml.sax.XMLReader;
+//import org.xml.sax.XMLReaderFactory;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class Dictionary {
+
+    private ResourceBundle glidict = null;
+    private ResourceBundle perldict = null;
+    private MacroFile core_macros = null;
+    private MacroFile aux_macros = null;
+    private HashMap metadata = null;
+    private Locale locale = null;
+    private String lang = null;
+    static final private int GLIDICT = 0;
+    static final private int GLIHELP = 1;
+    static final private int COREDM = 2;
+    static final private int AUXDM = 3;
+    static final private int TUTORIALS = 4;
+    static final private int PERLMODULES = 5;
+    static final private int METADATA = 6;
+
+    protected String gsdl_home = null;
+    
+    private ClassLoader classloader = null;
+
+
+    public Dictionary(String lang) {
+	this.lang = lang;
+	this.locale = new Locale(lang);
+	if (this.locale==null) {
+	    this.locale = Locale.getDefault();
+	}
+	gsdl_home = System.getProperty("GSDLHOME");
+	if (gsdl_home == null) {
+	    System.err.println("Error: GSDLHOME is null!!");
+	    System.exit(1);
+	}
+
+	this.classloader = new MyClassLoader(this.getClass().getClassLoader());
+    }
+    
+    public String get(String key) {
+	return get(key, null);
+    }
+    public String get(String key, String args) {
+	int pos = key.indexOf("::");
+	if (pos==-1) {
+	    System.err.println("invalid key: "+key);
+	    return "";
+	}
+	String package_name = key.substring(0, pos);
+	String key_name = key.substring(pos+2);
+	//System.err.println("pack = "+package_name+", key="+key_name);
+
+	if (package_name.equals("glidict")) {
+	    loadDictionary(GLIDICT);
+	    return getDictionaryText(glidict, key_name, args);
+	}
+	if (package_name.equals("coredm")) {
+	    loadDictionary(COREDM);
+	    return getMacroText(core_macros, key_name);
+	}
+	if (package_name.equals("perlmodules")) {
+	    loadDictionary(PERLMODULES);
+	    return getDictionaryText(perldict, key_name, args);
+	}
+	if (package_name.equals("auxdm")) {
+	    loadDictionary(AUXDM);
+	    return getMacroText(aux_macros, key_name);
+	}
+	if (package_name.equals("glihelp")) {
+	    return "";
+	}
+	if (package_name.equals("tutorials")) {
+	    return "";
+	}
+	if (package_name.equals("metadata")) {
+	    pos = key_name.indexOf(".");
+	    String namespace = key_name.substring(0,pos);
+	    String element = key_name.substring(pos+1);
+	    if (loadMetadata(namespace)) {
+		return getMetadataName(namespace, element);
+	    }
+	    return key_name;
+	}
+	System.err.println("invalid package name "+package_name);
+	return "";
+    }
+
+    public String getDictionaryText(ResourceBundle dictionary, String key, String args) {
+
+	try {
+	    String initial_raw = dictionary.getString(key);
+	    // convert to unicode, copied from gatherer dictionary
+	    String initial = new String(initial_raw.getBytes("ISO-8859-1"), "UTF-8");
+	    if (args == null || args.equals("")) {
+		return initial;
+	    }
+	    String [] args_array = args.split(";");
+	    // 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(0 <= arg_num && arg_num < args_array.length) {
+		    complete = complete + args_array[arg_num];
+		}
+	    }
+	    return complete + initial;
+
+	    //this.raw = ResourceBundle.getBundle(this.resource, this.locale);
+	} catch (Exception e) {
+	    //System.err.println("Dictionary: couldn't locate a resource bundle for "+resource);
+	}
+	System.err.println("no value found for key "+key+" in dictionary "+dictionary.toString());
+	return "";
+    }
+
+    private String getMacroText(MacroFile macros, String key) {
+	return macros.get(key);
+    }
+    
+    private String getMetadataName(String namespace, String element_name) {
+	Element meta_set = (Element)metadata.get(namespace);
+	String default_value = namespace+"."+element_name;
+	if (meta_set == null) {
+	    return default_value;
+	}
+	Element this_elem = getNamedChild(meta_set, "Element", "name", element_name);
+	if (this_elem == null) {
+	    return default_value;
+	}
+	Element this_lang = getNamedChild(this_elem, "Language", "code", this.lang);
+	if (this_lang == null) {
+	    this_lang = this_elem; // sometimes have attributes as children of element
+	}
+	
+	// need to modify this if we get multiple languages at the same level
+	Element label_att = getNamedChild(this_lang, "Attribute", "name", "label");
+	if (label_att == null) {
+	    return default_value;
+	}
+	return namespace+"."+getTextValue(label_att);
+    }
+    
+    private Element getNamedChild(Element parent, String child_element, String att_name, String att_value) {
+	NodeList elements = parent.getElementsByTagName(child_element);
+	for (int i=0; i<elements.getLength(); i++) {
+	    Element e = (Element)elements.item(i);
+	    if (e.getAttribute(att_name).equals(att_value)) {
+		return e;
+	    }
+	}
+	return null;
+    }
+    
+    private String getTextValue(Element elem) {
+	elem.normalize();
+	Node n = elem.getFirstChild();
+        while (n!=null && n.getNodeType() !=Node.TEXT_NODE) {
+            n=n.getNextSibling();
+        }
+	return n.getNodeValue();
+    }
+
+		
+    
+    private boolean loadDictionary(int type) {
+	switch (type) {
+	case GLIDICT:
+	    if (this.glidict == null) {
+		glidict = ResourceBundle.getBundle("dictionary", this.locale, this.classloader);
+		
+	    }
+	    break;
+	case PERLMODULES:
+	    if (this.perldict == null) {
+		perldict = ResourceBundle.getBundle("strings", this.locale, this.classloader);
+	    }
+	    break;
+	    
+	case COREDM:
+	    if (this.core_macros == null) {
+		core_macros = new MacroFile(MacroFile.CORE);
+	    }
+	    break;
+	    
+	case AUXDM:
+	    if (this.aux_macros == null) {
+		aux_macros = new MacroFile(MacroFile.AUX);
+	    }
+	    break;
+	}
+	return true;
+    }
+    
+    private boolean loadMetadata(String namespace) {
+	if (metadata == null) {
+	    metadata = new HashMap();
+	}
+
+	if (metadata.containsKey(namespace)) {
+	    // already loaded
+	    return true;
+	}
+	// find the metadata file
+	String file_name = namespace+".mds";
+	if (namespace.equals("dc")) {
+	    // what about qualified???
+	    file_name = "dublin.mds";
+	}
+	
+	file_name = gsdl_home + File.separator + "gli" + File.separator + "metadata"+ File.separator + file_name;
+	//System.err.println("metadata filename = "+file_name);
+	File metadata_file = new File(file_name);
+	if (!metadata_file.exists()) {
+	    System.err.println("metadata file "+file_name+" does not exist!");
+	    return false;
+	}
+	// parse the file
+	Element elem = parseXMLFile(metadata_file);
+	if (elem != null) {
+	    metadata.put(namespace, elem);
+	    return true;
+	}
+	return false;
+    }
+
+    private Element parseXMLFile(File file) {
+
+	try {
+	    //DOMParser parser = new DOMParser();
+	    //XMLReader parser = XMLReaderFactory.createXMLReader();
+	    DocumentBuilder builder =  DocumentBuilderFactory.newInstance().newDocumentBuilder();
+	    Document doc = builder.parse(file);
+	    //FileReader reader = new FileReader(file);
+	    //InputSource xml_source = new InputSource(reader);
+
+            //parser.parse(xml_source);
+            return doc.getDocumentElement();
+	} catch (Exception e) {
+	    System.err.println("XML Parse Error: "+e.getMessage());
+	    return null;
+	}
+	
+    }
+    private class MyClassLoader 
+    extends ClassLoader {
+
+	private String gliclassesdir = null;
+	private String perldir = null;
+
+	public MyClassLoader(ClassLoader parent) {
+
+	    super(parent);
+	    gliclassesdir = gsdl_home+File.separator+"gli"+File.separator+"classes";
+	    perldir = gsdl_home+File.separator+"perllib";
+	    
+	}
+
+	public URL findResource(String name) {
+	    try {
+		File resource_path = new File(this.gliclassesdir, name);
+		if (resource_path.exists()) {
+		    return new URL("file://"+resource_path.getAbsolutePath());
+		}
+		resource_path = new File(this.perldir, name);
+		if (resource_path.exists()) {
+		    return new URL("file://"+resource_path.getAbsolutePath());
+		}
+	    } catch (Exception e) {};
+	    
+	    
+	    return super.findResource(name);
+	}
+
+
+    }
+
+    private class MacroFile {
+	public static final int CORE = 0;
+	public static final int AUX = 1;
+	
+	private File macro_file = null;
+	private HashMap macros = null;
+
+	public MacroFile(int type) {
+	    String filename = gsdl_home+File.separator+"macros"+File.separator;
+	    if (lang.equals("en")) {
+		filename += "english";
+	    } else if (lang.equals("fr")) {
+		filename += "french";
+	    } else if (lang.equals("es")) {
+		filename += "spanish";
+	    } else if (lang.equals("ru")) {
+		filename += "russian";
+	    } else {
+		System.err.println("Couldn't work out macro file name for lang "+lang);
+		return;
+	    }
+	    if(type == CORE) {
+		filename += ".dm";
+	    } else if (type == AUX) {
+		filename += "2.dm";
+	    } else {
+		System.err.println("Unknown Macro file type: "+type+"!");
+	    }
+
+	    macro_file = new File(filename);
+	    if (!macro_file.exists()) {
+		System.err.println("Macro file "+filename+" doesn't exist!");
+		return;
+	    }
+	    macros = new HashMap();
+	    loadMacroFile();
+	}
+
+	public String get(String key) {
+	    if (!key.startsWith("_") || !key.endsWith("_")) {
+		System.err.println("Error in macro key "+key);
+		return "";
+	    }
+	    String value = (String)macros.get(key.substring(1, key.length()-1));
+	    //System.err.println("proper_key"+key.substring(1, key.length()-1));
+	    if (value == null) {
+		System.err.println("No value found for key "+key+" in macro file "+macro_file.getName());
+		return "";
+	    } 
+	    return value;
+	}
+	private boolean loadMacroFile() {
+	    String current_package = "";
+	    try {
+		InputStream istream = new FileInputStream(macro_file);
+		Reader in_reader = new InputStreamReader(istream, "UTF-8");
+		BufferedReader in = new BufferedReader(in_reader);
+		String macro_str = null;
+		while((macro_str = in.readLine()) != null) {
+		    if (macro_str.startsWith("#")) {
+			// a comment
+			continue;
+		    }
+		    if (macro_str.startsWith("package")) {
+			macro_str = macro_str.substring(8);
+			macro_str = macro_str.trim();
+			if (macro_str.indexOf("#")!=-1) {
+			    macro_str = macro_str.substring(0, macro_str.indexOf("#"));
+			    macro_str = macro_str.trim();
+			}
+			current_package = macro_str;
+			//System.err.println("current package = "+current_package);
+			continue;
+		    }
+		    if (macro_str.startsWith("_")) {
+			if (macro_str.indexOf("#")!=-1) {
+			    //strip off any comments - hopefully there are no # in the actual text
+			    macro_str = macro_str.substring(0, macro_str.indexOf("#"));
+			}
+			macro_str = macro_str.trim();
+			String macro_name = macro_str.substring(1, macro_str.indexOf("_", 1));
+			//System.err.println("macro name = "+macro_name);
+			// find the {
+			int start_bracket = macro_str.indexOf("{");
+			int end_bracket = 0;
+			String line = null;
+			while(!macro_str.endsWith("}") && (line = in.readLine()) != null) {
+			    macro_str += line;
+			    macro_str = macro_str.trim();
+			}
+			if (!macro_str.endsWith("}")) {
+			    System.err.println("can't find the end of macro "+macro_name+", value="+macro_str);
+			    continue;
+			}
+			String macro_value = macro_str.substring(start_bracket+1, macro_str.length()-1);
+			//System.err.println("macro value = "+macro_value);
+			//System.err.println("adding key "+current_package+":"+macro_name+", value = "+macro_value);
+			macros.put(current_package+":"+macro_name, macro_value);
+			continue;
+		    }
+		} //while
+	    } catch (Exception e) {
+		System.err.println("Exception when trying to load macro file "+macro_file+":"+e.getMessage());
+		return false;
+	    }
+	    return true;
+	}
+    }
+
+    public static void main(String []args) {
+	if (args.length != 1) {
+	    System.err.println("Usage: java Dictionary <iso lang code>");
+	    return;
+	}
+	
+	Dictionary dict = new Dictionary(args[0]);
+	System.err.println("glidict::General.OK " +dict.get("glidict::General.OK"));
+	System.err.println("glidict::Autofilter.Order_Tooltip "+ dict.get("glidict::Autofilter.Order_Tooltip"));
+
+	System.err.println("macros _Global:textdefaulttitle_ "+dict.get("coredm::_Global:textdefaulttitle_"));
+	System.err.println("macros _about:textsubcols2_ "+dict.get("coredm::_about:textsubcols2_"));
+	System.err.println("macros _home:textdescrcollector_ "+dict.get("auxdm::_home:textdescrcollector_"));
+	
+	//System.err.println("", dict.get(""));
+	//System.err.println("", dict.get(""));
+
+    }
+}
Index: /tags/start/gsdl-documentation/shared/ExternalRef.java
===================================================================
--- /tags/start/gsdl-documentation/shared/ExternalRef.java	(revision 13666)
+++ /tags/start/gsdl-documentation/shared/ExternalRef.java	(revision 13666)
@@ -0,0 +1,44 @@
+import java.io.InputStream;
+import java.io.FileInputStream;
+
+import org.w3c.dom.Document;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.DocumentBuilder;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+public class ExternalRef{	
+
+	public ExternalRef(){}	
+
+	public String getRef(String file, String lang, String targettype, String id){
+		
+		try{
+		String tfile = file+"_"+lang+".xml";
+		String path = tfile;
+
+		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        DocumentBuilder domBuilder = factory.newDocumentBuilder();
+        InputStream is = new FileInputStream(path);
+        Document doc = domBuilder.parse(is);
+
+		NodeList list = doc.getElementsByTagName(targettype);
+		System.out.println(list.getLength());
+		int i=0;
+		for(i=0; i<list.getLength(); i++){
+			Node node = list.item(i);
+			String id_temp = node.getAttributes().getNamedItem("id").getNodeValue();			
+			if(id_temp.equals(id)) break;
+		}
+		return (++i)+"";
+        
+		}catch(Exception e){
+			System.err.println(e.getMessage());
+			//e.printStackTrace();
+			return "";
+		}
+	}	
+}
Index: /tags/start/gsdl-documentation/tutorials/xml-source/tutorial_en.xml
===================================================================
--- /tags/start/gsdl-documentation/tutorials/xml-source/tutorial_en.xml	(revision 13666)
+++ /tags/start/gsdl-documentation/tutorials/xml-source/tutorial_en.xml	(revision 13666)
@@ -0,0 +1,2267 @@
+<?xml version="1.0"?>
+<!DOCTYPE TutorialList [
+     <!ENTITY nbsp "&#160;">
+]>
+<TutorialList>
+<Tutorial id="unaids">
+<Title>
+<Text id="0082">Working with a pre-packaged collection (UNAIDS)</Text>
+</Title>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<Comment>
+<Text id="0083">You will need the Greenstone UNAIDS CD-ROM</Text>
+</Comment>
+<Heading>
+<Text id="0084">Installing a pre-packaged Greenstone collection</Text>
+</Heading>
+<NumberedItem>
+<Text id="0085">On inserting the <b>UNAIDS CD-ROM</b>, for many computers installation will begin automatically. If not, "auto-run"--a configurable setting under Windows--is disabled on your computer and you need to double-click <i>setup.exe</i> on the CD-ROM.</Text>
+<Menu>
+<Text id="0086">My Computer --&gt;</Text>
+<Text id="0087"> UNAIDS20 --&gt;</Text>
+<Text id="0088"> setup.exe</Text>
+</Menu>
+</NumberedItem>
+<NumberedItem>
+<Text id="0089">The InstallShield Wizard begins to install the UNAIDS pre-packaged collection. Select the English language.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0090">Click the <b>&lt;next&gt;</b> button.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0091">Choose <b>Run from CD-ROM (standard) </b>as the setup type. This is the default and is already selected. Then click <b>&lt;next&gt;</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0092">Click <b>&lt;next&gt; </b>again to install the UNAIDS collection in the default folder, which is <b>C:\Program Files\UNAIDS Library 2.0 [CD-ROM]</b>.</Text>
+<Comment2>
+<Text id="0093">Installation Wizard copies the required files from CD-ROM to disk</Text>
+</Comment2>
+</NumberedItem>
+<NumberedItem>
+<Text id="0094">Click <b>&lt;OK</b>&gt; to confirm completion of UNAIDS collection (twice).</Text>
+<Comment2>
+<Text id="0095">InstallShield quits</Text>
+<Text id="0096">--the UNAIDS Library is installed.</Text>
+</Comment2>
+</NumberedItem>
+<Comment>
+<Text id="0097">CD-ROMs like this one that contain pre-packaged Greenstone collections do not include the full Greenstone software. Instead they embody a mini version of Greenstone that allows you to view the collection but not to build new ones.</Text>
+</Comment>
+<Heading>
+<Text id="0098">Browsing around a Greenstone collection</Text>
+</Heading>
+<NumberedItem>
+<Text id="0099">Launch the prebuilt library by clicking: </Text>
+<Menu>
+<Text id="0100">Start --&gt;</Text>
+<Text id="0101"> All Programs --&gt;</Text>
+<Text id="0102"> UNAIDS Library 2.0 [CD-ROM] --&gt;</Text>
+<Text id="0103"> UNAIDS Library 2.0 (Standard Version).</Text>
+</Menu>
+<Comment>
+<Text id="0104">To access Greenstone through the Local Library Server, it is sometimes necessary to turn off the proxy settings of the browser. Greenstone normally detects this and pops up a window alerting you to the problem.</Text>
+</Comment>
+</NumberedItem>
+<NumberedItem>
+<Text id="0105">Click <b>&lt;Enter Library&gt; </b>in the dialog box and your browser (typically Internet Explorer by default) will display the Greenstone home page.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0106">Within the web browser, click <b>titles a-z</b> (in the centre of the navigation bar near the top of the page).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0107">Access the <b>first book</b> in the list of titles by clicking the <b>book icon</b> next to the title: </Text>
+<Text id="0108"><i>About UNAIDS</i>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0109">Use the scroll bar to view the full length of the page.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0110">In the table of contents near the top, click the <b>page icon </b>next to the heading <i>Guiding principles of UNAIDS</i> to view this section.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0111">Click the <b>page icon</b> next to the heading <i>Global and local impact</i> to view the next section.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0112">This style of interaction can be continued to further expand and contract folders and switch to a different section.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0113">To fully expand the contents of this introduction chapter, click <b>Expand Document or Chapter</b> in the upper left portion of the page, under the picture of the document's front cover.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0114">You can return to the currently selected page of document titles by clicking the <b>book icon </b>next to the title of the book at the top of the table of contents (this signifies closing the book). You also get to the document titles using <b>titles a-z</b> in the navigation bar, in this case to the titles beginning with A-D.</Text>
+<Comment2>
+<Text id="0115">If the table of contents is open at the top level--showing all the chapters--then clicking <b>Expand Document or Chapter</b> expands the full document. For long documents, which take some time to load in, Greenstone seeks confirmation for this action: clicking 'continue' loads the full document.</Text>
+</Comment2>
+</NumberedItem>
+<NumberedItem>
+<Text id="0116">Browse around and peruse some other documents in the collection.</Text>
+</NumberedItem>
+<Heading>
+<Text id="0117">Searching within a Greenstone collection</Text>
+</Heading>
+<NumberedItem>
+<Text id="0118">Access the search page by clicking <b>search</b> in the navigation bar.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0119">In the query box under <b>Search for chapters in any language which contain some of the words</b>,<b> </b>enter the term <b>gender</b> then click <b>&lt;Begin Search&gt;</b>.</Text><Comment2>
+<Text id="0120">After a short pause, the web browser loads a fresh page showing the results of the search.</Text>
+</Comment2>
+</NumberedItem>
+<NumberedItem>
+<Text id="0121">Click the <b>page icon </b>for the <b>first matching document</b> in the result set (</Text>
+<Text id="0122"><i>Five Year Implementation Review of the Vienna Declaration and Programme of Action</i>) to view the document. Because the search was at the chapter level, you are taken directly to the matching chapter within the document.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0123">Experiment further with searching, and with the interface in general. For example, there is a detailed <b>Help</b> page. It contains a <b>Preferences</b> section through which you can control some search settings.</Text>
+<Comment2>
+<Text id="0124">The Preferences options in the UNAIDS collection are intentionally minimalist. Most collections have a separate Preferences button that offers more features.</Text>
+</Comment2>
+<Comment2>
+<Text id="0125">The home page of the UNAIDS library collection cycles through a sequence of front cover images, updated every 5 seconds or so. Clicking a particular image takes you directly to that document.</Text>
+</Comment2>
+</NumberedItem>
+<Heading>
+<Text id="0126">Leaving the Greenstone digital library</Text>
+</Heading>
+<NumberedItem>
+<Text id="0127">There are two ways of leaving Greenstone:</Text>
+<NumberedItem>
+<Text id="0128">Exit from the Greenstone Software server. Click on the <b>Greenstone Software</b> in the task bar, then choose <b>Exit</b> from the <b>Browser Selection and Settings</b> menu (or click on the exit hotspot, the red cross at the top right). The Greenstone Software exits, but your web browser continues to run.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0129">Exit from your web browser. Leave your web browser in the usual way. The Greenstone server detects when you exit from the browser and generates a popup window that asks whether to close down the server as well. (The reason is that other people may be using Greenstone over the network, and should not be rudely terminated.)</Text>
+</NumberedItem>
+</NumberedItem>
+<Heading>
+<Text id="0130">Exercise: Use the UNAIDS collection to answer these questions</Text>
+</Heading>
+<BulletList>
+<Bullet>
+<Question>
+<Text id="0131">How many publications are there in the collection?</Text>
+</Question>
+<Answer>900</Answer>
+</Bullet>
+<Bullet>
+<Question>
+<Text id="0132">How many documents are there that mention <i>Australia</i> in the title?</Text>
+</Question>
+<Answer>15</Answer>
+</Bullet>
+<Bullet>
+<Question>
+<Text id="0133">How many top-level subject categories are there?</Text>
+</Question>
+<Answer>21</Answer>
+</Bullet>
+<Bullet>
+<Question>
+<Text id="0134">What does AAVP stand for? </Text>
+</Question>
+<Answer>African Aids Vaccination Programme</Answer>
+</Bullet>
+<Bullet>
+<Question>
+<Text id="0136">What does AIDS stand for?</Text>
+</Question>
+<Answer>Acquired Immuno-Deficiency Syndrome
+<Text id="0138">(Search for "AIDS stands for")</Text>
+</Answer>
+</Bullet>
+<Bullet>
+<Question>
+<Text id="0139">Considering lower case variants only, how many times does the word "condom" appear in the collection? <br/>How many times for "condoms"?</Text>
+</Question>
+<Answer>6789<br/> 5243</Answer>
+</Bullet>
+<Bullet>
+<Question>
+<Text id="0140">If case sensitivity does not matter, how many times does the word "condom" appear in the collection? <br/>How many times for "condoms"?</Text>
+</Question>
+<Answer>7905<br/> 5571</Answer>
+</Bullet>
+<Bullet>
+<Question>
+<Text id="0141">If word endings are ignored, how many times does "condom" and variants such as "condoms" appear in the collection?</Text>
+</Question>
+<Answer>13477</Answer>
+</Bullet>
+<Bullet>
+<Question>
+<Text id="0142">How many <i>chapters</i> contain some variations of the word "condom"? <br/>Does this make it a useful search term?</Text>
+</Question>
+<Answer>
+<Text id="0143">2413 chapters. <br/>  No, since there are only 900 documents</Text>
+</Answer>
+</Bullet>
+<Bullet>
+<Question>
+<Text id="0144">What year saw the first reported case of AIDS in New Zealand?</Text>
+</Question>
+<Answer>1983</Answer>
+</Bullet>
+</BulletList>
+</Content>
+</Tutorial>
+<Tutorial id="IITE">
+<Title>
+<Text id="0145">Working with a pre-packaged collection (Digital Libraries in Education)</Text>
+</Title>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<Comment>
+<Text id="0146">You will need the Greenstone Digital Libraries in Education CD-ROM</Text>
+</Comment>
+<Heading>
+<Text id="0147">Installing a pre-packaged collection</Text>
+</Heading>
+<NumberedItem>
+<Text id="0148">Insert your CD-ROM for the course <i>Digital libraries in education</i> into a Windows computer. If the installation process does not start up straightaway (because the AutoPlay feature is disabled on your computer), navigate to your CD-ROM/DVD drive (normally D:), open the folder <i>prebuilt</i>, and double click on <b>Setup.exe</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0149">During installation you are offered a choice of folder to install in: we recommend the default, which is <i>C:\GSDL</i>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0150">You are also presented with the option to run Greenstone from the CD-ROM or to copy the entire CD-ROM. We recommend the latter: please check the box that says <b>Install all collection files</b>. It will take at least a couple of minutes to copy the files across.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0151">Finally, the installer offers to install the Netscape browser for you. Do <i>not</i> request this except in the unlikely event that you do not already have a web browser on your computer.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0152">CD-ROMs like this one that contain pre-packaged Greenstone collections do not include the full Greenstone software. Instead they embody a mini version of Greenstone that allows you to view the collection but not to build new ones.</Text>
+</Comment>
+<Heading>
+<Text id="0153">Browsing around a Greenstone collection</Text>
+</Heading>
+<NumberedItem>
+<Text id="0154">To run Greenstone, open the Windows Start menu, Programs, and select <i>Greenstone</i>, then the submenu item<i> Digital Libraries in Education</i>: then &lt;<b><i>Enter Library</i></b>&gt;.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0155">Click the Digital libraries in Education collection's icon. This takes you to the collection's home page, often called the "about" page.</Text>
+<Comment>
+<Text id="0156">The home page contains an access bar with buttons called search, contents, authors a-z, modules, and acronyms. This access bar is the key to finding information in any Greenstone collection.</Text>
+</Comment>
+</NumberedItem>
+<NumberedItem>
+<Text id="0157">Click &lt;<b>authors a-z</b>&gt;. A list of bookshelf icons appears. Click the one called Marchionini, G. to see the two course readings by Gary Marchionini.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0158">One of these items is a PDF file and the other is an HTML file. Click them both in turn to open up the documents.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0159">Click the &lt;<b>contents</b>&gt; button in the access bar. This shows two bookshelves, one for this Study Guide and the other for the Course Readings. Choose one and look at what it contains.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0160">Clicking a bookshelf that is open closes it. Close the bookshelf you have just opened and then choose the other one and examine its contents.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0161">Click &lt;<b>acronyms</b>&gt; in the access bar and find the meaning of the acronym "LOM".</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0162">Click &lt;<b>search</b>&gt; and search for the word "LOM". Check out the difference between searching text and searching titles (use the pull-down box on the search page).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0163">Click the collection icon <b>Digital Libraries in Education </b>at the top left. This takes you back to the collection's <b>about</b> page.</Text>
+
+<Text id="0164">Beneath the access bar on the collection's about page is a search box (just the same as the one that appears on the search page), a description of the collection under the heading <b>About this collection</b>, and instructions on how to find information in this collection.</Text>
+<Text id="0165">Above the access bar is the collection's icon, saying <b>Digital Libraries in Education</b>. On the right is an icon saying <b>about</b>, above which are three buttons, <b>home</b>, <b>help</b>, and <b>preferences</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0166">Click &lt;<b>home</b>&gt;. This returns you to the Greenstone home page.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0167">Return to the collection (by clicking its icon), and click &lt;<b>help</b>&gt;. This gives more information about how to access the collection.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0168">Click &lt;<b>preferences</b>&gt;. This takes you to a page where you can change some of the settings.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0169">Now explore the collection by navigating freely around it. Click liberally: all images that appear on the screen are clickable. If you hold the mouse stationary over an image, most browsers will soon pop up a brief "mouse-over" message that tells you what will happen if you click. Experiment! Choose common words like "the" or "and" to search for--that should evoke some response, and nothing will break. (Note: unlike many search systems, Greenstone indexes all words, including these ones.)</Text>
+</NumberedItem>
+<Heading>
+<Text id="0170">Exercise: Read the Help page; then answer these questions</Text>
+</Heading>
+<BulletList>
+<Bullet>
+<Text id="0171">What does this collection contain?</Text>
+</Bullet>
+<Bullet>
+<Text id="0172">Name five ways to navigate to a target document in this collection.</Text>
+</Bullet>
+<Bullet>
+<Text id="0173">How many documents in the collection are written by Erik Duval?</Text>
+</Bullet>
+<Bullet>
+<Text id="0174">Compare the number of times the words "he" and "she" appear in the collection.</Text>
+</Bullet>
+<Bullet>
+<Text id="0175">How many times does the word "metadata" appear in titles? In the text itself?</Text>
+</Bullet>
+<Bullet>
+<Text id="0176">What's the difference between a <i>some</i> and an <i>all</i> search?</Text>
+</Bullet>
+<Bullet>
+<Text id="0177">What does "MODS" stand for?</Text>
+</Bullet>
+<Bullet>
+<Text id="0178">How do you switch the interface from English to Russian? Does it stay in Russian when you go to the Greenstone home page?</Text>
+</Bullet>
+<Bullet>
+<Text id="0179">Find a search term that yields different results depending on whether you have <i>ignore word endings</i> or <i>whole word must match</i> set on the Preferences page.</Text>
+</Bullet>
+<Bullet>
+<Text id="0180">What's the difference between Graphical and Textual interface format (on the Preferences page)?</Text>
+</Bullet>
+</BulletList>
+<Heading>
+<Text id="0181">Exercise: Use the How to build a digital library collection to answer these questions.</Text>
+</Heading>
+<BulletList>
+<Bullet>
+<Text id="0182">How many sentences contain the word education?</Text>
+</Bullet>
+<Bullet>
+<Text id="0183">What story from the School Journal collection is featured in the book?</Text>
+</Bullet>
+<Bullet>
+<Text id="0184">How many acronyms used in the book begin with the word Standard?</Text>
+</Bullet>
+<Bullet>
+<Text id="0185">What does tapu mean?</Text>
+</Bullet>
+<Bullet>
+<Text id="0186">How many times does the word library appear? The word libraries?</Text>
+</Bullet>
+<Bullet>
+<Text id="0187">How many times does Library appear with an initial capital letter?</Text>
+</Bullet>
+<Bullet>
+<Text id="0188">How many times does some derivative of the word form appear?</Text>
+</Bullet>
+<Bullet>
+<Text id="0189">Name an English poem that was probably written in about 1000 A.D.</Text>
+</Bullet>
+<Bullet>
+<Text id="0190">Who is Alan Kay?</Text>
+</Bullet>
+<Bullet>
+<Text id="0191">On what page is the first mention of some aspect of Chinese culture?</Text>
+</Bullet>
+</BulletList>
+<Comment>
+<Text id="0192">Most of these questions would be rather difficult to answer from the printed book.</Text>
+</Comment>
+</Content>
+</Tutorial>
+<Tutorial id="install">
+<Title>
+<Text id="0193">Installing Greenstone</Text>
+</Title>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<Heading>
+<Text id="0194">Installing Greenstone on a Windows system</Text>
+</Heading>
+<Text id="0195">There are various ways of getting Greenstone:</Text>
+<NumberedItem>
+<Text id="0196">From a UNESCO CD-ROM (version 2.60) (or FAO IMARK CD-ROM, but this is an earlier version 2.51)</Text>
+<Text id="0197">These CD-ROMs contain the <b>Greenstone software</b>, plus <b>documented example collections</b>, four <b>language interfaces</b> (English French Spanish Russian), the <b>Export to CD-ROM</b> package, the <b>ImageMagick</b> graphics package, the <b>Java runtime environment</b>, and an <b>installer</b> that installs all of these.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0198">From the IITE Digital Libraries in Education CD-ROM, or a Greenstone workshop CD-ROM</Text>
+<Comment2>
+<Text id="0199">In addition to all the above software, these CD-ROMs contain the <b>Greenstone Language Pack</b>, which gives reader's interfaces in many languages (currently about 40). This has its own installer which you have to invoke separately, after you have installed Greenstone. They also contain a set of <b>sample files</b> to be used for exercises.</Text>
+</Comment2>
+<Comment>
+<Text id="0200">All these CD-ROMs contain the full Greenstone software, which allows you to view collections and build new ones. They are not the same as CD-ROMs that contain a pre-packaged Greenstone collection, which only allow you to view that collection.</Text>
+</Comment>
+</NumberedItem>
+<NumberedItem>
+<Text id="0201">From http://www.greenstone.org</Text>
+<Text id="0202">Most people download the Windows distribution from http://www.greenstone.org, which contains the latest version of the Greenstone. There are several optional modules that must be downloaded separately (to avoid a single massive download): <b>documented example collections</b>, the <b>Export to CD-ROM</b> package, and the <b>Language Pack</b>. There is also the set of <b>sample files</b> used in these exercises. (To reduce the download size the documented example collections are distributed in unbuilt form and need to be built.)</Text>
+<Text id="0203">You need <b>Java</b> to run Greenstone. You might already have it; otherwise download it from http://java.sun.com. To work with image collections, you need <b>ImageMagick</b> (from http://www.imagemagick.org). </Text>
+</NumberedItem>
+<Text id="0204">Most Greenstone CD-ROMs start the installation process as soon as they are inserted into the drive, assuming that the AutoPlay feature is enabled on your computer. If installation does not begin by itself, locate the file <i>setup.exe</i> and double click it to start the installation process. (On the IMARK CD-ROM this file resides in the folder <i>software_tools</i>--&gt;</Text>
+<Text id="0205"><i>Greenstone</i>). If you download Greenstone over the web, what you get is the installer--just double-click it.</Text>
+<Text id="0206"><b>If Greenstone has been installed on your computer before, you should completely remove the old version before installing a new one</b>. (However, you need not remove any pre-packaged collections that you may have installed.) To do this, see below under <i>Updating a Greenstone installation</i>.</Text>
+<Text id="0207">Here is what you need to do to install Greenstone. Older versions of the installer follow much the same sequence but use slightly different wording.</Text>
+<BulletList>
+<Bullet>
+<Text id="0208">Select the language for this installation. We choose <b>English</b></Text>
+</Bullet>
+<Bullet>
+<Text id="0209">Welcome to the InstallShield Wizard for the Greenstone Digital Library Software. Click &lt;<b>Next</b>&gt;</Text>
+</Bullet>
+<Bullet>
+<Text id="0210">License Agreement. Accept the agreement and then click &lt;<b>Next</b>&gt;</Text>
+</Bullet>
+<Bullet>
+<Text id="0211">Choose location to install Greenstone. Leave at the default and click &lt;<b>Next</b>&gt;</Text>
+</Bullet>
+<Bullet>
+<Text id="0212">Setup Type. Leave at the default (Local Library) and click &lt;<b>Next</b>&gt;</Text>
+</Bullet>
+<Bullet>
+<Text id="0213">(For older installers you must now select collections. Leave at the default, Documented Example Collections, and click &lt;<b>Next</b>&gt;)</Text>
+</Bullet>
+<Bullet>
+<Text id="0214">Set admin password. Choose a suitable password and click &lt;<b>Next</b>&gt; (If your computer will not be serving collections online, the password doesn't matter)</Text>
+</Bullet>
+<Bullet>
+<Text id="0215">Click &lt;<b>Install</b>&gt; to complete the installation</Text>
+</Bullet>
+<Bullet>
+<Text id="0216">Files are copied across</Text>
+</Bullet>
+<Bullet>
+<Text id="0217">Installation is complete. If you are installing from a CD-ROM, the installer will offer to install ImageMagick (see below), and Java, if necessary.</Text>
+</Bullet>
+</BulletList>
+<Text id="0218">To invoke the Greenstone Reader's interface, go to the <i>Greenstone Digital Library Software </i>item under <i>Programs</i> on the Windows <i>Start</i> menu and select <i>Greenstone Digital Library</i>. To invoke the Librarian interface, go to the same item and select <i>Greenstone Librarian Interface</i>.</Text>
+<Heading>
+<Text id="0219">Installing ImageMagick on a Windows system</Text>
+</Heading>
+<Text id="0220">Once Greenstone has been installed, you should ensure that ImageMagick is installed on your computer if you wish to build any image collections. If you are installing from a Greenstone CD-ROM, you will be asked whether you want to install ImageMagick: say <b>Yes</b>. If you are not, you will need to download ImageMagick (from <i>http://www.imagemagick.org</i>). To install this program you must have Windows "Administrator" privileges.<FootnoteRef id="foot1"/></Text>
+<Text id="0221"> The remaining steps are straightforward, and, as before, we recommend the default settings. Here is what you need to do.</Text>
+<BulletList>
+<Bullet>
+<Text id="0222">"This will install ImageMagick 5.5.7 Q8. Do you wish to continue?" <b>Yes</b></Text>
+</Bullet>
+<Bullet>
+<Text id="0223">"Welcome to the ImageMagick Setup Wizard Click &lt;<b>Next</b>&gt;</Text>
+</Bullet>
+<Bullet>
+<Text id="0224">"Information: Please read the following âŠ" Click &lt;<b>Next</b>&gt;</Text>
+</Bullet>
+<Bullet>
+<Text id="0225">"Select Destination Directory âŠ" Leave at default and click &lt;<b>Next</b>&gt;</Text>
+</Bullet>
+<Bullet>
+<Text id="0226">"Select Start Menu Folder âŠ" Leave at default and click &lt;<b>Next</b>&gt;</Text>
+</Bullet>
+<Bullet>
+<Text id="0227">"Select Additional Tasks âŠ" Leave at default and click &lt;<b>Next</b>&gt;</Text>
+</Bullet>
+<Bullet>
+<Text id="0228">"Ready to Install". Click &lt;<b>Install</b>&gt;</Text>
+</Bullet>
+<Bullet>
+<Text id="0229">Files are copied across</Text>
+</Bullet>
+<Bullet>
+<Text id="0230">"You have now installed âŠ" Click &lt;<b>Next</b>&gt;</Text>
+</Bullet>
+<Bullet>
+<Text id="0231">"Setup has finished âŠ". Deselect "View index.html" and click &lt;<b>Finish</b>&gt;.</Text>
+</Bullet>
+</BulletList>
+<Footnote id="foot1">
+<Text id="0796"> If you do not have Windows Administrator privileges, the ImageMagick installer will give a cryptic error complaining that it failed to set a particular Windows registry value. If this happens you can continue your work with Greenstone, but you will not be able to build collections of images.</Text>
+</Footnote>
+</Content>
+</Tutorial>
+<Tutorial id="update_greenstone_installation">
+<Title>
+<Text id="0232">Updating a Greenstone installation</Text>
+</Title>
+<Prerequisite id=""/>
+<SampleFiles folder=""/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<Comment>
+<Text id="0233">These tutorial exercises assume that you are using Greenstone 2.60 or above.</Text>
+</Comment>
+<Comment>
+<Text id="0234">Before updating to a new version of Greenstone, ensure that the computer is not running the Greenstone Librarian Interface or the Greenstone local library server. Normally, quitting your web browser, or quitting the Librarian Interface, also quits the server.</Text>
+</Comment>
+<Heading>
+<Text id="0235">Removing Greenstone from a Windows system</Text>
+</Heading>
+<Comment>
+<Text id="0236">Completely remove the existing version before you install a new version of Greenstone.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0237">Ensure that you are not running Greenstone.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0238">Remove the old version by going to the Windows Control Panel (from the <i>Settings</i> item on the <i>Start</i> menu). Click <b>Add or Remove Programs</b>, select <b>Greenstone Digital Library Software</b>, and <b>Remove</b> it. (To do this you may need Windows "Administrator" privileges.) </Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0239">At the end of this procedure you will be asked whether you would like all your Greenstone collections to be removed: you should probably say <i>No</i> if you wish to preserve your work.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0240">Occasionally, problems are encountered if older Greenstone installations are not fully removed. To clean up your system, move your Greenstone collect folder, which contains all your collections, to the desktop. Then check for the folder C:\Program Files\gsdl or C:\Program Files\Greenstone, which is where Greenstone is usually installed, and remove it completely if it exists.</Text>
+</Comment>
+<Heading>
+<Text id="0241">Reinstalling Greenstone on a Windows system</Text>
+</Heading>
+<NumberedItem>
+<Text id="0242">The reinstallation procedure is exactly the same as the original installation procedure, described above. If you already have ImageMagick, you do not need to install it again.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0243">There have been some superficial changes to the installation procedure in moving to Greenstone Version 2.60, because it uses a different installer program. </Text>
+</Comment>
+<Comment>
+<Text id="0244">There is another important difference that you should be aware of: Versions 2.60 and above are installed in the folder Program Files\Greenstone, whereas prior versions were placed in the folder Program Files\gsdl (these are both default locations that you could have changed during installation.) When upgrading to Version 2.60, if you want to save existing collections you must explicitly move the contents of your collect folder from the old place to the new one. Future Greenstone versions will be installed in the new place, Program Files\Greenstone, so this problem will not happen again.</Text>
+</Comment>
+<Heading>
+<Text id="0245">Amalgamating different Greenstone collections</Text>
+</Heading>
+<NumberedItem>
+<Text id="0246">If you have previously installed the Greenstone Digital Library software in a non-standard place, you should amalgamate your collections by moving them from the <i>collect</i> folder in the old place into the folder <i>Program Files\Greenstone\collect</i>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0247">If you have installed collections from pre-packaged Greenstone CD-ROMs, they reside in a different place: <i>C:\GSDL\collect</i>. To amalgamate these with your main Greenstone installation, move them into the folder <i>Program Files\Greenstone\collect</i>. The mini version of Greenstone that is associated with the pre-packaged collections is no longer necessary. To uninstall it, select <i>Uninstall</i> on the Greenstone menu of the Windows <i>Start</i> menu.</Text>
+</NumberedItem>
+<Heading>
+<Text id="0248">Installing the Greenstone language pack</Text>
+</Heading>
+<Comment>
+<Text id="0249">If you go to the Preferences page of any Greenstone collection, and look at the <b>Interface language</b> menu, you will probably find that only English, Spanish, French and Russian interfaces are installed.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0250">Locate the Greenstone Language Pack. This may be on the CD-ROM from which you installed Greenstone, or you may have to download it from <i>http://www.greenstone.org</i>. </Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0251">Double-click the <i>.exe</i> file; this will start the installer. Accept all the defaults</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0252">Restart the Greenstone Digital Library and look at the interface language menu again. Now you should see about 40 different languages.</Text>
+</NumberedItem>
+</Content>
+</Tutorial>
+<Tutorial id="small_html_collection">
+<Title>
+<Text id="0253">Building a small collection of HTML files</Text>
+</Title>
+<Prerequisite id=""/>
+<SampleFiles folder="hobbits"/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<Comment>
+<Text id="0254">You will need some HTML files, such as those in the hobbits folder in sample_files. You can download the sample files that are used in these exercises from http://www.greenstone.org.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0255">Start the Greenstone Librarian Interface:</Text>
+<Menu>
+Start--&gt;All Programs--&gt;Greenstone Digital Library Software--&gt;Greenstone Librarian Interface
+</Menu> 
+<Comment2>
+<Text id="0256">After a short pause a startup screen appears, and then after a slightly longer pause the main Greenstone Librarian Interface appears.</Text>
+</Comment2>
+</NumberedItem>
+<NumberedItem>
+<Text id="0257">Start a new collection within the Librarian Interface:</Text>
+<Text id="0258">File--&gt;</Text>
+<Text id="0259">New</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0260">You will create a collection based on a few HTML web pages that describe some Hobbits in <i>Lord of the Rings</i>.</Text>
+<Text id="0261">A window pops up. Fill it out with appropriate values--for example,</Text>
+<Indent>
+<Text id="0261a">Collection Title: About Hobbits<br/></Text>
+<Text id="0261b">Description of Content: A collection about hobbits.</Text>
+</Indent>
+<Text id="0262">Leave the setting for <b>Base this collection on:</b> at its default <b>New Collection,</b> and click <b>&lt;OK&gt;</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0263">Another window pops up, from which you select the metadata set (or sets) to use. This is discussed in other exercises. For now, select <b>Dublin Core Metadata Element Set Version 1.1 </b>followed by <b>&lt;OK&gt;</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0264">Next you must gather together the files that will constitute the collection. A suitable set has been prepared ahead of time in <i>sample_files</i> in the folder <i>hobbits</i>. Using the left-hand side of the Librarian Interface's <b>Gather</b> panel, interactively navigate to the <i>sample_files</i> folder. </Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0265">Now drag the <i>hobbits</i> folder from the left-hand side and drop it on the right. The progress bar at the bottom shows some activity. Gradually, duplicates of all the files will appear in the right-hand panel.</Text>
+<Comment2>
+<Text id="0266">You can inspect the files that have been copied by double-clicking on the folder in the right-hand side.</Text>
+</Comment2>
+</NumberedItem>
+<NumberedItem>
+<Text id="0267">Since this is our first collection, we won't complicate matters by manually assigning metadata or altering the collection's design. Instead we rely on default behaviour. So pass directly to the <b>Create</b> panel by clicking the <b>Create </b>tab.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0268">To start building the collection, click the <b>&lt;Build Collection&gt;</b> button.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0269">Once the collection has built successfully, a window pops up to confirm this. Click <b>&lt;OK&gt;</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0270">Click the <b>Preview Collection</b> button to look at the end result. This loads the relevant page into your web browser (starting it up if necessary). Look around the collection and learn about Hobbits!</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0271">Back in the Librarian Interface, click the <b>Enrich</b> tab to view the metadata associated with the documents in the collection. </Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0272">Presently there is no manually assigned metadata, but the act of building the collection has extracted metadata from the documents. Double click the <i>hobbits</i> folder to expand its content. Then single-click <i>bilbo.html</i> to display all its metadata in the right-hand side of the panel. The initial fields, starting "dc.", are empty. These are Dublin Core metadata fields (we asked you to include this metadata set when the collection was initially formed) for manually entered data.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0273">Use the scroll bar on the extreme right to view the bottom part of the list. There you will see fields starting "ex." that express the extracted metadata: for example <i>ex.Title</i>, based on the text within the HTML Title tags, and <i>ex.Language</i>, the document's language (represented using the ISO standard 2-letter mnemonic) which is set by an algorithm that Greenstone uses to analyse the document's text.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0274">Close the collection by clicking <b>File</b>--&gt;</Text>
+<Text id="0275"><b>Close</b></Text>
+<Text id="0276">. This automatically saves the collection to disk.</Text>
+</NumberedItem>
+<Heading>
+<Text id="0277">Setting up a shortcut in the Librarian interface</Text>
+</Heading>
+<NumberedItem>
+<Text id="0278">To set up a shortcut to the source files, return to the Gather panel and navigate to the folder in your local file space that contains the files you want to use--in our case, the <i>sample_files</i> folder. Select this folder and then right-click it. Follow the instructions to set up a shortcut. Close all the folders in the file tree and you will see the shortcut to your source files in the left-hand pane of the Gather panel.</Text>
+</NumberedItem>
+</Content>
+</Tutorial>
+<Tutorial id="word_PDF_collection">
+<Title>
+<Text id="0279">A collection of Word and PDF files</Text>
+</Title>
+<Prerequisite id=""/>
+<SampleFiles folder=""/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<Comment>
+<Text id="0280">You will need some source files like those in the sample_files\Word_and_PDF folder.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0281">Start a new collection called <b>reports</b>, fill out appropriate fields for it, and choose Dublin Core as the metadata set.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0282">Copy the 12 files from <i>sample_files</i>--&gt;</Text>
+<Text id="0283"><i>Word_and_PDF</i>--&gt;</Text>
+<Text id="0284"><i>Documents</i></Text>
+<Text id="0285"> into the collection. You can select multiple files by clicking on the first one and shift-clicking on the last one, and drag them all across together. </Text>
+<Text id="0286">(This is the normal technique of multiple selection.)</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0287">Switch to the <b>Create</b> panel, and <b>build</b> and <b>preview</b> the collection.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0288">Again, this collection contains no manually assigned metadata. All the information that appears--title and filename--is extracted automatically from the documents themselves. Because of this the quality of some of the title metadata is suspect.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0289">Back in the Librarian Interface, click the <b>Enrich</b> tab to view the automatically extracted metadata. You will need to scroll down to see the extracted metadata, which begins with "ex.".<i> </i>The PostScript documents (<i>cluster.ps</i> and <i>langmodl.ps</i> do not have extracted titles: what appears in the <i>titles a-z </i>list is just the first few characters of the document).</Text>
+</NumberedItem>
+<Heading>
+<Text id="0290">Manually adding metadata to documents in a collection</Text>
+</Heading>
+<NumberedItem>
+<Text id="0291">In the <b>Enrich</b> panel, manually add Dublin Core <i>dc.Title</i> metadata to one of these documents. Select <i>word03.doc</i> and double-click to open it in Word. Copy the title of this document ("Greenstone: A comprehensive open-source digital library software system") from Word, return to the Librarian Interface, click the <i>dc.Title</i> field, and paste the value into the Value box. Click &lt;<b>Append</b>&gt;.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0292">Now add <i>dc.Creator</i> information for the same document. You can add more than one value for the same field, to accommodate multiple authors--just put in the next value and click &lt;<b>Append</b>&gt;.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0293">Next add title and creator metadata for a few of the other documents.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0294">If you build and preview your collection at this point, you will find that nothing has changed. You need to alter the collection design to use the new Dublin Core metadata instead of the original extracted metadata.</Text>
+</Comment>
+<Heading>
+<Text id="0295">Collection design; branding a collection with an image</Text>
+</Heading>
+<NumberedItem>
+<Text id="0296">Change to the <b>Design</b> panel, which is split into several sections. The first section <b>General Options</b> appears. This allows you to modify the values you provided when defining the collection, if desired. You can also brand the collection using a suitable image.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0297">Click on the &lt;<b>Browse</b>&gt; button associated with "URL to about page icon", and browse to the image </Text>
+<Text id="0298"><i>sample_files</i>--&gt;</Text>
+<Text id="0299"><i>Word_and_PDF</i>--&gt;</Text>
+<Text id="0300"><i>wrdpdf.gif</i> on your computer. When you select this image, Greenstone automatically generates an appropriate URL for the image.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0301">If you are on the web, you can easily make your own Greenstone-style icon by going to</Text>
+<Indent>
+http://www.greenstone.org/make-images.html
+</Indent> 
+<Text id="0302">and following the instructions there.</Text>
+</NumberedItem>
+<Heading>
+<Text id="0303">Document plugins</Text>
+</Heading>
+<NumberedItem>
+<Text id="0304">Now look at the <b>Document Plugins</b> section, by clicking on this in the list to the left. Here you can add, configure or remove plugins to be used in the collection. There is no need to remove any plugins, but it will speed up processing a little. In this case we have only Word, PDF, RTF, and PostScript documents, and can remove the ZIPPlug, TEXTPlug, HTMLPlug, EMAILPlug ImagePlug and NULPlug plugins. To delete a plugin, select it and click &lt;<b>Remove Plugin</b>&gt;. GAPlug is required for any type of source collection and should not be removed. </Text>
+</NumberedItem>
+<Heading>
+<Text id="0305">Search types and fielded searching</Text>
+</Heading>
+<NumberedItem>
+<Text id="0306">Go to the <b>Search Types</b> section. This specifies what kind of search interface and what search indexes will be provided for the collection. Let's add a form search option. Click &lt;<b>Enable Advanced Searches</b>&gt;; this includes "form search" in the collection.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0307">To include "plain search" as well, pull down the <b>Search Types</b> menu and select <b>plain</b>; then click &lt;<b>Add Search Type</b>&gt;.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0308">To set plain search as the default type, click on <b>plain</b>, then click &lt;<b>Move Up</b>&gt;. The first one in the list will be the default.</Text>
+</NumberedItem>
+<Heading>
+<Text id="0309">Search indexes</Text>
+</Heading>
+<NumberedItem>
+<Text id="0310">The next step in the <b>Design</b> panel is <b>Search Indexes</b>. These specify what parts of the collection are searchable (e.g. searching by title and author). Delete the <i>ex.Title</i> and <i>ex.Source</i> indexes, which are not particularly useful, by selecting them one at a time and clicking &lt;<b>Remove Index</b>&gt;. Only the <i>text</i> index remains.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0311">Now add a Title index based on <i>dc.Title</i> by providing an <b>Index Name </b>(e.g. "Document Title") and selecting <i>dc.Title</i> from the <b>Index Source</b> box. Then click &lt;<b>Add Index</b>&gt;.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0312">You can add indexes based on any metadata. Add an index called "Authors" based on <i>dc.Creator</i> metadata.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0313">The next two sections are <b>Partition Indexes</b> and <b>Cross-Collection Search</b>. In this exercise, we will not make any changes to these.</Text>
+</Comment>
+<Heading>
+<Text id="0314">Browsing classifiers</Text>
+</Heading>
+<NumberedItem>
+<Text id="0315">The <b>Browsing Classifiers</b> section adds "classifiers," which provide the collection with browsing functions. Go to this section and observe that Greenstone has provided two classifiers, <i>AZLists</i> based on <i>ex.Title</i> and <i>ex.Source</i> metadata. Remove both of these by selecting them in turn and clicking &lt;<b>Remove Classifier</b>&gt;. </Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0316">Now we add an <i>AZList</i> classifier for <i>dc.Title</i> metadata. Select <i>AZList</i> from the <b>Select classifier to add</b> drop-down list and click &lt;<b>Add Classifier</b>&gt;</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0317">A popup window <b>Configuring Arguments</b> appears. Select <i>dc.Title</i> from the <b>metadata</b> drop-down list, and check the <b>button name</b> checkbox to provide a button name; call it "Title". Now click &lt;<b>OK</b>&gt;.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0318">Now add an <i>AZCompactList</i> classifier. Click &lt;<b>Add Classifier</b>&gt; and configure it to use <i>dc.Creator</i> metadata, with button name "Creator". Check the <b>mingroup</b> box and select 1 (to group all publications by the same author under a single bookshelf icon). Click &lt;<b>OK</b>&gt;.</Text>
+<Comment>
+<Text id="0319">The last three sections are <b>Format Features</b>, <b>Translate Text</b> and <b>Metadata Sets</b>. In this exercise, we will not make any changes to these.</Text>
+</Comment>
+</NumberedItem>
+<NumberedItem>
+<Text id="0320">Switch to the <b>Create</b> panel, and <b>build</b> and <b>preview</b> the collection.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0321">Check that all the facilities work properly. There should be three full-text indexes, called <i>text</i>, <i>Document Title</i>, and <i>Authors</i>. In the <i>titles a-z</i> list should appear all the documents to which you have assigned <i>dc.Title</i> metadata (and only those documents). In the <i>authors aÂ­-z</i> list should appear one bookshelf for each author you have assigned as <i>dc.Creator</i>, and clicking on that bookshelf should take you to all the documents they authored.</Text></NumberedItem>
+<Comment>
+<Text id="0322">At this point you might like to publish the collection on CD-ROM, See below under "Exporting a collection to CD-ROM" for how to do this.</Text>
+</Comment>
+</Content>
+</Tutorial>
+<Tutorial id="difficult_PDF">
+<Title>
+<Text id="0323">Difficult PDF documents</Text>
+</Title>
+<Prerequisite id=""/>
+<SampleFiles folder=""/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<NumberedItem>
+<Text id="0324">Build a fresh Greenstone collection from the two files in <i>sample_files\difficult_documents.</i> Use the default collection configuration: that is, simply gather the files into a new collection, and build it.</Text>
+<Comment>
+<Text id="0325">These files are called No extractable text.pdf and Weird characters.pdf--their names hint at the problems they will cause!</Text>
+</Comment>
+</NumberedItem>
+<NumberedItem>
+<Text id="0326">Now preview the collection. The titles and filenames lists show only one of the documents. When you click the "text" icon to look at the text extracted from that document, it's garbage. During the building process this message appeared: "One document was processed and included in the collection; one was rejected."</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0327">These problems can be overcome by an option to PDFPlug. Greenstone can convert PDF files into a series of images with a corresponding file that details how they are composed into the complete document (called an <i>item</i> file). For this part of the exercise, ImageMagick needs to be installed (see exercise 3 on Installing Greenstone).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0328">In the <b>Document Plugins</b> list in the <b>Design</b> panel, double-click <b>PDFPlug </b>to pop up a window that shows its settings, and set the <b>convert_to</b> option to <i>pagedimg_gif</i>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0329"><b>Build</b> the collection and <b>preview </b>it. Both PDF documents have been processed and divided into pages, but each page displays "This document has no text" because when converting PDF documents to images, no text is extracted.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0330" funky="1">In order to view the documents properly we need to modify a format statement. In the <b>Format Features</b> section on the <b>Design</b> panel, select the <b>DocumentText</b> format statement. Replace:<Format>[Text]</Format></Text>
+<Text id="0331">with</Text>
+<Format>[srcicon]</Format>
+</NumberedItem>
+<NumberedItem>
+<Text id="0332"><b>Preview</b> the collection from the <b>Create</b> panel. (There is no need to build it). Images from the documents are now displayed instead of the extracted text. Both <i>No extractable text.pdf</i> and <i>Weird characters.pdf</i> display nicely now. </Text>
+</NumberedItem>
+<Heading>
+<Text id="0333">Modes in the Librarian Interface</Text>
+</Heading>
+<Comment>
+<Text id="0334">The Librarian Interface can operate in different modes. So far, you have been using the default mode, called "Librarian." </Text>
+</Comment>
+<NumberedItem>
+<Text id="0335">Use the <i>Preferences</i> item on the <i>File</i> menu to switch to <i>Expert</i> mode and then build the collection again. The <b>Create</b> panel looks different in Expert mode because it gives more options: locate the <b>Build Collection</b> button, near the bottom of the window, and click it. Now a message appears saying that the file could not be processed, and why.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0336">We recommend that you switch back to <i>Librarian</i> mode for subsequent exercises, to avoid confusion.</Text>
+</NumberedItem>
+</Content>
+</Tutorial>
+<Tutorial id="simple_image">
+<Title>
+<Text id="0337">A simple image collection</Text>
+</Title>
+<Prerequisite id=""/>
+<SampleFiles folder=""/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<NumberedItem>
+<Text id="0338">Start a new collection (File--&gt;</Text>
+<Text id="0339">New) called <b>backdrop</b>. Fill out the fields with appropriate information. For <b>Base this collection on</b>, select the item <b>Simple image collection (image-e)</b> from the pull-down menu.</Text>
+<Comment>
+<Text id="0340">Greenstone does not ask you to choose a metadata set because the new collection inherits whatever is used by the base collection.</Text>
+</Comment>
+</NumberedItem>
+<NumberedItem>
+<Text id="0341">Copy the images provided in <i>sample_files\images</i> into your newly-formed collection.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0342">Change to the <b>Create </b>panel and <b>build</b> the collection.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0343"><b>Preview</b> the result.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0344">Click &lt;<b>browse&gt;</b> in the navigation bar to view a list of the photos ordered by filename and presented as a thumbnail accompanied by some basic data about the image. The structure of this collection is the same as <b>Simple image collection (image-e)</b>, but the content is different.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0345">Change to the <b>Enrich</b> panel and view the extracted metadata for <i>Ascent.jpg</i>.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0346">We now add our own metadata and use it to give users a new way to browse the collection. We use the Dublin Core metadata set.</Text>
+</Comment>
+<Heading>
+<Text id="0347">Adding a metadata set to the collection</Text>
+</Heading>
+<NumberedItem>
+<Text id="0348">The collection (image-e) on which <b>backdrop</b> is based uses only extracted metadata. To add another metadata set, go to the <b>Design</b> panel of the Librarian Interface and click &lt;<b>Metadata Sets</b>&gt; in the list on the left (the last one). Then click<b> &lt;Add Metadata Set</b>&gt; (lower left button).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0349">In the window that pops up, select <b>dublin.mds </b>and click &lt;<b>Add Metadata Set</b>&gt;.</Text>
+</NumberedItem>
+<Heading>
+<Text id="0350">Adding Title metadata</Text>
+</Heading>
+<NumberedItem>
+<Text id="0351">Now switch to the <b>Enrich</b> panel by clicking this tab. The metadata for each file now shows the Dublin core <i>dc.</i> fields as well as the extracted <i>ex.</i> fields.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0352">We work with just the first three files (<i>Ascent.jpg</i>, <i>Autumn.jpg </i>and <i>Azul.jpg</i>) to get a flavour of what is possible. First, set each file's <b>dc.Title</b> field to be the same as its filename but without the filename extension.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0353">Click on <b><i>Ascent.jpg </i></b>so its metadata fields are available, then click on its <b>dc.Title </b>field on the right-hand side. Click on the <b>Value </b>text box, enter <b>Ascent</b>, and click <b>&lt;Append&gt;</b>.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0354">The <b>All Previous Values </b>box will become more useful when more entries have been added.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0355">Repeat the process for <b>Autumn.jpg </b>and <b>Azul.jpg</b>.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0356">Now we customize the collection's appearance. Building or previewing the collection at this point won't reveal anything new. That's because we haven't changed the design of the collection to take advantage of the new metadata.</Text>
+</Comment>
+<Heading>
+<Text id="0357">Change Format Features to display new metadata</Text>
+</Heading>
+<NumberedItem>
+<Text id="0358">Go to the <b>Design</b> panel (by clicking on its tab) and select <b>Format Features </b>from the left-hand list. Leave the <b>Editing Controls </b>at their default value, so that <b>Choose Feature </b>remains blank and <b>VList </b>is selected as the <b>Affected Component</b>. In the <b>HTML Format String</b>, edit the text as follows:</Text>
+<Indent>
+<Text id="0359">Change "_ImageName_:" to "Title:" <br/> Change "[Image]" to "[dc.Title]"</Text>
+</Indent>
+<Comment>
+<Text id="0360">Metadata names are case-sensitive in Greenstone: it is important that you capitalize "Title" (and don't capitalize "dc").</Text>
+</Comment></NumberedItem>
+<NumberedItem>
+<Text id="0361">Next click <b>&lt;Replace Format&gt;</b>. The first of the above changes alters the fragment of text that appears to the right of the thumbnail image, the second alters the item of metadata that follows it.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0362">Go to the <b>Create</b> panel and click <b>&lt;Build Collection&gt;</b>. Now <b>preview </b>the collection. When you click on <b>browse</b> in the navigation bar the presentation has changed to "Title: Ascent" and so on.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0363">Because we only assigned metadata to the first three items, after this the title becomes blank because the subsequent items have no dc.Title metadata. To get a full listing, enter all the metadata.</Text>
+</Comment>
+<Comment>
+<Text id="0364">For some design parameters the collection must be rebuilt before the effect of changes can be seen. However, changes to format statements take place immediately and you can see the result straightaway by clicking <b>reload </b>in the web browser.</Text>
+</Comment>
+<Heading>
+<Text id="0365">Changing the size of image thumbnails</Text>
+</Heading>
+<NumberedItem>
+<Text id="0366">Thumbnail images are created by the <i>ImagePlug</i> plug-in, so we need to access its configuration settings. To do this, switch to the <b>Design</b> panel and select <b>Document Plugins</b> from the list on the left. Double-click <b>plugin ImagePlug</b> to pop up a window that shows its settings. (Alternatively, select <b>ImagePlug </b>with a single click and then click <b>&lt;Configure Plugin&gt; </b>further down the screen). Currently all options are off, so standard defaults are used. Select <b>thumbnailsize</b>, set it to <b>50</b>, and click <b>&lt;OK&gt;</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0367"><b>Build </b>and <b>preview </b>the collection.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0368">Once you have seen the result of the change, return to the <b>Design</b> panel, select the configuration options for <i>ImagePlug</i>, and switch the thumbnail size option off so that the thumbnail reverts to its normal size when the collection is re-built.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0369">Now add metadata that describes the photos in the collection. Again, for illustration, we focus on the first three images (Ascent.jpg, Autumn.jpg and Azul.jpg).</Text>
+</Comment>
+<Heading>
+<Text id="0370">Adding Description metadata</Text>
+</Heading>
+<NumberedItem>
+<Text id="0371">Switch to the <b>Enrich</b> panel and select <i>Ascent.jpg</i>. We'll store our description in the <b>dc.Description </b>metadata element, so select it now in the right-hand panel.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0372">What description should you enter? To remind yourself of a file's content, the Librarian Interface lets you open files by double-clicking them. It launches the appropriate application based on the filename extension, Word for .doc files, Acrobat for .pdf files and so on. Double-click Ascent.jpg: the image will normally be displayed by Microsoft's Photo Editor (although this depends on how your computer has been set up).</Text>
+</Comment>
+<NumberedItem>
+<Text id="0373">Back in the Librarian Interface enter the text <b>Moon rising over mountain landscape </b>as the <b>dc.Description </b>field's value and click <b>&lt;Append&gt; </b>to have it added.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0374">Repeat this process for <i>Autumn.jpg </i>and <i>Azul.jpg</i>, adding a suitable description for each.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0375">Build the collection again, to incorporate the new metadata.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0376">Now update the format statement to use the new <b>dc.Description </b>metadata. Switch to the <b>Design </b>panel and enter the <b>Format Features </b>section by selecting this from the list of names on the left-hand size and ensure <b>VList</b> is selected. In the <b>HTML Format String</b>, place your cursor after the text that says</Text>
+<Format>[dc.Title]&lt;br&gt;</Format> 
+</NumberedItem>
+<NumberedItem>
+<Text id="0377">and add the following text:</Text>
+<Format>Description: [dc.Description]&lt;br&gt;</Format> 
+</NumberedItem>
+<NumberedItem>
+<Text id="0378">Then click <b>&lt;Replace Format&gt;</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0379"><b>Preview</b> the result (you don't need to build the collection as was done in step 22 to incorporate the metadata, because changes to format statements take effect immediately). Each image's description should appear beside the thumbnail, following the title.</Text>
+</NumberedItem>
+<Heading>
+<Text id="0380">Adding a browsing classifier based on Description metadata</Text>
+</Heading>
+<NumberedItem>
+<Text id="0381">Switch to the <b>Design</b> panel and select <b>Browsing Classifiers </b>from the left-hand list. Set the menu item for <b>Select classifier to add </b>to <b>AZList</b>; then click &lt;<b>Add Classifier</b>&gt;.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0382">A window pops up to control the classifier's options. Set the menu item for metadata to <b>dc.Description</b> and click <b>&lt;OK&gt;</b>. Now switch to the <b>Create </b>panel, <b>build </b>the collection, and <b>preview </b>it. Choose the new <b>descriptions </b>link that appears in the navigation bar.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0383">Only three items are shown, because only items with the relevant metadata (dc.Description in this case) appear in the list. The original browse list includes all photos in the collection because it is based on ex.Image, extracted metadata that reflects an image's filename, which is set for all images in the collection.</Text>
+</Comment>
+<Heading>
+<Text id="0384">Creating a searchable index based on Description metadata</Text>
+</Heading>
+<NumberedItem>
+<Text id="0385">Switch to the <b>Design </b>panel and select <b>Search Indexes </b>from the left-hand list. Enter the text "descriptions" as the <b>Index Name</b>, select <b>dc.Description </b>and click <b>&lt;Add Index&gt;</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0386">Switch to the <b>Create </b>panel, <b>build </b>the collection, then <b>preview </b>it. As an example, search for the term "mountain" in the <i>descriptions</i> index.</Text>
+</NumberedItem>
+</Content>
+</Tutorial>
+<Tutorial id="large_html_collection">
+<Title>
+<Text id="0387">A large collection of HTML files--Tudor</Text>
+</Title>
+<Prerequisite id=""/>
+<SampleFiles folder=""/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<NumberedItem>
+<Text id="0388">Invoke the Greenstone Librarian Interface (from the Windows <i>Start</i> menu) and start a new collection called <b>tudor</b> (use the <i>File</i> menu). Fill out the pop-up dialog with appropriate values and leave <b>Dublin Core</b>, which is selected by default, as the metadata set.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0389">In the <b>Gather</b> panel, open the <i>tudor </i>folder in <i>sample_files</i>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0390">Drag <i>englishhistory.net </i>from the left-hand side to the right to include it in your <b>tudor</b> collection.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0391">Switch to the <b>Create</b> panel and click <b>&lt;Build Collection&gt;</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0392">When building has finished, <b>preview</b> the collection.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0393">The browsing facilities in this collection (<i>titles a-z</i> and <i>filenames</i>) are based entirely on extracted metadata. Return to the Librarian Interface and examine the metadata that has been extracted for some of the files.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0394">You've probably noticed that the collection contains a few stray image files, as well as the HTML documents. This is a mistake. The issue is that many of the HTML documents include images, and although Greenstone attempts to determine which images belong to HTML pages and only considers other images for inclusion in the collection, in this case it hasn't been completely successful. (This is because the web site from which these files were downloaded occasionally departs from the usual convention of hierarchical structuring.)</Text>
+</Comment>
+<NumberedItem>
+<Text id="0395">Switch to the <b>Design</b> panel and select the <b>Document Plugins</b> section. Beside <b>plugin HTMLPlug</b> you will see <i>-smart_block</i>. This is the option that attempts to identify images in the HTML pages and block them from inclusion--in this case, it's not smart enough! Select the <b>plugin HTMLPlug</b> line and click &lt;<b>Configure Plugin&gt;</b>. A popup window appears. Scroll down the page to locate the <b>smart_block</b> option and switch it off. Click &lt;<b>OK&gt;</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0396">Switch to the <b>Create</b> panel and <b>build</b> and <b>preview</b> the collection. The collection is exactly as before except that these stray images are suppressed. What is happening is that plug-ins operate as a pipeline: files are passed to each one in turn until one is found that can process it. By default (i.e. without <i>smart_block</i>) the HTML plug-in blocks <i>all</i> images, which is appropriate for this collection.</Text>
+</NumberedItem>
+<Heading>
+<Text id="0397">Looking at different views of the files in the Gather and Enrich panels</Text>
+</Heading>
+<NumberedItem>
+<Text id="0398">Switch to the <b>Gather</b> panel and in the right-hand side open <i>englishhistory.net </i>--&gt;</Text>
+<Text id="0399"> <i>tudor</i>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0400">Change the <b>Show Files</b> menu for the right-hand side from <b>All Files</b> to <b>HTM &amp; HTML</b>. Notice the files displayed above are filtered accordingly, to show only files of this type.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0401">Change the <b>Show Files</b> menu to <b>Images</b>. Again, the files shown above alter.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0402">Now return the <b>Show Files</b> setting back to <b>All Files</b>, otherwise you may get confused later. Remember, if the <b>Gather</b> or <b>Enrich</b> panels do not seem to be showing all your files, this could be the problem.</Text>
+</NumberedItem>
+</Content>
+
+</Tutorial>
+<Tutorial id="export_to_CDROM">
+<Title>
+<Text id="0403">Exporting a collection to CD-ROM</Text>
+</Title>
+<Prerequisite id=""/>
+<SampleFiles folder=""/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<Comment>
+<Text id="0404">To publish a collection on CD-ROM, Greenstone's Export to CD-ROM export module must be installed (see above, under "Installing Greenstone").</Text>
+</Comment>
+<NumberedItem>
+<Text id="0405">Launch the Greenstone Librarian Interface if it is not already running.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0406">Choose <b>File</b>--&gt;</Text>
+<Text id="0407"><b>Write CD/DVD image</b>, and in the popup window select the <b>tudor</b> collection as the collection to export. You can optionally name the CD-ROM; otherwise the default "collections" is used. Do so now, entering "Tudor collection" in the field for <b>CD/DVD name</b>; then click <b>&lt;Write CD/DVD image&gt;</b>.</Text>
+<Text id="0408">The necessary files for export are written to:</Text>
+<Indent>
+C:\Program Files\Greenstone\tmp\exported_Tudorcollection
+</Indent> 
+<Text id="0409">You need to use your own computer's software to write these on to CD-ROM. On WindowsXP this ability is built into the operating system: assuming you have a CD-ROM or DVD writer insert a blank disk into the drive and drag the contents of <i>exported_Tudorcollection</i> into the folder that represents the disk.</Text>
+<Comment2>
+<Text id="0410">The result will be a self-installing Greenstone CD-ROM, which starts the installation process as soon as it is placed in the drive.</Text>
+</Comment2>
+</NumberedItem>
+</Content>
+</Tutorial>
+<Tutorial id="downloading_from_internet">
+<Title>
+<Text id="0411">Downloading files from the web</Text>
+</Title>
+<Prerequisite id=""/>
+<SampleFiles folder=""/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<Comment>
+<Text id="0412">The Greenstone Librarian Interface's Download panel allows you to download individual files, parts of websites, and indeed whole websites, from the web.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0413">Start a new collection called <b>webtudor</b>, and base it on the <b>tudor</b> collection.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0414">In a web browser, visit <i>http://englishhistory.net</i>, follow the link to <i>Tudor England</i>, and click &lt;<b>enter</b>&gt;. You should be at the URL</Text>
+<Indent>
+http://englishhistory.net/tudor/contents.html
+</Indent> 
+<Text id="0415">This is where we started the downloading process to obtain the files you have been using for the <b>tudor</b> collection.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0416">You could do the same thing by copying this URL from the web browser, pasting it into the <b>Download </b>panel, and clicking the &lt;<b>Download&gt;</b> button. However, several megabytes will be downloaded, which might strain your network resources--or your patience! For a faster exercise we focus on a smaller section of the site. In the <b>Download</b> panel, enter this URL</Text>
+<Indent>
+http://englishhistory.net/tudor/monarchs/edward6.html
+</Indent> 
+<Text id="0417">into the <b>Source URL</b> box. There are several options that govern how the download process proceeds. To copy the <i>monarchs </i>section of the website, select <b>Only mirror files below this URL</b>. If you don't do this, the downloading process will follow links to other areas of the <i>englishhistory.net</i> website and grab those as well. Set <b>Download</b> <b>depth</b> to <b>Unlimited</b>-we want to follow as many links as necessary to download all the pages.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0418">Now click &lt;<b>Download&gt;</b>. A progress bar appears in the lower half of the panel that reports on how the downloading process is doing.</Text>
+<Comment2>
+<Text id="0419">More detailed information can be obtained by clicking &lt;<b>View Log&gt;</b>. The process can be paused and restarted as needed, or stopped altogether by clicking &lt;<b>Close&gt;</b>. Downloading can be a lengthy process involving multiple sites, and so Greenstone allows additional downloads to be queued up. When new URLs are pasted into the Source URL box and &lt;<b>Download&gt;</b> clicked, a new progress bar is appended to those already present in the lower half of the panel. When the currently active download item completes, the next is started automatically.</Text>
+</Comment2>
+</NumberedItem>
+<NumberedItem>
+<Text id="0420">Downloaded files are stored in a top-level folder called <b>Downloaded Files</b> that appears on the left-hand side of the <b>Gather</b> panel. You may not need all the downloaded files, and you choose which you want by dragging selected files from this folder over into the collection area on the right-hand side, just like we have done before when selecting data from the <i>sample_files</i> folder. In this example we will include everything that has been downloaded.</Text>
+<Text id="0421">Select the <b>englishhistory.net</b> folder within <b>Downloaded Files</b> and drag it across into the collection area.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0422">Switch to the <b>Create</b> panel to <b>build</b> and <b>preview</b> the collection. It is smaller than the previous collection because we included only the <i>monarchs</i> files. However, these now represent the latest versions of the documents.</Text>
+</NumberedItem>
+</Content>
+</Tutorial>
+<Tutorial id="web_linking">
+<Title>
+<Text id="0423">Pointing to documents on the web</Text>
+</Title>
+<Prerequisite id="downloading_from_internet"/>
+<SampleFiles folder=""/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<NumberedItem>
+<Text id="0424">Open up your <b>webtudor</b> collection, and in the <b>Gather</b> panel inspect the files you dragged into it. The first folder is <i>englishhistory.net</i>, which opens up to reveal <i>tudor</i>, and so on. The files represent a complete sweep of the pages (and supporting images) that constitute the <i>Tudor monarchs</i> section of the <i>englishhistory.net</i> web site. They were downloaded from the web in a way that preserved the structure of the original site. This allows any page's original URL to be reconstructed from the folder hierarchy.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0425">In the <b>Design</b> panel, select the <b>Document Plugins</b> section, then select the <b>plugin HTMLPlug</b> line and click &lt;<b>Configure Plugin&gt;</b>. A popup window appears. Locate the <b>file_is_url</b> option (about halfway down the first block of items) and switch it on. Click &lt;<b>OK&gt;</b>.</Text>
+<Text id="0426">Setting this option to the HTMLPlug means that Greenstone sets an additional piece of metadata for each document called URL, which gives its original URL.</Text>
+<Text id="0427">It is important that the files gathered in the collection start with the web domain name (<i>englishhistory.net</i> in this case). The conversion process will not work if you dragged over a subfolder, for example the <i>tudor</i> folder, because this will set URL metadata to something like</Text>
+<Indent>
+http://tudor/monarchs/...
+</Indent> 
+<Text id="0428">rather than</Text>
+<Indent>
+http://englishhistory.net/tudor/monarchs/...
+</Indent> 
+<Text id="0429">If you have copied over a subfolder previously, delete it and make a fresh copy. Drag the folder in the right-hand side of the <b>Gather</b> panel on to the trash can in the lower right corner. Then obtain a fresh copy of the files by dragging across the <i>englishhistory.net</i> folder from the Downloaded Files folder on the left-hand side.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0430">To make use of the new URL metadata, the icon link must be changed to serve up the original URL rather than the copy stored in the digital library. Go to the <b>Design</b> panel, select the <b>Format Features</b> section and edit the <b>VList</b> format statement by replacing</Text>
+<Format>[link][icon][/link]</Format>
+<Text id="0431">with</Text>
+<Format>[weblink][webicon][/weblink]</Format>
+<Text id="0432">Click &lt;<b>Replace Format&gt;</b> to commit the change.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0433">Switch to the <b>Create</b> panel and <b>build</b> and <b>preview</b> the collection. The collection behaves exactly as before, except that when you click a document icon your web browser retrieves the original document from the web (assuming it is still there by the time you do this exercise!). If you are working offline you will be unable to retrieve the document.</Text>
+</NumberedItem>
+</Content>
+</Tutorial>
+<Tutorial id="enhanced_html_collection">
+<Title>
+<Text id="0434">Enhanced collection of HTML files</Text>
+</Title>
+<Prerequisite id="large_html_collection"/>
+<SampleFiles folder=""/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<Comment>
+<Text id="0435">We return to the Tudor collection and add metadata that expresses a subject hierarchy. Then we build a classifier that exploits it by allowing</Text>
+<Text id="0436"> readers to browse the documents about Monarchs, Relatives, Citizens, and Others separately.</Text>
+</Comment>
+<Heading>
+<Text id="0437">Adding hierarchically-structured metadata and a Hierarchy classifier</Text>
+</Heading>
+<NumberedItem>
+<Text id="0438">Open up your <b>tudor</b> collection (the original version, not the <b>webtudor</b> version), switch to the <b>Enrich </b>panel and select the <i>monarchs</i> folder (a subfolder of <i>tudor</i>). Set its <b>dc.Subject and Keywords</b> metadata to <b>Tudor period|Monarchs</b>. (For brevity, we refer to this metadata element in future simply as <b>dc.Subject</b>.) The vertical bar ("|") is a hierarchy marker. Selecting a <i>folder</i> and using the <b>Append</b> button to set its metadata has the effect of setting this metadata value for all files contained in this folder, its subfolders, and so on. A popup alerts you to this fact.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0439">Repeat for the <i>relative</i> and <i>citizens</i> folder, setting their <b>dc.Subject</b> metadata to <b>Tudor period|Relatives</b> and <b>Tudor period|Citizens</b> respectively. Note that the hierarchy appears in the <b>All Previous Values</b> area.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0440">Finally, select all remaining files--the ones that are not in the <i>monarchs</i>, <i>relative</i>, and <i>citizens</i> folders--by selecting the first and shift-clicking the last. Set their <b>dc.Subject</b> metadata to <b>Tudor period|Others</b>: this is done in a single operation (there is a short delay before it completes).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0441">Switch to the <b>Design</b> panel and select <b>Browsing Classifiers </b>from the left-hand list. Set the menu item for <b>Select classifier to add </b>to <b>Hierarchy</b>; then click &lt;<b>Add Classifier</b>&gt;.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0442">A window pops up to control the classifier's options. Change the metadata to <i>dc.Subject</i> and then click <b>&lt;OK&gt;</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0443">For tidiness' sake, <b>remove</b> the <b>classifier</b> for <b>Source</b> metadata (included by default) from the list of currently assigned classifiers, because this adds little to the collection.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0444">Now switch to the <b>Create </b>panel, <b>build </b>the collection, and <b>preview </b>it. Choose the new <b>subjects </b>link that appears in the navigation bar, and click the bookshelves to navigate around the four-entry hierarchy that you have created.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0445">Next we partition the full-text index into four separate pieces. To do this we first define four subcollections obtained by "filtering" the documents according to a criterion based on their <b>dc.Subject</b> metadata. Then an index is assigned to each subcollection.</Text>
+</Comment>
+<Heading>
+<Text id="0446">Partitioning the full-text index based on metadata values</Text>
+</Heading>
+<NumberedItem>
+<Text id="0447">Switch to the <b>Design</b> panel, and click &lt;<b>Partition Indexes</b>&gt;. This feature is disabled because you are operating in <i>Librarian Mode</i> (this is indicated in the title bar at the top of the window).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0448">Switch to <i>Library Systems Specialist</i> mode by going to <b>Preferences</b> (on the <i>File</i> menu) and clicking &lt;<b>Mode</b>&gt;. Read about the other modes too. Note that the mode appears in the title bar.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0449">Return to the <b>Partition Indexes</b> section of the <b>Design</b> panel. Ensure that the <b>Define Filters</b> tab is selected (the default). Define a subcollection filter with name <b>monarchs</b> that matches against <b>dc.Subject and Keywords, </b>and type <b>Monarchs</b> as the regular expression to match with. Click &lt;<b>Add Filter</b>&gt;. This filter includes any file whose <b>dc.Subject</b> metadata contains the word <i>Monarchs</i>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0450">Define another filter, <b>relatives</b>, which matches <b>dc.Subject </b>against the word <b>Relatives</b>.<b> </b>Define a third and fourth, <b>citizens</b> and <b>others</b>, which matches it against the words <b>Citizens</b> and <b>Others</b> respectively.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0451">Having defined the subcollections, we partition the index into corresponding parts. Click the &lt;<b>Assign Partitions</b>&gt; tab. Select the first subcollection and give it the name <b>monarchs</b>; click &lt;<b>Add Partition</b>&gt;. Repeat for the other three subcollections, naming their partitions <b>relatives</b>, <b>citizens</b> and <b>others</b>. <b>Build</b> and <b>preview</b> the collection.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0452">The search page includes a pulldown menu that allows you to select one of these partitions for searching. For example, try searching the <i>relatives</i> partition for <i>mary</i>. and then search the <i>monarchs</i> partition for the same thing.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0453">To allow users to search the collection as a whole as well as each subcollection individually, return to the <b>Partition Indexes</b> section of the <b>Design</b> panel and select the <b>Assign Partitions </b>tab.<b> </b>Type <b>all</b> into the <b>Partition Name </b>and select all four subcollections by checking their boxes.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0454">To ensure that the <i>all</i> index appears first in the list on the reader's web page, use the &lt;<b>Move Up</b>&gt; button to get it to the top of the list here in the <b>Design</b> panel. Then <b>build</b> and <b>preview</b> the collection.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0455">Search for a common term (like <i>the</i>) in all five index partitions, and check that the numbers add up.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0456">Return to <i>Librarian </i>mode, using <b>Preferences</b> (on the <i>File</i> menu).</Text>
+</NumberedItem>
+<Heading>
+<Text id="0457">Adding a hierarchical phrase index (PHIND)</Text>
+</Heading>
+<NumberedItem>
+<Text id="0458">Switch to the <b>Design</b> panel and choose the <b>Browsing Classifiers</b> item from the left-hand list.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0459">Choose <b>Phind</b> from the <b>Select classifier to add</b> menu. Click &lt;<b>Add Classifier&gt;</b>. A window pops asking for configuration options: leave the values at their preset defaults (this will base the phrase index on the full text) and click <b>&lt;OK&gt;</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0460"><b>Build</b> the collection again, <b>preview</b> it, and try out the new <b>phrases</b> option in the navigation bar. An interesting PHIND search term for this collection is <b>king</b>.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0461">Finally we look at how the building process can be controlled. Developing a new collection usually involves numerous cycles of building, previewing, adjusting some enrich and design features, and so on. While prototyping, it is best to temporarily reduce the number of documents in the collection. This can be accomplished through the "maxdocs" parameter to the building process.</Text>
+</Comment>
+<Heading>
+<Text id="0462">Controlling the building process</Text>
+</Heading>
+<NumberedItem>
+<Text id="0463">Switch to the <b>Create</b> panel and view the options that are displayed in the top portion of the screen. Select <b>maxdocs</b> and set its numeric counter to <b>3</b>. Now <b>build</b>. In fact, you will find that the collection now contains 5 documents (not 3 as you specified: for technical reasons the number you give to <b>maxdocs</b> is an approximate value.)</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0464">Preview the newly rebuilt collection's <b>titles a-z</b> page. Previously this listed more than a dozen pages per letter of the alphabet, but now there are just three--the first three files encountered by the building process.</Text>
+</NumberedItem>
+</Content>
+</Tutorial>
+<Tutorial id="format_and_macros">
+<Title>
+<Text id="0465">Learning about formats and macros</Text>
+</Title>
+<Prerequisite id=""/>
+<SampleFiles folder=""/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<Comment>
+<Text id="0466">Format statements and macro files allow you to customize the appearance of Greenstone collections. They are very powerful, but complex and hard to learn. This tutorial exercise gives an introduction to the facilities they provide.</Text>
+</Comment>
+<Heading>
+<Text id="0467">Experimenting with format statements</Text>
+</Heading>
+<NumberedItem>
+<Text id="0468">Open up your <b>tudor</b> collection, go to the <b>Design</b> panel (by clicking on its tab) and select <b>Format Features </b>from the left-hand list. Leave the <b>Editing Controls </b>at their default value, so that <b>Choose Feature </b>remains blank and <b>VList </b>is selected as the <b>Affected Component</b>. The text in the <b>HTML Format String</b> box reads as follows:</Text>
+<Format>
+&lt;td valign=top&gt;[link][icon][/link]&lt;/td&gt;<br/>
+&lt;td valign=top&gt;[ex.srclink]{Or}{[ex.thumbicon],[ex.srcicon]} [ex./srclink]&lt;/td&gt;<br/>
+&lt;td valign=top&gt;[highlight]<br/>
+{Or}{[dls.Title],[dc.Title],[ex.Title],Untitled}<br/>
+[/highlight]{If}{[ex.Source],&lt;br&gt;&lt;i&gt;([ex.Source])&lt;/i&gt;}&lt;/td&gt;
+</Format> 
+<Text id="0469" funky="1">This displays </Text>
+<Text id="0470">something that looks like this: </Text>
+<Indent>
+<table><tr><td><img width='15' height='20' src="tutorial_images/itext.gif"/></td><td width='408' valign='top'>A discussion of question five from Tudor Quiz: Henry VIII <br/><i>(quizstuff.html)</i></td></tr></table>
+</Indent>
+<Text id="0472">for a particular document whose <i>Title</i> metadata is <i>A discussion of question five from Tudor Quiz: Henry VIII</i> and whose <i>Source</i> metadata is <i>quizstuff.html</i></Text>
+<Text id="0473">. This format appears in the search results list, in the <i>titles a-z</i> list, and also when you get down to individual documents in the <i>subjects</i> hierarchy. This is Greenstone's default format statement.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0474">Greenstone's default format statement is complex--even baroque--because it is designed to produce something reasonable under almost any conditions, and also because for practical reasons it needs to be backwards compatible with legacy collections.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0475">Delete the contents of the <b>HTML</b> <b>Format String</b> box and replace it with this simpler version:</Text>
+<Format>
+&lt;td&gt;[link][icon][/link]&lt;/td&gt; <br/>
+&lt;td&gt;[ex.Title]&lt;br&gt;<br/>
+&lt;i&gt;([ex.Source])&lt;/i&gt;<br/>
+&lt;/td&gt;
+</Format> 
+<Text id="0476"><b>Preview</b> the result (you don't need to build the collection, because changes to format statements take effect immediately). Look at some search results and at </Text>
+<Text id="0477">the <i>titles a-z</i> list. They are just the same as before! Under most circumstances this far simpler format statement is entirely equivalent to Greenstone's more complex default. </Text>
+<Comment>
+<Text id="0478">But there's a problem. Beside the bookshelves in the hierarchy browser, beneath the subject appears a mysterious "()</Text>
+<Text id="0479">". What is printed on these bookshelf nodes is governed by the same format statement, and though bookshelf nodes of the hierarchy have associated </Text>
+<Text id="0480">Title metadata--their title is the name of the metadata value associated with that bookshelf--they do not have </Text>
+<Text id="0481">ex.Source metadata, so it comes out blank.</Text>
+</Comment></NumberedItem>
+<NumberedItem>
+<Text id="0482">In the <b>Format Features</b> section of the <b>Design</b> panel, the <b>Choose Feature</b> menu (just above <b>Affected Component</b> menu) is blank. That implies that the same format is used for the search results, titles, and all nodes in the subject hierarchy--including internal nodes (that is, bookshelves). The <b>Choose Feature</b> menu can be used to restrict a format statement to a specific one of these lists; when it's blank, the <b>VList</b> specification applies throughout. We will override this format statement for the hierarchical <i>subject</i> classifier. In the <b>Choose Feature</b> menu, scroll down to the item that says</Text>
+<Indent>
+CL2: Hierarchy -metadata dc.Subject and Keywords
+</Indent> 
+<Text id="0483">and select it. This is the format statement that affects the second classifier (i.e., "CL2"), which is a <b>Hierarchy</b> classifier based on <b>dc.Subject and Keywords</b> metadata.</Text>
+<Text id="0484">Edit the <b>HTML Format String</b> box below to read</Text>
+<Format>
+&lt;td&gt;[link][icon][/link]&lt;/td&gt;<br/>
+&lt;td&gt;[ex.Title]&lt;/td&gt;
+</Format> 
+<Text id="0485">and click &lt;<b>Add Format</b>&gt;.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0486">Now go to the <b>Create</b> panel and click &lt;<b>Preview</b>&gt;. First, the offending "<i>()</i>" has disappeared from the bookshelves. Second, when you get down to a list of documents in the subject hierarchy, the filename does not appear beside the title, because <i>ex.Source</i> is not specified in the format statement and this format statement applies to all nodes in the <i>subject</i> classifier. Note that the search results and titles lists have not changed: they still display the filename underneath the title.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0487">Let's change the search results format so that <i>dc.Subject and Keywords </i>metadata is displayed here instead of the filename. In the <b>Choose Feature </b>menu (under <b>Format Features </b>on the <b>Design </b>panel), scroll down to the item <b>Search</b> and select it. Change the <b>HTML Format String</b> box below to read</Text>
+<Format>
+&lt;td&gt;[link][icon][/link]&lt;/td&gt;<br/>
+&lt;td&gt;[ex.Title]&lt;br&gt;<br/> 
+   [dc.Subject]<br/> 
+&lt;/td&gt;<br/>
+</Format> 
+<Text id="0488">and click &lt;<b>Add Format</b>&gt;.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0489">To insert the <b>[dc.Subject]</b>, position the cursor at the appropriate point and investigate the <b>Variables</b> dropdown menu below--the one that says <b>[Text]</b>. Make it say <b>[dc.Subject]</b> and click <b>Insert </b>to insert this into the <b>HTML Format String</b>. This menu shows all the things that you can put in square brackets in the format statement. The only exception is <b>[Text]</b>, which gives the full text of the document, and can only be used when <b>DocumentText</b> is the <b>Affected Component</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0490">Now go to the <b>Create</b> panel and click &lt;<b>Preview</b>&gt;. Documents in the search results list will be displayed like this:</Text>
+<table><tr><td><img width='15' height='20' src="tutorial_images/itext.gif" /></td><td width='408' valign='top'>A discussion of question five from Tudor Quiz: Henry VIII <br/>
+Tudor period|Others</td></tr></table>
+<Text id="0493">(The vertical bar appears because this <i>dc.Subject and Keywords</i> metadata is hierarchical metadata. Unfortunately there is no way to get at individual components of the hierarchy. For most metadata, such as title and author, this isn't a problem.) </Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0494">Finally, let's return to the <i>subjects</i> hierarchy and learn how to do different things to the bookshelves and to the documents themselves. In the <b>Choose Feature </b>menu, re-select the item </Text>
+<Indent>
+CL2: Hierarchy -metadata dc.Subject and Keywords
+</Indent> 
+<Text id="0495">Edit the <b>HTML Format String </b>box below to read</Text>
+<Format>
+&lt;td&gt;[link][icon][/link]&lt;/td&gt;<br/>
+&lt;td&gt;{If}{[numleafdocs],&lt;b&gt;Bookshelf title:&lt;/b&gt; [ex.Title],<br/>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;b&gt;Title:&lt;/b&gt; [ex.Title]}<br/> 
+&lt;/td&gt;
+</Format> 
+<Text id="0496">and click <b>Replace Format</b>. Again, you can insert the items in square brackets by selecting them from the <b>Variables</b> dropdown box (don't forget to click <b>Insert</b>).</Text>
+<Comment2>
+<Text id="0497">The <b>if </b>statement tests the value of the variable <b>numleafdocs</b>. This variable is only set for internal nodes of the hierarchy, i.e. bookshelves, and gives the number of documents below that node. If it is set we take the first branch, otherwise we take the second. Commas are used to separate the branches. The curly brackets serve to indicate that the <b>if</b> is special--otherwise the word "if" itself would be output.</Text>
+</Comment2></NumberedItem>
+<NumberedItem>
+<Text id="0498">Go to the <b>Create </b>panel, click &lt;<b>Preview</b>&gt;, and examine the subject hierarchy again to see the effect of your changes. </Text>
+</NumberedItem>
+<Heading>
+<Text id="0499">Collection-specific macros</Text>
+</Heading>
+<Comment>
+<Text id="0500">The appearance of all pages produced by Greenstone is governed by macro files, which reside in the folder </Text>
+<Text id="0501">C:\Program Files\Greenstone\macros. The </Text>
+<Text id="0502">garish example collection is a version of the </Text>
+<Text id="0503">demo collection with bizarre layout and coloring. Now we apply the same bizarre layout and coloring to the </Text>
+<Text id="0504">tudor collection.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0505">Go to the folder <i>C:\Program Files\Greenstone\macros</i>. Copy the file <i>garish.dm</i> (do not <i>cut</i> it; it must remain in this folder, otherwise Greenstone will not start up). Now go to your collection folder <i>C:\Program Files\Greenstone\collect\tudor </i>and create a new folder in there called <i>macros</i>. Paste <i>garish.dm</i> into that new folder, and change its name to <i>extra.dm</i>. The overall effect is that you have created a new file <i>C:\Program Files\Greenstone\collect\ tudor\macros\extra.dm</i> with the contents of <i>garish.dm</i>. Make sure that the new file is called <i>extra.dm</i> and not <i>extra.dm.dm</i>, which Windows sometimes tends to do.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0506">Now edit this file <i>extra.dm</i> using WordPad or Notepad. Search for the string <i>[c=garish]</i> and remove this string wherever it appears. Lines starting with <i>#</i> are comment lines; you don't have to remove the string from these (though it won't do any harm). There are 11 other occurrences of <i>[c=garish]</i>: you must remove them all.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0507">Go to the <b>Create </b>panel and click &lt;<b>Preview</b>&gt;. The content of your collection remains the same, but its appearance has changed completely--for example, all the pages are pink! To learn about how to control these changes, go to the documented example collection called <i>Garish version of demo collection</i>, and read about it.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0508">A small but important enhancement to Greenstone has been made since the garish collection was written. Instead of using the </Text>
+<Text id="0509">[c=garish] macro argument to restrict the macros to apply to a certain collection, you can now put collection-specific macros in the </Text>
+<Text id="0510">macros directory of the collection, in a file called </Text>
+<Text id="0511">extra.dm. In fact, this is what you have just done. </Text>
+</Comment>
+<Heading>
+<Text id="0512">General macros</Text>
+</Heading>
+<Comment>
+<Text id="0513">You can also use macros to completely change the appearance of your Greenstone site. Like the above exercise, what follows is just a lead-in to illustrate what is possible and show you where to look to achieve different kinds of effects.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0514">Exit from the Librarian Interface, since it is concerned with individual collections and we are now dealing with the site as a whole.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0515">Go to the folder <i>C:\Program Files\Greenstone\etc</i> and edit the file called <i>main.cfg</i>. This is Greenstone's main configuration file, and contains a list of the macros that will be loaded in on startup. One of them, <i>home.dm</i>, dictates how the Greenstone home page will look, which is specified in the file <i>C:\Program Files\Greenstone\macros\home.dm</i>. This <i>macros</i> folder contains an alternative version, called <i>yourhome.dm</i>, which is not currently being used. To use it instead, in <i>main.cfg</i> change the string <i>home.dm</i> to <i>yourhome.dm</i>. </Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0516">Now restart Greenstone (just the Greenstone Digital Library will do, rather than the Greenstone Librarian Interface). You will find that the appearance of the home page has changed completely.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0517">Instead of substituting <i>yourhome.dm</i> for <i>home.dm</i> in the file <i>main.cfg</i>, you could have simply edited <i>home.dm</i> and left <i>main.cfg</i> as it is. However, we wanted to preserve <i>home.dm</i> so that you could revert to your original Greenstone home page! Do this now by editing <i>main.cfg</i> and changing the string <i>yourhome.dm</i> back to <i>home.dm</i>. You will need to re-start Greenstone for this to take effect.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0518">To learn how more about macros, read </Text>
+<Text id="0519">Customizing the Greenstone User Interface, an illustrated guide to customizing the user interface, by Allison Zhang of the Washington Research Library Consortium, available at http://www.wrlc.org/dcpc/UserInterface/interface.htm.</Text>
+</Comment>
+</Content>
+</Tutorial>
+<Tutorial id="bibliography_collection">
+<Title>
+<Text id="0520">A bibliographic collection</Text>
+</Title>
+<Prerequisite id=""/>
+<SampleFiles folder=""/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<NumberedItem>
+<Text id="0521">Start a new collection called <b>Beatles Bibliography</b>. Enter the requested information and make it a <b>New Collection</b>. There is no need to include any metadata sets because the metadata extracted from the MARC records will appear as extracted metadata.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0522">In the <b>Gather</b> panel, open the <i>marc</i> folder, drag <b>locbeatles50.marc</b> into the right-hand pane and drop it there. A popup window asks whether you want to add <b>MARCPlug</b> to the collection to process this file. Click &lt;<b>Add Plugin</b>&gt;, because this plugin will be needed to process the MARC records.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0523">Remove the plugins <b>TextPlug</b> to <b>NULPlug</b> (<b>ZIPPlug</b>, <b>GAPlug</b> and <b>MARCPlug</b> remain). It is not strictly necessary to remove these redundant plugins, but it is good practice to include only plugins that are needed, to avoid accidentally including stray documents.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0524">Now select <b>Browsing Classifiers</b> within the <b>Design</b> panel and <b>remove</b> the default classifier for <b>Source</b> metadata. In this collection all records are from the same file, so <b>Source</b> metadata, which is set to the filename, is not particularly interesting.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0525">Switch to the <b>Create</b> panel, <b>build </b>the collection, and <b>preview</b> it. Browse through the <b>titles a-z</b> and view a record or two. Try searching--for example, find items that include <b>George Martin</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0526">Add an <b>AZCompactList</b> classifier for the <b>Subject</b> metadata. Select this item from the relevant menu of the <b>Browsing Classifiers </b>section of the <b>Design</b> panel and click <b>&lt;Add Classifier&gt;</b>. In the popup window, select <b>ex.Subject </b>as the metadata item, activate the <b>mingroup</b> option and set its field to <b>1</b>.</Text>
+<Comment>
+<Text id="0527"><b>AZCompactList</b> is like <b>AZList,</b> except that terms that appear multiple times in the hierarchy are automatically grouped together and a new node, shown as a bookshelf icon, is formed. Setting <b>mingroup</b> to 1 means that the bookshelf appears even when there is just one item, and is done here to provide a more uniform display.</Text>
+</Comment></NumberedItem>
+<NumberedItem>
+<Text id="0528"><b>Build</b> the collection and <b>preview</b> the result.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0529">Make each bookshelf node show how many entries it contains by appending this to the <b>Format Features </b>for <b>VList</b> format statement in the <b>Design</b> panel:</Text>
+<Format>{If}{[numleafdocs],&lt;td&gt;&lt;i&gt;([numleafdocs])&lt;/i&gt;&lt;/td&gt;}</Format> 
+</NumberedItem>
+<NumberedItem>
+<Text id="0530">Click <b>&lt;Replace Format&gt;</b>, switch to the <b>Create</b> panel, and click <b>&lt;Preview Collection&gt;</b> (no need to build the collection again).</Text>
+</NumberedItem>
+<Heading>
+<Text id="0531">Adding fielded searching</Text>
+</Heading>
+<NumberedItem>
+<Text id="0532">In the <b>Design</b> panel select <b>Search Types</b> from the left-hand list and activate the <b>Enable Advanced Searches </b>options.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0533"><b>Build</b> the collection once again, and <b>preview</b> the results. Notice that the collection's home page no longer includes a query box. (This is because the search form is too big to fit here nicely.) To search, you have to click <b>search</b> in the navigation bar. Note that the <i>Preferences </i>page has changed to control the advanced searching options.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0534">To finish off the collection, brand it with an image that will be used to represent the collection on the Greenstone page, and appear at the top of each page of the collection</Text>
+</Comment>
+<Heading>
+<Text id="0535">Branding a collection with an image</Text>
+</Heading>
+<NumberedItem>
+<Text id="0536">From the <b>General</b> section of the <b>Design</b> panel, click the <b>&lt;Browse&gt;</b> button next to the label <b>URL to âabout page' icon</b> and use the resulting popup file browser to access the folder <i>sample_files\marc</i>. Select <i>beatles_logo.jpg</i> and click &lt;<b>Open</b>&gt;.</Text>
+<Comment2>
+<Text id="0537">Greenstone copies the image into your collection area, so the collection will still work when the CD-ROM is removed from the drive.</Text>
+</Comment2>
+</NumberedItem>
+<NumberedItem>
+<Text id="0538">Repeat this process for the <b>URL to âhome page' icon</b>, selecting the same image.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0539">Now <b>build</b> the collection and <b>preview</b> it.</Text>
+</NumberedItem>
+</Content>
+</Tutorial>
+<Tutorial id="multimedia_collection_explore">
+<Title>
+<Text id="0540">Looking at a multimedia collection</Text>
+</Title>
+<Prerequisite id=""/>
+<SampleFiles folder=""/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<NumberedItem>
+<Text id="0541">Copy the entire folder</Text>
+<Indent>
+sample_files--&gt;beatles--&gt;advbeat_large
+</Indent> 
+<Text id="0542">(with all its contents) into your Greenstone <i>collect</i> folder. If you have installed Greenstone in the usual place, this is</Text>
+<Indent>
+My Computer--&gt;Local Disk (C:)--&gt;Program Files--&gt;Greenstone--&gt;collect
+</Indent> 
+<Text id="0543">Put <i>advbeat_large</i> in there.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0544">If the Greenstone Digital Library Local Library Server is already running, re-start it by clicking the CD icon on the task bar and then pressing <i>Restart Library</i>. If not, start it up by selecting <i>Greenstone Digital Library</i> from the <i>Start</i> menu.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0545">Explore the Beatles collection. Note how the <i>browse</i> button divides the material into seven different types. Within each category, the documents have appropriate icons. Some documents have an audio icon: when you click these you hear the music (assuming your computer is set up with appropriate player software). Others have an image thumbnail: when you click these you see the images.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0546">Look at the <i>titles a-z</i> browser. Each title has a bookshelf that may include several related items. For example, <i>Hey Jude</i> has a cover image, MP3 audio and MIDI versions, lyrics, and a discography item.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0547">Observe the low quality of the metadata. For example, the four items under <i>A HARD DAY'S NIGHT</i> (under "H" in the <i>titles a-z</i> browser) have different variants as their titles. The collection would have been easier to organize had the metadata been cleaned up manually first, but that would be a big job. Only a tiny amount of metadata was added by hand--fewer than ten items. The original metadata was left untouched and Greenstone facilities used to clean it up automatically. (You will find below that this is possible but tricky.)</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0548">In the Windows file browser, take a look at the files that makes up the collection, in the</Text>
+<Indent>
+sample_files--&gt;beatles--&gt;advbeat_large--&gt;import
+</Indent> 
+<Text id="0549">folder. What a mess! There are over 450 files under seven top-level sub-folders. Organization is minimal, reflecting the different times and ways the files were gathered. For example, <i>html_lyrics</i> and <i>discography</i> are excerpts of web sites, and <i>cover_images </i>contains album covers in JPEG format. For each type, drill down through the hierarchy and look at a sample document.</Text>
+</NumberedItem>
+</Content>
+</Tutorial>
+<Tutorial id="multimedia_collection_build">
+<Title>
+<Text id="0550">Building a multimedia collection</Text>
+</Title>
+<Prerequisite id=""/>
+<SampleFiles folder=""/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<Comment>
+<Text id="0551">We will proceed to reconstruct from scratch the Beatles collection that you have just looked at. We develop the collection using a small subset of the material, purely to speed up the repeated rebuilding that is involved.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0552">Start a new collection (<i>File</i>--&gt;</Text>
+<Text id="0553"><i>New</i>) called <b>small_beatles</b>, basing it on the default "New Collection." (Basing it on the existing Advanced Beatles collection would make your life far easier, but we want you to learn how to build it from scratch!) Fill out the fields with appropriate information. Use the Dublin Core metadata set (set by default).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0554">Copy the files provided in</Text>
+<Indent>
+sample_files--&gt;beatles--&gt;advbeat_small
+</Indent> 
+<Text id="0555">into your new collection. Do this by opening up <i>advbeat_small</i>,<i> </i>selecting the eight items within it (from <i>cover_images</i> to <i>beatles_midi.zip</i>), and dragging them across. Because some of these files are in MP3 and MARC formats you will be asked whether to include the <b>MP3Plug</b> and <b>MARCPlug</b> in your collection. Click &lt;<b>Add Plugin</b>&gt;. Also, a popup window will tell you that no plugins can process the .css file: click &lt;<b>OK</b>&gt; to close this popup.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0556">Change to the <b>Enrich</b> panel and browse around the files. There is no metadata--yet. Recall that you can double-click files to view them.</Text>
+<Text id="0557">(There are no MIDI files in the collection: these require more advanced customisation because there is no MIDI plugin. We will deal with them later.)</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0558">Change to the <b>Create</b> panel and <b>build </b>the collection.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0559"><b>Preview</b> the result.</Text>
+</NumberedItem>
+<Heading>
+<Text id="0560">Manually correcting metadata</Text>
+</Heading>
+<NumberedItem>
+<Text id="0561">You might want to correct some of the metadata--for example, the atrocious misspelling in the titles "MAGICAL MISTERY TOUR." These documents are in the discography section, with filenames that contain the same misspelling. Locate one of them in the <b>Enrich</b> panel. Notice that the extracted metadata element <b>ex.Title</b> is now filled in, and misspelt. You cannot correct this element, for it is extracted from the file and will be re-extracted every time the collection is re-built.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0562">Instead, add <b>dc.Title</b> metadata for these two files: "Magical Mystery Tour." Change to the <b>Enrich</b> panel, open the discography folder and drill down to the individual files. Set the <b>dc.Title</b> value for the two offending items.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0563">Now there's a twist. The <b>dc.Title</b> metadata won't appear in titles a-z because the classifier has been instructed to use <b>ex.Title</b>. But changing the classifier to use <b>dc.Title</b> would miss out all the extracted titles! Fortunately, there's a way of dealing with this by specifying a list of metadata names in the classifier.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0564">Change to the <b>Design</b> panel and select the <b>Browsing Classifiers</b> section. Double-click the <b>Title</b> classifier (the first one) to edit its configuration settings.</Text>
+<BulletList>
+<Bullet>
+<Text id="0565">Type "dc.Title," before the <i>ex.Title </i>in the metadata box--i.e. make it read</Text>
+<Indent>
+dc.Title,ex.Title
+</Indent> 
+</Bullet>
+</BulletList>
+<Text id="0566"><b>Build </b>the collection again, and <b>preview </b>it.</Text>
+<Text id="0567">Extracted metadata is unreliable. But it is very cheap! On the other hand, manually assigned metadata is reliable, but expensive. The previous section of this exercise has shown how to aim for the best of both worlds by using extracted metadata but correcting it when it is wrong. While this may not satisfy the professional librarian, it could provide a useful compromise for the music teacher who wants to get their collection together with a minimum of effort.</Text>
+</NumberedItem>
+<Heading>
+<Text id="0568">Browsing by media type</Text>
+</Heading>
+<NumberedItem>
+<Text id="0569">First let's remove the <b>AZList</b> classifier for filenames, which isn't very useful, and replace it with a browsing structure that groups documents by category (discography, lyrics, audio etc.). Categories are defined by manually assigned metadata.</Text>
+<BulletList>
+<Bullet>
+<Text id="0570">Change to the <b>Enrich</b> panel, select the folder <i>cover_images</i> and set its <b>dc.Format</b> metadata value to "Images". Setting this value at the folder level means that all files within the folder inherit it.</Text>
+</Bullet>
+<Bullet>
+<Text id="0571">Repeat the process. Assign "Discography" to the <i>discography</i> folder, "Lyrics" to <i>html_lyrics</i>, "MARC" to <i>marc</i>, "Audio" to <i>mp3</i>, "Tablature" to <i>tablature_txt</i>, and "Supplementary" to <i>wordpdf</i>.</Text>
+</Bullet>
+<Bullet>
+<Text id="0572">Switch to the <b>Design</b> panel and select the <b>Browsing Classifiers </b>section.</Text>
+</Bullet>
+<Bullet>
+<Text id="0573">Delete the <b>ex.Source </b>classifier (the second one).</Text>
+</Bullet>
+<Bullet>
+<Text id="0574">Add an <b>AZCompactList</b> classifier. Select <b>dc.Format</b> as the metadata field and specify "Category" as the <b>buttonname</b>.</Text>
+</Bullet>
+</BulletList>
+<Text id="0575"><b>Build</b> the collection again and <b>preview</b> it.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0576">Greenstone has no pre-defined button for "Category", so it appears in the navigation bar as text. It does, however, have a button for <i>browse</i> (it's used in the Beatles collection you looked at in Part I).</Text>
+<BulletList>
+<Bullet>
+<Text id="0577">Go back to the <b>AZCompactList</b> classifier for <b>dc.Format</b>. Click the <b>sort</b> checkbox, and leave <b>Title</b> in the adjacent text box: this will make the classifier display documents in alphabetical order of title. Also, specify "Browse" as the <b>buttonname</b>.</Text>
+</Bullet>
+</BulletList>
+<Text id="0578">You will need to build the collection for this to take effect.</Text>
+</NumberedItem>
+<Heading>
+<Text id="0579">Suppressing dummy text</Text>
+</Heading>
+<NumberedItem>
+<Text id="0580">Alongside the Audio files there is an MP3 icon, which plays the audio when you click it, and also a text document that contains some dummy text. This isn't supposed to be seen, but to suppress it you have to fiddle with a format statement.</Text>
+<BulletList>
+<Bullet>
+<Text id="0581">Change to the <b>Design</b> panel and select the <b>Format Features</b> section.</Text>
+</Bullet>
+<Bullet>
+<Text id="0582">Ensure that <b>VList</b> is selected, and make the changes that are highlighted below. You need to insert three lines into the first line, and delete the second line.<br/> <br/> Change:</Text>
+<Format>
+&lt;td valign=top&gt;[link][icon][/link]&lt;/td&gt;<br/> 
+&lt;td valign=top&gt;<br/>
+[ex.srclink]{Or}{[ex.thumbicon],[ex.srcicon]}[ex./srclink]&lt;/td&gt; <br/>
+&lt;td valign=top&gt;[highlight]<br/>
+{Or}{[dls.Title],[dc.Title],[Title],Untitled} <br/>
+[/highlight]{If}{[ex.Source],&lt;br&gt;&lt;i&gt;([ex.Source])&lt;/i&gt;}&lt;/td&gt;
+</Format> 
+<Text id="0583">to this: </Text>
+<Format>
+&lt;td valign=top&gt;<br/>
+{If}{[dc.Format] eq 'Audio', <br/>
+[srclink][srcicon][/srclink], <br/>
+[link][icon][/link]}&lt;/td&gt; <br/>
+&lt;td valign=top&gt;[highlight] {Or}{[dls.Title],[dc.Title],[Title],Untitled} [/highlight]{If}{[ex.Source],&lt;br&gt;&lt;i&gt;([ex.Source])&lt;/i&gt;}&lt;/td&gt;
+</Format> 
+</Bullet>
+<Bullet>
+<Text id="0584">Then click &lt;<b>Replace Format</b>&gt;.</Text>
+</Bullet>
+</BulletList>
+<Text id="0585">To make this easier for you we have prepared a plain text file that contains the new text. In WordPad open the following file:</Text>
+<Indent>
+sample_files--&gt;beatles--&gt;format_tweaks--&gt;audio_tweak.txt
+</Indent> 
+<Text id="0586">(Be sure to use WordPad rather than Notepad, because Notepad does not display the line breaks correctly.) Place it in the copy buffer by highlighting the text in WordPad and selecting Edit--&gt;</Text>
+<Text id="0587">Copy. Now move back to the Librarian Interface, highlight all the text that makes up the current VList format statement, and use Edit--&gt;</Text>
+<Text id="0588">Paste to transform the old statement to the new one. Remember to press &lt;<b>Replace Format</b>&gt; when finished.</Text>
+<b>
+<Text id="0589">Preview</Text>
+</b>
+<Text id="0590"> the result. If </Text>
+<Text id="0591">you are using the Greenstone Local Library server, change to the <b>Create </b>panel and click &lt;<b>Preview Collection</b>&gt;, which causes the local library server to rescan the format statements. You do not need to build the collection again because format statements are only used by the runtime system.</Text>
+<Text id="0592">However, you may need to click the browser's &lt;<b>Reload</b>&gt; button to force it to re-load the page.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0593">While we're at it, let's remove the source filename from where it appears after each document.</Text>
+<BulletList>
+<Bullet>
+<Text id="0594">In the VList format feature, delete the text that is highlighted below:</Text>
+<Format>
+&lt;td valign=top&gt;<br/>
+{If}{[dc.Format] eq 'Audio',<br/> 
+&nbsp;[srclink][srcicon][/srclink],<br/>
+&nbsp;[link][icon][/link]}&lt;/td&gt; <br/>
+&lt;td valign=top&gt;[highlight] {Or}{[dls.Title],[dc.Title],[Title],Untitled} [/highlight]{If}{[ex.Source],&lt;br&gt;&lt;i&gt;([ex.Source])&lt;/i&gt;}&lt;/td&gt;</Format> 
+</Bullet>
+</BulletList>
+<Text id="0595">Don't forget to click &lt;<b>Replace Format</b>&gt; after all this work! <b>Preview</b> the result (you don't need to build the collection.)</Text>
+</NumberedItem>
+<Heading>
+<Text id="0596">Using AZCompactList rather than AZList</Text>
+</Heading>
+<NumberedItem>
+<Text id="0597">There are sometimes several documents with the same title. For example, <i>All My Loving </i>appears both as lyrics and tablature (under <i>ALL MY LOVING</i>). The <i>titles a-z</i> browser might be improved by grouping these together under a bookshelf icon. This is a job for an <b>AZCompactList</b>.</Text>
+<BulletList>
+<Bullet>
+<Text id="0598">Change to the <b>Design</b> panel and select the <b>Browsing Classifiers </b>section.</Text>
+</Bullet>
+<Bullet>
+<Text id="0599">Remove the <b>Title</b> classifier (at the top)</Text>
+</Bullet>
+<Bullet>
+<Text id="0600">Add an <b>AZCompactList</b> classifier, and enter <b>dc.Title,ex.Title</b> as its metadata.</Text>
+</Bullet>
+<Bullet>
+<Text id="0601">Activate <b>mingroup</b> and set it to 1. This gives a uniform appearance by creating a bookshelf for every title.</Text>
+</Bullet>
+<Bullet>
+<Text id="0602">Finish by pressing &lt;<b>OK</b>&gt;.</Text>
+</Bullet>
+<Bullet>
+<Text id="0603">Move the new classifier to the top of the list (<b>Move Up</b> button).</Text>
+</Bullet>
+</BulletList>
+<Text id="0604"><b>Build </b>the collection again and <b>preview </b>it. Both items for <i>All My Loving </i>now appear under the same bookshelf. However, many entries haven't been amalgamated because of non-uniform titles: for example <i>A Hard Day's Night</i> appears as four different variants. We will learn below how to amalgamate these.</Text>
+</NumberedItem>
+<Heading>
+<Text id="0605">Making bookshelves show how many items they contain</Text>
+</Heading>
+<NumberedItem>
+<Text id="0606">Make the bookshelves show how many documents they contain by inserting a line in the VList format statement in the <b>Design</b> panel:</Text>
+<Format>
+&lt;td valign=top&gt;<br/> 
+{If}{[dc.Format] eq 'Audio',<br/> 
+ [srclink][srcicon][/srclink],<br/> 
+ [link][icon][/link]}&lt;/td&gt;<br/> 
+&lt;td&gt;{If}{[numleafdocs],([numleafdocs])}&lt;/td&gt;<br/> 
+&lt;td valign=top&gt;[highlight] {Or}{[dls.Title],[dc.Title],[Title],Untitled} [/highlight]&lt;/td&gt;</Format> 
+<Text id="0607">You will find this text in <i>format_tweaks</i>--&gt;</Text>
+<Text id="0608"><i>show_num_docs.txt</i>, which can be copied and pasted in as before. Don't forget to click &lt;<b>Replace Format</b>&gt;.</Text>
+<Text id="0609"><b>Preview</b> the result (you don't need to build the collection.)</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0610">Now turn to the images. Dummy documents are displayed here too. First change to the <b>Enrich</b> panel, open the folder <i>cover_images</i> and add <b>dc.Title</b><i> </i>metadata, assigning to each of the ten documents the title of the corresponding album. Remember, you can double-click a file to view it.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0611">To suppress the dummy documents, change the <b>VList</b> format statement in the <b>Design</b> panel again by adding the two highlighted lines, and the close curly bracket:</Text>
+<Format>&lt;td valign=top&gt;<br/> 
+{If}{[dc.Format] eq 'Audio',<br/> 
+ [srclink][srcicon][/srclink],<br/> 
+ {If}{[dc.Format] eq 'Images',<br/> 
+ [srclink][thumbicon][/srclink],<br/> 
+ [link][icon][/link]}}&lt;/td&gt;<br/> 
+&lt;td&gt;{If}{[numleafdocs],([numleafdocs])}&lt;/td&gt;<br/> 
+&lt;td valign=top&gt;[highlight] {Or}{[dls.Title],[dc.Title],[Title],Untitled} [/highlight]&lt;/td&gt;</Format> 
+</NumberedItem>
+<NumberedItem>
+<Text id="0612">Add a <b>Phind</b> browsing classifier that sources its phrases from <i>Title</i> and <i>text</i> (the default setting).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0613">To complete the collection, use the browse button of <b>URL to âabout page' icon</b> in the <b>General</b> section of the <b>Design</b> panel to select the following image: <i>advbeatles_large</i>--&gt;</Text>
+<Text id="0614"><i>images</i>--&gt;</Text>
+<Text id="0615"><i>flick4.gif.</i></Text>
+<Text id="0616"><b>Build</b> the collection again and <b>preview</b> it.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0617">Note how we assigned dc.Format metadata to all documents in the collection with a minimum of labour. We did this by capitalizing on the folder structure of the original information. Even though we complained earlier about how messy this folder structure is, you can still take advantage of it when assigning metadata.</Text>
+</Comment>
+<Comment>
+<Text id="0618">In the next exercise we incorporate the MIDI files. Greenstone has no MIDI plugin (yet). But that doesn't mean you can't use MIDI files! We also clean up the </Text>
+<Text id="0619">titles a-z</Text>
+<Text id="0620"><b> </b>browser.<b></b></Text>
+</Comment>
+<Comment>
+<Text id="0621">To do this we must put the Librarian Interface into a different mode. The interface supports four levels of user: Library Assistants, who can add documents and metadata to collections, and create new ones whose structure mirrors that of existing collections; Librarians, who can, in addition, design new collections, but cannot use specialist IT features (e.g. regular expressions); Library Systems Specialists, who can use all design features, but cannot perform troubleshooting tasks (e.g. interpreting debugging output from Perl programs); and Experts, who can perform all functions.</Text>
+</Comment>
+<Comment>
+<Text id="0622">So far you have mostly been operating in Librarian mode. We switch to Library Systems Specialist mode for the next exercise.</Text>
+</Comment>
+<Heading>
+<Text id="0623">Using UnknownPlug</Text>
+</Heading>
+<NumberedItem>
+<Text id="0624">To switch modes, click <i>File</i>--&gt;</Text>
+<Text id="0625"><i>Preferences</i>--&gt;</Text>
+<Text id="0626"><i>Mode </i>and change to <b>Library Systems Specialist</b>. Note from the description that appears that you need to be able to formulate regular expressions to use this mode fully. That is what we do below.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0627"><b>UnknownPlug</b> is a useful generic plugin. It knows nothing about any given format but can be tailored to process particular document types--like MIDI--based on their filename extension, and set basic metadata.</Text>
+<BulletList>
+<Bullet>
+<Text id="0628">add <b>UnknownPlug</b>;</Text>
+</Bullet>
+<Bullet>
+<Text id="0629">activate its <i>process_extension</i> field and set it to <i>mid</i> to make it recognize files with extension .<i>mid</i>;</Text>
+</Bullet>
+<Bullet>
+<Text id="0630">Set <i>file_format</i> to "MIDI" and <i>mime_type</i> to "audio/midi".</Text>
+</Bullet>
+</BulletList>
+<Text id="0631">In this collection, all MIDI files are contained in the file <i>beatles_midi.zip</i>. <b>ZIPPlug</b> (already in the list of default plugins) is used to unpack the files and pass them down the list of plugins until they reach UnknownPlug.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0632"><b>Build</b> the collection and <b>preview</b> it. Unfortunately the MIDI files don't appear as Audio under the <i>browse</i> button. That's because they haven't been assigned <b>dc.Format</b> metadata.</Text>
+<BulletList>
+<Bullet>
+<Text id="0633">Back in the <b>Enrich</b> panel, click on the file <i>beatles_midi.zip</i> and assign its <b>dc.Format</b> value to "Audio"--do this by clicking on "Audio" in the <b>All Previous Values</b> list. All files extracted from the Zip file inherit its settings.</Text>
+</Bullet>
+</BulletList>
+</NumberedItem>
+<Heading>
+<Text id="0634">Cleaning up a title browser using regular expressions</Text>
+</Heading>
+<NumberedItem>
+<Text id="0635">Next we return to our <i>titles a-z</i> browser and clean it up. The aim is to amalgamate variants of titles by stripping away extraneous text. For example, we would like to treat "ANTHOLOGY 1", "ANTHOLOGY 2" and "ANTHOLOGY 3" the same for grouping purposes. To achieve this:</Text>
+<BulletList>
+<Bullet>
+<Text id="0636">Go to the Title <b>AZCompactList</b> under <b>Browsing Classifiers</b> on the <b>Design</b> panel;</Text>
+</Bullet>
+<Bullet>
+<Text id="0637">Activate <b>removesuffix</b> and set it to:</Text>
+<Format>(?i)(\\s+\\d+)|(\\s+[[:punct:]].*)</Format> 
+</Bullet>
+</BulletList>
+<Text id="0638"><b>Build</b> the collection and <b>preview</b> the result. Observe how many more times similar titles have been amalgamated under the same bookshelf. Test your understanding of regular expressions by trying to rationalize the amalgamations. (Note: <i>[[:punct:]]</i> stands for any punctuation character.) The icons beside the Word and PDF documents are not the correct ones, but that will be fixed in the next format statement.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0639">The previous exercise was done in Librarian Systems Specialist mode because it requires the use of regular expressions, something librarians are not normally trained in.</Text>
+</Comment>
+<Comment>
+<Text id="0640">One powerful use of regular expressions in the exercise was to clean up the </Text>
+<Text id="0641">titles a-z</Text>
+<Text id="0642"> browser. Perhaps the best way of doing this would be to have proper title metadata. The metadata extracted from HTML files is messy and inconsistent, and this was reflected in the original titles a-z browser. Defining proper title metadata would be simple but rather laborious. Instead, we have opted to use regular expressions in the AZCompactList classifier to clean up the title metadata. This is difficult to understand, and a bit fiddly to do, but if you can cope with its idiosyncrasies it provides a quick way to clean up the extracted metadata and avoid having to enter a large amount of metadata.</Text>
+</Comment>
+<Heading>
+<Text id="0643">Using non-standard macro files</Text>
+</Heading>
+<Comment>
+<Text id="0644">To put finishing touches to our collection, we add some decorative features</Text>
+</Comment>
+<NumberedItem>
+<Text id="0645">Using your Windows file browser outside Greenstone, locate the folder</Text>
+<Indent>
+sample_files--&gt;beatles--&gt;advbeat_large
+</Indent> 
+</NumberedItem>
+<NumberedItem>
+<Text id="0646">Copy the <i>images</i> and <i>macros</i> folders located there into your collection's top-level folder. (It's OK to overwrite the existing <i>images</i> folder: the image in it is included in the folder being copied.) The <i>images</i> folder includes some useful icons, and the <i>macros</i> folder defines some macro names that use these images. To see the macro definitions, take a look by using a text editor to open the file <i>extra.dm</i> in the <i>macros</i> folder.</Text>
+</NumberedItem>
+<Heading>
+<Text id="0647">Using different icons for different media types</Text>
+</Heading>
+<NumberedItem>
+<Text id="0648">Re-Edit your <b>VList</b> format statement to be the following</Text>
+<Format>&lt;td valign=top&gt;<br/> 
+{If}{[numleafdocs],[link][icon][/link]}<br/> 
+{If}{[dc.Format] eq 'Lyrics',[link]_iconlyrics_[/link]}<br/> 
+{If}{[dc.Format] eq 'Discography',[link]_icondisc_[/link]}<br/> 
+{If}{[dc.Format] eq 'Tablature',[link]_icontab_[/link]}<br/> 
+{If}{[dc.Format] eq 'MARC',[link]_iconmarc_[/link]}<br/> 
+{If}{[dc.Format] eq 'Images',[srclink][thumbicon][/srclink]}<br/> 
+{If}{[dc.Format] eq 'Supplementary',[srclink][srcicon][/srclink]}<br/> 
+{If}{[dc.Format] eq 'Audio',[srclink]{If}{[FileFormat] eq 'MIDI',_iconmidi_,_iconmp3_}[/srclink]}<br/> 
+&lt;/td&gt;<br/> 
+&lt;td&gt;<br/> 
+{If}{[numleafdocs],([numleafdocs])}<br/> 
+&lt;/td&gt;<br/> 
+&lt;td valign=top&gt;<br/> 
+[highlight]<br/> 
+{Or}{[dc.Title],[Title],Untitled}<br/> 
+[/highlight]<br/> 
+&lt;/td&gt;</Format> 
+</NumberedItem>
+<NumberedItem>
+<Text id="0649">The complete statement is in the file <i>format_tweaks</i>--&gt;</Text>
+<Text id="0650"><i>multi_icons.txt</i>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0651"><b>Preview</b> your collection as before. Now different icons are used for discography, lyrics, tablature, and MARC metadata. Even MP3 and MIDI audio file types are distinguished. If you let the mouse hover over one of these images a "tool tip" appears explaining what file type the icon represents in the current interface language (note: <i>extra.dm</i> only defines English and French).</Text>
+</NumberedItem>
+<Heading>
+<Text id="0652">Changing the collection's background image</Text>
+</Heading>
+<NumberedItem>
+<Text id="0653">Open your collection's <i>macros</i> folder and locate the <i>extra.dm</i> file within it. <b>Right-click </b>on it. If prompted, select <b>WordPad</b> as the application to open it with.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0654">The file content is fairly brief, specifying only what needs to be overridden from the default behaviour for this collection. In WordPad, near the top of the file you should see:</Text>
+<Format>_httpiconchalk_ {_httpcimages_/beat_margin.gif}<br/> 
+_widthchalk_ {1800}<br/> 
+_heightchalk_ {68}.</Format> 
+<Text id="0655">Use copy and paste on these three lines to make this part of the file look like:</Text>
+<Format># Original statements<br/> 
+#_httpiconchalk_ {_httpcimages_/beat_margin.gif}<br/> 
+#_widthchalk_ {1800}<br/> 
+#_heightchalk_ {68}<br/> 
+_httpiconchalk_ {_httpcimages_/tile.jpg}<br/> 
+_widthchalk_ {22}<br/> 
+_heightchalk_ {22}</Format> 
+<Text id="0656">A hash (#) at the start of line signals a comment, and Greenstone ignores the following text. We use this to comment out the original three statements and replace them with modified lines. It is useful to retain the original version in case we need to restore the original lines at a later date. These three lines relate to the background image used. The new image <i>tile.jpg</i> was also in the <i>images</i> folder that was copied across previously.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0657">Within <b>WordPad</b>, save <i>extra.dm</i>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0658"><b>Preview</b> the collection's home page. The page background is now the new graphic.</Text>
+<Text id="0659">Other features can be altered by editing the macro files--for example, the headers and footers used on each page, and the highlighting style used for search terms (specify a different colour, use bold etc.).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0660">If you want to you can reverse the most recent change you made by commenting out the three new lines added (add #) and uncommenting the original three (delete # character). Remember to save the file. To undo all the customized changes made, delete the content of the <i>macros</i> and <i>images</i> folders.</Text>
+</NumberedItem>
+<Heading>
+<Text id="0661">Building a full-size version of the collection</Text>
+</Heading>
+<NumberedItem>
+<Text id="0662">To finish, let's now build a larger version of the collection. To do this:</Text>
+<BulletList>
+<Bullet>
+<Text id="0663">Close the current collection.</Text>
+</Bullet>
+<Bullet>
+<Text id="0664">Start a new collection called <i>advbeat_large.</i></Text>
+</Bullet>
+<Bullet>
+<Text id="0665">Base this new collection on <i>small_beatles</i>.</Text>
+</Bullet>
+<Bullet>
+<Text id="0666">Copy the content of <i>sample_files</i>--&gt;</Text>
+<Text id="0667"><i>beatles</i>--&gt;</Text>
+<Text id="0668"><i>advbeat_large</i>--&gt;</Text>
+<Text id="0669"><i>import</i> into this newly formed collection. Since there are considerably more files in this set of documents the copy will take longer.</Text>
+<Text id="0670"><b>Build</b> the collection and preview the result. (If you want the collection to have an icon, you will have to add it from the <b>Design</b> panel.)</Text>
+</Bullet>
+</BulletList>
+</NumberedItem>
+<Heading>
+<Text id="0671">Adding an image collage browser</Text>
+</Heading>
+<NumberedItem>
+<Text id="0672">Switch to the <b>Design</b> panel and select the <b>Browsing Classifiers</b> section. Pull down the <b>select classifier to add</b> menu and select <b>Collage</b>. Click &lt;<b>Add Classifier</b>&gt;. There is no need to customize the options, so click &lt;<b>OK</b>&gt; at the bottom of the resulting popup.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0673">Now change to the <b>Create</b> panel and <b>build</b> and <b>preview</b> the collection.</Text>
+</NumberedItem>
+</Content>
+</Tutorial>
+<Tutorial id="scanned_image_collection">
+<Title>
+<Text id="0674">Scanned image collection</Text>
+</Title>
+<Prerequisite id=""/>
+<SampleFiles folder=""/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<Comment>
+<Text id="0675">Here we build a small replica of Niupepa, the Maori Newspaper collection, using five newspapers taken from two newspaper series. It allows full text searching and browsing by title and date. When a newspaper is viewed, a preview image and its corresponding plain text are presented side by side, with a goto page navigation feature at the top of the page.</Text>
+</Comment>
+<Comment>
+<Text id="0676">The collection involves a mixture of plug-ins, classifiers, and format statements. The bulk of the work is done by PagedImgPlug, a plug-in designed precisely for the kind of data we have in this example. For each document, an "item" file is prepared that specifies a list of image files that constitute the document, tagged with their page number and (optionally) accompanied by a text file containing the machine-readable version of the image, which is used for full text searching. Three newspapers in our collection (all from the series Te Whetu o Te Tau) have text representations, and two (from Te Waka o Te Iwi) have images only. Item files can also specify metadata. In our example the newspaper series is recorded as ex.Title and its date of publication as ex.Date. This metadata is extracted as part of the building process.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0677">Start a new collection called <b>Paged Images</b> and fill out the fields with appropriate information: it is a collection sourced from an excerpt of Niupepa documents; the only metadata used is document title and date, and these are extracted from the "item" files included in the source documents so no metadata set need be stipulated.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0678">Add <b>PagedImgPlug</b> and switch on its <b>screenview</b> configuration option by checking the box. The source images we use were scanned at high resolution and are large files for a browser to download. The <i>screenview</i> option generates smaller screen-resolution images of each page when the collection is built. </Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0679">In the <b>Gather </b>panel, open the <i>niupepa\sample_items </i>folder in <i>sample_files </i>and drag it into your collection on the right-hand side.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0680">Some of the files you have just dragged in are text files that contain the text extracted from page images. We want these to be processed by <b>PagedImgPlug</b>, not <b>TEXTPlug</b>. Switch to the <b>Design</b> panel and delete <b>TEXTPlug</b>. While you are at it, you could tidy things up by deleting <b>HTMLPlug</b>, <b>EMAILPlug</b>, <b>PDFPlug</b>, <b>RTFPlug</b>, <b>WordPlug</b>, and <b>PSPlug</b> as well, since they will not be used.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0681">Now go to the <b>Create</b> panel, <b>build</b> the collection and <b>preview</b> the result. Search for <i>waka</i> and view one of the titles listed (all three appear as <i>Te Whetu o Te Tau</i>). Browse by <i>titles a-z </i>and view one of the <i>Te Waka o Te Iwi</i> titles.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0682">This collection was built with Greenstone's default settings. You can locate items of interest, but the information is less clearly and attractively presented than in the full Niupepa collection. </Text>
+</Comment>
+<Heading>
+<Text id="0683">Grouping documents by series title and displaying dates within each group</Text>
+</Heading>
+<Comment>
+<Text id="0684">Under titles a-z documents from the same series are repeated without any distinguishing features such as date. It would be better to group them by series title and display dates within each group. This can be accomplished using an AZCompactList classifier rather than AZList, and tuning the VList format statement.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0685">In the <b>Design</b> panel, under the <b>Browsing Classifiers </b>section, delete the <b>AZList</b> classifiers for <i>ex.Source </i>and <i>ex.Title</i>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0686">Now add <b>AZCompactList</b> for <i>ex.Title</i> and <b>DateList</b> for <i>ex.Date</i>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0687"><b>Modify</b></Text>
+<Text id="0688"> the format statement for <b>VList</b>. Find the part of the default statement that says</Text>
+<Format>{If}{[ex.Source],&lt;br&gt;&lt;i&gt;([ex.Source])&lt;/i&gt;}</Format> 
+<Text id="0689">and change it to</Text>
+<Format>{If}{[ex.Date],: [ex.Date]}</Format> 
+<Text id="0690">This has the effect of displaying the extracted date information, if present.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0691">At the end of this format statement, where is says:</Text>
+<Format>&lt;/td&gt;</Format> 
+<Text id="0692">append</Text>
+<Format>{If}{[numleafdocs],&lt;td&gt;([numleafdocs] items)&lt;/td&gt;}</Format> 
+<Comment2>
+<Text id="0693">As a consequence of using the AZCompactList classifier, bookshelf icons appear when titles are browsed. This revised format statement has the effect of specifying in brackets how many items are contained within a bookshelf. It works by exploiting the fact that only bookshelf icons define [numleafdocs] metadata.</Text>
+</Comment2>
+</NumberedItem>
+<Heading>
+<Text id="0694">Suppressing dummy text</Text>
+</Heading>
+<Comment>
+<Text id="0695">When you reach a newspaper, only its associated text is displayed. When either of the Te Waka o Te Iwi newspapers is accessed, the document view presents the message This document has no text. No scanned image information (screen-view resolution or otherwise) is shown, even though it has been computed and stored with the document. This can be fixed by a format statement that modifies the default behaviour for DocumentText.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0696">Staying within the <b>Format Features</b> section of the <b>Design </b>panel, under "Choose Feature" select <b>DocumentText</b>. Its HTML format string is empty, triggering the default behaviour of displaying the document's plain text, or, if there is none, "This document has no text". Change this to:</Text>
+<Format>&lt;center&gt;<br/>  &lt;table width=_pagewidth_&gt;<br/>  &lt;tr&gt;<br/>  &lt;td valign=top&gt;[srclink][screenicon][/srclink]&lt;/td&gt;<br/>  &lt;td&gt;[Text]&lt;/td&gt;<br/>  &lt;/tr&gt;<br/>  &lt;/table&gt;<br/> &lt;/center&gt;</Format>
+<Text id="0697">(available as niupepa\doc_tweak.txt)</Text>
+<Comment2>
+<Text id="0698">Including [screenicon] has the effect of embedding the screen-sized image generated by switching the screenview option on in PagedImgPlug. It is hyperlinked to the original image by the construct [srclink]âŠ[/srclink].</Text>
+</Comment2>
+</NumberedItem>
+<NumberedItem>
+<Text id="0699">Switch to the <b>Create </b>panel<b>;</b> <b>build</b> and <b>preview</b> the revised collection.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0700">If you like, add a logo and change the background as you have done before. You will find a suitable image in the file <i>niupepa\images</i>, that is activated through <i>macros\extra.dm</i>.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0701">In the collection you have just built, newspapers are grouped by series title, and dates are supplied alongside each one to distinguish it from others in the same series. Users can browse chronologically by date, and when a newspaper page is viewed a preview image is shown on the left that displays the original high-resolution version when clicked, accompanied on the right by the plain-text version of that newspaper (if available).</Text>
+</Comment>
+</Content>
+</Tutorial>
+<Tutorial id="OAI_collection">
+<Title>
+<Text id="0702">Open Archives Initiative (OAI) collection</Text>
+</Title>
+<Prerequisite id=""/>
+<SampleFiles folder=""/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<Comment>
+<Text id="0703">This exercise explores service-level interoperability using the Open Archive Initiative Protocol for Metadata Harvesting (OAI-PMH). So that you can do this on a stand-alone computer, we do not actually connect to the external server that is acting as the data provider. Instead we have provided an appropriate set of files that take the form of XML records produced by the OAI-PMH protocol. </Text>
+</Comment>
+<Comment>
+<Text id="0704">One of Greenstone's documented example collections is sourced over OAI. This exercise takes you through the steps necessary to reconstruct it. (Note: this example is a collection of images: you will not be able to build it unless ImageMagick is installed on your computer.) You may wish to take a look at the documented example collection OAI demo now to see what this exercise will build.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0705">Start a new collection called <b>OAI Service Provider</b>. Fill out the fields with appropriate information. You can leave the default metadata set as Dublin Core, although we do not make use of it.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0706">In the <b>Gather</b> panel, navigate to the <i>sample_small </i>folder in <i>sample_files/oai</i>. Drag this folder into the collection and drop it there.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0707">During the copy operation, a popup window appears asking whether to add <b>OAIPlug</b> to the list of plug-ins used in the collection, because the Librarian Interface has not found an existing plug-in that can handle this file type. Press the <b>&lt;Add Plugin&gt;</b> button to include it.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0708">When files are copied across like this, the Librarian Interface studies each one and uses its filename extension to check whether the collection contains a corresponding plug-in. Up until now, the answer has always been yes, so all file transfers have proceeded without interruption. This time, however, no plug-in in the list is capable of processing the OAI file records that are copied across (they have the file extension .oai).</Text>
+</Comment>
+<Comment>
+<Text id="0709">Sometimes there is more than one plug-in that could process a file--for example, the .xml extension is used for many different XML formats. The popup window, therefore, offers a choice of all possible plug-ins that matched. It is normally easy to determine the correct choice. If you wish, you can ignore the prompt (click &lt;Don't Add Plugin&gt;), because plug-ins can be added later, in the Document Plugins section of the Design panel.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0710">You need to configure the Image plug-in. In the <b>Design</b> panel, select the <b>Document Plugins</b> section, then select the <b>plugin ImagePlug</b> line and click &lt;<b>Configure Plugin&gt;</b>. In the resulting popup window locate the <b>screenviewsize</b> option, switch it on, and type the number 300 in the box beside it to create a screen-view image of 300 pixels. Click &lt;<b>OK&gt;</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0711">Now switch to the <b>Create</b> panel and <b>build</b> and <b>preview</b> the collection.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0712">Like other collections we have built by relying on Greenstone defaults, the end result is passable but can be improved. The next steps refine the collection using the metadata harvested by OAI-PMH into the .oai files.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0713">In the <b>Browsing Classifiers</b> section of the <b>Design </b>panel, delete the two <b>AZList</b> classifiers (<i>ex.Title</i> and <i>ex.Source</i>).</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0714">Add an <b>AZCompactList</b> classifier based on <b>ex.Subject</b> metadata.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0715">Now add an <b>AZCompactList</b> classifier based on <b>ex.Description </b>metadata. In its configuration panel select <b>mincompact</b> = <b>1</b>, <b>maxcompact</b> = <b>10</b> and <b>buttonname</b> = <b>Captions</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0716">In the <b>Search Indexes</b> section of the <b>Design</b> panel, delete all indexes and add a new one called "captions" based on <i>ex.Description </i>metadata.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0717"><b>Build</b> collection and <b>preview</b> it.</Text>
+</NumberedItem>
+<Heading>
+<Text id="0718">Tweaking the presentation with format statements</Text>
+</Heading>
+<NumberedItem>
+<Text id="0719">In the <b>Design</b> panel, select <b>Format Features</b>. First replace the <b>VList</b> format statement with this:</Text>
+<Format>
+&lt;td&gt;<br/> 
+{If}{[numleafdocs],[link][icon][/link],[link][thumbicon]<br/> 
+ [/link]}<br/> 
+&lt;/td&gt;<br/> 
+&lt;td valign=middle&gt;<br/> 
+ {If}{[numleafdocs],[Title],&lt;i&gt;[Description]&lt;/i&gt;}<br/> 
+&lt;/td&gt;
+</Format> 
+<Text id="0720">You will find this text in the file <i>vlist_tweak.txt </i>in the <i>oai/format_tweaks</i> folder of <i>sample_files. </i>Remember to press &lt;<b>Replace Format</b>&gt; when finished</Text>
+<Comment2>
+<Text id="0721">This format statement customizes the appearance of vertical lists such as the search results and captions lists to show a thumbnail icon followed by Description metadata. Greenstone's default is to use extracted metadata, so [Description] is the same as [ex.Description].</Text>
+</Comment2></NumberedItem>
+<NumberedItem>
+<Text id="0722">Next, select <b>DocumentHeading</b> from the <b>Choose Feature</b> pull-down list and make its format statement (which is currently blank) read</Text>
+<Format>&lt;h3&gt;[Subject]&lt;/h3&gt;</Format> 
+<Comment2>
+<Text id="0723">The document heading appears above the detach and no highlighting buttons when you get to a document in the collection. By default DocumentHeading displays the document's ex.Title metadata. In this particular set of OAI exported records, titles are filenames of JPEG images, and the filenames are particularly uninformative (for example, 01dla14). You can see them in the <b>Enrich</b> panel if you select an image in sample_small--&gt;</Text>
+<Text id="0724">oai--&gt;</Text>
+<Text id="0725"> JCDLPICS--&gt;</Text>
+<Text id="0726">srcdocs and check its filename and ex.Title metadata. The above format statement displays ex.Subject metadata instead.</Text>
+</Comment2></NumberedItem>
+<NumberedItem>
+<Text id="0727">Finally, you will have noticed that where the document itself should appear, you see only <i>This document has no text</i>. To rectify this, select <b>DocumentText</b> in the <b>Choose Feature</b> pull-down list and use the following as its format statement (which is currently blank) (this text is in </Text>
+<Text id="0728"><i>doctxt_tweak.txt</i></Text>
+<Text id="0729"> in the <i>format_tweaks</i> folder mentioned earlier):</Text>
+<Format>&lt;center&gt;&lt;table width=_pagewidth_ border=1&gt;<br/> 
+&lt;tr&gt;&lt;td colspan=2 align=center&gt;<br/> 
+&lt;a href=[OrigURL]&gt;[screenicon]&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;<br/> 
+&lt;tr&gt;&lt;td&gt;Caption:&lt;/td&gt;&lt;td&gt; &lt;i&gt;[Description]&lt;/i&gt; &lt;br&gt;<br/> 
+(&lt;a href=[OrigURL]&gt;original [ImageWidth]x[ImageHeight] [ImageType] available&lt;/a&gt;)<br/> 
+&lt;/td&gt;&lt;/tr&gt;<br/> 
+&lt;tr&gt;&lt;td&gt;Subject:&lt;/td&gt;&lt;td&gt; [Subject]&lt;/td&gt;&lt;/tr&gt;<br/> 
+&lt;tr&gt;&lt;td&gt;Publisher:&lt;/td&gt;&lt;td&gt; [Publisher]&lt;/td&gt;&lt;/tr&gt;<br/> 
+&lt;tr&gt;&lt;td&gt;Rights:&lt;td&gt; [Rights]&lt;/td&gt;&lt;/tr&gt;<br/> 
+&lt;/table&gt;&lt;/center&gt;</Format> 
+<Text id="0730">This format statement alters how the document view is presented. It includes a screen-sized version of the image that hyperlinks back to the original larger version available on the web. Factual information extracted from the image, such as width, height and type, is also displayed.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0731">Format statements are processed by the runtime system, so the collection does not need to be rebuilt for these changes to take effect. Switch to the <b>Design</b> panel and press &lt;<b>Preview Collection</b>&gt; to see the changes.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0732">To expedite building, this collection contains fewer source documents than the pre-built version supplied with the Greenstone installation. However, after these modifications, its functionality is the same.</Text>
+</Comment>
+</Content>
+</Tutorial>
+<Tutorial id="OAI_downloading">
+<Title>
+<Text id="0733">Downloading over OAI</Text>
+</Title>
+<Prerequisite id=""/>
+<SampleFiles folder=""/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<Comment>
+<Text id="0734">The previous exercise did not obtain the data from an external OAI-PMH server. This missing step is accomplished by running a command-line program. To do this, your computer must have a direct connection to the Internet--being behind a firewall may interfere with the ability to download the information.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0735"><b>Save</b> your collection. Note its directory name, which should be <i>oaiservi </i>(it appears in the title bar of the Librarian Interface), and <b>quit</b> the Librarian Interface.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0736">In a text editor (e.g. WordPad), open the collection's configuration file, which is in <i>C:\Program Files\Greenstone\collect\oaiservi\etc\collect.cfg</i>. Add the following line (all on one line):</Text>
+<Command>acquire OAI -src rocky.dlib.vt.edu/~jcdlpix/cgi-bin/OAI1.1/jcdlpix.pl -getdoc</Command>
+<Text id="0737">Although the position of this line is not critical, we recommend that you place it near the beginning of the file, after the public and creator lines but before the index line. Save the file and quit the editor.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0738">Delete the contents of the collection's <i>import</i> folder. This contains the canned version of the collection files, put there during the previous exercise. Now we want to witness the data arriving anew from the external OAI server.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0739">Open a DOS window to access the command-line prompt. This facility should be located somewhere within your Start--&gt;</Text>
+<Text id="0740">Programs menu, but details vary between different Windows systems. If you cannot locate it, select Start--&gt;</Text>
+<Text id="0741">Run and enter <i>cmd</i> in the popup window that appears.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0742">In the DOS window, move to the home directory where you installed Greenstone. This is accomplished by something like:</Text>
+<Format>cd C:\Program Files\Greenstone</Format> 
+</NumberedItem>
+<NumberedItem>
+<Text id="0743">Type:</Text>
+<Format>setup.bat</Format> 
+<Text id="0744">to set up the ability to run Greenstone command-line programs.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0745">Change directory into the folder containing the OAI Services Provider collection you built in the last exercise.</Text>
+<Format>cd collect\oaiservi</Format> 
+<Comment2>
+<Text id="0746">Even though the collection name used capital letters the directory generated by the Librarian Interface is all lowercase.</Text>
+</Comment2></NumberedItem>
+<NumberedItem>
+<Text id="0747">Run <i>perl -S importfrom.pl oaiservi</i></Text>
+<Comment>
+<Text id="0748">Greenstone will immediately set to work and generate a stream of diagnostic output. The importfrom.pl program connects to the OAI data provider specified in collection configuration file (it does this for each "acquire" line in the file) and exports all the records on that site.</Text>
+</Comment></NumberedItem>
+<NumberedItem>
+<Text id="0749">The downloaded files are saved in the collection's import folder. Once the command is finished, everything is in place and the collection is ready to be built. Confirm you have successfully acquired the OAI records by rebuilding the collection.</Text>
+</NumberedItem>
+</Content>
+</Tutorial>
+<Tutorial id="METS_export">
+<Title>
+<Text id="0750">Use METS as Greenstone's Internal Representation</Text>
+</Title>
+<Prerequisite id=""/>
+<SampleFiles folder=""/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<NumberedItem>
+<Text id="0751">In the Greenstone Librarian Interface, open the <b>Tudor</b> collection.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0752">To be able to substitute METSPlug for GAPlug you need to be in Expert mode.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0753">Click <i>File</i>--&gt;</Text>
+<Text id="0754"><i>Preferences</i>--&gt;</Text>
+<Text id="0755"><i>Mode </i>and change to <i>Expert</i> mode.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0756">Switch to the <b>Design</b> panel select <b>Document Plugins</b>. Remove <b>GAPlug </b>from the list of plug-ins and add <b>METSPlug</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0757">Now change to the <b>Create </b>panel, locate the options for the import process and set <i>-saveas </i>to <i>METS</i>. Import options are not available unless you are in <i>Expert</i> mode.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0758">Rebuild the collection.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0759">In your Windows file browser, locate the <i>archives </i>folder for the Tudor collection. For each document in the collection, Greenstone has generated two files: <i>docmets.xml</i>, the core METS description, and <i>doctxt.xml</i>,<i> </i>a supporting file. (Note: unless you are connected to the Internet you will be unable to view <i>doctxt.xml</i> in your web browser, because it refers to a remote resource.) Depending on the source documents there may be additional files, such as the images used within a web page. One of MET's many features is the ability to reference information in external XML files. Greenstone uses this to tie the content of the document, which is stored in the external XML file <i>doctxt.xml</i>, to its hierarchical structure, which is described in the core METS file <i>docmets.xml</i>.</Text>
+</NumberedItem>
+</Content>
+</Tutorial>
+<Tutorial id="dspace_to_greenstone">
+<Title>
+<Text id="0760">Moving a collection from DSpace to Greenstone</Text>
+</Title>
+<Prerequisite id=""/>
+<SampleFiles folder=""/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<NumberedItem>
+<Text id="0761">If you have just done the previous exercise the Greenstone Librarian Interface will already be in <i>Expert</i> mode. Otherwise, change to <i>Library System Specialist</i> (or <i>Expert</i>) mode (using File--&gt;</Text>
+<Text id="0762">Preferences), because you will need to change the order of plug-ins in the <b>Design</b> panel.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0763">Start a <b>new collection</b> called <b>StoneD</b> and fill out its fields appropriately. Leave the metadata set at Dublin Core, the default.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0764">Switch to the <b>Design </b>panel and select the <b>Document Plugins</b> section on the left-hand side. <b>Remove</b> <b>TEXTPlug</b>, <b>HTMLPlug</b> and <b>EMAILPlug</b>. Strictly speaking we do not need to remove these, however it reduces clutter.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0765">Now add <b>DSpacePlug</b>. Leave the plugin options at their defaults and press &lt;<b>OK</b>&gt;.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0766">Using the up and down arrows, <b>Move</b> the position of <b>DSpacePlug</b> to above <b>PDFPlug</b> and below <b>GAPlug</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0767">Now add <b>MP3Plug</b>, with the default configuration options. Its position in the plug-in pipeline need not be changed.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0768">In the <b>Gather</b> panel, locate the folder <b>sample_files\dspace\exported_docs</b>. It contains five example items exported from a DSpace institutional repository. Copy them into your collection by dragging them over to the right-hand side of the panel.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0769"><b>Build</b> the collection and <b>preview</b> it to see the basic defaults exhibited by a DSpace collection.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0770">If you browse by titles a-z, you will find 7 documents listed, though only 5 items were exported from DSpace. Two of the original items had alternative forms in their directory folder. DSpace plug-in options control what happens in such situations: the default is to treat them as separate Greenstone documents.</Text>
+</Comment>
+<Comment>
+<Text id="0771">Below we use a plug-in option (first_inorder_ext) to fuse the alternative forms together. This option has the effect of treating documents with the same filename but different extensions as a single entity within a collection. One of the files is viewed as the primary document--it is indexed, and metadata is extracted from it if possible--while the others are handled as "associated files."</Text>
+</Comment>
+<Comment>
+<Text id="0772">The first_inorder_ext option takes as its argument a list of file extensions (separated by commas): the first one in the list that matches becomes the primary document.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0773">Select <b>DSpacePlug</b> and click &lt;<b>Configure Plugin</b>&gt;. Switch on its configuration option <b>first_inorder_ext</b>. Set its value to <i>pdf,doc,mp3</i> in the popup window that appears and press <b>&lt;OK&gt;</b>.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0774"><b>Build</b> and <b>preview</b> the collection.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0775">There are now only 5 documents, because only one version of each document has been included--the primary version.</Text>
+</Comment>
+<Comment>
+<Text id="0776">The DSpace exported files contain Dublin Core metadata for title and author (amongst other things).</Text>
+</Comment>
+<Heading>
+<Text id="0777">Adding indexing and browsing capabilities to match DSpace's</Text>
+</Heading>
+<NumberedItem>
+<Text id="0778">In the <b>Design</b> panel, select <b>Search Indexes</b>. Delete the <i>ex.Title </i>and <i>ex.Source </i>indexes, and add one for <b>dc.Title</b> called "titles" and another for <b>dc.Contributor</b> called "authors".</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0779">Staying within the <b>Design</b> panel, select <b>Browsing Classifiers</b> and <b>delete</b> both <b>AZList</b> classifiers (<i>ex.Title </i>and <i>ex.Source</i>). Add an <b>AZList</b> classifier for <b>dc.Title</b> and an <b>AZCompactList</b> classifier for <b>dc.Contributor</b>. Check the <b>mingroup</b> box in this classifier and set its field to 1<b>.</b></Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0780">Now select the <b>Format Features </b>section of the <b>Design</b> panel and replace the <b>VList</b> format statement with this:</Text>
+<Format>&lt;td valign=top&gt;[link][icon][/link]&lt;/td&gt;<br/> &lt;td valign=top&gt;<br/>  [srclink][srcicon][/srclink]<br/> &lt;/td&gt;<br/> &lt;td valign=top&gt;<br/> [highlight]{Or}{[dc.Title],[ex.Title],Untitled}[/highlight]<br/>  {If}{[ex.Source],&lt;br&gt;<br/>  &lt;i&gt;([ex.Source])&lt;/i&gt;}{If}{[equivlink],&lt;br&gt;<br/>  Also available as:[equivlink]}<br/> &lt;/td&gt; </Format>
+<Text id="0781">You will find this text in the file <i>format_tweak.txt </i>in the <i>dspace </i>folder of <i>sample_files</i>, and you can copy and paste this. Remember to press &lt;<b>Replace Format</b>&gt; when finished.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0782">Also, let's add a format statement for the classifier based on <b>dc.Contributor</b> metadata. In the <b>Choose Feature </b>menu (under <b>Format Features </b>on the <b>Design </b>panel), select the item that says:</Text>
+<Indent>
+CL2: AZCompactList -metadata dc.Contributor -mingroup 1
+</Indent> 
+</NumberedItem>
+<NumberedItem>
+<Text id="0783">Leave <b>VList</b> in the <b>Affected Component</b> and edit the text in the <b>HTML Format String</b> box so that it looks like:</Text>
+<Format>
+&lt;td valign=top&gt;[link][icon][/link]&lt;/td&gt;<br/> 
+&lt;td valign=top&gt;<br/>  
+[srclink][srcicon][/srclink]<br/> 
+&lt;/td&gt;<br/> 
+&lt;td valign=top&gt;<br/> 
+[highlight] <br/>  
+{If}{[numleafdocs],([numleafdocs]) [ex.Title],[dc.Title]}<br/> 
+[/highlight]<br/>
+  {If}{[ex.Source],&lt;br&gt;<br/>
+  &lt;i&gt;([ex.Source])&lt;/i&gt;}{If}{[equivlink],&lt;br&gt;<br/>
+  Also available as:[equivlink]}<br/>
+ &lt;/td&gt;</Format>
+<Text id="0784">and click &lt;<b>Add Format</b>&gt;. This will display the number of documents for each bookshelf in the authors classifier.</Text>
+<Text id="0785">You will find this text in the file <i>format_contributor.txt </i>in the <i>dspace </i>folder of <i>sample_files</i>, and you can copy and paste this.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0786"><b>Build</b> collection once again and <b>preview</b> it.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0787">There are still only 5 documents, but against some of the entries--for example, Interview with Bob Dylan--appears the line "Also available as," followed by icons that link to the alternative representations.</Text>
+</Comment>
+</Content>
+</Tutorial>
+<Tutorial id="greenstone_to_dspace">
+<Title>
+<Text id="0788">Moving a collection from Greenstone to DSpace</Text>
+</Title>
+<Prerequisite id=""/>
+<SampleFiles folder=""/>
+<Version initial="2.60" current="2.60"/>
+<Content>
+<Comment>
+<Text id="0789">In this exercise you export a Greenstone collection in a form suitable for DSpace. It is possible to do this from the Librarian Interface's File menu, which contains an item called Export... that allows you to export collections in different forms. However, to gain a deeper understanding of Greenstone, we perform the work by invoking a program from the Windows command-line prompt. This requires some technical skill; if you are not used to working in the command-line environment we recommend that you skip this exercise.</Text>
+</Comment>
+<Heading>
+<Text id="0790">Using Greenstone from the command line</Text>
+</Heading>
+<NumberedItem>
+<Text id="0791">Perform the first four steps of the "Downloading over OAI" exercise: open a command window, change directory to where Greenstone is installed, run <i>setup.bat</i>,and change directory once again, this time into <i>collect\stoned</i>, the collection you built in the last exercise.</Text>
+</NumberedItem>
+<NumberedItem>
+<Text id="0792">Run the following command to export the collection using the DSpace import/export format:</Text>
+<Command>perl -S export.pl -saveas DSpace -removeold stoned</Command> 
+</NumberedItem>
+<Comment>
+<Text id="0793">Exporting in Greenstone is an additive process. If you ran the export.pl command once again, the new files exported would be added--with different folder names--to those already in the export folder. For the kind of explorations we are conducting we might re-run the command several times. The -removeold option deletes files that have previously been exported.</Text>
+</Comment>
+<NumberedItem>
+<Text id="0794">This command has created a new subfolder, <i>collect\stoned\export</i>. Use the file browser to explore it. In it are the files needed to ingest this set of documents into DSpace.</Text>
+</NumberedItem>
+<Comment>
+<Text id="0795">You could equally well run the export.pl command on a different Greenstone collection and transfer the output to a DSpace installation by using DSpace's batch-import facility.</Text>
+</Comment>
+</Content>
+</Tutorial>
+</TutorialList>
Index: /tags/start/gsdl/bin/script/buildcol.pl
===================================================================
--- /tags/start/gsdl/bin/script/buildcol.pl	(revision 13666)
+++ /tags/start/gsdl/bin/script/buildcol.pl	(revision 13666)
@@ -0,0 +1,111 @@
+#!/usr/local/bin/perl5 -w
+
+# This program will build a particular collection
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/lib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/lib/plugins");
+}
+
+use parsargv;
+use util;
+
+&main();
+
+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 "   -archivedir directory Where the archives live\n";
+    print STDERR "   -cachedir directory   Where to cache the archives\n";
+    print STDERR "   -builddir directory   Where to put the built indexes\n\n";
+}
+
+
+sub main
+{
+    if (!parsargv::parse(\@ARGV, 
+			 'verbosity/\d+/2', \$verbosity,
+			 'archivedir/.*/', \$archivedir,
+			 'cachedir/.*/', \$cachedir,
+			 'builddir/.*/', \$builddir)) {
+	&print_usage();
+	die "\n";
+    }
+
+    # get and check the collection
+    ($collection) = @ARGV;
+    if (!defined ($collection)) {
+	&print_usage();
+	die "\n";
+    }
+    if (!-e "$ENV{'GSDLHOME'}/collect/$collection") {
+	die "Invalid collection name ($collection).\n";
+    }
+
+    # fill in the default archives and building directories if none
+    # were supplied, turn all \ into / and remove trailing /
+    $archivedir = "$ENV{'GSDLHOME'}/collect/$collection/archives" if $archivedir eq "";
+    $archivedir =~ s/[\\\/]+/\//g;
+    $archivedir =~ s/\/$//;
+    $builddir = "$ENV{'GSDLHOME'}/collect/$collection/building" if $builddir eq "";
+    $builddir =~ s/[\\\/]+/\//g;
+    $builddir =~ s/\/$//;
+
+    # update the archive cache if needed
+    if ($cachedir) {
+	print STDERR "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);
+
+
+    # if a builder class has been created for this collection, use it
+    # otherwise, use the mg builder
+    if (-e "$ENV{'GSDLHOME'}/collect/$collection/lib/${collection}builder.pm") {
+	$builderdir = "$ENV{'GSDLHOME'}/collect/$collection/lib";
+	$buildertype = "${collection}builder";
+    } else {
+	$builderdir = "$ENV{'GSDLHOME'}/lib";
+	$buildertype = "mgbuilder";
+    }
+	
+    require "$builderdir/$buildertype.pm";
+
+    eval("\$builder = new $buildertype(\$collection, " .
+	 "\$realarchivedir, \$realbuilddir, \$verbosity)");
+    die "$@" if $@;
+
+    $builder->init();
+    $builder->compress_text();
+    $builder->build_indexes();
+    $builder->make_infodatabase();
+    $builder->make_auxiliary_files();
+    $builder->deinit();
+
+
+    if ($realbuilddir ne $builddir) {
+	print STDERR "Copying back the cached build\n" if ($verbosity >= 1);
+	&util::rm_r ($builddir);
+	&util::cp_r ($realbuilddir, $builddir);
+    }
+}
+
+
Index: /tags/start/gsdl/bin/script/gettext.pl
===================================================================
--- /tags/start/gsdl/bin/script/gettext.pl	(revision 13666)
+++ /tags/start/gsdl/bin/script/gettext.pl	(revision 13666)
@@ -0,0 +1,91 @@
+#!/usr/local/bin/perl5 -w
+
+# This program will output the text for a particular index
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/lib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/lib/plugins");
+}
+
+use parsargv;
+use plugin;
+use colcfg;
+
+sub print_usage {
+    print STDERR "\n  usage: $0 collection-name\n";
+    print STDERR "  options:\n";
+    print STDERR "   -index index   The index to output\n\n";
+}
+
+
+&main ();
+
+sub main {
+
+    if (!parsargv::parse(\@ARGV, 
+			 'index/.*/section:text', \$index,
+			 'mode/.*/text', \$mode)) {
+	&print_usage();
+	die "\n";
+    }
+
+    # get and check the collection name
+    ($collection) = @ARGV;
+
+    if (!defined($collection)) {
+	&print_usage();
+	die "\n";
+    }
+    
+    # get the list of plugins for this collection
+    @plugins = ("RecPlug", "HTMLPlug", "TXTPlug");
+    if (-e "$ENV{'GSDLHOME'}/collect/$collection/collect.cfg") {
+	$collectcfg = &colcfg::read_collect_cfg ("$ENV{'GSDLHOME'}/collect/$collection/collect.cfg");
+	if (defined $collectcfg->{'plugins'}) {
+	    @plugins = @{$collectcfg->{'plugins'}};
+	}
+    }
+    
+
+    # load all the plugins
+    $pluginfo = &plugin::load_plugins ($collection, \@plugins);
+    if (scalar(@$pluginfo) == 0) {
+	print STDERR "No plugins were loaded.\n";
+	die "\n";
+    }
+
+    # load up the document processor for building
+    # if a buildproc class has been created for this collection, use it
+    # otherwise, use the mg buildproc
+    my ($buildprocdir, $buildproctype);
+    if (-e "$ENV{'GSDLHOME'}/collect/$collection/lib/${collection}buildproc.pm") {
+	$buildprocdir = "$ENV{'GSDLHOME'}/collect/$collection/lib";
+	$buildproctype = "${collection}buildproc";
+    } else {
+	$buildprocdir = "$ENV{'GSDLHOME'}/lib";
+	$buildproctype = "mgbuildproc";
+    }
+    require "$buildprocdir/$buildproctype.pm";
+
+    my $source_dir = "$ENV{'GSDLHOME'}/collect/$collection/archives";
+    my $build_dir = "$ENV{'GSDLHOME'}/collect/$collection/building";
+    my $verbosity = 1;
+
+    eval("\$buildproc = new $buildproctype(\$collection, " .
+	 "\$source_dir, \$build_dir, \$verbosity)");
+    die "$@" if $@;
+
+    # set up the document processor
+    $buildproc->set_output_handle ('STDOUT');
+    $buildproc->set_mode ($mode);
+    $buildproc->set_index ($index);
+
+    $buildproc->reset();
+
+    # process the import directory
+    &plugin::read ($pluginfo, $source_dir, 
+		   "", {}, $buildproc);
+
+}
Index: /tags/start/gsdl/bin/script/gsdlinfo.pl
===================================================================
--- /tags/start/gsdl/bin/script/gsdlinfo.pl	(revision 13666)
+++ /tags/start/gsdl/bin/script/gsdlinfo.pl	(revision 13666)
@@ -0,0 +1,110 @@
+#!/usr/local/bin/perl5 -w
+
+# 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'}/lib");
+}
+
+use parsargv;
+use colcfg;
+
+
+# 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)$/) {
+	# do nothing
+
+    } else {
+	# read in the collection configuration file
+	my $collectcfg = {};
+	if (-e "$ENV{'GSDLHOME'}/collect/$dir/collect.cfg") {
+	    $collectcfg = &colcfg::read_collect_cfg ("$ENV{'GSDLHOME'}/collect/$dir/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/start/gsdl/bin/script/import.pl
===================================================================
--- /tags/start/gsdl/bin/script/import.pl	(revision 13666)
+++ /tags/start/gsdl/bin/script/import.pl	(revision 13666)
@@ -0,0 +1,69 @@
+#!/usr/local/bin/perl5 -w
+
+# This program will import a number of files into a particular collection
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/lib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/lib/plugins");
+}
+
+use arcinfo;
+use colcfg;
+use plugin;
+use docsave;
+
+
+sub print_usage {
+    print STDERR "\n  usage: $0 collection-name\n";
+}
+
+
+&main ();
+
+sub main {
+    # get and check the collection name
+    ($collection) = @ARGV;
+    if (!defined($collection)) {
+	&print_usage();
+	die "\n";
+    }
+    
+    if ($collection eq "modelcol") {
+	print STDERR "You can't import documents into modelcol.\n";
+	die "\n";
+    }
+    
+    # get the list of plugins for this collection
+    @plugins = ("RecPlug", "HTMLPlug", "TXTPlug");
+    if (-e "$ENV{'GSDLHOME'}/collect/$collection/collect.cfg") {
+	$collectcfg = &colcfg::read_collect_cfg ("$ENV{'GSDLHOME'}/collect/$collection/collect.cfg");
+	if (defined $collectcfg->{'plugins'}) {
+	    @plugins = @{$collectcfg->{'plugins'}};
+	}
+    }
+    
+
+    # load all the plugins
+    $pluginfo = &plugin::load_plugins ($collection, \@plugins);
+    if (scalar(@$pluginfo) == 0) {
+	print STDERR "No plugins were loaded.\n";
+	die "\n";
+    }
+    
+    # read the archive information file
+    $archive_info_filename = "$ENV{'GSDLHOME'}/collect/$collection/archives/archives.inf";
+    $archive_info = new arcinfo ();
+    $archive_info->load_info ($archive_info_filename);
+
+    # create a docsave object to process the documents
+    $processor = new docsave ($collection, $archive_info);
+
+    # process the import directory
+    &plugin::read ($pluginfo, "$ENV{'GSDLHOME'}/collect/$collection/import/", 
+		   "", {}, $processor);
+    
+    # write out the archive information file
+    $archive_info->save_info($archive_info_filename);
+}
Index: /tags/start/gsdl/bin/script/mkcol.pl
===================================================================
--- /tags/start/gsdl/bin/script/mkcol.pl	(revision 13666)
+++ /tags/start/gsdl/bin/script/mkcol.pl	(revision 13666)
@@ -0,0 +1,159 @@
+#!/usr/local/bin/perl5 -w
+
+# 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.
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/lib");
+}
+
+use parsargv;
+
+sub print_usage {
+    print STDERR "\n  usage: $0 [options] collection-name\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -creator email      Your email address\n";
+    print STDERR "   -maintainer email   The current maintainer's email address\n";
+    print STDERR "   -public true|false  If this collection has anonymous access\n";
+    print STDERR "   -beta true|false    If this collection is still under development\n";
+    print STDERR "   -index type         The indexes which should be made\n";
+    print STDERR "   -indextext name     The index description\n";
+    print STDERR "   -defaultindex type  The index to use if no others are supplied\n\n";
+}
+
+sub traverse_dir
+{
+    my ($modeldir, $coldir) = @_;
+    my ($newfile, @filetext);
+
+    if (!(-e $coldir)) {
+	if (!mkdir ($coldir, 0775)) {
+	    die "$!";
+	}
+    }
+
+    opendir(DIR, $modeldir) || die "Can't read $modeldir";
+    my @files = grep(!/^\.\.?$/, readdir(DIR));
+    closedir(DIR);
+
+    foreach $file (@files)
+    {
+	if (-d "$modeldir/$file") {
+	    traverse_dir ("$modeldir/$file", "$coldir/$file");
+
+	} else {
+	    my $destfile = $file;
+	    $destfile =~ s/^\modelcol/$collection/;
+	    $destfile =~ s/^\MODELCOL/$capcollection/;
+
+	    print STDERR "doing replacements for $modeldir/$file\n";
+	    open (INFILE, "$modeldir/$file") || 
+		die "Can't read file $modeldir/$file";
+	    open (OUTFILE, ">$coldir/$destfile") ||
+		die "Can't create file $coldir/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/\*\*beta\*\*/$beta/g;
+		$line =~ s/\*\*key\*\*/$key/g;
+		$line =~ s/\*\*indexes\*\*/$indexesstr/g;
+		$line =~ s/\*\*indexestext\*\*/$indexestextstr/g;
+		$line =~ s/\*\*defaultindex\*\*/$defaultindex/g;
+
+		print OUTFILE $line;
+	    }
+	    
+	    close (OUTFILE);
+	    close (INFILE);
+	}
+    }
+}
+
+
+my (@indexes, @indexestext);
+
+# get and check options
+if (!&parsargv::parse(\@ARGV,
+		       'creator/\w+\@[\w\.]+/', \$creator,
+		       'maintainer/\w+\@[\w\.]+/', \$maintainer,
+		       'public/true|false/true', \$public,
+		       'beta/true|false/true', \$beta,
+		       'index/.*/document:all', \@indexes,
+		       'indextext/\.*/Terms must appear within the same document', \@indexestext,
+		       'defaultindex/.*/document:all', \$defaultindex
+		       )) {
+    &print_usage();
+    die "\n";
+}
+    
+# get and check the collection name
+($collection) = @ARGV;
+if (!defined($collection)) {
+    &print_usage();
+    die "\n";
+}
+
+if (length($collection) > 8) {
+    print STDERR "The collection name must be less than 8 characters\n";
+    print STDERR "so compatibility with earlier filesystems can be\n";
+    print STDERR "maintained.\n";
+    die "\n";
+}
+
+if ($collection eq "modelcol") {
+    print STDERR "No collection can be named modelcol as this is the\n";
+    print STDERR "name of the model collection.\n";
+    die "\n";
+}
+
+if (!defined($creator) || $creator eq "") {
+    print STDERR "The creator was not defined. This variable is\n";
+    print STDERR "needed to recognise duplicate collection names.\n";
+    die "\n";
+}
+
+if (!defined($maintainer) || $maintainer eq "") {
+    $maintainer = $creator;
+}
+
+$public = "true" unless defined $public;
+$beta = "true" unless defined $beta;
+
+srand(time);
+$key = int(rand()*100000000.0) + int(rand()*100000000.0);
+
+# get capitalised version of the collection
+$capcollection = $collection;
+$capcollection =~ tr/a-z/A-Z/;
+
+
+# get the strings to include.
+$indexesstr = join ("\t", @indexes);
+$indexestextstr = "";
+for ($i=0; $i<scalar(@indexestext); $i++) {
+    $indexestextstr .= "_$indexes[$i]_[] {$indexestext[$i]}\n";
+}
+
+
+# make sure the model collection exists
+die "Cannot find the model collection $ENV{'GSDLHOME'}/collect/modelcol" unless
+    (-d "$ENV{'GSDLHOME'}/collect/modelcol");
+
+# make sure this collection does not already exist
+if (-e "$ENV{'GSDLHOME'}/collect/$collection") {
+    print STDERR "This collection already exists\n";
+    die "\n";
+}
+
+
+# start creating the collection
+print STDERR "Creating the collection $collection\n\n";
+&traverse_dir ("$ENV{'GSDLHOME'}/collect/modelcol", "$ENV{'GSDLHOME'}/collect/$collection");
+print STDERR "\n\nThe new collection is in $ENV{'GSDLHOME'}/collect/$collection.\n\n";
+
Index: /tags/start/gsdl/bin/script/perlcalc.pl
===================================================================
--- /tags/start/gsdl/bin/script/perlcalc.pl	(revision 13666)
+++ /tags/start/gsdl/bin/script/perlcalc.pl	(revision 13666)
@@ -0,0 +1,5 @@
+#! /usr/local/bin/perl5 -w
+
+while (defined($line=<STDIN>)) {
+	print eval($line), "\n";
+}
Index: /tags/start/gsdl/collect/modelcol/collect.cfg
===================================================================
--- /tags/start/gsdl/collect/modelcol/collect.cfg	(revision 13666)
+++ /tags/start/gsdl/collect/modelcol/collect.cfg	(revision 13666)
@@ -0,0 +1,8 @@
+creator	**creator**
+maintainer	**maintainer**
+public	**public**
+beta	**beta**
+key	**key**
+indexes	**indexes**
+defaultindex	**defaultindex**
+plugins	GMLPlug	ArcPlug	TOCPlug	HBPlug
Index: /tags/start/gsdl/perllib/arcinfo.pm
===================================================================
--- /tags/start/gsdl/perllib/arcinfo.pm	(revision 13666)
+++ /tags/start/gsdl/perllib/arcinfo.pm	(revision 13666)
@@ -0,0 +1,110 @@
+# This module stores information about the archives. At the moment
+# this information just consists of the file name (relative to the
+# directory the archives information file is in) and its OID.
+
+# This module assumes there is a one to one correspondance between
+# a file in the archives directory and an OID.
+
+
+package arcinfo;
+
+sub new {
+    my ($class) = @_;
+    my $self = {'info'=>{}};
+
+    return bless $self, $class;
+}
+
+sub load_info {
+    my $self = shift (@_);
+    my ($filename) = @_;
+
+    $self->{'info'} = {};
+
+    if (-e $filename) {
+	open (INFILE, $filename) || 
+	    die "arcinfo::load_info couldn't read $filename\n";
+
+	my ($line, @line);
+	while (defined ($line = <INFILE>)) {
+	    $line =~ s/\cM|\cJ//g; # remove end-of-line characters
+	    @line = split ("\t", $line); # filename, 
+	    if (scalar(@line) >= 2) {
+		$self->add_info ($line[0], $line[1]);
+	    }
+	}
+
+	close (INFILE);
+    }
+}
+
+sub save_info {
+    my $self = shift (@_);
+    my ($filename) = @_;
+
+    my ($OID);
+
+    open (OUTFILE, ">$filename") || 
+	die "arcinfo::save_info couldn't write $filename\n";
+
+    foreach $OID (keys(%{$self->{'info'}})) {
+	my $info = $self->get_info($OID);
+	if (defined $info) {
+	    print OUTFILE "$OID\t", join("\t", @$info), "\n";
+	}
+    }
+    
+    close (OUTFILE);
+}
+
+sub add_info {
+    my $self = shift (@_);
+    my ($OID, $doc_file) = @_;
+
+    $self->{'info'}->{$OID} = [$doc_file];
+}
+
+# returns a list of the form [[OID, doc_file], ...]
+sub get_OID_list {
+    my $self = shift (@_);
+
+    my ($OID);
+    my @list = ();
+
+    foreach $OID (sort(keys(%{$self->{'info'}}))) {
+	push (@list, [$OID, $self->{'info'}->{$OID}->[0]]);
+    }
+
+    return \@list;
+}
+
+# returns a list of the form [[doc_file, OID], ...]
+sub get_file_list {
+    my $self = shift (@_);
+
+    my ($OID);
+    my @list = ();
+
+    foreach $OID (sort(keys(%{$self->{'info'}}))) {
+	push (@list, [$self->{'info'}->{$OID}->[0], $OID]);
+    }
+
+    return \@list;
+}
+
+
+# returns a list of the form [doc_file]
+sub get_info {
+    my $self = shift (@_);
+    my ($OID) = @_;
+
+    if (defined $self->{'info'}->{$OID}) {
+	return $self->{'info'}->{$OID};
+    }
+
+    return undef;
+}
+
+
+1;
+
Index: /tags/start/gsdl/perllib/cfgread.pm
===================================================================
--- /tags/start/gsdl/perllib/cfgread.pm	(revision 13666)
+++ /tags/start/gsdl/perllib/cfgread.pm	(revision 13666)
@@ -0,0 +1,75 @@
+# reads in configuration files
+
+package cfgread;
+
+
+sub read_cfg_line {
+    my ($handle) = @_;
+    my $line = "";
+
+    while (defined($line = <$handle>)) {
+	$line =~ s/^\#.*$//; # remove comments
+	$line =~ s/\cM|\cJ//g; # remove end-of-line characters
+	if ($line =~ /\w/) {
+	    my @line = split(/\t/, $line);
+	    return \@line;
+	}
+    }
+    return undef;
+}
+
+sub write_cfg_line {
+    my ($handle, $line) = @_;
+    print $handle join ("\t", @$line), "\n";
+}
+
+
+# stringexp and arrayexp should be something like
+#   '^(this|that)$'
+sub read_cfg_file {
+    my ($filename, $stringexp, $arrayexp) = @_;
+    my ($line);
+    my $data = {};
+
+    if (open (COLCFG, $filename)) {
+	while (defined ($line = &read_cfg_line('COLCFG'))) {
+	    if (scalar(@$line) >= 2) {
+		my $key = shift (@$line);
+		if ($key =~ /$stringexp/) {
+		    $data->{$key} = shift (@$line);
+
+		} elsif ($key =~ /$arrayexp/) {
+		    push (@{$data->{$key}}, @$line);
+		}
+	    }
+	}
+	close (COLCFG);
+    } else {
+	print STDERR "cfgread::read_cfg_file couldn't read the cfg file $filename\n";
+    }
+
+    return $data;
+}
+
+
+# stringexp and arrayexp should be something like
+#   '^(this|that)$'
+sub write_cfg_file {
+    my ($filename, $data, $stringexp, $arrayexp) = @_;
+
+    if (open (COLCFG, ">$filename")) {
+	foreach $key (sort(keys(%$data))) {
+	    if ($key =~ /$stringexp/) {
+		&write_cfg_line ('COLCFG', [$key, $data->{$key}]);
+	    } elsif ($key =~ /$arrayexp/) {
+		&write_cfg_line ('COLCFG', [$key, @{$data->{$key}}]);
+	    }
+	}
+	close (COLCFG);
+    } else {
+	print STDERR "cfgread::write_cfg_file couldn't write the cfg file $filename\n";
+    }
+}
+
+
+1;
Index: /tags/start/gsdl/perllib/colcfg.pm
===================================================================
--- /tags/start/gsdl/perllib/colcfg.pm	(revision 13666)
+++ /tags/start/gsdl/perllib/colcfg.pm	(revision 13666)
@@ -0,0 +1,62 @@
+# reads in a collection configuration file
+
+package colcfg;
+
+use cfgread;
+
+
+# the collection configuration file data is stored in the form
+#
+# {'creator'}->string
+# {'maintainer'}->array of strings
+# {'public'}->string
+# {'beta'}->string
+# {'key'}->string
+# {'indexes'}->array of strings
+# {'defaultindex'}->string
+# {'plugins'}->array of strings
+
+sub read_collect_cfg {
+    my ($filename) = @_;
+
+    return &cfgread::read_cfg_file ($filename, 
+		    '^(creator|public|beta|key|defaultindex)$', 
+		    '^(maintainer|indexes|plugins)$');
+}
+
+sub write_collect_cfg {
+    my ($filename, $data) = @_;
+
+    &cfgread::write_cfg_file($filename, $data,
+		    '^(creator|public|beta|key|defaultindex)$', 
+		    '^(maintainer|indexes|plugins)$');
+}
+
+
+# the build configuration file data is stored in the form
+#
+# {'builddate'}->string
+# {'metadata'}->array of strings
+# {'languages'}->array of strings
+# {'numdocs'}->string
+# {'numwords'}->string
+# {'numbytes'}->string
+
+sub read_build_cfg {
+    my ($filename) = @_;
+
+    return &cfgread::read_cfg_file ($filename, 
+		    '^(builddate|numdocs|numwords|numbytes)$', 
+		    '^(metadata|languages)$');
+}
+
+sub write_build_cfg {
+    my ($filename, $data) = @_;
+
+    &cfgread::write_cfg_file($filename, $data,
+		    '^(builddate|numdocs|numwords|numbytes)$', 
+		    '^(metadata|languages)$');
+}
+
+
+1;
Index: /tags/start/gsdl/perllib/doc.pm
===================================================================
--- /tags/start/gsdl/perllib/doc.pm	(revision 13666)
+++ /tags/start/gsdl/perllib/doc.pm	(revision 13666)
@@ -0,0 +1,677 @@
+# class to hold documents
+
+package doc;
+
+use util;
+use html;
+
+# the document type may be indexed_doc, nonindexed_doc, or
+# classification
+
+sub new {
+    my $class = shift (@_);
+    my ($source_filename, $doc_type) = @_;
+    
+    my $self = bless {'associated_files'=>[],
+		      'subsection_order'=>[],
+		      'next_subsection'=>1,
+		      'subsections'=>{},
+		      'metadata'=>[],
+		      'text'=>""}, $class;
+
+    $self->set_source_filename ($source_filename) if defined $source_filename;
+    $self->set_doc_type ($doc_type) if defined $doc_type;
+
+    return $self;
+}
+
+sub set_source_filename {
+    my $self = shift (@_);
+    my ($source_filename) = @_;
+
+    $self->set_metadata_element ($self->get_top_section(), 
+				 "gsdlsourcefilename", 
+				 $source_filename);
+}
+
+# returns the source_filename as it was provided
+sub get_source_filename {
+    my $self = shift (@_);
+
+    return $self->get_metadata_element ($self->get_top_section(), "gsdlsourcefilename");
+}
+
+sub set_doc_type {
+    my $self = shift (@_);
+    my ($doc_type) = @_;
+
+    $self->set_metadata_element ($self->get_top_section(), 
+				 "gsdldoctype", 
+				 $doc_type);
+}
+
+# returns the source_filename as it was provided
+sub get_doc_type {
+    my $self = shift (@_);
+
+    return $self->get_metadata_element ($self->get_top_section(), "gsdldoctype");
+}
+
+sub output_section {
+    my $self = shift (@_);
+    my ($handle, $section, $suppress_subject_info) = @_;
+    $suppress_subject_info = 0 unless defined $suppress_subject_info;
+    my ($data, $subsection);
+    
+    my $section_ptr = $self->_lookup_section ($section);
+    my ($section_num) = $section =~ /(\d+)$/;
+    
+    return unless defined $section_ptr;
+
+    # output the section header (including the section number
+    # and metadata)
+    print $handle "<gsdlsection";
+    print $handle " gsdlnum=\"$section_num\"" if defined $section_num;
+    foreach $data (@{$section_ptr->{'metadata'}}) {
+	print $handle " $data->[0]=\"$data->[1]\"" 
+	    unless $suppress_subject_info && $data->[0] eq "Subject";
+    }
+    print $handle ">";
+
+    # output the text
+    print $handle $section_ptr->{'text'};
+
+    # output all the subsections
+    foreach $subsection (@{$section_ptr->{'subsection_order'}}) {
+	$self->output_section($handle, "$section.$subsection", $suppress_subject_info);
+    }
+    
+    # output the closing tag
+    print $handle "</gsdlsection>\n";
+}
+
+# look up the reference to the a particular section
+sub _lookup_section {
+    my $self = shift (@_);
+    my ($section) = @_;
+
+    my ($num);
+    my $sectionref = $self;
+
+    while ($section ne "") {
+	($num, $section) = $section =~ /^\.?(\d+)(.*)$/;
+	$num =~ s/^0+(\d)/$1/; # remove leading 0s
+	$section = "" unless defined $section;
+	
+	if (defined $num && defined $sectionref->{'subsections'}->{$num}) {
+	    $sectionref = $sectionref->{'subsections'}->{$num};
+	} else {
+	    return undef;
+	}
+    }
+    
+    return $sectionref;
+}
+
+sub _calc_OID {
+    my $self = shift (@_);
+    my ($filename) = @_;
+
+    my $hashfile_exe = "$ENV{'GSDLHOME'}/bin/$ENV{'GSDLOS'}/hashfile.exe";
+    my $result = "NULL";
+
+    if (-e "$hashfile_exe") {
+	$result = `$hashfile_exe \"$filename\"`;
+	($result) = $result =~ /:\s*([0-9a-f]+)/i;
+
+    } else {
+	print STDERR "doc::_calc_OID hashfile.exe could not be found\n";
+    }
+
+    return "HASH$result";
+}
+
+# methods dealing with OID, not groups of them.
+
+# if $OID is not provided one is calculated from hashing the
+# current contents of the document
+# An OID are actually stored as metadata of the document
+sub set_OID {
+    my $self = shift (@_);
+    my ($OID) = @_;
+
+    # if an OID wasn't provided then feed this document to 
+    # hashfile.exe
+    if (!defined $OID) {
+	$OID = "NULL";
+	my $tmp_filename = &util::get_tmp_filename();
+	if (!open (OUTFILE, ">$tmp_filename")) {
+	    print STDERR "doc::set_OID could not write to $tmp_filename\n";
+	} else {
+	    $self->output_section('OUTFILE', $self->get_top_section(), 1);
+	    close (OUTFILE);
+
+	    $OID = $self->_calc_OID ($tmp_filename);
+	    &util::rm ($tmp_filename);
+	}
+    }
+
+    $self->set_metadata_element ($self->get_top_section(), "Identifier", $OID);
+}
+
+# returns the OID for this document
+sub get_OID {
+    my $self = shift (@_);
+    
+    return $self->get_metadata_element ($self->get_top_section(), "Identifier");
+}
+
+sub delete_OID {
+    my $self = shift (@_);
+    
+    $self->set_metadata_element ($self->get_top_section(), "Identifier", "NULL");
+}
+
+
+# methods for manipulating section names
+
+# returns the name of the top-most section (the top
+# level of the document
+sub get_top_section {
+    my $self = shift (@_);
+    
+    return "";
+}
+
+# returns a section
+sub get_parent_section {
+    my $self = shift (@_);
+    my ($section) = @_;
+
+    $section =~ s/(^|\.)\d+$//;
+
+    return $section;
+}
+
+# returns the first child section (or the end child 
+# if there isn't any)
+sub get_begin_child {
+    my $self = shift (@_);
+    my ($section) = @_;
+
+    my $section_ptr = $self->_lookup_section($section);
+    return "" unless defined $section_ptr;
+
+    if (defined $section_ptr->{'subsection_order'}->[0]) {
+	return "$section.$section_ptr->{'subsection_order'}->[0]";
+    }
+
+    return $self->get_end_child ($section);
+}
+
+# returns the next child of a parent section
+sub get_next_child {
+    my $self = shift (@_);
+    my ($section) = @_;
+    
+    my $parent_section = $self->get_parent_section($section);
+    my $parent_section_ptr = $self->_lookup_section($parent_section);
+    return undef unless defined $parent_section_ptr;
+
+    my ($section_num) = $section =~ /(\d+)$/;
+    return undef unless defined $section_num;
+
+    my $i = 0;
+    my $section_order = $parent_section_ptr->{'subsection_order'};
+    while ($i < scalar(@$section_order)) {
+	last if $section_order->[$i] eq $section_num;
+	$i++;
+    }
+
+    $i++; # the next child
+    if ($i < scalar(@$section_order)) {
+	return $section_order->[$i] if $parent_section eq "";
+	return "$parent_section.$section_order->[$i]";
+    }
+
+    # no more sections in this level
+    return undef;
+}
+
+# returns a reference to a list of children
+
+sub get_children {
+    my $self = shift (@_);
+    my ($section) = @_;
+
+    my $section_ptr = $self->_lookup_section($section);
+    return [] unless defined $section_ptr;
+
+    my @children = @{$section_ptr->{'subsection_order'}};
+
+    map {$_ = "$section.$_"; $_ =~ s/^\.+//;} @children;
+    return \@children;
+}
+
+# returns the child section one past the last one (which
+# is coded as "0")
+sub get_end_child {
+    my $self = shift (@_);
+    my ($section) = @_;
+
+    return $section . ".0" unless $section eq "";
+    return "0";
+}
+
+# returns the next section in book order
+sub get_next_section {
+    my $self = shift (@_);
+    my ($section) = @_;
+
+    return undef unless defined $section;
+
+    my $section_ptr = $self->_lookup_section($section);
+    return undef unless defined $section_ptr;
+
+    # first try to find first child
+    if (defined $section_ptr->{'subsection_order'}->[0]) {
+	return $section_ptr->{'subsection_order'}->[0] if ($section eq "");
+	return "$section.$section_ptr->{'subsection_order'}->[0]";
+    }
+
+    do {
+	# try to find sibling
+	my $next_child = $self->get_next_child ($section);
+	return $next_child if (defined $next_child);
+
+	# move up one level
+	$section = $self->get_parent_section ($section);
+    } while $section =~ /\d/;
+
+    return undef;
+}
+
+sub is_leaf_section {
+    my $self = shift (@_);
+    my ($section) = @_;
+
+    my $section_ptr = $self->_lookup_section($section);
+    return 1 unless defined $section_ptr;
+
+    return (scalar (@{$section_ptr->{'subsection_order'}}) == 0);
+}
+
+# methods for dealing with sections
+
+# returns the name of the inserted section
+sub insert_section {
+    my $self = shift (@_);
+    my ($before_section) = @_;
+
+    # get the child to insert before and its parent section
+    my $parent_section = "";
+    my $before_child = "0";
+    my @before_section = split (/\./, $before_section);
+    if (scalar(@before_section) > 0) {
+	$before_child = pop (@before_section);
+	$parent_section = join (".", @before_section);
+    }
+
+    my $parent_section_ptr = $self->_lookup_section($parent_section);
+    if (!defined $parent_section_ptr) {
+	print STDERR "doc::insert_section couldn't find parent section " .
+	    "$parent_section\n";
+	return;
+    }
+
+    # get the next section number
+    my $section_num = $parent_section_ptr->{'next_subsection'}++;
+
+    my $i = 0;
+    while ($i < scalar(@{$parent_section_ptr->{'subsection_order'}}) &&
+	   $parent_section_ptr->{'subsection_order'}->[$i] ne $before_child) {
+	$i++;
+    }
+    
+    # insert the section number into the order list
+    splice (@{$parent_section_ptr->{'subsection_order'}}, $i, 0, $section_num);
+
+    # add this section to the parent section
+    my $section_ptr = {'subsection_order'=>[],
+		       'next_subsection'=>1,
+		       'subsections'=>{},
+		       'metadata'=>[],
+		       'text'=>""};
+    $parent_section_ptr->{'subsections'}->{$section_num} = $section_ptr;
+
+    # work out the full section number
+    my $section = $parent_section;
+    $section .= "." unless $section eq "";
+    $section .= $section_num;
+    
+    return $section;
+}
+
+# creates a pre-named section
+sub create_named_section {
+    my $self = shift (@_);
+    my ($mastersection) = @_;
+
+    my ($num);
+    my $section = $mastersection;
+    my $sectionref = $self;
+
+    while ($section ne "") {
+	($num, $section) = $section =~ /^\.?(\d+)(.*)$/;
+	$num =~ s/^0+(\d)/$1/; # remove leading 0s
+	$section = "" unless defined $section;
+	
+	if (defined $num) {
+	    if (!defined $sectionref->{'subsections'}->{$num}) {
+		push (@{$sectionref->{'subsection_order'}}, $num);
+		$sectionref->{'subsections'}->{$num} = {'subsection_order'=>[],
+							'next_subsection'=>1,
+							'subsections'=>{},
+							'metadata'=>[],
+							'text'=>""};
+		if ($num >= $sectionref->{'next_subsection'}) {
+		    $sectionref->{'next_subsection'} = $num + 1;
+		}
+	    }
+	    $sectionref = $sectionref->{'subsections'}->{$num};
+
+	} else {
+	    print STDERR "doc::create_named_section couldn't create section " .
+		"$mastersection\n";
+	    last;
+	}
+    }
+}
+
+# returns a reference to a list of subsections
+sub list_subsections {
+    my $self = shift (@_);
+    my ($section) = @_;
+
+    my $section_ptr = $self->_lookup_section ($section);
+    if (!defined $section_ptr) {
+	print STDERR "doc::list_subsections couldn't find section $section\n";
+	return [];
+    }
+
+    return [@{$section_ptr->{'subsection_order'}}];
+}
+
+sub delete_section {
+    my $self = shift (@_);
+    my ($section) = @_;
+
+#    my $section_ptr = {'subsection_order'=>[],
+#		       'next_subsection'=>1,
+#		       'subsections'=>{},
+#		       'metadata'=>[],
+#		       'text'=>""};
+
+    # if this is the top section reset everything
+    if ($section eq "") {
+	$self->{'subsection_order'} = [];
+	$self->{'subsections'} = {};
+	$self->{'metadata'} = [];
+	$self->{'text'} = "";
+	return;
+    }
+
+    # find the parent of the section to delete
+    my $parent_section = "";
+    my $child = "0";
+    my @section = split (".", $section);
+    if (scalar(@section) > 0) {
+	$child = pop (@section);
+	$parent_section = join (".", @section);
+    }
+
+    my $parent_section_ptr = $self->_lookup_section($parent_section);
+    if (!defined $parent_section_ptr) {
+	print STDERR "doc::delete_section couldn't find parent section " .
+	    "$parent_section\n";
+	return;
+    }
+
+    # remove this section from the subsection_order list
+    my $i = 0;
+    while ($i < scalar (@{$parent_section_ptr->{'subsection_order'}})) {
+	if ($parent_section_ptr->{'subsection_order'}->[$i] eq $child) {
+	    splice (@{$parent_section_ptr->{'subsection_order'}}, $i, 1);
+	    last;
+	}
+	$i++;
+    }
+
+    # remove this section from the subsection hash
+    if (defined ($parent_section_ptr->{'subsections'}->{$child})) {
+	undef $parent_section_ptr->{'subsections'}->{$child};
+    }
+}
+
+
+# methods for dealing with metadata
+
+# set_metadata_element and get_metadata_element are for metadata
+# which should only have one value. add_meta_data and get_metadata
+# are for metadata which can have more than one value.
+
+sub set_metadata_element {
+    my $self = shift (@_);
+    my ($section, $field, $value) = @_;
+
+    $self->delete_metadata ($section, $field);
+    $self->add_metadata ($section, $field, $value);
+}
+
+# returns the first metadata value which matches field
+sub get_metadata_element {
+    my $self = shift (@_);
+    my ($section, $field) = @_;
+    my ($data);
+
+    my $section_ptr = $self->_lookup_section($section);
+    if (!defined $section_ptr) {
+	print STDERR "doc::get_metadata_element couldn't find section " .
+	    "$section\n";
+	return;
+    }
+
+    foreach $data (@{$section_ptr->{'metadata'}}) {
+	return $data->[1] if ($data->[0] eq $field);
+    }
+	
+    return undef; # was not found
+}
+
+sub add_metadata {
+    my $self = shift (@_);
+    my ($section, $field, $value) = @_;
+
+    my $section_ptr = $self->_lookup_section($section);
+    if (!defined $section_ptr) {
+	print STDERR "doc::add_metadata couldn't find section " .
+	    "$section\n";
+	return;
+    }
+    
+    push (@{$section_ptr->{'metadata'}}, [$field, $value]);
+}
+
+# returns a list of the form [value1, value2, ...]
+sub get_metadata {
+    my $self = shift (@_);
+    my ($section, $field) = @_;
+    my ($data);
+
+    my $section_ptr = $self->_lookup_section($section);
+    if (!defined $section_ptr) {
+	print STDERR "doc::get_metadata couldn't find section " .
+	    "$section\n";
+	return;
+    }
+
+    my @metadata = ();
+    foreach $data (@{$section_ptr->{'metadata'}}) {
+	push (@metadata, $data->[1]) if ($data->[0] eq $field);
+    }
+	
+    return \@metadata;
+}
+
+# returns a list of the form [[field,value],[field,value],...]
+sub get_all_metadata {
+    my $self = shift (@_);
+    my ($section) = @_;
+
+    my $section_ptr = $self->_lookup_section($section);
+    if (!defined $section_ptr) {
+	print STDERR "doc::get_all_metadata couldn't find section " .
+	    "$section\n";
+	return;
+    }
+    
+    return $section_ptr->{'metadata'};
+}
+
+# $value is optional
+sub delete_metadata {
+    my $self = shift (@_);
+    my ($section, $field, $value) = @_;
+
+    my $section_ptr = $self->_lookup_section($section);
+    if (!defined $section_ptr) {
+	print STDERR "doc::delete_metadata couldn't find section " .
+	    "$section\n";
+	return;
+    }
+
+    my $i = 0;
+    while ($i < scalar (@{$section_ptr->{'metadata'}})) {
+	if (($section_ptr->{'metadata'}->[$i]->[0] eq $field) &&
+	    (!defined $value || $section_ptr->{'metadata'}->[$i]->[1] eq $value)) {
+	    splice (@{$section_ptr->{'metadata'}}, $i, 1);
+	} else {
+	    $i++;
+	}
+    }
+}
+
+sub delete_all_metadata {
+    my $self = shift (@_);
+    my ($section) = @_;
+
+    my $section_ptr = $self->_lookup_section($section);
+    if (!defined $section_ptr) {
+	print STDERR "doc::delete_all_metadata couldn't find section " .
+	    "$section\n";
+	return;
+    }
+    
+    $section_ptr->{'metadata'} = [];
+}
+
+
+# methods for dealing with associated files
+
+sub associate_file {
+    my $self = shift (@_);
+    my ($real_filename, $assoc_filename, $mime_type) = @_;
+    $mime_type = &html::guess_mime_type ($real_filename) unless defined $mime_type;
+
+    # remove all associated files with the same name
+    $self->delete_assoc_file ($assoc_filename);
+
+    push (@{$self->{'associated_files'}}, 
+	  [$real_filename, $assoc_filename, $mime_type]);
+}
+
+# returns a list of associated files in the form
+#   [[real_filename, assoc_filename, mimetype], ...]
+sub get_assoc_files {
+    my $self = shift (@_);
+
+    return $self->{'associated_files'};
+}
+
+sub delete_assoc_file {
+    my $self = shift (@_);
+    my ($assoc_filename) = @_;
+
+    my $i=0;
+    while ($i < scalar (@{$self->{'associated_files'}})) {
+	if ($self->{'associated_files'}->[$i]->[1] eq $assoc_filename) {
+	    splice (@{$self->{'associated_files'}}, $i, 1);
+	} else {
+	    $i++;
+	}
+    }
+}
+
+
+# methods for dealing with text
+
+sub add_text {
+    my $self = shift (@_);
+    my ($section, $text) = @_;
+
+    my $section_ptr = $self->_lookup_section($section);
+    if (!defined $section_ptr) {
+	print STDERR "doc::add_text couldn't find section " .
+	    "$section\n";
+	return;
+    }
+
+    $section_ptr->{'text'} .= $text;
+}
+
+# returns the text for a section
+sub get_text {
+    my $self = shift (@_);
+    my ($section) = @_;
+
+    my $section_ptr = $self->_lookup_section($section);
+    if (!defined $section_ptr) {
+	print STDERR "doc::get_text couldn't find section " .
+	    "$section\n";
+	return "";
+    }
+
+    return $section_ptr->{'text'};
+}
+
+# returns the length of the text for a section
+sub get_text_length {
+    my $self = shift (@_);
+    my ($section) = @_;
+
+    my $section_ptr = $self->_lookup_section($section);
+    if (!defined $section_ptr) {
+	print STDERR "doc::get_text_length couldn't find section " .
+	    "$section\n";
+	return 0;
+    }
+
+    return length ($section_ptr->{'text'});
+}
+
+sub delete_text {
+    my $self = shift (@_);
+    my ($section) = @_;
+
+    my $section_ptr = $self->_lookup_section($section);
+    if (!defined $section_ptr) {
+	print STDERR "doc::delete_text couldn't find section " .
+	    "$section\n";
+	return;
+    }
+
+    $section_ptr->{'text'} = "";
+}
+
+
+1;
Index: /tags/start/gsdl/perllib/docproc.pm
===================================================================
--- /tags/start/gsdl/perllib/docproc.pm	(revision 13666)
+++ /tags/start/gsdl/perllib/docproc.pm	(revision 13666)
@@ -0,0 +1,21 @@
+# document processors are used by the document reader plugins
+# to do some processing on some documents
+
+package docproc;
+
+sub new {
+    my ($class) = @_;
+    my $self = {};
+
+    return bless $self, $class;
+}
+
+sub process {
+    my $self = shift (@_);
+    my ($doc_obj) = @_;
+
+    die "docproc::process function must be implemented in sub classes\n";
+}
+
+1;
+
Index: /tags/start/gsdl/perllib/docsave.pm
===================================================================
--- /tags/start/gsdl/perllib/docsave.pm	(revision 13666)
+++ /tags/start/gsdl/perllib/docsave.pm	(revision 13666)
@@ -0,0 +1,73 @@
+# This document processor saves a document in the 
+# archives directory of a collection
+
+
+package docsave;
+
+use arcinfo;
+use docproc;
+use util;
+
+
+sub BEGIN {
+    @ISA = ('docproc');
+}
+
+sub new {
+    my ($class, $collection, $archive_info) = @_;
+    my $self = new docproc ();
+
+    $self->{'collection'} = $collection;
+    $self->{'archive_info'} = $archive_info;
+
+    return bless $self, $class;
+}
+
+sub process {
+    my $self = shift (@_);
+    my ($doc_obj) = @_;
+
+    my $archive_dir = "$ENV{'GSDLHOME'}/collect/$self->{'collection'}/archives";
+    my $OID = $doc_obj->get_OID();
+    $OID = "NULL" unless defined $OID;
+
+    # get the document's directory by inserting a / every 1-8 characters
+    # and removing the last /
+    my $doc_dir = $OID;
+    $doc_dir =~ s/(.{1,8})/$1\//g;
+    $doc_dir =~ s/\/$//;
+    $doc_dir .= ".dir";
+    &util::mk_all_dir ("$archive_dir/$doc_dir");
+
+    # copy all the associated files, add this information as metadata
+    # to the document
+    my @assoc_files = ();
+    foreach $assoc_file (@{$doc_obj->get_assoc_files()}) {
+	if (-e $assoc_file->[0]) {
+	    &util::cp ($assoc_file->[0], "$archive_dir/$doc_dir/$assoc_file->[1]");
+	    $doc_obj->add_metadata ($doc_obj->get_top_section(), 
+				    "gsdlassocfile", 
+				    "$assoc_file->[1]:$assoc_file->[2]");
+	} else {
+	    print STDERR "docsave::process couldn't copy the associated file " .
+		"$assoc_file->[0] to $archive_dir/$doc_dir/$assoc_file->[1]\n"
+	}
+    }
+
+    # save this document
+    if (!open (OUTDOC, ">$archive_dir/$doc_dir/doc.gml")) {
+	print STDERR "docsave::process could not write to file " . 
+	    "$archive_dir/$doc_dir/doc.gml\n";
+	return;
+    }
+    $doc_obj->output_section('docsave::OUTDOC', $doc_obj->get_top_section());
+    close OUTDOC;
+
+    # store reference in the archive_info
+    $self->{'archive_info'}->add_info($OID, 
+				      "$doc_dir/doc.gml");
+    
+}
+
+
+1;
Index: /tags/start/gsdl/perllib/html.pm
===================================================================
--- /tags/start/gsdl/perllib/html.pm	(revision 13666)
+++ /tags/start/gsdl/perllib/html.pm	(revision 13666)
@@ -0,0 +1,248 @@
+package html;
+
+# htmlsafe(TEXT)
+# 
+# Converts SGML meta characters in TEXT to entity references.
+# 
+sub htmlsafe
+{
+    $_[0] =~ s/&/&amp;/og;
+    $_[0] =~ s/</&lt;/og;
+    $_[0] =~ s/>/&gt;/og;
+}
+
+# urlsafe(TEXT)
+# 
+# Converts characters not allowed in a URL to their hex representation.
+# 
+sub urlsafe
+{
+    $_[0] =~ s/[\x09\x20\x22\x3c\x3e\x5b\x5c\x5d\x5e\x60\x7b\x7c\x7d\x7e\?\=\&\+_]/sprintf("%%%2x", ord($&))/ge;
+}
+
+# dmsafe
+#
+# Converts characters which could make display.pl or html crack to their entity references.
+# Don't use this on dm macros as they will no longer be recognisable by dm (which
+# by the way, is the whole idea).
+# -- Rodger 12/1/98
+sub dmsafe {
+    my ($s) = $_[0];
+    $s =~ s/&/&amp;/og; # for html
+    $s =~ s/</&lt;/og;  # for html
+    $s =~ s/>/&gt;/og;  # for html
+    $s =~ s/\_/&#095;/og; # for dm (we have a convention of starting macros with _
+    $s =~ s/\"/&quot;/og; # for html (don't want to be interpreted as a quote)
+    $s =~ s/\{/&#123;/og; # for dm blocks
+    $s =~ s/\}/&#125;/og; # for dm blocks
+    return $s;
+}
+
+
+# named entry to the standard html font
+%charnetosf = ("Agrave"=> "192",  "Aacute"=> "193",  "Acirc" => "194",  "Atilde"=> "195",
+	       "Auml"  => "196",  "Aring" => "197",  "AElig" => "198",  "Ccedil"=> "199",
+	       "Egrave"=> "200",  "Eacute"=> "201",  "Ecirc" => "202",  "Euml"  => "203",
+	       "Igrave"=> "204",  "Iacute"=> "205",  "Icirc" => "206",  "Iuml"  => "207",
+	       "ETH"   => "208",  "Ntilde"=> "209",  "Ograve"=> "210",  "Oacute"=> "211",
+	       "Ocirc" => "212",  "Otilde"=> "213",  "Ouml"  => "214",  
+	       "Oslash"=> "216",  "Ugrave"=> "217",  "Uacute"=> "218",  "Ucirc" => "219",
+	       "Uuml"  => "220",  "Yacute"=> "221",  "THORN" => "222",  "szlig" => "223",
+	       "agrave"=> "224",  "aacute"=> "225",  "acirc" => "226",  "atilde"=> "227",
+	       "auml"  => "228",  "aring" => "229",  "aelig" => "230",  "ccedil"=> "231",
+	       "egrave"=> "232",  "eacute"=> "233",  "ecirc" => "234",  "euml"  => "235",
+	       "igrave"=> "236",  "iacute"=> "237",  "icirc" => "238",  "iuml"  => "239",
+	       "eth"   => "240",  "ntidle"=> "241",  "ograve"=> "242",  "oacute"=> "243",
+	       "ocirc" => "244",  "otilde"=> "245",  "ouml"  => "246",  
+	       "oslash"=> "248",  "ugrave"=> "249",  "uacute"=> "250",  "ucirc" => "251",
+	       "uuml"  => "252",  "yacute"=> "253",  "thorn" => "254",  "yuml"  => "255");
+
+%symnetosf = ("quot"  => "34",   "amp"   => "38",   "lt"    => "60",   "gt"    => "62",
+	      "nbsp"  => "160",  "iexcl" => "161",  "cent"  => "162",  "pound" => "163",
+	      "curren"=> "164",  "yen"   => "165",  "brvbar"=> "166",  "sect"  => "167",
+	      "uml"   => "168",  "copy"  => "169",  "ordf"  => "170",  "laquo" => "171",
+	      "not"   => "172",  "shy"   => "173",  "reg"   => "174",  "macr"  => "175",
+	      "deg"   => "176",  "plusmn"=> "177",  "sup2"  => "178",  "sup3"  => "179",
+	      "acute" => "180",  "micro" => "181",  "para"  => "182",  "middot"=> "183",
+	      "cedil" => "184",  "sup1"  => "185",  "ordm"  => "186",  "raquo" => "187",
+	      "frac14"=> "188",  "frac12"=> "189",  "frac34"=> "190",  "iquest"=> "191",
+	      "times" => "215",  "divide"=> "247");
+
+
+
+# standard font to plain text
+%sftotxt = ("32"  => " ",  "33"  => "!",  "34"  => "\"",  "35"  => "\#",  "36"  => "\$",
+	    "37"  => "\%", "38"  => "&",  "39"  => "'",   "40"  => "(",   "41"  => ")",
+	    "42"  => "*",  "43"  => "+",  "44"  => ",",   "45"  => "-",   "46"  => ".",
+	    "47"  => "/",  "48"  => "0",  "49"  => "1",   "50"  => "2",   "51"  => "3",
+	    "52"  => "4",  "53"  => "5",  "54"  => "6",   "55"  => "7",   "56"  => "8",
+	    "57"  => "9",  "58"  => ":",  "59"  => ";",   "60"  => "<",   "61"  => "=",
+	    "62"  => ">",  "63"  => "?",  "64"  => "\@",  "65"  => "A",   "66"  => "B",
+	    "57"  => "9",  "58"  => ":",  "59"  => ";",   "61"  => "=",
+	    "63"  => "?",  "64"  => "\@", "65"  => "A",  "66"  => "B",
+	    "67"  => "C",  "68"  => "D",  "69"  => "E",   "70"  => "F",   "71"  => "G",
+	    "72"  => "H",  "73"  => "I",  "74"  => "J",   "75"  => "K",   "76"  => "L",
+	    "77"  => "M",  "78"  => "N",  "79"  => "O",   "80"  => "P",   "81"  => "Q",
+	    "82"  => "R",  "83"  => "S",  "84"  => "T",   "85"  => "U",   "86"  => "V",
+	    "87"  => "W",  "88"  => "X",  "89"  => "Y",   "90"  => "Z",   "91"  => "[",
+	    "92"  => "\\", "93"  => "]",  "94"  => "^",   "95"  => "_",   "96"  => "`",
+	    "97"  => "a",  "98"  => "b",  "99"  => "c",   "100" => "d",   "101" => "e",
+	    "102" => "f",  "103" => "g",  "104" => "h",   "105" => "i",   "106" => "j",
+	    "107" => "k",  "108" => "l",  "109" => "m",   "110" => "n",   "111" => "o",
+	    "112" => "p",  "113" => "q",  "114" => "r",   "115" => "s",   "116" => "t",
+	    "117" => "u",  "118" => "v",  "119" => "w",   "120" => "x",   "121" => "y",
+	    "122" => "z",  "123" => "{",  "124" => "|",   "125" => "}",   "126" => "~",
+	    "130" => ",",  "131" => "f",  "132" => "\"",   "133" => "...", "139" => "<",
+	    "140" => "OE", "145" => "'",  "146" => "'",   "147" => "\"",   "148" => "\"",
+	    "149" => "o",  "150" => "--", "151" => "-",   "152" => "~",   "153" => "TM",
+	    "155" => ">",  "156" => "oe", "159" => "Y",   "160" => " ",   "178" => "2",
+	    "179" => "3",  "185" => "1",  "188" => "1/4", "189" => "1/2", "190" => "3/4",
+	    "192" => "A",  "193" => "A",  "194" => "A",   "195" => "A",   "196" => "A",
+	    "197" => "A",  "198" => "AE", "199" => "C",   "200" => "E",   "201" => "E",
+	    "202" => "E",  "203" => "E",  "204" => "I",   "205" => "I",   "206" => "I",
+	    "207" => "I",  "208" => "D",  "209" => "N",   "210" => "O",   "211" => "O",
+	    "212" => "O",  "213" => "O",  "214" => "O",   "215" => "*",   "216" => "O",
+	    "217" => "U",  "218" => "U",  "219" => "U",   "220" => "U",   "221" => "Y",
+	    "223" => "ss", "224" => "a",  "225" => "a",   "226" => "a",   "227" => "a",
+	    "228" => "a",  "229" => "a",  "230" => "ae",  "231" => "c",   "232" => "e",
+	    "233" => "e",  "234" => "e",  "235" => "e",   "236" => "i",   "237" => "i",
+	    "238" => "i",  "239" => "i",  "241" => "n",   "242" => "o",   "243" => "o",
+	    "244" => "o",  "245" => "o",  "246" => "o",   "247" => "/",   "248" => "o",
+	    "249" => "u",  "250" => "u",  "251" => "u",   "252" => "u",   "253" => "y",
+	    "255" => "y",  "8218" => ",");
+
+
+# returns the character in the standard html font. It assumes that the
+# & and ; have been stripped off the string.
+sub getcharequiv {
+    my ($entity, $convertsymbols) = @_;
+
+    # replace &#8218 with comma (",")
+    $entity =~ s/8218/044/;
+
+    # a numeric entity
+    if ($entity =~ /^\#0*(\d+)/) {
+	return pack("c", $1);
+    }
+    
+    # a named character entity
+    if (defined $charnetosf{$entity}) {
+	return pack("c", $charnetosf{$entity});
+    }
+
+    # a named symbol entity
+    if ($convertsymbols && defined $symnetosf{$entity}) {
+	return pack("c", $symnetosf{$entity});
+    }
+
+    return "&$entity;"; # unknown character
+}
+
+# convert character entities from named equivalents to html font
+sub convertcharentities {
+    # args: the text that you want to convert
+
+    $_[0] =~ s/&([^;]+);/&getcharequiv($1,0)/ge;
+}
+
+# convert any entities from named equivalents to html font
+sub convertallentities {
+    # args: the text that you want to convert
+
+    $_[0] =~ s/&([^;]+);/&getcharequiv($1,1)/ge;
+}
+
+sub html2txt {
+    # args: the text that you want converted to ascii, 
+    # and whether to strip out sgml tags
+
+    # strip out sgml tags if needed
+    $_[0] =~ s/<[^>]>//g if $_[1];
+
+    # convert the char entities to the standard html font
+    &convertcharentities($_[0]); 
+    
+    # convert the html character set to a plain ascii character set
+    my $pos = 0;
+    while ($pos < length($_[0])) {
+	my $charnum = ord(substr($_[0], $pos, 1));
+	if ($charnum >= 32) { # only convert characters above #32
+	    my $replacechars = " ";
+	    $replacechars = $sftotxt{$charnum} if defined $sftotxt{$charnum};
+	    substr($_[0], $pos, 1) = $replacechars;
+	    $pos += length ($replacechars);
+
+	} else {
+	    $pos ++;
+	}
+    }
+}  
+
+
+sub guess_mime_type {
+    my ($filename) = @_;
+
+    my ($fileext) = $filename =~ /\.(\w+)$/;
+    return "unknown" unless defined $fileext;
+
+    my %mime_type = ("ai"=>"application/postscript", "aif"=>"audio/x-aiff", 
+		     "aifc"=>"audio/x-aiff", "aiff"=>"audio/x-aiff", 
+		     "au"=>"audio/basic", "avi"=>"video/x-msvideo",
+		     "bcpio"=>"application/x-bcpio", "bin"=>"application/octet-stream", 
+		     "cdf"=>"application/x-netcdf", "class"=>"application/octet-stream", 
+		     "cpio"=>"application/x-cpio", "cpt"=>"application/mac-compactpro",
+		     "csh"=>"application/x-csh", "dcr"=>"application/x-director", 
+		     "dir"=>"application/x-director", "dms"=>"application/octet-stream", 
+		     "doc"=>"application/msword", "dvi"=>"application/x-dvi",
+		     "dxr"=>"application/x-director", "eps"=>"application/postscript", 
+		     "etx"=>"text/x-setext",
+		     "exe"=>"application/octet-stream", "gif"=>"image/gif",
+		     "gtar"=>"application/x-gtar", "hdf"=>"application/x-hdf",
+		     "hqx"=>"application/mac-binhex40", "htm"=>"text/html",
+		     "html"=>"text/html", "ice"=>"x-conference/x-cooltalk",
+		     "ief"=>"image/ief", "jpe"=>"image/jpeg",
+		     "jpeg"=>"image/jpeg", "jpg"=>"image/jpeg",
+		     "kar"=>"audio/midi", "latex"=>"application/x-latex",
+		     "lha"=>"application/octet-stream", "lzh"=>"application/octet-stream",
+		     "man"=>"application/x-troff-man", "mcf"=>"image/vasa",
+		     "me"=>"application/x-troff-me", "mid"=>"audio/midi",
+		     "midi"=>"audio/midi", "mif"=>"application/x-mif",
+		     "mov"=>"video/quicktime", "movie"=>"video/x-sgi-movie",
+		     "mp2"=>"audio/mpeg", "mpe"=>"video/mpeg",
+		     "mpeg"=>"video/mpeg", "mpg"=>"video/mpeg",
+		     "mpga"=>"audio/mpeg", "ms"=>"application/x-troff-ms",
+		     "nc"=>"application/x-netcdf", "oda"=>"application/oda",
+		     "pbm"=>"image/x-portable-bitmap", "pdb"=>"chemical/x-pdb",
+		     "pdf"=>"application/pdf", "pgm"=>"image/x-portable-graymap",
+		     "png"=>"image/png", "pnm"=>"image/x-portable-anymap",
+		     "ppm"=>"image/x-portable-pixmap", "ppt"=>"application/powerpoint",
+		     "ps"=>"application/postscript", "qt"=>"video/quicktime",
+		     "ra"=>"audio/x-realaudio", "ram"=>"audio/x-pn-realaudio",
+		     "ras"=>"image/x-cmu-raster", "rgb"=>"image/x-rgb",
+		     "roff"=>"application/x-troff", "rpm"=>"audio/x-pn-realaudio-plugin",
+		     "rtf"=>"application/rtf", "rtx"=>"text/richtext",
+		     "sgm"=>"text/x-sgml", "sgml"=>"text/x-sgml",
+		     "sh"=>"application/x-sh", "shar"=>"application/x-shar",
+		     "sit"=>"application/x-stuffit", "skd"=>"application/x-koan",
+		     "skm"=>"application/x-koan", "skp"=>"application/x-koan",
+		     "skt"=>"application/x-koan", "snd"=>"audio/basic",
+		     "src"=>"application/x-wais-source", "sv4cpio"=>"application/x-sv4cpio",
+		     "sv4crc"=>"application/x-sv4crc", "t"=>"application/x-troff",
+		     "tar"=>"application/x-tar", "tcl"=>"application/x-tcl",
+		     "tex"=>"application/x-tex", "texi"=>"application/x-texinfo",
+		     "texinfo"=>"application/x-texinfo", "tif"=>"image/tiff",
+		     "tiff"=>"image/tiff", "tr"=>"application/x-troff",
+		     "tsv"=>"text/tab-separated-values", "txt"=>"text/plain",
+		     "ustar"=>"application/x-ustar", "vcd"=>"application/x-cdlink",
+		     "vrml"=>"x-world/x-vrml", "wav"=>"audio/x-wav",
+		     "wrl"=>"x-world/x-vrml", "xbm"=>"image/x-xbitmap",
+		     "xpm"=>"image/x-xpixmap", "xwd"=>"image/x-xwindowdump",
+		     "xyz"=>"chemical/x-pdb", "zip"=>"application/zip");
+
+    return $mime_type{$fileext} if (defined $mime_type{$fileext});
+
+    return "unknown";
+}
+
+
+1;
Index: /tags/start/gsdl/perllib/lang.pm
===================================================================
--- /tags/start/gsdl/perllib/lang.pm	(revision 13666)
+++ /tags/start/gsdl/perllib/lang.pm	(revision 13666)
@@ -0,0 +1,176 @@
+# this module translates language descriptions to and from
+# the ISO 639 standard
+
+package lang;
+
+@trans = (["ab", "Abkhazian"],      ["om", "Afan Oromo"],
+	  ["om", "Oromo"],          ["aa", "Afar"],
+	  ["af", "Afrikaans"],      ["sq", "Albanian"],
+	  ["am", "Amharic"],        ["ar", "Arabic"],
+	  ["hy", "Armenian"],       ["as", "Assamese"],
+	  ["ay", "Aymara"],         ["az", "Azerbaijani"],
+
+	  ["ba", "Bashkir"],        ["eu", "Basque"],
+	  ["bn", "Bengali"],        ["bn", "Bangla"],
+	  ["dz", "Bhutani"],        ["bh", "Bihari"],
+	  ["bi", "Bislama"],        ["br", "Breton"],
+	  ["bg", "Bulgarian"],      ["my", "Burmese"],
+	  ["be", "Byelorussian"],
+
+	  ["km", "Cambodian"],      ["ca", "Catalan"],
+	  ["zh", "Chinese"],        ["co", "Corsican"],
+	  ["hr", "Croatian"],       ["cs", "Czech"],
+
+	  ["da", "Danish"],         ["nl", "Dutch"],
+
+	  ["en", "English"],        ["eo", "Esperanto"],
+	  ["et", "Estonian"],       ["fo", "Faroese"],
+	  ["fj", "Fijian"],         ["fi", "Finnish"],
+	  ["fr", "French"],         ["fy", "Frisian"],
+
+	  ["gl", "Galician"],       ["ka", "Georgian"],
+	  ["de", "German"],         ["el", "Greek"],
+	  ["kl", "Greenlandic"],    ["gn", "Guarani"],
+	  ["gu", "Gujarati"],
+
+	  ["ha", "Hausa"],          ["iw", "Hebrew"],
+	  ["hi", "Hindi"],          ["hu", "Hungarian"],
+
+	  ["is", "Icelandic"],      ["in", "Indonesian"],
+	  ["ia", "Interlingua"],    ["ie", "Interlingue"],
+	  ["ik", "Inupiak"],        ["ga", "Irish"],
+	  ["it", "Italian"],
+
+	  ["ja", "Japanese"],       ["jv", "Javanese"],
+
+	  ["kn", "Kannada"],        ["ks", "Kashmiri"],
+	  ["kk", "Kazakh"],         ["rw", "Kinyarwanda"],
+	  ["ky", "Kirghiz"],        ["rn", "Kirundi"],
+	  ["ko", "Korean"],         ["ku", "Kurdish"],
+
+	  ["lo", "Laothian"],       ["la", "Latin"],
+	  ["lv", "Latvian"],        ["lv", "Lettish"],
+	  ["ln", "Lingala"],        ["lt", "Lithuanian"],
+
+	  ["mk", "Macedonian"],     ["mg", "Malagasy"],
+	  ["ms", "Malay"],          ["ml", "Malayalam"],
+	  ["mt", "Maltese"],        ["mi", "Maori"],
+	  ["mr", "Marathi"],        ["mo", "Moldavian"],
+	  ["mn", "Mongolian"],
+
+	  ["na", "Nauru"],          ["ne", "Nepali"],
+	  ["no", "Norwegian"],
+
+	  ["oc", "Occitan"],        ["or", "Oriya"],
+
+	  ["ps", "Pashto"],         ["ps", "Pushto"],
+	  ["fa", "Persian"],        ["pl", "Polish"],
+	  ["pt", "Portuguese"],     ["pa", "Punjabi"],
+
+	  ["qu", "Quechua"],
+
+	  ["rm", "Rhaeto-Romance"], ["ro", "Romanian"],
+	  ["ru", "Russian"],
+
+	  ["sm", "Samoan"],         ["sg", "Sangho"],
+	  ["sa", "Sanskrit"],       ["gd", "Scots Gaelic"],
+	  ["sr", "Serbian"],        ["sh", "Serbo-Croatian"],
+	  ["st", "Sesotho"],        ["tn", "Setswana"],
+	  ["sn", "Shona"],          ["sd", "Sindhi"],
+	  ["si", "Singhalese"],     ["ss", "Siswati"],
+	  ["sk", "Slovak"],         ["sl", "Slovenian"],
+	  ["so", "Somali"],         ["es", "Spanish"],
+	  ["su", "Sundanese"],      ["sw", "Swahili"],
+	  ["sv", "Swedish"],
+
+	  ["tl", "Tagalog"],        ["tg", "Tajik"],
+	  ["ta", "Tamil"],          ["tt", "Tatar"],
+	  ["te", "Telugu"],         ["th", "Thai"],
+	  ["bo", "Tibetan"],        ["ti", "Tigrinya"],
+	  ["to", "Tonga"],          ["ts", "Tsonga"],
+	  ["tr", "Turkish"],        ["tk", "Turkmen"],
+	  ["tw", "Twi"],
+
+	  ["uk", "Ukrainian"],      ["ur", "Urdu"],
+	  ["uz", "Uzbek"],
+
+	  ["vi", "Vietnamese"],     ["vo", "Volapuk"],
+
+	  ["cy", "Welsh"],          ["wo", "Wolof"],
+
+	  ["xh", "Xhosa"],
+
+	  ["ji", "Yiddish"],        ["yo", "Yoruba"],
+
+	  ["zu", "Zulu"]);
+
+
+sub one_english_to_iso639 {
+    my ($english) = @_;
+    my $iso639 = "";
+
+    foreach $lang (@trans) {
+	my $code = $lang->[0];
+	my $enname = $lang->[1];
+	if ($english =~ /\s*($code|$enname)\s*$/i) {
+	    # found the language
+	    $iso639 = $code;
+	    last;
+
+	}
+    }
+
+    return $iso639;
+}
+
+
+sub english_to_iso639 {
+    my ($englishlist) = @_;
+    my ($english);
+
+    my @englishlist = split (",", $englishlist);
+    my @iso639list = ();
+
+    foreach $english (@englishlist) {
+	push (@iso639list, &one_english_to_iso639($english));
+    }
+
+    return join (",", @iso639list);
+}
+
+
+sub one_iso639_to_english {
+    my ($iso639) = @_;
+    my $english = "";
+
+    foreach $lang (@trans) {
+	my $code = $lang->[0];
+	my $enname = $lang->[1];
+	if ($iso639 =~ /\s*($code|$enname)\s*$/i) {
+	    # found the language
+	    $english = $enname;
+	    last;
+
+	}
+    }
+
+    return $enname;
+}
+
+
+sub iso639_to_english {
+    my ($iso639list) = @_;
+    my ($iso639);
+
+    my @iso639list = split (",", $iso639list);
+    my @englishlist = ();
+
+    foreach $iso639 (@iso639list) {
+	push (@englishlist, &one_iso639_to_english($iso639));
+    }
+
+    return join (",", @englishlist);
+}
+
+
+1;
Index: /tags/start/gsdl/perllib/mgbuilder.pm
===================================================================
--- /tags/start/gsdl/perllib/mgbuilder.pm	(revision 13666)
+++ /tags/start/gsdl/perllib/mgbuilder.pm	(revision 13666)
@@ -0,0 +1,383 @@
+# MGBuilder object
+#
+
+package mgbuilder;
+
+use cfgread;
+use colcfg;
+use plugin;
+use util;
+
+$maxdocsize = 12000;
+
+%wanted_index_files = ('td'=>1,
+		       't'=>1,
+		       'idb'=>1,
+		       'ib1'=>1,
+		       'ib2'=>1,
+		       'ib3'=>1,
+		       'i'=>1,
+		       'ip'=>1,
+		       'tiw'=>1,
+		       'wa'=>1);
+
+
+sub new {
+    my ($class, $collection, $source_dir, $build_dir, $verbosity) = @_;
+
+    # create an mgbuilder object
+    my $self = bless {'collection'=>$collection,
+		      'source_dir'=>$source_dir,
+		      'build_dir'=>$build_dir,
+		      'verbosity'=>$verbosity}, $class;
+
+
+    # read in the collection configuration file
+    if (!-e "$ENV{'GSDLHOME'}/collect/$collection/collect.cfg") {
+	die "mgbuilder::new - couldn't find collect.cfg for collection $collection\n";
+    }
+    $self->{'collect_cfg'} = &colcfg::read_collect_cfg ("$ENV{'GSDLHOME'}/collect/" .
+							"$collection/collect.cfg");
+
+
+    # get the list of plugins for this collection
+    my @plugins = (); # some good choice of plugins .... ????
+    if (defined $self->{'collect_cfg'}->{'plugins'}) {
+	@plugins = @{$self->{'collect_cfg'}->{'plugins'}};
+    }
+    
+
+    # load all the plugins
+    $self->{'pluginfo'} = &plugin::load_plugins ($collection, \@plugins);
+    if (scalar(@{$self->{'pluginfo'}}) == 0) {
+	print STDERR "No plugins were loaded.\n";
+	die "\n";
+    }
+    
+
+    # load up the document processor for building
+    # if a buildproc class has been created for this collection, use it
+    # otherwise, use the mg buildproc
+    my ($buildprocdir, $buildproctype);
+    if (-e "$ENV{'GSDLHOME'}/collect/$collection/lib/${collection}buildproc.pm") {
+	$buildprocdir = "$ENV{'GSDLHOME'}/collect/$collection/lib";
+	$buildproctype = "${collection}buildproc";
+    } else {
+	$buildprocdir = "$ENV{'GSDLHOME'}/lib";
+	$buildproctype = "mgbuildproc";
+    }
+    require "$buildprocdir/$buildproctype.pm";
+
+    eval("\$self->{'buildproc'} = new $buildproctype(\$collection, " .
+	 "\$source_dir, \$build_dir, \$verbosity)");
+    die "$@" if $@;
+
+
+    return $self;
+}
+
+sub init {
+    my $self = shift (@_);
+
+    # remove any old builds
+    &util::rm_r($self->{'build_dir'});
+    &util::mk_all_dir($self->{'build_dir'});
+        
+    # make the text directory
+    my $textdir = "$self->{'build_dir'}/text";
+    &util::mk_all_dir($textdir);
+}
+
+sub compress_text {
+    my $self = shift (@_);
+    my $exedir = "$ENV{'GSDLHOME'}/bin/$ENV{'GSDLOS'}";
+    my $exe = &util::get_os_exe ();
+
+    &util::mk_all_dir (&util::filename_cat($self->{'build_dir'}, "text"));
+    my $basefilename = "text/$self->{'collection'}";
+    my $fulltextprefix = &util::filename_cat ($self->{'build_dir'}, $basefilename);
+
+    my $osextra = "";
+    if ($ENV{'GSDLOS'} =~ /^windows$/i) {
+	$fulltextprefix =~ s/\//\\/g;
+    } else {
+	$osextra = " -d /";
+    }
+
+    print STDERR "\n*** creating the compressed text\n" if ($self->{'verbosity'} >= 1);
+
+    # set up the document processor
+    $self->{'buildproc'}->set_output_handle ('mgbuilder::PIPEOUT');
+    $self->{'buildproc'}->set_mode ('text');
+    $self->{'buildproc'}->set_index ('section:text');
+    
+    # collect the statistics for the text
+    # -b $maxdocsize sets the maximum document size to be 12 meg
+    print STDERR "\n    collecting text statistics\n"  if ($self->{'verbosity'} >= 1);
+    if (!-e "$exedir/mg_passes$exe" || !open (PIPEOUT, 
+            "| $exedir/mg_passes$exe -f $fulltextprefix -b $maxdocsize -T1 $osextra")) {
+	die "mgbuilder::compress_text - couldn't run $exedir/mg_passes$exe\n";
+    }
+    $self->{'buildproc'}->reset();
+    &plugin::read ($self->{'pluginfo'}, $self->{'source_dir'}, 
+		   "", {}, $self->{'buildproc'});
+    close (PIPEOUT);
+
+    # create the compression dictionary
+    # the compression dictionary is built by assuming the stats are from a seed
+    # dictionary (-S), if a novel word is encountered it is spelled out (-H),
+    # and the resulting dictionary must be less than 5 meg with the most frequent
+    # words being put into the dictionary first (-2 -k 5120)
+    print STDERR "\n    creating the compression dictionary\n"  if ($self->{'verbosity'} >= 1);
+    if (!-e "$exedir/mg_compression_dict$exe") {
+	die "mgbuilder::compress_text - couldn't run $exedir/mg_compression_dict$exe\n";
+    }
+    system ("$exedir/mg_compression_dict$exe -f $fulltextprefix -S -H -2 -k 5120 $osextra");
+
+    # compress the text
+    # -b $maxdocsize sets the maximum document size to be 12 meg
+    print STDERR "\n    compressing the text\n"  if ($self->{'verbosity'} >= 1);
+    if (!-e "$exedir/mg_passes$exe" || !open (PIPEOUT, 
+            "| $exedir/mg_passes$exe -f $fulltextprefix -b $maxdocsize -T2 $osextra")) {
+	die "mgbuilder::compress_text - couldn't run $exedir/mg_passes$exe\n";
+    }
+    $self->{'buildproc'}->reset();
+    &plugin::read ($self->{'pluginfo'}, $self->{'source_dir'}, 
+		   "", {}, $self->{'buildproc'});
+    close (PIPEOUT);
+}
+
+sub build_indexes {
+    my $self = shift (@_);
+    my $indexes = $self->{'collect_cfg'}->{'indexes'};
+
+    # create the mapping between the index descriptions 
+    # and their directory names
+    $self->{'index_mapping'} = $self->create_index_mapping ($indexes);
+
+    # build each of the indexes
+    foreach $index (@$indexes) {
+	print STDERR "\n*** building index $index in subdirectory " . 
+	    "$self->{'index_mapping'}->{$index}\n" if ($self->{'verbosity'} >= 1);
+	$self->build_index($index);
+    }
+}
+
+# creates directory names for each of the index descriptions
+sub create_index_mapping {
+    my $self = shift (@_);
+    my ($indexes) = @_;
+
+    my %mapping = ();
+    
+    # dirnames is used to check for collisions. Start this off
+    # with the manditory directory names
+    my %dirnames = ('text'=>'text',
+		    'extra'=>'extra');
+    
+    foreach $index (@$indexes) {
+	my ($level, $fields) = split (":", $index);
+	my @fields = split (",", $fields);
+	splice (@fields, 2); # just want first two fields
+	
+	# the directory names starts with the first character of the index level
+	my ($dirname) = $level =~ /^(.)/;
+
+	# next comes a processed version of the first two fields in the index
+	# the processed version contains the first character and the next
+	# consonant
+	map {s/^(.).*?([bcdfghjklmnpqrstvwxyz]).*$/$1$2/i;} @fields;
+	$dirname .= join("", @fields);
+
+	# convert the directory name to lowercase
+	$dirname = lc ($dirname);
+
+	# add a number to make this directory name unique
+	if (defined $dirnames{$dirname}) {
+	    my $num = 1;
+	    while (defined $dirnames{"$dirname$num"}) {
+		$num++;
+	    }
+	    $dirname .= $num;
+	}
+	
+	$mapping{$index} = $dirname;
+	$dirnames{$dirname} = $index;
+    }
+
+    return \%mapping;
+}
+
+
+sub build_index {
+    my $self = shift (@_);
+    my ($index) = @_;
+
+    # get the full index directory path and make sure it exists
+    my $indexdir = $self->{'index_mapping'}->{$index};
+    &util::mk_all_dir (&util::filename_cat($self->{'build_dir'}, $indexdir));
+    my $fullindexprefix = &util::filename_cat ($self->{'build_dir'}, $indexdir, 
+					       $self->{'collection'});
+    my $fulltextprefix = &util::filename_cat ($self->{'build_dir'}, "text", 
+					       $self->{'collection'});
+
+    # get any os specific stuff
+    my $exedir = "$ENV{'GSDLHOME'}/bin/$ENV{'GSDLOS'}";
+    my $exe = &util::get_os_exe ();
+    my $osextra = "";
+    if ($ENV{'GSDLOS'} =~ /^windows$/i) {
+	$fullindexprefix =~ s/\//\\/g;
+    } else {
+	$osextra = " -d /";
+    }
+
+    # get the index level from the index description
+    # the index will be level 2 unless we are building a
+    # paragraph level index
+    my $index_level = 2;
+    $index_level = 3 if $index =~ /^paragraph/i;
+
+    # set up the document processor
+    $self->{'buildproc'}->set_output_handle ('mgbuilder::PIPEOUT');
+    $self->{'buildproc'}->set_mode ('text');
+    $self->{'buildproc'}->set_index ($index);
+
+
+    # Build index dictionary. Uses verbatim stem method
+    print STDERR "\n    creating index dictionary\n"  if ($self->{'verbosity'} >= 1);
+    if (!-e "$exedir/mg_passes$exe" || !open (PIPEOUT, 
+	    "| $exedir/mg_passes$exe -f $fullindexprefix -b $maxdocsize " .
+	    "-$index_level -m 32 -s 0 -G -t 10 -N1 $osextra")) {
+	die "mgbuilder::build_index - couldn't run $exedir/mg_passes$exe\n";
+    }
+    $self->{'buildproc'}->reset();
+    &plugin::read ($self->{'pluginfo'}, $self->{'source_dir'}, 
+		   "", {}, $self->{'buildproc'});
+    close (PIPEOUT);
+
+    # create the perfect hash function
+    if (!-e "$exedir/mg_perf_hash_build$exe") {
+	die "mgbuilder::build_index - couldn't run $exedir/mg_perf_hash_build$exe\n";
+    }
+    system ("$exedir/mg_perf_hash_build$exe -f $fullindexprefix $osextra");
+
+    # invert the text
+    print STDERR "\n    inverting the text\n"  if ($self->{'verbosity'} >= 1);
+    if (!-e "$exedir/mg_passes$exe" || !open (PIPEOUT, 
+	    "| $exedir/mg_passes$exe -f $fullindexprefix -b $maxdocsize " .
+	    "-$index_level -c 3 -G -t 10 -N2 $osextra")) {
+	die "mgbuilder::build_index - couldn't run $exedir/mg_passes$exe\n";
+    }
+    $self->{'buildproc'}->reset();
+    &plugin::read ($self->{'pluginfo'}, $self->{'source_dir'}, 
+		   "", {}, $self->{'buildproc'});
+    close (PIPEOUT);
+
+    # create the weights file
+    print STDERR "\n    create the weights file\n"  if ($self->{'verbosity'} >= 1);
+    if (!-e "$exedir/mg_weights_build$exe") {
+	die "mgbuilder::build_index - couldn't run $exedir/mg_weights_build$exe\n";
+    }
+    system ("$exedir/mg_weights_build$exe -f $fullindexprefix -t $fulltextprefix $osextra");
+
+    # create 'on-disk' stemmed dictionary
+    print STDERR "\n    creating 'on-disk' stemmed dictionary\n"  if ($self->{'verbosity'} >= 1);
+    if (!-e "$exedir/mg_invf_dict$exe") {
+	die "mgbuilder::build_index - couldn't run $exedir/mg_invf_dict$exe\n";
+    }
+    system ("$exedir/mg_invf_dict$exe -f $fullindexprefix $osextra");
+
+
+    # creates stem index files for the various stemming methods
+    print STDERR "\n    creating stem indexes\n"  if ($self->{'verbosity'} >= 1);
+    if (!-e "$exedir/mg_stem_idx$exe") {
+	die "mgbuilder::build_index - couldn't run $exedir/mg_stem_idx$exe\n";
+    }
+    system ("$exedir/mg_stem_idx$exe -b 4096 -s1 -f $fullindexprefix $osextra");
+    system ("$exedir/mg_stem_idx$exe -b 4096 -s2 -f $fullindexprefix $osextra");
+    system ("$exedir/mg_stem_idx$exe -b 4096 -s3 -f $fullindexprefix $osextra");
+
+    
+    # remove unwanted files
+    my $tmpdir = &util::filename_cat ($self->{'build_dir'}, $indexdir);
+    opendir (DIR, $tmpdir) || die
+	"mgbuilder::build_index - couldn't read directory $tmpdir\n";
+    foreach $file (readdir(DIR)) {
+	next if $file =~ /^\./;
+	my ($suffix) = $file =~ /\.([^\.]+)$/;
+	if (defined $suffix && !defined $wanted_index_files{$suffix}) {
+	    # delete it!
+#	    print STDERR "deleting $file\n";
+	    &util::rm (&util::filename_cat ($tmpdir, $file));
+	}
+    }
+    closedir (DIR);
+}
+
+sub make_infodatabase {
+    my $self = shift (@_);
+    my $textdir = &util::filename_cat($self->{'build_dir'}, "text");
+    &util::mk_all_dir ($textdir);
+
+    # assume little-endian for now :-)
+    my $fulldbname = &util::filename_cat ($textdir, "$self->{'collection'}.ldb");
+    $fulldbname =~ s/\//\\/g if ($ENV{'GSDLOS'} =~ /^windows$/i);
+    my $exedir = "$ENV{'GSDLHOME'}/bin/$ENV{'GSDLOS'}";
+    my $exe = &util::get_os_exe ();
+
+    print STDERR "\n*** creating the info database\n" if ($self->{'verbosity'} >= 1);
+
+    # set up the document processor
+    $self->{'buildproc'}->set_output_handle ('mgbuilder::PIPEOUT');
+    $self->{'buildproc'}->set_mode ('infodb');
+    
+    # collect the statistics for the text
+    # -b $maxdocsize sets the maximum document size to be 12 meg
+    if (!-e "$exedir/txt2db$exe" || !open (PIPEOUT, 
+            "| $exedir/txt2db$exe $fulldbname")) {
+	die "mgbuilder::make_infodatabase - couldn't run $exedir/txt2db$exe\n";
+    }
+    $self->{'buildproc'}->reset();
+    &plugin::read ($self->{'pluginfo'}, $self->{'source_dir'}, 
+		   "", {}, $self->{'buildproc'});
+    close (PIPEOUT);
+}
+
+sub make_auxiliary_files {
+    my $self = shift (@_);
+    my ($index);
+    my %build_cfg = ();
+
+    print STDERR "\n*** creating auxiliary files \n" if ($self->{'verbosity'} >= 1);
+
+    # get the text directory
+    &util::mk_all_dir ($self->{'build_dir'});
+
+    # store the build date
+    $build_cfg->{'builddate'} = time;
+
+    # store the number of documents and number of bytes
+    $build_cfg->{'numdocs'} = $self->{'buildproc'}->get_num_docs();
+    $build_cfg->{'numbytes'} = $self->{'buildproc'}->get_num_bytes();
+
+    # store the mapping between the index names and the directory names
+    my @indexmap = ();
+    foreach $index (@{$self->{'collect_cfg'}->{'indexes'}}) {
+	push (@indexmap, "$index\-\>$self->{'index_mapping'}->{$index}");
+    }
+    $build_cfg->{'indexmap'} = \@indexmap;
+
+    # write out the build information
+    &cfgread::write_cfg_file("$self->{'build_dir'}/build.cfg", $build_cfg,
+			     '^(builddate|numdocs|numbytes)$', '^(indexmap)$');
+
+}
+
+sub deinit {
+    my $self = shift (@_);
+}
+
+
+1;
+
+
Index: /tags/start/gsdl/perllib/mgbuildproc.pm
===================================================================
--- /tags/start/gsdl/perllib/mgbuildproc.pm	(revision 13666)
+++ /tags/start/gsdl/perllib/mgbuildproc.pm	(revision 13666)
@@ -0,0 +1,467 @@
+# This document processor saves a document in the 
+# archives directory of a collection
+
+
+package mgbuildproc;
+
+use docproc;
+use util;
+
+
+BEGIN {
+    @ISA = ('docproc');
+}
+
+
+sub new {
+    my ($class, $collection, $source_dir, $build_dir, $verbosity) = @_;
+    my $self = new docproc ();
+
+    $self->{'collection'} = $collection;
+    $self->{'source_dir'} = $source_dir;
+    $self->{'build_dir'} = $build_dir;
+    $self->{'verbosity'} = $verbosity;
+    $self->{'mode'} = "text";
+    $self->{'index'} = "section:text";
+    $self->{'output_handle'} = "STDOUT";
+    $self->{'num_docs'} = 0;
+    $self->{'num_sections'} = 0;
+    $self->{'num_bytes'} = 0;
+
+    return bless $self, $class;
+}
+
+sub reset {
+    my $self = shift (@_);
+    
+    $self->{'num_docs'} = 0;
+    $self->{'num_sections'} = 0;
+    $self->{'num_bytes'} = 0;
+}
+
+sub get_num_docs {
+    my $self = shift (@_);
+
+    return $self->{'num_docs'};
+}
+
+sub get_num_sections {
+    my $self = shift (@_);
+
+    return $self->{'num_sections'};
+}
+
+sub get_num_bytes {
+    my $self = shift (@_);
+
+    return $self->{'num_bytes'};
+}
+
+sub set_output_handle {
+    my $self = shift (@_);
+    my ($handle) = @_;
+
+    $self->{'output_handle'} = $handle;
+}
+
+sub set_mode {
+    my $self = shift (@_);
+    my ($mode) = @_;
+
+    $self->{'mode'} = $mode;
+}
+
+sub set_index {
+    my $self = shift (@_);
+    my ($index) = @_;
+
+    $self->{'index'} = $index;
+}
+
+sub process {
+    my $self = shift (@_);
+    my ($doc_obj) = @_;
+    my $method = $self->{'mode'};
+
+    $self->$method($doc_obj);
+}
+
+sub infodb {
+    my $self = shift (@_);
+    my ($doc_obj) = @_;
+    my $handle = $self->{'output_handle'};
+
+    if ($doc_obj eq 'classifications') {
+	# output classifications if all books have been processed
+	foreach $key (keys %$saved_classifications) {
+	    $saved_classifications->{$key}->{'contains'} = undef if 
+		$saved_classifications->{$key}->{'contains'} eq "";
+	    $saved_classifications->{$key}->{'parent'} = undef if 
+		(!defined $saved_classifications->{$key}->{'parent'}) || 
+		    ($saved_classifications->{$key}->{'parent'} eq "");
+	    $self->write_to_gdbm ($handle, $key, $saved_classifications->{$key}->{'title'}, 
+				  undef, undef, 
+				  $saved_classifications->{$key}->{'contains'}, undef, 
+				  $saved_classifications->{$key}->{'parent'}, undef);
+	}
+	return;
+    }
+
+    my $doctype = $doc_obj->get_doc_type();
+
+    # only output this document if it is one to be indexed
+    return if ($doctype ne "indexed_doc" && 
+	       $doctype ne "classification");
+
+    # found classification document
+    $saved_classifications = {} if ($doctype eq "classification");
+    $sectionmap = {};
+
+    # this is another document
+    $self->{'num_docs'} += 1 unless ($doctype eq "classification");
+
+    my $section = $doc_obj->get_top_section();
+    while (defined $section) {
+	# update a few statistics
+	$self->{'num_bytes'} += $doc_obj->get_text_length ($section);
+	$self->{'num_sections'} += 1 unless ($doctype eq "classification");
+
+	my $title = $doc_obj->get_metadata_element($section, "Title");
+	my $jobnumber = $doc_obj->get_source_filename();
+
+	my $mapped_section = $self->map_section($doctype, $section);
+	if ($doctype eq "classification") {
+	    $mapped_section = $self->char_classification($mapped_section);
+	} else {
+	    $mapped_section = "B.$self->{'num_docs'}.$mapped_section";
+	}
+	$mapped_section =~ s/\.+$//;
+
+	my ($parent, $classification, $creator, $OID);
+
+	if ($section ne $doc_obj->get_top_section()) {
+	    $parent = $self->map_section($doctype, $doc_obj->get_parent_section($section));
+	    if ($doctype eq "classification") {
+		$parent = $self->char_classification($parent);
+	    } else {
+		$parent = "B.$self->{'num_docs'}.$parent";
+	    }
+	    $parent =~ s/\.+$//;
+	} else {
+	    $classification = $self->get_classifications($doc_obj, $section, $mapped_section)
+		unless $doctype eq "classification";
+	    $creator = $doc_obj->get_metadata_element($section, "Creator");
+	    $OID = $doc_obj->get_OID();
+	    # this is a hack at getting OID to look like the directory path - I'm sure there's 
+	    # a better way to do it but it's late... Stefan
+	    my @OIDchars = split //, $OID;
+	    $OID = "";
+	    my $count = 0;
+	    foreach $i (@OIDchars) {
+		if ($count == 7) {
+		    $OID .= "$i/";
+		    $count = 0;
+		} else {
+		    $OID .= $i;
+		    $count ++;
+		}
+	    }
+	    $OID =~ s/\/$//;
+	    $OID .= ".dir";
+	}
+
+	if ($doc_obj->is_leaf_section($section)) {
+	    if ($doctype eq "classification") {
+		if (defined $saved_classifications->{$mapped_section}) {
+		    print STDERR "mgbuildproc:warning: classification $mapped_section " .
+			"declared multiple times\n";
+		} else {
+		    $saved_classifications->{$mapped_section}  = {'title' => $title, 'contains' => "",
+								  'parent' => $parent};
+		}
+	    } else {
+		$self->write_to_gdbm($handle, $mapped_section, $title, $creator, $jobnumber, undef,
+				     $self->{'num_sections'}, $parent, $classification, $OID);
+	    }
+	} else {
+
+	    # add the introductory section if it exists
+	    my $contains = "";
+	    if ($doc_obj->get_text_length($section) > 0) {
+		$contains .= "B.$self->{'num_docs'}." . $self->map_section ($doctype, "$section.0");
+	    }
+
+	    # add the rest of the children
+	    my @children = @{$doc_obj->get_children($section)};
+	    if ($doctype eq "classification") {
+		map {$_ = $self->char_classification($_);} @children;
+		if (defined $saved_classifications->{$mapped_section}) {
+		    print STDERR "mgbuildproc:warning: classification $mapped_section " .
+			"declared multiple times\n";
+		} else {
+		    $saved_classifications->{$mapped_section}  = {'title' => $title, 'contains' => ""};
+		    $saved_classifications->{$mapped_section}->{'contains'} = join ":", @children;
+		    $saved_classifications->{$mapped_section}->{'parent'} = $parent;
+		}
+	    } else {
+		map {$_ = "B.$self->{'num_docs'}." . $self->map_section($doctype, $_);} @children;
+		$contains .= ":" if $contains ne "";
+		$contains .= join ":", @children;
+		$self->write_to_gdbm ($handle, $mapped_section, $title, $creator,
+				      $jobnumber, $contains, $self->{'num_sections'},
+				      $parent, $classification, $OID);
+
+		if ($doc_obj->get_text_length($section) > 0) {
+		    my $intromapsection = "B.$self->{'num_docs'}." . 
+			$self->map_section($doctype, "$section.0");
+		    $self->write_to_gdbm ($handle, $intromapsection, "<i>(introductory text)</i>", $creator,
+					  $jobnumber, undef, $self->{'num_sections'},
+					  $mapped_section, undef, $OID);
+		}
+	    }
+	}
+	$section = $doc_obj->get_next_section($section);
+    }
+    
+    # update classification list with those books that 
+    # were processed before classification list
+    if ($doctype eq "classification" && defined $temp_classifications) {
+	foreach $key (keys(%$temp_classifications)) {
+	    if (!defined $saved_classifications->{$key}) {
+		print STDERR "mgbuildproc:$temp_classifications->{$key} belong to " .
+		    "undefined classification $key\n";
+	    } 
+	    $saved_classifications->{$key}->{'contains'} = $temp_classifications->{$key}->{'contains'};
+	}
+	$temp_classifications = undef;
+    }
+}
+
+
+sub write_to_gdbm {
+    my $self = shift (@_);
+    my ($handle, $section, $title, $creator, $jobnumber, $contains,
+	$docnum, $parent, $classification, $OID) = @_;
+
+    print $handle "[$section]\n";
+    print $handle "<t>$title\n" if defined $title;
+    print $handle "<a>$creator\n" if defined $creator;
+    print $handle "<j>$jobnumber\n" if defined $jobnumber;
+    print $handle "<c>$contains\n" if defined $contains;
+    print $handle "<d>$docnum\n" if defined $docnum;
+    print $handle "<p>$parent\n" if defined $parent;
+    print $handle "<x>$classification\n" if defined $classification;
+    print $handle "<o>$OID\n" if defined $OID;
+    print $handle '-' x 70, "\n";
+    
+    if (defined $docnum) {
+	print $handle "[$docnum]\n";
+	print $handle "<x>$section\n";
+	print $handle '-' x 70, "\n";
+    }
+}
+
+sub get_classifications {
+    my $self = shift (@_);
+    my ($doc_obj, $section, $mapped_section) = @_;
+
+    my ($classificationsref);
+    if (defined $saved_classifications) {
+	# classification list has been processed
+	$classificationsref = $saved_classifications;
+    } else {
+	# classification list has yet to be processed, save
+	# books in temp_classifications until list is processed
+	# and they can be moved into saved_classifications
+	$temp_classifications = {} unless defined $temp_classifications;
+	$classificationsref = $temp_classifications;
+    }
+
+    my $classifications = $doc_obj->get_metadata($section, "Subject");
+
+    # need to save which books belong in each classification
+    # to output later
+    foreach $classification (@$classifications) {
+
+	if (!defined $classificationsref->{$classification}) {
+	    $classificationsref->{$classification}->{'parent'} = $doc_obj->get_parent_section($section);
+	    $classificationsref->{$classification}->{'contains'} = "";
+	}
+	$classificationsref->{$classification}->{'contains'} .= ":" unless
+	    $classificationsref->{$classification}->{'contains'} eq "";
+	$classificationsref->{$classification}->{'contains'} .= $mapped_section;
+    }
+
+    return (join ":", @$classifications);
+}
+
+sub map_section {
+    my $self = shift (@_);
+    my ($doctype, $section) = @_;
+
+    # classifications should never need to be mapped
+    return $section if $doctype eq "classification";
+
+    return "" unless (defined $section) && ($section ne "");
+
+    $sectionmap = {} unless defined $sectionmap;
+
+
+
+    # get the section into a standard format
+    $section =~ s/^\.+|\.+$//g;
+
+    # return the mapped section if it has been seen before
+    if (defined $sectionmap->{$section}) {
+	return $sectionmap->{$section};
+    }
+
+    # find out the parent section
+    my ($parentsection, $num);
+    if ($section =~ /^(.+)\.(\d+)$/) {
+	$parentsection = $1;
+	$num = $2;
+    } elsif ($section =~ /^(\d+)$/) {
+	$parentsection = "";
+	$num = $1;
+    } else {
+	print STDERR "mgbuildproc:map_section - misformed section $section\n";
+    }
+    $parentsection = "" unless defined $parentsection;
+
+    if ($parentsection eq "") {
+	$num ++ if $num == 1 and defined $sectionmap->{'0'};
+    } else {
+	$num ++ if $num == 1 and defined $sectionmap->{"$parentsection.0"};
+    }
+
+    # find out the mapped parent section
+    my $mappedparentsection = $self->map_section ($doctype, $parentsection);
+
+    # find the next unused child section
+    my $previousnum = $num - 1;
+    my $previoussection = "";
+    if ($parentsection eq "") {
+	$previoussection = $previousnum;
+	$previoussection = 0 if ($section == 1) && (defined $sectionmap->{'0'});
+    } else{
+	$previoussection = "$parentsection.$previousnum";
+	$previoussection = "$parentsection.0" if ($section =~ /\.1$/) && (defined $sectionmap->{"$parentsection.0"});
+    }
+    while (($previousnum > 0) && (!defined $sectionmap->{$previoussection})) {
+	$previousnum--;
+	$previoussection = "$parentsection.$previousnum";
+	$previoussection = $previousnum if $parentsection eq "";
+    }
+
+    # there has been no children under this parent, this section will be number 1
+    if ($previousnum <= 0) {
+	if ($mappedparentsection eq "") {
+	    $sectionmap->{$section} = "1";
+	} else {
+	    $sectionmap->{$section} = "$mappedparentsection.1";
+	}
+
+    } else {
+	# get the previous mapped number
+	my $previousmapnum = 0;
+	if ($sectionmap->{$previoussection} =~ /(^|\.)?(\d+)$/) {
+	    $previousmapnum = $2;
+	}
+	
+	# increment it to get this mapped child
+	my $mappednum = $previousmapnum+1;
+
+	if ($mappedparentsection eq "") {
+	    $sectionmap->{$section} = $mappednum;
+	} else {
+	    $sectionmap->{$section} = "$mappedparentsection.$mappednum";
+	}
+    }
+
+    return $sectionmap->{$section};
+}
+
+sub text {
+    my $self = shift (@_);
+    my ($doc_obj) = @_;
+    my $handle = $self->{'output_handle'};
+
+    # only output this document if it is one to be indexed
+    return if ($doc_obj->get_doc_type() ne "indexed_doc");
+
+    # this is another document
+    $self->{'num_docs'} += 1;
+
+    # get the parameters for the output
+    my ($level, $fields) = split (/:/, $self->{'index'});
+    $fields =~ s/\ball\b/Title,Creator,text/;
+    $fields =~ s/\btopall\b/topTitle,topCreator,toptext/;
+
+    my $doc_section = 0; # just for this document
+    my $text = "";
+    my $text_extra = "";
+
+    # get the text for this document
+    my $section = $doc_obj->get_top_section();
+    while (defined $section) {
+	# update a few statistics
+	$doc_section++;
+	$self->{'num_bytes'} += $doc_obj->get_text_length ($section);
+	$self->{'num_sections'} += 1;
+	
+	foreach $field (split (/,/, $fields)) {
+	    # only deal with this field if it doesn't start with top or
+	    # this is the first section
+	    my $real_field = $field;
+	    if (!($real_field =~ s/^top//) || ($doc_section == 1)) {
+		my $new_text = "";
+		if ($real_field eq "text") {
+		    $new_text = $doc_obj->get_text ($section);
+		    $new_text =~ s/[\cB\cC]//g;
+		    $new_text =~ s/(<p\b)/\cC$1/gi;
+		    
+		} else {
+		    $new_text = join ("\cC", @{$doc_obj->get_metadata ($section, $real_field)});
+		}
+	    
+		$text .= "$new_text\cC";
+	    }
+	}
+	
+	if ($level eq "document") { $text_extra .= "\cB"; }
+	else { $text .= "\cB"; }
+	
+	$section = $doc_obj->get_next_section($section);
+    }
+
+    print $handle "$text$text_extra";
+}
+
+# converts leading number in classification back 
+# to letter it represents
+# i.e 67.2.4 becomes C.2.4
+sub char_classification {
+    my $self = shift (@_);
+    my ($classification) = @_;
+
+    return $classification if $classification eq "";
+    my ($c) = $classification =~ /^\.?(\d+)/;
+    $c = chr($c);
+    $classification =~ s/^\d+/$c/;
+
+    return $classification;
+}
+
+# converts leading letter of a classification into its ascii equivalent
+# i.e C.2.4 becomes 67.2.4
+sub int_classification {
+    my $self = shift (@_);
+    my ($classification) = @_;
+    my $c = ord($classification);
+    $classification =~ s/^./$c/;
+
+    return $classification;
+}
+1;
+
Index: /tags/start/gsdl/perllib/parsargv.pm
===================================================================
--- /tags/start/gsdl/perllib/parsargv.pm	(revision 13666)
+++ /tags/start/gsdl/perllib/parsargv.pm	(revision 13666)
@@ -0,0 +1,181 @@
+package parsargv;
+# 
+# parse(ARGVREF, [SPEC, VARREF] ...)
+# 
+# Parse command line arguments.
+# 
+# ARGVREF is an array reference, usually to @ARGV.  The remaining
+# arguments are paired (SPEC, VARREF).  SPEC is a specification string
+# for a particular argument; VARREF is a variable reference that will
+# receive the argument.
+# 
+# SPEC is in one of the following forms:
+# 
+# ARG/REGEX/DEFAULT ARG is the name of command line argument.  REGEX is
+#     a regular expression that gives legal values for the argument.
+#     DEFAULT is the default value assigned to VARREF if the option does
+#     not appear on the command line.  Example
+# 
+# 
+# ARG/REGEX ARG and REGEX are as above.  Since no default is given, ARG
+#     must appear on the command line; if it doesn't, parse() returns 0.
+# 
+# ARG ARG is as above.  ARG is a boolean option.  VARREF is assigned 0 if ARG
+#     is not on the command line; 1 otherwise.
+# 
+# SPEC may start with a punctuation character, in which case this
+# character will be used instead of '/' as a delimiter.  Useful when '/'
+# is needed in the REGEX part.
+# 
+# VARREF is a reference to a scalar or an array.  If VARREF is an array
+# reference, then multiple command line options are allowed an append.  Example:
+# 
+# 	Command line: -day mon -day fri
+# 
+# 	parse(\@ARGV, "day/(mon|tue|wed|thu|fri)", \@days)
+# 
+# 	days => ('mon', 'fri')
+# 
+# Returns 0 if there was an error, nonzero otherwise.
+# 
+sub parse
+{
+    my $arglist = shift;
+    my ($spec, $var);
+    my %option;
+
+    while (($spec, $var) = splice(@_, 0, 2))
+    {
+	die "Variable for $spec is not a valid type."
+	    unless ref($var) eq 'SCALAR' || ref($var) eq 'ARRAY';
+
+	my $delimiter;
+	if ($spec !~ /^\w/)
+	{
+	    $delimiter = substr($spec, 0, 1);
+	    $spec = substr($spec, 1);
+	}
+	else
+	{
+	    $delimiter = '/';
+	}
+	my ($name, $regex, $default) = split(/$delimiter/, $spec, 3);
+	
+	if ($name)
+	{
+	    if ($default && $default !~ /$regex/)
+	    {
+		die "Default value for $name doesn't match regex ($spec).";
+	    }
+	    $option{$name} = {'name' => $name,
+			      'regex' => $regex,
+			      'default' => $default,
+			      'varref' => $var,
+			      'set' => 0};
+	}
+	else
+	{
+	    die "Invalid argument ($spec) for parsargv.";
+	}
+    }
+
+    my @argv;
+    my $arg;
+    my $parse_options = 1;
+    my $errors = 0;
+
+    while ($arg = shift(@$arglist))
+    {
+	if ($parse_options && $arg eq '--')
+	{
+	    $parse_options = 0;
+	    next;
+	}
+
+	if ($parse_options && $arg =~ /^-+\w/)
+	{
+	    $arg =~ s/^-+//;
+
+	    if (defined $option{$arg})
+	    {
+		&process_arg($option{$arg}, $arglist, \$errors);
+	    }
+	    else
+	    {
+		print STDERR "$arg is not a valid option.\n";
+		$errors++;
+	    }
+	}
+	else
+	{
+	    push(@argv, $arg);
+	}
+    }
+    @$arglist = @argv;
+
+    foreach $arg (keys %option)
+    {
+	if ($option{$arg}->{'set'} == 0)
+	{
+	    if (defined $option{$arg}->{'default'})
+	    {
+		&set_var($option{$arg}, $option{$arg}->{'default'});
+	    }
+	    elsif (!$option{$arg}->{'regex'})
+	    {
+		&set_var($option{$arg}, 0)
+	    }
+	    elsif (ref($option{$arg}->{'varref'}) ne 'ARRAY')
+	    {
+		print STDERR "Missing command line argument -$arg.\n";
+		$errors++;
+	    }
+	}
+    }
+    return $errors == 0;
+}
+
+sub process_arg
+{
+    my ($option, $arglist, $errors) = @_;
+
+    if ($option->{'regex'} && @$arglist > 0 && $arglist->[0] !~ /^-+\w/)
+    {
+	if ($arglist->[0] =~ /$option->{'regex'}/)
+	{
+	    &set_var($option, shift(@$arglist));
+	}
+	else
+	{
+	    print STDERR "Bad value for -$option->{'name'} argument.\n";
+	    $$errors++;
+	}
+    }
+    elsif (!$option->{'regex'})
+    {
+	&set_var($option, 1);
+    }
+    else
+    {
+	print STDERR "No value given for -$option->{'name'}.\n";
+	$$errors++;
+    }
+}
+
+sub set_var
+{
+    my ($option, $value) = @_;
+    my $type = ref($option->{'varref'});
+
+    if ($type eq 'SCALAR')
+    {
+	${$option->{'varref'}} = $value;
+    }
+    elsif ($type eq 'ARRAY')
+    {
+	push(@{$option->{'varref'}}, $value);
+    }
+    $option->{'set'} = 1;
+}
+
+1;
Index: /tags/start/gsdl/perllib/plugin.pm
===================================================================
--- /tags/start/gsdl/perllib/plugin.pm	(revision 13666)
+++ /tags/start/gsdl/perllib/plugin.pm	(revision 13666)
@@ -0,0 +1,50 @@
+# functions to handle using the plugins
+
+package plugin;
+
+
+sub load_plugins {
+    my ($collection, $plugin_list) = @_;
+    my @plugin_objects = ();
+
+    foreach $plugin (@$plugin_list) {
+	# find the plugin
+	if (-e "$ENV{'GSDLHOME'}/collect/$collection/lib/plugins/${plugin}.pm") {
+	    require "$ENV{'GSDLHOME'}/collect/$collection/lib/plugins/${plugin}.pm";
+
+	} elsif (-e "$ENV{'GSDLHOME'}/lib/plugins/${plugin}.pm") {
+	    require "$ENV{'GSDLHOME'}/lib/plugins/${plugin}.pm";
+
+	} else {
+	    die "ERROR - couldn't find plugin $plugin\n";
+	}
+
+	# create a plugin object
+	my ($plugobj);
+	eval ("\$plugobj = new $plugin()");
+	die "$@" if $@;
+
+	# add this object to the list
+	push (@plugin_objects, $plugobj);
+    }
+
+    return \@plugin_objects;
+}
+
+sub read {
+    my ($pluginfo, $base_dir, $file, $metadata, $processor) = @_;
+
+    # pass this file by each of the plugins in turn until one
+    # is found which will process it
+    foreach $plugobj (@$pluginfo) {
+	if ($plugobj->read($pluginfo, $base_dir, $file, 
+			   $metadata, $processor)) {
+	    return;
+	}
+    }
+
+    print STDERR "WARNING - no plugin could process $base_dir$file\n";
+}
+
+
+1;
Index: /tags/start/gsdl/perllib/plugins/ArcPlug.pm
===================================================================
--- /tags/start/gsdl/perllib/plugins/ArcPlug.pm	(revision 13666)
+++ /tags/start/gsdl/perllib/plugins/ArcPlug.pm	(revision 13666)
@@ -0,0 +1,104 @@
+# plugin which recurses through directories processing
+# each file it finds
+
+package ArcPlug;
+
+use util;
+use BasPlug;
+use plugin;
+use arcinfo;
+
+BEGIN {
+    @ISA = ('BasPlug');
+}
+
+sub new {
+    my ($class) = @_;
+    my $self = new BasPlug ();
+
+    return bless $self, $class;
+}
+
+# return 1 if this class might recurse using $pluginfo
+sub is_recursive {
+    my $self = shift (@_);
+
+    return 1;
+}
+
+# return 1 if processed, 0 if not processed
+# Note that $base_dir might be "" and that $file might 
+# include directories
+sub read {
+    my $self = shift (@_);
+    ($pluginfo, $base_dir, $file, $metadata, $processor) = @_;
+
+    # see if this has a archives information file within it
+    $archive_info_filename = &util::filename_cat($base_dir,$file,"archives.inf");
+
+    if (-e $archive_info_filename) {
+
+	# read in the archives information file
+	my $archive_info = new arcinfo ();
+	$archive_info->load_info ($archive_info_filename);
+	
+	my $file_list = $archive_info->get_file_list();
+
+	# process each file
+	foreach $subfile (sort alphabetically @$file_list) {
+	    # note: metadata is not carried on to the next level
+	    my $tmp = &util::filename_cat ($file, $subfile->[0]);
+	    next if $tmp eq $file;
+	    &plugin::read ($pluginfo, $base_dir, $tmp, {}, $processor);
+	}
+	
+	# all books have been processed so need to output classifications
+	# to infodb - note that at present you have to import before building
+	if ($processor->{'mode'} eq 'infodb') {
+	    print STDERR "ArcPlug: Adding classifications to infodb\n";
+	    $processor->process('classifications');
+	}
+
+	return 1;
+    }
+
+    # wasn't an archives directory, someone else will have to process it
+    return 0;
+}
+
+# sort files so they're built (and displayed) in alphabetical order
+sub alphabetically {
+    open (A, &util::filename_cat($base_dir, $file, $a->[0])) || 
+	die "couldn't open " . &util::filename_cat($base_dir, $file, $a->[0]) . "\n";
+    open (B, &util::filename_cat($base_dir, $file, $b->[0])) || 
+	die "couldn't open " . &util::filename_cat($base_dir, $file, $b->[0]) . "\n";
+    my ($atitle, $btitle);
+    my $line = "";
+    while (defined ($line .= <A>)) {
+	if ($line =~ /Title=\"([^\"]*)\"/) {$atitle = $1; last;}
+    } 
+    $line = "";
+    while (defined ($line .= <B>)) {
+	if ($line =~ /Title=\"([^\"]*)\"/) {$btitle = $1; last;}
+    } 
+    close A;
+    close B;
+    
+    $atitle =~ tr/A-Z/a-z/;
+    $atitle =~ s/[^a-z0-9 ]//g;
+    $atitle =~ s/^\s+//;
+    $atitle =~ s/^(the|a|an)\b//;
+    $atitle =~ s/^\s+//;
+    $atitle =~ s/^(.).*$/$1/;
+    
+    $btitle =~ tr/A-Z/a-z/;
+    $btitle =~ s/[^a-z0-9 ]//g;
+    $btitle =~ s/^\s+//;
+    $btitle =~ s/^(the|a|an)\b//;
+    $btitle =~ s/^\s+//;
+    $btitle =~ s/^(.).*$/$1/;
+
+    $atitle cmp $btitle;
+}
+
+1;
Index: /tags/start/gsdl/perllib/plugins/BasPlug.pm
===================================================================
--- /tags/start/gsdl/perllib/plugins/BasPlug.pm	(revision 13666)
+++ /tags/start/gsdl/perllib/plugins/BasPlug.pm	(revision 13666)
@@ -0,0 +1,32 @@
+# base class for all the import plugins
+
+package BasPlug;
+
+
+sub new {
+    my ($class) = @_;
+
+    return bless {}, $class;
+}
+
+# return 1 if this class might recurse using $pluginfo
+sub is_recursive {
+    my $self = shift (@_);
+
+    die "BasPlug::is_recursive function must be implemented in sub classes\n";
+}
+
+# return 1 if processed, 0 if not processed
+# Note that $base_dir might be "" and that $file might 
+# include directories
+sub read {
+    my $self = shift (@_);
+    my ($pluginfo, $base_dir, $file, $metadata, $processor) = @_;
+
+    die "BasPlug::read function must be implemented in sub classes\n";
+
+    return 0; # will never get here
+}
+
+
+1;
Index: /tags/start/gsdl/perllib/plugins/GMLPlug.pm
===================================================================
--- /tags/start/gsdl/perllib/plugins/GMLPlug.pm	(revision 13666)
+++ /tags/start/gsdl/perllib/plugins/GMLPlug.pm	(revision 13666)
@@ -0,0 +1,117 @@
+# plugin which process an HTML book directory
+
+package GMLPlug;
+
+use html;
+use BasPlug;
+use util;
+use doc;
+
+
+sub BEGIN {
+    @ISA = ('BasPlug');
+}
+
+sub new {
+    my ($class) = @_;
+    $self = new BasPlug ();
+
+    return bless $self, $class;
+}
+
+sub is_recursive {
+    my $self = shift (@_);
+
+    return 0; # this is not a recursive plugin
+}
+
+# return 1 if processed, 0 if not processed
+# Note that $base_dir might be "" and that $file might 
+# include directories
+sub read {
+    my $self = shift (@_);
+    my ($pluginfo, $base_dir, $file, $metadata, $processor) = @_;
+    my $fullname = &util::filename_cat ($base_dir, $file);
+
+    # see if this is a gml book
+    return 0 unless (-f $fullname && $fullname =~ /\.gml$/i);
+
+    my ($parent_dir) = $fullname =~ /^(.*)\/[^\/]+.gml$/;
+
+    # create a new document
+    my $doc_obj = new doc ();
+    my $section = $doc_obj->get_top_section();
+
+    print STDERR "GMLPlug: processing $file\n";
+
+    # read in the document
+    my $gml = "";
+    my $line = "";
+    if (!open (INFILE, $fullname)) {
+	print STDERR "GMLPlug::read - couldn't read $fullname\n";
+	return 0;
+    }
+    while (defined ($line = <INFILE>)) {
+	$gml .= $line;
+    }
+    close (INFILE);
+
+    # process the document
+    my $firstsection = 1;
+    while ($gml =~ /\S/) {
+	if ($gml =~ s/^\s*<gsdlsection([^>]*)>(.*?)(<\/?gsdlsection)/$3/is) {
+	    my $tags = $1;
+	    $tags = "" unless defined $tags;
+	    my $text = $2;
+
+	    # create the section (unless this is the first section)
+	    if (!$firstsection) {
+		$tags =~ s/gsdlnum\s*=\s*\"?(\d+)\"?//i;
+		if (defined $1) {
+		    $section .= ".$1";
+		    $doc_obj->create_named_section($section);
+		} else {
+		    $section = $doc_obj->insert_section($doc_obj->get_end_child($section));
+		}
+	    }
+	    $firstsection = 0;
+
+	    # add the tags
+	    while ((defined $tags) && ($tags =~ s/^\s*(\w+)\s*=\s*\"([^\"]*)\"//)) {
+		$doc_obj->add_metadata($section, $1 , $2) if (defined $1 and defined $2);
+	    }
+
+	    # add the text
+	    $doc_obj->add_text($section, $text) if ((defined $text) && ($text ne ""));
+
+	} elsif ($gml =~ s/^\s*<\/gsdlsection>//) {
+	    $section = $doc_obj->get_parent_section ($section);
+
+	} else {
+	    print STDERR "GMLPlug::read - error in file $fullname\n";
+	    print STDERR "text: \"$gml\"\n";
+	    last;
+	}
+    }
+
+    # add the associated files
+    $assoc_files = $doc_obj->get_metadata($doc_obj->get_top_section(), "gsdlassocfile");
+    my ($assoc_file_info);
+    foreach $assoc_file_info (@$assoc_files) {
+	my ($assoc_file, $mime_type) = split (":", $assoc_file_info);
+	$doc_obj->associate_file(&util::filename_cat($parent_dir, $assoc_file),
+				 $assoc_file, $mime_type);
+				 
+    }
+    $doc_obj->delete_metadata($doc_obj->get_top_section(), "gsdlassocfile");
+
+    # assume the document has an OID
+
+    # process the document
+    $processor->process($doc_obj);
+        
+    return 1; # processed the file
+}
+
+
+1;
Index: /tags/start/gsdl/perllib/plugins/HBPlug.pm
===================================================================
--- /tags/start/gsdl/perllib/plugins/HBPlug.pm	(revision 13666)
+++ /tags/start/gsdl/perllib/plugins/HBPlug.pm	(revision 13666)
@@ -0,0 +1,244 @@
+# plugin which process an HTML book directory
+
+package HBPlug;
+
+use html;
+use BasPlug;
+
+
+sub BEGIN {
+    @ISA = ('BasPlug');
+}
+
+sub new {
+    my ($class) = @_;
+    $self = new BasPlug ();
+
+    return bless $self, $class;
+}
+
+sub is_recursive {
+    my $self = shift (@_);
+
+    return 0; # this is not a recursive plugin
+}
+
+sub HB_read_html_file {
+    my $self = shift (@_);
+    my ($htmlfile) = @_;
+
+    # load in the file
+    if (!open (FILE, $htmlfile)) {
+	print STDERR "ERROR - could not open $htmlfile\n";
+	return "";
+    }
+
+    my $line = "";
+    my $file = "";
+    my $foundbody = 0;
+    while (defined ($line = <FILE>)) {
+	# look for body tag
+	if (!$foundbody) {
+	    if ($line =~ s/^.*<body[^>]*>//i) {
+		$foundbody = 1;
+	    } else {
+		next;
+	    }
+	}
+
+	# check for symbol fonts
+	if ($line =~ /<font [^>]*?face\s*=\s*\"?(\w+)\"?/i) {
+	    my $font = $1;
+	    print STDERR "HBPlug::HB_read_html_file - warning font $font used\n" 
+		if ($font !~ /^arial$/i);
+	}
+
+
+	$line =~ s/<\/p>//ig;   # remove </p> tags
+	$line =~ s/<\/?(body|html|font)\b[^>]*>//ig; # remove any unwanted tags
+
+	# convert any alphanumeric character entities to their extended
+	# ascii equivalent for indexing purposes
+	&html::convertcharentities ($line);
+
+	$file .= $line;
+    }
+    close FILE;
+
+    $file =~ s/\s+/ /g; # remove \n's
+
+    return $file;
+}
+
+sub HB_clean_section {
+    my $self = shift (@_);
+    my ($section) = @_;
+
+    # remove tags without a starting tag from the section
+    my ($tag, $tagstart);
+    while ($section =~ /<\/([^>]{1,10})>/) {
+	$tag = $1;
+	$tagstart = index($section, "<$tag");
+	last if (($tagstart >= 0) && ($tagstart < index($section, "<\/$tag")));
+	$section =~ s/<\/$tag>//;
+    }
+    
+    # remove extra paragraph tags
+    while ($section =~ s/<p\b[^>]*>\s*<p\b/<p/ig) {}
+    
+    # remove extra stuff at the end of the section
+    while ($section =~ s/(<u>|<i>|<b>|<p\b[^>]*>|&nbsp;|\s)$//i) {}
+    
+    # add a newline at the beginning of each paragraph
+    $section =~ s/(.)\s*<p\b/$1\n\n<p/gi;
+    
+    # add a newline every 80 characters at a word boundary
+    # Note: this regular expression puts a line feed before
+    # the last word in each section, even when it is not
+    # needed.
+    $section =~ s/(.{1,80})\s/$1\n/g;
+    
+    # fix up the image links -- not sure what Rodger intended here - Stefan.
+#    $section =~ s/<img[^>]*?src=\"?([^\">]+)\"?[^>]*>/<img src=\"_linkOID_(_thisOID_\/$1)\"><br>/ig;
+#    $section =~ s/&lt;&lt;I&gt;&gt;\s*([^\.]+\.(png|jpg|gif))/<img src=\"_linkOID_(_thisOID_\/$1)\"><br>/ig;
+
+    $section =~ s/<img[^>]*?src=\"?([^\">]+)\"?[^>]*>/<center><img src=\"_httpcollection_\/archives\/_thisOID_\/$1\"><\/center><br>/ig;
+    $section =~ s/&lt;&lt;I&gt;&gt;\s*([^\.]+\.(png|jpg|gif))/<center><img src=\"_httpcollection_\/archives\/_thisOID_\/$1\"><\/center><br>/ig;
+
+    return $section;
+}
+
+
+sub shorten {
+    my $self = shift (@_);
+    my ($text) = @_;
+
+    return "\"$text\"" if (length($text) < 100);
+
+    return "\"" . substr ($text, 0, 50) . "\" ... \"" . 
+	substr ($text, length($text)-50) . "\"";
+}
+
+
+# return 1 if processed, 0 if not processed
+# Note that $base_dir might be "" and that $file might 
+# include directories
+sub read {
+    my $self = shift (@_);
+    my ($pluginfo, $base_dir, $file, $metadata, $processor) = @_;
+
+    # get the html filename and see if this is a HTML Book...
+    my ($jobnumber);
+    if ($file =~ /[\\\/]/) {
+	($jobnumber) = $file =~ /[\\\/]([^\\\/]+)$/;
+    } else {
+	($jobnumber) = $file =~ /^([^\\\/]+)$/;
+    }
+    return 0 unless defined $jobnumber;
+    my $htmlfile = "$base_dir$file/$jobnumber.htm";
+    return 0 unless -e $htmlfile;
+
+    print STDERR "HBPlug: processing $file\n";
+
+    # read in the file and do basic html cleaning (removing header etc)
+    my $html = $self->HB_read_html_file ($htmlfile);
+
+    # create a new document
+    my $doc_obj = new doc ($file, "indexed_doc");
+
+    # copy the book cover if it exists
+    my $bookcover = "$base_dir$file/$jobnumber.jpg";
+    $doc_obj->associate_file($bookcover, "cover.jpg", "image/jpeg") 
+	if -e $bookcover;
+
+    # process the file one section at a time
+    my $curtoclevel = 1;
+    my $cursection = $doc_obj->get_top_section();
+    my $firstsection = 1;
+    while (length ($html) > 0) {
+	if ($html =~ s/^.*?<p\b[^>]*>((<b>|<i>|<u>|\s)*)&lt;&lt;TOC(\d+)&gt;&gt;\s*(.*?)<p\b/<p/i) {
+	    my $toclevel = $3;
+	    my $title = $4;
+	    my $sectiontext = "";
+	    if ($html =~ s/^(.*?)(<p\b[^>]*>((<b>|<i>|<u>|\s)*)&lt;&lt;TOC\d+&gt;&gt;)/$2/i) {
+		$sectiontext = $1;
+	    } else {
+		$sectiontext = $html;
+		$html = "";
+	    }
+
+	    # remove tags and extra spaces from the title
+	    $title =~ s/<\/?[^>]+>//g;
+	    $title =~ s/^\s+|\s+$//g;
+
+	    # close any sections below the current level and
+	    # create a new section (special case for the firstsection)
+	    while (($curtoclevel > $toclevel) ||
+		   (!$firstsection && $curtoclevel == $toclevel)) {
+		$cursection = $doc_obj->get_parent_section ($cursection);
+		$curtoclevel--;
+	    }
+	    if ($curtoclevel+1 < $toclevel) {
+		print STDERR "WARNING - jump in toc levels in $htmlfile " . 
+		    "from $curtoclevel to $toclevel\n";
+	    }
+	    while ($curtoclevel < $toclevel) {
+		$curtoclevel++;
+		$cursection = 
+		    $doc_obj->insert_section($doc_obj->get_end_child($cursection));
+	    }
+
+	    # add the metadata to this section
+	    if (!$firstsection || !defined($metadata->{'Title'})) {
+		$doc_obj->add_metadata ($cursection, "Title", $title);
+	    }
+	    if ($firstsection) {
+		foreach $field (keys(%$metadata)) {
+		    # Subjects may be a colon separated list
+		    if ($field eq "Subject") {
+			my @subjects = split /:/, $metadata->{'Subject'};
+			foreach $subject (@subjects) {
+			    $doc_obj->add_metadata ($cursection, 'Subject', $subject); 
+			}
+		    } else {
+			$doc_obj->add_metadata ($cursection, $field, $metadata->{$field});
+		    }
+		}
+		$firstsection = 0;
+	    }
+
+	    # clean up the section html
+	    $sectiontext = $self->HB_clean_section($sectiontext);
+
+	    # associate any files
+#	    map { $doc_obj->associate_file("$base_dir$file/$1", $1) 
+#		      if /_linkOID_\(_thisOID_\/([^\)]+)\)/; 0; }
+#		 split (/(_linkOID_\(_thisOID_\/[^\)]+\))/, $sectiontext);
+
+	    map { $doc_obj->associate_file("$base_dir$file/$1", $1)
+		      if /_httpcollection_\/archives\/_thisOID_\/([^\"]+)\"/; 0; }
+	         split (/(_httpcollection_\/archives\/_thisOID_\/[^\"]+\")/, $sectiontext);
+
+	    # add the text for this section
+	    $doc_obj->add_text ($cursection, $sectiontext);
+	    
+	} else {
+	    print STDERR "WARNING - leftover text\n" , $self->shorten($html), 
+	    "\nin $htmlfile\n";
+	    last;
+	}
+    }
+
+    # add a OID
+    $doc_obj->set_OID ();
+
+    print STDERR "OID: ", $doc_obj->get_OID(), "\n";
+
+    # process the document
+    $processor->process($doc_obj);
+        
+    return 1; # processed the file
+}
+
+
+1;
Index: /tags/start/gsdl/perllib/plugins/RecPlug.pm
===================================================================
--- /tags/start/gsdl/perllib/plugins/RecPlug.pm	(revision 13666)
+++ /tags/start/gsdl/perllib/plugins/RecPlug.pm	(revision 13666)
@@ -0,0 +1,65 @@
+# plugin which recurses through directories processing
+# each file it finds
+
+package RecPlug;
+
+use BasPlug;
+use plugin;
+
+
+BEGIN {
+    @ISA = ('BasPlug');
+}
+
+sub new {
+    my ($class) = @_;
+    my $self = new BasPlug ();
+
+    return bless $self, $class;
+}
+
+# return 1 if this class might recurse using $pluginfo
+sub is_recursive {
+    my $self = shift (@_);
+
+    return 1;
+}
+
+# return 1 if processed, 0 if not processed
+# Note that $base_dir might be "" and that $file might 
+# include directories
+sub read {
+    my $self = shift (@_);
+    my ($pluginfo, $base_dir, $file, $metadata, $processor) = @_;
+
+
+    my (@dir, $subfile);
+
+    # see if this is a directory
+    if (-d "$base_dir$file") {
+
+	# read all the files in the directory
+	opendir (DIR, "$base_dir$file") ||
+	    die "ERROR - couldn't read directory $base_dir$file\n";
+	@dir = readdir (DIR);
+	closedir (DIR);
+
+	# process each file
+	foreach $subfile (@dir) {
+	    if ($subfile !~ /^\.\.?$/) {
+		# note: metadata is not carried on to the next level
+		my $tmp = "$file/$subfile";
+		$tmp =~ s/^[\\\/]+|[\\\/]+$//g; # remove extra slashes
+		&plugin::read ($pluginfo, $base_dir, $tmp, {}, $processor);
+	    }
+	}
+
+	return 1;
+    }
+
+    # wasn't a directory, someone else will have to process it
+    return 0;
+}
+
+
+1;
Index: /tags/start/gsdl/perllib/plugins/TOCPlug.pm
===================================================================
--- /tags/start/gsdl/perllib/plugins/TOCPlug.pm	(revision 13666)
+++ /tags/start/gsdl/perllib/plugins/TOCPlug.pm	(revision 13666)
@@ -0,0 +1,142 @@
+# This plugin processes all books in a table of contents file.
+# A toc.txt file contains two things: a subject classification and a
+# list of file names.
+
+package TOCPlug;
+
+use plugin;
+use BasPlug;
+use lang;
+use doc;
+
+sub BEGIN {
+    @ISA = ('BasPlug');
+}
+
+sub new {
+    my ($class) = @_;
+    $self = new BasPlug ();
+
+    return bless $self, $class;
+}
+
+# return 1 if this class might recurse using $pluginfo
+sub is_recursive {
+    my $self = shift (@_);
+    
+    return 1;
+}
+
+sub read_toc_subject {
+    my $self = shift (@_);
+    my ($pluginfo, $base_dir, $file, $metadata, $processor) = @_;
+
+    my ($infoline, $line, @line);
+
+    open (TOCFILE, "$base_dir$file") || 
+	die "TOCPlug::read_toc_subject couldn't open $tocfile\n";
+    $infoline = <TOCFILE>;     # first line is an info line
+    my $doc_obj = new doc($file, "classification");
+    $doc_obj->set_OID ("CLSU");
+
+    while (defined ($line = <TOCFILE>)) {
+	$line =~ s/^\#.*$//;   # remove comments
+	$line =~ s/\cM|\cJ//g; # remove end-of-line characters
+	@line = split(/\t/, $line);
+
+	# remove spaces at the start and end of each field
+	map { s/^\s+|\s+$//g; } @line;
+
+	# if this is a classification entry add it to the classification file
+	if ((scalar(@line) >= 2) && ($line[0] ne "") && ($line[1] ne "")) {
+	    my $classifier = $self->int_classification ($line[0]); # convert leading letter to int
+	    $doc_obj->create_named_section($classifier);
+	    $doc_obj->add_metadata($classifier, "Title", $line[1]);
+	}
+    }
+
+    close (TOCFILE);
+    
+    # process the classification file
+    $processor->process($doc_obj);
+}
+
+# converts leading letter of a classification into its ascii equivalent
+# i.e C.2.4 becomes 67.2.4
+sub int_classification {
+    my $self = shift (@_);
+    my ($classification) = @_;
+    my $c = ord($classification);
+    $classification =~ s/^./$c/;
+
+    return $classification;
+}
+
+sub read_toc_files {
+    my $self = shift (@_);
+    my ($pluginfo, $base_dir, $file, $metadata, $processor) = @_;
+
+    my ($infoline, $line);
+# the fields are in the following order (separated by tabs):
+# Classification, Classification title, Title, 
+# Language, Creator
+
+    open (TOCFILE, "$base_dir$file") || 
+	die "TOCPlug::read_toc_files couldn't open $tocfile\n";
+    $infoline = <TOCFILE>;     # first line is an info line
+
+    while (defined ($line = <TOCFILE>)) {
+	next if ($line =~ $line =~ /^\#.*$/) || ($line !~ /\w/);
+	$line =~ s/\cM|\cJ//g; # remove end-of-line characters
+	@line = split(/\t/, $line);
+
+	# remove spaces at the start and end of each field
+	map { s/^\s+|\s+$//g; } @line;
+
+	# if this is a file entry process it
+	if ((scalar(@line) >= 5) && ($line[1] eq "") && ($line[4] ne "")) {
+	    my $metadata = {'Subject' => $line[0],
+			    'Title'   => $line[2],
+			    'Language'=> &lang::english_to_iso639($line[3])};
+
+	    $metadata->{'Creator'} = $line[5] if defined $line[5]; 
+
+
+	    my $subimportfile = "$base_dir$line[4]";
+
+	    &plugin::read ($pluginfo, $base_dir, $line[4], $metadata, $processor);
+	}
+    }
+
+    close (TOCFILE);
+}
+
+
+# return 1 if processed, 0 if not processed
+# Note that $base_dir might be "" and that $file might 
+# include directories
+sub read {
+    my $self = shift (@_);
+    my ($pluginfo, $base_dir, $file, $metadata, $processor) = @_;
+
+    my $tocfile = "$file/toc.txt";
+    if (!(-f "$base_dir$tocfile")) {
+	# not a directory containing a toc file
+	return 0;
+    }
+
+    # found a toc.txt file
+
+    print STDERR "TOCPlug: processing $tocfile\n";
+
+    # create the subject classification document
+    $self->read_toc_subject ($pluginfo, $base_dir, $tocfile, {}, $processor);
+    
+    # process each file within this table of contents file
+    $self->read_toc_files ($pluginfo, $base_dir, $tocfile, {}, $processor);
+
+    return 1; # was processed
+}
+
+
+1;
Index: /tags/start/gsdl/perllib/util.pm
===================================================================
--- /tags/start/gsdl/perllib/util.pm	(revision 13666)
+++ /tags/start/gsdl/perllib/util.pm	(revision 13666)
@@ -0,0 +1,359 @@
+# various useful utilities
+
+package util;
+
+use File::Copy;
+
+
+# removes files (but not directories)
+sub rm {
+    my (@files) = @_;
+    my @filefiles = ();
+
+    # make sure the files we want to delete exist 
+    # and are regular files
+    foreach $file (@files) {
+	if (!-e $file) {
+	    print STDERR "util::rm $file does not exist\n";
+	} elsif (!-f $file) {
+	    print STDERR "util::rm $file is not a regular file\n";
+	} else {
+	    push (@filefiles, $file);
+	}
+    }
+    
+    # remove the files
+    my $numremoved = unlink @filefiles;
+
+    # check to make sure all of them were removed
+    if ($numremoved != scalar(@filefiles)) {
+	print STDERR "util::rm Not all files were removed\n";
+    }
+}
+
+
+# recursive removal
+sub rm_r {
+    my (@files) = @_;
+
+    # recursively remove the files
+    foreach $file (@files) {
+	$file =~ s/[\/\\]+$//; # remove trailing slashes
+	
+	if (!-e $file) {
+	    print STDERR "util::rm_r $file does not exist\n";
+
+	} elsif (-d $file) {
+	    # get the contents of this directory
+	    if (!opendir (INDIR, $file)) {
+		print STDERR "util::rm_r could not open directory $file\n";
+	    } else {
+		my @filedir = grep (!/^\.\.?$/, readdir (INDIR));
+		closedir (INDIR);
+
+		# remove all the files in this directory
+		&rm_r (map {$_="$file/$_";} @filedir);
+
+		# remove this directory
+		if (!rmdir $file) {
+		    print STDERR "util::rm_r couldn't remove directory $file\n";
+		}
+	    }
+
+	} else {
+	    # remove this file
+	    &rm ($file);
+	}
+    }
+}
+
+
+# copies a file or a group of files
+sub cp {
+    my $dest = pop (@_);
+    my (@srcfiles) = @_;
+
+    # remove trailing slashes from source and destination files
+    $dest =~ s/[\\\/]+$//;
+    map {$_ =~ s/[\\\/]+$//;} @srcfiles;
+
+    # a few sanity checks
+    if (scalar (@srcfiles) == 0) {
+	print STDERR "util::cp no destination directory given\n";
+	return;
+    } elsif ((scalar (@srcfiles) > 1) && (!-d $dest)) {
+	print STDERR "util::cp if multiple source files are given the ".
+	    "destination must be a directory\n";
+	return;
+    }
+
+    # copy the files
+    foreach $file (@srcfiles) {
+	my $tempdest = $dest;
+	if (-d $tempdest) {
+	    my ($filename) = $file =~ /([^\\\/]+)$/;
+	    $tempdest .= "/$filename";
+	}
+	if (!-e $file) {
+	    print STDERR "util::cp $file does not exist\n";
+	} elsif (!-f $file) {
+	    print STDERR "util::cp $file is not a plain file\n";
+	} else {
+	    &File::Copy::copy ($file, $tempdest);
+	}
+    }
+}
+
+
+# recursively copies a file or group of files
+# syntax: cp_r (sourcefiles, destination file or directory)
+sub cp_r {
+    my $dest = pop (@_);
+    my (@srcfiles) = @_;
+
+    # remove trailing slashes from source and destination files
+    $dest =~ s/[\\\/]+$//;
+    map {$_ =~ s/[\\\/]+$//;} @srcfiles;
+
+    # a few sanity checks
+    if (scalar (@srcfiles) == 0) {
+	print STDERR "util::cp no destination directory given\n";
+	return;
+    } elsif ((scalar (@srcfiles) > 1) && (!-d $dest)) {
+	print STDERR "util::cp if multiple source files are given the ".
+	    "destination must be a directory\n";
+	return;
+    }
+    
+    # copy the files
+    foreach $file (@srcfiles) {
+	# copy the file to within dest if dest is a directory
+	# exception: if there is only one source file and that
+	# source file is a directory
+	my $tempdest = $dest;
+	if (-d $tempdest && !(scalar(@srcfiles) == 1 && -d $file)) {
+	    my ($filename) = $file =~ /([^\\\/]+)$/;
+	    $tempdest .= "/$filename";
+	}
+
+	if (!-e $file) {
+	    print STDERR "util::cp $file does not exist\n";
+
+	} elsif (-d $file) {
+	    # make a new directory (if needed)
+	    mkdir ($tempdest, 0775) unless -e $tempdest;
+	    
+	    # get the contents of this directory
+	    if (!opendir (INDIR, $file)) {
+		print STDERR "util::cp_r could not open directory $file\n";
+	    } else {
+		my @filedir = grep (!/^\.\.?$/, readdir (INDIR));
+		closedir (INDIR);
+
+		# copy all the files in this directory
+		&cp_r (map {$_="$file/$_";} @filedir, $tempdest);
+	    }
+
+	} else {
+	    &cp($file, $tempdest);
+	}
+    }
+}
+
+
+sub mk_all_dir {
+    my ($dir) = @_;
+
+    # use / for the directory separator, remove duplicate and
+    # trailing slashes
+    $dir=~s/[\\\/]+/\//g; 
+    $dir=~s/[\\\/]+$//;
+
+    # make sure the cache directory exists
+    my $dirsofar = "";
+    my $first = 1;
+    foreach $dirname (split ("/", $dir)) {
+	$dirsofar .= "/" unless $first;
+	$first = 0;
+
+	$dirsofar .= $dirname;
+
+	next if $dirname =~ /^(|[a-z]:)$/i;
+	if (!-e $dirsofar && !mkdir ($dirsofar, 0775)) {
+	    print STDERR "util::mk_all_dir could not create directory $dirsofar\n";
+	    return;
+	}
+    }
+}
+
+
+# updates a copy of a directory in some other part of the filesystem
+# verbosity settings are: 0=low, 1=normal, 2=high
+# both $fromdir and $todir should be absolute paths
+sub cachedir {
+    my ($fromdir, $todir, $verbosity) = @_;
+    $verbosity = 1 unless defined $verbosity;
+
+    # use / for the directory separator, remove duplicate and
+    # trailing slashes
+    $fromdir=~s/[\\\/]+/\//g; 
+    $fromdir=~s/[\\\/]+$//;
+    $todir=~s/[\\\/]+/\//g; 
+    $todir=~s/[\\\/]+$//;
+
+    &mk_all_dir ($todir);
+
+    # get the directories in ascending order
+    if (!opendir (FROMDIR, $fromdir)) {
+	print STDERR "util::cachedir could not read directory $fromdir\n";
+	return;
+    }
+    my @fromdir = grep (!/^\.\.?$/, sort(readdir (FROMDIR)));
+    closedir (FROMDIR);
+
+    if (!opendir (TODIR, $todir)) {
+	print STDERR "util::cacedir could not read directory $todir\n";
+	return;
+    }
+    my @todir = grep (!/^\.\.?$/, sort(readdir (TODIR)));
+    closedir (TODIR);
+
+    my $fromi = 0;
+    my $toi = 0;
+		    
+    while ($fromi < scalar(@fromdir) || $toi < scalar(@todir)) {
+#	print "fromi: $fromi toi: $toi\n";
+
+	# see if we should delete a file/directory
+	# this should happen if the file/directory
+	# is not in the from list or if its a different
+	# size, or has an older timestamp
+	if ($toi < scalar(@todir)) {
+	    if (($fromi >= scalar(@fromdir)) ||
+		($todir[$toi] lt $fromdir[$fromi] || 
+		 ($todir[$toi] eq $fromdir[$fromi] && 
+		  &differentfiles("$fromdir/$fromdir[$fromi]","$todir/$todir[$toi]",
+				  $verbosity)))) {
+
+		# the files are different
+		&rm_r("$todir/$todir[$toi]");
+		splice(@todir, $toi, 1); # $toi stays the same
+
+	    } elsif ($todir[$toi] eq $fromdir[$fromi]) {
+		# the files are the same
+		# if it is a directory, check its contents
+		if (-d "$todir/$todir[$toi]") {
+		    &cachedir ("$fromdir/$fromdir[$fromi]",
+			       "$todir/$todir[$toi]", $verbosity);
+		}
+
+		$toi++;
+		$fromi++;
+		next;
+	    }
+	}
+  
+	# see if we should insert a file/directory
+	# we should insert a file/directory if there
+	# is no tofiles left or if the tofile does not exist
+	if ($fromi < scalar(@fromdir) && ($toi >= scalar(@todir) || 
+					  $todir[$toi] gt $fromdir[$fromi])) {
+	    &cp_r ("$fromdir/$fromdir[$fromi]", "$todir/$fromdir[$fromi]");
+	    splice (@todir, $toi, 0, $fromdir[$fromi]);
+
+	    $toi++;
+	    $fromi++;
+	}
+    }
+}
+
+# this function returns -1 if either file is not found
+# assumes that $file1 and $file2 are absolute file names or
+# in the current directory
+# $file2 is allowed to be newer than $file1
+sub differentfiles {
+    my ($file1, $file2, $verbosity) = @_;
+    $verbosity = 1 unless defined $verbosity;
+
+    $file1 =~ s/\/+$//;
+    $file2 =~ s/\/+$//;
+    
+    my ($file1name) = $file1 =~ /\/([^\/]*)$/;
+    my ($file2name) = $file2 =~ /\/([^\/]*)$/;
+
+    return -1 unless (-e $file1 && -e $file2);
+    if ($file1name ne $file2name) {
+	print STDERR "filenames are not the same\n" if ($verbosity >= 2);
+	return 1;
+    }
+
+    @file1stat = stat ($file1);
+    @file2stat = stat ($file2);
+
+    if (-d $file1) {
+	if (! -d $file2) {
+	    print STDERR "one file is a directory\n" if ($verbosity >= 2);
+	    return 1;
+	}
+	return 0;
+    }
+
+    # both must be regular files
+    unless (-f $file1 && -f $file2) {
+	print STDERR "one file is not a regular file\n" if ($verbosity >= 2);
+	return 1;
+    }
+
+    # the size of the files must be the same
+    if ($file1stat[7] != $file2stat[7]) {
+	print STDERR "different sized files\n" if ($verbosity >= 2);
+	return 1;
+    }
+
+    # the second file cannot be older than the first
+    if ($file1stat[9] > $file2stat[9]) {
+	print STDERR "file is older\n" if ($verbosity >= 2);
+	return 1;
+    }
+
+    return 0;
+}
+
+
+sub get_tmp_filename {
+    my $tmpdir = "$ENV{'GSDLHOME'}/tmp";
+    &mk_all_dir ($tmpdir) unless -e $tmpdir;
+
+    my $count = 1000;
+    my $rand = int(rand $count);
+    while (-e "$tmpdir/F$rand") {
+	$rand = int(rand $count);
+	$count++;
+    }
+
+    return "$tmpdir/F$rand";
+}
+
+
+sub filename_cat {
+    my (@filenames) = @_;
+    my $filename = join("/", @filenames);
+
+    # remove duplicate slashes and remove the last slash
+    $filename =~ s/[\\\/]+/\//g;
+    $filename =~ s/\/$//;
+
+    return $filename;
+}
+
+
+# if this is running on windows we want binaries to end in
+# .exe, otherwise they don't have to end in any extension
+sub get_os_exe {
+    return ".exe" if $ENV{'GSDLOS'} =~ /^windows$/i;
+    return "";
+}
+
+
+
+1;
Index: /tags/start/gsdl/src/hashfile/hashfile.cpp
===================================================================
--- /tags/start/gsdl/src/hashfile/hashfile.cpp	(revision 13666)
+++ /tags/start/gsdl/src/hashfile/hashfile.cpp	(revision 13666)
@@ -0,0 +1,192 @@
+#include <stdio.h>
+
+#define MAXNUMLEN  100   // bytes
+
+
+// The number class is used to store very long unsigned integers.
+// The least significant of each number is stored first. Numbers can 
+// be no longer than MAXNUMLEN bytes long. A number with length=0
+// is considered to be equal to 0. There should be no extra zeros
+// at the front of the number.
+
+struct number {
+  unsigned int len;
+  unsigned char num[MAXNUMLEN];
+
+  number () {len = 0;}
+};
+
+
+// evaluates a = a + b
+// a and b can be the same number
+void my_inc (number &a, number &b) {
+  unsigned int carry = 0;
+  unsigned int num = 0;
+  unsigned int i = 0;
+
+  while ((carry || (i < a.len) || (i < b.len)) && (i < MAXNUMLEN)) {
+    num = carry;
+    if (i < a.len) num += a.num[i];
+    if (i < b.len) num += b.num[i];
+
+    if (num >= 256) {
+      num -= 256; // assumes that each number in the list < 256
+      carry = 1;
+    } else {
+      carry = 0;
+    }
+    a.num[i] = (unsigned char)num;
+
+    i++;
+  }
+
+  a.len = i;
+}
+
+
+// evaluates a = a - b if a >= b
+// returns true if the subtraction was possible
+int my_ifpos_dec (number &a, number &b) {
+  int carry = 0;
+  int num = 0;
+  unsigned int i = 0;
+  unsigned int len = 0; // the last non-zero digit
+
+  // make sure a >= b
+  if (b.len > a.len) return 0;
+  if (b.len == a.len) {
+    i = a.len - 1;
+    while (i >= 0) {
+      if (a.num[i] > b.num[i]) break;
+      if (a.num[i] < b.num[i]) return 0;
+      i--;
+    }
+  }
+
+  i = 0;
+  len = 0;
+  while ((i < a.len) || (i < b.len)) {
+    num = -carry;
+    if (i < a.len) num += a.num[i];
+    if (i < b.len) num -= b.num[i];
+
+    if (num < 0) {
+      num += 256; // assumes each number in the list < 256
+      carry = 1;
+    } else {
+      carry = 0;
+    }
+
+    a.num[i] = (unsigned char) num;
+    
+    i++;
+    if (num != 0) len = i;
+  }
+
+  a.len = len;
+
+  if (carry) {
+    // panic, this should NOT happen
+    fprintf (stderr, "panic: error in my_ifpos_dec\n");
+  }
+
+  return 1;
+}
+
+
+char *my_convert_num (number &a) {
+  char *result = new char[a.len+2];
+  int i,len;
+  char convert[16] = {'0','1','2','3','4','5','6','7',
+		      '8','9','a','b','c','d','e','f'};
+
+  // zero might be a special case
+  if (a.len == 0) {
+    result[0] = '0';
+    result[1] = '\0';
+    return result;
+  }
+
+  for (i=a.len-1, len=0; i >= 0; i--) {
+    result[len++] = convert[a.num[i]/16];
+    result[len++] = convert[a.num[i]%16];
+  }
+  result[len] = '\0';
+
+  return result;
+}
+
+
+char *hashfile (char *filename) {
+  FILE *infile = NULL;
+  int i;
+
+  // calculate the 8 multiples of the prime number to use
+  // in the long division
+  number primepow[8];
+  number pow;
+  number remainder;
+  unsigned char c;
+
+  // our prime number (618970019642690137449562111)
+  pow.num[0] = 255;  pow.num[1] = 255;
+  pow.num[2] = 255;  pow.num[3] = 255;
+  pow.num[4] = 255;  pow.num[5] = 255;
+  pow.num[6] = 255;  pow.num[7] = 255;
+  pow.num[8] = 255;  pow.num[9] = 255;
+  pow.num[10] = 255; pow.num[11] = 1;
+  pow.len = 12;
+
+  for (i=0; i<8; i++) {
+    primepow[i] = pow;
+    my_inc (pow, pow);
+  }
+
+  infile = fopen (filename, "rb");
+  if (infile == NULL) {
+    return NULL;
+  }
+  
+  remainder.len = 0;
+  c = (unsigned char)fgetc(infile);
+  while (!feof (infile)) {
+    // remainder = remainder * 256 + c
+    if (remainder.len == MAXNUMLEN-1) {
+      fprintf (stderr, "ERROR - number overflow\n");
+      return NULL;
+    }
+    for (i=remainder.len; i>0; i--) {
+      remainder.num[i] = remainder.num[i-1];
+    }
+    remainder.num[0] = c;
+    remainder.len = remainder.len+1;
+    
+    for (i=7; i>=0; i--) {
+      my_ifpos_dec (remainder, primepow[i]);
+    }
+
+    c = (unsigned char)fgetc(infile);
+  }
+
+  fclose (infile);
+
+  return my_convert_num (remainder);
+}
+
+
+int main (int argc, char *argv[]) {
+  int i;
+  char *result;
+
+  for (i = 1; i < argc; i++) {
+    result = hashfile (argv[i]);
+    if (result == NULL) {
+      printf ("ERROR - could not process %s\n", argv[i]);
+    } else {
+      printf ("%s: %s\n", argv[i], result);
+      delete [] result;
+    }
+  }
+
+  return 0;
+}
Index: /tags/start/gsdl/src/library/browse.cpp
===================================================================
--- /tags/start/gsdl/src/library/browse.cpp	(revision 13666)
+++ /tags/start/gsdl/src/library/browse.cpp	(revision 13666)
@@ -0,0 +1,1 @@
+#include "browse.h"
Index: /tags/start/gsdl/src/library/browse.h
===================================================================
--- /tags/start/gsdl/src/library/browse.h	(revision 13666)
+++ /tags/start/gsdl/src/library/browse.h	(revision 13666)
@@ -0,0 +1,41 @@
+#ifndef BROWSE_H
+#define BROWSE_H
+
+#include "text_t.h"
+#include "gdbmclass.h"
+#include "cgiargs.h"
+
+class browseclass 
+{
+  
+public:
+
+  browseclass () {}
+  virtual ~browseclass () {}
+
+  virtual void get_browse_bar(const text_t &targetdoc, text_t &return_text) {}
+
+  virtual void get_top_locator(cgiargsclass &args, gdbmclass &gdbm, int oversize, text_t &return_text) {}
+  virtual void get_links(cgiargsclass &args, gdbmclass &gdbm, text_t &return_text) {}
+  virtual void get_contents_arr(cgiargsclass &args, gdbmclass &gdbm, vector<text_t> &contents_arr) {}
+
+protected:
+
+  virtual void get_expanded_toc(cgiargsclass &args, text_t &booksection, 
+				const text_t &classification, gdbmclass &gdbm, 
+				text_t &return_text) {}
+  virtual void get_standard_toc(cgiargsclass &args, text_t &booksection, 
+				const text_t &classification, gdbmclass &gdbm, 
+				text_t &return_text) {}
+  virtual void get_alphabet_links (const text_t &booksection, gdbmclass &gdbm, 
+				   const text_t &collection, text_t &return_text) {}
+  virtual void get_title_arrows(text_t classification, gdbmclass &gdbm, 
+				const text_t &collection, text_t &alphabet_arrows) {}
+  virtual void get_contents (text_t expandlevel, gdbmclass &gdbm, 
+			     const text_t &collection, vector<text_t> &contents, 
+			     int &totalcols) {}
+
+};
+
+
+#endif
Index: /tags/start/gsdl/src/library/cgiargs.cpp
===================================================================
--- /tags/start/gsdl/src/library/cgiargs.cpp	(revision 13666)
+++ /tags/start/gsdl/src/library/cgiargs.cpp	(revision 13666)
@@ -0,0 +1,83 @@
+#include "cgiargs.h"
+
+
+  
+// constructors
+cgiargsclass::cgiargsclass ()
+{
+}
+
+
+// this returns NULL if there isn't an entry with a value of
+// 'key' already defined
+
+void cgiargsclass::setarg (const text_t &key, const text_t &value)
+{
+  args[key] = value;
+}
+
+void cgiargsclass::setdefaultarg (const text_t &key, const text_t &value)
+{
+  if (getarg(key) == NULL) setarg (key, value);
+}
+
+void cgiargsclass::setintarg (const text_t &key, int value)
+{
+  setarg (key, value);
+}
+
+void cgiargsclass::setdefaultintarg (const text_t &key, int value)
+{
+  if (getarg(key) == NULL) setintarg (key, value);
+}
+
+void cgiargsclass::setcarg (const text_t &key, unsigned short c)
+{
+  text_t t; 
+  t.push_back(c);
+  setarg(key,t);
+}
+
+void cgiargsclass::setdefaultcarg (const text_t &key, unsigned short c)
+{
+  if (getarg(key) == NULL) setcarg (key, c);
+}
+
+text_t *cgiargsclass::getarg (const text_t &key)
+{
+  iterator here = args.find (key);
+  if (here == args.end()) return NULL;
+
+  return &((*here).second);
+}
+
+int cgiargsclass::getintarg (const text_t &key)
+{
+  text_t *text = getarg (key);
+  if (text == NULL) return 0;
+  return text->getint();
+}
+
+
+
+// stream operators to print cgi arguments for debugging purposes
+ostream &operator<<(ostream &outs, const cgiargsclass &args)
+{
+  outconvertclass text_t2ascii;
+  cgiargsclass::const_iterator here = args.begin ();
+  cgiargsclass::const_iterator end = args.end ();
+
+  outs << "*** cgiargsclass\n";
+  
+  while (here != end)
+    {
+      outs << text_t2ascii << " \"" << (*here).first << "\"=\"" << 
+	(*here).second << "\"\n";
+      here++;
+    }
+  outs << "\n";
+
+  return outs;
+}
+
+
Index: /tags/start/gsdl/src/library/cgiargs.h
===================================================================
--- /tags/start/gsdl/src/library/cgiargs.h	(revision 13666)
+++ /tags/start/gsdl/src/library/cgiargs.h	(revision 13666)
@@ -0,0 +1,85 @@
+#ifndef CGIARGS_H
+#define CGIARGS_H
+
+
+#ifdef __GNUG__
+#  include <ostream.h>
+#else
+#  ifndef USE_OBJECTSPACE
+#    include <ostream>
+#  else
+#    include <ospace\std\ostream>
+#  endif
+#endif
+
+#ifndef USE_OBJECTSPACE
+#  include <map>
+#else
+#  include <ospace\std\map>
+#endif
+
+
+#include "text_t.h"
+
+typedef map<text_t, text_t, lttext_t> textmap;
+
+
+class cgiargsclass
+{
+protected:
+  textmap args;
+
+public:
+  //type support for textmap
+  typedef textmap::iterator iterator;
+  typedef textmap::const_iterator const_iterator;
+  typedef textmap::reference reference;
+  typedef textmap::const_reference const_reference;
+  typedef textmap::size_type size_type;
+  typedef textmap::difference_type difference_type;
+  typedef textmap::const_reverse_iterator const_reverse_iterator;
+  typedef textmap::reverse_iterator reverse_iterator;
+  
+  // constructors
+  cgiargsclass ();
+
+  // basic container support
+  iterator begin () {return args.begin();}
+  const_iterator begin () const {return args.begin();}
+  iterator end () {return args.end();}
+  const_iterator end () const {return args.end();}
+
+  void erase(iterator pos) {args.erase(pos);}
+  void erase(iterator first, iterator last) {args.erase(first, last);}
+  cgiargsclass &operator=(const cgiargsclass &x) {args=x.args;return *this;}
+
+  bool empty () const {return args.empty();}
+  size_type size() const {return args.size();}
+
+
+  // added functionality
+  void clear () {args.erase(args.begin(),args.end());}
+
+  // setdefaultarg, setdefaultintarg, and setdefaultcarg will 
+  // only set the argument if it is not already set
+  // getargs NULLs if there isn't an entry with
+  // 'key' already defined, getintarg returns 0 if there wasn't an
+  // entry with 'key' defined and operator[] returns "" if
+  // 'key' wasn't already defined (and sets 'key'="").
+  void setarg (const text_t &key, const text_t &value);
+  void setdefaultarg (const text_t &key, const text_t &value); 
+  void setintarg (const text_t &key, int value);
+  void setdefaultintarg (const text_t &key, int value);
+  void setcarg (const text_t &key, unsigned short c);
+  void setdefaultcarg (const text_t &key, unsigned short c);
+  text_t *getarg (const text_t &key);
+  int getintarg (const text_t &key);
+  text_t &operator[] (const text_t &key) {return args[key];}
+};
+
+
+// stream operators to print cgi arguments for debugging purposes
+ostream &operator<<(ostream &outs, const cgiargsclass &args);
+
+
+#endif
Index: /tags/start/gsdl/src/library/conftools.cpp
===================================================================
--- /tags/start/gsdl/src/library/conftools.cpp	(revision 13666)
+++ /tags/start/gsdl/src/library/conftools.cpp	(revision 13666)
@@ -0,0 +1,43 @@
+#ifdef __GNUG__
+#  include <iostream.h>
+#  include <fstream.h>
+#else
+#  ifndef USE_OBJECTSPACE
+#    include <iostream>
+#    include <fstream>
+#  else
+#    include <ospace\std\iostream>
+#    include <ospace\std\fstream>
+#  endif
+#endif
+
+#include "text_t.h"
+#include "conftools.h"
+
+int write_confline (ofstream &fileout, const text_t &key, const text_t value) {
+  if (key.empty() || value.empty()) return -1;
+  outconvertclass text_t2ascii;
+  fileout << text_t2ascii << key << "=" << value << "\n";
+  return 0;
+}
+
+int get_confline (ifstream &filein, text_t &key, text_t &value) {
+  if (filein.eof()) return -1;
+
+  key.clear();
+  value.clear();
+  char c;
+  filein.get(c);
+
+  int foundeq = 0;
+  while (!filein.eof() && c != '\n') {
+    if (!foundeq && c == '=') {foundeq = 1; filein.get(c);}
+
+    if (foundeq) value.push_back(c);
+    else key.push_back(c);
+    filein.get(c);
+  }
+  if (key.empty()) return -1;
+  return 0;
+} 
+
Index: /tags/start/gsdl/src/library/conftools.h
===================================================================
--- /tags/start/gsdl/src/library/conftools.h	(revision 13666)
+++ /tags/start/gsdl/src/library/conftools.h	(revision 13666)
@@ -0,0 +1,11 @@
+#ifndef CONFTOOLS_H
+#define CONFTOOLS_H
+
+#ifdef __WIN32__
+#include <ospace/std/fstream>
+#endif
+
+int write_confline (ofstream &fileout, const text_t &key, const text_t value);
+int get_confline (ifstream &filein, text_t &key, text_t &value);
+
+#endif
Index: /tags/start/gsdl/src/library/display.cpp
===================================================================
--- /tags/start/gsdl/src/library/display.cpp	(revision 13666)
+++ /tags/start/gsdl/src/library/display.cpp	(revision 13666)
@@ -0,0 +1,1527 @@
+/**************************************************************************
+ *
+ * display.cpp -- Context sensitive macro language
+ * Copyright (c) 1998 -- Rodger McNab and Hong Chen
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+/*fopen
+   $Log$
+   Revision 1.1  1998/11/17 01:11:03  sjboddie
+   Initial revision
+
+   Revision 1.8  1998/06/24 01:49:28  rjmcnab
+   Added stuff for the objectspace libraries
+
+   Revision 1.7  1998/06/22 01:05:49  rjmcnab
+   Added a warning when a macro is not found
+
+   Revision 1.6  1998/06/18 23:58:03  rjmcnab
+   changed 'display' to 'displayclass'
+   added support to stream text through display with <<
+
+   Revision 1.5  1998/06/18 00:14:21  rjmcnab
+   fixed a bug in "macro" and added a comment about what
+   the use of macro names
+
+   Revision 1.4  1998/06/17 10:30:00  rjmcnab
+   added a simple _If_ statement
+
+   Revision 1.3  1998/06/17 08:51:08  rjmcnab
+   Added the expansion of macro options, some checking
+   for recursive macro calls, and changed 'set' to
+   'setmacro' in a few places as the MVC++ version 4.2
+   was getting 'set' confused with the STL 'set'
+
+   Revision 1.2  1998/06/15 22:00:29  rjmcnab
+   a lot of restructuring and simplifying
+
+   Revision 1.1  1998/06/13 20:06:05  rjmcnab
+   Initial revision
+
+*/
+
+static char *RCSID = "$Id$";
+
+
+#include "display.h"
+#include <assert.h>
+
+// include to get NULL
+#include <stdlib.h>
+
+#ifdef __GNUG__
+#  include <iostream.h>
+#  include <fstream.h>
+#else
+#  ifndef USE_OBJECTSPACE
+#    include <iostream>
+#    include <fstream>
+#  else
+#    include <ospace\std\iostream>
+#    include <ospace\std\fstream>
+#  endif
+#endif
+
+
+
+
+/////////////////////////////////////
+// misc classes
+/////////////////////////////////////
+
+
+// precedencetype defines a 'precedence value' for each parameter
+typedef map<text_t, double, lttext_t> precedencetype;
+
+
+// macro value structure
+struct mvalue
+{
+  text_t filename;
+  text_t value;
+};
+
+
+
+/////////////////////////////////////
+// stuff for defaultmacros_t
+/////////////////////////////////////
+  
+typedef map<text_t, mvalue, lttext_t> defparammap;
+typedef map<text_t, defparammap, lttext_t> defmacromap;
+typedef map<text_t, defmacromap, lttext_t> defpackagemap;
+
+// all methods in defaultmacros_t assume the parameters
+// and packages in a standard form and not empty
+class defaultmacros_t
+{
+protected:
+  defpackagemap macros;
+
+public:
+  typedef defpackagemap::const_iterator const_package_iterator;
+  typedef defpackagemap::size_type package_size_type;
+
+  // setmacro returns 0 if there was no error,
+  //            -1 if it redefined a macro
+  //            -2 if it hid a Global macro
+  //            -3 if it redefined a macro and hid a Global macro
+  //            -4 if either a package, macroname, or params were not supplied
+  int setmacro(const text_t &package,
+	  const text_t &macroname, 
+	  const text_t &params, 
+	  const text_t &filename, 
+	  const text_t &macrovalue);
+
+  void delmacro(const text_t &package,
+	      const text_t &macroname, 
+	      const text_t &params);
+
+  void clear () {macros.erase(macros.begin(), macros.end());}
+
+  // top level stuff
+  const_package_iterator package_begin () const {return macros.begin();}
+  const_package_iterator package_end () const {return macros.end();}
+  bool package_empty () const {return macros.empty();}
+  package_size_type package_size() const {return macros.size();}
+
+  // methods to find things
+  defmacromap *package_find (const text_t &packagename);
+  defparammap *macro_find (const text_t &packagename, 
+			   const text_t &macroname);
+  mvalue *parameter_find (const text_t &packagename, 
+			  const text_t &macroname,
+			  const text_t &parametername);
+};
+
+
+// setmacro returns 0 if there was no error,
+//            -1 if it redefined a macro
+//            -2 if it hid a Global macro
+//            -3 if it redefined a macro and hid a Global macro
+//            -4 if either a package, macroname, or params were not supplied
+int defaultmacros_t::setmacro(const text_t &package,
+			 const text_t &macroname, 
+			 const text_t &params, 
+			 const text_t &filename, 
+			 const text_t &macrovalue)
+{
+  text_t constGlobal("Global");
+  paramhashtype paramhash;
+
+  defmacromap *macromapptr;
+  defparammap *parammapptr;
+  mvalue *mvalueptr;
+
+  int warning = 0;
+
+  // check to see if we would be hiding a Global macro with the 
+  // same name. Note: it doesn't matter what parameters are used
+  // a Global macro will still be hid by a non-Global one with
+  // the same name.
+  if ((package != constGlobal) && 
+      (macro_find (constGlobal, macroname) != NULL))
+    {
+      warning -= 2; // found the macroname
+    }
+
+  // define this macro
+  macromapptr = &(macros[package]); // -- package
+  parammapptr = &((*macromapptr)[macroname]); // -- macro name
+  // -- parameters
+  if ((*parammapptr).find(params) != (*parammapptr).end()) {
+    warning -= 1; // found the parameters
+  }
+  mvalueptr = &((*parammapptr)[params]);
+
+  // -- value
+  (*mvalueptr).filename = filename;
+  (*mvalueptr).value = macrovalue;
+
+  return warning;
+}
+
+void defaultmacros_t::delmacro(const text_t &package,
+			     const text_t &macroname, 
+			     const text_t &params)
+{
+  // make sure everything was supplied
+  if (package.empty() || macroname.empty() || params.empty()) return;
+
+  // find the package and macroname
+  defparammap *parammapptr = macro_find(package, macroname);
+  if (parammapptr == NULL) return;
+
+  // find the parameters
+  defparammap::iterator parammapit = parammapptr->find(params);
+  if (parammapit == parammapptr->end()) return;
+
+  // finally delete this element
+  parammapptr->erase(parammapit);
+}
+
+defmacromap *defaultmacros_t::package_find (const text_t &packagename)
+{
+  if (packagename.empty()) return NULL;
+
+  defpackagemap::iterator it = macros.find(packagename);
+  if (it == macros.end()) return NULL;
+
+  return &((*it).second);
+}
+
+defparammap *defaultmacros_t::macro_find (const text_t &packagename, 
+					       const text_t &macroname)
+{
+  defmacromap *macromapptr = package_find(packagename);
+  if (macromapptr == NULL || macroname.empty()) return NULL;
+
+  defmacromap::iterator it = (*macromapptr).find(macroname);
+  if (it == (*macromapptr).end()) return NULL;
+
+  return &((*it).second);
+}
+
+mvalue *defaultmacros_t::parameter_find (const text_t &packagename, 
+					 const text_t &macroname,
+					 const text_t &parametername)
+{
+  defparammap *parammapptr = macro_find(packagename, macroname);
+  if (parammapptr == NULL || parametername.empty()) return NULL;
+
+  defparammap::iterator it = (*parammapptr).find(parametername);
+  if (it == (*parammapptr).end()) return NULL;
+
+  return &((*it).second);
+}
+
+
+
+/////////////////////////////////////
+// stuff for currentmacros_t
+/////////////////////////////////////
+
+typedef map<text_t, mvalue, lttext_t> curmacromap;
+typedef map<text_t, curmacromap, lttext_t> curpackagemap;
+
+// all methods in currentmacros_t assume the parameters
+// and packages in a standard form and not empty
+class currentmacros_t 
+{
+protected:
+  curpackagemap macros;
+
+public:
+  typedef curpackagemap::const_iterator const_package_iterator;
+  typedef curpackagemap::size_type package_size_type;
+
+  // setmacro returns 0 if there was no error,
+  //            -1 if it redefined a macro
+  //            -4 if either a package, or macroname were not supplied
+  int setmacro(const text_t &package,
+	  const text_t &macroname, 
+	  const text_t &filename, 
+	  const text_t &macrovalue);
+
+  void delmacro(const text_t &package,
+		const text_t &macroname);
+
+  void clear () {macros.erase(macros.begin(), macros.end());}
+
+  // top level stuff
+  const_package_iterator package_begin () const {return macros.begin();}
+  const_package_iterator package_end () const {return macros.end();}
+  bool package_empty () const {return macros.empty();}
+  package_size_type package_size() const {return macros.size();}
+
+  // methods to find things
+  curmacromap *package_find (const text_t &packagename);
+  mvalue *macro_find (const text_t &packagename, 
+		      const text_t &macroname);
+};
+
+
+// setmacro returns 0 if there was no error,
+//            -1 if it redefined a macro
+//            -4 if either a package, or macroname were not supplied
+int currentmacros_t::setmacro(const text_t &package,
+			 const text_t &macroname, 
+			 const text_t &filename, 
+			 const text_t &macrovalue)
+{
+  int warning = 0;
+
+  // make sure everything was supplied
+  if (package.empty() || macroname.empty()) return -4;
+
+  // define this macro
+  curmacromap *macromapptr = &(macros[package]);
+  if ((*macromapptr).find(macroname) != (*macromapptr).end()) 
+    {
+      warning -= 1; // found the macroname
+    }
+  mvalue *mvalueptr = &((*macromapptr)[macroname]);
+
+  // -- value
+  (*mvalueptr).filename = filename;
+  (*mvalueptr).value = macrovalue;
+
+  return warning;
+}
+
+void currentmacros_t::delmacro(const text_t &package,
+			     const text_t &macroname)
+{
+  // make sure everything was supplied
+  if (package.empty() || macroname.empty()) return;
+
+  // find the package
+  curmacromap *macromapptr = package_find(package);
+  if (macromapptr == NULL) return;
+
+  // find the macroname
+  curmacromap::iterator macromapit = macromapptr->find(macroname);
+  if (macromapit == macromapptr->end()) return;
+
+  // finally delete this element
+  macromapptr->erase(macromapit);
+}
+
+curmacromap *currentmacros_t::package_find (const text_t &packagename)
+{
+  if (packagename.empty()) return NULL;
+
+  curpackagemap::iterator it = macros.find(packagename);
+  if (it == macros.end()) return NULL;
+
+  return &((*it).second);
+}
+
+mvalue *currentmacros_t::macro_find (const text_t &packagename, 
+				     const text_t &macroname)
+{
+  curmacromap *macromapptr = package_find(packagename);
+  if (macromapptr == NULL || macroname.empty()) return NULL;
+
+  curmacromap::iterator it = (*macromapptr).find(macroname);
+  if (it == (*macromapptr).end()) return NULL;
+
+  return &((*it).second);
+}
+
+
+
+
+/////////////////////////////////////
+// support functions
+/////////////////////////////////////
+
+// this calculation of precedence will make one occurance of a high
+// precedence item override many occurances of lower precedence items
+void calcprecedence (const text_t &precedstr, precedencetype &precedhash) 
+{
+  text_t param;
+  double multiple = 5.0;
+  double nextprec = multiple;
+
+  text_t::const_iterator here, end;
+
+  // set precedhash to an empty hash
+  precedhash.erase(precedhash.begin(), precedhash.end());
+
+  // iterate through paramstring ignoring space and extracting
+  // out key value pairs.
+  here = precedstr.begin();
+  end = precedstr.end();
+  while (here != end) 
+    {
+      // get the next parameter
+      param.clear(); // set param to an empty string
+      
+      while (here != end) 
+	{
+	  if (*here == ',') 
+	    {
+	      // found the end of the parameter
+	      here++;
+	      break;
+	    } 
+	  else if (*here == ' ') 
+	    {
+	      // do nothing (ignore spaces)
+	    } 
+	  else 
+	    {
+	      // character in parameter
+	      param.push_back (*here); // copy this character
+	    }
+	  
+	  here++;
+	}
+
+      // if a parameter was found insert its value
+      if (!param.empty()) 
+	{
+	  precedhash[param] = nextprec;
+	  nextprec *= multiple;
+	}
+    }
+}
+
+
+// decides how specific any given parameter is to the page parameters. Returns 
+// negative if any options are different or else the sum of the precedence for
+// the options which match. 
+double getspecificness(const paramhashtype &pageparams, 
+		       const paramhashtype &theseparams, 
+		       const precedencetype &precedhash) 
+{
+  double specificness = 0.0;
+  paramhashtype::const_iterator here, pagevalueit;
+  precedencetype::const_iterator precedit;
+  text_t thesekey, thesevalue, constignore("ignore");
+  
+  here = theseparams.begin();
+  while (here != theseparams.end()) 
+    {
+      thesekey = (*here).first;
+      thesevalue = (*here).second;
+      
+      if (thesekey == constignore) 
+	{
+	  // do nothing, this is a placeholder
+	} 
+      else 
+	{
+	  pagevalueit = pageparams.find(thesekey);
+	  if ((pagevalueit != pageparams.end()) && 
+	      ((*pagevalueit).second == thesevalue)) 
+	    {
+	      // this parameter fits, add its precedence value
+	      precedit = precedhash.find(thesekey);
+	      if (precedit == precedhash.end()) 
+		specificness += 1.0; // no precedence defined
+	      else 
+		  specificness += (*precedit).second;
+	    }
+	  else 
+	    {
+	      return -1.0; // did not match
+	    }
+	}
+
+      here++;
+    }
+  
+  return specificness;
+}
+
+
+void splitparams (const text_t &paramstring, paramhashtype &paramhash)
+{
+  text_t key;
+  text_t value;
+
+  text_t::const_iterator here, end;
+
+  // set paramhash to an empty hash
+  paramhash.erase(paramhash.begin(), paramhash.end());
+
+  // iterate through paramstring ignoring space and extracting
+  // out key value pairs.
+  here = paramstring.begin();
+  end  = paramstring.end();
+  while (here != end) 
+    {
+      // reset key and value
+      key.clear();
+      value.clear();
+
+      // get key
+      while (here != end) 
+	{
+	  if (*here == ',') 
+	    {
+	      // have a key with no value
+	      break;
+	    } 
+	  else if (*here == '=') 
+	    {
+	      // found the end of the key
+	      here ++; 
+	      break;
+	    } 
+	  else if (*here == ' ') 
+	    {
+	      // do nothing (ignore spaces)
+	    } 
+	  else 
+	    {
+	      // character in key
+	      key.push_back (*here); // copy this character
+	    }
+	  here ++;
+	}
+
+      // get value
+      while (here != end) 
+	{
+	  if (*here == '=') 
+	    {
+	      // multiple values for one key, ignore previous
+	      // values
+	      value.clear();
+	    } 
+	  else if (*here == ',') 
+	    {
+	      // found the end of the value
+	      here ++;
+	      break;
+	    } 
+	  else if (*here == ' ') 
+	    {
+	      // do nothing (ignore spaces)
+	    } 
+	  else 
+	    {
+	      // character in value
+	      value.push_back (*here); // copy this character
+	    }
+	  here ++;
+	}
+    
+      // if a key was found insert the key/value pair in 
+      // the map 
+      if (!key.empty()) 
+	{
+	  paramhash[key] = value;
+	}
+    }
+}
+
+
+void joinparams (const paramhashtype &paramhash, text_t &paramstring)
+{
+  //set paramstring to an empty string
+  paramstring.clear();
+
+  //iterate through the paramhash
+  paramhashtype::const_iterator thepair;
+  int firstparam = 1;
+
+  for (thepair=paramhash.begin();thepair!=paramhash.end(); thepair++)
+    {
+      if (!firstparam) paramstring.push_back(',');
+      firstparam = 0;
+      
+      // insert pairs of "key=value"
+      text_t thevalue;
+      paramstring.append((*thepair).first);
+      paramstring.push_back('=');
+      paramstring.append((*thepair).second);
+    }
+}
+
+
+
+/////////////////////////////////////
+// parsing support functions
+/////////////////////////////////////
+
+inline int my_isspace (char ch) 
+{
+  unsigned char c = ch;
+  return (((c > 0) && (c <= 31)) || (c == ' '));
+}
+
+
+inline int my_isalpha (char c) 
+{
+  return ((c >= 'A' && c <= 'Z') ||
+	  (c >= 'a' && c <= 'z'));
+} 
+
+
+// as we are using one character lookahead the
+// value of line might be off by one.
+inline char my_get (istream &fin, int &line) 
+{
+  char c;
+  fin.get(c);
+  if (c == '\n') line++;
+  return c;
+}
+
+
+inline unsigned short my_ttnextchar (text_t::const_iterator &here, 
+				     text_t::const_iterator &end) 
+{
+  if (here != end) 
+    {
+      here++;
+      if (here != end) return (*here);
+    }
+  return '\0';
+}
+
+
+
+/////////////////////////////////////
+// methods for display
+/////////////////////////////////////
+
+// public methods for display
+
+displayclass::displayclass ()
+{
+  defaultmacros = new defaultmacros_t;
+  defaultfiles = new fileinfomap;
+  
+  orderparamlist = new paramspeclist;
+  currentmacros = new currentmacros_t;
+
+  outc = NULL;
+}
+
+
+displayclass::~displayclass ()
+{
+  delete defaultmacros;
+  delete defaultfiles;
+  
+  delete orderparamlist;
+  delete currentmacros;
+}
+  
+// setdefaultmacro adds an entry to the list of default macros 
+// returns 0 if there was no error,
+//        -1 if it redefined a macro
+//        -2 if it hid a Global macro
+//        -3 if it redefined a macro and hid a Global macro
+//        -4 if no macroname was supplied
+int displayclass::setdefaultmacro (text_t package, const text_t &macroname, 
+			      text_t params, const text_t &macrovalue) 
+{
+  return setdefaultmacro (macroname, package, params, macrovalue, "memory");
+}
+
+
+
+// loads a default macro file (if it isn't already loaded)
+// returns 0 if didn't need to load the file (it was already loaded)
+//         1 if was (re)loaded
+//        -1 an error occurred while trying to load the file
+int displayclass::loaddefaultmacros (text_t thisfilename)
+{
+  // convert the filename to a C string
+  char *filenamestr = thisfilename.getcstr();
+  outconvertclass text_t2ascii;
+
+  // see if we need to open this file -- this isn't implemented yet
+  
+  // open the file
+  ifstream fin(filenamestr);
+  if (fin.fail()) return -1; // read failed
+
+  text_t package = "Global";
+  int line  = 1;
+  char c = my_get(fin, line); // pre-fetch the next character
+
+  text_t macropackage, macroname, macroparameters, macrovalue;
+  int err; // for keeping track of whether an error occurred somewhere
+
+  while (!fin.eof()) 
+    {
+      // expect: white space, comment, "package", or macroname
+      if (my_isspace(c)) 
+	{
+	  // found some white-space
+	  c = my_get(fin, line);
+	}
+      else if (c == '#') 
+	{
+	  // found the start of a comment
+	  // skip all characters up to the end of the line
+	  c = my_get(fin, line); // skip the '#'
+	  while (!fin.eof ()) 
+	    {
+	      if (c == '\n') break;
+	      c = my_get(fin, line);
+	    }
+
+	} 
+      else if (c == 'p') 
+	{
+	  // found the start of 'package' (hopefully)
+	  // get everything up to the next space
+	  text_t tmp;
+	  while (!fin.eof() && my_isalpha(c)) 
+	    {
+	      tmp.push_back((unsigned char)c);
+	      c = my_get(fin, line);
+	    }
+	  // see if we have a package name
+	  if (tmp == "package") 
+	    {
+	      // skip all white space
+	      while (!fin.eof() && my_isspace(c)) 
+		c = my_get(fin, line);
+
+	      // get the package name
+	      tmp.clear(); // init tmp
+	      while (!fin.eof() && my_isalpha(c)) 
+		{
+		  tmp.push_back((unsigned char)c);
+		  c = my_get(fin, line);
+		}
+	      package = tmp;
+	      if (package.empty()) package = "Global";
+
+	    } 
+	  else 
+	    {
+	      // error
+	      cerr << "Expected 'package' on line " << line << "\n";
+	    }
+
+	} 
+      else if (c == '_') 
+	{
+	  // found the start of a macro (hopefully)
+	  c = my_get(fin, line); // skip the _
+
+	  // init variables
+	  err = 0;
+	  macropackage = package;
+	  macroname.clear(); // init macroname
+	  macroparameters.clear(); // init macroname
+	  macrovalue.clear(); // init macroname
+
+	  // get the macro name
+	  while ((!fin.eof()) && (!my_isspace(c)) && 
+		 (c != '\\') && (c != '_') &&(c != ':') && 
+		 (macroname.size() < 80)) 
+	    {
+	      macroname.push_back((unsigned char)c);
+	      c = my_get(fin, line);
+	    }
+	  
+	  if (c == ':') 
+	    {
+	      // we actually had the macro package
+	      c = my_get(fin, line); // skip :
+	      macropackage = macroname;
+	      macroname.clear ();
+
+	      // get the macro name (honest!)
+	      while ((!fin.eof()) && (!my_isspace(c)) && 
+		     (c != '\\') && (c != '_') &&(c != ':') && 
+		     (macroname.size() < 80)) 
+		{
+		  macroname.push_back((unsigned char)c);
+		  c = my_get(fin, line);
+		}
+	    }
+
+	  if (!err && c == '_') 
+	    {
+	      c = my_get(fin, line); // skip the _
+
+	      // skip all white space
+	      while (!fin.eof() && my_isspace(c)) c = my_get(fin, line);
+	    } 
+	  else err = 1;
+
+	  // get the macro parameters (optional)
+	  if (!err && c == '[') 
+	    {
+	      c = my_get(fin, line); // skip the [
+	      while ((!fin.eof()) && (c != '\n') && (c != '\\') && (c != ']')) 
+		{
+		  macroparameters.push_back((unsigned char)c);
+		  c = my_get(fin, line);
+		}
+
+	      if (c == ']') 
+		{
+		  c = my_get(fin, line); // skip the ]
+	  
+		  // skip all white space
+		  while (!fin.eof() && my_isspace(c)) c = my_get(fin, line);
+		} 
+	      else err = 2;
+	    }
+
+	  // get the macro value
+	  if (!err && c == '{') 
+	    {
+	      c = my_get(fin, line); // skip the {
+	      while ((!fin.eof()) && (c != '}')) 
+		{
+		  if (c == '\\') 
+		    {
+		      macrovalue.push_back((unsigned char)c); // keep the '\'
+		      c = my_get(fin, line); // store the *next* value regardless
+		      if (!fin.eof()) macrovalue.push_back((unsigned char)c);
+		      c = my_get(fin, line);
+		    }
+		  macrovalue.push_back((unsigned char)c);
+		  c = my_get(fin, line);
+		}
+
+	      if (c == '}') 
+		{
+		  c = my_get(fin, line); // skip the }
+	  
+		  // define the macro
+		  err = setdefaultmacro (macropackage, macroname, macroparameters,
+					 thisfilename, macrovalue);
+		  if (err == -1 || err == -3) 
+		    {
+		      cerr << text_t2ascii << "Warning: redefinition of _" << 
+			package << ":" << macroname << "_[" << macroparameters <<
+			"] on line ";
+		      cerr << line;
+		      cerr << text_t2ascii << " of " << thisfilename << "\n";
+	    
+		    } 
+		  else if (err == -2) 
+		    {
+		      cerr << text_t2ascii << "Warning: _" << 
+			package << ":" << macroname << "_[" << macroparameters <<
+			"] on line ";
+		      cerr << line;
+		      cerr << text_t2ascii << " of " << 
+			thisfilename << " hides a Global macro with the same name\n";
+	    
+		    } 
+		  else if (err == -4) 
+		    {
+		      cerr << text_t2ascii << "Error: macro name expected on line ";
+		      cerr << line ;
+		      cerr << text_t2ascii << " of " << thisfilename << "\n";
+		    }		  
+	  
+		  err = 0; // for the test below
+		} 
+	      else err = 3;
+	    } 
+	  else err = 4;
+
+	  if (err) 
+	    {
+	      // found an error, skip to the end of the line
+	      cerr << text_t2ascii << "Err: Unexpected input on line ";
+	      cerr << line;
+	      cerr << text_t2ascii << " (";
+	      cerr << err;
+	      cerr << text_t2ascii << ")\n";
+	      while (!fin.eof ()) 
+		{
+		  if (c == '\n') break;
+		  c = my_get(fin, line);
+		}
+	    }
+
+	} 
+      else 
+	{
+	  // found an error, skip to the end of the line
+	  cerr << "Error: Unexpected input on line " << line << "\n";
+	  while (!fin.eof ()) 
+	    {
+	      if (c == '\n') break;
+	      c = my_get(fin, line);
+	    }
+      
+	}
+    }
+  
+  fin.close ();
+  
+  // free up memory
+  delete filenamestr;
+  return 0;
+}
+
+
+// prepares to create a page.
+void displayclass::openpage (const text_t &thispageparams, 
+			const text_t &thisprecedence)
+{
+  // init variables
+  currentmacros->clear();
+
+  // reload any default macro files which have changed.
+  if (checkdefaultmacrofiles() < 0) 
+    {
+      // print error message
+    }
+
+  setpageparams (thispageparams, thisprecedence);
+}
+
+
+// changes the parameters for the current page.
+void displayclass::setpageparams (text_t thispageparams, 
+			     text_t thisprecedence)
+{
+  paramhashtype thissplitparams, splittheseparams;
+  precedencetype precedhash;
+  text_tset::iterator text_tsetit;
+  paramspec tmpps;
+
+  precedence = thisprecedence;
+  calcprecedence(thisprecedence, precedhash);
+
+  splitparams(thispageparams, thissplitparams);
+  joinparams(thissplitparams, thispageparams);
+  params = thispageparams;
+
+  // get a list of parameters with their specificness
+  orderparamlist->erase(orderparamlist->begin(), orderparamlist->end());
+  for (text_tsetit=allparams.begin();
+       text_tsetit!=allparams.end();
+       text_tsetit++) 
+    {
+      tmpps.param = (*text_tsetit);
+      splitparams(tmpps.param, splittheseparams);
+      tmpps.spec = getspecificness(thissplitparams, splittheseparams, precedhash);
+      if (tmpps.spec >= 0) 
+	{
+	  orderparamlist->push_back (tmpps);
+	}
+    }
+
+  // sort the list
+  sort(orderparamlist->begin(), orderparamlist->end());
+
+//   paramspeclist::iterator pshere = orderparamlist->begin();
+//   paramspeclist::iterator psend = orderparamlist->end();
+//   while (pshere != psend) 
+//     {
+//       cerr << text_t2ascii << "param=" << (*pshere).param;
+//       cerr << " spec=" << (int)((*pshere).spec) << "\n";
+//       pshere++;
+//     }
+}
+
+
+// overrides (or sets) a macro for the current page.
+// returns 0 if there was no error,
+//        -1 if it redefined a macro
+//        -4 if no macroname was supplied
+int displayclass::setmacro (const text_t &macroname, 
+		       text_t package, 
+		       const text_t &macrovalue)
+{
+  // make sure a macroname was supplied
+  if (macroname.empty()) return -4;
+
+  // make package "Global" if it doesn't point to anything yet
+  if (package.empty()) package = "Global";
+
+  // set the macro
+  return currentmacros->setmacro(package, macroname, "memory", macrovalue);
+}
+
+
+void displayclass::expandstring (const text_t &inputtext, text_t &outputtext)
+{
+  expandstring("", inputtext, outputtext);
+}
+
+
+void displayclass::expandstring (text_t package, const text_t &inputtext,
+			    text_t &outputtext, int recursiondepth)
+{
+  text_t macroname, macropackage, macroargs;
+  text_t::const_iterator tthere = inputtext.begin();
+  text_t::const_iterator ttend = inputtext.end();
+  unsigned short c;
+
+  if (package.empty()) package = "Global";
+
+  outputtext.clear();
+      
+  // use one-character lookahead
+  if (tthere != ttend) c = (*tthere);
+  while (tthere != ttend) 
+    {
+      if (c == '\\')
+	{
+	  // found an escape character
+	  c = my_ttnextchar (tthere, ttend); // skip the escape character
+	  if (tthere != ttend) 
+	    {
+	      if (c == 'n') outputtext.push_back('\n');
+	      else if (c == 't') outputtext.push_back('\t');
+	      else outputtext.push_back(c);
+	    }
+	  c = my_ttnextchar (tthere, ttend);
+	  
+	} 
+      else if (c == '_') 
+	{
+	  // might have found the start of a macro
+      
+	  // embedded macros (macros within the names
+	  // of other macros) are no longer supported -- Rodger.
+      
+	  // save the current state (in case we need to back out)
+	  text_t::const_iterator savedtthere = tthere;
+	  unsigned short savedc = c;
+	  
+	  macroname.clear();
+	  macropackage = package;
+	  macroargs.clear();
+      
+	  c = my_ttnextchar (tthere, ttend); // skip the '_'
+	  
+	  // get the macroname
+	  while (tthere != ttend && (!my_isspace(c)) && 
+		 (c != '\\') && (c != '_') &&(c != ':') && 
+		 (macroname.size() < 80)) 
+	    {
+	      macroname.push_back((unsigned char)c);
+	      c = my_ttnextchar (tthere, ttend);
+	    }
+      
+	  if (c == ':') 
+	    {
+	      // we actually had the macro package
+	      c = my_ttnextchar (tthere, ttend);
+	      macropackage = macroname;
+	      macroname.clear ();
+	
+	      // get the macro name (honest!)
+	      while ((tthere != ttend) && (!my_isspace(c)) && 
+		     (c != '\\') && (c != '_') &&(c != ':') && 
+		     (macroname.size() < 80)) 
+		{
+		  macroname.push_back((unsigned char)c);
+		  c = my_ttnextchar (tthere, ttend);
+		}
+	    }
+      
+	  if ((tthere != ttend) && (c == '_') &&
+	      (macroname.size() > 0)) 
+	    {
+	      // found a macro!!!! (maybe)
+	
+	      c = my_ttnextchar (tthere, ttend); // skip the '_'
+	
+	      // get the parameters (if there are any)
+	      if ((tthere != ttend) && (c == '(')) 
+		{
+		  c = my_ttnextchar (tthere, ttend); // skip '('
+	  
+		  // have to be careful of quotes
+		  unsigned short quote = '\0';
+		  while (tthere != ttend) 
+		    {
+		      if (c == '\\') 
+			{
+			  // have an escape character, save escape 
+			  // character and next character as well
+			  macroargs.push_back (c);
+			  c = my_ttnextchar (tthere, ttend); 
+	      
+			} 
+		      else if (quote == '\0') 
+			{
+			  // not in a quote at the moment
+			  if (c == ')') 
+			    {
+			      // found end of the arguments
+			      c = my_ttnextchar (tthere, ttend); // skip ')'
+			      break;
+		
+			    } 
+			  else if (c == '\'' || c == '\"') 
+			    {
+			      // found a quote
+			      quote = c;
+			    }
+	      
+			} 
+		      else 
+			{
+			  // we are in a quote
+			  if (c == quote) quote = '\0';
+			}
+	    
+		      // save this character
+		      if (tthere != ttend) macroargs.push_back (c);
+		      c = my_ttnextchar (tthere, ttend);
+		    }
+		}
+	
+	      //
+	      // we now have the macropackage, macroname, and macroargs
+	      //
+	
+	      // try to expand out this macro
+	      text_t expandedmacro;
+	      if (macro (macroname, macropackage, macroargs, expandedmacro, recursiondepth)) 
+		{
+		  // append the expanded macro
+		  outputtext += expandedmacro;
+		} 
+	      else
+		{
+		  // wasn't a macro
+		  tthere = savedtthere;
+		  c = savedc;
+		  outputtext.push_back(c); // the '_'
+		  c = my_ttnextchar (tthere, ttend);
+		}
+	
+
+	    }
+	  else
+	    {
+	      // wasn't a macro
+	      tthere = savedtthere;
+	      c = savedc;
+	      outputtext.push_back(c); // the '_'
+	      c = my_ttnextchar (tthere, ttend);
+	    }
+
+	}
+      else 
+	{
+	  // nothing of interest
+	  outputtext.push_back(c); // the '_'
+	  c = my_ttnextchar (tthere, ttend);
+	}
+    }
+}
+
+
+// protected methods for display
+
+// reloads any default macro files which have changed
+// returns 0 no errors occurred
+//        -1 an error occurred while trying to load one of the files
+int displayclass::checkdefaultmacrofiles ()
+{
+  // this isn't implemented yet
+  return 0;
+}
+
+// setdefaultmacro adds an entry to the list of default macros 
+// returns 0 if there was no error,
+//        -1 if it redefined a macro
+//        -2 if it hid a Global macro
+//        -3 if it redefined a macro and hid a Global macro
+//        -4 if no macroname was supplied
+int displayclass::setdefaultmacro (text_t package, const text_t &macroname, 
+			      text_t params, const text_t &filename,
+			      const text_t &macrovalue) 
+{
+  // make sure a macroname was supplied
+  if (macroname.empty()) return -4;
+
+  // put the parameters in a standard form
+  paramhashtype paramhash;
+  if (params.empty()) params = "ignore=yes";
+  splitparams (params, paramhash);
+  joinparams (paramhash, params);
+
+  // make package "Global" if it doesn't point to anything yet
+  if (package.empty()) package = "Global";
+
+  // remember these parameters
+  allparams.insert (params);
+
+  // remember this filename (this part isn't finished yet -- Rodger).
+
+  // set the macro
+  return defaultmacros->setmacro(package, macroname, params, filename, macrovalue);
+}
+
+// (recursively) expand out a macro
+// returns true  if the macro was found
+//         false if the macro was not found
+bool displayclass::macro (const text_t &macroname, text_t macropackage, 
+		     const text_t &macroparam, text_t &outputtext,
+		     int recursiondepth)
+{
+  outconvertclass text_t2ascii;
+  text_tlist splitmacroparam;
+  text_t::const_iterator hereit, endit;
+  text_t aparam;
+  unsigned short c, quote;
+
+  //  cerr << "r: " << recursiondepth << "\n";
+
+  // check for deep recursion
+  if (recursiondepth >= MAXRECURSIONDEPTH)
+    {
+      cerr << "Warning: deep recursion, limiting macro expansion\n";
+      return false;
+    }
+
+  // check the macropackage
+  if (macropackage.empty()) macropackage = "Global";
+
+  // get the parameters (but don't expand them)
+  if (macroparam.size() > 0) {
+    // set up for loop
+    hereit = macroparam.begin();
+    endit = macroparam.end();
+    if (hereit != endit) c = (*hereit);
+
+    while (hereit != endit) {
+      // get the next parameter
+      aparam.clear();
+      quote = '\0'; // not-quoted unless proven quoted
+      
+      // ignore initial whitespace
+      while ((hereit!=endit)&&my_isspace(c)) c=my_ttnextchar(hereit,endit);
+      
+      // look for the end of the parameter
+      while (hereit != endit) {
+	if (c == '\\') {
+	  // found escape character, also get next character
+	  aparam.push_back(c);
+	  c = my_ttnextchar (hereit, endit);
+	  if (hereit != endit) aparam.push_back(c);
+	  
+	} else if (quote=='\0' && (c=='\'' || c=='"')) {
+	  // found a quoted section
+	  quote = c;
+
+	} else if (quote!='\0' && c==quote) {
+	  // found the end of a quote
+	  quote = '\0';
+
+	} else if (quote=='\0' && c==',') {
+	  // found the end of a parameter
+	  c = my_ttnextchar (hereit, endit);
+	  break;
+
+	} else {
+	  // ordinary character
+	  aparam.push_back(c);
+	}
+
+	c = my_ttnextchar (hereit, endit);
+      }
+
+      // add this parameter to the list
+      splitmacroparam.push_back(aparam);
+    }
+  }
+
+  // I'm only supporting a simple version of _If_ at the moment
+  if (macroname == "If")
+    {
+      // get the condition, then clause and else clause
+      text_tlist::iterator paramcond = splitmacroparam.begin();
+      text_tlist::iterator paramend = splitmacroparam.end();
+      text_tlist::iterator paramthen = paramend;
+      text_tlist::iterator paramelse = paramend;
+
+      if (paramcond != paramend)
+	{
+	  paramthen = paramcond;
+	  paramthen++;
+	}
+      if (paramthen != paramend)
+	{
+	  paramelse = paramthen;
+	  paramelse++;
+	}
+
+      // will always output something
+      outputtext.clear();
+
+      // expand out the first parameter
+      if (paramcond != paramend)
+	{
+	  text_t tmpoutput;
+	  expandstring (macropackage, *paramcond, tmpoutput, recursiondepth+1);
+	  
+	  // test the expanded string
+	  if (tmpoutput.size() > 1 || 
+	      (tmpoutput.size() == 1 && tmpoutput[0] != '0'))
+	    {
+	      // true
+	      if (paramthen != paramend)
+		expandstring (macropackage, *paramthen, outputtext, recursiondepth+1);
+	    }
+	  else
+	    {
+	      // false
+	      if (paramelse != paramend)
+		expandstring (macropackage, *paramelse, outputtext, recursiondepth+1);
+	    }
+	}
+
+      return true;
+    }
+
+  // try and find this macro
+
+  // this list might be replaced by something a little more
+  // sophisticated in the future.
+  text_tlist packagelist;
+  packagelist.push_back (macropackage);
+  packagelist.push_back ("Global");
+
+  paramspeclist::iterator paramhere, paramend;
+  text_tlist::iterator packagehere = packagelist.begin();
+  text_tlist::iterator packageend = packagelist.end();
+  mvalue *macrovalue = NULL;
+  while ((macrovalue == NULL) && (packagehere != packageend)) 
+    {
+      // first look in the currentmacros
+      macrovalue = currentmacros->macro_find(*packagehere, macroname);
+      if (macrovalue == NULL)
+	macrovalue = currentmacros->macro_find("Style", macroname);
+
+      // look in the default macros
+      if (macrovalue == NULL) 
+	{
+	  // next look in the defaultmacros
+	  if (defaultmacros->macro_find (*packagehere, macroname) != NULL)
+	    {
+	      paramhere = orderparamlist->begin(); paramend = orderparamlist->end();
+	      while ((macrovalue == NULL) && (paramhere != paramend))
+		{
+// 		  cerr << text_t2ascii << "\npackage: " << *packagehere << "\n";
+// 		  cerr << text_t2ascii << "macroname: " << macroname << "\n";
+// 		  cerr << text_t2ascii << "param: " << (*paramhere).param << "\n";
+// 		  cerr << "spec: " << (int)((*paramhere).spec) << "\n";
+		  macrovalue = defaultmacros->parameter_find(*packagehere, macroname,
+							     (*paramhere).param);
+		  paramhere++;
+		}
+	    }
+	}
+
+      // and again in the package "Style"
+      if (macrovalue == NULL) 
+	{
+	  // next look in the defaultmacros
+	  if (defaultmacros->macro_find ("Style", macroname) != NULL)
+	    {
+	      paramhere = orderparamlist->begin(); paramend = orderparamlist->end();
+	      while ((macrovalue == NULL) && (paramhere != paramend))
+		{
+		  macrovalue = defaultmacros->parameter_find("Style", macroname,
+							     (*paramhere).param);
+		  paramhere++;
+		}
+	    }
+	}
+      if (macrovalue == NULL) packagehere++;
+    }
+
+  if (macrovalue != NULL)
+    {
+      // we found a macro
+
+      // replace all the option macros (_1_, _2_, ...) in the 
+      // value of this macro
+      text_t tempmacrovalue;
+      tempmacrovalue.clear();
+      hereit = macrovalue->value.begin();
+      endit = macrovalue->value.end();
+      if (hereit != endit) c = (*hereit);
+      while (hereit != endit)
+	{
+	  if (c == '\\')
+	    {
+	      // found an escape character
+	      tempmacrovalue.push_back(c);
+	      c = my_ttnextchar (hereit, endit);
+	      if (hereit != endit) tempmacrovalue.push_back(c);
+	      c = my_ttnextchar (hereit, endit);
+	    }
+	  else if (c == '_')
+	    {
+	      text_t::const_iterator savedhereit = hereit;
+	      unsigned short c2 = my_ttnextchar (hereit, endit);
+	      unsigned short c3 = my_ttnextchar (hereit, endit);
+	      if ((c2 >= '1') && (c2 <= '9') && (c3 == '_'))
+		{
+		  // found an option macro, append the appropriate text
+		  text_tlist::iterator ttlisthere = splitmacroparam.begin();
+		  text_tlist::iterator ttlistend = splitmacroparam.end();
+		  while ((c2 > '1') && (ttlisthere != ttlistend))
+		    {
+		      c2--;
+		      ttlisthere++;
+		    }
+		  if (ttlisthere != ttlistend)
+		    tempmacrovalue.append(*ttlisthere);
+
+		  c = my_ttnextchar (hereit, endit);
+
+		}
+	      else
+		{
+		  // wasn't a option macro
+		  tempmacrovalue.push_back(c);
+		  hereit = savedhereit;
+		  c = my_ttnextchar (hereit, endit);
+		}
+	    }
+	  else
+	    {
+	      tempmacrovalue.push_back(c);
+	      c = my_ttnextchar (hereit, endit);
+	    }
+	}
+      
+      // recursively replace this macro
+      expandstring (*packagehere, tempmacrovalue, outputtext, recursiondepth+1);
+
+      return true;
+    }
+
+  cerr << text_t2ascii << "Warning: _" << 
+    macropackage << ":" << macroname << "_ not found\n";
+  
+  return false; // didn't find the macro
+}
+
+
+void displayclass::printdefaultmacros ()
+{
+  defpackagemap::const_iterator packagemapit;
+  defmacromap::const_iterator macromapit;
+  defparammap::const_iterator parammapit;
+  const mvalue *mvalueptr;
+  outconvertclass text_t2ascii;
+
+  text_t packagename, macroname, macroparam;
+  
+  for (packagemapit = defaultmacros->package_begin();
+       packagemapit != defaultmacros->package_end();
+       packagemapit++) 
+    {
+      packagename = (*packagemapit).first;
+      //     cerr << "***package   : \"" << packagename << "\"\n";
+    
+      for (macromapit = (*packagemapit).second.begin();
+	   macromapit != (*packagemapit).second.end();
+	   macromapit++) 
+	{
+	  macroname = (*macromapit).first;
+	  //       cerr << "***macroname : \"" << macroname << "\"\n";
+
+	  for (parammapit = (*macromapit).second.begin();
+	       parammapit != (*macromapit).second.end();
+	       parammapit++) 
+	    {
+	      macroparam = (*parammapit).first;
+	      mvalueptr = &((*parammapit).second);
+	      cerr << text_t2ascii << "package   : \"" << packagename << "\"\n";
+	      cerr << text_t2ascii << "macroname : \"" << macroname << "\"\n";
+	      cerr << text_t2ascii << "parameters: [" << macroparam << "]\n";
+	      cerr << text_t2ascii << "filename  : \"" << mvalueptr->filename << "\"\n";
+	      cerr << text_t2ascii << "value     : {" << mvalueptr->value << "}\n\n";
+	    }
+	}
+    }
+}
+
+void displayclass::printallparams ()
+{
+  text_tset::iterator text_tsetit;
+  outconvertclass text_t2ascii;
+
+  cerr << text_t2ascii << "** allparams\n";
+  for (text_tsetit=allparams.begin();
+       text_tsetit!=allparams.end();
+       text_tsetit++) {
+    cerr << text_t2ascii << (*text_tsetit) << "\n";
+  }
+  cerr << text_t2ascii << "\n";
+}
+
+
+
+/////////////////////////////////////
+// stuff to do tricky output
+/////////////////////////////////////
+
+displayclass &operator<< (outconvertclass &theoutc, displayclass &display)
+{
+  display.setconvertclass (&theoutc);
+  return display;
+}
+
+displayclass &operator<< (displayclass &display, const text_t &t)
+{
+  outconvertclass *theoutc = display.getconvertclass();
+
+  if (theoutc == NULL) return display;
+  
+  text_t output;
+  display.expandstring (t, output);
+  (*theoutc) << output;
+
+  return display;
+}
Index: /tags/start/gsdl/src/library/display.h
===================================================================
--- /tags/start/gsdl/src/library/display.h	(revision 13666)
+++ /tags/start/gsdl/src/library/display.h	(revision 13666)
@@ -0,0 +1,229 @@
+/**************************************************************************
+ *
+ * display.h
+ *
+ * This is an implementation of a macro language that is context 
+ * sensitive. It is used to generate pages which have different
+ * 'versions'. Many variants of a macro are possible, macro
+ * resolution is done at expansion time by finding the best
+ * macro for the 'situation'.
+ *
+ * This implementation relies heavily on the Standard Template
+ * Library.
+ *
+ * Copyright (c) 1998 -- Rodger McNab and Hong Chen
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+#ifndef DISPLAY_H
+#define DISPLAY_H
+
+#include "text_t.h"
+
+
+#ifndef USE_OBJECTSPACE
+#  include <vector>
+#  include <list>
+#  include <set>
+#  include <map>
+#  include <algorithm>
+#else
+#  include <ospace\std\vector>
+#  include <ospace\std\list>
+#  include <ospace\std\set>
+#  include <ospace\std\map>
+#  include <ospace\std\algorithm>
+#endif
+
+// use the standard namespace
+#ifdef __GNUG__
+// namespaces are broken in current version of gcc
+#else
+#  ifndef USE_OBJECTSPACE
+using namespace std;
+#  else
+#    ifndef OS_NO_NAMESPACE
+using namespace ospace::std;
+#    endif
+#  endif
+#endif
+
+
+
+// MAXRECURSIONDEPTH is a cutoff to catch
+// cyclic macros (a includes b and b includes a)
+#define MAXRECURSIONDEPTH 30
+
+
+// class prototypes
+class defaultmacros_t;
+class currentmacros_t;
+
+// a few supporting types
+// fileelement isn't finished yet, I have to find out
+// more about getting information about files
+struct fileinfoelement 
+{
+  int otherinfo;
+};
+
+typedef map<text_t, fileinfoelement, lttext_t> fileinfomap;
+
+
+typedef map<text_t, text_t, lttext_t> paramhashtype;
+
+
+struct paramspec 
+{
+  double spec;
+  text_t param;
+};
+
+inline bool operator==(const paramspec& x, const paramspec& y) 
+{
+  return ((x.spec == y.spec) && (x.param == y.param));
+}
+
+inline bool operator!=(const paramspec& x, const paramspec& y) 
+{
+  return ((x.spec != y.spec) || (x.param != y.param));
+}
+
+// note: paramspec is sorted by reverse spec and then param
+
+inline bool operator<(const paramspec& x, const paramspec& y) 
+{
+  return ((x.spec > y.spec) ||
+	  ((x.spec == y.spec) && (x.param < y.param)));
+}
+
+inline bool operator>(const paramspec& x, const paramspec& y) 
+{
+  return ((x.spec < y.spec) ||
+	  ((x.spec == y.spec) && (x.param > y.param)));
+}
+
+typedef vector<paramspec> paramspeclist;
+
+
+// NOTE: when macros are used within text they should have
+// underscores '_' on both sides, however, in calls to
+// setdefaultmacro and setmacro they should not have the
+// underscores. So you might have
+//
+// setmacro ("aname", "query", " some text ");
+// expandstring ("_aname_", expandedtext);
+//
+// because the input to expandstring is a block of text, not
+// a macroname
+
+class displayclass 
+{
+public:
+  displayclass ();
+  ~displayclass ();
+  
+  // setdefaultmacro adds an entry to the list of default macros 
+  // returns 0 if there was no error,
+  //        -1 if it redefined a macro
+  //        -2 if it hid a Global macro
+  //        -3 if it redefined a macro and hid a Global macro
+  //        -4 if no macroname was supplied
+  int setdefaultmacro (text_t package, const text_t &macroname, 
+		       text_t params, const text_t &macrovalue);
+  
+  // loads a default macro file (if it isn't already loaded)
+  // returns 0 if didn't need to load the file (it was already loaded)
+  //         1 if was (re)loaded
+  //        -1 an error occurred while trying to load the file
+  int loaddefaultmacros (text_t thisfilename);
+  
+  // prepares to create a page: deletes all macros set with
+  // 'setmacro', checks all the default macro files to see
+  // if any need reloading, and sets the page parameters.
+  void openpage (const text_t &thispageparams, 
+		 const text_t &thisprecedence);
+  
+  // changes the parameters for the current page.
+  void setpageparams (text_t thispageparams, 
+		      text_t thisprecedence);
+  
+  // overrides (or sets) a macro for the current page.
+  // returns 0 if there was no error,
+  //        -1 if it redefined a macro
+  //        -4 if no macroname was supplied
+  int setmacro (const text_t &macroname, 
+		text_t package, 
+		const text_t &macrovalue);
+  
+  void expandstring (const text_t &inputtext, text_t &outputtext);
+  void expandstring (text_t package, const text_t &inputtext,
+		     text_t &outputtext, int recursiondepth = 0);
+
+  // these functions are not ment to be used directly, they are used to permit 
+  // concise stream output like:
+  // cout << text_t2ascii << display << "_amacro_" << "_anothermacro_";
+  void setconvertclass (outconvertclass *theoutc) {outc = theoutc;}
+  outconvertclass *getconvertclass () {return outc;}
+
+
+  // debug stuff
+  void printdefaultmacros ();
+  void printallparams ();
+
+protected:
+  // special variables to permit trickly output
+  outconvertclass *outc;
+
+  // general variables
+  text_tset allparams;  // possible parameter combinations
+  defaultmacros_t *defaultmacros;
+  fileinfomap *defaultfiles;
+  
+  // variables to do with a page expansion
+  text_t params;
+  text_t precedence;
+  paramspeclist *orderparamlist; // ordered by specificness
+  currentmacros_t *currentmacros; // only macros set by setmacro
+  
+  // reloads any default macro files which have changed
+  // returns 0 no errors occurred
+  //        -1 an error occurred while trying to load one of the files
+  int checkdefaultmacrofiles ();
+
+  int setdefaultmacro (text_t package, const text_t &macroname, 
+		       text_t params, const text_t &filename,
+		       const text_t &macrovalue); 
+
+  // (recursively) expand out a macro
+  // returns true  if the macro was found
+  //         false if the macro was not found
+  bool macro (const text_t &macroname, text_t macropackage, 
+	      const text_t &macroparam, text_t &outputtext,
+	      int recursiondepth);
+};
+
+
+displayclass &operator<< (outconvertclass &theoutc, displayclass &display);
+displayclass &operator<< (displayclass &display, const text_t &t);
+
+
+#endif
+
Index: /tags/start/gsdl/src/library/gdbmclass.cpp
===================================================================
--- /tags/start/gsdl/src/library/gdbmclass.cpp	(revision 13666)
+++ /tags/start/gsdl/src/library/gdbmclass.cpp	(revision 13666)
@@ -0,0 +1,575 @@
+#include "text_t.h"
+#include "gdbmclass.h"
+#include <ctype.h>
+
+#ifndef USE_OBJECTSPACE
+#  include <algorithm>
+#else
+#  include <ospace\std\algorithm>
+#endif
+
+
+void gdbm_info::clear () {
+  d = 0;
+  t.clear();
+  p.clear();
+  x.clear();
+  c.clear();
+  j.clear();
+  o.clear();
+  a.clear();
+}
+
+// checks if key is present in infodb.
+// returns 1 on success 0 on failure
+int gdbmclass::exists (text_t key, text_t collection) {
+
+  datum key_data;
+  datum return_data;
+
+  // try to open the database if it's not already open
+  if (!open_database(collection)) {
+    if (logout != NULL) (*logout) << "gdbmclass: can't open database\n"; 
+    return 0;
+  }
+  
+  // sanity check
+  if (gdbm_file == NULL) {
+    if (logout != NULL) (*logout) << "gdbmclass: failed sanity check\n";	
+    return 0;
+  }
+
+  char *db_key = key.getcstr();
+
+  if (db_key == NULL) {
+    if (logout != NULL) (*logout) << "gdbmclass: failed sanity check\n";
+    return 0;
+  }
+
+  key_data.dptr = db_key;
+  key_data.dsize = strlen (db_key);
+  return_data = gdbm_fetch (gdbm_file, key_data);
+  delete db_key;
+  db_key = NULL;
+
+  if (return_data.dptr == NULL) {
+    if (logout != NULL) {
+      (*logout) << "gdbmclass: null data pointer\n";
+      outconvertclass text_t2ascii;
+      (*logout) << text_t2ascii << "gdbmclass: key was \"" << key << "\"\n";
+    }
+    return 0;
+  }
+  free (return_data.dptr);
+  return 1;
+}
+
+
+// returns 0 on success, -1 on failure
+// key and collection aren't references as they might be aliases to
+// something in info
+int gdbmclass::getinfo (text_t key, text_t collection, gdbm_info &info) {
+
+  info.clear (); // reset info
+  
+  datum key_data;
+  datum return_data;
+  char ikey[256];
+  char ivalue[16384];
+  int pos = 0;
+
+  // try to open the database if it's not already open
+  if (!open_database(collection)) {
+    if (logout != NULL) (*logout) << "gdbmclass: can't open database\n"; 
+    return -1;
+  }
+  
+  // sanity check
+  if (gdbm_file == NULL) {
+    if (logout != NULL) (*logout) << "gdbmclass: failed sanity check\n";	
+    return -1;
+  }
+
+  char *db_key = key.getcstr();
+
+  if (db_key == NULL) {
+    if (logout != NULL) (*logout) << "gdbmclass: failed sanity check\n";
+    return -1;
+  }
+
+  key_data.dptr = db_key;
+  key_data.dsize = strlen (db_key);
+  return_data = gdbm_fetch (gdbm_file, key_data);
+  delete db_key;
+  db_key = NULL;
+
+  if (return_data.dptr == NULL) {
+    if (logout != NULL) {
+      (*logout) << "gdbmclass: null data pointer\n";
+	  outconvertclass text_t2ascii;
+      (*logout) << text_t2ascii << "gdbmclass: key was \"" << key << "\"\n";
+    }
+    return -1;
+  }
+  
+  while ((pos = get_infoline(return_data.dptr, return_data.dsize, 
+			     pos, ikey, ivalue)) >= 0) {
+
+    if (strcmp (ikey, "d") == 0) {
+      info.d = atoi(ivalue);
+      
+    } else if (strcmp (ikey, "p") == 0) {
+      info.p = ivalue;
+
+    } else if (strcmp (ikey, "t") == 0) {
+      info.t = ivalue;
+      
+    } else if (strcmp (ikey, "x") == 0) {
+      info.x = ivalue;
+      
+    } else if (strcmp (ikey, "c") == 0) {
+      info.c = ivalue;
+      
+    } else if (strcmp (ikey, "j") == 0) {
+      info.j = ivalue;
+
+	} else if (strcmp (ikey, "o") == 0) {
+      info.o = ivalue;
+
+	} else if (strcmp (ikey, "a") == 0) {
+      info.a = ivalue;
+    }
+  }
+  
+  free (return_data.dptr);
+  
+  return 0;
+}
+
+void gdbmclass::setgdbmhome (const text_t &thegdbmhome)
+{
+  gdbmhome = thegdbmhome;
+}
+
+// parses a line of the form <key>value\n
+// returns next position, -1 if there was nothing left to process
+// in the string, -2 if there was an error
+int gdbmclass::get_infoline (char *str, int len, int pos, char *key, char *value) {
+  int keylen = 0;
+  int valuelen = 0;
+  
+  key[0] = '\0';
+  value[0] = '\0';
+  
+  // ignore white space
+  while (pos < len && isspace(str[pos])) pos++;
+  
+  // get the '<'
+  if (pos >= len) return -1;
+  if (str[pos] != '<') return -2;
+  pos++;
+  
+  // get the key
+  while (pos < len && str[pos] != '>')
+    key[keylen++] = str[pos++];
+  
+  key[keylen] = '\0';
+  
+  // get the '>'
+  if (pos >= len || str[pos] != '>') return -2;
+  pos++;
+  
+  // get the value
+  while (pos < len && str[pos] != '\n') 
+    value[valuelen++] = str[pos++];
+  
+  value[valuelen] = '\0';
+  
+  return pos; 
+}
+
+
+// returns 0 if failed, 1 if opened
+int gdbmclass::open_database (const text_t &collection) {
+  text_t data_location, text_dir;
+  int block_size = 0;
+  
+  if (gdbm_file != NULL) {
+    if (collection != gdbm_open_name) {
+      close_database();
+    }
+  }
+  if (gdbm_file == NULL) {
+    gdbm_open_name = collection;
+    gettextsuffix (collection, text_dir);
+
+#ifdef __WIN32__
+    data_location = gdbmhome + "\\" + text_dir;
+#else
+    data_location = gdbmhome + "/" + text_dir;
+#endif
+        
+#ifdef _LITTLE_ENDIAN
+    data_location += ".ldb"; // little endian version of the gdbm database
+#else
+    data_location += ".bdb"; // big endian version on the gdbm database
+#endif
+    char *namebuffer = data_location.getcstr();	
+    gdbm_file = gdbm_open (namebuffer, block_size, GDBM_READER, 00664, NULL);
+    delete namebuffer;
+  }
+  return (gdbm_file != NULL);
+}
+
+
+void gdbmclass::close_database () {
+  
+  if (gdbm_file == NULL) return;
+  
+  gdbm_close (gdbm_file);
+  gdbm_file = NULL;
+}
+
+
+
+// a few useful functions
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// functions for testing classification strings
+
+
+// returns 1 if targetdoc is top level of a book (i.e. =~ /B\.\d+$/) - otherwise 0;
+int is_top_level (const text_t &targetdoc) {
+
+  text_t::const_iterator here = targetdoc.begin();
+  text_t::const_iterator end = targetdoc.end();
+
+  // look for the 'B'
+  here = findchar (here, end, 'B');
+
+  // there must be exactly one dot after the 'B'
+  if ((here != end) && (countchar (here, end, '.') == 1))
+    return 1;
+
+  return 0;
+}
+
+// returns 1 if targetdoc is any level of a book (i.e. contains 'B') - otherwise 0 
+int is_book (const text_t &targetdoc) {
+
+  text_t::const_iterator here = targetdoc.begin();
+  text_t::const_iterator end = targetdoc.end();
+  
+  here = findchar (here, end, 'B');
+  if (here != end) return 1;
+  return 0;
+}
+
+// returns (in book_top) the top level of the book in targetdoc 
+void get_book_top (const text_t &targetdoc, text_t &book_top) {
+
+  text_t::const_iterator here = targetdoc.begin();
+  text_t::const_iterator end = targetdoc.end();
+
+  book_top.clear();
+
+  // look for the 'B'
+  here = findchar (here, end, 'B');
+
+  // copy up to the second '.'
+  int founddot = 0;
+  while (here != end) {
+    if (*here == '.') {
+      if (founddot) return;
+      founddot = 1;
+    }
+    book_top.push_back(*here);
+    here++;
+  }
+}	
+
+// returns (in book) the book section part of the classification
+// contained in targetdoc
+void get_book (const text_t &targetdoc, text_t &book) {
+
+  text_t::const_iterator here = targetdoc.begin();
+  text_t::const_iterator end = targetdoc.end();
+  
+  book.clear ();
+
+  // look for the 'B'
+  here = findchar (here, end, 'B');
+
+  // copy the rest of the string
+  while (here != end) {
+    book.push_back(*here);
+    here ++;
+  }
+}
+
+// get_parent_section removes the last part from section (i.e.=~ s/\.\d+$//)  
+void get_parent_section (text_t &section) {
+  int founddot = 0;
+  text_t::iterator end;
+  while (!founddot && !section.empty()) {
+    end = section.end();
+    end --;
+    if (*end == '.') founddot = 1;
+    section.pop_back();
+  }
+}
+
+// same as above but also returns ths child section that's removed
+void get_parent_section (text_t &parentsection, text_t &childsection) {
+ int founddot = 0;
+ text_t tmp;
+ childsection.clear();
+  text_t::iterator end;
+  while (!founddot && !parentsection.empty()) {
+    end = parentsection.end();
+    end --;
+    if (*end == '.') founddot = 1;
+    else tmp.push_back(*end); childsection = tmp + childsection; tmp.clear();
+    parentsection.pop_back();
+  }
+}
+
+// count_dots returns the number of dots ('.') there are
+// in a range of a targetdoc string
+int count_dots(text_t::const_iterator first, text_t::const_iterator last) {
+  return countchar (first, last, '.');
+}
+
+int count_dots (const text_t &targetdoc) {
+  return count_dots(targetdoc.begin(), targetdoc.end());
+}
+
+// returns 1 if targetdoc is a first level descendant
+// (i.e. B.n.1, B.n.1.1, B.n.1.1.1 etc.) - otherwise 0
+int is_section_top(const text_t &targetdoc) {
+  text_t::const_iterator here = targetdoc.begin();
+  text_t::const_iterator end = targetdoc.end();
+  
+  // look for the 'B'
+  here = findchar (here, end, 'B');
+  here = findchar (here, end, '.');
+  if (here != end) here++; // skip over the '.'
+  here = findchar (here, end, '.');
+
+  // make sure that all '.' are followed by a '1'
+  while (here != end) {
+    if (*here != '.') return 0;
+    here ++;
+
+    if (here != end) {
+      if (*here != '1') return 0;
+      here ++;
+    }
+  }
+  return 1;
+}
+
+// seperate_parts seperates targetdoc into its classification and booksection
+// if classification isn't supplied it gets the first classification for the 
+// book from the gdbm
+// if booksection doesn't exist it remains blank
+void seperate_parts(const text_t &targetdoc, gdbmclass &gdbm, const text_t &collection, 
+		    text_t &classification, text_t &booksection) {
+  
+  split_targetdoc (targetdoc, classification, booksection);
+
+  if (classification.empty()) {
+    // no classification included so get first one for this book
+    gdbm_info info;
+    text_t book_top;
+    vector<text_t> classarray;
+    get_book_top (targetdoc, book_top);
+    gdbm.getinfo(book_top, collection, info);
+    splitstring (info.x, classarray);
+    if (!classarray.empty()) classification = classarray[0];
+	else classification = "C.1";
+  }
+}
+
+// split_targetdoc splits up a string containing a classification
+// and book (or one or the other)
+void split_targetdoc(const text_t &targetdoc, text_t &classification, 
+		     text_t &booksection) {
+  
+  classification.clear ();
+  booksection.clear();
+
+  text_t::const_iterator here = targetdoc.begin();
+  text_t::const_iterator end = targetdoc.end();
+
+  // copy everything up to the first 'B'
+  while (here != end) {
+    if (*here == 'B') break;
+    classification.push_back(*here);
+    here++;
+  }
+
+  // remove middle '.'
+  if (!classification.empty() && 
+      classification[classification.size()-1] == '.') 
+    classification.pop_back();
+
+  // copy the rest of the string
+  while (here != end) {
+    booksection.push_back(*here);
+    here++;
+  }
+}
+
+// splitstring splits a colon seperated string into an array
+void splitstring (const text_t &string, vector<text_t> &array) {
+  splitchar (string.begin(), string.end(), ':', array);
+}
+
+// get_parents returns the parents array containing all the parents of the
+// document specified by classification and booksection
+void get_parents (const text_t &targetdoc, vector<text_t> &parents)
+{
+  text_t::const_iterator here = targetdoc.begin ();
+  text_t::const_iterator end = targetdoc.end ();
+
+  text_t currentparent;
+  text_t newsuffixpart;
+  text_t newsuffix;
+  bool first = true;
+  while (here != end)
+    {
+      // if there is a newsuffix add it to the current parent
+      // and add that parent to the parents vector
+      if (!newsuffix.empty())
+	{
+	  currentparent += newsuffix;
+	  parents.push_back (currentparent);
+	}
+      
+      // keep getting suffixes until one is found which starts with
+      // a number
+      newsuffix.clear();
+      do 
+	{
+	  here = getdelimitstr (here, end, '.', newsuffixpart);
+	  if (!first) newsuffix.push_back ('.');
+	  first = false;
+	  newsuffix += newsuffixpart;
+	} 
+      while ((here != end) && !newsuffixpart.empty() && 
+	     (newsuffixpart[0] < '0' || newsuffixpart[0] > '9'));
+    }
+}
+
+
+// get_siblings returns the siblings array containing all the siblings of the current
+// classification or booksection
+void get_siblings (const text_t &classification, const text_t &booksection, 
+		   gdbmclass &gdbm, const text_t &collection, 
+		   vector<text_t> &siblings) {
+  
+  gdbm_info info;
+  
+  if (booksection.empty() &&  classification.size() == 1) {
+    // top level classification has no siblings
+    return;
+
+  } else if (booksection.empty()) {
+    // get classification siblings
+    gdbm.getinfo(classification, collection, info);
+    gdbm.getinfo(info.p, collection, info); // info is now parent info
+    splitstring(info.c, siblings);
+    return;
+
+  } else {
+    // get book section siblings
+    if (is_top_level(booksection)) {
+      // top level of book so siblings are children of classification
+      gdbm.getinfo(classification, collection, info);
+      splitstring(info.c, siblings);
+
+      // add classifications to book sections
+      for (unsigned int i = 0; i < siblings.size(); i++) {
+	if (is_book(siblings[i])) siblings[i] = classification + "." + siblings[i];
+      } 
+
+    } else {
+      // siblings come from immediate parent
+      gdbm.getinfo(booksection, collection, info);
+      gdbm.getinfo(info.p, collection, info); // info is now parent info
+      splitstring(info.c, siblings);
+
+      // add classifications to book sections
+      for (unsigned int i = 0; i < siblings.size(); i++) {
+	if (is_book(siblings[i])) siblings[i] = classification + "." + siblings[i];
+      } 
+    }
+  }
+}
+
+// compares section 1 and section 2 and returns 1 if section2 belongs to 
+// the same chapter as section1 (i.e. is sibling of or child of or child of sibling) 
+int are_same_chapter(text_t section1, text_t section2)
+{
+  get_parent_section(section1);
+
+  while (!section2.empty()) {
+    get_parent_section(section2);
+    if (section2 == section1) return 1;
+  }
+  return 0;
+}
+
+// get_first_section gets the first section from a colon separated
+// list (instring)
+void get_first_section(const text_t &instring, text_t &returnstring) {
+
+  returnstring.clear();
+  
+  text_t::const_iterator here = instring.begin();
+  text_t::const_iterator end = instring.end();
+  
+  while (here != end) {
+    if (*here == ':') return;
+    returnstring.push_back(*here);
+	here ++;
+  }
+}
+
+
+// removes html tags from string - everything after < will be removed
+// if < occurs without >
+void remove_tags (text_t &text) 
+{
+  text_t::const_iterator here = text.begin ();
+  text_t::const_iterator end = text.end ();
+  int found = 0;
+  text_t tmp;
+
+  while (here != end) {
+    if (*here == '<') {found = 1; here ++; continue;}
+    if (*here == '>') {found = 0; here ++; continue;}
+
+    if (!found) tmp.push_back(*here);
+    here ++;
+  }
+  text = tmp;
+}
+
+// checks text to see if it is a number (i.e. contains only 0-9)
+// returns 1 if true, 0 if false
+int is_number (text_t &text) {
+
+  text_t::const_iterator here = text.begin();
+  text_t::const_iterator end = text.end();
+
+  while (here != end) {
+    if ((*here!='0') && (*here!='1') && (*here!='2') &&
+	(*here!='3') && (*here!='4') && (*here!='5') &&
+	(*here!='6') && (*here!='7') && (*here!='8') &&
+	(*here!='9')) return 0;
+    here ++;
+  }
+  return 1;
+}
Index: /tags/start/gsdl/src/library/gdbmclass.h
===================================================================
--- /tags/start/gsdl/src/library/gdbmclass.h	(revision 13666)
+++ /tags/start/gsdl/src/library/gdbmclass.h	(revision 13666)
@@ -0,0 +1,84 @@
+#ifndef GDBMCLASS_H
+#define GDBMCLASS_H
+
+#ifdef __WIN32__
+#include "autoconf.h"
+#include "systems.h"
+#include "gdbmconst.h"
+#include "gdbm.h"
+
+#else
+#include <gdbm.h>
+#endif
+
+#include "locateinfo.h"
+
+
+class gdbm_info 
+{
+public:
+  int docnum;
+  int d;
+  text_t t;
+  text_t p;
+  text_t x;
+  text_t c;
+  text_t j;
+  text_t o;
+  text_t a;
+
+  void clear ();
+};
+
+
+class gdbmclass 
+{
+public:
+  gdbmclass() {gdbm_file = NULL; logout = &cerr;};
+  ~gdbmclass() {};
+  
+  // returns 0 on success, -1 on failure
+  int getinfo (text_t key, text_t collection, gdbm_info &info);
+  void setgdbmhome (const text_t &thegdbmhome);
+  void setlogout (ostream *thelogout) {logout = thelogout;}
+  int exists (text_t key, text_t collection);
+
+protected:
+  text_t gdbmhome; // top level directory for gdbm files
+  GDBM_FILE gdbm_file;
+  text_t gdbm_open_name;
+  ostream *logout;
+  
+  int open_database (const text_t &collection);
+  void close_database ();
+  
+  int get_infoline (char *str, int len, int pos, char *key, char *value);
+};
+
+
+// a few useful functions
+
+int is_top_level (const text_t &targetdoc);
+int is_book (const text_t &targetdoc);
+void get_book_top (const text_t &targetdoc, text_t &book_top);
+void get_book (const text_t &targetdoc, text_t &book);
+void get_parent_section (text_t &section);
+void get_parent_section (text_t &parentsection, text_t &childsection);
+int count_dots (text_t::const_iterator first, text_t::const_iterator last);
+int count_dots (const text_t &targetdoc);
+int is_section_top (const text_t &targetdoc);
+void remove_tags (text_t &text);
+
+void seperate_parts (const text_t &targetdoc, gdbmclass &gdbm, const text_t &collection, 
+		     text_t &classification, text_t &booksection);
+void split_targetdoc (const text_t &targetdoc, text_t &classification, 
+		     text_t &booksection);
+void splitstring (const text_t &string, vector<text_t> &array);
+void get_parents (const text_t &targetdoc, vector<text_t> &parents);
+void get_siblings (const text_t &classification, const text_t &booksection, 
+		   gdbmclass &gdbm, const text_t &collection, 
+		   vector<text_t> &siblings);
+int are_same_chapter(text_t section1, text_t section2);
+void get_first_section(const text_t &instring, text_t &returnstring);
+int is_number (text_t &text);
+#endif
Index: /tags/start/gsdl/src/library/libinterface.cpp
===================================================================
--- /tags/start/gsdl/src/library/libinterface.cpp	(revision 13666)
+++ /tags/start/gsdl/src/library/libinterface.cpp	(revision 13666)
@@ -0,0 +1,1012 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+#include "libinterface.h"
+#include "cgiargs.h"
+
+#include <assert.h>
+
+///////////////////////
+// support functions //
+///////////////////////
+
+unsigned short hexdigit (unsigned short c)
+{
+  if (c >= '0' && c <= '9') return (c-'0');
+  if (c >= 'a' && c <= 'f') return (c-'a'+10);
+  if (c >= 'A' && c <= 'F') return (c-'A'+10);
+  return c;
+}
+
+
+void c2hex (unsigned short c, text_t &t)
+{
+  t.clear();
+
+  if (c >= 256) 
+    {
+      t = "20"; // ' '
+      return;
+    }
+
+  unsigned short o1, o2;
+ 
+  o1 = (c/16) % 16;
+  o2 = c % 16;
+  if (o1 >= 10) o1 += 'a' - 10;
+  else o1 += '0';
+  if (o2 >= 10) o2 += 'a' - 10;
+  else o2 += '0';
+
+  t.push_back(o1);
+  t.push_back(o2);
+}
+
+// convert %xx and + to their appropriate equivalents
+void decode (text_t &argstr)
+{
+  text_t::iterator in = argstr.begin();
+  text_t::iterator out = in;
+  text_t::iterator end = argstr.end();
+
+  while (in != end)
+    {
+      if (*in == '+') *out = ' ';
+
+      else if (*in == '%')
+	{
+	  unsigned short c = '%';
+	  in++;
+	  if (in != end)
+	    {
+	      c = hexdigit (*in);
+	      in++;
+	    }
+	  if (in != end && c < 16) // sanity check on the previous character
+	    {
+	      c = c*16 + hexdigit (*in);
+	    }
+
+	  *out = c;
+	}
+      else *out = *in;
+
+      if (in != end) in++;
+      out++;
+    }
+  
+  // remove the excess characters
+  argstr.erase (out, end);
+}
+
+
+// split up the cgi arguments
+void parse_cgi_args (text_t argstr, cgiargsclass &args)
+{
+  args.clear();
+
+  text_t::iterator here = argstr.begin();
+  text_t::iterator end = argstr.end();
+  text_t key, value;
+
+  // extract out the key=value pairs
+  while (here != end) 
+    {
+      // get the next key and value pair
+      here = getdelimitstr (here, end, '=', key);
+      here = getdelimitstr (here, end, '&', value);
+
+      // convert %xx and + to their appropriate equivalents
+      decode (value);
+      // store this key=value pair
+      if (!key.empty()) args.setarg (key, value);
+    }
+}
+
+text_t cgisafe (text_t &intext)
+{
+  text_t outtext;
+
+  text_t::iterator here = intext.begin ();
+  text_t::iterator end = intext.end ();
+  unsigned short c;
+  text_t ttmp;
+
+  while (here != end)
+    {
+      c = *here;
+      if (((c >= 'a') && (c <= 'z')) ||
+	  ((c >= 'A') && (c <= 'Z')) ||
+	  ((c >= '0') && (c <= '9'))) {
+	// alphanumeric character
+	outtext.push_back(c);
+      } else {
+	  // non-alphnumeric character
+	  outtext.push_back('%');
+	  c2hex(c, ttmp);
+	  outtext += ttmp;
+      }
+	  
+      here++;
+    }
+
+  return outtext;
+}
+
+//////////////////////////////
+// methods for libinterface //
+//////////////////////////////
+
+// constructor
+
+libinterface::libinterface() 
+{
+  browse = NULL;
+}
+
+void libinterface::setgsdlhome (const text_t &thegsdlhome)
+{
+  gsdlhome = thegsdlhome;
+  setmacroshome (thegsdlhome);
+  setgdbmhome (thegsdlhome);
+  setindexhome (thegsdlhome);
+}
+
+void libinterface::setmacroshome (const text_t &themacroshome)
+{
+  macroshome = themacroshome;
+}
+
+void libinterface::setgdbmhome (const text_t &thegdbmhome)
+{
+  gdbmhome = thegdbmhome;
+  gdbm.setgdbmhome(gdbmhome);
+}
+
+void libinterface::setindexhome (const text_t &theindexhome)
+{
+  indexhome = theindexhome;
+  search.setindexhome(theindexhome);
+}
+
+void libinterface::sethttpprefix (const text_t &thehttpprefix)
+{
+  httpprefix = thehttpprefix;
+}
+
+void libinterface::setgwcgi (const text_t &thegwcgi)
+{
+  gwcgi = thegwcgi;
+}
+
+// init should be called after the various homes are set,
+// it returns 'false' on failure and 'true' on success
+bool libinterface::init ()
+{
+  set_default_index();
+  text_t collection = get_collection_name();
+
+  // load up default macro files -- these shouldn't have absolute file names
+#ifdef __WIN32__
+  disp.loaddefaultmacros(macroshome + "\\macros\\base.dm");
+  disp.loaddefaultmacros(macroshome + "\\macros\\browse.dm");
+  disp.loaddefaultmacros(macroshome + "\\macros\\text.dm");
+  disp.loaddefaultmacros(macroshome + "\\macros\\query.dm");
+  disp.loaddefaultmacros(macroshome + "\\macros\\help.dm");
+  disp.loaddefaultmacros(macroshome + "\\macros\\gsdl.dm");
+  disp.loaddefaultmacros(macroshome + "\\macros\\pref.dm");
+#else
+  disp.loaddefaultmacros(macroshome + "/macros/base.dm");
+  disp.loaddefaultmacros(macroshome + "/macros/browse.dm");
+  disp.loaddefaultmacros(macroshome + "/macros/text.dm");
+  disp.loaddefaultmacros(macroshome + "/macros/query.dm");
+  disp.loaddefaultmacros(macroshome + "/macros/help.dm");
+  disp.loaddefaultmacros(macroshome + "/macros/gsdl.dm");
+  disp.loaddefaultmacros(macroshome + "/macros/pref.dm");
+#endif
+
+  srand(time(NULL));
+
+  return collection_init(collection);
+}
+
+
+// examine the cgi arguments and create the appropriate page, 
+// outputing the page to textout and any debug information to logout
+//
+// returns LI_NOERROR on success, LI_LOADDATABASEFAILED on failure
+int libinterface::getpage (const text_t &argstr, ostream &textout, ostream &logout)
+{
+  int err = LI_NOERROR;
+
+  gdbm.setlogout (&logout); // make the output go where they want!
+
+  cgiargsclass args;
+
+  parse_cgi_args (argstr, args);
+  expand_compressed_args (args);
+  add_default_args (args);
+  check_args (args);
+
+  lastcomparg = get_compressed_args (args);
+
+  logout << args;
+
+  text_t &arg_a = args["a"];
+  if (arg_a == "q") err = query_action (args, textout, logout);
+  else if (arg_a == "b") browse_action (args, textout, logout);
+  else if (arg_a == "t") document_action (args, textout, logout);
+  else if (arg_a == "p") page_action (args, textout, logout);
+  else 
+    {
+      // output error page
+    }
+
+  return err;
+}
+
+// the arg config string is used to do processing on the arguments
+// entries take the form argname[defaultvalue]
+// if the argument name is preceeded by a "+" it means that the
+// value may be more than one character long
+// the main state variable missed on this list is "q" the query string
+void libinterface::get_arg_config (text_t &argconfigstr)
+{
+  argconfigstr = 
+    "a[p]"     // action: q=query, b=browse, t=targetdoc, p=page
+    "t[1]"     // query type: 0=boolean, 1=ranked
+    "i[c]"     // index: c=chapter, p=paragraph, t=title, b=book
+    "k[1]"     // casefolding: 0=off, 1=on
+    "s[0]"     // stemming: 0=off, 1=on
+    "+p[home]" // page
+    "+c[unu2]" // collection
+    "+r[1]"    // results from
+    "+d[C.1]"  // the target document
+    "+j[11]"   // partial index: 11=all, 10=f&n, 01=other
+    "+m[100]"   // maxdocs
+    "+o[20]"   // hits per page
+    "v[0]"     // version: 0=text+graphics, 1=text
+    "f[0]";    // query box size: 0=normal, 1=big
+  
+}
+
+text_t::iterator libinterface::get_next_config_arg (text_t::iterator first, 
+						    text_t::iterator last,
+						    text_t &argname, 
+						    text_t &defaultvalue, 
+						    bool &longarg)
+{
+  first = getdelimitstr (first, last, '[', argname);
+  first = getdelimitstr (first, last, ']', defaultvalue);
+  longarg = false;
+
+  if (!argname.empty() && (argname[0] == '+'))
+    {
+      argname.erase(argname.begin(), argname.begin()+1);
+      longarg = true;
+    }
+
+  return first;
+}
+
+text_t libinterface::get_compressed_args (cgiargsclass &args)
+{
+  text_t argconfigstr; get_arg_config (argconfigstr);
+  text_t arg_e;
+  text_t argname, defaultvalue;
+  text_t *argvalue;
+  bool longarg;
+
+  text_t::iterator here = argconfigstr.begin();
+  text_t::iterator end = argconfigstr.end();
+  while (here != end)
+    {
+      here = get_next_config_arg (here, end, argname, defaultvalue, longarg);
+
+      if (!argname.empty())
+	{
+	  argvalue = args.getarg (argname);
+	  if (argvalue == NULL) arg_e += defaultvalue;
+	  else arg_e += *argvalue;
+	    
+	  if (longarg) arg_e += "-";
+	}
+    }
+  
+  return arg_e;
+}
+
+
+// the compressed options should never override explicit options
+// but they should always be expanded before add_default_args is
+// called
+void libinterface::expand_compressed_args (cgiargsclass &args)
+{
+  text_t *arg_e = args.getarg("e");
+
+  // see if there is compressed options
+  if (arg_e != NULL)
+    {
+      text_t argconfigstr; get_arg_config (argconfigstr);
+      text_t argname, defaultvalue, argvalue;
+      bool longarg;
+
+      text_t::iterator confighere = argconfigstr.begin();
+      text_t::iterator configend = argconfigstr.end();
+
+      text_t::iterator arghere = arg_e->begin();
+      text_t::iterator argend = arg_e->end();
+      while (confighere != configend && arghere != argend)
+	{
+	  confighere = get_next_config_arg (confighere, configend, argname, 
+					    defaultvalue, longarg);
+	  if (!argname.empty())
+	    {
+	      if (longarg)
+		{
+		  arghere = getdelimitstr (arghere, argend, '-', argvalue);
+		  if (!argvalue.empty()) args.setdefaultarg (argname, argvalue);
+		}
+	      else
+		{
+		  args.setdefaultcarg (argname,*arghere);
+		  arghere++;
+		}
+	    }
+	}
+    }
+}
+
+
+void libinterface::add_default_args (cgiargsclass &args)
+{ 
+  text_t argconfigstr; get_arg_config (argconfigstr);
+  text_t argname, defaultvalue;
+  bool longarg;
+
+  text_t::iterator confighere = argconfigstr.begin();
+  text_t::iterator configend = argconfigstr.end();
+  while (confighere != configend)
+    {
+      confighere = get_next_config_arg (confighere, configend, argname, 
+					defaultvalue, longarg);
+      if (!argname.empty()) args.setdefaultarg (argname, defaultvalue);
+    }
+  
+  // the query string and format string are not included in the argument configuration string
+  args.setdefaultarg ("q", ""); // the default query string is ""
+  args.setdefaultarg ("g", "00");
+  args.setdefaultarg ("x", "0");
+}
+
+
+// check and attempt to fix an problems encountered in the list
+// of cgi arguments
+void libinterface::check_args (cgiargsclass &args)
+{
+  text_t collection = get_collection_name();
+  args.setarg("c", collection);
+}
+
+
+void libinterface::define_general_macros (cgiargsclass &args, ostream &logout)
+{
+  disp.setmacro("httpprefix", "Global", httpprefix);
+  disp.setmacro("gwcgi", "Global", gwcgi);
+
+  disp.setmacro("collection", "Global", cgisafe(args["c"]));
+  disp.setmacro("compressedoptions", "Global", get_compressed_args(args));
+  disp.setmacro("urlsafequerystring", "Global", cgisafe(args["q"]));
+
+  // need to escape any quotes in querystring to prevent them upsetting the html
+  text_t querystring;
+  text_t::iterator here = args["q"].begin();
+  text_t::iterator end = args["q"].end();
+  while (here != end) {
+    if (*here == '"') querystring += "&quot;";
+    else querystring.push_back(*here);
+    here ++;
+  }
+  disp.setmacro("querystring", "Global", querystring);
+
+
+  if (args.getintarg("x") == 0) disp.setmacro("notdetached", "Global", "1");
+  if (args["d"][0] == 'T') disp.setmacro("istitle", "Global", "1");
+
+  int i = rand();
+  disp.setmacro("pagedest", "Global", text_t(i));
+
+  // define the macro for the "g" argument
+  disp.setmacro("g", "Global", args["g"]);
+}
+
+
+// prepare_page prepares to write out a page using the current 
+// page parameters and defines any general macros
+void libinterface::prepare_page (cgiargsclass &args, ostream &logout)
+{
+  // get page parameters
+  text_t pageparams = text_t("collection=") + args["c"];
+  if (args.getintarg("u") == 1) pageparams += ",style=htmlonly";
+  if (args.getintarg("v") == 1) pageparams += ",version=text";
+  if (args.getintarg("f") == 1) pageparams += ",queryversion=big";
+
+  disp.openpage(pageparams, MACROPRECEDENCE);
+  define_general_macros(args, logout);
+  define_collection_macros(args, logout);
+}
+
+void libinterface::set_query_params (cgiargsclass &args, queryparamclass &queryparams)
+{
+  queryparams.collection = args["c"];
+  assemble_index (args, queryparams.search_index);
+  queryparams.querystring = args["q"];
+  format_querystring (queryparams.querystring);
+  queryparams.search_type = args.getintarg ("t");
+  queryparams.casefolding = args.getintarg ("k");
+  queryparams.stemming = args.getintarg ("s");
+  queryparams.maxdocs = args.getintarg ("m");
+}
+
+void libinterface::format_querystring (text_t &querystring)
+{
+  text_t formattedstring;
+  quotedstring.clear();
+
+  text_t::iterator here = querystring.begin();
+  text_t::iterator end = querystring.end();
+  int foundquote = 0;
+
+  // want to remove ()|!& from querystring so boolean queries are just
+  // "all the words" queries
+  while (here != end) {
+    if (*here == '(' || *here == ')' || *here == '|' ||
+	*here == '!' || *here == '&') {
+      formattedstring += " ";
+    } else {
+      if (*here == '"') {
+	if (foundquote) {foundquote = 0; quotedstring.push_back(*here);}
+	else foundquote = 1;
+      } else {
+	formattedstring.push_back(*here);
+      }
+      if (foundquote) quotedstring.push_back(*here);
+    }
+    here ++;
+  }
+  querystring = formattedstring + quotedstring;
+}
+
+void libinterface::define_query_macros (cgiargsclass &args, 
+					queryparamclass &queryparams,
+					queryresultsclass &queryresults, 
+					ostream &logout) 
+{
+  int numdocs = queryresults.getnumdocs();
+  int numterms = queryresults.getnumterms();
+  disp.setmacro("querysize", "query", args["f"]);
+  disp.setmacro("haveresults", "query", numdocs);
+  
+  // set the display frequency macro
+  text_t freqmsg = "_textfm1_";
+
+  int first = 1;
+  for (int i = 0; i < numterms; i++) {
+    if (first == 0) freqmsg += "; ";
+    first = 0;
+    freqmsg += queryresults.terms[i].termstr + ": " + queryresults.terms[i].termfreq;
+  }
+  if (!quotedstring.empty()) freqmsg += "<br><i>post-processed to find " + quotedstring + "</i>\n";
+  disp.setmacro("freqmsg", "query", freqmsg);
+
+  // set the result line macro
+
+  text_t resline;
+  
+  if (numdocs >= queryparams.maxdocs)
+    resline.setcstr("_textmt2_");
+  
+  if (numdocs == 0) {
+    resline.setcstr("_textndmtq_");
+  } else if (numdocs == 1) {
+    resline += text_t(numdocs) + text_t(" _textdmtq2_.");
+  } else {
+    resline += text_t(numdocs) + text_t(" _textdmtq3_.");
+  }
+
+  disp.setmacro("resultline", "query", resline);
+
+  //  define_collection_macros (args, logout);
+
+  if (queryresults.getnumdocs() > 0) {
+    docLinks(args, queryresults, logout);
+  }
+}
+
+
+// set the _links_ macro to create the links between pages of query results
+void libinterface::docLinks (cgiargsclass &args, 
+			     queryresultsclass &queryresults, 
+			     ostream &logout) 
+{
+  text_t links;
+  int a, b, documents, nextfirst, nextlast, prevfirst, prevlast;
+  int results_from = args.getintarg("r");
+  int hitsperpage = args.getintarg("o");
+  
+  documents = queryresults.getnumdocs();
+  
+  a = results_from;
+  b = a + (hitsperpage - 1);
+  
+  // make sure a and b are in range
+  if (a < 1) a = 1;
+  if (b < 1) b = 1;
+  if (a > documents) a = documents;
+  if (b > documents) b = documents;
+  
+  links.setcstr("<table cellspacing=0 cellpadding=0 border=0 width=\"100%\">\n");
+  links += "<tr valign=bottom>\n";
+  links += "<td align=left>\n";
+  links += "<_font_>\n";
+  
+  // previous page link
+  if (a > 1) {
+    prevlast = a - 1;
+    prevfirst = a - hitsperpage;
+    
+    links += "<p><a href=\"_httpqueryresults_&r="; 
+    links += prevfirst;
+    links += "\">_iconprev__textmatches_ ";
+    links += prevfirst;
+    links += " - ";
+    links += prevlast;
+    links += "</a>\n";
+  }
+  
+  links += "</font>\n";
+  links += "</td><td width=100></td><td align=right>\n";
+  links += "<_font_>\n";
+  
+  // next page link
+  if (b < documents) {
+    nextfirst = b + 1;
+    nextlast = b + hitsperpage;
+    if (nextlast > documents) nextlast = documents;
+    
+    links += "<p><a href=\"_httpqueryresults_&r=";
+    links += nextfirst;
+    links += "\">_textmatches_ ";
+    links += nextfirst;
+    links += " - ";
+    links += nextlast ;
+    links += "_iconnext_</a>\n";
+  }
+  
+  links += "</font>\n";
+  links += "</td></tr></table>\n";
+  
+  disp.setmacro("links", "query", links);
+}
+
+
+// returns LI_NOERROR on success, LI_LOADDATABASEFAILED on failure
+int libinterface::do_query(cgiargsclass &args, queryparamclass &queryparams, 
+			    queryresultsclass &queryresults, ostream &logout) 
+{
+  set_query_params(args, queryparams);
+
+  if (!queryparams.querystring.empty()) {
+    // do the query - the results are returned in queryresults
+    if (!search.search(queryparams, queryresults)) {
+      logout << "ERROR: database didn't load\n";
+	  return LI_LOADDATABASEFAILED;
+    }
+  }
+  return LI_NOERROR;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+// query_action is called whenever a search is to be carried out  (i.e. when the 
+// 'a' parameter == 'q') - query calls the mgsearch search() function (via do_query()) to 
+// carry out the search then displays the first page of results.
+//
+// returns LI_NOERROR on success, LI_LOADDATABASEFAILED on failure
+int libinterface::query_action (cgiargsclass &args, ostream &textout, ostream &logout)
+{
+  int err = LI_NOERROR;
+
+  queryparamclass queryparams;
+  queryresultsclass queryresults;
+
+  err = do_query(args, queryparams, queryresults, logout);
+
+  // prepare to print out the page
+  prepare_page(args, logout);
+  define_query_macros(args, queryparams, queryresults, logout);
+
+  // print out the query page
+  textout << text_t2ascii << disp << "_query:header_\n";
+
+  // output query results if there is a query string - 
+  // otherwise output help text
+  if (!queryparams.querystring.empty()) 
+    {
+      displayresults (args, textout, logout, queryresults);
+    } 
+  else 
+    {
+      textout << text_t2ascii << disp << "_query:noqueryheader_\n";
+    }
+  
+  textout << text_t2ascii << disp << "_query:footer_\n";
+
+  return err;
+}
+
+void libinterface::displayresults (cgiargsclass &args, ostream &textout, ostream &logout,
+				   queryresultsclass &queryresults) 
+{
+  textout << text_t2ascii << disp << "_query:queryheader_";
+
+
+  int startresults = args.getintarg("r") - 1;
+  int numresults = args.getintarg("o");
+
+  textout << text_t2ascii << "<table cellspacing=4>\n";
+  for (int i=startresults; i < startresults+numresults; i++)
+    {
+      displaydocsummary (args, textout, logout, queryresults, i);
+    }
+  textout << text_t2ascii << "</table>\n\n";
+
+  textout << text_t2ascii << disp << "_query:queryfooter_";
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+// browse_action writes out the browse pages (i.e. the top level hierarchy pages)
+void libinterface::browse_action (cgiargsclass &args, ostream &textout, ostream &logout)
+{
+  text_t browse_bar, locator, output;
+  gdbm_info info;
+  
+  prepare_page(args, logout);
+  
+  // get browse bar unless page has been detached 
+  if (args.getintarg("x") == 0) {
+    browse->get_browse_bar(args["d"], browse_bar);
+  }
+  
+  // get top locator
+  browse->get_top_locator(args, gdbm, 0, locator);	
+
+  // expand and output page 
+  // Note: we need to expand these out using package 'browse'
+  // so we can't use the tricky '<<' syntax
+  disp.expandstring("browse", "_header_", output);
+  textout << text_t2ascii << output;
+  disp.expandstring("browse", browse_bar, output);
+  textout << text_t2ascii << output;
+  disp.expandstring("browse", locator, output);
+  textout << text_t2ascii << output;
+  disp.expandstring("browse", "_footer_", output); 
+  textout << text_t2ascii << output;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// document_action is called to retrieve and display collection documents
+// It calls the mgsearch function docTargetDocument() to retrieve 
+// a document. 
+
+void libinterface::document_action (cgiargsclass &args, ostream &textout, ostream &logout) {
+  
+  text_t locator, content, links, output;
+  gdbm_info info;
+  queryparamclass queryparams;
+  queryresultsclass queryresults;
+  int oversize = 0;
+
+  // have to redo the query to get queryterms for highlight text
+  do_query(args, queryparams, queryresults, logout);
+
+  prepare_page(args, logout);
+  
+  if (args["g"][1] == '0') {
+    // get docnum from gdbm
+    text_t docref;
+    if (args["d"][0] != 'B') get_book(args["d"], docref);
+    else docref = args["d"];
+    if (gdbm.getinfo(docref, queryparams.collection, info) != 0) {
+      logout << text_t2ascii << "info_db wasn't opened - " << docref << "\n";
+      return;
+    }
+    
+    // get document text if there is any
+    if (info.c.empty()) {
+        search.docTargetDocument(default_index, queryparams.collection,
+				 info.d, content);
+	if (info.t != "<i>(introductory text)</i>")
+	  content = "<h3>" + info.t + "</h3>\n" + content;
+    }
+  } 
+
+  if (args["g"][1] == '1') {
+    // want to get expanded out text
+    vector<text_t> contents_arr;
+    text_t booksection;
+    int levelcount;
+
+    get_book (args["d"], booksection);
+    levelcount = count_dots(booksection);
+
+    browse->get_contents_arr(args, gdbm, contents_arr);
+    
+
+    // get text for each section of book
+    vector<text_t>::const_iterator thiscontent = contents_arr.begin();
+    vector<text_t>::const_iterator end = contents_arr.end();
+
+    int first = 1;
+    int count = 1;
+    while (thiscontent != end) {
+      text_t text;
+
+      // get docnum from gdbm
+      if (gdbm.getinfo(*thiscontent, queryparams.collection, info) != 0) { 
+	logout << text_t2ascii << "info_db wasn't opened - " << args["d"] << "\n";
+	return;
+      }
+
+      // if section has text get it, otherwise output section title
+      if (info.c.empty()) {
+
+	// output <a name= > tags for all text sections currently displayed in toc (all text sections
+	// if contents are expanded
+	if (count_dots(*thiscontent) == levelcount || args["g"][0] == '1') {
+	  content += "<a name=\"";
+	  content += count;
+	  content += "\"></a>\n";
+	  count ++;
+	}
+
+	search.docTargetDocument(default_index, queryparams.collection,
+				 info.d, text);					
+	if (info.t != "<i>(introductory text)</i>") 
+	  content += "<h3>" + info.t + "</h3>\n";
+	//	content += text + "<hr><br>\n";
+	content += text + "<p>\n"; // no longer want <hr> between sections
+      } else {
+	content += "<h3>" + info.t + "</h3>\n";
+      }
+
+      if (args["n"] == 1) {
+	if (first) {
+	  browse->get_top_locator(args, gdbm, 0, locator);
+	  disp.expandstring("text", "_header_", output);
+	  textout << text_t2ascii << output;
+	  disp.expandstring("text", locator, output);
+	  textout << text_t2ascii << output;
+	}
+	
+	disp.expandstring("text", content, output);
+	if (!queryparams.querystring.empty())
+	  highlighttext(queryresults.termvariants, textout, logout, output);
+	else
+	  textout << text_t2ascii << output;
+   	first = 0;
+	content.clear();
+      }
+
+      thiscontent ++;
+      if (content.size() > 200000 && args["n"] != 1) {
+	content.clear();
+	oversize = 1;
+	args["g"][1] = '0';
+	break;
+      }
+    }
+
+    if (args["g"][1] == '0') {
+      // get docnum from gdbm
+      text_t docref;
+      if (args["d"][0] != 'B') get_book(args["d"], docref);
+      else docref = args["d"];
+      if (gdbm.getinfo(docref, queryparams.collection, info) != 0) {
+        logout << text_t2ascii << "info_db wasn't opened - " << docref << "\n";
+        return;
+      }
+    
+      // get document text if there is any
+      if (info.c.empty()) {
+        search.docTargetDocument(default_index, queryparams.collection,
+                                 info.d, content);
+	if (info.t != "<i>(introductory text)</i>")
+	  content = "<h3>" + info.t + "</h3>\n" + content;
+      }
+    }
+  }
+
+  if (args["n"] != 1) {
+    // get top locator
+    browse->get_top_locator(args, gdbm, oversize, locator);
+
+    // expand and output page 
+    // Note: we need to expand these out using package 'text'
+    // so we can't use the tricky '<<' syntax
+    disp.expandstring("text", "_header_", output);
+    textout << text_t2ascii << output;
+
+    disp.expandstring("text", locator, output);
+    textout << text_t2ascii << output;
+
+    disp.expandstring("text", content, output);
+    if (!queryparams.querystring.empty())
+      highlighttext(queryresults.termvariants, textout, logout, output);
+    else
+      textout << text_t2ascii << output;
+  }
+
+  // get links to next and previous sections unless in expand text mode
+  if (args["g"][1] == '0') {
+    browse->get_links(args, gdbm, links);
+    disp.expandstring("text", links, output);
+    textout << text_t2ascii << output;
+  }
+
+  disp.expandstring("text", "_footer_", output); 
+  textout << text_t2ascii << output;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// page is called when a standard html page is to be displayed
+void libinterface::page_action (cgiargsclass &args, ostream &textout, ostream &logout)
+{
+
+  text_t &arg_p = args["p"];
+
+  prepare_page(args, logout);
+
+  if (arg_p == "preferences")
+    define_pref_macros(args, logout);
+
+  textout << text_t2ascii << disp << ("_" + arg_p + ":header_\n")
+	  << ("_" + arg_p + ":imagestandardbar_\n") << ("_" + arg_p + ":content_\n")
+	  << ("_" + arg_p + ":footer_\n");
+}
+
+// highlighttext highlights query terms in text string and outputs the resulting text string
+void libinterface::highlighttext(vector<text_t> &termvars, ostream &textout, 
+				 ostream &logout, text_t &text) 
+{
+  map<text_t, int, lttext_t> terms;
+  map<text_t, int, lttext_t>::const_iterator it;
+  for (unsigned int i = 0; i < termvars.size(); i++) {
+    terms[termvars[i]] = 1;
+  }
+
+  text_t::iterator here = text.begin(); 
+  text_t::iterator end = text.end();
+  text_t word, buffer;
+  while (here != end) {
+    if (((*here >= 65) && (*here <= 90)) ||
+	((*here >= 97) && (*here <= 122)) ||
+	((*here >= '0') && (*here <= '9')) ||
+	((*here >= 192) && (*here <= 214)) ||
+	((*here >= 216) && (*here <= 246)) ||
+	((*here >= 248) && (*here <= 255))) {
+      // not word boundary
+      word.push_back(*here);
+      here++;
+
+    } else {
+      // found word boundary
+      // add last word if there was one
+      if (!word.empty()) {
+	it = terms.find(word);
+	if (it != terms.end()) {
+	  word = "<b><u>" + word + "</u></b>";
+	}
+	buffer += word;
+        word.clear();
+      }
+
+      if (*here == '<') {
+        // skip over rest of html tag
+	while ((here != end) && (*here != '>')) {
+	  buffer.push_back(*here);
+	  here++;
+	}
+      }
+
+      buffer.push_back(*here);
+      here++;
+
+      if (buffer.size() > 1024) {
+	textout << text_t2ascii << buffer;
+	buffer.clear();
+      }
+    }
+  }
+  textout << text_t2ascii << buffer;
+}
+
+void libinterface::define_pref_macros (cgiargsclass &args, ostream &logout)
+{
+  // the caseoption macro
+  text_t caseoption;
+  int arg_k = args.getintarg("k");
+
+  caseoption += "\n<input type=radio name=k value=1";
+  if (arg_k) caseoption += " checked";
+  caseoption += "> ignore case differences<br>\n";
+  caseoption += "<input type=radio name=k value=0";
+  if (!arg_k) caseoption += " checked";
+  caseoption += "> upper/lower case must match\n";
+
+  disp.setmacro ("caseoption", "preferences", caseoption);
+
+  // the stemoption macro
+  text_t stemoption;
+  int arg_s = args.getintarg("s");
+
+  stemoption += "\n<input type=radio name=s value=1";
+  if (arg_s) stemoption += " checked";
+  stemoption += "> ignore word endings<br>\n";
+  stemoption += "<input type=radio name=s value=0";
+  if (!arg_s) stemoption += " checked";
+  stemoption += "> whole word must match\n";
+
+  disp.setmacro ("stemoption", "preferences", stemoption);
+
+
+  // the maxdocoption
+  text_t maxdocoption;
+  int arg_m = args.getintarg("m");
+
+  maxdocoption += "\n<select name=m>\n";
+  maxdocoption += "  <option value=\"50\"";
+  if (arg_m < 100) maxdocoption += " selected";
+  maxdocoption += ">50\n";
+  maxdocoption += "  <option value=\"100\"";
+  if (arg_m >= 100 && arg_m < 200) maxdocoption += " selected";
+  maxdocoption += ">100\n";
+  maxdocoption += "  <option value=\"200\"";
+  if (arg_m >= 200 && arg_m < 500) maxdocoption += " selected";
+  maxdocoption += ">200\n";
+  maxdocoption += "  <option value=\"500\"";
+  if (arg_m >= 500) maxdocoption += " selected";
+  maxdocoption += ">500\n";
+  maxdocoption += "</select>\n";
+
+  disp.setmacro ("maxdocoption", "preferences", maxdocoption);
+
+  // the hitsperpageoption
+  text_t hitsoption;
+  int arg_o = args.getintarg("o");
+
+  hitsoption += "\n<select name=o>\n";
+  hitsoption += "  <option value=\"10\"";
+  if (arg_o < 20) hitsoption += " selected";
+  hitsoption += ">10\n";
+  hitsoption += "  <option value=\"20\"";
+  if (arg_o >= 20 && arg_o < 50) hitsoption += " selected";
+  hitsoption += ">20\n";
+  hitsoption += "  <option value=\"50\"";
+  if (arg_o >= 50 && arg_o < 100) hitsoption += " selected";
+  hitsoption += ">50\n";
+  hitsoption += "  <option value=\"100\"";
+  if (arg_o >= 100 && arg_o < 500) hitsoption += " selected";
+  hitsoption += ">100\n";
+  hitsoption += "  <option value=\"500\"";
+  if (arg_o >= 500) hitsoption += " selected";
+  hitsoption += ">all\n";
+  hitsoption += "  </select>\n";
+
+  disp.setmacro ("hitsperpageoption", "preferences", hitsoption);
+}
Index: /tags/start/gsdl/src/library/libinterface.h
===================================================================
--- /tags/start/gsdl/src/library/libinterface.h	(revision 13666)
+++ /tags/start/gsdl/src/library/libinterface.h	(revision 13666)
@@ -0,0 +1,146 @@
+#ifndef LIBINTERFACE_H
+#define LIBINTERFACE_H
+
+#include "browse.h"
+#include "queryinfo.h"
+#include "mgsearch.h"
+#include "display.h"
+#include "gdbmclass.h"
+
+#ifdef __GNUG__
+#  include <iostream.h>
+#  include <map>
+#else
+#  ifndef USE_OBJECTSPACE
+#    include <iostream>
+#  else
+#    include <ospace\std\iostream>
+#    include <ospace\std\map>
+#  endif
+#endif
+
+#include "cgiargs.h"
+
+// This is the precedence given to various parameters 
+// by the display class - note that at present language
+// is excluded but will be required for multi-language
+// collections
+#define MACROPRECEDENCE "style,collection,queryversion,version"
+
+
+// errors related to this module
+#define LI_NOERROR            0
+#define LI_LOADDATABASEFAILED 1
+
+
+
+class libinterface
+{
+public:
+  libinterface ();
+  virtual ~libinterface() {}
+
+  // setgsdlhome will set the macros, gdbm, index, and text homes
+  void setgsdlhome (const text_t &thegsdlhome);
+
+  void setmacroshome (const text_t &themacroshome);
+  void setgdbmhome (const text_t &thegdbmhome);
+  void setindexhome (const text_t &theindexhome);
+
+  void sethttpprefix (const text_t &thehttpprefix);
+  void setgwcgi (const text_t &thegwcgi);
+
+  // init should be called after the various homes are set,
+  // it returns 'false' on failure and 'true' on success
+  bool init ();
+  
+  // examine the cgi arguments and create the appropriate page, 
+  // outputing the page to textout and any debug information to logout
+  //
+  // returns LI_NOERROR on success, LI_LOADDATABASEFAILED on failure
+  virtual int getpage (const text_t &argstr, ostream &textout, ostream &logout);
+  
+  // returns the compressed arguments for the last getpage
+  const text_t &getlastcomparg() {return lastcomparg;}
+
+protected:
+  text_t gsdlhome;
+  text_t macroshome;
+  text_t gdbmhome;
+  text_t indexhome;
+
+  text_t books;
+  text_t hrefs;
+  text_t titles;
+  vector<text_t> bookarr;
+  vector<text_t> hrefarr;
+  vector<text_t> titlearr;
+  int numbooks;
+
+  text_t default_index;
+
+  text_t httpprefix;
+  text_t gwcgi;
+  text_t quotedstring;
+
+  text_t lastcomparg;
+
+  gdbmclass gdbm;
+  outconvertclass text_t2ascii;
+  displayclass disp;
+
+
+  browseclass *browse;
+  mgsearchclass search;
+  
+  virtual void get_arg_config (text_t &argconfigstr);
+  text_t::iterator get_next_config_arg (text_t::iterator first, text_t::iterator last,
+					text_t &argname, text_t &defaultvalue, bool &longarg);
+
+  virtual text_t get_compressed_args (cgiargsclass &args);
+  virtual void expand_compressed_args (cgiargsclass &args);
+  virtual void add_default_args (cgiargsclass &args);
+  virtual void check_args (cgiargsclass &args);
+
+  virtual void define_general_macros (cgiargsclass &args, ostream &logout);
+  virtual void prepare_page (cgiargsclass &args, ostream &logout);
+
+
+  virtual void set_query_params (cgiargsclass &args, queryparamclass &queryparams);
+  virtual void define_query_macros (cgiargsclass &args, 
+				    queryparamclass &queryparams,
+				    queryresultsclass &queryresults, 
+				    ostream &logout);
+  virtual void docLinks (cgiargsclass &args, queryresultsclass &queryresults, 
+			 ostream &logout);
+
+  virtual int query_action (cgiargsclass &args, ostream &textout, ostream &logout);
+  virtual void browse_action (cgiargsclass &args, ostream &textout, ostream &logout);
+  virtual void document_action (cgiargsclass &args, ostream &textout, ostream &logout);
+  virtual void page_action (cgiargsclass &args, ostream &textout, ostream &logout);
+  
+  virtual void displayresults (cgiargsclass &args, ostream &textout, ostream &logout,
+			       queryresultsclass &queryresults);
+
+  virtual void define_pref_macros (cgiargsclass &args, ostream &logout);
+  virtual int do_query(cgiargsclass &args, queryparamclass &queryparams, 
+			queryresultsclass &queryresults, ostream &logout);
+  virtual void highlighttext(vector<text_t> &termvars, ostream &textout, 
+			     ostream &logout, text_t &text);
+  void libinterface::format_querystring (text_t &querystring);
+
+
+
+  virtual void set_default_index(void) {}
+  virtual text_t get_collection_name(void) {return "";}
+  virtual void assemble_index (cgiargsclass &args, text_t &index) {}
+  virtual void define_collection_macros (cgiargsclass &args, ostream &logout) {}
+  virtual bool collection_init(const text_t &collection) {return true;}
+  virtual void displaydocsummary (cgiargsclass &args, ostream &textout,
+                                  ostream &logout, queryresultsclass &queryresults,
+								  int resultnum) {}
+
+
+};
+
+#endif
Index: /tags/start/gsdl/src/library/locateinfo.cpp
===================================================================
--- /tags/start/gsdl/src/library/locateinfo.cpp	(revision 13666)
+++ /tags/start/gsdl/src/library/locateinfo.cpp	(revision 13666)
@@ -0,0 +1,60 @@
+#include "locateinfo.h"
+
+void getindexsuffix (const text_t &index,
+		     const text_t &collection,
+		     text_t &ttidxsuffix)
+{
+  ttidxsuffix = "collect";
+
+#ifdef __WIN32__
+  ttidxsuffix += "\\";
+#else
+  ttidxsuffix += "/";
+#endif
+
+  ttidxsuffix += collection;
+
+#ifdef __WIN32__
+  ttidxsuffix += "\\index\\";
+#else
+  ttidxsuffix += "/index/";
+#endif
+
+//           ttidxsuffix += collection; //this changed with new build software
+  ttidxsuffix += index;
+#ifdef __WIN32__
+  ttidxsuffix += "\\";
+#else
+  ttidxsuffix += "/";
+#endif
+  ttidxsuffix += collection;
+}
+
+void gettextsuffix (const text_t &collection, 
+		    text_t &tttxtsuffix)
+{
+  tttxtsuffix = "collect";
+
+#ifdef __WIN32__
+  tttxtsuffix += "\\";
+#else
+  tttxtsuffix += "/";
+#endif
+
+  tttxtsuffix += collection;
+
+#ifdef __WIN32__
+  tttxtsuffix += "\\index\\";
+#else
+  tttxtsuffix += "/index/";
+#endif
+
+//                tttxtsuffix += collection; // path changed with new building software - Stefan.
+  tttxtsuffix += "text";
+#ifdef __WIN32__
+  tttxtsuffix += "\\";
+#else
+  tttxtsuffix += "/";
+#endif
+  tttxtsuffix += collection;
+}
Index: /tags/start/gsdl/src/library/locateinfo.h
===================================================================
--- /tags/start/gsdl/src/library/locateinfo.h	(revision 13666)
+++ /tags/start/gsdl/src/library/locateinfo.h	(revision 13666)
@@ -0,0 +1,13 @@
+#ifndef LOCATEINFO_H
+#define LOCATEINFO_H
+
+#include "text_t.h"
+
+void getindexsuffix (const text_t &index,
+		     const text_t &collection,
+		     text_t &ttidxsuffix);
+
+void gettextsuffix (const text_t &collection, 
+		    text_t &tttxtsuffix);
+
+#endif
Index: /tags/start/gsdl/src/library/mgq.c
===================================================================
--- /tags/start/gsdl/src/library/mgq.c	(revision 13666)
+++ /tags/start/gsdl/src/library/mgq.c	(revision 13666)
@@ -0,0 +1,347 @@
+/* cut-down version of mgquery */
+
+
+#include <stdio.h>
+#include <string.h>
+/* #include <io.h> */
+#include <fcntl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  
+#include "sysfuncs.h"
+  
+#include "messages.h"
+#include "memlib.h"
+  
+#include "invf.h"
+#include "text.h"
+#include "mg.h"
+#include "lists.h"
+#include "backend.h"
+#include "environment.h"
+#include "globals.h"
+#include "mg_errors.h"
+#include "commands.h"
+#include "text_get.h"
+#include "term_lists.h"
+#include "local_strings.h"
+  
+#ifdef __cplusplus
+}
+#endif
+
+
+#include "mgq.h"
+
+/* globals needed by some vague part of mg... */
+FILE *OutFile = NULL, *InFile = NULL;
+int OutPipe = 0, InPipe = 0;
+int Quitting = 0;
+
+static query_data *qd;
+char db_loaded_name[256] = "";
+
+#if defined(PARADOCNUM) ||  defined(NZDL)
+int *Paragraph = NULL;
+int Documents = 0;
+
+int GetDocNumFromParaNum(int paranum)
+{
+  int low = 1, high = Documents;
+  int mid = (low+high)/2;
+
+  while ((mid = (low+high)/2) >=1 && mid <= Documents)
+    {
+      if (paranum > Paragraph[mid])
+        low = mid+1;
+      else if (paranum <= Paragraph[mid-1])
+        high = mid-1;
+      else
+        return mid;
+    }
+  FatalError(1, "Bad paragraph number.\n");
+  return 0;
+}
+#endif
+
+
+/*****************************************************************************/
+
+static void MGQError(char *emsg)
+{
+  fprintf(stderr,"Fatal error: %s\n", emsg);
+  exit(1);
+}
+
+static int ProcessDocs (query_data * qd, int num, int skip, int howmany, int verbatim,
+			enum result_kinds kind, FILE * Output,
+			int (*sender)(char *,int,int,float,void *), void *ptr)
+{
+  int max_buf = 0, output_failure = 0;
+  int DocCount = 0;
+  int need_text = (kind == result_docs);
+  
+  for (;;) {
+    if (skip <= 0) break;
+    skip--;
+    if (!NextDoc(qd)) return 0;
+  }
+  
+  if (need_text)
+    {
+      max_buf = atoi (GetDefEnv ("buffer", "1048576"));
+    }
+  
+  do
+    {
+      u_char *UDoc = NULL;
+      unsigned long ULen;
+      
+      if (need_text)
+	{
+	  /* load the compressed text */
+	  if (LoadCompressedText (qd, max_buf))
+	    {
+	      MGQError("Unable to load compressed text(memory?).");
+	    }
+	  /* uncompress the loaded text */
+	  UDoc = GetDocText (qd, &ULen);
+	  if (UDoc == NULL)
+	    MGQError("UDoc is unexpectedly NULL");
+	}
+      
+      if (UDoc != NULL  ||  kind == result_docnums)
+	{
+	  int docnum = GetDocNum(qd);
+#if defined(PARADOCNUM) ||  defined(NZDL)
+	  if (qd->id->ifh.InvfLevel == 3) docnum = GetDocNumFromParaNum(docnum);
+#endif
+	  switch (kind)
+	    {
+	    case result_docnums:
+	      if (sender != NULL)
+		output_failure = (*sender)("",0,docnum,GetDocWeight(qd),ptr);
+	      break;
+	    case result_docs:
+	      if (sender != NULL)
+		output_failure = (*sender)(UDoc,ULen,docnum,GetDocWeight(qd),ptr);
+	      break;
+	    default:
+	      break;
+	    }
+	}
+      DocCount++;
+      
+    }
+  while (NextDoc (qd) && output_failure == 0 && --howmany > 0);
+  
+  if (need_text)
+    {
+      FreeTextBuffer (qd);
+    }
+  
+  return (DocCount);
+}
+
+
+void
+send_query_term_freqs(QueryTermList *qtl,
+		      int (*sender)(char *,int,int,float,void *), void *ptr)
+{
+  int i;  char *word;
+  for (i = 0; i < qtl->num; i++)
+    if (sender != NULL) {
+      word = word2str(qtl->QTE[i].Term);
+      (* sender)(word, strlen(word), qtl->QTE[i].Count, (float)0.0, ptr);
+    }
+}
+
+
+void
+send_terms (TermList * qtl, int (*sender)(char *,int,int,float,void *), void *ptr)
+{
+  int i = 0;
+  char *word;
+
+  if (sender == NULL) return;
+  for (i = 0; i < qtl->num; i++)
+    {
+      word = word2str(qtl->TE[i].Word);
+      (* sender)(word, strlen(word), qtl->TE[i].Count, (float)0.0, ptr);
+    }
+}
+
+
+/* MoreDocs () */
+/* Displays all documents in list  DocList. */
+/* Documents are fetched, then decompressed and displayed according to the */
+/* format implied in  FormString(). */
+
+static void
+MoreDocs (query_data * qd, enum result_kinds kind, 
+	  int skip, int howmany,
+	  int (*sender)(char *,int,int,float,void *), void *ptr)
+{
+  qd->num_of_ans = qd->DL->num;
+  switch (kind) {
+  case result_docs:
+  case result_docnums:
+    if (qd->num_of_ans > 0)
+      ProcessDocs (qd, qd->DL->num, skip, howmany,
+		   BooleanEnv (GetEnv ("verbatim"), 1),
+		   kind, NULL, sender, ptr);
+    break;
+  case result_termfreqs:
+    send_query_term_freqs(qd->QTL, sender, ptr);
+    break;
+  case result_terms:
+    send_terms(qd->TL, sender, ptr);
+    break;
+  }
+}
+
+
+int mgq_init(char *mgdir, char *gensuffix, char *textsuffix)
+{
+  /* Initialise the environment with default values */
+  InitEnv ();
+  
+  SetEnv("mgdir",mgdir,NULL);
+  SetEnv("mgname",gensuffix,NULL);
+  SetEnv("textname",textsuffix,NULL);
+  
+  PushEnv ();
+  
+  qd = InitQuerySystem (GetDefEnv ("mgdir", ""),
+			GetDefEnv ("mgname", ""),
+			GetDefEnv ("textname", NULL),
+			NULL);
+  
+  if (qd == NULL) return 0;  else return 1;
+}
+
+int mgq_ask(char *line)
+{
+  char QueryType;  char OutputType;  char *LinePtr;
+  
+  ResetFileStats (qd);
+  qd->max_mem_in_use = qd->mem_in_use = 0;
+  qd->tot_hops_taken += qd->hops_taken;
+  qd->tot_num_of_ptrs += qd->num_of_ptrs;
+  qd->tot_num_of_accum += qd->num_of_accum;
+  qd->tot_num_of_terms += qd->num_of_terms;
+  qd->tot_num_of_ans += qd->num_of_ans;
+  qd->tot_text_idx_lookups += qd->text_idx_lookups;
+  qd->hops_taken = qd->num_of_ptrs = 0;
+  qd->num_of_accum = qd->num_of_ans = qd->num_of_terms = 0;
+  qd->text_idx_lookups = 0;
+  
+  LinePtr = ProcessCommands (line, qd);
+  if (CommandsErrorStr) {
+    fprintf (stderr, "%s\n", CommandsErrorStr);
+    return 0;
+  }
+  if (*LinePtr == '\0') return 1;
+  
+  FreeQueryDocs (qd);
+  
+  QueryType = get_query_type ();
+  OutputType = get_output_type ();
+  /* No point in hiliting words on a docnum query */
+  if (OutputType == OUTPUT_HILITE && QueryType == QUERY_DOCNUMS)
+    OutputType = OUTPUT_TEXT;
+  
+  switch (QueryType)
+    {
+    case QUERY_BOOLEAN:
+      {
+	char *maxdocs;
+	BooleanQueryInfo bqi;
+	maxdocs = GetDefEnv ("maxdocs", "all");
+	bqi.MaxDocsToRetrieve = strcmp (maxdocs, "all") ? atoi (maxdocs) : -1;
+        if (qd->sd->sdh.indexed)
+	  BooleanQuery (qd, line, &bqi, (BooleanEnv (GetEnv ("casefold"), 0) |
+					 (BooleanEnv (GetEnv ("stem"), 0) << 1)));
+	else
+	  BooleanQuery (qd, line, &bqi, qd->sd->sdh.stem_method);
+	/*	if (qd->sd->sdh.indexed) BooleanQuery (qd, line, &bqi, 3);
+	else BooleanQuery (qd, line, &bqi, qd->sd->sdh.stem_method); */
+	break;
+      }
+    case QUERY_APPROX:
+    case QUERY_RANKED:
+      {
+	char *maxdocs;
+	char *maxterms;
+	char *maxaccum;
+	RankedQueryInfo rqi;
+	maxdocs = GetDefEnv ("maxdocs", "all");
+	maxterms = GetDefEnv ("max_terms", "all");
+	maxaccum = GetDefEnv ("max_accumulators", "all");
+	rqi.Sort = BooleanEnv (GetEnv ("sorted_terms"), 0);
+	rqi.QueryFreqs = BooleanEnv (GetEnv ("qfreq"), 1);
+	rqi.Exact = QueryType == QUERY_RANKED;
+	rqi.MaxDocsToRetrieve = strcmp (maxdocs, "all") ? atoi (maxdocs) : -1;
+	rqi.MaxTerms = strcmp (maxterms, "all") ? atoi (maxterms) : -1;
+	rqi.MaxParasToRetrieve = rqi.MaxDocsToRetrieve;
+	if (qd->id->ifh.InvfLevel == 3 && GetEnv ("maxparas"))
+	  rqi.MaxParasToRetrieve = atoi (GetEnv ("maxparas"));
+	rqi.AccumMethod = toupper (*GetDefEnv ("accumulator_method", "A"));
+	rqi.MaxAccums = strcmp (maxaccum, "all") ? atoi (maxaccum) : -1;
+	rqi.HashTblSize = IntEnv (GetEnv ("hash_tbl_size"), 1000);
+	rqi.StopAtMaxAccum = BooleanEnv (GetEnv ("stop_at_max_accum"), 0);
+	rqi.skip_dump = GetEnv ("skip_dump");
+	RankedQuery (qd, line, &rqi);
+	break;
+      }
+    case QUERY_DOCNUMS:
+      {
+	DocnumsQuery (qd, line);
+	break;
+      }
+    }
+
+  return 1;
+}
+
+int mgq_numdocs(void)
+{
+  if (qd->DL) return qd->DL->num;
+  else return 0;
+}
+
+int mgq_numterms(void)
+{
+  if (qd->QTL) return qd->QTL->num;
+  else return 0;
+}
+
+int mgq_results(enum result_kinds kind,int skip,int howmany, int (*sender)(char *, int, int, float, void *), void *ptr)
+{
+  if (qd->DL) {
+    qd->doc_pos = 0;
+    MoreDocs(qd, kind, skip, howmany, sender, ptr);
+  }
+  return 0;
+}
+
+
+void mgq_finish(void)
+{
+  FinishQuerySystem(qd);
+  UninitEnv ();
+}
+
+int load_database(char *mgdir, char *gensuffix, char *textsuffix)
+{
+  if ((db_loaded_name[0]) != '\0' && (strcmp(gensuffix,db_loaded_name) != 0)) {
+    mgq_finish();
+    db_loaded_name[0] = '\0';
+  }
+  if ((db_loaded_name[0] == '\0') && mgq_init(mgdir, gensuffix, textsuffix)) {
+    strcpy(db_loaded_name, gensuffix);
+  }
+  return (db_loaded_name[0] != '\0');
+}
Index: /tags/start/gsdl/src/library/mgq.h
===================================================================
--- /tags/start/gsdl/src/library/mgq.h	(revision 13666)
+++ /tags/start/gsdl/src/library/mgq.h	(revision 13666)
@@ -0,0 +1,25 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum result_kinds {
+	result_docs,      /* Return the documents found in last search */
+	result_docnums,   /* Return document id numbers and weights */
+	result_termfreqs, /* Return terms and frequencies */
+	result_terms      /* Return matching query terms */
+    };
+
+int mgq_ask(char *line);
+int mgq_results(enum result_kinds kind,int skip, int howmany, int (*sender)(char *, int, int, float, void *), void *ptr);
+int mgq_numdocs(void);
+int mgq_numterms(void);
+int load_database(char *mgdir, char *gensuffix, char *textsuffix);
+
+/* this will equal "" when a database is not loaded */
+/* if a database is loaded it will equal its gensuffix */
+extern char db_loaded_name[256];
+
+
+#ifdef __cplusplus
+}
+#endif
Index: /tags/start/gsdl/src/library/mgsearch.cpp
===================================================================
--- /tags/start/gsdl/src/library/mgsearch.cpp	(revision 13666)
+++ /tags/start/gsdl/src/library/mgsearch.cpp	(revision 13666)
@@ -0,0 +1,467 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#ifdef __GNUG__
+#  include <iostream.h>
+#  include <gdbm.h>
+
+#else
+#  ifndef USE_OBJECTSPACE
+#    include <iostream>
+#  else
+#    include <ospace\std\iostream>
+#  endif
+
+// gdbm stuff
+#  include "autoconf.h"
+#  include "systems.h"
+#  include "gdbmconst.h"
+#  include "gdbm.h"
+#endif
+  
+#include <assert.h>
+
+#include "mgq.h"
+#include "mgsearch.h"
+#include "locateinfo.h"
+
+/////////////
+// globals //
+/////////////
+
+static char *quotedquery = NULL;
+
+
+
+////////////////////////
+// callback functions //
+////////////////////////
+
+// This routine is called for each document found in a search
+// it assumes that cache_num is set up correctly to point to
+// a suitable result cache
+int ourquerycallback(char *UDoc, int ULen, int DocNum, 
+		     float Weight, void *info) {
+
+  
+  queryresultsclass *queryresults = (queryresultsclass * )info;
+
+  // check the returned document for the presence of the
+  // quoted part of the query, if there was one
+ 
+  if (UDoc != NULL && quotedquery != NULL &&
+      quotedquery[0] != '\0' && strstr (UDoc, quotedquery) == NULL) return 0;
+  
+  // append this entry to the document results
+  docresultclass docresult;
+  docresult.docnum = DocNum;
+  docresult.docweight = Weight;
+
+  queryresults->docs.push_back(docresult);
+  
+  return 0;
+}
+
+// This callback is called once for each term in the query
+int termfreqcallback(char *Word, int ULen,  int Freq, 
+		     float Weight,  void *info) {
+  queryresultsclass *queryresults = (queryresultsclass *)info;
+
+  termfreqclass termfreq;
+  termfreq.termstr.setcarr(Word, ULen);
+  termfreq.termfreq = Freq;
+  queryresults->terms.push_back(termfreq);
+  
+  return 0;
+}
+
+// this callback is called once for each variation of each term
+int termscallback(char *Word, int ULen, int Freq,
+		  float Weight, void *info) {
+
+  queryresultsclass *queryresults = (queryresultsclass *)info;
+  queryresults->termvariants.push_back(Word);
+
+  return 0;
+}
+
+// This callback is for getting document text
+int doctextcallback(char *Word, int ULen,  int Freq, 
+		    float Weight,  void *info) {
+  text_t *output = (text_t *)info;
+  if (output == NULL) return 0;
+
+  output->setcarr(Word, ULen);
+  
+  // replace all control-Cs with spaces
+  text_t::iterator here = output->begin();
+  text_t::iterator end = output->end();
+  while (here != end)
+    {
+      if (*here == '\x3') *here = ' ';
+      here++;
+    }
+  
+  return 0;
+}
+
+
+
+////////////////////
+// mgsearch class //
+////////////////////
+
+mgsearchclass::mgsearchclass ()
+{
+  cache = new querycache (RESULTCACHESIZE);
+}
+
+mgsearchclass::~mgsearchclass () 
+{
+  if (cache != NULL) 
+    {
+      delete cache;
+      cache = NULL;
+    }
+}
+
+
+void mgsearchclass::setindexhome (const text_t &theindexhome)
+{
+  indexhome = theindexhome;
+}
+
+
+bool mgsearchclass::search(const queryparamclass &queryparams, 
+		      queryresultsclass &queryresults)
+{
+  bool databaseloaded = true;
+
+  assert (cache != NULL);
+
+  queryresults.clear();
+
+  // first check the cache
+  if (cache->find(queryparams, queryresults))
+    {
+      return true;
+    }
+
+  // make sure there is a query to be processed
+  text_t::const_iterator queryhere = queryparams.querystring.begin();
+  text_t::const_iterator queryend = queryparams.querystring.end();
+  while (queryhere != queryend) {
+    if (((*queryhere >= 65) && (*queryhere <= 90)) ||
+      ((*queryhere >= 97) && (*queryhere <= 122)) ||
+      ((*queryhere >= 192) && (*queryhere <= 214)) ||
+      ((*queryhere >= 216) && (*queryhere <= 246)) ||
+      ((*queryhere >= 248) && (*queryhere <= 255)) ||
+      ((*queryhere >= '0') && (*queryhere <= '9'))) break;
+    queryhere++;
+  }
+
+  // if we reached the end of the query string without finding
+  // any alphanumeric characters then return no results (and say
+  // the database was loaded)
+  if (queryhere == queryend) return true;
+
+
+
+  // get the names of the index and text suffixes
+  text_t ttidxsuffix, tttxtsuffix;
+  getindexsuffix (queryparams.search_index, 
+		  queryparams.collection, ttidxsuffix);
+  gettextsuffix (queryparams.collection, tttxtsuffix);
+  char *idxsuffix = ttidxsuffix.getcstr(); assert (idxsuffix != NULL);
+  char *txtsuffix = tttxtsuffix.getcstr(); assert (txtsuffix != NULL);
+
+#ifdef __WIN32__
+  char *cindexhome = (indexhome+"\\").getcstr(); assert (cindexhome != NULL);
+#else
+  char *cindexhome = indexhome.getcstr(); assert (cindexhome != NULL);
+#endif
+
+  if (load_database(cindexhome, idxsuffix, txtsuffix))
+    {
+      setsearchmode (queryparams);
+      submitquery (queryparams);
+      getresults (queryresults);
+    }
+  else databaseloaded = false;
+
+  // free up the c strings
+  delete idxsuffix;
+  delete txtsuffix;
+  delete cindexhome;
+
+  return databaseloaded;
+}
+
+
+void mgsearchclass::setsearchmode (const queryparamclass &queryparams)
+{
+  mgq_ask(".set expert true");
+  mgq_ask(".set accumulator_method list");
+  mgq_ask(".set max_accumulators 50000");
+  mgq_ask(".set verbatim true");
+  mgq_ask(".unset skip_dump");
+  mgq_ask(".set mode docnums");
+
+  switch (queryparams.search_type) 
+    {
+    case 0: mgq_ask(".set query boolean");  break;
+    case 1:  mgq_ask(".set query ranked"); break;
+    }
+  switch (queryparams.casefolding) 
+    {
+    case 1: mgq_ask(".set casefold on");  break;
+    case 0: mgq_ask(".set casefold off"); break;
+    }
+  switch (queryparams.stemming) 
+    {
+    case 1: mgq_ask(".set stem on");  break;
+    case 0: mgq_ask(".set stem off"); break;
+    }
+  mgq_ask(".set heads_length 150");
+  
+  char maxdocstr[32];
+  sprintf(maxdocstr, ".set maxdocs %i", queryparams.maxdocs);
+  mgq_ask(maxdocstr);
+}
+
+
+void mgsearchclass::submitquery (const queryparamclass &queryparams)
+{
+  // sort out the query string
+  text_t ttquerystring = queryparams.querystring;
+  text_t ttquotedquery;
+  extractquoted (ttquerystring, ttquotedquery);
+  filterquery (ttquerystring);
+  
+  // turn the strings into c strings for mg
+  if (quotedquery != NULL) // quotedquery is a global
+    {
+      delete quotedquery;
+      quotedquery = NULL;
+    }
+
+  // quotedquery will be deleted on the next call to this function
+  quotedquery = ttquotedquery.getcstr ();
+  char *querystring = ttquerystring.getcstr();
+  
+  // submit the query
+  mgq_ask(querystring);
+
+  delete querystring;
+}
+
+
+void mgsearchclass::getresults (queryresultsclass &queryresults)
+{
+  if (quotedquery[0] == '\0') 
+    { 
+      // don't need the text
+      mgq_results(result_docnums, 0, MAXNUMDOCS, 
+		  ourquerycallback, (void *)(&queryresults));
+    }
+  else
+    {
+      // we need the text for this one
+      mgq_results(result_docs, 0, MAXNUMDOCS, 
+		  ourquerycallback, (void *)(&queryresults));
+    }
+  
+  // get the term frequencies
+  mgq_results(result_termfreqs, 0, MAXNUMTERMS, 
+	      termfreqcallback, (void *)(&queryresults));
+  mgq_results(result_terms, 0, MAXNUMTERMS,
+              termscallback, (void *)(&queryresults));
+  queryresults.sortqueryterms();
+  queryresults.uniqqueryterms();
+}
+
+
+void mgsearchclass::extractquoted (text_t &ttquerystring, text_t &ttquotedquery)
+{
+  ttquotedquery.clear();
+
+  text_t::iterator ithere = ttquerystring.begin ();
+  text_t::iterator itend = ttquerystring.end ();
+
+  bool inquote = false;
+
+  while (ithere != itend)
+    {
+      if ((*ithere) == '\"')
+	{
+	  if (!inquote) ttquotedquery.clear ();
+	  inquote = !inquote;
+	  *ithere = ' '; // delete the quote
+	}
+      else if (inquote)
+	{
+	  ttquotedquery.push_back(*ithere);
+	  *ithere = ' ';
+	}
+      
+      ithere++;
+    }
+}
+
+
+void mgsearchclass::filterquery (text_t &ttquerystring)
+{
+
+  text_t::iterator ithere = ttquerystring.begin ();
+  text_t::iterator itend = ttquerystring.end ();
+  unsigned short c;
+
+  // remove all non alphanumeric characters below 127
+  while (ithere != itend)
+    {
+      c = *ithere;
+
+      //      if ((c <= 127) && !((c >= '0' && c <= '9') ||
+      //			  (c >= 'A' && c <= 'Z') ||
+      //			  (c >= 'a' && c <= 'z')))
+      if (!(((c >= 65) && (c <= 90)) ||
+	    ((c >= 97) && (c <= 122)) ||
+	    ((c >= 192) && (c <= 214)) ||
+	    ((c >= 216) && (c <= 246)) ||
+	    ((c >= 248) && (c <= 255)) ||
+	    ((c >= '0') && (c <= '9')) ||
+	    (c == 176)))
+	(*ithere) = ' ';
+      
+      ithere++;
+    }
+}
+
+
+// the document text for 'docnum' is placed in 'output'
+// docTargetDocument returns 'true' if it was able to
+// try to get a document
+// collection is needed to see if an index from the 
+// collection is loaded. If no index has been loaded
+// defaultindex is needed to load one
+bool mgsearchclass::docTargetDocument(const text_t &defaultindex, 
+				 const text_t &collection,
+				 int docnum,
+				 text_t &output)
+{
+  bool databaseloaded = true;
+
+  output.clear();
+
+
+  // make sure index is level 2
+
+  ////// this changed with new naming scheme in new building software
+  /////  i.e paragraph level index no longer contain number '3' but begin
+  /////  with letter 'p'
+
+  text_t db_loaded = db_loaded_name;
+
+  if (!db_loaded.empty()) {
+	  text_t::const_iterator here = db_loaded.begin();
+	  text_t::const_iterator end = db_loaded.end();
+  
+	  
+	  //while (here != end) {
+	  //  if (*here == '3')
+	  //    databaseloaded = false;
+	  //  here ++;
+	  //}
+
+	  char separator = '/';
+	  text_t db;
+	  int found = 0;
+#ifdef __WIN32__
+	  separator = '\\';
+#endif;
+	  // strip away path to db and following collection name
+	  end --;
+	  while (end != here) {
+		  if (*end == separator) {
+			  if (found) break;
+			  else {db.clear(); found = 1; end--; continue;}
+		  }
+		  db.push_back(*end);
+		  end --;
+	  }
+
+	  // string will have been reversed above so see if last 
+	  // character is 'p'
+	  if (db[db.size()-1] == 'p') databaseloaded = false;
+  }
+
+  // find out if the database is already loaded
+  // this is needed because a different index (but valid one)
+  // might be already loaded.
+  // this comparison is needed because 'load_database'
+  // is now more oriented towards indexes
+  if (databaseloaded == true) {
+	  text_t::const_iterator here = collection.begin();
+	  text_t::const_iterator end = collection.end();
+	  char *dbhere = &db_loaded_name[strlen(db_loaded_name) - collection.size()]; // assumes collection shorter than db_loaded_name
+	  while (here != end)
+	  {
+		  if (*here != *dbhere)
+		  {
+			  databaseloaded = false;
+			  break;
+		  }
+		  here++;
+		  dbhere++;
+	  }
+  }
+
+  // try and load the database
+  if (!databaseloaded)
+    {
+      // get the names of the index and text suffixes
+      text_t ttidxsuffix, tttxtsuffix;
+      getindexsuffix (defaultindex, collection, ttidxsuffix);
+      gettextsuffix (collection, tttxtsuffix);
+	  char *idxsuffix = ttidxsuffix.getcstr(); assert (idxsuffix != NULL);
+      char *txtsuffix = tttxtsuffix.getcstr(); assert (txtsuffix != NULL);
+
+#ifdef __WIN32__
+      char *cindexhome = (indexhome+"\\").getcstr(); assert (cindexhome != NULL);
+#else
+      char *cindexhome = indexhome.getcstr(); assert (cindexhome != NULL);
+#endif
+      
+
+      if (load_database(cindexhome, idxsuffix, txtsuffix))
+	{
+	  databaseloaded = true;
+	}
+      else 
+	{
+	  databaseloaded = false;
+	}
+	  
+      // free up the c strings
+      delete idxsuffix;
+      delete txtsuffix;
+      delete cindexhome;
+    }
+  
+  if (databaseloaded)
+    {
+      // retrieve the document from mg
+      char docstr[32];
+      sprintf(docstr, "%i", docnum);
+
+      mgq_ask(".set mode text");
+      mgq_ask(".set query docnums");
+      mgq_ask(docstr);
+      mgq_results (result_docs, 0, 1, doctextcallback, (void *)&output);
+    }
+
+  return databaseloaded;
+}
+
Index: /tags/start/gsdl/src/library/mgsearch.h
===================================================================
--- /tags/start/gsdl/src/library/mgsearch.h	(revision 13666)
+++ /tags/start/gsdl/src/library/mgsearch.h	(revision 13666)
@@ -0,0 +1,51 @@
+#ifndef MGSEARCH_H
+#define MGSEARCH_H
+
+
+#include "text_t.h"
+#include "querycache.h"
+
+#define RESULTCACHESIZE 10
+#define MAXNUMDOCS      500
+#define MAXNUMTERMS     100
+
+class mgsearchclass
+{
+public:
+  mgsearchclass ();
+  virtual ~mgsearchclass ();
+  
+  // the index directory must be set before any searching
+  // is done
+  void setindexhome (const text_t &theindexhome);
+  
+  // the search results are returned in queryresults
+  // search returns 'true' if it was able to do a search
+  bool search(const queryparamclass &queryparams, 
+	      queryresultsclass &queryresults);
+  
+  // the document text for 'docnum' is placed in 'output'
+  // docTargetDocument returns 'true' if it was able to
+  // try to get a document
+  // collection is needed to see if an index from the 
+  // collection is loaded. If no index has been loaded
+  // defaultindex is needed to load one
+  bool docTargetDocument(const text_t &defaultindex, 
+			 const text_t &collection,
+			 int docnum,
+			 text_t &output);
+  
+protected:
+  querycache *cache;
+  text_t indexhome; // top level directory for indexes
+
+  void setsearchmode (const queryparamclass &queryparams);
+  void submitquery (const queryparamclass &queryparams);
+  void getresults (queryresultsclass &queryresults);
+
+  virtual void extractquoted (text_t &ttquerystring, text_t &ttquotedquery);
+  virtual void filterquery (text_t &ttquerystring);
+};
+
+#endif
+
Index: /tags/start/gsdl/src/library/querycache.cpp
===================================================================
--- /tags/start/gsdl/src/library/querycache.cpp	(revision 13666)
+++ /tags/start/gsdl/src/library/querycache.cpp	(revision 13666)
@@ -0,0 +1,77 @@
+#include "querycache.h"
+
+
+
+resultcacheel::resultcacheel () 
+{
+  accessnum = -1;
+}
+
+
+
+querycache::querycache (int themaxcachesize)
+{
+  if (themaxcachesize < 1) themaxcachesize = 1;
+  
+  resultcache = new resultcacheel[themaxcachesize];
+
+  maxcachesize = themaxcachesize;
+  nextaccessnum = 1;
+}
+
+querycache::~querycache ()
+{
+  delete [] resultcache;
+}
+
+// returns true if the query was found in the cache
+// if the query was found then queryresults contains
+// the results
+bool querycache::find (const queryparamclass &queryparams, 
+		       queryresultsclass &queryresults)
+{
+  int i;
+
+  for (i=0; i < maxcachesize; i++)
+    {
+      if (resultcache[i].queryparameters == queryparams)
+	{
+	  queryresults = resultcache[i].queryresults;
+	  resultcache[i].accessnum = getnextaccessnum ();
+	  return true;
+	}
+    }
+
+  return false;
+}
+
+
+void querycache::cache (const queryparamclass &queryparams,
+	  const queryresultsclass &queryresults)
+{
+  int i = getfreecachenum();
+  resultcache[i].queryparameters = queryparams;
+  resultcache[i].queryresults = queryresults;
+  resultcache[i].accessnum = getnextaccessnum ();
+}
+
+int querycache::getnextaccessnum ()
+{
+  return nextaccessnum++;
+}
+
+int querycache::getfreecachenum ()
+{
+  int i;
+  int minaccessnum = 0;
+  int minaccessi = 0;
+  
+  for (i=0; i < maxcachesize; i++)
+    {
+      if (resultcache[i].accessnum < minaccessnum)
+	minaccessi = i;
+    }
+
+  return i;
+}
+
Index: /tags/start/gsdl/src/library/querycache.h
===================================================================
--- /tags/start/gsdl/src/library/querycache.h	(revision 13666)
+++ /tags/start/gsdl/src/library/querycache.h	(revision 13666)
@@ -0,0 +1,44 @@
+#ifndef QUERYCACHE_H
+#define QUERYCACHE_H
+
+#include "text_t.h"
+#include "queryinfo.h"
+
+class resultcacheel
+{
+public:
+  resultcacheel ();
+
+  int accessnum;
+  queryparamclass queryparameters;
+  queryresultsclass queryresults;
+};
+
+
+class querycache {
+public:
+  querycache (int themaxcachesize);
+  ~querycache ();
+
+  // returns true if the query was found in the cache
+  // if the query was found then queryresults contains
+  // the results
+  bool find (const queryparamclass &queryparams, 
+	     queryresultsclass &queryresults);
+
+  void cache (const queryparamclass &queryparams,
+	    const queryresultsclass &queryresults);
+
+protected:
+  resultcacheel *resultcache;
+
+  int maxcachesize;
+  int nextaccessnum;
+  
+  int getnextaccessnum ();
+  int getfreecachenum ();
+};
+
+
+
+#endif
Index: /tags/start/gsdl/src/library/queryinfo.cpp
===================================================================
--- /tags/start/gsdl/src/library/queryinfo.cpp	(revision 13666)
+++ /tags/start/gsdl/src/library/queryinfo.cpp	(revision 13666)
@@ -0,0 +1,170 @@
+#include "queryinfo.h"
+
+
+// query parameters
+
+queryparamclass &queryparamclass::operator=(const queryparamclass &q)
+{
+  collection = q.collection;
+  search_index = q.search_index;
+  querystring = q.querystring;
+  search_type = q.search_type;
+  casefolding = q.casefolding;
+  stemming = q.stemming;
+  maxdocs = q.maxdocs;
+
+  return *this;
+}
+
+
+bool operator==(const queryparamclass &x, const queryparamclass &y)
+{
+  return ((x.collection == y.collection) &&
+	  (x.search_index == y.search_index) &&
+	  (x.querystring == y.querystring) &&
+	  (x.search_type == y.search_type) &&
+	  (x.casefolding == y.casefolding) &&
+	  (x.stemming == y.stemming) &&
+	  (x.maxdocs == y.maxdocs));
+}
+
+bool operator!=(const queryparamclass &x, const queryparamclass &y)
+{
+  return !(x == y);
+}
+
+
+ostream &operator<< (ostream &outs, queryparamclass &q)
+{
+  outconvertclass text_t2ascii;
+
+  outs << "*** queryparamclass\n";
+  outs << text_t2ascii << " collection = \"" << q.collection << "\"\n";
+  outs << text_t2ascii << " search_index = \"" << q.search_index << "\"\n";
+  outs << text_t2ascii << " querystring = \"" << q.querystring << "\"\n";
+  outs << " search_type = \"" << q.search_type << "\"\n";
+  outs << " casefolding = \"" << q.casefolding << "\"\n";
+  outs << " stemming = \"" << q.stemming << "\"\n";
+  outs << " maxdocs = \"" << q.maxdocs << "\"\n";
+  outs << "\n";
+
+  return outs;
+}
+
+
+
+
+// term frequencies
+
+termfreqclass &termfreqclass::operator=(const termfreqclass &t) 
+{
+  termstr = t.termstr;
+  termfreq = t.termfreq;
+
+  return *this;
+}
+	
+bool operator==(const termfreqclass &x, const termfreqclass &y)
+{
+  return ((x.termstr == y.termstr) &&
+	  (x.termfreq == y.termfreq));
+}
+
+bool operator!=(const termfreqclass &x, const termfreqclass &y)
+{
+  return !(x == y);
+}
+
+// ordered by termfreq and then by termstr
+bool operator<(const termfreqclass &x, const termfreqclass &y)
+{
+  return ((x.termfreq < y.termfreq) ||
+	  ((x.termfreq == y.termfreq) && (x.termstr < y.termstr)));
+
+}
+
+bool operator>(const termfreqclass &x, const termfreqclass &y)
+{
+  return ((x.termfreq > y.termfreq) ||
+	  ((x.termfreq == y.termfreq) && (x.termstr > y.termstr)));
+
+}
+
+// stream output for debugging purposes
+ostream &operator<< (ostream &outs, termfreqclass &t)
+{
+  outconvertclass text_t2ascii;
+
+  outs << text_t2ascii << " t:\"" << t.termstr << "\"";
+  outs << " f:" << t.termfreq << "\n";
+
+  return outs;
+}
+
+
+
+// one query result
+
+// stream output for debugging purposes
+ostream &operator<< (ostream &outs, docresultclass &a)
+{
+  outs << " d:" << a.docnum << " w:" << a.docweight << "\n";
+  return outs;
+}
+
+
+
+// query results
+
+void queryresultsclass::clear ()
+{
+  docs.erase(docs.begin(),docs.end());
+  terms.erase(terms.begin(),terms.end());
+}
+
+queryresultsclass &queryresultsclass::operator=(const queryresultsclass &q)
+{
+  docs = q.docs;
+  terms = q.terms;
+
+  return *this;
+}
+
+void queryresultsclass::sortqueryterms()
+{
+  sort (terms.begin(), terms.end());
+}
+
+void queryresultsclass::uniqqueryterms()
+{
+  vector<termfreqclass>::iterator new_end = unique (terms.begin(), terms.end());
+  terms.erase(new_end, terms.end());
+}
+
+
+
+// stream output for debugging purposes
+ostream &operator<< (ostream &outs, queryresultsclass &q)
+{
+  outs << "*** queryresultsclass\n";
+  outs << "docs\n";
+
+  vector<docresultclass>::iterator docshere = q.docs.begin();
+  vector<docresultclass>::iterator docsend = q.docs.end();
+  while (docshere != docsend) {
+    outs << (*docshere);
+    docshere++;
+  }
+
+  outs << "terms\n";
+  vector<termfreqclass>::iterator termshere = q.terms.begin();
+  vector<termfreqclass>::iterator termsend = q.terms.end();
+  while (termshere != termsend) {
+    outs << (*termshere);
+    termshere++;
+  }
+
+  outs << "\n";
+
+  return outs;
+}
Index: /tags/start/gsdl/src/library/queryinfo.h
===================================================================
--- /tags/start/gsdl/src/library/queryinfo.h	(revision 13666)
+++ /tags/start/gsdl/src/library/queryinfo.h	(revision 13666)
@@ -0,0 +1,96 @@
+#ifndef QUERYINFO_H
+#define QUERYINFO_H
+
+#include "text_t.h"
+
+#ifndef USE_OBJECTSPACE
+#  include <vector>
+#  include <algorithm>
+#else
+#  include <ospace\std\vector>
+#  include <ospace\std\algorithm>
+#endif
+
+// query parameters
+
+class queryparamclass 
+{
+public:
+  text_t collection;
+  text_t search_index;
+  text_t querystring;
+  int search_type; // 0 = boolean, 1 = ranked
+  int casefolding;
+  int stemming;
+  int maxdocs;
+
+  queryparamclass &operator=(const queryparamclass &q);
+};
+
+bool operator==(const queryparamclass &x, const queryparamclass &y);
+bool operator!=(const queryparamclass &x, const queryparamclass &y);
+
+// stream output for debugging purposes
+ostream &operator<< (ostream &outs, queryparamclass &q);
+
+
+
+// term frequencies
+
+class termfreqclass 
+{
+public:
+  text_t termstr;
+  unsigned int termfreq;
+  
+  termfreqclass &operator=(const termfreqclass &t);
+};
+
+bool operator==(const termfreqclass &x, const termfreqclass &y);
+bool operator!=(const termfreqclass &x, const termfreqclass &y);
+bool operator<(const termfreqclass &x, const termfreqclass &y);
+bool operator>(const termfreqclass &x, const termfreqclass &y);
+
+// stream output for debugging purposes
+ostream &operator<< (ostream &outs, termfreqclass &q);
+
+
+
+// one query result
+
+class docresultclass
+{
+public:
+  int docnum;
+  float docweight;
+};
+
+// stream output for debugging purposes
+ostream &operator<< (ostream &outs, docresultclass &a);
+
+
+
+// query results
+
+class queryresultsclass 
+{
+public:
+  vector<docresultclass> docs;
+  vector<termfreqclass> terms;
+  vector<text_t> termvariants;
+
+  void clear ();
+  queryresultsclass &operator=(const queryresultsclass &q);
+
+  int getnumdocs () {return docs.size();}
+  int getnumterms () {return terms.size();}
+
+  void sortqueryterms();
+  void uniqqueryterms();
+};
+
+// stream output for debugging purposes
+ostream &operator<< (ostream &outs, queryresultsclass &q);
+
+
+#endif
Index: /tags/start/gsdl/src/library/text_t.cpp
===================================================================
--- /tags/start/gsdl/src/library/text_t.cpp	(revision 13666)
+++ /tags/start/gsdl/src/library/text_t.cpp	(revision 13666)
@@ -0,0 +1,555 @@
+/**************************************************************************
+ *
+ * text_t.cpp -- a simple 16-bit charater string class
+ * Copyright (c) 1998 -- Rodger McNab
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  1998/11/17 01:11:06  sjboddie
+   Initial revision
+
+   Revision 1.7  1998/06/24 01:50:08  rjmcnab
+   Added stuff for the objectspace libraries
+
+   Revision 1.6  1998/06/22 22:11:14  rjmcnab
+   Added copy operator = for ints and c-strings for efficiency
+   Added some general functions for dealing with text_ts
+
+   Revision 1.5  1998/06/18 23:53:52  rjmcnab
+   added '+' operator for concatenation
+   removed global declaration of ascii2text_t and text_t2ascii
+     (too unfriendly for threads)
+   added support for integers
+
+   Revision 1.4  1998/06/17 04:52:32  rjmcnab
+   added support for arrays of characters
+
+   Revision 1.3  1998/06/17 02:09:42  rjmcnab
+   added getcstr
+
+   Revision 1.2  1998/06/15 22:01:19  rjmcnab
+   fixed a few bugs
+
+   Revision 1.1  1998/06/13 20:08:34  rjmcnab
+   Initial revision
+
+*/
+
+static char *RCSID = "$Id$";
+
+
+#ifndef USE_OBJECTSPACE
+#  include <algorithm>
+#else
+#  include <ospace\std\algorithm>
+#endif
+
+
+#include "text_t.h"
+
+////////////////////////////////////
+// text_t methods
+////////////////////////////////////
+
+text_t::text_t () 
+{
+  clear ();
+}
+
+text_t::text_t (int i) 
+{
+  clear ();
+  appendint (i);
+}
+
+text_t::text_t (char *s) 
+{
+  clear ();
+  appendcstr (s);
+}
+
+void text_t::append (const text_t &t) 
+{
+  const_iterator here, end=t.end();
+  for (here=t.begin(); here!=end;here++)
+    {
+      text.push_back(*here);
+    }
+}
+
+void text_t::appendrange (iterator first, iterator last) 
+{
+  while (first != last) 
+    {
+      text.push_back (*first);
+      first++;
+    }
+}
+
+void text_t::appendrange (const_iterator first, const_iterator last) 
+{
+  while (first != last) 
+    {
+      text.push_back (*first);
+      first++;
+    }
+}
+
+void text_t::appendint (int i)
+{
+  // deal with zeros and negatives
+  if (i == 0) 
+    {
+      text.push_back('0');
+      return;
+    }
+  else if (i < 0)
+    {
+      text.push_back('-');
+      i *= -1;
+    }
+
+  // get a buffer for the conversion
+  int maxbuflen = sizeof(int)*3;
+  char *buf = new char[maxbuflen];
+  int len = 0;
+  
+  // get the number in reverse
+  while (i > 0)
+    {
+      buf[len++] = '0'+ (i%10);
+      i = i/10;
+    }
+
+  // reverse the number
+  while (len > 0)
+    {
+      text.push_back(buf[--len]);
+    }
+
+  delete buf;
+}
+
+int text_t::getint ()
+{
+  int i = 0;
+  int mult = 1; // become -1 for negative numbers
+
+  iterator here = text.begin();
+  iterator end = text.end();
+  
+  // do plus and minus signs
+  if (here != end)
+    {
+      if (*here == '-')
+	{
+	  mult = -1;
+	  here++;
+	}
+      else if (*here == '+')
+	{
+	  mult = 1;
+	  here++;
+	}
+    }
+
+  // deal with the number
+  while ((here != end) && (*here >= '0') && (*here <= '9'))
+    {
+      i = 10*i + (*here - '0');
+      here++;
+    }
+
+  i *= mult;
+  return i;
+}
+
+
+
+void text_t::appendcarr (char *s, size_type len)
+{
+  unsigned char *us = (unsigned char *)s;
+  while (len > 0) 
+    {
+      text.push_back (*us); // append this character
+      us++;
+      len--;
+    }
+}
+
+void text_t::appendcstr (char *s) 
+{
+  unsigned char *us = (unsigned char *)s;
+  while (*us != '\0') 
+    {
+      text.push_back (*us); // append this character
+      us++;
+    }
+}
+
+
+// strings returned from getcarr and getcstr become the callers 
+// responsibility and should be deallocated with "delete"
+
+char *text_t::getcarr(size_type &len) const
+{
+  unsigned char *cstr = new unsigned char[size()];
+  const_iterator ithere = begin();
+  const_iterator itend = end();
+
+  while (ithere != itend)
+    {
+      if (*ithere >= 256) cstr[len] = ' ';
+      else cstr[len] = (*ithere);
+      len++;
+      ithere++;
+    }
+
+  return (char *)cstr;
+}
+
+char *text_t::getcstr() const
+{
+  unsigned char *cstr = new unsigned char[size() + 1];
+  const_iterator ithere = begin();
+  const_iterator itend = end();
+  int len = 0;
+
+  while (ithere != itend)
+    {
+      if (*ithere >= 256) cstr[len] = ' ';
+      else cstr[len] = (*ithere);
+      len++;
+      ithere++;
+    }
+
+  cstr[len] = '\0';
+
+  return (char *)cstr;
+}
+
+
+// general functions which work on text_ts
+
+// find a character within a range
+text_t::const_iterator findchar (text_t::const_iterator first, text_t::const_iterator last, 
+				 unsigned short c)
+{
+  while (first != last)
+    {
+      if (*first == c) break;
+      first++;
+    }
+  return first;
+}
+
+text_t::iterator findchar (text_t::iterator first, text_t::iterator last, 
+			   unsigned short c)
+{
+  while (first != last)
+    {
+      if (*first == c) break;
+      first++;
+    }
+  return first;
+}
+
+// get a string up to the next delimiter (which is skipped)
+text_t::const_iterator getdelimitstr (text_t::const_iterator first, 
+				      text_t::const_iterator last,
+				      unsigned short c, text_t &outstr)
+{
+  text_t::const_iterator here = first;
+  here = findchar (first, last, c);
+  outstr.clear();
+  outstr.appendrange (first, here);
+  if (here != last) here++; // skip c
+  return here;
+}
+
+text_t::iterator getdelimitstr (text_t::iterator first, text_t::iterator last,
+				unsigned short c, text_t &outstr)
+{
+  text_t::iterator here = first;
+  here = findchar (first, last, c);
+  outstr.clear();
+  outstr.appendrange (first, here);
+  if (here != last) here++; // skip c
+  return here;
+}
+
+// split a string with a character
+void splitchar (text_t::const_iterator first, text_t::const_iterator last,
+		unsigned short c, text_tlist &outlist)
+{
+  outlist.erase(outlist.begin(), outlist.end());
+
+  text_t t;
+
+  while (first != last)
+    {
+      first = getdelimitstr (first, last, c, t);
+      outlist.push_back (t);
+    }
+}
+
+void splitchar (text_t::const_iterator first, text_t::const_iterator last,
+		unsigned short c, text_tarray &outlist)
+{
+  outlist.erase(outlist.begin(), outlist.end());
+
+  text_t t;
+
+  while (first != last)
+    {
+      first = getdelimitstr (first, last, c, t);
+      outlist.push_back (t);
+    }
+}
+
+// join a string using a character
+void joinchar (const text_tlist &inlist, unsigned short c, text_t &outtext)
+{
+  outtext.clear ();
+
+  text_tlist::const_iterator here = inlist.begin ();
+  text_tlist::const_iterator end = inlist.end ();
+  bool first = true;
+  while (here != end)
+    {
+      if (!first) outtext.push_back (c);
+      first = false;
+      outtext += *here;
+      here++;
+    }
+}
+
+void joinchar (const text_tarray &inlist, unsigned short c, text_t &outtext)
+{
+  outtext.clear ();
+
+  text_tarray::const_iterator here = inlist.begin ();
+  text_tarray::const_iterator end = inlist.end ();
+  bool first = true;
+  while (here != end)
+    {
+      if (!first) outtext.push_back (c);
+      first = false;
+      outtext += *here;
+      here++;
+    }
+}
+
+// count the occurances of a character within a range
+int countchar (text_t::const_iterator first, text_t::const_iterator last,
+	       unsigned short c)
+{
+  int count = 0;
+  while (first != last) {
+    if (*first == c) count ++;
+    first ++;
+  }
+  return count;
+}
+
+
+
+////////////////////////////////////
+// convertclass methods
+////////////////////////////////////
+
+// conversion classes used for getting information in to and out of
+// the text_t class.
+
+convertclass::convertclass () 
+{
+  // nothing to do
+}
+
+void convertclass::reset ()
+{
+  // nothing to do
+}
+
+
+////////////////////////////////////
+// inconvertclass methods
+////////////////////////////////////
+
+// convert from a char stream to the text_t class
+// the default version assumes the input is a ascii
+// character array
+
+inconvertclass::inconvertclass () 
+{
+  start = NULL;
+  len = 0;
+}
+
+
+void inconvertclass::reset ()
+{
+  start = NULL;
+  len = 0;
+}
+
+void inconvertclass::setinput (char *thestart, size_t thelen)
+{
+  start = thestart;
+  len = thelen;
+}
+
+void inconvertclass::convert (text_t &output, status_t &status)
+{
+  if (start == NULL || len == 0)
+    {
+      status = finished;
+      return;
+    }
+
+  // don't want any funny sign conversions happening
+  unsigned char *here = (unsigned char *)start;
+  while (len > 0) 
+    {
+      output.push_back (*here); // append this character
+      ++here;
+      --len;
+    }
+
+  start = (char *)here; // save current position
+  status = finished;
+}
+
+// an instance of the default inconvertclass to do simple
+// conversions. Note that any functions that use this are
+// not reentrant. If a function needs to be reentrant it
+// should declare its own instance.
+inconvertclass ascii2text_t;
+
+
+////////////////////////////////////
+// outconvertclass methods
+////////////////////////////////////
+
+// Convert from a text_t class to a char stream
+// This default version assumes the output is a ascii
+// character array. If you set the output stream you
+// can use this class to output to a stream using the
+// << operator. The << operator can also be conveniently
+// used to set the output stream by doing something like
+//
+// cout << text_t2ascii << text_tstr << anothertext_tstr;
+//
+outconvertclass::outconvertclass ()
+{
+  input = NULL;
+  outs = NULL;
+}
+
+void outconvertclass::reset ()
+{
+  input = NULL;
+  outs = NULL;
+}
+
+void outconvertclass::setinput (text_t *theinput)
+{
+  input = theinput;
+  if (input != NULL) texthere = input->begin();
+}
+
+void outconvertclass::convert (char *output, size_t maxlen, 
+		      size_t &len, status_t &status)
+{
+  if (input == NULL || output == NULL)
+    {
+      status = finished;
+      return;
+    }
+
+  // don't want any funny sign conversions happening
+  unsigned char *uoutput = (unsigned char *)output;
+  text_t::iterator textend = input->end();
+  len = 0;
+  while ((len < maxlen) && (texthere != textend)) 
+    {
+      if (*texthere < 256) *uoutput = (unsigned char)(*texthere);
+      else *uoutput = 32; // put a space where a char >= 256 exists
+      ++uoutput;
+      ++len;
+      ++texthere;
+    }
+  
+  if (texthere == textend) status = finished;
+  else status = unfinished;
+}
+
+void outconvertclass::setostream (ostream *theouts)
+{
+  outs = theouts;
+}
+
+ostream *outconvertclass::getostream ()
+{
+  return outs;
+}
+
+
+
+
+// an instance of the default outconvertclass to do simple
+// conversions
+outconvertclass text_t2ascii;
+
+
+
+// stream operators for the output class
+
+outconvertclass &operator<< (ostream &theouts, outconvertclass &outconverter)
+{
+  outconverter.setostream(&theouts);
+  return outconverter;
+}
+
+
+#define STREAMBUFSIZE 256
+outconvertclass &operator<< (outconvertclass &outconverter, const text_t &t)
+{
+  ostream *outstream = outconverter.getostream();
+
+  if (outstream == NULL) return outconverter;
+
+  char outbuf[STREAMBUFSIZE];
+  size_t len;
+  outconvertclass::status_t status = outconvertclass::unfinished;
+
+  // assume that there is no data needing converting
+  // left in the converter
+  outconverter.setinput ((text_t *)(&t)); // note the const -> nonconst conversion
+
+  while (status == outconvertclass::unfinished)
+    {
+      outconverter.convert (outbuf, STREAMBUFSIZE, len, status);
+      if (len > 0) outstream->write(outbuf, len);
+    }
+
+  return outconverter;
+}
Index: /tags/start/gsdl/src/library/text_t.h
===================================================================
--- /tags/start/gsdl/src/library/text_t.h	(revision 13666)
+++ /tags/start/gsdl/src/library/text_t.h	(revision 13666)
@@ -0,0 +1,313 @@
+/**************************************************************************
+ *
+ * text_t.h -- a simple 16-bit charater string class
+ * Copyright (c) 1998 -- Rodger McNab
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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.
+ *
+ * $Id$
+ *
+ **************************************************************************/
+
+
+
+#ifndef TEXT_T_H
+#define TEXT_T_H
+
+#ifndef USE_OBJECTSPACE
+#  include <vector>
+#  include <list>
+#  include <set>
+#else
+#  include <ospace\std\vector>
+#  include <ospace\std\list>
+#  include <ospace\std\set>
+#endif
+
+// use the standard namespace
+#ifdef __GNUG__
+// namespaces are broken in current version of gcc
+#else
+#  ifndef USE_OBJECTSPACE
+using namespace std;
+#  else
+#    ifndef OS_NO_NAMESPACE
+using namespace ospace::std;
+#    endif
+#  endif
+#endif
+
+
+// class prototypes
+class inconvertclass;
+class outconvertclass;
+
+
+typedef vector<unsigned short> usvector;
+
+// The class text_t can handle long strings which may contain
+// null characters. It uses unsigned shorts to represent up to
+// 64K character values.
+class text_t {
+  public:
+  //type support for ucvector
+  typedef usvector::iterator iterator;
+  typedef usvector::const_iterator const_iterator;
+  typedef usvector::reference reference;
+  typedef usvector::const_reference const_reference;
+  typedef usvector::size_type size_type;
+  typedef usvector::difference_type difference_type;
+  typedef usvector::const_reverse_iterator const_reverse_iterator;
+  typedef usvector::reverse_iterator reverse_iterator;
+  
+protected:
+  usvector text;
+  
+public:
+  // constructors
+  text_t ();
+  text_t (int i);
+  text_t (char *s); // assumed to be a normal c string
+
+  // basic container support
+  iterator begin () {return text.begin();}
+  const_iterator begin () const {return text.begin();}
+  iterator end () {return text.end();}
+  const_iterator end () const {return text.end();}
+
+  void erase(iterator pos) {text.erase(pos);}
+  void erase(iterator first, iterator last) {text.erase(first, last);}
+  void push_back(unsigned short c) {text.push_back(c);}
+  void pop_back() {text.pop_back();}
+  text_t &operator=(const text_t &x) {text=x.text;return *this;}
+  reference operator[](size_type n) {return text[n];};
+  const_reference operator[](size_type n) const {return text[n];};
+
+  bool empty () const {return text.empty();}
+  size_type size() const {return text.size();}
+  friend bool operator!=(const text_t& x, const text_t& y);
+  friend bool operator==(const text_t& x, const text_t& y);
+  friend bool operator<(const text_t& x, const text_t& y);
+  friend bool operator>(const text_t& x, const text_t& y);
+  
+  // added functionality
+  void clear () {text.erase(text.begin(),text.end());}
+  void append (const text_t &t);
+  void appendrange (iterator first, iterator last);
+  void appendrange (const_iterator first, const_iterator last);
+  text_t &operator+= (const text_t &t) {append(t);return *this;}
+
+  // support for integers
+  void appendint (int i);
+  void setint (int i) {clear();appendint(i);}
+  text_t &operator=(int i) {setint (i);return *this;}
+  text_t &operator+= (int i) {appendint(i);return *this;}
+  int getint ();
+
+  // support for arrays of chars
+  void appendcarr (char *s, size_type len);
+  void setcarr (char *s, size_type len) {clear();appendcarr(s,len);}
+
+  // support for null-terminated C strings
+  void appendcstr (char *s);
+  void setcstr (char *s) {clear();appendcstr(s);}
+  text_t &operator= (char *s) {setcstr(s);return *this;} // c string
+  text_t &operator+= (char *s) {appendcstr(s);return *this;} // c string
+
+  // strings returned from getcarr and getcstr become the callers 
+  // responsibility and should be deallocated with "delete"
+  char *getcarr(size_type &len) const;
+  char *getcstr() const;
+};
+
+
+inline text_t operator+(const text_t &t1, const text_t &t2)
+{
+  text_t tnew = t1;
+  tnew.append(t2);
+  return tnew;
+}
+
+inline text_t operator+(const text_t &t1, int i1)
+{
+  text_t tnew = t1;
+  tnew.appendint(i1);
+  return tnew;
+}
+
+inline text_t operator+(const text_t &t1, char *s1)
+{
+  text_t tnew = t1;
+  tnew.appendcstr(s1);
+  return tnew;
+}
+
+
+inline bool operator!=(const text_t& x, const text_t& y) 
+{
+  return (x.text != y.text);
+}
+
+inline bool operator==(const text_t& x, const text_t& y) 
+{
+  return (x.text == y.text);
+}
+
+inline bool operator<(const text_t& x, const text_t& y) 
+{
+  return (x.text < y.text);
+}
+
+inline bool operator>(const text_t& x, const text_t& y) 
+{
+  return (x.text > y.text);
+}
+
+
+struct eqtext_t 
+{
+  bool operator()(const text_t t1, const text_t t2) const
+  { return t1 == t2; }
+};
+
+struct lttext_t 
+{
+  bool operator()(const text_t t1, const text_t t2) const
+  { return t1 < t2; }
+};
+
+
+// frequently used derived types
+typedef set<text_t,lttext_t> text_tset;
+typedef list<text_t> text_tlist;  // more efficient for insertions/deletions
+typedef vector<text_t> text_tarray; // more space efficient than text_tlist
+
+
+// general functions which work on text_ts
+
+// find a character within a range
+text_t::const_iterator findchar (text_t::const_iterator first, text_t::const_iterator last, 
+				 unsigned short c);
+text_t::iterator findchar (text_t::iterator first, text_t::iterator last, 
+			   unsigned short c);
+
+// get a string up to the next delimiter (which is skipped)
+text_t::const_iterator getdelimitstr (text_t::const_iterator first, 
+				      text_t::const_iterator last,
+				      unsigned short c, text_t &outstr);
+text_t::iterator getdelimitstr (text_t::iterator first, text_t::iterator last,
+				unsigned short c, text_t &outstr);
+
+// split a string with a character
+void splitchar (text_t::const_iterator first, text_t::const_iterator last,
+		unsigned short c, text_tlist &outlist);
+void splitchar (text_t::const_iterator first, text_t::const_iterator last,
+		unsigned short c, text_tarray &outlist);
+
+// join a string using a character
+void joinchar (const text_tlist &inlist, unsigned short c, text_t &outtext);
+void joinchar (const text_tarray &inlist, unsigned short c, text_t &outtext);
+
+// count the occurances of a character within a range
+int countchar (text_t::const_iterator first, text_t::const_iterator last,
+	       unsigned short c);
+
+
+
+
+
+
+
+
+// conversion classes used for getting information in to and out of
+// the text_t class.
+
+class convertclass 
+{
+public:
+  enum status_t {finished, stopped, unfinished};
+  
+  convertclass ();
+  virtual void reset ();
+};
+
+
+
+// convert from a char stream to the text_t class
+// the default version assumes the input is a ascii
+// character array
+class inconvertclass : public convertclass
+{
+public:
+  inconvertclass ();
+  void reset ();
+  void setinput (char *thestart, size_t thelen);
+  virtual void convert (text_t &output, status_t &status);
+
+protected:
+  char *start;
+  size_t len;
+};
+
+// to get something which will do the conversion
+// to ascii declare a (non global!) instance like
+// this
+// inconvertclass ascii2text_t;
+
+
+// Convert from a text_t class to a char stream
+// This default version assumes the output is a ascii
+// character array. If you set the output stream you
+// can use this class to output to a stream using the
+// << operator. The << operator can also be conveniently
+// used to set the output stream by doing something like
+//
+// cout << text_t2ascii << textstr << anothertextstr;
+//
+// this class assumes that the input text doesn't change
+// while the conversion takes place
+class outconvertclass : public convertclass
+{
+public:
+  outconvertclass ();
+  void reset ();
+  void setinput (text_t *theinput);
+  // note that convert does not null-terminate the
+  // output array of characters
+  virtual void convert (char *output, size_t maxlen, 
+			size_t &len, status_t &status);
+
+  void setostream (ostream *theouts);
+  ostream *getostream ();
+
+protected:
+  text_t *input;
+  text_t::iterator texthere; // only valid if input is valid
+
+  ostream *outs;
+};
+
+// to get something which will do the conversion
+// to text_t declare a (non global!) instance like
+// this
+// outconvertclass text_t2ascii;
+
+
+// stream operators for the output class
+outconvertclass &operator<< (ostream &theouts, outconvertclass &outconverter);
+outconvertclass &operator<< (outconvertclass &outconverter, const text_t &t);
+
+
+#endif
Index: /tags/start/gsdl/src/txt2db/txt2db.cpp
===================================================================
--- /tags/start/gsdl/src/txt2db/txt2db.cpp	(revision 13666)
+++ /tags/start/gsdl/src/txt2db/txt2db.cpp	(revision 13666)
@@ -0,0 +1,124 @@
+#ifdef __WIN32__
+#include "autoconf.h"
+#include "systems.h"
+#include "gdbmconst.h"
+#include "gdbm.h"
+
+#else
+#include <gdbm.h>
+#endif
+
+
+#ifdef __GNUG__
+#  include <iostream.h>
+#else
+#  ifndef USE_OBJECTSPACE
+#    include <iostream>
+#  else
+#    include <ospace\std\iostream>
+#  endif
+#endif
+
+#include "text_t.h"
+
+
+void print_usage (char *program_name) {
+	cerr << "usage: " << program_name << "database-name\n\n";
+}
+
+
+int main (int argc, char *argv[]) {
+	int block_size = 0;
+	GDBM_FILE dbf;
+	char c;
+	text_t key;
+	text_t value;
+	text_t tmp;
+	int num_dashes = 0;
+
+	// sanity check
+	if (argc != 2) {
+		print_usage (argv[0]);
+		exit (0);
+	}
+
+	// open the database
+	dbf = gdbm_open  (argv[1], block_size, GDBM_NEWDB, 00664, NULL);
+    if (dbf == NULL) {
+		cerr << "couldn't create " << argv[1] << "\n";
+		exit (0);
+	}
+
+	cin.get(c);
+	while (!cin.eof()) {
+		num_dashes = 0;
+		key = "";
+		value = "";
+
+		// look for [key]\n
+		while (!cin.eof() && c != '[') cin.get(c);
+		if (!cin.eof()) cin.get(c); // skip [
+		while (!cin.eof() && c != ']') {
+			key.push_back ((unsigned char)c);
+			cin.get(c);
+		}
+		if (!cin.eof()) cin.get(c); // skip ]
+		while (!cin.eof() && (c == '\n' || c == 'r')) cin.get(c);
+
+		// look for 70 dashes
+		tmp = "";
+		while (!cin.eof() && (num_dashes < 70)) {
+			if (c == '\n' || c == '\r') {
+				tmp.push_back ((unsigned char)c);
+				num_dashes = 0;
+
+			} else if (c == '-') {
+				tmp.push_back ((unsigned char)c);
+				num_dashes++;
+
+			} else {
+				value += tmp;
+				value.push_back ((unsigned char)c);
+				tmp = "";
+				num_dashes = 0;
+			}
+			cin.get(c);
+		}
+		
+		// if the key is not an empty string store this key-value pair
+		if (!key.empty()) {
+			// convert key to a datum datatype
+			datum key_data;
+			key_data.dptr = key.getcstr();
+			if (key_data.dptr == NULL) {
+				cerr << "NULL key_data.dptr\n";
+				exit (0);
+			}
+			key_data.dsize = strlen(key_data.dptr);
+
+			// convert value to a datum datatype
+			datum value_data;
+			value_data.dptr = value.getcstr();
+			if (value_data.dptr == NULL) {
+				cerr << "NULL value_data.dptr\n";
+				exit (0);
+			}
+			value_data.dsize = strlen(value_data.dptr);
+
+			// store the value
+			if (gdbm_store (dbf, key_data, value_data, GDBM_REPLACE) < 0) {
+				cerr << "gdbm_store returned an error\n";
+				exit (0);
+			}
+
+			delete key_data.dptr;
+			delete value_data.dptr;
+		}
+	}
+
+
+	gdbm_close (dbf);
+
+
+	return 0;
+}
Index: /tags/start/indexers/README.txt
===================================================================
--- /tags/start/indexers/README.txt	(revision 13666)
+++ /tags/start/indexers/README.txt	(revision 13666)
@@ -0,0 +1,1 @@
+A temporary readme file for new indexers project for greenstone.
Index: /tags/start/is7_bbc/BBC Collection/IsConfig.INI
===================================================================
--- /tags/start/is7_bbc/BBC Collection/IsConfig.INI	(revision 13666)
+++ /tags/start/is7_bbc/BBC Collection/IsConfig.INI	(revision 13666)
@@ -0,0 +1,2 @@
+[0]
+0=0
Index: /tags/start/is7_bbc/BBC Collection/Setup.map
===================================================================
--- /tags/start/is7_bbc/BBC Collection/Setup.map	(revision 13666)
+++ /tags/start/is7_bbc/BBC Collection/Setup.map	(revision 13666)
@@ -0,0 +1,645 @@
+***** External Functions *****
+1    AdminAskPath                                       iswi.obl(AdminAskPath.obs)
+2    AllFeaturesDeselected                              iswi.obl(CompHelperFuncs.obs)
+3    CHECK_RETURN                                       iswi.obl(ErrHandler.obs)
+4    CloseFile                                          isrt.obl(Files.obs)
+5    CmdGetHwndDlg                                      isrt.obl(CustomDlg.obs)
+6    ComponentCompareSizeRequired                       isrt.obl(component.obs)
+7    ComponentErrorInfo                                 iswi.obl(ComponentConv.obs)
+8    ComponentFilterLanguage                            iswi.obl(ComponentConv.obs)
+9    ComponentFilterOS                                  iswi.obl(ComponentConv.obs)
+10   ComponentGetData                                   iswi.obl(ComponentConv.obs)
+11   ComponentGetTotalCost                              isrt.obl(component.obs)
+12   ComponentIsItemSelected                            iswi.obl(ComponentConv.obs)
+13   ComponentListItems                                 iswi.obl(ComponentConv.obs)
+14   ComponentReinstall                                 iswi.obl(ComponentConv.obs)
+15   ComponentRemoveAll                                 iswi.obl(ComponentConv.obs)
+16   ComponentSaveTarget                                isrt.obl(component.obs)
+17   ComponentSelectItem                                iswi.obl(ComponentConv.obs)
+18   ComponentSetupTypeEnum                             isrt.obl(component.obs)
+19   ComponentSetupTypeGetData                          iswi.obl(ComponentConv.obs)
+20   ComponentSetupTypeSet                              iswi.obl(ComponentConv.obs)
+21   ComponentTransferData                              iswi.obl(ComponentConv.obs)
+22   ComponentTreeInit                                  isrt.obl(Dialogs.obs)
+23   CreateDir                                          isrt.obl(Files.obs)
+24   CreateFile                                         isrt.obl(Files.obs)
+25   CreateInstallationInfo                             iswi.obl(RegistryConv.obs)
+26   CreateObject                                       isrt.obl(Misc.obs)
+27   CtrlGetCurSel                                      isrt.obl(CustomDlg.obs)
+28   CtrlGetNotificationCode                            isrt.obl(CustomDlg.obs)
+29   CtrlGetState                                       isrt.obl(CustomDlg.obs)
+30   CtrlGetSubCommand                                  isrt.obl(CustomDlg.obs)
+31   CtrlGetText                                        isrt.obl(CustomDlg.obs)
+32   CtrlSelectText                                     isrt.obl(CustomDlg.obs)
+33   CtrlSetCurSel                                      isrt.obl(CustomDlg.obs)
+34   CtrlSetList                                        isrt.obl(CustomDlg.obs)
+35   CtrlSetState                                       isrt.obl(CustomDlg.obs)
+36   CtrlSetText                                        isrt.obl(CustomDlg.obs)
+37   DefineDialog                                       isrt.obl(CustomDlg.obs)
+38   DeleteFile                                         isrt.obl(Files.obs)
+39   DialogSetDefaultFont                               isrt.obl(Dialogs.obs)
+40   DialogSetFont                                      isrt.obl(Dialogs.obs)
+41   DialogSetInfo                                      isrt.obl(Dialogs.obs)
+42   Disable                                            isrt.obl(Enable.obs)
+43   DiskSizeToStr                                      isrt.obl(SDINT.obs)
+44   Divide                                             isrt.obl(Misc.obs)
+45   DllSizeOf                                          isrt.obl(Str.obs)
+46   Do                                                 isrt.obl(Misc.obs)
+47   Enable                                             isrt.obl(Enable.obs)
+48   EndDialog                                          isrt.obl(CustomDlg.obs)
+49   ExistsDir                                          isrt.obl(Files.obs)
+50   EzDefineDialog                                     isrt.obl(CustomDlg.obs)
+51   FeatureCompareSizeRequired                         iswi.obl(FeatureFuncsConv.obs)
+52   FeatureIsItemSelected                              iswi.obl(FeatureFuncsConv.obs)
+53   FeaturesInstalled                                  iswi.obl(FileTransferFuncsConv.obs)
+54   FeaturesInstalling                                 iswi.obl(FileTransferFuncsConv.obs)
+55   FindFile                                           isrt.obl(Files.obs)
+56   FindWindow                                         isrt.obl(Misc.obs)
+57   FormatMessage                                      isrt.obl(Misc.obs)
+58   GDI32.CreateRectRgn                                iswi.obl(AdminAskPath.obs)
+59   GDI32.GetDeviceCaps                                iswi.obl(AdminAskPath.obs)
+60   GeneratedMSIScript                                 iswi.obl(FileTransferFuncsConv.obs)
+61   GeneratingMSIScript                                iswi.obl(FileTransferFuncsConv.obs)
+62   GetBillboard                                       isrt.obl(SysVars.obs)
+63   GetComponentsFeatures                              iswi.obl(CompHelperFuncs.obs)
+64   GetDialogTitle                                     isrt.obl(Dialogs.obs)
+65   GetDir                                             isrt.obl(Str.obs)
+66   GetDisk                                            isrt.obl(Str.obs)
+67   GetDiskSpace                                       isrt.obl(GSI.obs)
+68   GetDiskSpaceEx                                     isrt.obl(GSI.obs)
+69   GetExtents                                         isrt.obl(GSI.obs)
+70   GetISRes                                           isrt.obl(SysVars.obs)
+71   GetLog                                             isrt.obl(SysVars.obs)
+72   GetMSIFeatureName                                  iswi.obl(CompHelperFuncs.obs)
+73   GetMaintenance                                     iswi.obl(ISWiInit.obs)
+74   GetMsiFeaturePath                                  iswi.obl(CompHelperFuncs.obs)
+75   GetMsiHandle                                       iswi.obl(SysVarsConv.obs)
+76   GetMsiNameFromAliasTable                           iswi.obl(CompHelperFuncs.obs)
+77   GetOpenFileMode                                    isrt.obl(Files.obs)
+78   GetProductGUID                                     iswi.obl(ISWiInit.obs)
+79   GetProfString                                      isrt.obl(Profile.obs)
+80   GetSelectedLanguage                                isrt.obl(SysVars.obs)
+81   GetSelectedTreeComponent                           isrt.obl(CmptView.obs)
+82   GetSourceDir                                       iswi.obl(SysVarsConv.obs)
+83   GetSupportDir                                      isrt.obl(SysVars.obs)
+84   GetSystemInfo                                      isrt.obl(GSI.obs)
+85   GetValidDrivesList                                 isrt.obl(GSI.obs)
+86   GetWinDir                                          isrt.obl(SysVars.obs)
+87   GetWinSysDir                                       isrt.obl(SysVars.obs)
+88   GetWindowHandle                                    iswi.obl(MiscConv.obs)
+89   HIWORD                                             isrt.obl(Misc.obs)
+90   HexStrToNum                                        isrt.obl(Str.obs)
+91   ISDeterminePlatform                                isrt.obl(OsInfo.obs)
+92   ISMIF32.InstallStatusMIF                           isrt.obl(MIF.obs)
+93   ISRT.ComponentViewSetInfoEx                        isrt.obl(Dialogs.obs)
+94   ISRT.EnableHourGlass                               isrt.obl(Enable.obs)
+95   ISRT.GetCPUType                                    isrt.obl(GSI.obs)
+96   ISRT.GetFontSub                                    isrt.obl(Dialogs.obs)
+97   ISRT.GetHandle                                     setup.obs
+98   ISRT.GetPorts                                      isrt.obl(GSI.obs)
+99   ISRT.IsEmpty                                       setup.obs
+100  ISRT.IsNTAdmin                                     isrt.obl(Is.obs)
+101  ISRT.IsObject                                      setup.obs
+102  ISRT.LangLoadString                                isrt.obl(SDINT.obs)
+103  ISRT.MessageBeepP                                  setup.obs
+104  ISRT.PathCompactPathPixel                          isrt.obl(CustomDlg.obs)
+105  ISRT.PathGetDir                                    isrt.obl(Str.obs)
+106  ISRT.PathGetDrive                                  isrt.obl(Str.obs)
+107  ISRT.PathGetFile                                   isrt.obl(Str.obs)
+108  ISRT.PathGetFileExt                                isrt.obl(Str.obs)
+109  ISRT.PathGetFileName                               isrt.obl(Str.obs)
+110  ISRT.PathGetPath                                   isrt.obl(Str.obs)
+111  ISRT.PathGetSpecialFolder                          isrt.obl(SysVars.obs)
+112  ISRT.PathIsValidSyntax                             isrt.obl(Is.obs)
+113  ISRT._BrowseForFolder                              isrt.obl(SelectDir.obs)
+114  ISRT._CloseFile                                    isrt.obl(Files.obs)
+115  ISRT._CmdGetHwndDlg                                isrt.obl(CustomDlg.obs)
+116  ISRT._ComponentCompareSizeRequired                 isrt.obl(component.obs)
+117  ISRT._ComponentGetTotalCost                        isrt.obl(component.obs)
+118  ISRT._ComponentSaveTarget                          isrt.obl(component.obs)
+119  ISRT._ComponentSetupTypeEnum                       isrt.obl(component.obs)
+120  ISRT._CreateDir                                    isrt.obl(Files.obs)
+121  ISRT._CreateObject                                 isrt.obl(Misc.obs)
+122  ISRT._CtrlGetNotificationCode                      isrt.obl(CustomDlg.obs)
+123  ISRT._CtrlGetSubCommand                            isrt.obl(CustomDlg.obs)
+124  ISRT._DefineDialog                                 isrt.obl(CustomDlg.obs)
+125  ISRT._DialogSetFont                                isrt.obl(Dialogs.obs)
+126  ISRT._DisableStatus                                isrt.obl(Enable.obs)
+127  ISRT._Divide                                       isrt.obl(Misc.obs)
+128  ISRT._DoSprintf                                    iswi.obl(HelperFuncs.obs)
+129  ISRT._EnableDialogCache                            isrt.obl(Enable.obs)
+130  ISRT._EnablePrevDialog                             iswi.obl(AdminAskPath.obs)
+131  ISRT._EnableStatus                                 isrt.obl(Enable.obs)
+132  ISRT._EndDialog                                    isrt.obl(CustomDlg.obs)
+133  ISRT._ExistsDir                                    isrt.obl(Files.obs)
+134  ISRT._ExistsFile                                   isrt.obl(Files.obs)
+135  ISRT._GetDiskSpaceEx                               isrt.obl(GSI.obs)
+136  ISRT._GetGlobalMemorySize                          isrt.obl(GSI.obs)
+137  ISRT._GetSelectedTreeComponent                     isrt.obl(CmptView.obs)
+138  ISRT._GetSupportDir                                isrt.obl(SysVars.obs)
+139  ISRT._ListAddItem                                  isrt.obl(scrlist.obs)
+140  ISRT._ListAddString                                isrt.obl(scrlist.obs)
+141  ISRT._ListCount                                    isrt.obl(scrlist.obs)
+142  ISRT._ListCreate                                   isrt.obl(scrlist.obs)
+143  ISRT._ListCurrentString                            isrt.obl(scrlist.obs)
+144  ISRT._ListDestroy                                  isrt.obl(scrlist.obs)
+145  ISRT._ListFindString                               isrt.obl(scrlist.obs)
+146  ISRT._ListGetFirstItem                             isrt.obl(scrlist.obs)
+147  ISRT._ListGetFirstString                           isrt.obl(scrlist.obs)
+148  ISRT._ListGetNextItem                              isrt.obl(scrlist.obs)
+149  ISRT._ListGetNextString                            isrt.obl(scrlist.obs)
+150  ISRT._ListGetType                                  isrt.obl(scrlist.obs)
+151  ISRT._ListSetIndex                                 isrt.obl(scrlist.obs)
+152  ISRT._OpenFile                                     isrt.obl(Files.obs)
+153  ISRT._RegCreateKey                                 iswi.obl(RegistryConv.obs)
+154  ISRT._RegQueryKeyBinaryValue                       iswi.obl(RegistryConv.obs)
+155  ISRT._RegQueryKeyValue                             iswi.obl(RegistryConv.obs)
+156  ISRT._ReleaseDialog                                isrt.obl(CustomDlg.obs)
+157  ISRT._SetAltMainImage                              isrt.obl(Dialogs.obs)
+158  ISRT._SetDisplayEffect                             isrt.obl(ui.obs)
+159  ISRT._TreeViewCreate                               isrt.obl(CmptView.obs)
+160  ISRT._WaitOnDialog                                 isrt.obl(CustomDlg.obs)
+161  ISRT._WriteLine                                    isrt.obl(Files.obs)
+162  ISRT.__CreateObjectContext                         isrt.obl(ISRTInit.obs)
+163  ISRT.__GetCmdLineOptions                           isrt.obl(ISRTInit.obs)
+164  ISRT.__GetContextGUID                              isrt.obl(ISRTInit.obs)
+165  ISRT.__GetFileRegistrar                            isrt.obl(ISRTInit.obs)
+166  ISRT.__GetInfo                                     isrt.obl(ISRTInit.obs)
+167  ISRT.__GetLog                                      isrt.obl(SysVars.obs)
+168  ISRT.__GetLogDB                                    isrt.obl(ISRTInit.obs)
+169  ISRT.__GetMainWindow                               setup.obs
+170  ISRT.__GetMaintenanceMode                          isrt.obl(SysVars.obs)
+171  ISRT.__GetObjects                                  isrt.obl(ISRTInit.obs)
+172  ISRT.__GetProductGuid                              isrt.obl(SysVars.obs)
+173  ISRT.__GetProgress                                 setup.obs
+174  ISRT.__GetReboot                                   isrt.obl(ISRTInit.obs)
+175  ISRT.__GetTextSub                                  isrt.obl(ISRTInit.obs)
+176  ISRT.__ReleaseObjectContext                        isrt.obl(ISRTInit.obs)
+177  ISRT.__RestoreMainLog                              isrt.obl(ISRTInit.obs)
+178  ISRT.__SetComponentLog                             isrt.obl(ISRTInit.obs)
+179  ISWIOnAppSearch                                    iswi.obl(DriverConv.obs)
+180  ISWIOnCCPSearch                                    iswi.obl(DriverConv.obs)
+181  ISWIOnExitInstall                                  iswi.obl(DriverConv.obs)
+182  ISWIOnFirstUIAfter                                 iswi.obl(DriverConv.obs)
+183  ISWIOnFirstUIBefore                                iswi.obl(DriverConv.obs)
+184  ISWIOnInitInstall                                  iswi.obl(DriverConv.obs)
+185  ISWIOnMaintUIAfter                                 iswi.obl(DriverConv.obs)
+186  ISWIOnMaintUIBefore                                iswi.obl(DriverConv.obs)
+187  ISWIOnMoveData                                     iswi.obl(DriverConv.obs)
+188  ISWIPCRestoreAfter                                 iswi.obl(DriverConv.obs)
+189  ISWIPCRestoreBefore                                iswi.obl(DriverConv.obs)
+190  InstallFilesActionAfter                            iswi.obl(FileTransferFuncsConv.obs)
+191  InstallFilesActionBefore                           iswi.obl(FileTransferFuncsConv.obs)
+192  Is                                                 isrt.obl(Is.obs)
+193  IsOSWinXP                                          iswi.obl(HelperFuncs.obs)
+194  KERNEL.GetModuleHandle                             setup.obs
+195  KERNEL32.CloseHandle                               iswi.obl(AdminAskPath.obs)
+196  KERNEL32.CreateFileA                               iswi.obl(AdminAskPath.obs)
+197  KERNEL32.DeleteFileA                               iswi.obl(AdminAskPath.obs)
+198  KERNEL32.FindClose                                 iswi.obl(AdminAskPath.obs)
+199  KERNEL32.FindFirstFileA                            iswi.obl(AdminAskPath.obs)
+200  KERNEL32.FindNextFileA                             iswi.obl(AdminAskPath.obs)
+201  KERNEL32.FormatMessageA                            iswi.obl(AdminAskPath.obs)
+202  KERNEL32.GetDriveType                              iswi.obl(AdminAskPath.obs)
+203  KERNEL32.GetFileAttributesA                        iswi.obl(AdminAskPath.obs)
+204  KERNEL32.GetLocalTime                              iswi.obl(AdminAskPath.obs)
+205  KERNEL32.GetLocaleInfo                             iswi.obl(AdminAskPath.obs)
+206  KERNEL32.GetPrivateProfileString                   iswi.obl(AdminAskPath.obs)
+207  KERNEL32.GetPrivateProfileStringA                  iswi.obl(AdminAskPath.obs)
+208  KERNEL32.GetProfileStringA                         iswi.obl(AdminAskPath.obs)
+209  KERNEL32.GetSystemDefaultLCID                      iswi.obl(AdminAskPath.obs)
+210  KERNEL32.GetUserDefaultLangID                      iswi.obl(AdminAskPath.obs)
+211  KERNEL32.GetVersion                                iswi.obl(AdminAskPath.obs)
+212  KERNEL32.GetVersionEx                              iswi.obl(AdminAskPath.obs)
+213  KERNEL32.GetVolumeInformation                      iswi.obl(AdminAskPath.obs)
+214  KERNEL32.GetWindowsDirectory                       iswi.obl(AdminAskPath.obs)
+215  KERNEL32.SetFileAttributesA                        iswi.obl(AdminAskPath.obs)
+216  KERNEL32.WritePrivateProfileString                 iswi.obl(AdminAskPath.obs)
+217  KERNEL32.WritePrivateProfileStringA                iswi.obl(AdminAskPath.obs)
+218  KERNEL32.WriteProfileStringA                       iswi.obl(AdminAskPath.obs)
+219  KERNEL32.lstrlen                                   iswi.obl(AdminAskPath.obs)
+220  Kernel32.GetModuleHandleA                          iswi.obl(ComponentConv.obs)
+221  LOWORD                                             isrt.obl(Misc.obs)
+222  ListAddItem                                        isrt.obl(scrlist.obs)
+223  ListAddString                                      isrt.obl(scrlist.obs)
+224  ListCount                                          isrt.obl(scrlist.obs)
+225  ListCreate                                         isrt.obl(scrlist.obs)
+226  ListCurrentString                                  isrt.obl(scrlist.obs)
+227  ListDestroy                                        isrt.obl(scrlist.obs)
+228  ListFindString                                     isrt.obl(scrlist.obs)
+229  ListGetFirstItem                                   isrt.obl(scrlist.obs)
+230  ListGetFirstString                                 isrt.obl(scrlist.obs)
+231  ListGetLastString                                  iswi.obl(CompHelperFuncs.obs)
+232  ListGetNextItem                                    isrt.obl(scrlist.obs)
+233  ListGetNextString                                  isrt.obl(scrlist.obs)
+234  ListGetType                                        isrt.obl(scrlist.obs)
+235  ListSetIndex                                       isrt.obl(scrlist.obs)
+236  LongPathToQuote                                    isrt.obl(Str.obs)
+237  MAKELONG                                           isrt.obl(Misc.obs)
+238  MIFCreateMIFFile                                   isrt.obl(MIF.obs)
+239  MIFDeleteMIFFile                                   isrt.obl(MIF.obs)
+240  MIFInitialize                                      isrt.obl(MIF.obs)
+241  MIFSetInformation                                  isrt.obl(MIF.obs)
+242  MIFUnInitialize                                    isrt.obl(MIF.obs)
+243  MIFWasSetInformationCalled                         isrt.obl(MIF.obs)
+244  MessageBeep                                        isrt.obl(Misc.obs)
+245  MessageBox                                         isrt.obl(MsgBox.obs)
+246  Moved                                              iswi.obl(FileTransferFuncsConv.obs)
+247  Moving                                             iswi.obl(FileTransferFuncsConv.obs)
+248  MsiCloseHandle                                     iswi.obl(MsiFuncsConv.obs)
+249  MsiCreateRecord                                    iswi.obl(MsiFuncsConv.obs)
+250  MsiDatabaseOpenView                                iswi.obl(MsiFuncsConv.obs)
+251  MsiDoAction                                        iswi.obl(MsiFuncsConv.obs)
+252  MsiGetActiveDatabase                               iswi.obl(MsiFuncsConv.obs)
+253  MsiGetFeatureState                                 iswi.obl(MsiFuncsConv.obs)
+254  MsiGetProperty                                     iswi.obl(MsiFuncsConv.obs)
+255  MsiGetPropertyIS                                   iswi.obl(MsiFuncsConv.obs)
+256  MsiGetSourcePath                                   iswi.obl(MsiFuncsConv.obs)
+257  MsiGetTargetPath                                   iswi.obl(MsiFuncsConv.obs)
+258  MsiInstallProduct                                  iswi.obl(MsiFuncsConv.obs)
+259  MsiProcessMessage                                  iswi.obl(MsiFuncsConv.obs)
+260  MsiRecordGetInteger                                iswi.obl(MsiFuncsConv.obs)
+261  MsiRecordGetString                                 iswi.obl(MsiFuncsConv.obs)
+262  MsiRecordSetString                                 iswi.obl(MsiFuncsConv.obs)
+263  MsiSetProperty                                     iswi.obl(MsiFuncsConv.obs)
+264  MsiSetTargetPath                                   iswi.obl(MsiFuncsConv.obs)
+265  MsiViewExecute                                     iswi.obl(MsiFuncsConv.obs)
+266  MsiViewFetch                                       iswi.obl(MsiFuncsConv.obs)
+267  OnAbort                                            iswi.obl(DriverConv.obs)
+268  OnAction                                           iswi.obl(ISWiInit.obs)
+269  OnAdminInstallUIAfter                              iswi.obl(DriverConv.obs)
+270  OnAdminInstallUIBefore                             iswi.obl(DriverConv.obs)
+271  OnAdminPatchUIAfter                                iswi.obl(DriverConv.obs)
+272  OnAdminPatchUIBefore                               iswi.obl(DriverConv.obs)
+273  OnAdvertisementAfter                               iswi.obl(DriverConv.obs)
+274  OnAdvertisementBefore                              iswi.obl(DriverConv.obs)
+275  OnAppSearch                                        iswi.obl(DriverConv.obs)
+276  OnBegin                                            iswi.obl(DriverConv.obs)
+277  OnCCPSearch                                        iswi.obl(DriverConv.obs)
+278  OnCanceling                                        iswi.obl(DriverConv.obs)
+279  OnComponentError                                   iswi.obl(Exceptions.obs)
+280  OnEnd                                              iswi.obl(DriverConv.obs)
+281  OnError                                            iswi.obl(DriverConv.obs)
+282  OnException                                        iswi.obl(Exceptions.obs)
+283  OnFeaturesInstalled                                iswi.obl(FileTransferFuncsConv.obs)
+284  OnFeaturesInstalling                               iswi.obl(FileTransferFuncsConv.obs)
+285  OnFilesInUse                                       iswi.obl(DriverConv.obs)
+286  OnFirstUIAfter                                     setup.obs
+287  OnFirstUIBefore                                    setup.obs
+288  OnGeneratedMSIScript                               iswi.obl(FileTransferFuncsConv.obs)
+289  OnGeneratingMSIScript                              iswi.obl(FileTransferFuncsConv.obs)
+290  OnHelp                                             iswi.obl(DriverConv.obs)
+291  OnInstallFilesActionAfter                          iswi.obl(FileTransferFuncsConv.obs)
+292  OnInstallFilesActionBefore                         iswi.obl(FileTransferFuncsConv.obs)
+293  OnMaintUIAfter                                     iswi.obl(DriverConv.obs)
+294  OnMaintUIBefore                                    setup.obs
+295  OnMaintenance                                      iswi.obl(DriverConv.obs)
+296  OnMoved                                            iswi.obl(FileTransferFuncsConv.obs)
+297  OnMoving                                           iswi.obl(FileTransferFuncsConv.obs)
+298  OnMsiSilentInstall                                 iswi.obl(DriverConv.obs)
+299  OnOutOfDiskSpace                                   iswi.obl(DriverConv.obs)
+300  OnPatchUIAfter                                     iswi.obl(DriverConv.obs)
+301  OnPatchUIBefore                                    iswi.obl(DriverConv.obs)
+302  OnRebooted                                         iswi.obl(DriverConv.obs)
+303  OnResolveSource                                    iswi.obl(DriverConv.obs)
+304  OnSelfRegistrationError                            iswi.obl(Exceptions.obs)
+305  OnUnhandledException                               iswi.obl(DriverConv.obs)
+306  OnUninstall                                        iswi.obl(DriverConv.obs)
+307  OnWarning                                          iswi.obl(DriverConv.obs)
+308  OpenFile                                           isrt.obl(Files.obs)
+309  OpenFileMode                                       isrt.obl(Files.obs)
+310  ParsePath                                          isrt.obl(Str.obs)
+311  ProgDefGroupType                                   isrt.obl(Shell.obs)
+312  ProgGetGroupType                                   isrt.obl(Shell.obs)
+313  PthFixPath                                         isrt.obl(Pth.obs)
+314  PthIsAbsPath                                       isrt.obl(Pth.obs)
+315  RebootNeeded                                       iswi.obl(FileTransferFuncsConv.obs)
+316  RedirectMsiCloseHandle                             iswi.obl(RedirectedMsiFuncsConv.obs)
+317  RedirectMsiCreateRecord                            iswi.obl(RedirectedMsiFuncsConv.obs)
+318  RedirectMsiGetActiveDatabase                       iswi.obl(RedirectedMsiFuncsConv.obs)
+319  RedirectMsiProcessMessage                          iswi.obl(RedirectedMsiFuncsConv.obs)
+320  RedirectMsiRecordGetInteger                        iswi.obl(RedirectedMsiFuncsConv.obs)
+321  RedirectMsiViewExecute                             iswi.obl(RedirectedMsiFuncsConv.obs)
+322  RedirectMsiViewFetch                               iswi.obl(RedirectedMsiFuncsConv.obs)
+323  RegDBGetKeyValueEx                                 iswi.obl(RegistryConv.obs)
+324  RegDBInit                                          iswi.obl(RegistryConv.obs)
+325  RegDBQueryValue                                    iswi.obl(RegistryConv.obs)
+326  RegDBSetDefaultRoot                                iswi.obl(RegistryConv.obs)
+327  ReleaseDialog                                      isrt.obl(CustomDlg.obs)
+328  RemoveSpaces                                       iswi.obl(HelperFuncs.obs)
+329  ResolveShellObjectsFolder                          iswi.obl(CompHelperFuncs.obs)
+330  SdAskDestPath                                      isrt.obl(SDADPATH.obs)
+331  SdCloseDlg                                         isrt.obl(SDINT.obs)
+332  SdComponentDlgCheckSpace                           isrt.obl(SDINT.obs)
+333  SdComponentTree                                    isrt.obl(SDCOMTREE.obs)
+334  SdDlgToTop                                         isrt.obl(SDINT.obs)
+335  SdDoStdButton                                      isrt.obl(SDINT.obs)
+336  SdEnablement                                       isrt.obl(SDINT.obs)
+337  SdError                                            isrt.obl(SDINT.obs)
+338  SdFeatureTree                                      iswi.obl(FeatureFuncsConv.obs)
+339  SdFilesInUse                                       iswi.obl(SdFilesInUse.obs)
+340  SdFinish                                           isrt.obl(SDFINISH.obs)
+341  SdFinishEx                                         isrt.obl(SdFinishEx.obs)
+342  SdFinishReboot                                     isrt.obl(SDFINBOT.obs)
+343  SdGeneralInit                                      isrt.obl(SDINT.obs)
+344  SdInit                                             isrt.obl(SDINT.obs)
+345  SdIsStdButton                                      isrt.obl(SDINT.obs)
+346  SdLoadString                                       isrt.obl(SDINT.obs)
+347  SdMakeName                                         isrt.obl(SDINT.obs)
+348  SdOutOfDiskSpace                                   iswi.obl(SdDiskReqs.obs)
+349  SdPatchWelcome                                     iswi.obl(SdPatchWel.obs)
+350  SdPlugInProductName                                isrt.obl(SDINT.obs)
+351  SdProductName                                      iswi.obl(SdprodctConv.obs)
+352  SdSetDlgTitle                                      isrt.obl(SDINT.obs)
+353  SdSetStatic                                        isrt.obl(SDINT.obs)
+354  SdSetupCompleteError                               iswi.obl(SdSetupCompleteError.obs)
+355  SdSetupTypeEx                                      isrt.obl(Sdstypex.obs)
+356  SdUnInit                                           isrt.obl(SDINT.obs)
+357  SdWelcome                                          isrt.obl(SDWEL.obs)
+358  SdWelcomeMaint                                     isrt.obl(SdWelcomeMaint.obs)
+359  SelectDir                                          isrt.obl(SelectDir.obs)
+360  SelectDirNoLog                                     isrt.obl(SelectDir.obs)
+361  SendMessage                                        isrt.obl(Misc.obs)
+362  SetCmdLine                                         isrt.obl(SysVars.obs)
+363  SetDisplayEffect                                   isrt.obl(ui.obs)
+364  SetFolderDesktop                                   isrt.obl(SysVars.obs)
+365  SetFolderPrograms                                  isrt.obl(SysVars.obs)
+366  SetFolderStartMenu                                 isrt.obl(SysVars.obs)
+367  SetFolderStartup                                   isrt.obl(SysVars.obs)
+368  SetGlobalVars                                      iswi.obl(ISWiInit.obs)
+369  SetInstallationInfo                                iswi.obl(RegistryConv.obs)
+370  SetMifInformationOnly                              iswi.obl(RegistryConv.obs)
+371  SetMsiHandle                                       iswi.obl(SysVarsConv.obs)
+372  SetPatch                                           iswi.obl(SysVarsConv.obs)
+373  SetSourceDir                                       iswi.obl(SysVarsConv.obs)
+374  SilentDoGeneralInfo                                isrt.obl(Silent.obs)
+375  SilentFailed                                       isrt.obl(Silent.obs)
+376  SilentFinish                                       isrt.obl(Silent.obs)
+377  SilentGetMode                                      isrt.obl(Silent.obs)
+378  SilentInit                                         isrt.obl(Silent.obs)
+379  SilentReadData                                     isrt.obl(Silent.obs)
+380  SilentSetInfo                                      isrt.obl(Silent.obs)
+381  SilentSetMode                                      isrt.obl(Silent.obs)
+382  SilentWriteData                                    isrt.obl(Silent.obs)
+383  Sprintf                                            isrt.obl(Str.obs)
+384  SprintfBox                                         isrt.obl(MsgBox.obs)
+385  SprintfMsiLog                                      iswi.obl(HelperFuncs.obs)
+386  StrDelete                                          iswi.obl(HelperFuncs.obs)
+387  StrGetTokens                                       isrt.obl(Str.obs)
+388  StrLength                                          isrt.obl(Str.obs)
+389  StrRemoveLastSlash                                 isrt.obl(Str.obs)
+390  StrRemoveSpaces                                    isrt.obl(Str.obs)
+391  StrToUpper                                         isrt.obl(Str.obs)
+392  SysVarsInit                                        isrt.obl(SysVars.obs)
+393  SysVarsInitConv                                    iswi.obl(SysVarsConv.obs)
+394  SysVarsUnInit                                      iswi.obl(SysVarsConv.obs)
+395  System                                             isrt.obl(Misc.obs)
+396  TreeViewCreate                                     isrt.obl(CmptView.obs)
+397  USER.EnableWindow                                  setup.obs
+398  USER.GetClassName                                  setup.obs
+399  USER.GetDC                                         setup.obs
+400  USER.GetDlgItem                                    setup.obs
+401  USER.GetFocus                                      setup.obs
+402  USER.GetWindowLong                                 setup.obs
+403  USER.IsIconic                                      setup.obs
+404  USER.IsWindow                                      setup.obs
+405  USER.IsWindowVisible                               iswi.obl(AdminAskPath.obs)
+406  USER.ReleaseDC                                     setup.obs
+407  USER.SendMessageA                                  iswi.obl(AdminAskPath.obs)
+408  USER.SetFocus                                      setup.obs
+409  USER.SetForegroundWindow                           iswi.obl(AdminAskPath.obs)
+410  USER.SetWindowPos                                  setup.obs
+411  USER.SetWindowText                                 setup.obs
+412  USER.ShowWindow                                    setup.obs
+413  USER32.CharUpperBuffA                              iswi.obl(AdminAskPath.obs)
+414  USER32.FindWindowA                                 iswi.obl(AdminAskPath.obs)
+415  USER32.GetDlgItem                                  iswi.obl(SdDiskReqs.obs)
+416  USER32.GetSystemMetrics                            iswi.obl(AdminAskPath.obs)
+417  USER32.GetWindowRect                               iswi.obl(SdDiskReqs.obs)
+418  USER32.GetWindowText                               iswi.obl(AdminAskPath.obs)
+419  USER32.GetWindowTextLength                         iswi.obl(AdminAskPath.obs)
+420  USER32.MessageBoxA                                 iswi.obl(AdminAskPath.obs)
+421  USER32.SendMessageA                                iswi.obl(AdminAskPath.obs)
+422  USER32.SetWindowLong                               iswi.obl(AdminAskPath.obs)
+423  USER32.SetWindowRgn                                iswi.obl(AdminAskPath.obs)
+424  User32.DestroyWindow                               iswi.obl(SdDiskReqs.obs)
+425  User32.LoadStringA                                 iswi.obl(ComponentConv.obs)
+426  WaitOnDialog                                       isrt.obl(CustomDlg.obs)
+427  WriteLine                                          isrt.obl(Files.obs)
+428  WriteProfString                                    isrt.obl(Profile.obs)
+429  _HandleException                                   isrt.obl(exceptions.obs)
+430  __AddIntegerToArray                                iswi.obl(HelperFuncs.obs)
+431  __AddStringToArray                                 iswi.obl(HelperFuncs.obs)
+432  __ComponentListItemsEx                             iswi.obl(CompHelperFuncs.obs)
+433  __ComponentListItemsExInstall                      iswi.obl(CompHelperFuncs.obs)
+434  __ComponentListItemsExUnInstall                    iswi.obl(CompHelperFuncs.obs)
+435  __ComponentMoveXferData                            iswi.obl(CompHelperFuncs.obs)
+436  __DefaultExitHandler                               isrt.obl(handlers.obs)
+437  __GetFinishMode                                    iswi.obl(ISWiInit.obs)
+438  __HandleError                                      iswi.obl(ErrHandler.obs)
+439  __ISRTDoExit                                       isrt.obl(Misc.obs)
+440  __ISRTInit                                         isrt.obl(ISRTInit.obs)
+441  __ISRTRestoreMainLog                               isrt.obl(ISRTInit.obs)
+442  __ISRTSetComponentLog                              isrt.obl(ISRTInit.obs)
+443  __ISRTUnInit                                       isrt.obl(ISRTInit.obs)
+444  __ISWIInit                                         iswi.obl(ISWiInit.obs)
+445  __ISWIMsiHandle                                    iswi.obl(ISWiInit.obs)
+446  __ISWIUnInit                                       iswi.obl(ISWiInit.obs)
+447  __IsArrayEmpty                                     iswi.obl(HelperFuncs.obs)
+448  __LoadIScriptString                                iswi.obl(ISWiInit.obs)
+449  __MsiGetFeatureState                               iswi.obl(MsiWrappersConv.obs)
+450  __MsiOpenView                                      iswi.obl(CompHelperFuncs.obs)
+451  __MsiRecordGetString                               iswi.obl(MsiWrappersConv.obs)
+452  __OnAbort                                          iswi.obl(DriverConv.obs)
+453  __OnAdminPatch                                     iswi.obl(DriverConv.obs)
+454  __OnAdministrativeInstall                          iswi.obl(DriverConv.obs)
+455  __OnAdvertisement                                  iswi.obl(DriverConv.obs)
+456  __OnBegin                                          iswi.obl(DriverConv.obs)
+457  __OnCanceling                                      iswi.obl(DriverConv.obs)
+458  __OnEnd                                            iswi.obl(DriverConv.obs)
+459  __OnError                                          iswi.obl(DriverConv.obs)
+460  __OnMsiMaintenance                                 iswi.obl(DriverConv.obs)
+461  __OnMsiRebooted                                    iswi.obl(DriverConv.obs)
+462  __OnMsiSilentInstall                               iswi.obl(DriverConv.obs)
+463  __OnMsiUninstall                                   iswi.obl(DriverConv.obs)
+464  __OnPatch                                          iswi.obl(DriverConv.obs)
+465  __OnWarning                                        iswi.obl(DriverConv.obs)
+466  __ResetMsiObject                                   iswi.obl(ISWiInit.obs)
+467  __SetMaintenance                                   iswi.obl(ISWiInit.obs)
+468  __SetMsiServer                                     iswi.obl(ISWiInit.obs)
+469  isrt.IsEmpty                                       iswi.obl(HelperFuncs.obs)
+470  isrt.IsObject                                      iswi.obl(MsiFuncsConv.obs)
+471  isrt._ComponentGetData                             iswi.obl(ComponentConv.obs)
+472  isrt._ComponentIsItemSelected                      iswi.obl(ComponentConv.obs)
+473  isrt._ComponentListItems                           iswi.obl(ComponentConv.obs)
+474  isrt._ComponentReinstall                           iswi.obl(ComponentConv.obs)
+475  isrt._ComponentRemoveAll                           iswi.obl(ComponentConv.obs)
+476  isrt._ComponentSelectItem                          iswi.obl(ComponentConv.obs)
+477  isrt._ComponentSetupTypeGetData                    iswi.obl(ComponentConv.obs)
+478  isrt._ComponentSetupTypeSet                        iswi.obl(ComponentConv.obs)
+479  isrt._EnableDialogCache                            iswi.obl(ISWiInit.obs)
+480  kernel32.GetLocalTime                              iswi.obl(ErrHandler.obs)
+481  kernel32.GetWindowsDirectoryA                      iswi.obl(ErrHandler.obs)
+482  msi.MsiCloseHandle                                 iswi.obl(RedirectedMsiFuncsConv.obs)
+483  msi.MsiCreateRecord                                iswi.obl(RedirectedMsiFuncsConv.obs)
+484  msi.MsiDatabaseOpenViewA                           setup.obs
+485  msi.MsiDoActionA                                   setup.obs
+486  msi.MsiGetActiveDatabase                           iswi.obl(RedirectedMsiFuncsConv.obs)
+487  msi.MsiGetFeatureStateA                            setup.obs
+488  msi.MsiGetProductInfoA                             setup.obs
+489  msi.MsiGetPropertyA                                setup.obs
+490  msi.MsiGetSourcePathA                              setup.obs
+491  msi.MsiGetTargetPathA                              setup.obs
+492  msi.MsiOpenDatabaseA                               setup.obs
+493  msi.MsiProcessMessage                              iswi.obl(RedirectedMsiFuncsConv.obs)
+494  msi.MsiRecordGetInteger                            iswi.obl(RedirectedMsiFuncsConv.obs)
+495  msi.MsiRecordGetStringA                            setup.obs
+496  msi.MsiRecordSetStringA                            setup.obs
+497  msi.MsiSetPropertyA                                setup.obs
+498  msi.MsiSetTargetPathA                              setup.obs
+499  msi.MsiViewExecute                                 iswi.obl(RedirectedMsiFuncsConv.obs)
+500  msi.MsiViewFetch                                   iswi.obl(RedirectedMsiFuncsConv.obs)
+501  program                                            iswi.obl(DriverConv.obs)
+502  sfc.SRSetRestorePoint                              setup.obs
+
+
+***** External Variables *****
+1    AdminToolsFolder                                   iswi.obl(DebugSymbolsConv.obs)
+2    AppDataFolder                                      iswi.obl(DebugSymbolsConv.obs)
+3    BATCH_INSTALL                                      setup.obs
+4    CMDLINE                                            iswi.obl(DebugSymbolsConv.obs)
+5    CMPTFILTERLANGOBJ                                  iswi.obl(CompHelperFuncs.obs)
+6    COMMONFILES                                        iswi.obl(DebugSymbolsConv.obs)
+7    CommonAppDataFolder                                iswi.obl(DebugSymbolsConv.obs)
+8    CommonFiles64Folder                                iswi.obl(DebugSymbolsConv.obs)
+9    CommonFilesFolder                                  iswi.obl(DebugSymbolsConv.obs)
+10   DISK1TARGET                                        setup.obs
+11   DesktopFolder                                      iswi.obl(DebugSymbolsConv.obs)
+12   ERRORFILENAME                                      setup.obs
+13   ERRORINFO                                          iswi.obl(ComponentConv.obs)
+14   Err                                                setup.obs
+15   FEATURE                                            iswi.obl(ComponentConv.obs)
+16   FILEERROR                                          iswi.obl(ComponentConv.obs)
+17   FILETIME                                           iswi.obl(AdminAskPath.obs)
+18   FIND_DATA                                          iswi.obl(AdminAskPath.obs)
+19   FOLDER_DESKTOP                                     iswi.obl(DebugSymbolsConv.obs)
+20   FOLDER_PROGRAMS                                    iswi.obl(DebugSymbolsConv.obs)
+21   FOLDER_STARTMENU                                   iswi.obl(DebugSymbolsConv.obs)
+22   FOLDER_STARTUP                                     iswi.obl(DebugSymbolsConv.obs)
+23   FavoritesFolder                                    iswi.obl(DebugSymbolsConv.obs)
+24   FileRegistrar                                      setup.obs
+25   FontsFolder                                        iswi.obl(DebugSymbolsConv.obs)
+26   INSTALLDIR                                         setup.obs
+27   ISMSI_HANDLE                                       iswi.obl(DebugSymbolsConv.obs)
+28   ISRES                                              iswi.obl(DebugSymbolsConv.obs)
+29   ISUSER                                             iswi.obl(DebugSymbolsConv.obs)
+30   ISUTIL_FUNCTION_ERROR                              iswi.obl(CompHelperFuncs.obs)
+31   ISUTIL_LINE_NUMBER                                 iswi.obl(CompHelperFuncs.obs)
+32   ISUTIL_POSITIVE_ERROR                              iswi.obl(CompHelperFuncs.obs)
+33   ISUTIL_SCRIPT_FILE                                 iswi.obl(CompHelperFuncs.obs)
+34   ISVERSION                                          iswi.obl(DebugSymbolsConv.obs)
+35   LAST_RESULT                                        setup.obs
+36   LVITEM                                             iswi.obl(SdDiskReqs.obs)
+37   LV_COLUMN                                          iswi.obl(SdDiskReqs.obs)
+38   LocalAppDataFolder                                 iswi.obl(DebugSymbolsConv.obs)
+39   LogDB                                              setup.obs
+40   MAINTENANCE                                        iswi.obl(DebugSymbolsConv.obs)
+41   MEDIA                                              setup.obs
+42   MODE                                               iswi.obl(DebugSymbolsConv.obs)
+43   MainWindow                                         setup.obs
+44   MyPicturesFolder                                   iswi.obl(DebugSymbolsConv.obs)
+45   NOTHING                                            setup.obs
+46   NetHoodFolder                                      iswi.obl(DebugSymbolsConv.obs)
+47   OSINFO_PLATFORM_INFO                               setup.obs
+48   OSVERSIONINFO                                      iswi.obl(AdminAskPath.obs)
+49   OSVERSIONINFOEX                                    iswi.obl(AdminAskPath.obs)
+50   Objects                                            setup.obs
+51   PATCH                                              iswi.obl(DebugSymbolsConv.obs)
+52   PRODUCT_GUID                                       iswi.obl(DebugSymbolsConv.obs)
+53   PROGRAMFILES                                       iswi.obl(DebugSymbolsConv.obs)
+54   PersonalFolder                                     iswi.obl(DebugSymbolsConv.obs)
+55   PrintHoodFolder                                    iswi.obl(DebugSymbolsConv.obs)
+56   ProgramFiles64Folder                               iswi.obl(DebugSymbolsConv.obs)
+57   ProgramFilesFolder                                 iswi.obl(DebugSymbolsConv.obs)
+58   ProgramMenuFolder                                  iswi.obl(DebugSymbolsConv.obs)
+59   RECT                                               iswi.obl(AdminAskPath.obs)
+60   Reboot                                             setup.obs
+61   RecentFolder                                       iswi.obl(DebugSymbolsConv.obs)
+62   SELECTED_LANGUAGE                                  iswi.obl(DebugSymbolsConv.obs)
+63   SHELL_OBJECT_FOLDER                                setup.obs
+64   SRCDIR                                             setup.obs
+65   SRCDISK                                            iswi.obl(DebugSymbolsConv.obs)
+66   SUPPORTDIR                                         iswi.obl(DebugSymbolsConv.obs)
+67   SYSTEMTIME                                         iswi.obl(AdminAskPath.obs)
+68   SYSTEMTIME2                                        iswi.obl(ErrHandler.obs)
+69   SendToFolder                                       iswi.obl(DebugSymbolsConv.obs)
+70   SetupInfo                                          setup.obs
+71   SourceDir                                          iswi.obl(DebugSymbolsConv.obs)
+72   StartMenuFolder                                    iswi.obl(DebugSymbolsConv.obs)
+73   StartupFolder                                      iswi.obl(DebugSymbolsConv.obs)
+74   StatusDlg                                          setup.obs
+75   System16Folder                                     iswi.obl(DebugSymbolsConv.obs)
+76   System64Folder                                     iswi.obl(DebugSymbolsConv.obs)
+77   SystemFolder                                       iswi.obl(DebugSymbolsConv.obs)
+78   TARGETDIR                                          setup.obs
+79   TARGETDISK                                         iswi.obl(DebugSymbolsConv.obs)
+80   TempFolder                                         iswi.obl(DebugSymbolsConv.obs)
+81   TemplateFolder                                     iswi.obl(DebugSymbolsConv.obs)
+82   TextSub                                            setup.obs
+83   UNINST                                             setup.obs
+84   UNINSTALL_STRING                                   setup.obs
+85   WINDIR                                             iswi.obl(DebugSymbolsConv.obs)
+86   WINDISK                                            iswi.obl(DebugSymbolsConv.obs)
+87   WINSYSDIR                                          iswi.obl(DebugSymbolsConv.obs)
+88   WINSYSDISK                                         iswi.obl(DebugSymbolsConv.obs)
+89   WindowsFolder                                      iswi.obl(DebugSymbolsConv.obs)
+90   WindowsVolume                                      iswi.obl(DebugSymbolsConv.obs)
+91   _INT64                                             setup.obs
+92   _RESTOREINFO_                                      setup.obs
+93   _RESTOREPTINFO                                     setup.obs
+94   _SMGRSTATUS                                        setup.obs
+95   _SMGSTATUS_                                        setup.obs
+96   _WIN9X                                             setup.obs
+97   _WINNT                                             setup.obs
+98   __SYSTEMINFORMATION                                setup.obs
+99   __gbAliasingOff                                    iswi.obl(CompHelperFuncs.obs)
+100  __gbGetTarget                                      iswi.obl(CompHelperFuncs.obs)
+101  __gbInitialized                                    iswi.obl(CompHelperFuncs.obs)
+102  __gbInstallInfo                                    setup.obs
+103  __gbMaintenance                                    iswi.obl(CompHelperFuncs.obs)
+104  __gbReopening                                      iswi.obl(CompHelperFuncs.obs)
+105  __ghActiveDataBase                                 iswi.obl(CompHelperFuncs.obs)
+106  __ghErrFileHandle                                  iswi.obl(CompHelperFuncs.obs)
+107  __ghMsiInstall                                     iswi.obl(CompHelperFuncs.obs)
+108  __gnButtonSelected                                 iswi.obl(CompHelperFuncs.obs)
+109  __gnLastError                                      iswi.obl(CompHelperFuncs.obs)
+110  __gnMsiReturn                                      iswi.obl(CompHelperFuncs.obs)
+111  __gnOSMask                                         iswi.obl(CompHelperFuncs.obs)
+112  __gnScriptMode                                     iswi.obl(CompHelperFuncs.obs)
+113  __goISDriver                                       iswi.obl(CompHelperFuncs.obs)
+114  __goLanguageFilter                                 iswi.obl(CompHelperFuncs.obs)
+115  __goMsiServer                                      iswi.obl(CompHelperFuncs.obs)
+116  __gsINSTALLDIR                                     iswi.obl(CompHelperFuncs.obs)
+117  __gsProductGuid                                    iswi.obl(CompHelperFuncs.obs)
+118  __gsSourceDir                                      iswi.obl(CompHelperFuncs.obs)
+119  __hContext                                         iswi.obl(CompHelperFuncs.obs)
+120  __objGlobalTextSub                                 setup.obs
+121  __objStringTable                                   iswi.obl(ISWiInit.obs)
+122  __szGUID                                           iswi.obl(RegistryConv.obs)
+123  bBackButton                                        setup.obs
+124  bCancelButton                                      setup.obs
+125  bEnterDiskBeep                                     iswi.obl(AdminAskPath.obs)
+126  bFinishButton                                      setup.obs
+127  bIfxPCHInitialized                                 setup.obs
+128  bIfxPCHOn                                          setup.obs
+129  bInstall16                                         setup.obs
+130  bNextButton                                        setup.obs
+131  bSdInit                                            setup.obs
+132  bViewCmptKunits                                    setup.obs
+133  bViewCmptUseDecimal                                setup.obs
+134  g_bSuppressMissingStringWarning                    iswi.obl(DriverConv.obs)
+135  nIfxPCHType                                        setup.obs
+136  szAppKey                                           setup.obs
+137  szInstallDeinstKey                                 setup.obs
+138  szSdProduct                                        setup.obs
+139  szSdStr_NotEnoughSpace                             setup.obs
Index: /tags/start/is7_bbc/BBC Collection/Setup.rul
===================================================================
--- /tags/start/is7_bbc/BBC Collection/Setup.rul	(revision 13666)
+++ /tags/start/is7_bbc/BBC Collection/Setup.rul	(revision 13666)
@@ -0,0 +1,289 @@
+
+////////////////////////////////////////////////////////////////////////////////
+//                                                                            
+//  File Name:	Setup.rul                                                   
+//                                                                            
+//  Description:	InstallShield script                                        
+//                                                                            
+//  Comments:	This script was generated based on the selections you made in
+//           	the Project Wizard.  Refer to the help topic entitled "Modify      
+//           	the script that the Project Wizard generates" for information
+//				on possible next steps.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+
+// Include header files
+    
+#include "ifx.h"
+    
+////////////////////// string defines ////////////////////////////
+
+// these macros should match the MSI properties with the same names
+#define GSDL "gsdl"
+#define GSDL_COLLECTION "bbc"
+#define GSDL_SUBCOLLECTION "bfi1"
+
+
+
+//////////////////// installation declarations ///////////////////
+
+// ----- DLL function prototypes -----
+
+
+    // your DLL function prototypes
+
+
+// ---- script function prototypes -----
+
+
+    // your script function prototypes
+	prototype check_registry();
+	prototype edit_gsdlsite();
+
+    // your global variables
+    BOOL bIsMulti;
+    STRING szInstallDir;
+
+//////////////////////////////////////////////////////////////////////////////
+//                                                                           
+//  FUNCTION:   OnFirstUIBefore                                            
+//                                                                           
+//  EVENT:      FirstUIBefore event is sent when installation is run for the first
+//              time on given machine. In the handler installation usually displays
+//              UI allowing end user to specify installation parameters. After this
+//              function returns, FeatureTransferData is called to perform file
+//              transfer.
+//                                                                           
+///////////////////////////////////////////////////////////////////////////////
+function OnFirstUIBefore()
+    number  nResult;
+    string  szTitle, szMsg;
+    string  szTargetPath;
+    string  szDir, svSetupType;
+    number  nvSize;
+begin	
+    // TO DO: if you want to enable background, window title, and caption bar title                                                                     
+    // SetTitle( @PRODUCT_NAME, 24, WHITE );                                        
+    // SetTitle( @PRODUCT_NAME, 0, BACKGROUNDCAPTION ); 	                   
+    // Enable( FULLWINDOWMODE );						   
+    // Enable( BACKGROUND );							  
+    // SetColor(BACKGROUND,RGB (0, 128, 128));					   
+    
+    SHELL_OBJECT_FOLDER = @PRODUCT_NAME;
+    
+    svSetupType = "Full";	
+    szDir = INSTALLDIR;
+    
+    // check if this collection is a second or subsequent volume
+    // in a multi-volume set (check_registry sets the bIsMulti and
+    // szInstallDir variables)
+    bIsMulti = FALSE;
+    szInstallDir = "";
+    check_registry();
+    
+        
+Dlg_Start:
+    // beginning of dialogs label
+
+Dlg_SdWelcome:
+    szTitle = "";
+    szMsg   = "";
+    nResult = SdWelcome( szTitle, szMsg );
+    if (nResult = BACK) goto Dlg_Start;
+
+// If we're installing a subsequent volume of a multi-volume set
+// we won't give the user the option of where to install it. We'll
+// just force them to install it in the same place as the previous
+// volume.
+Dlg_SdAskDestPath:
+	if (!bIsMulti) then
+    	szTitle = "";
+    	szMsg   = "";
+    	nResult = SdAskDestPath( szTitle, szMsg, szDir, 0 );
+    	INSTALLDIR = szDir;
+    	if (nResult = BACK) goto Dlg_SdWelcome;
+	else        
+		szDir = szInstallDir;
+		INSTALLDIR = szDir;
+	endif;	
+
+Dlg_SetupType:   
+    szTitle    = "";
+    szMsg      = "";
+    nResult = SdSetupTypeEx ( szTitle , szMsg , "" , svSetupType , 0 );
+    if (nResult = BACK) then
+        if (bIsMulti) then
+        	goto Dlg_SdWelcome;
+        else 
+        	goto Dlg_SdAskDestPath;
+        endif;
+    else
+        szTargetPath = INSTALLDIR;
+	    nvSize = 0;
+	    FeatureCompareSizeRequired(MEDIA,szTargetPath,nvSize);
+	    if (nvSize != 0) then      
+       	   MessageBox( szSdStr_NotEnoughSpace, WARNING );
+	       goto Dlg_SetupType;
+        endif;
+    endif;   
+    
+    Enable(STATUSEX);
+
+    return 0;
+end;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+//  FUNCTION:   OnMaintUIBefore
+//
+//  EVENT:      MaintUIBefore event is sent when end user runs installation that
+//              has already been installed on the machine. Usually this happens 
+//              through Add/Remove Programs applet. In the handler, installation 
+//              usually displays UI allowing end user to modify existing installation
+//              or uninstall application. After this function returns, 
+//              FeatureTransferData is called to perform file transfer.
+//
+///////////////////////////////////////////////////////////////////////////////
+function OnMaintUIBefore()
+    NUMBER nResult, nType;
+    STRING szTitle, szMsg, svDir, svResult, szCaption;
+begin
+    // TO DO: if you want to enable background, window title, and caption bar title   								
+    // SetTitle( @PRODUCT_NAME, 24, WHITE );					
+    // SetTitle( @PRODUCT_NAME, 0, BACKGROUNDCAPTION );  			
+    // SetColor(BACKGROUND,RGB (0, 128, 128));					
+    // Enable( FULLWINDOWMODE );						
+    // Enable( BACKGROUND );							
+	
+Dlg_Start:
+    Disable(BACKBUTTON);
+    nType = SdWelcomeMaint(szTitle, szMsg, MODIFY);
+    Enable(BACKBUTTON);
+
+    if (nType = REMOVEALL) then
+        svResult = SdLoadString(IFX_MAINTUI_MSG);
+        szCaption = SdLoadString(IFX_ONMAINTUI_CAPTION);
+        nResult = SprintfBox(MB_OKCANCEL,szCaption,"%s",svResult);
+        if (nResult = IDCANCEL) goto Dlg_Start;
+    endif;
+
+    nResult = NEXT;
+
+Dlg_SdFeatureTree:
+    if (nType = MODIFY) then
+        szTitle = "";
+        szMsg = "";
+        nResult = SdFeatureTree(szTitle, szMsg, TARGETDIR, "", 2);
+        if (nResult = BACK) goto Dlg_Start;
+    endif;
+
+    switch(nType)
+        case REMOVEALL: ComponentRemoveAll();
+        case REPAIR:    ComponentReinstall();
+    endswitch;
+    
+    Enable(STATUSEX);
+end;
+///////////////////////////////////////////////////////////////////////////////
+//
+//  FUNCTION:   OnFirstUIAfter
+//
+//  EVENT:      FirstUIAfter event is sent after file transfer, when installation 
+//              is run for the first time on given machine. In this event handler 
+//              installation usually displays UI that will inform end user that
+//              installation has been completed successfully.
+//
+///////////////////////////////////////////////////////////////////////////////
+function OnFirstUIAfter()
+	STRING szTitle, szMsg1, szMsg2, szOption1, szOption2;
+	NUMBER bOpt1, bOpt2;
+	STRING szGSDLHOME, szGDBMHOME;
+begin
+	Disable(STATUSEX);
+
+	// edit the gsdlsite.cfg file
+	edit_gsdlsite();
+
+	bOpt1  = FALSE;
+	bOpt2  = FALSE;
+	szMsg1 = SdLoadString(IFX_SDFINISH_MSG1);
+	SdFinishEx(szTitle, szMsg1, szMsg2, szOption1, szOption2, bOpt1, bOpt2);
+end;
+
+   
+// check the registry to find out if this collection is the second
+// or subsequent volume of a multi-volume set
+function check_registry ()
+	STRING szKey, szName, svValue;
+	NUMBER nvType, nvSize;
+begin	    
+
+	bIsMulti = FALSE;
+	szInstallDir = "";
+	                        
+	szKey = "SOFTWARE\\" + GSDL + "\\" + @PRODUCT_VERSION + "\\" + GSDL_COLLECTION;
+	szName = "gsdlhome";
+	                     
+	RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);	                     
+	if (RegDBGetKeyValueEx(szKey, szName, nvType, svValue, nvSize) == 0) then
+          bIsMulti = TRUE;
+          szInstallDir = svValue;
+    endif;
+					  
+end;
+
+// edit the gsdlsite.cfg file - this should be done after 
+// the files have been copied across
+// note the the gsdlsite.cfg component should have its "never
+// overwrite" attribute set so that subsequent volumes of a
+// multi-volume set don't overwrite the existing file
+function edit_gsdlsite ()
+	STRING szFileName, svResult;  
+	BOOL bIsFullInstall;
+begin
+
+	szFileName = INSTALLDIR ^ "gsdlsite.cfg";
+	
+	bIsFullInstall = FeatureIsItemSelected(MEDIA, "full_install");
+	
+	if (!bIsMulti) then
+	    // set top level gsdlhome and gdbmhome fields
+	    // only if this isn't the second or subsequent
+	    // volume
+		if (bIsFullInstall) then
+	      	WriteProfString(szFileName, "gsdl", "gsdlhome", INSTALLDIR);
+	    else
+	        WriteProfString(szFileName, "gsdl", "gsdlhome", SRCDIR ^ "gsdl");
+	    endif;
+	 	WriteProfString(szFileName, "gsdl", "gdbmhome", INSTALLDIR);
+	 
+		// set the "collections" line
+		WriteProfString(szFileName, "gsdl", "collections",
+						GSDL_COLLECTION + "#" + GSDL_SUBCOLLECTION);
+	 
+	 else
+	 
+	 	// append this volume to the existing "collections" line
+	    GetProfString(szFileName, "gsdl", "collections", svResult);
+	    if (StrLengthChars(svResult) > 0) then
+	    	svResult = svResult + ",";
+	    endif;
+		svResult = svResult + GSDL_COLLECTION + "#" + GSDL_SUBCOLLECTION;	          
+		WriteProfString(szFileName, "gsdl", "collections", svResult);
+		          
+	 endif;
+
+	 // add the "collection#volume" section
+	 if (bIsFullInstall) then
+	   	WriteProfString(szFileName, GSDL_COLLECTION + "#" + GSDL_SUBCOLLECTION,
+	   				    "gsdlhome", INSTALLDIR);
+	 else
+	    WriteProfString(szFileName, GSDL_COLLECTION + "#" + GSDL_SUBCOLLECTION,
+	    				"gsdlhome", SRCDIR ^ "gsdl");
+	 endif;
+	 WriteProfString(szFileName, GSDL_COLLECTION + "#" + GSDL_SUBCOLLECTION,
+	 				 "gdbmhome", INSTALLDIR);
+	 
+	 
+end;
Index: /tags/start/is7_bbc/BBC Collection/String1033.txt
===================================================================
--- /tags/start/is7_bbc/BBC Collection/String1033.txt	(revision 13666)
+++ /tags/start/is7_bbc/BBC Collection/String1033.txt	(revision 13666)
@@ -0,0 +1,763 @@
+﻿COMPANY_NAME=NZDL
+DN_AlwaysInstall=Always Install
+IDPROP_ARPCOMMENTS=Your Comments
+IDPROP_ARPCONTACT=Customer Support Department
+IDPROP_ARPHELPLINK=http://www.yourcompany.com/help
+IDPROP_ARPHELPTELEPHONE=1-555-555-4505
+IDPROP_ARPREADME=Readme.txt
+IDPROP_ARPURLINFOABOUT=http://www.greenstone.org
+IDPROP_ARPURLUPDATEINFO=http://www.yourcompany.com/updateinfo
+IDPROP_SETUPTYPE_COMPACT=Compact Installation
+IDPROP_SETUPTYPE_COMPACT_DESC=The compact installation option will install only those files neccessary to run Greenstone. Most of the content of the collection will be retrieved from the CD-ROM when it is required (you must have the CD-ROM in the drive to view your collection if you select this option). If you intend to install a multi-volume set this option is not recommended.
+IDPROP_SETUPTYPE_CUSTOM=Custom
+IDPROP_SETUPTYPE_CUSTOM_DESC=Custom Description
+IDPROP_SETUPTYPE_TYPICAL=Full Installation
+IDPROP_SETUPTYPE_TYPICAL_DESC=A full installation installs the entire collection on your hard drive. This is the best option as long as you have enough free disk space (approximately 650Mb is required for a full CD-ROM collection).
+IDS_ACTIONTEXT_1=Advertising application
+IDS_ACTIONTEXT_10=Computing space requirements
+IDS_ACTIONTEXT_100=MIME Content Type: [1], Extension: [2]
+IDS_ACTIONTEXT_101=Unregistering program identifiers
+IDS_ACTIONTEXT_102=ProgID: [1]
+IDS_ACTIONTEXT_103=Unregistering type libraries
+IDS_ACTIONTEXT_104=LibID: [1]
+IDS_ACTIONTEXT_105=Updating environment strings
+IDS_ACTIONTEXT_106=Name: [1], Value: [2], Action [3]
+IDS_ACTIONTEXT_107=Writing INI file values
+IDS_ACTIONTEXT_108=File: [1],  Section: [2],  Key: [3], Value: [4]
+IDS_ACTIONTEXT_109=Writing system registry values
+IDS_ACTIONTEXT_11=Creating folders
+IDS_ACTIONTEXT_110=Key: [1], Name: [2], Value: [3]
+IDS_ACTIONTEXT_111=Registering COM+ Applications and Components
+IDS_ACTIONTEXT_112=AppId: [1]{{, AppType: [2], Users: [3], RSN: [4]}}
+IDS_ACTIONTEXT_113=Unregistering COM+ Applications and Components
+IDS_ACTIONTEXT_114=AppId: [1]{{, AppType: [2]}}
+IDS_ACTIONTEXT_115=Searching for related applications
+IDS_ACTIONTEXT_116=Found application: [1]
+IDS_ACTIONTEXT_117=Migrating feature states from related applications
+IDS_ACTIONTEXT_118=Application: [1]
+IDS_ACTIONTEXT_119=Removing applications
+IDS_ACTIONTEXT_12=Folder: [1]
+IDS_ACTIONTEXT_120=Application: [1], Command line: [2]
+IDS_ACTIONTEXT_121=Installing system catalog
+IDS_ACTIONTEXT_122=File: [1],  Dependencies: [2]
+IDS_ACTIONTEXT_13=Creating shortcuts
+IDS_ACTIONTEXT_14=Shortcut: [1]
+IDS_ACTIONTEXT_15=Deleting services
+IDS_ACTIONTEXT_16=Service: [1]
+IDS_ACTIONTEXT_17=Creating duplicate files
+IDS_ACTIONTEXT_18=File: [1],  Directory: [9],  Size: [6]
+IDS_ACTIONTEXT_19=Computing space requirements
+IDS_ACTIONTEXT_2=Allocating registry space
+IDS_ACTIONTEXT_20=Generating script operations for action:
+IDS_ACTIONTEXT_21=[1]
+IDS_ACTIONTEXT_22=Copying files to the network
+IDS_ACTIONTEXT_23=File: [1], Directory: [9], Size: [6]
+IDS_ACTIONTEXT_24=Copying new files
+IDS_ACTIONTEXT_25=File: [1],  Directory: [9],  Size: [6]
+IDS_ACTIONTEXT_26=Installing ODBC components
+IDS_ACTIONTEXT_27=Installing new services
+IDS_ACTIONTEXT_28=Service: [2]
+IDS_ACTIONTEXT_29=Validating install
+IDS_ACTIONTEXT_3=Free space: [1]
+IDS_ACTIONTEXT_30=Evaluating launch conditions
+IDS_ACTIONTEXT_31=Moving files
+IDS_ACTIONTEXT_32=File: [1],  Directory: [9],  Size: [6]
+IDS_ACTIONTEXT_33=Patching files
+IDS_ACTIONTEXT_34=File: [1],  Directory: [2],  Size: [3]
+IDS_ACTIONTEXT_35=Updating component registration
+IDS_ACTIONTEXT_36=Publishing qualified components
+IDS_ACTIONTEXT_37=Component ID: [1], Qualifier: [2]
+IDS_ACTIONTEXT_38=Publishing product features
+IDS_ACTIONTEXT_39=Feature: [1]
+IDS_ACTIONTEXT_4=Searching for installed applications
+IDS_ACTIONTEXT_40=Publishing product information
+IDS_ACTIONTEXT_41=Registering class servers
+IDS_ACTIONTEXT_42=Class ID: [1]
+IDS_ACTIONTEXT_43=Registering extension servers
+IDS_ACTIONTEXT_44=Extension: [1]
+IDS_ACTIONTEXT_45=Registering fonts
+IDS_ACTIONTEXT_46=Font: [1]
+IDS_ACTIONTEXT_47=Registering MIME info
+IDS_ACTIONTEXT_48=MIME Content Type: [1], Extension: [2]
+IDS_ACTIONTEXT_49=Registering product
+IDS_ACTIONTEXT_5=Property: [1], Signature: [2]
+IDS_ACTIONTEXT_50=[1]
+IDS_ACTIONTEXT_51=Registering program identifiers
+IDS_ACTIONTEXT_52=ProgID: [1]
+IDS_ACTIONTEXT_53=Registering type libraries
+IDS_ACTIONTEXT_54=LibID: [1]
+IDS_ACTIONTEXT_55=Registering user
+IDS_ACTIONTEXT_56=[1]
+IDS_ACTIONTEXT_57=Removing duplicated files
+IDS_ACTIONTEXT_58=File: [1], Directory: [9]
+IDS_ACTIONTEXT_59=Updating environment strings
+IDS_ACTIONTEXT_6=Binding executables
+IDS_ACTIONTEXT_60=Name: [1], Value: [2], Action [3]
+IDS_ACTIONTEXT_61=Removing files
+IDS_ACTIONTEXT_62=File: [1], Directory: [9]
+IDS_ACTIONTEXT_63=Removing folders
+IDS_ACTIONTEXT_64=Folder: [1]
+IDS_ACTIONTEXT_65=Removing INI file entries
+IDS_ACTIONTEXT_66=File: [1],  Section: [2],  Key: [3], Value: [4]
+IDS_ACTIONTEXT_67=Removing ODBC components
+IDS_ACTIONTEXT_68=Removing system registry values
+IDS_ACTIONTEXT_69=Key: [1], Name: [2]
+IDS_ACTIONTEXT_7=File: [1]
+IDS_ACTIONTEXT_70=Removing shortcuts
+IDS_ACTIONTEXT_71=Shortcut: [1]
+IDS_ACTIONTEXT_72=Searching for qualifying products
+IDS_ACTIONTEXT_73=Rolling back action:
+IDS_ACTIONTEXT_74=[1]
+IDS_ACTIONTEXT_75=Removing backup files
+IDS_ACTIONTEXT_76=File: [1]
+IDS_ACTIONTEXT_77=Registering modules
+IDS_ACTIONTEXT_78=File: [1], Folder: [2]
+IDS_ACTIONTEXT_79=Unregistering modules
+IDS_ACTIONTEXT_8=Searching for qualifying products
+IDS_ACTIONTEXT_80=File: [1], Folder: [2]
+IDS_ACTIONTEXT_81=Initializing ODBC directories
+IDS_ACTIONTEXT_82=Starting services
+IDS_ACTIONTEXT_83=Service: [1]
+IDS_ACTIONTEXT_84=Stopping services
+IDS_ACTIONTEXT_85=Service: [1]
+IDS_ACTIONTEXT_86=Removing moved files
+IDS_ACTIONTEXT_87=File: [1], Directory: [9]
+IDS_ACTIONTEXT_88=Unpublishing Qualified Components
+IDS_ACTIONTEXT_89=Component ID: [1], Qualifier: [2]
+IDS_ACTIONTEXT_9=Computing space requirements
+IDS_ACTIONTEXT_90=Unpublishing product features
+IDS_ACTIONTEXT_91=Feature: [1]
+IDS_ACTIONTEXT_92=Unpublishing product information
+IDS_ACTIONTEXT_93=Unregister class servers
+IDS_ACTIONTEXT_94=Class ID: [1]
+IDS_ACTIONTEXT_95=Unregistering extension servers
+IDS_ACTIONTEXT_96=Extension: [1]
+IDS_ACTIONTEXT_97=Unregistering fonts
+IDS_ACTIONTEXT_98=Font: [1]
+IDS_ACTIONTEXT_99=Unregistering MIME info
+IDS_ERROR_0={{Fatal error: }}
+IDS_ERROR_1=Error [1].
+IDS_ERROR_10==== Logging started: [Date]  [Time] ===
+IDS_ERROR_100=Could not remove shortcut [2]. Verify that the shortcut file exists and that you can access it.
+IDS_ERROR_101=Could not register type library for file [2].  Contact your support personnel.
+IDS_ERROR_102=Could not unregister type library for file [2].  Contact your support personnel.
+IDS_ERROR_103=Could not update the INI file [2][3].  Verify that the file exists and that you can access it.
+IDS_ERROR_104=Could not schedule file [2] to replace file [3] on reboot.  Verify that you have write permissions to file [3].
+IDS_ERROR_105=Error removing ODBC driver manager, ODBC error [2]: [3]. Contact your support personnel.
+IDS_ERROR_106=Error installing ODBC driver manager, ODBC error [2]: [3]. Contact your support personnel.
+IDS_ERROR_107=Error removing ODBC driver [4], ODBC error [2]: [3]. Verify that you have sufficient privileges to remove ODBC drivers.
+IDS_ERROR_108=Error installing ODBC driver [4], ODBC error [2]: [3]. Verify that the file [4] exists and that you can access it.
+IDS_ERROR_109=Error configuring ODBC data source [4], ODBC error [2]: [3]. Verify that the file [4] exists and that you can access it.
+IDS_ERROR_11==== Logging stopped: [Date]  [Time] ===
+IDS_ERROR_110=Service [2] ([3]) failed to start.  Verify that you have sufficient privileges to start system services.
+IDS_ERROR_111=Service [2] ([3]) could not be stopped.  Verify that you have sufficient privileges to stop system services.
+IDS_ERROR_112=Service [2] ([3]) could not be deleted.  Verify that you have sufficient privileges to remove system services.
+IDS_ERROR_113=Service [2] ([3]) could not be installed.  Verify that you have sufficient privileges to install system services.
+IDS_ERROR_114=Could not update environment variable [2].  Verify that you have sufficient privileges to modify environment variables.
+IDS_ERROR_115=You do not have sufficient privileges to complete this installation for all users of the machine.  Log on as an administrator and then retry this installation.
+IDS_ERROR_116=Could not set file security for file [3]. Error: [2].  Verify that you have sufficient privileges to modify the security permissions for this file.
+IDS_ERROR_117=Component Services (COM+ 1.0) are not installed on this computer.  This installation requires Component Services in order to complete successfully.  Component Services are available on Windows 2000.
+IDS_ERROR_118=Error registering COM+ application.  Contact your support personnel for more information.
+IDS_ERROR_119=Error unregistering COM+ application.  Contact your support personnel for more information.
+IDS_ERROR_12=Action start [Time]: [1].
+IDS_ERROR_120=Removing older versions of this application
+IDS_ERROR_121=Preparing to remove older versions of this application
+IDS_ERROR_122=Error applying patch to file [2].  It has probably been updated by other means, and can no longer be modified by this patch.  For more information contact your patch vendor.  {{System Error: [3]}}
+IDS_ERROR_123=[2] cannot install one of its required products. Contact your technical support group.  {{System Error: [3].}}
+IDS_ERROR_124=The older version of [2] cannot be removed.  Contact your technical support group.  {{System Error [3].}}
+IDS_ERROR_125=The description for service '[2]' ([3]) could not be changed.
+IDS_ERROR_126=The Windows Installer service cannot update the system file [2] because the file is protected by Windows.  You may need to update your operating system for this program to work correctly. {{Package version: [3], OS Protected version: [4]}}
+IDS_ERROR_127=The Windows Installer service cannot update the protected Windows file [2]. {{Package version: [3], OS Protected version: [4], SFP Error: [5]}}
+IDS_ERROR_13=Action ended [Time]: [1]. Return value [2].
+IDS_ERROR_14=Time remaining: {[1] minutes }{[2] seconds}
+IDS_ERROR_15=Out of memory. Shut down other applications before retrying.
+IDS_ERROR_16=Installer is no longer responding.
+IDS_ERROR_17=Installer terminated prematurely.
+IDS_ERROR_18=Please wait while Windows configures [ProductName]
+IDS_ERROR_19=Gathering required information...
+IDS_ERROR_2=Warning [1].
+IDS_ERROR_20={[ProductName] }Setup completed successfully.
+IDS_ERROR_21={[ProductName] }Setup failed.
+IDS_ERROR_22=Error reading from file: [2]. {{ System error [3].}}  Verify that the file exists and that you can access it.
+IDS_ERROR_23=Cannot create the file [3].  A directory with this name already exists.  Cancel the installation and try installing to a different location.
+IDS_ERROR_24=Please insert the disk: [2]
+IDS_ERROR_25=The installer has insufficient privileges to access this directory: [2].  The installation cannot continue.  Log on as an administrator or contact your system administrator.
+IDS_ERROR_26=Error writing to file [2].  Verify that you have access to that directory.
+IDS_ERROR_27=Error reading from file [2].  Verify that the file exists and that you can access it.
+IDS_ERROR_28=Another application has exclusive access to the file [2].  Please shut down all other applications, then click Retry.
+IDS_ERROR_29=There is not enough disk space to install thi file [2].  Free some disk space and click Retry, or click Cancel to exit.
+IDS_ERROR_3=Info [1].
+IDS_ERROR_30=Source file not found: [2].  Verify that the file exists and that you can access it.
+IDS_ERROR_31=Error reading from file: [3]. {{ System error [2].}}  Verify that the file exists and that you can access it.
+IDS_ERROR_32=Error writing to file: [3]. {{ System error [2].}}  Verify that you have access to that directory.
+IDS_ERROR_33=Source file not found{{(cabinet)}}: [2].  Verify that the file exists and that you can access it.
+IDS_ERROR_34=Cannot create the directory [2].  A file with this name already exists.  Please rename or remove the file and click Retry, or click Cancel to exit.
+IDS_ERROR_35=The volume [2] is currently unavailable.  Please select another.
+IDS_ERROR_36=The specified path [2] is unavailable.
+IDS_ERROR_37=Unable to write to the specified folder [2].
+IDS_ERROR_38=A network error occurred while attempting to read from the file [2]
+IDS_ERROR_39=An error occurred while attempting to create the directory [2]
+IDS_ERROR_4=Internal Error [1]. [2]{, [3]}{, [4]}
+IDS_ERROR_40=A network error occurred while attempting to create the directory [2]
+IDS_ERROR_41=A network error occurred while attempting to open the source file cabinet [2].
+IDS_ERROR_42=The specified path is too long [2].
+IDS_ERROR_43=The Installer has insufficient privileges to modify the file [2].
+IDS_ERROR_44=A portion of the path [2] exceeds the length allowed by the system.
+IDS_ERROR_45=The path [2] contains words that are not valid in folders.
+IDS_ERROR_46=The path [2] contains an invalid character.
+IDS_ERROR_47=[2] is not a valid short file name.
+IDS_ERROR_48=Error getting file security: [3] GetLastError: [2]
+IDS_ERROR_49=Invalid Drive: [2]
+IDS_ERROR_5={{Disk full: }}
+IDS_ERROR_50=Could not create key [2]. {{ System error [3].}}  Verify that you have sufficient access to that key, or contact your support personnel.
+IDS_ERROR_51=Could not open key: [2]. {{ System error [3].}}  Verify that you have sufficient access to that key, or contact your support personnel.
+IDS_ERROR_52=Could not delete value [2] from key [3]. {{ System error [4].}}  Verify that you have sufficient access to that key, or contact your support personnel.
+IDS_ERROR_53=Could not delete key [2]. {{ System error [3].}}  Verify that you have sufficient access to that key, or contact your support personnel.
+IDS_ERROR_54=Could not read value [2] from key [3]. {{ System error [4].}}  Verify that you have sufficient access to that key, or contact your support personnel.
+IDS_ERROR_55=Could not write value [2] to key [3]. {{ System error [4].}}  Verify that you have sufficient access to that key, or contact your support personnel.
+IDS_ERROR_56=Could not get value names for key [2]. {{ System error [3].}}  Verify that you have sufficient access to that key, or contact your support personnel.
+IDS_ERROR_57=Could not get sub key names for key [2]. {{ System error [3].}}  Verify that you have sufficient access to that key, or contact your support personnel.
+IDS_ERROR_58=Could not read security information for key [2]. {{ System error [3].}}  Verify that you have sufficient access to that key, or contact your support personnel.
+IDS_ERROR_59=Could not increase the available registry space. [2] KB of free registry space is required for the installation of this application.
+IDS_ERROR_6=Action [Time]: [1]. [2]
+IDS_ERROR_60=Another installation is in progress. You must complete that installation before continuing this one.
+IDS_ERROR_61=Error accessing secured data. Please make sure the Windows Installer is configured properly and try the installation again.
+IDS_ERROR_62=User [2] has previously initiated an installation for product [3].  That user will need to run that installation again before using that product.  Your current installation will now continue.
+IDS_ERROR_63=User [2] has previously initiated an installation for product [3].  That user will need to run that installation again before using that product.
+IDS_ERROR_64=Out of disk space -- Volume: '[2]'; required space: [3] KB; available space: [4] KB.  Free some disk space and retry.
+IDS_ERROR_65=Are you sure you want to cancel?
+IDS_ERROR_66=The file [2][3] is being held in use{ by the following process: Name: [4], ID: [5], Window Title: [6]}.  Close that application and retry.
+IDS_ERROR_67=The product [2] is already installed, preventing the installation of this product.  The two products are incompatible.
+IDS_ERROR_68=Out of disk space -- Volume: [2]; required space: [3] KB; available space: [4] KB.  If rollback is disabled, enough space is available. Click Cancel to quit, Retry to check available disk space again, or Ignore to continue without rollback.
+IDS_ERROR_69=Could not access network location [2].
+IDS_ERROR_7=[ProductName]
+IDS_ERROR_70=The following applications should be closed before continuing the installation:
+IDS_ERROR_71=Could not find any previously installed compliant products on the machine for installing this product.
+IDS_ERROR_72=The key [2] is not valid.  Verify that you entered the correct key.
+IDS_ERROR_73=The installer must restart your system before configuration of [2] can continue.  Click Yes to restart now or No if you plan to restart later.
+IDS_ERROR_74=You must restart your system for the configuration changes made to [2] to take effect. Click Yes to restart now or No if you plan to restart later.
+IDS_ERROR_75=An installation for [2] is currently suspended.  You must undo the changes made by that installation to continue.  Do you want to undo those changes?
+IDS_ERROR_76=A previous installation for this product is in progress.  You must undo the changes made by that installation to continue.  Do you want to undo those changes?
+IDS_ERROR_77=No valid source could be found for product [2].  The Windows Installer cannot continue.
+IDS_ERROR_78=Installation operation completed successfully.
+IDS_ERROR_79=Installation operation failed.
+IDS_ERROR_8={[2]}{, [3]}{, [4]}
+IDS_ERROR_80=Product: [2] -- [3]
+IDS_ERROR_81=You may either restore your computer to its previous state or continue the installation later. Would you like to restore?
+IDS_ERROR_82=An error occurred while writing installation information to disk.  Check to make sure enough disk space is available, and click Retry, or Cancel to end the installation.
+IDS_ERROR_83=One or more of the files required to restore your computer to its previous state could not be found.  Restoration will not be possible.
+IDS_ERROR_84=The path [2] is not valid.  Please specify a valid path.
+IDS_ERROR_85=Out of memory. Shut down other applications before retrying.
+IDS_ERROR_86=There is no disk in drive [2]. Please insert one and click Retry, or click Cancel to go back to the previously selected volume.
+IDS_ERROR_87=There is no disk in drive [2]. Please insert one and click Retry, or click Cancel to return to the browse dialog and select a different volume.
+IDS_ERROR_88=The folder [2] does not exist.  Please enter a path to an existing folder.
+IDS_ERROR_89=You have insufficient privileges to read this folder.
+IDS_ERROR_9=Message type: [1], Argument: [2]
+IDS_ERROR_90=A valid destination folder for the installation could not be determined.
+IDS_ERROR_91=Error attempting to read from the source installation database: [2].
+IDS_ERROR_92=Scheduling reboot operation: Renaming file [2] to [3]. Must reboot to complete operation.
+IDS_ERROR_93=Scheduling reboot operation: Deleting file [2]. Must reboot to complete operation.
+IDS_ERROR_94=Module [2] failed to register.  HRESULT [3].  Contact your support personnel.
+IDS_ERROR_95=Module [2] failed to unregister.  HRESULT [3].  Contact your support personnel.
+IDS_ERROR_96=Failed to cache package [2]. Error: [3]. Contact your support personnel.
+IDS_ERROR_97=Could not register font [2].  Verify that you have sufficient permissions to install fonts, and that the system supports this font.
+IDS_ERROR_98=Could not unregister font [2]. Verify that you have sufficient permissions to remove fonts.
+IDS_ERROR_99=Could not create shortcut [2]. Verify that the destination folder exists and that you can access it.
+IDS_ERROR_SN_INVALID=The serial number is invalid.
+IDS_ISSCRIPT_VERSION_MISSING=The InstallScript engine is missing from this machine.  If available, please run ISScript.msi, or contact your support personnel for further assistance.
+IDS_ISSCRIPT_VERSION_OLD=The InstallScript engine on this machine is older than the version required to run this setup.  If available, please install the latest version of ISScript.msi, or contact your support personnel for further assistance.
+IDS_PRODUCT_DEFAULT_1=Your Product Name
+IDS_STANDARD_USE_SETUPEXE=This installation can not be run by directly launching the MSI package; you must run setup.exe.
+IDS_SetupTips_1=OK
+IDS_SetupTips_10=Will be installed on first use. (Available only if the feature supports this option.)
+IDS_SetupTips_11=Will be installed to run from the network. (Available only if the feature supports this option.)
+IDS_SetupTips_12=This install state means the feature...
+IDS_SetupTips_13=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBanner.ibd
+IDS_SetupTips_14=<ISProductFolder>\Redist\Language Independent\OS Independent\NetworkInstall.ico
+IDS_SetupTips_15=<ISProductFolder>\Redist\Language Independent\OS Independent\Install.ico
+IDS_SetupTips_16=<ISProductFolder>\Redist\Language Independent\OS Independent\InstallFirstUse.ico
+IDS_SetupTips_17=<ISProductFolder>\Redist\Language Independent\OS Independent\InstallPartial.ico
+IDS_SetupTips_18=<ISProductFolder>\Redist\Language Independent\OS Independent\DontInstall.ico
+IDS_SetupTips_19=<ISProductFolder>\Redist\Language Independent\OS Independent\InstallStateMenu.ico
+IDS_SetupTips_2={&MSSWhiteSerif8}InstallShield
+IDS_SetupTips_3=InstallShield
+IDS_SetupTips_4=Custom Setup allows you to selectively install program features.
+IDS_SetupTips_5={&MSSansBold8}Custom Setup Tips
+IDS_SetupTips_6=Will not be installed.
+IDS_SetupTips_7=Will have some subfeatures installed to the local hard drive. (Available only if the feature has subfeatures.)
+IDS_SetupTips_8=Will be completely installed to the local hard drive.
+IDS_SetupTips_9=The icon next to the feature name indicates the install state of the feature. Click the icon to drop down the install state menu for each feature.
+IDS_UITEXT_0=bytes
+IDS_UITEXT_1=GB
+IDS_UITEXT_10=This feature will remain uninstalled.
+IDS_UITEXT_11=This feature will be set to be installed when required.
+IDS_UITEXT_12=This feature will be installed to run from CD.
+IDS_UITEXT_13=This feature will be installed on the local hard drive.
+IDS_UITEXT_14=This feature will be installed to run from the network.
+IDS_UITEXT_15=This feature will become unavailable.
+IDS_UITEXT_16=Will be installed when required.
+IDS_UITEXT_17=This feature will be available to run from CD.
+IDS_UITEXT_18=This feature will be installed on your local hard drive.
+IDS_UITEXT_19=This feature will be available to run from the network.
+IDS_UITEXT_2=KB
+IDS_UITEXT_20=This feature will be uninstalled completely, and you won't be able to run it from CD.
+IDS_UITEXT_21=This feature was run from the CD but will be set to be installed when required.
+IDS_UITEXT_22=This feature will continue to be run from the CD
+IDS_UITEXT_23=This feature was run from the CD but will be installed on the local hard drive.
+IDS_UITEXT_24=This feature frees up [1] on your hard drive.
+IDS_UITEXT_25=This feature requires [1] on your hard drive.
+IDS_UITEXT_26=Compiling cost for this feature...
+IDS_UITEXT_27=This feature will be completely removed.
+IDS_UITEXT_28=This feature will be removed from your local hard drive but will be set to be installed when required.
+IDS_UITEXT_29=This feature will be removed from your local hard drive but will still be available to run from CD.
+IDS_UITEXT_3=MB
+IDS_UITEXT_30=This feature will remain on your local hard drive.
+IDS_UITEXT_31=This feature will be removed from your local hard drive, but will be still available to run from the network.
+IDS_UITEXT_32=This feature will be uninstalled completely, and you won't be able to run it from the network.
+IDS_UITEXT_33=This feature was run from the network but will be installed when required.
+IDS_UITEXT_34=This feature was run from the network but will be installed on the local hard drive.
+IDS_UITEXT_35=This feature will continue to be run from the network
+IDS_UITEXT_36=This feature frees up [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures free up [4] on your hard drive.
+IDS_UITEXT_37=This feature frees up [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures require [4] on your hard drive.
+IDS_UITEXT_38=This feature requires [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures free up [4] on your hard drive.
+IDS_UITEXT_39=This feature requires [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures require [4] on your hard drive.
+IDS_UITEXT_4=This feature will not be available.
+IDS_UITEXT_40=Time remaining: {[1] min }[2] sec
+IDS_UITEXT_41=Available
+IDS_UITEXT_42=Differences
+IDS_UITEXT_43=Required
+IDS_UITEXT_44=Disk Size
+IDS_UITEXT_45=Volume
+IDS_UITEXT_46=This feature, and all subfeatures, will be installed to run from the network.
+IDS_UITEXT_47=This feature, and all subfeatures, will be installed to run from the CD.
+IDS_UITEXT_48=This feature, and all subfeatures, will be installed on local hard drive.
+IDS_UITEXT_5=This feature will be installed when required.
+IDS_UITEXT_6=This feature will be installed to run from CD.
+IDS_UITEXT_7=This feature will be installed on local hard drive.
+IDS_UITEXT_8=This feature will be installed to run from network.
+IDS_UITEXT_9=Fldr|New Folder
+IDS__AgreeToLicense_0=I &do not accept the terms in the license agreement
+IDS__AgreeToLicense_1=I &accept the terms in the license agreement
+IDS__DatabaseFolder_0=[ProductName] - InstallShield Wizard
+IDS__DatabaseFolder_1=Cancel
+IDS__DatabaseFolder_10=Install [ProductName] database to:
+IDS__DatabaseFolder_11=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBanner.ibd
+IDS__DatabaseFolder_12=<ISProductFolder>\Redist\Language Independent\OS Independent\DestIcon.ibd
+IDS__DatabaseFolder_2=InstallShield
+IDS__DatabaseFolder_3={&MSSWhiteSerif8}InstallShield
+IDS__DatabaseFolder_4=Click Next to install to this folder, or click Change to install to a different folder.
+IDS__DatabaseFolder_5={&MSSansBold8}Database Folder
+IDS__DatabaseFolder_6=< &Back
+IDS__DatabaseFolder_7=&Next >
+IDS__DatabaseFolder_8=&Change...
+IDS__DatabaseFolder_9=[DATABASEDIR]
+IDS__DestinationFolder_0=[ProductName] - InstallShield Wizard
+IDS__DestinationFolder_1=Cancel
+IDS__DestinationFolder_10=Install [ProductName] to:
+IDS__DestinationFolder_11=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBanner.ibd
+IDS__DestinationFolder_12=<ISProductFolder>\Redist\Language Independent\OS Independent\DestIcon.ibd
+IDS__DestinationFolder_2=InstallShield
+IDS__DestinationFolder_3={&MSSWhiteSerif8}InstallShield
+IDS__DestinationFolder_4=Click Next to install to this folder, or click Change to install to a different folder.
+IDS__DestinationFolder_5={&MSSansBold8}Destination Folder
+IDS__DestinationFolder_6=< &Back
+IDS__DestinationFolder_7=&Next >
+IDS__DestinationFolder_8=&Change...
+IDS__DestinationFolder_9=[INSTALLDIR]
+IDS__DisplayName_Custom=Custom
+IDS__DisplayName_Minimal=Minimal
+IDS__DisplayName_Typical=Typical
+IDS__IsAdminInstallBrowse_0=[ProductName] - InstallShield Wizard
+IDS__IsAdminInstallBrowse_1={&MSSWhiteSerif8}InstallShield
+IDS__IsAdminInstallBrowse_10=OK
+IDS__IsAdminInstallBrowse_11=
+IDS__IsAdminInstallBrowse_12=&Folder name:
+IDS__IsAdminInstallBrowse_13=Up one level|
+IDS__IsAdminInstallBrowse_14=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBanner.ibd
+IDS__IsAdminInstallBrowse_15=<ISProductFolder>\Redist\Language Independent\OS Independent\New.ibd
+IDS__IsAdminInstallBrowse_16=<ISProductFolder>\Redist\Language Independent\OS Independent\Up.ibd
+IDS__IsAdminInstallBrowse_2=InstallShield
+IDS__IsAdminInstallBrowse_3=Cancel
+IDS__IsAdminInstallBrowse_4=
+IDS__IsAdminInstallBrowse_5=&Look in:
+IDS__IsAdminInstallBrowse_6=Browse to the destination folder.
+IDS__IsAdminInstallBrowse_7={&MSSansBold8}Change Current Destination Folder
+IDS__IsAdminInstallBrowse_8=
+IDS__IsAdminInstallBrowse_9=Create new folder|
+IDS__IsAdminInstallPointWelcome_0=[ProductName] - InstallShield Wizard
+IDS__IsAdminInstallPointWelcome_1=< &Back
+IDS__IsAdminInstallPointWelcome_2=Cancel
+IDS__IsAdminInstallPointWelcome_3=&Next >
+IDS__IsAdminInstallPointWelcome_4={&TahomaBold10}Welcome to the InstallShield Wizard for [ProductName]
+IDS__IsAdminInstallPointWelcome_5=The InstallShield(R) Wizard will create a server image of [ProductName] at a specified network location. To continue, click Next.
+IDS__IsAdminInstallPointWelcome_6=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBitmap.ibd
+IDS__IsAdminInstallPoint_0=[ProductName] - InstallShield Wizard
+IDS__IsAdminInstallPoint_1=< &Back
+IDS__IsAdminInstallPoint_10=&Network location:
+IDS__IsAdminInstallPoint_11=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBanner.ibd
+IDS__IsAdminInstallPoint_2={&MSSWhiteSerif8}InstallShield
+IDS__IsAdminInstallPoint_3=InstallShield
+IDS__IsAdminInstallPoint_4=&Change...
+IDS__IsAdminInstallPoint_5=Cancel
+IDS__IsAdminInstallPoint_6=Specify a network location for the server image of the product.
+IDS__IsAdminInstallPoint_7=Enter the network location or click Change to browse to a location.  Click Install to create a server image of [ProductName] at the specified network location or click Cancel to exit the wizard.
+IDS__IsAdminInstallPoint_8={&MSSansBold8}Network Location
+IDS__IsAdminInstallPoint_9=&Install
+IDS__IsBitmapDlg_0=[ProductName] - InstallShield Wizard
+IDS__IsBitmapDlg_1=< &Back
+IDS__IsBitmapDlg_2={&MSSWhiteSerif8}InstallShield
+IDS__IsBitmapDlg_3=InstallShield
+IDS__IsBitmapDlg_4=Cancel
+IDS__IsBitmapDlg_5=&Next >
+IDS__IsBitmapDlg_6=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBitmap.ibd
+IDS__IsBrowseFolderDlg_0=[ProductName] - InstallShield Wizard
+IDS__IsBrowseFolderDlg_1={&MSSWhiteSerif8}InstallShield
+IDS__IsBrowseFolderDlg_10=OK
+IDS__IsBrowseFolderDlg_11=
+IDS__IsBrowseFolderDlg_12=&Folder name:
+IDS__IsBrowseFolderDlg_13=Up One Level|
+IDS__IsBrowseFolderDlg_14=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBanner.ibd
+IDS__IsBrowseFolderDlg_15=<ISProductFolder>\Redist\Language Independent\OS Independent\New.ibd
+IDS__IsBrowseFolderDlg_16=<ISProductFolder>\Redist\Language Independent\OS Independent\Up.ibd
+IDS__IsBrowseFolderDlg_2=InstallShield
+IDS__IsBrowseFolderDlg_3=Cancel
+IDS__IsBrowseFolderDlg_4=
+IDS__IsBrowseFolderDlg_5=&Look in:
+IDS__IsBrowseFolderDlg_6=Browse to the destination folder.
+IDS__IsBrowseFolderDlg_7={&MSSansBold8}Change Current Destination Folder
+IDS__IsBrowseFolderDlg_8=
+IDS__IsBrowseFolderDlg_9=Create New Folder|
+IDS__IsCancelDlg_0=[ProductName] - InstallShield Wizard
+IDS__IsCancelDlg_1=Information icon|
+IDS__IsCancelDlg_2=InstallShield
+IDS__IsCancelDlg_3=Are you sure you want to cancel the installation?
+IDS__IsCancelDlg_4=Are you sure you want to cancel [ProductName] installation?
+IDS__IsCancelDlg_5={&MSSansBold8}Cancel Setup
+IDS__IsCancelDlg_6=&No
+IDS__IsCancelDlg_7=To continue installing [ProductName], click Resume. To exit the installation, click Exit.
+IDS__IsCancelDlg_8=&Yes
+IDS__IsCancelDlg_9=<ISProductFolder>\Redist\Language Independent\OS Independent\WarningIcon.ibd
+IDS__IsCustomSelectionDlg_0=[ProductName] - InstallShield Wizard
+IDS__IsCustomSelectionDlg_1=< &Back
+IDS__IsCustomSelectionDlg_10=Feature Description:
+IDS__IsCustomSelectionDlg_11=&Next >
+IDS__IsCustomSelectionDlg_12=Feature size
+IDS__IsCustomSelectionDlg_13=&Help
+IDS__IsCustomSelectionDlg_14=Multiline description of the currently selected item
+IDS__IsCustomSelectionDlg_15=Feature Description
+IDS__IsCustomSelectionDlg_16=&Change...
+IDS__IsCustomSelectionDlg_17=<selected feature path>
+IDS__IsCustomSelectionDlg_18=Install to:
+IDS__IsCustomSelectionDlg_19=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBanner.ibd
+IDS__IsCustomSelectionDlg_2={&MSSWhiteSerif8}InstallShield
+IDS__IsCustomSelectionDlg_3=InstallShield
+IDS__IsCustomSelectionDlg_4=Cancel
+IDS__IsCustomSelectionDlg_5=&Space
+IDS__IsCustomSelectionDlg_6=Select the program features you want installed.
+IDS__IsCustomSelectionDlg_7=Click on an icon in the list below to change how a feature is installed.
+IDS__IsCustomSelectionDlg_8={&MSSansBold8}Custom Setup
+IDS__IsCustomSelectionDlg_9=Multiline description of the currently selected item
+IDS__IsDatabaseLocation_1=InstallShield
+IDS__IsDatabaseLocation_10=[DATABASEDIR]
+IDS__IsDatabaseLocation_11=Install Application Database to:
+IDS__IsDatabaseLocation_12={&MSSWhiteSerif8}InstallShield
+IDS__IsDatabaseLocation_13=[ProductName] - InstallShield Wizard
+IDS__IsDatabaseLocation_2=2
+IDS__IsDatabaseLocation_3=Cancel
+IDS__IsDatabaseLocation_4=4
+IDS__IsDatabaseLocation_5=Click next to install the application's database to this folder, or click change to install it to a different folder.
+IDS__IsDatabaseLocation_6={&MSSansBold8}Database Destination Folder
+IDS__IsDatabaseLocation_7=< &Back
+IDS__IsDatabaseLocation_8=&Next >
+IDS__IsDatabaseLocation_9=&Change...
+IDS__IsDiskSpaceDlg_0=[ProductName] - InstallShield Wizard
+IDS__IsDiskSpaceDlg_1={&MSSWhiteSerif8}InstallShield
+IDS__IsDiskSpaceDlg_10=OK
+IDS__IsDiskSpaceDlg_11=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBanner.ibd
+IDS__IsDiskSpaceDlg_2=InstallShield
+IDS__IsDiskSpaceDlg_3=&Disk Cleanup
+IDS__IsDiskSpaceDlg_4=Disk space required for the installation exceeds available disk space.
+IDS__IsDiskSpaceDlg_5=The highlighted volumes do not have enough disk space available for the currently selected features. You can remove files from the highlighted volumes, choose to install less features onto local drives, or select different destination drives.
+IDS__IsDiskSpaceDlg_6={&MSSansBold8}Out of Disk Space
+IDS__IsDiskSpaceDlg_7=&Exit
+IDS__IsDiskSpaceDlg_8=Use disk cleanup to free more disk space by removing unneeded files.
+IDS__IsDiskSpaceDlg_9={120}{70}{70}{70}{70}
+IDS__IsErrorDlg_0=[ProductName] Installer Information
+IDS__IsErrorDlg_1=&Abort
+IDS__IsErrorDlg_2=&Cancel
+IDS__IsErrorDlg_3=<error text goes here><error text goes here><error text goes here><error text goes here><error text goes here><error text goes here><error text goes here><error text goes here><error text goes here><error text goes here><error text goes here>
+IDS__IsErrorDlg_4=&Ignore
+IDS__IsErrorDlg_5=&No
+IDS__IsErrorDlg_6=&OK
+IDS__IsErrorDlg_7=&Retry
+IDS__IsErrorDlg_8=&Yes
+IDS__IsErrorDlg_9=<ISProductFolder>\Redist\Language Independent\OS Independent\WarningIcon.ibd
+IDS__IsExitDialog_0=[ProductName] - InstallShield Wizard
+IDS__IsExitDialog_1=< &Back
+IDS__IsExitDialog_2=Cancel
+IDS__IsExitDialog_3=&Finish
+IDS__IsExitDialog_4={&TahomaBold10}InstallShield Wizard Completed
+IDS__IsExitDialog_5=The InstallShield Wizard has successfully installed [ProductName]. Click Finish to exit the wizard.
+IDS__IsExitDialog_6=The InstallShield Wizard has successfully uninstalled [ProductName]. Click Finish to exit the wizard.
+IDS__IsExitDialog_7=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBitmap.ibd
+IDS__IsExitDialog_8=Show the readme file
+IDS__IsExitDialog_9=Launch the program
+IDS__IsFatalError_0=[ProductName] - InstallShield Wizard
+IDS__IsFatalError_1=< &Back
+IDS__IsFatalError_10=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBitmap.ibd
+IDS__IsFatalError_2=Cancel
+IDS__IsFatalError_3=&Finish
+IDS__IsFatalError_4=Your system has not been modified. To complete installation at another time, please run setup again.
+IDS__IsFatalError_5=Click Finish to exit the wizard.
+IDS__IsFatalError_6=You can either keep any existing installed elements on your system to continue this installation at a later time or you can restore your system to its original state prior to the installation.
+IDS__IsFatalError_7=Click Restore or Continue Later to exit the wizard.
+IDS__IsFatalError_8={&TahomaBold10}InstallShield Wizard Completed
+IDS__IsFatalError_9=The wizard was interrupted before [ProductName] could be completely installed.
+IDS__IsFeatureDetailsDlg_0=[ProductName] - InstallShield Wizard
+IDS__IsFeatureDetailsDlg_1={&MSSWhiteSerif8}InstallShield
+IDS__IsFeatureDetailsDlg_10=Use disk cleanup to free more disk space by removing unneeded files.
+IDS__IsFeatureDetailsDlg_11=Install to:
+IDS__IsFeatureDetailsDlg_12=Total disk space required:
+IDS__IsFeatureDetailsDlg_13={120}{70}{70}{70}{70}
+IDS__IsFeatureDetailsDlg_14=OK
+IDS__IsFeatureDetailsDlg_15=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBanner.ibd
+IDS__IsFeatureDetailsDlg_2=InstallShield
+IDS__IsFeatureDetailsDlg_3=&Change...
+IDS__IsFeatureDetailsDlg_4=Cancel
+IDS__IsFeatureDetailsDlg_5=&Disk Cleanup
+IDS__IsFeatureDetailsDlg_6=The disk space required for the installation of the selected features.
+IDS__IsFeatureDetailsDlg_7=The highlighted volumes do not have enough disk space available for the currently selected features. You can remove files from the highlighted volumes, choose to install less features onto local drives, or select different destination drives.
+IDS__IsFeatureDetailsDlg_8={&MSSansBold8}Disk Space Requirements
+IDS__IsFeatureDetailsDlg_9=
+IDS__IsFilesInUse_0=[ProductName] - InstallShield Wizard
+IDS__IsFilesInUse_1={&MSSWhiteSerif8}InstallShield
+IDS__IsFilesInUse_10=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBanner.ibd
+IDS__IsFilesInUse_2=InstallShield
+IDS__IsFilesInUse_3=Some files that need to be updated are currently in use.
+IDS__IsFilesInUse_4=The following applications are using files that need to be updated by this setup. Close these applications and click Retry to continue.
+IDS__IsFilesInUse_5={&MSSansBold8}Files in Use
+IDS__IsFilesInUse_6=&Exit
+IDS__IsFilesInUse_7=&Ignore
+IDS__IsFilesInUse_8=&Retry
+IDS__IsFilesInUse_9=
+IDS__IsInitDlg_0=[ProductName] - InstallShield Wizard
+IDS__IsInitDlg_1=
+IDS__IsInitDlg_2=
+IDS__IsInitDlg_3=< &Back
+IDS__IsInitDlg_4=Cancel
+IDS__IsInitDlg_5=&Next >
+IDS__IsInitDlg_6={&TahomaBold10}Welcome to the InstallShield Wizard for [ProductName]
+IDS__IsInitDlg_7=[ProductName] Setup is preparing the InstallShield Wizard which will guide you through the program setup process.  Please wait.
+IDS__IsInitDlg_8=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBitmap.ibd
+IDS__IsLicenseDlg_0=[ProductName] - InstallShield Wizard
+IDS__IsLicenseDlg_1=< &Back
+IDS__IsLicenseDlg_2={&MSSWhiteSerif8}InstallShield
+IDS__IsLicenseDlg_3=InstallShield
+IDS__IsLicenseDlg_4=Cancel
+IDS__IsLicenseDlg_5=Please read the following license agreement carefully.
+IDS__IsLicenseDlg_6=Click Accept to accept the terms of this agreement, or click Decline to exit the wizard.
+IDS__IsLicenseDlg_7={&MSSansBold8}License Agreement
+IDS__IsLicenseDlg_8=&Next >
+IDS__IsLicenseDlg_9=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBanner.ibd
+IDS__IsLicenseDlg_EULA=<ISProductFolder>\Redist\0409\Eula.rtf
+IDS__IsMaintenanceDlg_0=[ProductName] - InstallShield Wizard
+IDS__IsMaintenanceDlg_1=< &Back
+IDS__IsMaintenanceDlg_10={&MSSansBold8}&Remove
+IDS__IsMaintenanceDlg_11=
+IDS__IsMaintenanceDlg_12=Change which program features are installed. This option displays the Custom Selection dialog in which you can change the way features are installed.
+IDS__IsMaintenanceDlg_13=Repair installation errors in the program. This option fixes missing or corrupt files, shortcuts, and registry entries.
+IDS__IsMaintenanceDlg_14=Remove [ProductName] from your computer.
+IDS__IsMaintenanceDlg_15=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBanner.ibd
+IDS__IsMaintenanceDlg_16=<ISProductFolder>\Redist\Language Independent\OS Independent\RemoveIco.ibd
+IDS__IsMaintenanceDlg_17=<ISProductFolder>\Redist\Language Independent\OS Independent\ReinstIco.ibd
+IDS__IsMaintenanceDlg_18=<ISProductFolder>\Redist\Language Independent\OS Independent\CustomSetupIco.ibd
+IDS__IsMaintenanceDlg_2={&MSSWhiteSerif8}InstallShield
+IDS__IsMaintenanceDlg_3=InstallShield
+IDS__IsMaintenanceDlg_4=Cancel
+IDS__IsMaintenanceDlg_5=Modify, repair, or remove the program.
+IDS__IsMaintenanceDlg_6={&MSSansBold8}Program Maintenance
+IDS__IsMaintenanceDlg_7=&Next >
+IDS__IsMaintenanceDlg_8={&MSSansBold8}&Modify
+IDS__IsMaintenanceDlg_9={&MSSansBold8}Re&pair
+IDS__IsMaintenanceWelcome_0=[ProductName] - InstallShield Wizard
+IDS__IsMaintenanceWelcome_1=< &Back
+IDS__IsMaintenanceWelcome_2=Cancel
+IDS__IsMaintenanceWelcome_3=&Next >
+IDS__IsMaintenanceWelcome_4={&TahomaBold10}Welcome to the InstallShield Wizard for [ProductName]
+IDS__IsMaintenanceWelcome_5=The InstallShield(R) Wizard will allow you to modify, repair, or remove [ProductName]. To continue, click Next.
+IDS__IsMaintenanceWelcome_6=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBitmap.ibd
+IDS__IsPatchDlg_0=[ProductName] Patch - InstallShield Wizard
+IDS__IsPatchDlg_1={&TahomaBold10}Welcome to the Patch for [ProductName]
+IDS__IsPatchDlg_2=The InstallShield(R) Wizard will install the Patch for [ProductName] on your computer.  To continue, click Update.
+IDS__IsPatchDlg_3=Cancel
+IDS__IsPatchDlg_4=< &Back
+IDS__IsPatchDlg_5=&Update >
+IDS__IsPatchDlg_6=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBitmap.ibd
+IDS__IsProgressDlg_0=[ProductName] - InstallShield Wizard
+IDS__IsProgressDlg_1=Progress done
+IDS__IsProgressDlg_10=(Hidden for now)Sec.
+IDS__IsProgressDlg_11=Status:
+IDS__IsProgressDlg_12=&Next >
+IDS__IsProgressDlg_13=(Hidden for now)
+IDS__IsProgressDlg_14=)Hidden for now)Estimated time remaining:
+IDS__IsProgressDlg_15={&MSSansBold8}Uninstalling [ProductName]
+IDS__IsProgressDlg_16=The program features you selected are being uninstalled.
+IDS__IsProgressDlg_17=Please wait while the InstallShield Wizard uninstalls [ProductName]. This may take several minutes.
+IDS__IsProgressDlg_18=<ISProductFolder>\Redist\Language Independent\OS Independent\SetupIcon.ibd
+IDS__IsProgressDlg_19=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBanner.ibd
+IDS__IsProgressDlg_2=
+IDS__IsProgressDlg_3=< &Back
+IDS__IsProgressDlg_4={&MSSWhiteSerif8}InstallShield
+IDS__IsProgressDlg_5=InstallShield
+IDS__IsProgressDlg_6=Cancel
+IDS__IsProgressDlg_7=The program features you selected are being installed.
+IDS__IsProgressDlg_8=Please wait while the InstallShield Wizard installs [ProductName]. This may take several minutes.
+IDS__IsProgressDlg_9={&MSSansBold8}Installing [ProductName]
+IDS__IsReadmeDlg_0={&MSSansBold8}Readme Information
+IDS__IsReadmeDlg_1=Please read the following readme information carefully.
+IDS__IsReadmeDlg_2=[ProductName] - InstallShield Wizard
+IDS__IsReadmeDlg_3=< &Back
+IDS__IsReadmeDlg_4=&Next >
+IDS__IsReadmeDlg_5=&Cancel
+IDS__IsReadmeDlg_6=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBitmap.ibd
+IDS__IsReadmeDlg_7=InstallShield
+IDS__IsReadmeDlg_8={&MSSWhiteSerif8}InstallShield
+IDS__IsRegisterUserDlg_0=[ProductName] - InstallShield Wizard
+IDS__IsRegisterUserDlg_1=< &Back
+IDS__IsRegisterUserDlg_10={\Tahoma8}{50}
+IDS__IsRegisterUserDlg_11=&User Name:
+IDS__IsRegisterUserDlg_12=&Next >
+IDS__IsRegisterUserDlg_13=Install this application for:
+IDS__IsRegisterUserDlg_14=&Anyone who uses this computer (all users)
+IDS__IsRegisterUserDlg_15=Only for &me ([USERNAME])
+IDS__IsRegisterUserDlg_16=
+IDS__IsRegisterUserDlg_17=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBanner.ibd
+IDS__IsRegisterUserDlg_18=&Serial Number:
+IDS__IsRegisterUserDlg_2={&MSSWhiteSerif8}InstallShield
+IDS__IsRegisterUserDlg_3=InstallShield
+IDS__IsRegisterUserDlg_4=Cancel
+IDS__IsRegisterUserDlg_5={\Tahoma8}{80}
+IDS__IsRegisterUserDlg_6=&Organization:
+IDS__IsRegisterUserDlg_7=Please enter your information.
+IDS__IsRegisterUserDlg_8=Please enter your name and organization.
+IDS__IsRegisterUserDlg_9={&MSSansBold8}Customer Information
+IDS__IsReinstallDlg_0=[ProductName] - InstallShield Wizard
+IDS__IsReinstallDlg_1=< &Back
+IDS__IsReinstallDlg_10=&Complete
+IDS__IsReinstallDlg_11=
+IDS__IsReinstallDlg_12=Replace all files whose versions differ from that required by the program and all registry entries and shortcuts required by the program.
+IDS__IsReinstallDlg_13=Replace only missing program files and registry entries for installed features.
+IDS__IsReinstallDlg_14=Replace all files, registry entries, and shortcuts required by the program.
+IDS__IsReinstallDlg_2={&MSSWhiteSerif8}InstallShield
+IDS__IsReinstallDlg_3=InstallShield
+IDS__IsReinstallDlg_4=Cancel
+IDS__IsReinstallDlg_5=Select how you want the program elements reinstalled.
+IDS__IsReinstallDlg_6={&MSSansBold8}Reinstallation Mode
+IDS__IsReinstallDlg_7=&Next >
+IDS__IsReinstallDlg_8=No&rmal
+IDS__IsReinstallDlg_9=&Minimal
+IDS__IsResumeDlg_0=[ProductName] - InstallShield Wizard
+IDS__IsResumeDlg_1=< &Back
+IDS__IsResumeDlg_2=Cancel
+IDS__IsResumeDlg_3=&Next >
+IDS__IsResumeDlg_4=The InstallShield(R) Wizard will complete the installation of [ProductName] on your computer. To continue, click Next.
+IDS__IsResumeDlg_5=The InstallShield(R) Wizard will complete the suspended installation of [ProductName] on your computer. To continue, click Next.
+IDS__IsResumeDlg_6={&TahomaBold10}Resuming the InstallShield Wizard for [ProductName]
+IDS__IsResumeDlg_7=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBitmap.ibd
+IDS__IsSetupTypeMinDlg_0=[ProductName] - InstallShield Wizard
+IDS__IsSetupTypeMinDlg_1=< &Back
+IDS__IsSetupTypeMinDlg_10=&Next >
+IDS__IsSetupTypeMinDlg_11={&MSSansBold8}&Complete
+IDS__IsSetupTypeMinDlg_12={&MSSansBold8}Cu&stom
+IDS__IsSetupTypeMinDlg_13=
+IDS__IsSetupTypeMinDlg_14=<ISProductFolder>\Redist\Language Independent\OS Independent\CustomSetupIco.ibd
+IDS__IsSetupTypeMinDlg_15=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBanner.ibd
+IDS__IsSetupTypeMinDlg_16=<ISProductFolder>\Redist\Language Independent\OS Independent\CompleteSetupIco.ibd
+IDS__IsSetupTypeMinDlg_17=<ISProductFolder>\Redist\Language Independent\OS Independent\DestIcon.ibd
+IDS__IsSetupTypeMinDlg_18=Minimum required features will be installed.
+IDS__IsSetupTypeMinDlg_19=<ISProductFolder>\Redist\Language Independent\OS Independent\CustomSetupIco.ibd
+IDS__IsSetupTypeMinDlg_2={&MSSWhiteSerif8}InstallShield
+IDS__IsSetupTypeMinDlg_20={&MSSansBold8}&Minimal
+IDS__IsSetupTypeMinDlg_21=<ISProductFolder>\Redist\Language Independent\OS Independent\CustomSetupIco.ibd
+IDS__IsSetupTypeMinDlg_22=<ISProductFolder>\Redist\Language Independent\OS Independent\CompleteSetupIco.ibd
+IDS__IsSetupTypeMinDlg_23=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBanner.ibd
+IDS__IsSetupTypeMinDlg_24={&MSSansBold8}&Typical
+IDS__IsSetupTypeMinDlg_3=InstallShield
+IDS__IsSetupTypeMinDlg_4=Cancel
+IDS__IsSetupTypeMinDlg_5=All program features will be installed. (Requires the most disk space.)
+IDS__IsSetupTypeMinDlg_6=Choose which program features you want installed and where they will be installed. Recommended for advanced users.
+IDS__IsSetupTypeMinDlg_7=Choose the setup type that best suits your needs.
+IDS__IsSetupTypeMinDlg_8=Please select a setup type.
+IDS__IsSetupTypeMinDlg_9={&MSSansBold8}Setup Type
+IDS__IsStartCopyDlg_0=[ProductName] - InstallShield Wizard
+IDS__IsStartCopyDlg_1=< &Back
+IDS__IsStartCopyDlg_2={&MSSWhiteSerif8}InstallShield
+IDS__IsStartCopyDlg_3=InstallShield
+IDS__IsStartCopyDlg_4=Cancel
+IDS__IsStartCopyDlg_5=The wizard is ready to begin installation.
+IDS__IsStartCopyDlg_6=Click Next to begin the installation.
+IDS__IsStartCopyDlg_7=If you want to review or change any of your installation settings, click Back. Click Cancel to exit the wizard.
+IDS__IsStartCopyDlg_8={&MSSansBold8}Ready to Install
+IDS__IsStartCopyDlg_9=&Next >
+IDS__IsUserExit_0=[ProductName] - InstallShield Wizard
+IDS__IsUserExit_1=< &Back
+IDS__IsUserExit_10=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBitmap.ibd
+IDS__IsUserExit_2=Cancel
+IDS__IsUserExit_3=&Finish
+IDS__IsUserExit_4=Your system has not been modified. To install this program at a later time, please run the installation again.
+IDS__IsUserExit_5=Click Finish to exit the wizard.
+IDS__IsUserExit_6=You can either keep any existing installed elements on your system to continue this installation at a later time or you can restore your system to its original state prior to the installation.
+IDS__IsUserExit_7=Click Restore or Continue Later to exit the wizard.
+IDS__IsUserExit_8={&TahomaBold10}InstallShield Wizard Completed
+IDS__IsUserExit_9=The wizard was interrupted before [ProductName] could be completely installed.
+IDS__IsVerifyReadyDlg_0=[ProductName] - InstallShield Wizard
+IDS__IsVerifyReadyDlg_1=< &Back
+IDS__IsVerifyReadyDlg_10={&MSSansBold8}Ready to Repair the Program
+IDS__IsVerifyReadyDlg_11={&MSSansBold8}Ready to Install the Program
+IDS__IsVerifyReadyDlg_12=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBanner.ibd
+IDS__IsVerifyReadyDlg_13=Serial: [SERIALNUMBER]
+IDS__IsVerifyReadyDlg_14=Company: [COMPANYNAME]
+IDS__IsVerifyReadyDlg_15=Name: [USERNAME]
+IDS__IsVerifyReadyDlg_16=User Information:
+IDS__IsVerifyReadyDlg_17=[INSTALLDIR]
+IDS__IsVerifyReadyDlg_18=Destination Folder:
+IDS__IsVerifyReadyDlg_19=[SelectedSetupType]
+IDS__IsVerifyReadyDlg_2={&MSSWhiteSerif8}InstallShield
+IDS__IsVerifyReadyDlg_20=Setup Type:
+IDS__IsVerifyReadyDlg_21=Current Settings:
+IDS__IsVerifyReadyDlg_3=InstallShield
+IDS__IsVerifyReadyDlg_4=Cancel
+IDS__IsVerifyReadyDlg_5=The wizard is ready to begin installation.
+IDS__IsVerifyReadyDlg_6=Click Install to begin the installation.
+IDS__IsVerifyReadyDlg_7=If you want to review or change any of your installation settings, click Back. Click Cancel to exit the wizard.
+IDS__IsVerifyReadyDlg_8={&MSSansBold8}Ready to Modify the Program
+IDS__IsVerifyReadyDlg_9=&Install
+IDS__IsVerifyRemoveAllDlg_0=[ProductName] - InstallShield Wizard
+IDS__IsVerifyRemoveAllDlg_1=< &Back
+IDS__IsVerifyRemoveAllDlg_10=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBanner.ibd
+IDS__IsVerifyRemoveAllDlg_2={&MSSWhiteSerif8}InstallShield
+IDS__IsVerifyRemoveAllDlg_3=InstallShield
+IDS__IsVerifyRemoveAllDlg_4=Cancel
+IDS__IsVerifyRemoveAllDlg_5=You have chosen to remove the program from your system.
+IDS__IsVerifyRemoveAllDlg_6=Click Remove to remove [ProductName] from your computer. After removal, this program will no longer be available for use.
+IDS__IsVerifyRemoveAllDlg_7=If you want to review or change any settings, click Back.
+IDS__IsVerifyRemoveAllDlg_8={&MSSansBold8}Remove the Program
+IDS__IsVerifyRemoveAllDlg_9=&Remove
+IDS__IsWelcomeDlg_0=[ProductName] - InstallShield Wizard
+IDS__IsWelcomeDlg_1=< &Back
+IDS__IsWelcomeDlg_2=Cancel
+IDS__IsWelcomeDlg_3=&Next >
+IDS__IsWelcomeDlg_4={&TahomaBold10}Welcome to the InstallShield Wizard for [ProductName]
+IDS__IsWelcomeDlg_5=The InstallShield(R) Wizard will install [ProductName] on your computer. To continue, click Next.
+IDS__IsWelcomeDlg_6=<ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBitmap.ibd
+IDS__IsWelcomeDlg_7=WARNING: This program is protected by copyright law and international treaties.
+IDS__SetupTips_0=[ProductName] - InstallShield Wizard
+IDS__TargetReq_DESC_COLOR=The color settings of your system are not adequate for running [ProductName].
+IDS__TargetReq_DESC_OS=The operating system is not adequate for running [ProductName].
+IDS__TargetReq_DESC_PROCESSOR=The processor is not adequate for running [ProductName].
+IDS__TargetReq_DESC_RAM=The amount of RAM is not adequate for running [ProductName].
+IDS__TargetReq_DESC_RESOLUTION=The screen resolution is not adequate for running [ProductName].
+ID_STRING1=IniFile1.ini
+ID_STRING2=BBC|BBC Archives
+PRODUCT_NAME=BBC Archives (BFI1)
+PRODUCT_VERSION=2.38.0000
Index: /tags/start/is_5_gsdl_cdrom/Component Definitions/Default.cdf
===================================================================
--- /tags/start/is_5_gsdl_cdrom/Component Definitions/Default.cdf	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/Component Definitions/Default.cdf	(revision 13666)
@@ -0,0 +1,262 @@
+[Local library]
+SELECTED=Yes
+FILENEED=STANDARD
+HTTPLOCATION=
+STATUS=
+UNINSTALLABLE=Yes
+TARGET=<TARGETDIR>
+FTPLOCATION=
+VISIBLE=Yes
+DESCRIPTION=
+DISPLAYTEXT=
+IMAGE=
+DEFSELECTION=Yes
+filegroup0=Local library
+COMMENT=
+INCLUDEINBUILD=Yes
+INSTALLATION=ALWAYSOVERWRITE
+COMPRESSIFSEPARATE=No
+MISC=
+ENCRYPT=No
+DISK=ANYDISK
+TARGETDIRCDROM=..\bin\windows
+PASSWORD=
+TARGETHIDDEN=General Application Destination
+
+[collections\wordpdf]
+SELECTED=Yes
+FILENEED=STANDARD
+HTTPLOCATION=
+STATUS=
+UNINSTALLABLE=Yes
+TARGET=<TARGETDIR>\collect
+FTPLOCATION=
+VISIBLE=Yes
+DESCRIPTION=
+DISPLAYTEXT=TEXT_WORDPDF
+IMAGE=
+DEFSELECTION=Yes
+filegroup0=wordpdf
+COMMENT=
+INCLUDEINBUILD=Yes
+INSTALLATION=ALWAYSOVERWRITE
+COMPRESSIFSEPARATE=No
+MISC=
+ENCRYPT=No
+DISK=ANYDISK
+TARGETDIRCDROM=..\..\collect
+PASSWORD=
+TARGETHIDDEN=General Application Destination\collect
+
+[setpw]
+SELECTED=Yes
+FILENEED=STANDARD
+HTTPLOCATION=
+STATUS=
+UNINSTALLABLE=Yes
+TARGET=<TARGETDIR>
+FTPLOCATION=
+VISIBLE=Yes
+DESCRIPTION=
+DISPLAYTEXT=
+IMAGE=
+DEFSELECTION=Yes
+filegroup0=setpw
+COMMENT=
+INCLUDEINBUILD=Yes
+INSTALLATION=ALWAYSOVERWRITE
+COMPRESSIFSEPARATE=No
+MISC=
+ENCRYPT=No
+DISK=ANYDISK
+TARGETDIRCDROM=..\bin\windows
+PASSWORD=
+TARGETHIDDEN=General Application Destination
+
+[Components]
+component0=collections\wordpdf
+component1=Local library
+component2=setpw
+component3=collections\gsarch
+component4=collections\hdlsub
+component5=Run-time files
+component6=Readme
+component7=collections
+component8=collections\chinese
+
+[SetupTypeItem-Default]
+Comment=
+item0=Local library
+item1=Run-time files
+item2=Readme
+Descrip=LOCAL_LIBRARY_DESC
+DisplayText=LOCAL_LIBRARY
+
+[TopComponents]
+component0=collections
+component1=Local library
+component2=Run-time files
+component3=Readme
+component4=setpw
+
+[collections\gsarch]
+SELECTED=Yes
+FILENEED=STANDARD
+HTTPLOCATION=
+STATUS=
+UNINSTALLABLE=Yes
+TARGET=<TARGETDIR>\collect
+FTPLOCATION=
+VISIBLE=Yes
+DESCRIPTION=
+DISPLAYTEXT=TEXT_GSARCH
+IMAGE=
+DEFSELECTION=Yes
+filegroup0=gsarch
+COMMENT=
+INCLUDEINBUILD=Yes
+INSTALLATION=ALWAYSOVERWRITE
+COMPRESSIFSEPARATE=No
+MISC=
+ENCRYPT=No
+DISK=ANYDISK
+TARGETDIRCDROM=..\..\collect
+PASSWORD=
+TARGETHIDDEN=General Application Destination\collect
+
+[SetupType]
+setuptype0=Default
+
+[collections\hdlsub]
+SELECTED=Yes
+FILENEED=STANDARD
+HTTPLOCATION=
+STATUS=
+UNINSTALLABLE=Yes
+TARGET=<TARGETDIR>\collect
+FTPLOCATION=
+VISIBLE=Yes
+DESCRIPTION=
+DISPLAYTEXT=TEXT_HDLSUB
+IMAGE=
+DEFSELECTION=Yes
+filegroup0=hdlsub
+COMMENT=
+INCLUDEINBUILD=Yes
+INSTALLATION=ALWAYSOVERWRITE
+COMPRESSIFSEPARATE=No
+MISC=
+ENCRYPT=No
+DISK=ANYDISK
+TARGETDIRCDROM=..\..\collect
+PASSWORD=
+TARGETHIDDEN=General Application Destination\collect
+
+[Run-time files]
+SELECTED=Yes
+FILENEED=STANDARD
+HTTPLOCATION=
+STATUS=
+UNINSTALLABLE=Yes
+TARGET=<TARGETDIR>
+FTPLOCATION=
+VISIBLE=Yes
+DESCRIPTION=
+DISPLAYTEXT=
+IMAGE=
+DEFSELECTION=Yes
+filegroup0=Run-time files
+COMMENT=
+INCLUDEINBUILD=Yes
+INSTALLATION=ALWAYSOVERWRITE
+COMPRESSIFSEPARATE=No
+MISC=
+ENCRYPT=No
+DISK=ANYDISK
+TARGETDIRCDROM=..\..\gsdl
+PASSWORD=
+TARGETHIDDEN=General Application Destination
+
+[Info]
+Type=CompDef
+Version=1.00.000
+Name=
+
+[collections]
+SELECTED=Yes
+FILENEED=STANDARD
+HTTPLOCATION=
+STATUS=
+UNINSTALLABLE=Yes
+TARGET=<TARGETDIR>\collect
+member0=collections\gsarch
+FTPLOCATION=
+member1=collections\chinese
+VISIBLE=Yes
+DESCRIPTION=
+member2=collections\hdlsub
+member3=collections\wordpdf
+DISPLAYTEXT=
+IMAGE=
+DEFSELECTION=Yes
+COMMENT=
+INCLUDEINBUILD=Yes
+INSTALLATION=ALWAYSOVERWRITE
+COMPRESSIFSEPARATE=No
+MISC=
+ENCRYPT=No
+DISK=ANYDISK
+TARGETDIRCDROM=..\..\collect
+PASSWORD=
+TARGETHIDDEN=General Application Destination\collect
+
+[Readme]
+SELECTED=Yes
+FILENEED=STANDARD
+HTTPLOCATION=
+STATUS=
+UNINSTALLABLE=Yes
+TARGET=<TARGETDIR>
+FTPLOCATION=
+VISIBLE=Yes
+DESCRIPTION=
+DISPLAYTEXT=
+IMAGE=
+DEFSELECTION=Yes
+filegroup0=Readme
+COMMENT=
+INCLUDEINBUILD=Yes
+INSTALLATION=ALWAYSOVERWRITE
+COMPRESSIFSEPARATE=No
+MISC=
+ENCRYPT=No
+DISK=ANYDISK
+TARGETDIRCDROM=..\..
+PASSWORD=
+TARGETHIDDEN=General Application Destination
+
+[collections\chinese]
+SELECTED=Yes
+FILENEED=STANDARD
+HTTPLOCATION=
+STATUS=
+UNINSTALLABLE=Yes
+TARGET=<TARGETDIR>\collect
+FTPLOCATION=
+VISIBLE=Yes
+DESCRIPTION=
+DISPLAYTEXT=TEXT_CHINESE
+IMAGE=
+DEFSELECTION=Yes
+filegroup0=chinese
+COMMENT=
+INCLUDEINBUILD=Yes
+INSTALLATION=ALWAYSOVERWRITE
+COMPRESSIFSEPARATE=No
+MISC=
+ENCRYPT=No
+DISK=ANYDISK
+TARGETDIRCDROM=..\..\collect
+PASSWORD=
+TARGETHIDDEN=General Application Destination\collect
+
Index: /tags/start/is_5_gsdl_cdrom/Component Definitions/Default.fgl
===================================================================
--- /tags/start/is_5_gsdl_cdrom/Component Definitions/Default.fgl	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/Component Definitions/Default.fgl	(revision 13666)
@@ -0,0 +1,66 @@
+[<TARGETDIR>\bin\windows]
+DISPLAYTEXT=
+TYPE=FOLDER
+fulldirectory=
+
+[<PROGRAMFILES>\<COMMONFILES>]
+DISPLAYTEXT=Common Files Folder
+TYPE=TEXTSUBFIXED
+fulldirectory=
+
+[<TARGETDIR>\cgi-bin]
+DISPLAYTEXT=
+TYPE=FOLDER
+fulldirectory=
+
+[<WINDIR>\<WINSYSDIR>]
+DISPLAYTEXT=Windows System Folder
+TYPE=TEXTSUBFIXED
+fulldirectory=
+
+[USERDEFINED]
+DISPLAYTEXT=Script-defined Folders
+TYPE=USERSTART
+fulldirectory=
+
+[<TARGETDIR>\bin]
+DISPLAYTEXT=
+SubDir0=<TARGETDIR>\bin\windows
+TYPE=FOLDER
+fulldirectory=
+
+[<PROGRAMFILES>]
+DISPLAYTEXT=Program Files Folder
+SubDir0=<PROGRAMFILES>\<COMMONFILES>
+TYPE=TEXTSUBFIXED
+fulldirectory=
+
+[<TARGETDIR>]
+DISPLAYTEXT=General Application Destination
+SubDir0=<TARGETDIR>\bin
+SubDir1=<TARGETDIR>\cgi-bin
+TYPE=TEXTSUBFIXED
+SubDir2=<TARGETDIR>\collect
+fulldirectory=
+
+[<WINDIR>]
+DISPLAYTEXT=Windows Operating System
+SubDir0=<WINDIR>\<WINSYSDIR>
+TYPE=TEXTSUBFIXED
+fulldirectory=
+
+[TopDir]
+SubDir0=<WINDIR>
+SubDir1=<PROGRAMFILES>
+SubDir2=<TARGETDIR>
+SubDir3=USERDEFINED
+
+[General]
+Type=FILELIST
+Version=1.10.000
+
+[<TARGETDIR>\collect]
+DISPLAYTEXT=
+TYPE=FOLDER
+fulldirectory=
+
Index: /tags/start/is_5_gsdl_cdrom/File Groups/Default.fdf
===================================================================
--- /tags/start/is_5_gsdl_cdrom/File Groups/Default.fdf	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/File Groups/Default.fdf	(revision 13666)
@@ -0,0 +1,135 @@
+[gsarch]
+SELFREGISTERING=No
+HTTPLOCATION=
+LANGUAGE=
+OPERATINGSYSTEM=
+FTPLOCATION=
+FILETYPE=No
+INFOTYPE=Standard
+COMMENT=
+COMPRESS=Yes
+COMPRESSDLL=
+LINKTYPE=Static Link
+POTENTIALLY=No
+MISC=
+
+[FileGroups]
+group0=Local library
+group1=gsarch
+group2=setpw
+group3=hdlsub
+group4=Run-time files
+group5=chinese
+group6=Readme
+group7=wordpdf
+
+[Local library]
+SELFREGISTERING=No
+HTTPLOCATION=
+LANGUAGE=
+OPERATINGSYSTEM=
+FTPLOCATION=
+FILETYPE=No
+INFOTYPE=Standard
+COMMENT=
+COMPRESS=Yes
+COMPRESSDLL=
+LINKTYPE=Static Link
+POTENTIALLY=No
+MISC=
+
+[hdlsub]
+SELFREGISTERING=No
+HTTPLOCATION=
+LANGUAGE=
+OPERATINGSYSTEM=
+FTPLOCATION=
+FILETYPE=No
+INFOTYPE=Standard
+COMMENT=
+COMPRESS=Yes
+COMPRESSDLL=
+LINKTYPE=Static Link
+POTENTIALLY=No
+MISC=
+
+[setpw]
+SELFREGISTERING=No
+HTTPLOCATION=
+LANGUAGE=
+OPERATINGSYSTEM=
+FTPLOCATION=
+FILETYPE=No
+INFOTYPE=Standard
+COMMENT=
+COMPRESS=Yes
+COMPRESSDLL=
+LINKTYPE=Static Link
+POTENTIALLY=No
+MISC=
+
+[Run-time files]
+SELFREGISTERING=No
+HTTPLOCATION=
+LANGUAGE=
+OPERATINGSYSTEM=
+FTPLOCATION=
+FILETYPE=No
+INFOTYPE=Standard
+COMMENT=
+COMPRESS=Yes
+COMPRESSDLL=
+LINKTYPE=Static Link
+POTENTIALLY=No
+MISC=
+
+[Info]
+Type=FileGrp
+Version=1.00.000
+Name=
+
+[chinese]
+SELFREGISTERING=No
+HTTPLOCATION=
+LANGUAGE=
+OPERATINGSYSTEM=
+FTPLOCATION=
+FILETYPE=No
+INFOTYPE=Standard
+COMMENT=
+COMPRESS=Yes
+COMPRESSDLL=
+LINKTYPE=Static Link
+POTENTIALLY=No
+MISC=
+
+[Readme]
+SELFREGISTERING=No
+HTTPLOCATION=
+LANGUAGE=
+OPERATINGSYSTEM=
+FTPLOCATION=
+FILETYPE=No
+INFOTYPE=Standard
+COMMENT=
+COMPRESS=Yes
+COMPRESSDLL=
+LINKTYPE=Static Link
+POTENTIALLY=No
+MISC=
+
+[wordpdf]
+SELFREGISTERING=No
+HTTPLOCATION=
+LANGUAGE=
+OPERATINGSYSTEM=
+FTPLOCATION=
+FILETYPE=No
+INFOTYPE=Standard
+COMMENT=
+COMPRESS=Yes
+COMPRESSDLL=
+LINKTYPE=Static Link
+POTENTIALLY=No
+MISC=
+
Index: /tags/start/is_5_gsdl_cdrom/File Groups/Local library.fgl
===================================================================
--- /tags/start/is_5_gsdl_cdrom/File Groups/Local library.fgl	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/File Groups/Local library.fgl	(revision 13666)
@@ -0,0 +1,12 @@
+[TopDir]
+file0=C:\sjboddie\gsdl-2.38-cdrom\Windows\bin\windows\server.exe
+SubDir0=net16
+
+[net16]
+file0=C:\sjboddie\gsdl-2.38-cdrom\Windows\bin\windows\net16\WINSOCK.DLL
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\Windows\bin\windows\net16
+
+[General]
+Type=FILELIST
+Version=1.10.000
+
Index: /tags/start/is_5_gsdl_cdrom/File Groups/Program Executable Files.fgl
===================================================================
--- /tags/start/is_5_gsdl_cdrom/File Groups/Program Executable Files.fgl	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/File Groups/Program Executable Files.fgl	(revision 13666)
@@ -0,0 +1,4 @@
+[General]
+Type=FILELIST
+Version=1.00.000
+
Index: /tags/start/is_5_gsdl_cdrom/File Groups/Readme.fgl
===================================================================
--- /tags/start/is_5_gsdl_cdrom/File Groups/Readme.fgl	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/File Groups/Readme.fgl	(revision 13666)
@@ -0,0 +1,7 @@
+[TopDir]
+file0=C:\sjboddie\gsdl-2.38-cdrom\README.TXT
+
+[General]
+Type=FILELIST
+Version=1.10.000
+
Index: /tags/start/is_5_gsdl_cdrom/File Groups/Run-time files.fgl
===================================================================
--- /tags/start/is_5_gsdl_cdrom/File Groups/Run-time files.fgl	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/File Groups/Run-time files.fgl	(revision 13666)
@@ -0,0 +1,1949 @@
+[images\nl]
+file59=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tlanggr.gif
+file48=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tbrwseof.gif
+file37=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\h_title.gif
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\h_date.gif
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\eexpcon.gif
+file49=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tbrwseon.gif
+file38=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\h_to.gif
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\h_from.gif
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\ehlof.gif
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\chelpof.gif
+file39=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\h_topic.gif
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\h_help.gif
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\ehlon.gif
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\chelpon.gif
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\h_how.gif
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\enhlof.gif
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\chomeof.gif
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\enhlon.gif
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\chomeon.gif
+file80=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\ttogr.gif
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\contof.gif
+file81=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\ttoof.gif
+file70=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tseron.gif
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\conton.gif
+file82=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\ttoon.gif
+file71=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tsrchgr.gif
+file60=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tlangof.gif
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\cprefof.gif
+file83=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\ttopicgr.gif
+file72=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tsrchof.gif
+file61=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tlangon.gif
+file50=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tdategr.gif
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\cprefon.gif
+file84=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\ttopicof.gif
+file73=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tsrchon.gif
+file62=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\torggr.gif
+file51=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tdateof.gif
+file40=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\qryresb.gif
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\ealltof.gif
+file85=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\ttopicon.gif
+file74=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tsubjgr.gif
+file63=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\torgof.gif
+file52=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tdateon.gif
+file41=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tacrogr.gif
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\h_lang.gif
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\eallton.gif
+file75=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tsubjof.gif
+file64=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\torgon.gif
+file53=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tfromgr.gif
+file42=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tacroof.gif
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\h_org.gif
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\etsecof.gif
+file76=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tsubjon.gif
+file65=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tpeopgr.gif
+file54=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tfromof.gif
+file43=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tacroon.gif
+file32=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\h_people.gif
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\etsecon.gif
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\econcof.gif
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl
+file77=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\ttitlgr.gif
+file66=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tpeopof.gif
+file55=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tfromon.gif
+file44=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tauthgr.gif
+file33=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\h_pref.gif
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\h_about.gif
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\econcon.gif
+file78=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\ttitlof.gif
+file67=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tpeopon.gif
+file56=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\thowgr.gif
+file45=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tauthof.gif
+file34=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\h_search.gif
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\h_acro.gif
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\edtchof.gif
+file79=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\ttitlon.gif
+file68=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tsergr.gif
+file57=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\thowof.gif
+file46=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tauthon.gif
+file35=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\h_ser.gif
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\h_auth.gif
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\edtchon.gif
+file69=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tserof.gif
+file58=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\thowon.gif
+file47=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\tbrwsegr.gif
+file36=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\h_subj.gif
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\h_brwse.gif
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nl\eexpcof.gif
+
+[tmp]
+fulldirectory=
+
+[collect\demo\index\dtx]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\dtx\demo.i
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\dtx\demo.ib1
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\dtx\demo.ib2
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\dtx\demo.ib3
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\dtx\demo.idb
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\dtx\demo.tiw
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\dtx\demo.wa
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\dtx
+
+[images\zh]
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\tauthof.gif
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\tauthon.gif
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\chelpof.gif
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\tsrchgr.gif
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\chelpon.gif
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\tsrchof.gif
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\chomeof.gif
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\tsrchon.gif
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\chomeon.gif
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\contof.gif
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\conton.gif
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\cprefof.gif
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\cprefon.gif
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\h_auth.gif
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\h_help.gif
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\ttitlgr.gif
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\ttitlof.gif
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\h_pref.gif
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\ttitlon.gif
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\h_search.gif
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\h_title.gif
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\qryresb.gif
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\zh\tauthgr.gif
+
+[mappings\to_uc]
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\win1258.ump
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\koi8_u.ump
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\win874.ump
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\shiftjis.ump
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\8859_1.ump
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\uhc.ump
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\8859_2.ump
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\win1250.ump
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\8859_3.ump
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\win1251.ump
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\8859_4.ump
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\8859_5.ump
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\8859_6.ump
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\8859_7.ump
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\8859_8.ump
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\8859_9.ump
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\big5.ump
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\win1252.ump
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\win1253.ump
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\dos866.ump
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\win1254.ump
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\euc_jp.ump
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\win1255.ump
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\gbk.ump
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\win1256.ump
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\iscii_de.ump
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\win1257.ump
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\to_uc\koi8_r.ump
+
+[bin]
+SubDir0=bin\java
+fulldirectory=
+
+[collect\demo\index\assoc\HASH01f2.dir]
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p84.png
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p55.png
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p87.png
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p58.png
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\cover.jpg
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p88.png
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p61.png
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p00.png
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p91.png
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p63.png
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p06.png
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p66.png
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p09.png
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p101.png
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p13.png
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p23.png
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p26.png
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p29.png
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p93.png
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p33.png
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p94.png
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p68.png
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p70.png
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p40.png
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p73.png
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p43.png
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p77.png
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p45.png
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p79.png
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p48.png
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p82.png
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01f2.dir\p52.png
+
+[collect\demo\import\b20cre]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b20cre\b20a.png
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b20cre\b20cre.htm
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b20cre\b20cre.jpg
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b20cre
+
+[images\ar]
+file59=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tsrchgr.gif
+file48=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\thowof.gif
+file37=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\qryresb.gif
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\h_date.gif
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\eexpcof.gif
+file49=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\thowon.gif
+file38=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tauthgr.gif
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\h_help.gif
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\eexpcon.gif
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\chelpof.gif
+file39=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tauthof.gif
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\h_how.gif
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\ehlof.gif
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\chelpon.gif
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\h_org.gif
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\ehlon.gif
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\chomeof.gif
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\enhlof.gif
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\chomeon.gif
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\contof.gif
+file70=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\ttopicon.gif
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\conton.gif
+file60=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tsrchof.gif
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\cprefof.gif
+file61=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tsrchon.gif
+file50=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\torggr.gif
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\cprefon.gif
+file62=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tsubjgr.gif
+file51=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\torgof.gif
+file40=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tauthon.gif
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\display.gif
+file63=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tsubjof.gif
+file52=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\torgon.gif
+file41=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tbrwsegr.gif
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\h_people.gif
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\ealltof.gif
+file64=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tsubjon.gif
+file53=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tpeopgr.gif
+file42=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tbrwseof.gif
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\h_pref.gif
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\enhlon.gif
+file65=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\ttitlgr.gif
+file54=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tpeopof.gif
+file43=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tbrwseon.gif
+file32=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\h_search.gif
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\etsecof.gif
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\eallton.gif
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar
+file66=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\ttitlof.gif
+file55=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tpeopon.gif
+file44=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tdategr.gif
+file33=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\h_ser.gif
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\etsecon.gif
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\econcof.gif
+file67=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\ttitlon.gif
+file56=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tsergr.gif
+file45=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tdateof.gif
+file34=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\h_subj.gif
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\h_about.gif
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\econcon.gif
+file68=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\ttopicgr.gif
+file57=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tserof.gif
+file46=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tdateon.gif
+file35=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\h_title.gif
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\h_auth.gif
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\edtchof.gif
+file69=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\ttopicof.gif
+file58=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\tseron.gif
+file47=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\thowgr.gif
+file36=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\h_topic.gif
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\h_brwse.gif
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ar\edtchon.gif
+
+[images\de]
+file59=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tsrchof.gif
+file48=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\thowon.gif
+file37=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tauthgr.gif
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\h_help.gif
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\eexpcon.gif
+file49=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\torggr.gif
+file38=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tauthof.gif
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\h_how.gif
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\ehlof.gif
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\chelpof.gif
+file39=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tauthon.gif
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\h_org.gif
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\ehlon.gif
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\chelpon.gif
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\h_people.gif
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\enhlof.gif
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\chomeof.gif
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\enhlon.gif
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\chomeon.gif
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\contof.gif
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\conton.gif
+file60=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tsrchon.gif
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\cprefof.gif
+file61=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tsubjgr.gif
+file50=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\torgof.gif
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\cprefon.gif
+file62=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tsubjof.gif
+file51=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\torgon.gif
+file40=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tbrwsegr.gif
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\ealltof.gif
+file63=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tsubjon.gif
+file52=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tpeopgr.gif
+file41=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tbrwseof.gif
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\h_pref.gif
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\eallton.gif
+file64=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\ttitlgr.gif
+file53=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tpeopof.gif
+file42=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tbrwseon.gif
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\h_search.gif
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\etsecof.gif
+file65=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\ttitlof.gif
+file54=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tpeopon.gif
+file43=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tdategr.gif
+file32=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\h_ser.gif
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\etsecon.gif
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\econcof.gif
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de
+file66=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\ttitlon.gif
+file55=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tsergr.gif
+file44=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tdateof.gif
+file33=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\h_subj.gif
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\h_about.gif
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\econcon.gif
+file67=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\ttopicgr.gif
+file56=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tserof.gif
+file45=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tdateon.gif
+file34=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\h_title.gif
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\h_auth.gif
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\edtchof.gif
+file68=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\ttopicof.gif
+file57=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tseron.gif
+file46=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\thowgr.gif
+file35=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\h_topic.gif
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\h_brwse.gif
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\edtchon.gif
+file69=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\ttopicon.gif
+file58=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\tsrchgr.gif
+file47=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\thowof.gif
+file36=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\qryresb.gif
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\h_date.gif
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\de\eexpcof.gif
+
+[collect\demo\index\assoc\HASH30aa.dir]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH30aa.dir\cover.jpg
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH30aa.dir\p07a.png
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH30aa.dir\p32a.png
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH30aa.dir\p95a.png
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH30aa.dir
+
+[collect\demo\index\assoc\HASH01d2.dir]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01d2.dir\cover.jpg
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01d2.dir\p04to05.png
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01d2.dir\p27.png
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01d2.dir\p31.png
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01d2.dir\p32.png
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01d2.dir\p59.png
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01d2.dir\p68to69.png
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01d2.dir\p98.png
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH01d2.dir
+
+[collect\demo\import\b21wae]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b21wae\b21wae.htm
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b21wae\b21wae.jpg
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b21wae\p04to05.png
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b21wae\p27.png
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b21wae\p31.png
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b21wae\p32.png
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b21wae\p59.png
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b21wae\p68to69.png
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b21wae\p98.png
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b21wae
+
+[collect\demo\index\assoc\HASH5756.dir]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH5756.dir\cover.jpg
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH5756.dir\p15.png
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH5756.dir\p32.png
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH5756.dir\p48.png
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH5756.dir
+
+[images\ru]
+file59=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tfromgr.gif
+file48=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tauthof.gif
+file37=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\h_subj.gif
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\h_date.gif
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\eexpcon.gif
+file49=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tauthon.gif
+file38=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\h_title.gif
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\h_from.gif
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\ehlof.gif
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\chelpof.gif
+file39=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\h_to.gif
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\h_help.gif
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\ehlon.gif
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\chelpon.gif
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\h_how.gif
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\enhlof.gif
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\chomeof.gif
+file90=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\ttoof.gif
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\enhlon.gif
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\chomeon.gif
+file91=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\ttoon.gif
+file80=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tsrchgr.gif
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\contof.gif
+file92=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\ttopicgr.gif
+file81=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tsrchof.gif
+file70=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\torgon.gif
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\conton.gif
+file93=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\ttopicof.gif
+file82=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tsrchon.gif
+file71=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tpeopgr.gif
+file60=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tfromof.gif
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\cprefof.gif
+file94=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\ttopicon.gif
+file83=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tsubjgr.gif
+file72=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tpeopof.gif
+file61=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tfromon.gif
+file50=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tbrwsegr.gif
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\cprefon.gif
+file84=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tsubjof.gif
+file73=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tpeopon.gif
+file62=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\thowgr.gif
+file51=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tbrwseof.gif
+file40=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\h_topic.gif
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\ealltof.gif
+file85=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tsubjon.gif
+file74=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tphrsegr.gif
+file63=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\thowof.gif
+file52=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tbrwseon.gif
+file41=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\qryresb.gif
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\h_lang.gif
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\eallton.gif
+file86=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\ttitlgr.gif
+file75=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tphrseof.gif
+file64=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\thowon.gif
+file53=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tcatgr.gif
+file42=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\schhistb.gif
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\h_org.gif
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\etsecof.gif
+file87=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\ttitlof.gif
+file76=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tphrseon.gif
+file65=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tlanggr.gif
+file54=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tcatof.gif
+file43=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\selcolgr.gif
+file32=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\h_people.gif
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\etsecon.gif
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\econcof.gif
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru
+file88=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\ttitlon.gif
+file77=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tsergr.gif
+file66=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tlangof.gif
+file55=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tcaton.gif
+file44=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tacrogr.gif
+file33=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\h_phrse.gif
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\h_about.gif
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\econcon.gif
+file89=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\ttogr.gif
+file78=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tserof.gif
+file67=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tlangon.gif
+file56=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tdategr.gif
+file45=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tacroof.gif
+file34=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\h_pref.gif
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\h_acro.gif
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\edtchof.gif
+file79=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tseron.gif
+file68=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\torggr.gif
+file57=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tdateof.gif
+file46=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tacroon.gif
+file35=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\h_search.gif
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\h_auth.gif
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\edtchon.gif
+file69=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\torgof.gif
+file58=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tdateon.gif
+file47=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\tauthgr.gif
+file36=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\h_ser.gif
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\h_brwse.gif
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ru\eexpcof.gif
+
+[collect\demo\index\assoc\HASH0102.dir]
+file59=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p293a.png
+file48=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p210a.png
+file37=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g037a.png
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g026a.png
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g015a.png
+file49=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p219a.png
+file38=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g038a.png
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g027a.png
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g016a.png
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\cover.jpg
+file39=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g039a.png
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g028a.png
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g017a.png
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g001a.png
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g029a.png
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g018a.png
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g002a.png
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g019a.png
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g003a.png
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g004a.png
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g005a.png
+file60=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p301a.png
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g006a.png
+file61=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p309a.png
+file50=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p227a.png
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g007a.png
+file62=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p323a.png
+file51=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p236a.png
+file40=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g040a.png
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g008a.png
+file63=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p349a.png
+file52=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p243a.png
+file41=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p112a.png
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g030a.png
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g009a.png
+file64=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p357a.png
+file53=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p24a.png
+file42=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p117a.png
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g031a.png
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g020a.png
+file65=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p39a.png
+file54=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p252a.png
+file43=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p129a.png
+file32=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g032a.png
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g021a.png
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g010a.png
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir
+file66=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p81a.png
+file55=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p260a.png
+file44=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p138a.png
+file33=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g033a.png
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g022a.png
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g011a.png
+file67=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p96a.png
+file56=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p265a.png
+file45=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p149a.png
+file34=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g034a.png
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g023a.png
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g012a.png
+file68=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p9a.png
+file57=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p274a.png
+file46=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p159a.png
+file35=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g035a.png
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g024a.png
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g013a.png
+file58=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p292a.png
+file47=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\p203a.png
+file36=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g036a.png
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g025a.png
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH0102.dir\g014a.png
+
+[macros]
+file37=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\style.dm
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\italian2.dm
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\extlink.dm
+file38=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\tip.dm
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\maori.dm
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\french.dm
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\about.dm
+file39=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\users.dm
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\nzdlhome.dm
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\french2.dm
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\arabic.dm
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\port.dm
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\german.dm
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\authen.dm
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\gsdl.dm
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\base.dm
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\browse.dm
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\bsummary.dm
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\chinese.dm
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\Chktrans.pl
+file40=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\yourhome.dm
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\collect.dm
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\pref.dm
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\dateqry.dm
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\query.dm
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\hebrew.dm
+file32=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\russian.dm
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\help.dm
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\docs.dm
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros
+file33=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\russian2.dm
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\home.dm
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\document.dm
+file34=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\spanish.dm
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\html.dm
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\dutch.dm
+file35=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\spanish2.dm
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\indo.dm
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\english.dm
+file36=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\status.dm
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\italian.dm
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\macros\english2.dm
+
+[images\pt]
+file59=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tsrchof.gif
+file48=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\thowon.gif
+file37=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tauthgr.gif
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\h_help.gif
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\eexpcon.gif
+file49=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\torggr.gif
+file38=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tauthof.gif
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\h_how.gif
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\ehlof.gif
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\chelpof.gif
+file39=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tauthon.gif
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\h_org.gif
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\ehlon.gif
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\chelpon.gif
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\h_people.gif
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\enhlof.gif
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\chomeof.gif
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\enhlon.gif
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\chomeon.gif
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\contof.gif
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\conton.gif
+file60=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tsrchon.gif
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\cprefof.gif
+file61=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tsubjgr.gif
+file50=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\torgof.gif
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\cprefon.gif
+file62=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tsubjof.gif
+file51=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\torgon.gif
+file40=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tbrwsegr.gif
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\ealltof.gif
+file63=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tsubjon.gif
+file52=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tpeopgr.gif
+file41=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tbrwseof.gif
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\h_pref.gif
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\eallton.gif
+file64=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\ttitlgr.gif
+file53=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tpeopof.gif
+file42=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tbrwseon.gif
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\h_search.gif
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\etsecof.gif
+file65=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\ttitlof.gif
+file54=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tpeopon.gif
+file43=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tdategr.gif
+file32=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\h_ser.gif
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\etsecon.gif
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\econcof.gif
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt
+file66=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\ttitlon.gif
+file55=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tsergr.gif
+file44=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tdateof.gif
+file33=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\h_subj.gif
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\h_about.gif
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\econcon.gif
+file67=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\ttopicgr.gif
+file56=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tserof.gif
+file45=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tdateon.gif
+file34=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\h_title.gif
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\h_auth.gif
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\edtchof.gif
+file68=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\ttopicof.gif
+file57=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tseron.gif
+file46=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\thowgr.gif
+file35=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\h_topic.gif
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\h_brwse.gif
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\edtchon.gif
+file69=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\ttopicon.gif
+file58=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\tsrchgr.gif
+file47=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\thowof.gif
+file36=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\qryresb.gif
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\h_date.gif
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pt\eexpcof.gif
+
+[collect\demo\index\assoc\HASH010f.dir]
+file59=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p81a.png
+file48=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p77a.png
+file37=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p72b.png
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p68d.png
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p65b.png
+file49=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p77b.png
+file38=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p73a.png
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p69a.png
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p65c.png
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\cover.jpg
+file39=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p73b.png
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p69b.png
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p65d.png
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p60a.png
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p69c.png
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p66a.png
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p61a.png
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p66b.png
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p61b.png
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p61c.png
+file70=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p85a.png
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p61d.png
+file71=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p85b.png
+file60=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p81b.png
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p62a.png
+file72=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p85c.png
+file61=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p82a.png
+file50=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p77c.png
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p62b.png
+file73=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p86a.png
+file62=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p82b.png
+file51=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p78a.png
+file40=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p74a.png
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p63a.png
+file74=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p86b.png
+file63=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p82c.png
+file52=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p78b.png
+file41=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p74b.png
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p70a.png
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p63b.png
+file75=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p86c.png
+file64=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p82d.png
+file53=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p79a.png
+file42=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p75a.png
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p70b.png
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p66c.png
+file76=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p87a.png
+file65=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p83a.png
+file54=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p79b.png
+file43=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p75b.png
+file32=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p70c.png
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p67a.png
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p64a.png
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir
+file77=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p87b.png
+file66=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p84a.png
+file55=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p79c.png
+file44=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p75c.png
+file33=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p71a.png
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p67b.png
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p64b.png
+file78=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p87c.png
+file67=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p84b.png
+file56=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p79d.png
+file45=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p76a.png
+file34=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p71b.png
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p68a.png
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p64c.png
+file79=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p88a.png
+file68=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p84c.png
+file57=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p80a.png
+file46=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p76b.png
+file35=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p71c.png
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p68b.png
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p64d.png
+file69=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p84d.png
+file58=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p80b.png
+file47=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p76c.png
+file36=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p72a.png
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p68c.png
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH010f.dir\f33p65a.png
+
+[collect\demo\index\assoc]
+SubDir8=collect\demo\index\assoc\HASH92b3.dir
+SubDir9=collect\demo\index\assoc\HASHa84b.dir
+SubDir10=collect\demo\index\assoc\HASHac0a.dir
+SubDir0=collect\demo\index\assoc\HASH0102.dir
+SubDir1=collect\demo\index\assoc\HASH010f.dir
+SubDir2=collect\demo\index\assoc\HASH01d2.dir
+SubDir3=collect\demo\index\assoc\HASH01f2.dir
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc
+SubDir4=collect\demo\index\assoc\HASH1631.dir
+SubDir5=collect\demo\index\assoc\HASH30aa.dir
+SubDir6=collect\demo\index\assoc\HASH4632.dir
+SubDir7=collect\demo\index\assoc\HASH5756.dir
+
+[collect\demo\import\fb33fe]
+file59=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p81b.png
+file48=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p77b.png
+file37=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p73a.png
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p69a.png
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p65c.png
+file49=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p77c.png
+file38=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p73b.png
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p69b.png
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p65d.png
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p60a.png
+file39=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p74a.png
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p69c.png
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p66a.png
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p61a.png
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p70a.png
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p66b.png
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p61b.png
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p66c.png
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p61c.png
+file80=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\fb33fe.jpg
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p61d.png
+file70=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p85b.png
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p62a.png
+file71=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p85c.png
+file60=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p82a.png
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p62b.png
+file72=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p86a.png
+file61=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p82b.png
+file50=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p78a.png
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p63a.png
+file73=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p86b.png
+file62=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p82c.png
+file51=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p78b.png
+file40=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p74b.png
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p63b.png
+file74=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p86c.png
+file63=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p82d.png
+file52=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p79a.png
+file41=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p75a.png
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p70b.png
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p64a.png
+file75=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p87a.png
+file64=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p83a.png
+file53=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p79b.png
+file42=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p75b.png
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p70c.png
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p67a.png
+file76=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p87b.png
+file65=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p84a.png
+file54=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p79c.png
+file43=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p75c.png
+file32=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p71a.png
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p67b.png
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p64b.png
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe
+file77=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p87c.png
+file66=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p84b.png
+file55=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p79d.png
+file44=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p76a.png
+file33=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p71b.png
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p68a.png
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p64c.png
+file78=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p88a.png
+file67=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p84c.png
+file56=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p80a.png
+file45=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p76b.png
+file34=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p71c.png
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p68b.png
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p64d.png
+file79=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\fb33fe.htm
+file68=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p84d.png
+file57=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p80b.png
+file46=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p76c.png
+file35=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p72a.png
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p68c.png
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p65a.png
+file69=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p85a.png
+file58=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p81a.png
+file47=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p77a.png
+file36=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p72b.png
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p68d.png
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb33fe\f33p65b.png
+
+[collect\demo\import\ec159e]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec159e\ec159e.htm
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec159e\ec159e.jpg
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec159e\p021.png
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec159e\p038.png
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec159e\p043.png
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec159e\p094.png
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec159e
+
+[collect\demo\import\b18ase]
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p82.png
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p52.png
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p84.png
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p55.png
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\b18ase.htm
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p87.png
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p58.png
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\b18ase.jpg
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p88.png
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p61.png
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p00.png
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p63.png
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p06.png
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p09.png
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p101.png
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p13.png
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p23.png
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p26.png
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p91.png
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p29.png
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p93.png
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p66.png
+file32=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p94.png
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p68.png
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p33.png
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p70.png
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p40.png
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p73.png
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p43.png
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p77.png
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p45.png
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p79.png
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b18ase\p48.png
+
+[images]
+SubDir8=images\nl
+file194=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ycbildof.gif
+file183=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ttitlgr.gif
+file172=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tseron.gif
+file161=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\torggr.gif
+file150=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tdateon.gif
+file59=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\gsdlhead.gif
+file48=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\gcexpton.gif
+file37=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\enhlon.gif
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ealltof.gif
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\chomeof.gif
+SubDir9=images\pt
+file195=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ycbildon.gif
+file184=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ttitlof.gif
+file173=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tspace.gif
+file162=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\torgof.gif
+file151=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tfromgr.gif
+file140=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tauthof.gif
+file49=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\gcinfoof.gif
+file38=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\etsecof.gif
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\eallton.gif
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\chomeon.gif
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\abgsgr.gif
+file196=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ycconfof.gif
+file185=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ttitlon.gif
+file174=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tsrcgr.gif
+file163=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\torgon.gif
+file152=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tfromof.gif
+file141=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tauthon.gif
+file130=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tacrnmgr.gif
+file39=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\etsecon.gif
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\econcof.gif
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\clsdfldr.gif
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\blank.gif
+SubDir10=images\ru
+file197=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ycconfon.gif
+file186=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ttogr.gif
+file175=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tsrchgr.gif
+file164=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tpeopgr.gif
+file153=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tfromon.gif
+file142=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tbrwsegr.gif
+file131=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tacrnmof.gif
+file120=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\qryresb.gif
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\econcon.gif
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\comment.gif
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\book.gif
+SubDir11=images\zh
+file198=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ycinfoof.gif
+file187=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ttoof.gif
+file176=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tsrchof.gif
+file165=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tpeopof.gif
+file154=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\thowgr.gif
+file143=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tbrwseof.gif
+file132=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tacrnmon.gif
+file121=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\schhistb.gif
+file110=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ncconfof.gif
+file90=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\icomm.gif
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\contof.gif
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\bshelf.gif
+file199=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ycinfoon.gif
+file188=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ttoon.gif
+file177=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tsrchon.gif
+file166=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tpeopon.gif
+file155=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\thowof.gif
+file144=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tbrwseon.gif
+file133=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tacrogr.gif
+file122=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\selcolde.gif
+file111=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ncinfoof.gif
+file100=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\irtf.gif
+file91=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iexcel.gif
+file80=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_rw.gif
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\cabgsof.gif
+file200=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ycsrceof.gif
+file189=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ttopicgr.gif
+file178=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tsrcof.gif
+file167=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tphrsegr.gif
+file156=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\thowon.gif
+file145=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tcatgr.gif
+file134=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tacroof.gif
+file123=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\selcolgr.gif
+file112=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ncsrceof.gif
+file101=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\itext.gif
+file92=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\imidi.gif
+file81=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_search.gif
+file70=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_date.gif
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\cabgson.gif
+file201=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ycsrceon.gif
+file179=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tsrcon.gif
+file168=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tphrseof.gif
+file157=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tick.gif
+file146=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tcatof.gif
+file135=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tacroon.gif
+file124=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\selcolun.gif
+file113=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ncviewof.gif
+file102=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\less.gif
+file93=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\impegvid.gif
+file82=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_ser.gif
+file71=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_from.gif
+file60=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\gsdocsgr.gif
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\cadminof.gif
+file202=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ycviewof.gif
+file169=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tphrseon.gif
+file158=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tlanggr.gif
+file147=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tcaton.gif
+file136=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tartstgr.gif
+file125=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\smtext.gif
+file114=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nosearch.gif
+file103=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\meldexsm.gif
+file94=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\imsword.gif
+file83=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_src.gif
+file72=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_help.gif
+file61=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\guarrow.gif
+file50=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\gcinfoon.gif
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\cadminon.gif
+SubDir0=images\ar
+file203=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ycviewon.gif
+file159=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tlangof.gif
+file148=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tdategr.gif
+file137=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tartstof.gif
+file126=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\space.gif
+file115=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\nzdl2gr.gif
+file104=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\more.gif
+file95=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ipdf.gif
+file84=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_subj.gif
+file73=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_how.gif
+file62=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\hdlimg.jpg
+file51=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\gcsrceof.gif
+file40=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\gbull.gif
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ccolof.gif
+SubDir1=images\de
+file149=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tdateof.gif
+file138=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tartston.gif
+file127=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\spacer.gif
+file116=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\openbook.gif
+file105=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\moreof.gif
+file96=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ippt.gif
+file85=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_tech.gif
+file74=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_lang.gif
+file63=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_about.gif
+file52=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\gcsrceon.gif
+file41=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\gcbildof.gif
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\edtchof.gif
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ccolon.gif
+SubDir2=images\es
+file139=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tauthgr.gif
+file128=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\stop.gif
+file117=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\openfldr.gif
+file106=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\moreon.gif
+file97=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ips.gif
+file86=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_title.gif
+file75=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_list.gif
+file64=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_acro.gif
+file53=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\gcviewof.gif
+file42=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\gcbildon.gif
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\edtchon.gif
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\conton.gif
+SubDir3=images\fr
+file129=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tabspace.gif
+file118=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\pdf.gif
+file107=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mstdsof.gif
+file98=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iqtvideo.gif
+file87=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_to.gif
+file76=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_org.gif
+file65=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_artist.gif
+file54=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\gcviewon.gif
+file43=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\gcconfof.gif
+file32=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\eexpcof.gif
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\cprefof.gif
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\cgsdocof.gif
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images
+SubDir4=images\id
+file190=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ttopicof.gif
+file119=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\phindbg1.jpg
+file108=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mstdson.gif
+file99=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\irmvideo.gif
+file88=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_topic.gif
+file77=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_people.gif
+file66=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_auth.gif
+file55=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ghproj.jpg
+file44=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\gcconfon.gif
+file33=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\eexpcon.gif
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\cprefon.gif
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\cgsdocon.gif
+SubDir5=images\it
+file191=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ttopicon.gif
+file180=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tsubjgr.gif
+file109=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ncbildof.gif
+file89=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ibtext.gif
+file78=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_phrse.gif
+file67=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_brwse.gif
+file56=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ghproj2.jpg
+file45=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\gcdelof.gif
+file34=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ehlof.gif
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\cross.gif
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\chalk.gif
+SubDir6=images\iw
+file192=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\unesco.gif
+file181=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tsubjof.gif
+file170=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tsergr.gif
+file79=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_pref.gif
+file68=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_cat.gif
+file57=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\grarrow.gif
+file46=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\gcdelon.gif
+file35=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\ehlon.gif
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\display.gif
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\chelpof.gif
+SubDir7=images\mi
+file193=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\warning.gif
+file182=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tsubjon.gif
+file171=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tserof.gif
+file160=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\tlangon.gif
+file69=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\h_colect.gif
+file58=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\gsdl.gif
+file47=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\gcexptof.gif
+file36=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\enhlof.gif
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\divb.gif
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\chelpon.gif
+
+[mappings\from_uc]
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\win1258.ump
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\koi8_u.ump
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\win874.ump
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\shiftjis.ump
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\8859_1.ump
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\uhc.ump
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\8859_2.ump
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\win1250.ump
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\8859_3.ump
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\win1251.ump
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\8859_4.ump
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\8859_5.ump
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\8859_6.ump
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\8859_7.ump
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\8859_8.ump
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\8859_9.ump
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\big5.ump
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\win1252.ump
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\win1253.ump
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\dos866.ump
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\win1254.ump
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\euc_jp.ump
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\win1255.ump
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\gbk.ump
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\win1256.ump
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\iscii_de.ump
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\win1257.ump
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\from_uc\koi8_r.ump
+
+[collect\demo\import\fb34fe]
+file37=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p111a.png
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p106c.png
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p101b.png
+file38=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p111b.png
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p106d.png
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p102a.png
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p093a.png
+file39=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\fb34fe.htm
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p107a.png
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p103a.png
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p094a.png
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p107b.png
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p103b.png
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p094b.png
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p104a.png
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p095a.png
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p095b.png
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p095c.png
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p096a.png
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p096b.png
+file40=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\fb34fe.jpg
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p096c.png
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p107c.png
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p097a.png
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p108a.png
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p104b.png
+file32=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p108b.png
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p105a.png
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p097b.png
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe
+file33=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p109a.png
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p105b.png
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p098a.png
+file34=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p109b.png
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p105c.png
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p099a.png
+file35=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p110a.png
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p106a.png
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p099b.png
+file36=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p110b.png
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p106b.png
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\fb34fe\f34p101a.png
+
+[collect\demo\import\ec158e]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec158e\ec158e.htm
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec158e\ec158e.jpg
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec158e\p07a.png
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec158e\p32a.png
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec158e\p95a.png
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec158e
+
+[bin\java]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\bin\java\Phind.jar
+fulldirectory=
+
+[collect\demo\import]
+SubDir8=collect\demo\import\fb33fe
+SubDir9=collect\demo\import\fb34fe
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\metadata.xml
+SubDir10=collect\demo\import\wb34te
+SubDir0=collect\demo\import\b17mie
+SubDir1=collect\demo\import\b18ase
+SubDir2=collect\demo\import\b20cre
+SubDir3=collect\demo\import\b21wae
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import
+SubDir4=collect\demo\import\b22bue
+SubDir5=collect\demo\import\ec158e
+SubDir6=collect\demo\import\ec159e
+SubDir7=collect\demo\import\ec160e
+
+[collect]
+SubDir0=collect\demo
+fulldirectory=
+
+[TopDir]
+SubDir0=collect
+SubDir1=bin
+SubDir2=tmp
+SubDir3=etc
+SubDir4=mappings
+SubDir5=images
+SubDir6=macros
+
+[collect\demo\index\assoc\HASHac0a.dir]
+file37=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p110b.png
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p106b.png
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p101a.png
+file38=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p111a.png
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p106c.png
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p101b.png
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\cover.jpg
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p106d.png
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p102a.png
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p093a.png
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p107a.png
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p103a.png
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p094a.png
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p103b.png
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p094b.png
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p095a.png
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p095b.png
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p095c.png
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p096a.png
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p096b.png
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p107b.png
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p096c.png
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p107c.png
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p104a.png
+file32=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p108a.png
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p104b.png
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p097a.png
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir
+file33=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p108b.png
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p105a.png
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p097b.png
+file34=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p109a.png
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p105b.png
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p098a.png
+file35=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p109b.png
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p105c.png
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p099a.png
+file36=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p110a.png
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p106a.png
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHac0a.dir\f34p099b.png
+
+[collect\demo\index\assoc\HASH1631.dir]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH1631.dir\b20a.png
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH1631.dir\cover.jpg
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH1631.dir
+
+[collect\demo\import\wb34te]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\wb34te\p16.png
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\wb34te\p17.png
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\wb34te\p18.png
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\wb34te\p19.png
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\wb34te\p20.png
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\wb34te\p23.png
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\wb34te\p24.png
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\wb34te\p28.png
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\wb34te\p29a.png
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\wb34te\p29b.png
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\wb34te\wb34te.htm
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\wb34te
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\wb34te\wb34te.jpg
+
+[collect\demo\images]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\images\demo.gif
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\images\demosm.gif
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\images
+
+[collect\demo]
+SubDir0=collect\demo\etc
+SubDir1=collect\demo\images
+SubDir2=collect\demo\import
+SubDir3=collect\demo\index
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo
+
+[collect\demo\index\stt]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\stt\demo.i
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\stt\demo.ib1
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\stt\demo.ib2
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\stt\demo.ib3
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\stt\demo.idb
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\stt\demo.tiw
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\stt\demo.wa
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\stt
+
+[collect\demo\index\assoc\HASHa84b.dir]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHa84b.dir\cover.jpg
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHa84b.dir\p16.png
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHa84b.dir\p17.png
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHa84b.dir\p18.png
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHa84b.dir\p19.png
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHa84b.dir\p20.png
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHa84b.dir\p23.png
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHa84b.dir\p24.png
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHa84b.dir\p28.png
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHa84b.dir\p29a.png
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHa84b.dir\p29b.png
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASHa84b.dir
+
+[collect\demo\index\assoc\HASH92b3.dir]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH92b3.dir\cover.jpg
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH92b3.dir\p08.png
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH92b3.dir\p16.png
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH92b3.dir
+
+[collect\demo\index\assoc\HASH4632.dir]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH4632.dir\cover.jpg
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH4632.dir\p021.png
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH4632.dir\p038.png
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH4632.dir\p043.png
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH4632.dir\p094.png
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\assoc\HASH4632.dir
+
+[collect\demo\import\b22bue]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b22bue\b22bue.htm
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b22bue\b22bue.jpg
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b22bue\p08.png
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b22bue\p16.png
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b22bue
+
+[collect\demo\import\b17mie]
+file59=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p292a.png
+file48=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p203a.png
+file37=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g036a.png
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g025a.png
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g014a.png
+file49=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p210a.png
+file38=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g037a.png
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g026a.png
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g015a.png
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\b17mie.htm
+file39=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g038a.png
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g027a.png
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g016a.png
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\b17mie.jpg
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g028a.png
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g017a.png
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g001a.png
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g018a.png
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g002a.png
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g003a.png
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g004a.png
+file60=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p293a.png
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g005a.png
+file61=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p301a.png
+file50=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p219a.png
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g006a.png
+file62=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p309a.png
+file51=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p227a.png
+file40=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g039a.png
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g007a.png
+file63=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p323a.png
+file52=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p236a.png
+file41=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g040a.png
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g029a.png
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g008a.png
+file64=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p349a.png
+file53=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p243a.png
+file42=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p112a.png
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g030a.png
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g019a.png
+file65=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p357a.png
+file54=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p24a.png
+file43=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p117a.png
+file32=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g031a.png
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g020a.png
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g009a.png
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie
+file66=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p39a.png
+file55=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p252a.png
+file44=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p129a.png
+file33=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g032a.png
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g021a.png
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g010a.png
+file67=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p81a.png
+file56=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p260a.png
+file45=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p138a.png
+file34=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g033a.png
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g022a.png
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g011a.png
+file68=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p96a.png
+file57=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p265a.png
+file46=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p149a.png
+file35=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g034a.png
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g023a.png
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g012a.png
+file69=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p9a.png
+file58=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p274a.png
+file47=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\p159a.png
+file36=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g035a.png
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g024a.png
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\b17mie\g013a.png
+
+[images\it]
+file59=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\thowgr.gif
+file48=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tauthof.gif
+file37=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\h_subj.gif
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\h_date.gif
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\eexpcon.gif
+file49=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tauthon.gif
+file38=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\h_title.gif
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\h_from.gif
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\ehlof.gif
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\chelpof.gif
+file39=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\h_to.gif
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\h_help.gif
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\ehlon.gif
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\chelpon.gif
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\h_how.gif
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\enhlof.gif
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\chomeof.gif
+file90=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\ttopicof.gif
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\enhlon.gif
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\chomeon.gif
+file91=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\ttopicon.gif
+file80=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tsubjgr.gif
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\contof.gif
+file81=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tsubjof.gif
+file70=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tpeopon.gif
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\conton.gif
+file82=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tsubjon.gif
+file71=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tphrsegr.gif
+file60=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\thowof.gif
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\cprefof.gif
+file83=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\ttitlgr.gif
+file72=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tphrseof.gif
+file61=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\thowon.gif
+file50=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tbrwsegr.gif
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\cprefon.gif
+file84=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\ttitlof.gif
+file73=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tphrseon.gif
+file62=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tlanggr.gif
+file51=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tbrwseof.gif
+file40=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\h_topic.gif
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\ealltof.gif
+file85=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\ttitlon.gif
+file74=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tsergr.gif
+file63=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tlangof.gif
+file52=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tbrwseon.gif
+file41=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\qryresb.gif
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\h_lang.gif
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\eallton.gif
+file86=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\ttogr.gif
+file75=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tserof.gif
+file64=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tlangon.gif
+file53=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tdategr.gif
+file42=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\schhistb.gif
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\h_org.gif
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\etsecof.gif
+file87=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\ttoof.gif
+file76=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tseron.gif
+file65=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\torggr.gif
+file54=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tdateof.gif
+file43=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\selcolgr.gif
+file32=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\h_people.gif
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\etsecon.gif
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\econcof.gif
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it
+file88=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\ttoon.gif
+file77=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tsrchgr.gif
+file66=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\torgof.gif
+file55=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tdateon.gif
+file44=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tacrogr.gif
+file33=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\h_phrse.gif
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\h_about.gif
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\econcon.gif
+file89=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\ttopicgr.gif
+file78=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tsrchof.gif
+file67=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\torgon.gif
+file56=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tfromgr.gif
+file45=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tacroof.gif
+file34=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\h_pref.gif
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\h_acro.gif
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\edtchof.gif
+file79=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tsrchon.gif
+file68=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tpeopgr.gif
+file57=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tfromof.gif
+file46=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tacroon.gif
+file35=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\h_search.gif
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\h_auth.gif
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\edtchon.gif
+file69=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tpeopof.gif
+file58=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tfromon.gif
+file47=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\tauthgr.gif
+file36=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\h_ser.gif
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\h_brwse.gif
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\it\eexpcof.gif
+
+[images\id]
+file59=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\thowof.gif
+file48=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tauthon.gif
+file37=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\h_subj.gif
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\h_date.gif
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\eexpcon.gif
+file49=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tbrwsegr.gif
+file38=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\h_title.gif
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\h_from.gif
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\ehlof.gif
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\chelpof.gif
+file39=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\h_to.gif
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\h_help.gif
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\ehlon.gif
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\chelpon.gif
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\h_how.gif
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\enhlof.gif
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\chomeof.gif
+file90=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\ttopicon.gif
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\enhlon.gif
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\chomeon.gif
+file80=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tsubjof.gif
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\contof.gif
+file81=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tsubjon.gif
+file70=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tphrsegr.gif
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\conton.gif
+file82=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\ttitlgr.gif
+file71=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tphrseof.gif
+file60=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\thowon.gif
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\cprefof.gif
+file83=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\ttitlof.gif
+file72=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tphrseon.gif
+file61=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tlanggr.gif
+file50=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tbrwseof.gif
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\cprefon.gif
+file84=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\ttitlon.gif
+file73=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tsergr.gif
+file62=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tlangof.gif
+file51=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tbrwseon.gif
+file40=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\h_topic.gif
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\ealltof.gif
+file85=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\ttogr.gif
+file74=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tserof.gif
+file63=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tlangon.gif
+file52=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tdategr.gif
+file41=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\qryresb.gif
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\h_lang.gif
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\eallton.gif
+file86=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\ttoof.gif
+file75=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tseron.gif
+file64=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\torggr.gif
+file53=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tdateof.gif
+file42=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\schhistb.gif
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\h_org.gif
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\etsecof.gif
+file87=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\ttoon.gif
+file76=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tsrchgr.gif
+file65=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\torgof.gif
+file54=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tdateon.gif
+file43=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tacrogr.gif
+file32=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\h_people.gif
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\etsecon.gif
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\econcof.gif
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id
+file88=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\ttopicgr.gif
+file77=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tsrchof.gif
+file66=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\torgon.gif
+file55=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tfromgr.gif
+file44=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tacroof.gif
+file33=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\h_phrse.gif
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\h_about.gif
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\econcon.gif
+file89=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\ttopicof.gif
+file78=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tsrchon.gif
+file67=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tpeopgr.gif
+file56=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tfromof.gif
+file45=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tacroon.gif
+file34=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\h_pref.gif
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\h_acro.gif
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\edtchof.gif
+file79=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tsubjgr.gif
+file68=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tpeopof.gif
+file57=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tfromon.gif
+file46=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tauthgr.gif
+file35=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\h_search.gif
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\h_auth.gif
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\edtchon.gif
+file69=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tpeopon.gif
+file58=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\thowgr.gif
+file47=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\tauthof.gif
+file36=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\h_ser.gif
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\h_brwse.gif
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\id\eexpcof.gif
+
+[images\fr]
+file59=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tsrchof.gif
+file48=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\thowon.gif
+file37=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tauthgr.gif
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\h_help.gif
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\eexpcon.gif
+file49=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\torggr.gif
+file38=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tauthof.gif
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\h_how.gif
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\ehlof.gif
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\chelpof.gif
+file39=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tauthon.gif
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\h_org.gif
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\ehlon.gif
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\chelpon.gif
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\h_people.gif
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\enhlof.gif
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\chomeof.gif
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\enhlon.gif
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\chomeon.gif
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\contof.gif
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\conton.gif
+file60=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tsrchon.gif
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\cprefof.gif
+file61=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tsubjgr.gif
+file50=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\torgof.gif
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\cprefon.gif
+file62=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tsubjof.gif
+file51=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\torgon.gif
+file40=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tbrwsegr.gif
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\ealltof.gif
+file63=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tsubjon.gif
+file52=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tpeopgr.gif
+file41=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tbrwseof.gif
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\h_pref.gif
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\eallton.gif
+file64=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\ttitlgr.gif
+file53=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tpeopof.gif
+file42=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tbrwseon.gif
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\h_search.gif
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\etsecof.gif
+file65=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\ttitlof.gif
+file54=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tpeopon.gif
+file43=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tdategr.gif
+file32=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\h_ser.gif
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\etsecon.gif
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\econcof.gif
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr
+file66=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\ttitlon.gif
+file55=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tsergr.gif
+file44=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tdateof.gif
+file33=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\h_subj.gif
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\h_about.gif
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\econcon.gif
+file67=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\ttopicgr.gif
+file56=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tserof.gif
+file45=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tdateon.gif
+file34=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\h_title.gif
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\h_auth.gif
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\edtchof.gif
+file68=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\ttopicof.gif
+file57=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tseron.gif
+file46=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\thowgr.gif
+file35=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\h_topic.gif
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\h_brwse.gif
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\edtchon.gif
+file69=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\ttopicon.gif
+file58=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\tsrchgr.gif
+file47=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\thowof.gif
+file36=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\qryresb.gif
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\h_date.gif
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\fr\eexpcof.gif
+
+[General]
+Type=FILELIST
+Version=1.10.000
+
+[images\mi]
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\tsergr.gif
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\etsecon.gif
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\tserof.gif
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\h_about.gif
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\chelpof.gif
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\tseron.gif
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\h_date.gif
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\chelpon.gif
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\tsrchgr.gif
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\h_help.gif
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\chomeof.gif
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\h_pref.gif
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\chomeon.gif
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\cprefof.gif
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\cprefon.gif
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\ealltof.gif
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\eallton.gif
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\edtchof.gif
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\tsrchof.gif
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\edtchon.gif
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\tsrchon.gif
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\h_search.gif
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\h_ser.gif
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\ehlof.gif
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\qryresb.gif
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\ehlon.gif
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\tdategr.gif
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\enhlof.gif
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\tdateof.gif
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\enhlon.gif
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\tdateon.gif
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\mi\etsecof.gif
+
+[collect\demo\index\stx]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\stx\demo.i
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\stx\demo.ib1
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\stx\demo.ib2
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\stx\demo.ib3
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\stx\demo.idb
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\stx\demo.tiw
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\stx\demo.wa
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\stx
+
+[collect\demo\etc]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\etc\collect.cfg
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\etc\org.txt
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\etc\sub.txt
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\etc\title.txt
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\etc\VERSION
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\etc
+
+[images\iw]
+file59=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tlangof.gif
+file48=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tbrwseon.gif
+file37=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\h_topic.gif
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\h_help.gif
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\ehlon.gif
+file49=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tdategr.gif
+file38=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\qryresb.gif
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\h_how.gif
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\enhlof.gif
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\chelpof.gif
+file39=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\schhistb.gif
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\h_lang.gif
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\enhlon.gif
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\chelpon.gif
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\h_org.gif
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\etsecof.gif
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\chomeof.gif
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\etsecon.gif
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\chomeon.gif
+file80=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\ttoof.gif
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\cprefof.gif
+file81=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\ttoon.gif
+file70=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tsrchgr.gif
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\cprefon.gif
+file82=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\ttopicgr.gif
+file71=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tsrchof.gif
+file60=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tlangon.gif
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\ealltof.gif
+file83=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\ttopicof.gif
+file72=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tsrchon.gif
+file61=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\torggr.gif
+file50=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tdateof.gif
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\eallton.gif
+file84=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\ttopicon.gif
+file73=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tsubjgr.gif
+file62=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\torgof.gif
+file51=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tdateon.gif
+file40=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tacrogr.gif
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\econcof.gif
+file74=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tsubjof.gif
+file63=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\torgon.gif
+file52=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tfromgr.gif
+file41=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tacroof.gif
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\h_people.gif
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\econcon.gif
+file75=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tsubjon.gif
+file64=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tpeopgr.gif
+file53=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tfromof.gif
+file42=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tacroon.gif
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\h_pref.gif
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\h_about.gif
+file76=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\ttitlgr.gif
+file65=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tpeopof.gif
+file54=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tfromon.gif
+file43=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tauthgr.gif
+file32=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\h_search.gif
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\h_acro.gif
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\edtchof.gif
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw
+file77=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\ttitlof.gif
+file66=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tpeopon.gif
+file55=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\thowgr.gif
+file44=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tauthof.gif
+file33=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\h_ser.gif
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\h_auth.gif
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\edtchon.gif
+file78=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\ttitlon.gif
+file67=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tsergr.gif
+file56=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\thowof.gif
+file45=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tauthon.gif
+file34=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\h_subj.gif
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\h_brwse.gif
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\eexpcof.gif
+file79=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\ttogr.gif
+file68=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tserof.gif
+file57=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\thowon.gif
+file46=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tbrwsegr.gif
+file35=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\h_title.gif
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\h_date.gif
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\eexpcon.gif
+file69=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tseron.gif
+file58=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tlanggr.gif
+file47=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\tbrwseof.gif
+file36=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\h_to.gif
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\h_from.gif
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\iw\ehlof.gif
+
+[images\es]
+file59=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tsrchof.gif
+file48=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\thowon.gif
+file37=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tauthgr.gif
+file26=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\h_help.gif
+file15=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\eexpcon.gif
+file49=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\torggr.gif
+file38=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tauthof.gif
+file27=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\h_how.gif
+file16=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\ehlof.gif
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\chelpof.gif
+file39=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tauthon.gif
+file28=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\h_org.gif
+file17=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\ehlon.gif
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\chelpon.gif
+file29=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\h_people.gif
+file18=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\enhlof.gif
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\chomeof.gif
+file19=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\enhlon.gif
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\chomeon.gif
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\contof.gif
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\conton.gif
+file60=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tsrchon.gif
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\cprefof.gif
+file61=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tsubjgr.gif
+file50=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\torgof.gif
+file7=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\cprefon.gif
+file62=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tsubjof.gif
+file51=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\torgon.gif
+file40=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tbrwsegr.gif
+file8=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\ealltof.gif
+file63=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tsubjon.gif
+file52=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tpeopgr.gif
+file41=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tbrwseof.gif
+file30=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\h_pref.gif
+file9=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\eallton.gif
+file64=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\ttitlgr.gif
+file53=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tpeopof.gif
+file42=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tbrwseon.gif
+file31=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\h_search.gif
+file20=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\etsecof.gif
+file65=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\ttitlof.gif
+file54=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tpeopon.gif
+file43=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tdategr.gif
+file32=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\h_ser.gif
+file21=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\etsecon.gif
+file10=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\econcof.gif
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es
+file66=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\ttitlon.gif
+file55=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tsergr.gif
+file44=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tdateof.gif
+file33=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\h_subj.gif
+file22=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\h_about.gif
+file11=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\econcon.gif
+file67=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\ttopicgr.gif
+file56=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tserof.gif
+file45=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tdateon.gif
+file34=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\h_title.gif
+file23=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\h_auth.gif
+file12=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\edtchof.gif
+file68=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\ttopicof.gif
+file57=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tseron.gif
+file46=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\thowgr.gif
+file35=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\h_topic.gif
+file24=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\h_brwse.gif
+file13=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\edtchon.gif
+file69=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\ttopicon.gif
+file58=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\tsrchgr.gif
+file47=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\thowof.gif
+file36=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\qryresb.gif
+file25=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\h_date.gif
+file14=C:\sjboddie\gsdl-2.38-cdrom\gsdl\images\es\eexpcof.gif
+
+[mappings]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings\README
+SubDir0=mappings\from_uc
+SubDir1=mappings\to_uc
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\mappings
+
+[etc]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\etc\BVERSION
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\etc\history.db
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\etc\key.db
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\etc\main.cfg
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\etc\usage.txt
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\etc\users.db
+file6=C:\sjboddie\gsdl-2.38-cdrom\gsdl\etc\VERSION
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\etc
+
+[collect\demo\index\text]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\text\demo.ldb
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\text\demo.t
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\text\demo.td
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\text\demo.ti
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\text\demo.tsd
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\text
+
+[collect\demo\index]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index\build.cfg
+SubDir0=collect\demo\index\assoc
+SubDir1=collect\demo\index\dtx
+SubDir2=collect\demo\index\stt
+SubDir3=collect\demo\index\stx
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\index
+SubDir4=collect\demo\index\text
+
+[collect\demo\import\ec160e]
+file0=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec160e\ec160e.htm
+file1=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec160e\ec160e.jpg
+file2=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec160e\p15.png
+file3=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec160e\p32.png
+file4=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec160e\p48.png
+file5=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec160e\p90.png
+fulldirectory=C:\sjboddie\gsdl-2.38-cdrom\gsdl\collect\demo\import\ec160e
+
Index: /tags/start/is_5_gsdl_cdrom/File Groups/chinese.fgl
===================================================================
--- /tags/start/is_5_gsdl_cdrom/File Groups/chinese.fgl	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/File Groups/chinese.fgl	(revision 13666)
@@ -0,0 +1,100 @@
+[chinese\index\assoc\HASH019b.dir]
+file0=C:\sjboddie\cd-collections\chinese\index\assoc\HASH019b.dir\cover.jpg
+fulldirectory=C:\sjboddie\cd-collections\chinese\index\assoc\HASH019b.dir
+
+[chinese\index\assoc\HASH60f9.dir]
+file0=C:\sjboddie\cd-collections\chinese\index\assoc\HASH60f9.dir\cover.jpg
+fulldirectory=C:\sjboddie\cd-collections\chinese\index\assoc\HASH60f9.dir
+
+[chinese\index\assoc\HASH01b7.dir]
+file0=C:\sjboddie\cd-collections\chinese\index\assoc\HASH01b7.dir\cover.jpg
+fulldirectory=C:\sjboddie\cd-collections\chinese\index\assoc\HASH01b7.dir
+
+[chinese\index\assoc]
+SubDir0=chinese\index\assoc\HASH0164.dir
+SubDir1=chinese\index\assoc\HASH019b.dir
+SubDir2=chinese\index\assoc\HASH01ab.dir
+SubDir3=chinese\index\assoc\HASH01b7.dir
+fulldirectory=C:\sjboddie\cd-collections\chinese\index\assoc
+SubDir4=chinese\index\assoc\HASH01f5.dir
+SubDir5=chinese\index\assoc\HASH60f9.dir
+SubDir6=chinese\index\assoc\HASHba33.dir
+SubDir7=chinese\index\assoc\HASHf360.dir
+
+[chinese\etc]
+file0=C:\sjboddie\cd-collections\chinese\etc\collect.cfg
+fulldirectory=C:\sjboddie\cd-collections\chinese\etc
+
+[chinese\index\assoc\HASHba33.dir]
+file0=C:\sjboddie\cd-collections\chinese\index\assoc\HASHba33.dir\cover.jpg
+fulldirectory=C:\sjboddie\cd-collections\chinese\index\assoc\HASHba33.dir
+
+[chinese\index\assoc\HASH0164.dir]
+file0=C:\sjboddie\cd-collections\chinese\index\assoc\HASH0164.dir\cover.jpg
+fulldirectory=C:\sjboddie\cd-collections\chinese\index\assoc\HASH0164.dir
+
+[chinese\index\dtt]
+file0=C:\sjboddie\cd-collections\chinese\index\dtt\chinese.i
+file1=C:\sjboddie\cd-collections\chinese\index\dtt\chinese.ib1
+file2=C:\sjboddie\cd-collections\chinese\index\dtt\chinese.ib2
+file3=C:\sjboddie\cd-collections\chinese\index\dtt\chinese.ib3
+file4=C:\sjboddie\cd-collections\chinese\index\dtt\chinese.idb
+file5=C:\sjboddie\cd-collections\chinese\index\dtt\chinese.tiw
+file6=C:\sjboddie\cd-collections\chinese\index\dtt\chinese.wa
+fulldirectory=C:\sjboddie\cd-collections\chinese\index\dtt
+
+[TopDir]
+SubDir0=chinese
+
+[chinese\index\text]
+file0=C:\sjboddie\cd-collections\chinese\index\text\chinese.ldb
+file1=C:\sjboddie\cd-collections\chinese\index\text\chinese.t
+file2=C:\sjboddie\cd-collections\chinese\index\text\chinese.td
+file3=C:\sjboddie\cd-collections\chinese\index\text\chinese.ti
+file4=C:\sjboddie\cd-collections\chinese\index\text\chinese.tsd
+fulldirectory=C:\sjboddie\cd-collections\chinese\index\text
+
+[chinese\index\stx]
+file0=C:\sjboddie\cd-collections\chinese\index\stx\chinese.i
+file1=C:\sjboddie\cd-collections\chinese\index\stx\chinese.ib1
+file2=C:\sjboddie\cd-collections\chinese\index\stx\chinese.ib2
+file3=C:\sjboddie\cd-collections\chinese\index\stx\chinese.ib3
+file4=C:\sjboddie\cd-collections\chinese\index\stx\chinese.idb
+file5=C:\sjboddie\cd-collections\chinese\index\stx\chinese.tiw
+file6=C:\sjboddie\cd-collections\chinese\index\stx\chinese.wa
+fulldirectory=C:\sjboddie\cd-collections\chinese\index\stx
+
+[chinese\index\assoc\HASHf360.dir]
+file0=C:\sjboddie\cd-collections\chinese\index\assoc\HASHf360.dir\cover.jpg
+fulldirectory=C:\sjboddie\cd-collections\chinese\index\assoc\HASHf360.dir
+
+[chinese\index\assoc\HASH01ab.dir]
+file0=C:\sjboddie\cd-collections\chinese\index\assoc\HASH01ab.dir\cover.jpg
+fulldirectory=C:\sjboddie\cd-collections\chinese\index\assoc\HASH01ab.dir
+
+[chinese\index\assoc\HASH01f5.dir]
+file0=C:\sjboddie\cd-collections\chinese\index\assoc\HASH01f5.dir\cover.jpg
+fulldirectory=C:\sjboddie\cd-collections\chinese\index\assoc\HASH01f5.dir
+
+[chinese\index]
+file0=C:\sjboddie\cd-collections\chinese\index\build.cfg
+SubDir0=chinese\index\assoc
+SubDir1=chinese\index\dtt
+SubDir2=chinese\index\stx
+SubDir3=chinese\index\text
+fulldirectory=C:\sjboddie\cd-collections\chinese\index
+
+[chinese\images]
+file0=C:\sjboddie\cd-collections\chinese\images\chinsm.jpg
+fulldirectory=C:\sjboddie\cd-collections\chinese\images
+
+[chinese]
+SubDir0=chinese\etc
+SubDir1=chinese\images
+SubDir2=chinese\index
+fulldirectory=C:\sjboddie\cd-collections\chinese
+
+[General]
+Type=FILELIST
+Version=1.10.000
+
Index: /tags/start/is_5_gsdl_cdrom/File Groups/gsarch.fgl
===================================================================
--- /tags/start/is_5_gsdl_cdrom/File Groups/gsarch.fgl	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/File Groups/gsarch.fgl	(revision 13666)
@@ -0,0 +1,82 @@
+[gsarch\index]
+file0=C:\sjboddie\cd-collections\gsarch\index\build.cfg
+SubDir0=gsarch\index\assoc
+SubDir1=gsarch\index\dfr
+SubDir2=gsarch\index\dhd
+SubDir3=gsarch\index\dsb
+fulldirectory=C:\sjboddie\cd-collections\gsarch\index
+SubDir4=gsarch\index\dtx
+SubDir5=gsarch\index\text
+
+[gsarch\etc]
+file0=C:\sjboddie\cd-collections\gsarch\etc\collect.cfg
+fulldirectory=C:\sjboddie\cd-collections\gsarch\etc
+
+[gsarch]
+SubDir0=gsarch\etc
+SubDir1=gsarch\images
+SubDir2=gsarch\index
+fulldirectory=C:\sjboddie\cd-collections\gsarch
+
+[gsarch\index\text]
+file0=C:\sjboddie\cd-collections\gsarch\index\text\gsarch.ldb
+file1=C:\sjboddie\cd-collections\gsarch\index\text\gsarch.t
+file2=C:\sjboddie\cd-collections\gsarch\index\text\gsarch.td
+file3=C:\sjboddie\cd-collections\gsarch\index\text\gsarch.ti
+file4=C:\sjboddie\cd-collections\gsarch\index\text\gsarch.tsd
+fulldirectory=C:\sjboddie\cd-collections\gsarch\index\text
+
+[gsarch\index\dtx]
+file0=C:\sjboddie\cd-collections\gsarch\index\dtx\gsarch.i
+file1=C:\sjboddie\cd-collections\gsarch\index\dtx\gsarch.ib1
+file2=C:\sjboddie\cd-collections\gsarch\index\dtx\gsarch.ib2
+file3=C:\sjboddie\cd-collections\gsarch\index\dtx\gsarch.ib3
+file4=C:\sjboddie\cd-collections\gsarch\index\dtx\gsarch.idb
+file5=C:\sjboddie\cd-collections\gsarch\index\dtx\gsarch.tiw
+file6=C:\sjboddie\cd-collections\gsarch\index\dtx\gsarch.wa
+fulldirectory=C:\sjboddie\cd-collections\gsarch\index\dtx
+
+[gsarch\images]
+file0=C:\sjboddie\cd-collections\gsarch\images\gsarch.gif
+fulldirectory=C:\sjboddie\cd-collections\gsarch\images
+
+[gsarch\index\assoc]
+fulldirectory=C:\sjboddie\cd-collections\gsarch\index\assoc
+
+[TopDir]
+SubDir0=gsarch
+
+[gsarch\index\dfr]
+file0=C:\sjboddie\cd-collections\gsarch\index\dfr\gsarch.i
+file1=C:\sjboddie\cd-collections\gsarch\index\dfr\gsarch.ib1
+file2=C:\sjboddie\cd-collections\gsarch\index\dfr\gsarch.ib2
+file3=C:\sjboddie\cd-collections\gsarch\index\dfr\gsarch.ib3
+file4=C:\sjboddie\cd-collections\gsarch\index\dfr\gsarch.idb
+file5=C:\sjboddie\cd-collections\gsarch\index\dfr\gsarch.tiw
+file6=C:\sjboddie\cd-collections\gsarch\index\dfr\gsarch.wa
+fulldirectory=C:\sjboddie\cd-collections\gsarch\index\dfr
+
+[gsarch\index\dhd]
+file0=C:\sjboddie\cd-collections\gsarch\index\dhd\gsarch.i
+file1=C:\sjboddie\cd-collections\gsarch\index\dhd\gsarch.ib1
+file2=C:\sjboddie\cd-collections\gsarch\index\dhd\gsarch.ib2
+file3=C:\sjboddie\cd-collections\gsarch\index\dhd\gsarch.ib3
+file4=C:\sjboddie\cd-collections\gsarch\index\dhd\gsarch.idb
+file5=C:\sjboddie\cd-collections\gsarch\index\dhd\gsarch.tiw
+file6=C:\sjboddie\cd-collections\gsarch\index\dhd\gsarch.wa
+fulldirectory=C:\sjboddie\cd-collections\gsarch\index\dhd
+
+[General]
+Type=FILELIST
+Version=1.10.000
+
+[gsarch\index\dsb]
+file0=C:\sjboddie\cd-collections\gsarch\index\dsb\gsarch.i
+file1=C:\sjboddie\cd-collections\gsarch\index\dsb\gsarch.ib1
+file2=C:\sjboddie\cd-collections\gsarch\index\dsb\gsarch.ib2
+file3=C:\sjboddie\cd-collections\gsarch\index\dsb\gsarch.ib3
+file4=C:\sjboddie\cd-collections\gsarch\index\dsb\gsarch.idb
+file5=C:\sjboddie\cd-collections\gsarch\index\dsb\gsarch.tiw
+file6=C:\sjboddie\cd-collections\gsarch\index\dsb\gsarch.wa
+fulldirectory=C:\sjboddie\cd-collections\gsarch\index\dsb
+
Index: /tags/start/is_5_gsdl_cdrom/File Groups/hdlsub.fgl
===================================================================
--- /tags/start/is_5_gsdl_cdrom/File Groups/hdlsub.fgl	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/File Groups/hdlsub.fgl	(revision 13666)
@@ -0,0 +1,23 @@
+[hdlsub]
+SubDir0=hdlsub\etc
+SubDir1=hdlsub\images
+fulldirectory=
+
+[hdlsub\images]
+file0=C:\sjboddie\cd-collections\hdlsub\images\hdlsub.gif
+fulldirectory=C:\sjboddie\cd-collections\hdlsub\images
+
+[TopDir]
+SubDir0=hdlsub
+
+[General]
+Type=FILELIST
+Version=1.10.000
+
+[hdlsub\etc]
+file0=C:\sjboddie\cd-collections\hdlsub\etc\collect.cfg
+file1=C:\sjboddie\cd-collections\hdlsub\etc\mags.txt
+file2=C:\sjboddie\cd-collections\hdlsub\etc\org.txt
+file3=C:\sjboddie\cd-collections\hdlsub\etc\sub.txt
+fulldirectory=C:\sjboddie\cd-collections\hdlsub\etc
+
Index: /tags/start/is_5_gsdl_cdrom/File Groups/setpw.fgl
===================================================================
--- /tags/start/is_5_gsdl_cdrom/File Groups/setpw.fgl	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/File Groups/setpw.fgl	(revision 13666)
@@ -0,0 +1,7 @@
+[TopDir]
+file0=C:\sjboddie\gsdl-2.38-cdrom\Windows\bin\windows\setpw.exe
+
+[General]
+Type=FILELIST
+Version=1.10.000
+
Index: /tags/start/is_5_gsdl_cdrom/File Groups/wordpdf.fgl
===================================================================
--- /tags/start/is_5_gsdl_cdrom/File Groups/wordpdf.fgl	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/File Groups/wordpdf.fgl	(revision 13666)
@@ -0,0 +1,137 @@
+[wordpdf\index\assoc\HASHbd64.dir]
+file0=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASHbd64.dir\doc.doc
+fulldirectory=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASHbd64.dir
+
+[wordpdf\index\assoc\HASH2886.dir]
+file0=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH2886.dir\doc.doc
+fulldirectory=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH2886.dir
+
+[wordpdf\index\assoc\HASH011b.dir]
+file0=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH011b.dir\doc.ps
+fulldirectory=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH011b.dir
+
+[wordpdf\index]
+file0=C:\sjboddie\cd-collections\wordpdf\index\build.cfg
+SubDir0=wordpdf\index\assoc
+SubDir1=wordpdf\index\dtx
+SubDir2=wordpdf\index\text
+fulldirectory=C:\sjboddie\cd-collections\wordpdf\index
+
+[wordpdf\index\assoc\HASH0199.dir]
+file0=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH0199.dir\doc.pdf
+fulldirectory=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH0199.dir
+
+[wordpdf\index\assoc\HASH126c.dir]
+file0=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH126c.dir\doc.ps
+fulldirectory=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH126c.dir
+
+[wordpdf\index\assoc\HASH0147.dir]
+file0=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH0147.dir\doc.doc
+fulldirectory=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH0147.dir
+
+[wordpdf\index\assoc]
+SubDir8=wordpdf\index\assoc\HASH2886.dir
+SubDir9=wordpdf\index\assoc\HASH4b40.dir
+SubDir10=wordpdf\index\assoc\HASH6768.dir
+SubDir11=wordpdf\index\assoc\HASHbd64.dir
+SubDir12=wordpdf\index\assoc\HASHf72d.dir
+SubDir0=wordpdf\index\assoc\0
+SubDir1=wordpdf\index\assoc\HASH011b.dir
+SubDir2=wordpdf\index\assoc\HASH0147.dir
+SubDir3=wordpdf\index\assoc\HASH0150.dir
+fulldirectory=C:\sjboddie\cd-collections\wordpdf\index\assoc
+SubDir4=wordpdf\index\assoc\HASH017e.dir
+SubDir5=wordpdf\index\assoc\HASH0199.dir
+SubDir6=wordpdf\index\assoc\HASH01b7.dir
+SubDir7=wordpdf\index\assoc\HASH126c.dir
+
+[wordpdf\index\assoc\HASH4b40.dir]
+file0=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH4b40.dir\doc.pdf
+fulldirectory=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH4b40.dir
+
+[wordpdf\images]
+file0=C:\sjboddie\cd-collections\wordpdf\images\wordpdf.gif
+fulldirectory=C:\sjboddie\cd-collections\wordpdf\images
+
+[TopDir]
+SubDir0=wordpdf
+
+[wordpdf\index\assoc\HASH01b7.dir]
+file0=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH01b7.dir\doc.pdf
+fulldirectory=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH01b7.dir
+
+[wordpdf\index\assoc\HASHf72d.dir]
+file0=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASHf72d.dir\doc.doc
+fulldirectory=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASHf72d.dir
+
+[wordpdf\index\assoc\HASH6768.dir]
+file0=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH6768.dir\doc.pdf
+fulldirectory=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH6768.dir
+
+[wordpdf\etc]
+file0=C:\sjboddie\cd-collections\wordpdf\etc\collect.cfg
+fulldirectory=C:\sjboddie\cd-collections\wordpdf\etc
+
+[wordpdf\index\assoc\0]
+file15=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\3.png
+file16=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\4.jpg
+file0=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\0.jpg
+file17=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\4.png
+file1=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\0.png
+file18=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\5.jpg
+file2=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\1.jpg
+file19=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\5.png
+file3=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\1.png
+file4=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\10.png
+file5=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\11.png
+file6=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\12.png
+file7=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\13.png
+file8=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\14.png
+file9=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\15.png
+file20=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\6.png
+file21=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\7.png
+file10=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\16.png
+fulldirectory=C:\sjboddie\cd-collections\wordpdf\index\assoc\0
+file22=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\8.png
+file11=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\17.png
+file23=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\9.png
+file12=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\2.jpg
+file13=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\2.png
+file14=C:\sjboddie\cd-collections\wordpdf\index\assoc\0\3.jpg
+
+[wordpdf\index\text]
+file0=C:\sjboddie\cd-collections\wordpdf\index\text\wordpdf.ldb
+file1=C:\sjboddie\cd-collections\wordpdf\index\text\wordpdf.t
+file2=C:\sjboddie\cd-collections\wordpdf\index\text\wordpdf.td
+file3=C:\sjboddie\cd-collections\wordpdf\index\text\wordpdf.ti
+file4=C:\sjboddie\cd-collections\wordpdf\index\text\wordpdf.tsd
+fulldirectory=C:\sjboddie\cd-collections\wordpdf\index\text
+
+[wordpdf\index\assoc\HASH017e.dir]
+file0=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH017e.dir\doc.rtf
+fulldirectory=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH017e.dir
+
+[wordpdf\index\assoc\HASH0150.dir]
+file0=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH0150.dir\doc.ps
+fulldirectory=C:\sjboddie\cd-collections\wordpdf\index\assoc\HASH0150.dir
+
+[General]
+Type=FILELIST
+Version=1.10.000
+
+[wordpdf\index\dtx]
+file0=C:\sjboddie\cd-collections\wordpdf\index\dtx\wordpdf.i
+file1=C:\sjboddie\cd-collections\wordpdf\index\dtx\wordpdf.ib1
+file2=C:\sjboddie\cd-collections\wordpdf\index\dtx\wordpdf.ib2
+file3=C:\sjboddie\cd-collections\wordpdf\index\dtx\wordpdf.ib3
+file4=C:\sjboddie\cd-collections\wordpdf\index\dtx\wordpdf.idb
+file5=C:\sjboddie\cd-collections\wordpdf\index\dtx\wordpdf.tiw
+file6=C:\sjboddie\cd-collections\wordpdf\index\dtx\wordpdf.wa
+fulldirectory=C:\sjboddie\cd-collections\wordpdf\index\dtx
+
+[wordpdf]
+SubDir0=wordpdf\etc
+SubDir1=wordpdf\images
+SubDir2=wordpdf\index
+fulldirectory=C:\sjboddie\cd-collections\wordpdf
+
Index: /tags/start/is_5_gsdl_cdrom/Greenstone Digital Library Software.ipr
===================================================================
--- /tags/start/is_5_gsdl_cdrom/Greenstone Digital Library Software.ipr	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/Greenstone Digital Library Software.ipr	(revision 13666)
@@ -0,0 +1,60 @@
+[Language]
+LanguageSupport0=0009
+LanguageSupport1=040c
+LanguageSupport2=000a
+
+[OperatingSystem]
+OSSupport=0000000000011051
+
+[Data]
+CurrentMedia=cdrom
+set_mifserial=
+ProductName=Greenstone Digital Library Software
+CurrentComponentDef=Default.cdf
+set_dlldebug=No
+AppExe=
+DevEnvironment=Microsoft Visual C++
+FreshBits=FALSE
+set_mif=No
+set_testmode=No
+Instructions=Instructions.txt
+EmailAddresss=
+SummaryText=
+Department=
+Type=Internet Application
+Author=
+HomeURL=
+InstallRoot=C:\sjboddie\is_gsdl_cdrom
+UpdateURL=http://
+set_level=Level 3
+InstallationGUID=4c986880-d387-11d5-840f-a0c20cc10000
+Version=2.37.000
+set_miffile=Status.mif
+set_args=
+set_maxerr=50
+Notes=Notes.txt
+CurrentFileGroupDef=Default.fdf
+set_dllcmdline=
+set_warnaserr=No
+Copyright=
+set_preproc=
+Category=Internet Tool
+CurrentPlatform=
+set_compileb4build=No
+set_crc=Yes
+set_maxwarn=50
+Description=Description.txt
+CompanyName=New Zealand Digital Library Project
+CurrentLanguage=English
+
+[MediaInfo]
+mediadata0=cdrom/Media\cdrom
+mediadata1=web/Media\web
+
+[General]
+PassData=
+ReadOnly=N
+Type=INSTALLMAIN
+Version=1.20.000
+PassOn=N
+
Index: /tags/start/is_5_gsdl_cdrom/Registry Entries/Default.rge
===================================================================
--- /tags/start/is_5_gsdl_cdrom/Registry Entries/Default.rge	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/Registry Entries/Default.rge	(revision 13666)
@@ -0,0 +1,4 @@
+[General]
+Type=REGISTRYDATA
+Version=1.00.000
+
Index: /tags/start/is_5_gsdl_cdrom/Script Files/setup.rul
===================================================================
--- /tags/start/is_5_gsdl_cdrom/Script Files/setup.rul	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/Script Files/setup.rul	(revision 13666)
@@ -0,0 +1,671 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  IIIIIII SSSSSS
+//    II    SS                          InstallShield (R)
+//    II    SSSSSS      (c) 1996-1997, InstallShield Software Corporation
+//    II        SS      (c) 1990-1996, InstallShield Corporation
+//  IIIIIII SSSSSS                     All Rights Reserved.
+//
+//
+//  This code is generated as a starting setup template.  You should
+//  modify it to provide all necessary steps for your setup.
+//
+//
+//    File Name:  Setup.rul
+//
+//  Description:  InstallShield script
+//
+//     Comments:  This template script performs a basic setup. With minor
+//                modifications, this template can be adapted to create
+//                new, customized setups.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+
+// Include header files
+
+    #include "sdlang.h"
+    #include "sddialog.h"
+
+////////////////////// string defines ////////////////////////////
+
+    #define UNINST_LOGFILE_NAME      "Uninst.isu"
+
+//////////////////// installation declarations ///////////////////
+
+// ----- DLL function prototypes -----
+
+
+    // your DLL function prototypes
+
+
+// ---- script function prototypes -----
+
+    // generated by the Project Wizard
+    prototype ShowDialogs();
+    prototype MoveFileData();
+    prototype HandleMoveDataError( NUMBER );
+    prototype ProcessBeforeDataMove();
+    prototype ProcessAfterDataMove();
+    prototype SetupRegistry();
+    prototype SetupFolders();
+    prototype CleanUpInstall();
+    prototype SetupInstall();
+    prototype SetupScreen();
+    prototype CheckRequirements();
+    prototype DialogShowSdLicense();
+    prototype DialogShowSdFinishReboot();
+
+    // your script function prototypes
+	prototype DialogSelectCollections();
+	prototype DialogGetAdminPassword();
+	prototype SetAdminPassword();
+	prototype CheckWin32s();
+	
+    // ----- global variables ------
+
+    // generated by the Project Wizard
+    BOOL        bIsShellExplorer, bInstallAborted, bIs32BitSetup;
+    STRING      svDir;
+    STRING      svName, svCompany, svSerial;
+    STRING      svDefGroup;
+    STRING      szAppPath;
+    STRING      svSetupType;
+
+
+    // your global variables
+	STRING svAdminPassword, svLogFile;
+	BOOL bWinNT;
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+//   MAIN PROGRAM
+//
+//      The setup begins here by hiding the visible setup
+//      window.  This is done to allow all the titles, images, etc. to
+//      be established before showing the main window.  The setup is
+//      then performed in a series of calls to script defined functions,
+//      with error checking at each step.
+//
+///////////////////////////////////////////////////////////////////////////////
+program
+    Disable( BACKGROUND );
+
+    CheckRequirements();
+
+    SetupInstall();
+
+    SetupScreen();
+
+   	CheckWin32s();
+
+    if (ShowDialogs()<0) goto end_install;
+
+    if (ProcessBeforeDataMove()<0) goto end_install;
+
+    if (MoveFileData()<0) goto end_install;
+
+    if (ProcessAfterDataMove()<0) goto end_install;
+
+    if (SetupRegistry()<0) goto end_install;
+
+    if (SetupFolders()<0) goto end_install;
+
+
+    end_install:
+
+    CleanUpInstall();
+
+    // If an unrecoverable error occurred, clean up
+    // the partial installation. Otherwise, exit normally.
+
+    if (bInstallAborted) then
+        abort;
+    endif;
+
+endprogram
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function:  ShowDialogs
+//
+//  Purpose:  This function manages the display and navigation of
+//            the standard dialogs that exist in a setup.
+//
+///////////////////////////////////////////////////////////////////////////////
+function ShowDialogs()
+    NUMBER  nResult;
+
+begin
+
+    Dlg_Start:
+    // beginning of dialogs label
+
+    Dlg_SdLicense:
+    nResult = DialogShowSdLicense();
+    if (nResult = BACK) goto Dlg_Start;
+
+   	Dlg_SelectCollections:
+   	nResult = DialogSelectCollections();
+	
+   	if (nResult = BACK) goto Dlg_SdLicense;
+		
+   	Dlg_GetAdminPassWord:
+   	nResult = DialogGetAdminPassword();
+   	if (nResult = BACK) goto Dlg_SelectCollections;
+   		
+    return 0;
+
+end;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function: ProcessBeforeDataMove
+//
+//  Purpose: This function performs any necessary operations prior to the
+//           actual file transfer.
+//
+///////////////////////////////////////////////////////////////////////////////
+function ProcessBeforeDataMove()
+    NUMBER nResult;
+
+begin
+
+  // Create app information, uninstallation, and App Paths registry keys.
+
+    InstallationInfo( @COMPANY_NAME, @PRODUCT_NAME, @PRODUCT_VERSION, @PRODUCT_KEY );
+
+    svLogFile = UNINST_LOGFILE_NAME;
+
+    nResult = DeinstallStart( svDir, svLogFile, @UNINST_KEY, 0 );
+    if (nResult < 0) then
+        MessageBox( @ERROR_UNINSTSETUP, WARNING );
+    endif;
+
+    szAppPath = TARGETDIR;
+
+    if ((bIs32BitSetup) && (bIsShellExplorer)) then
+        RegDBSetItem( REGDB_APPPATH, szAppPath );
+        RegDBSetItem( REGDB_APPPATH_DEFAULT, szAppPath ^ @PRODUCT_KEY );
+        RegDBSetItem( REGDB_UNINSTALL_NAME, @UNINST_DISPLAY_NAME );
+    endif;
+
+    // TO DO : any other tasks you want to perform before file transfer
+
+    return 0;
+end;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+//  Function:  MoveFileData
+//
+//  Purpose:  This function handles the file transfer for
+//            the setup.
+//
+///////////////////////////////////////////////////////////////////////////////
+function MoveFileData()
+    NUMBER nResult, nDisk;
+
+begin
+
+    nDisk = 1;
+    SetStatusWindow( 0, "" );
+    Disable( DIALOGCACHE );
+    Enable( STATUS );
+    StatusUpdate( ON, 100 );
+    nResult = ComponentMoveData( MEDIA, nDisk, 0 );
+
+    HandleMoveDataError( nResult );
+
+    Disable( STATUS );
+
+    return nResult;
+
+end;
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function: HandleMoveDataError
+//
+//  Purpose: This function handles the error (if any) during the file transfer
+//           operation.
+//
+///////////////////////////////////////////////////////////////////////////////
+function HandleMoveDataError( nResult )
+    STRING szErrMsg, svComponent , svFileGroup , svFile;
+
+begin
+
+    svComponent = "";
+    svFileGroup = "";
+    svFile = "";
+
+    switch (nResult)
+        case 0:
+            return 0;
+        default:
+            ComponentError ( MEDIA , svComponent , svFileGroup , svFile , nResult );
+            szErrMsg = @ERROR_MOVEDATA  + "\n\n" +
+                @ERROR_COMPONENT + " " + svComponent + "\n" +
+                @ERROR_FILEGROUP + " " + svFileGroup + "\n" +
+                @ERROR_FILE      + " " + svFile;
+            SprintfBox( SEVERE, @TITLE_CAPTIONBAR, szErrMsg, nResult );
+            bInstallAborted = TRUE;
+            return nResult;
+    endswitch;
+
+end;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function: ProcessAfterDataMove
+//
+//  Purpose: This function performs any necessary operations needed after
+//           all files have been transferred.
+//
+///////////////////////////////////////////////////////////////////////////////
+function ProcessAfterDataMove()
+    STRING szReferenceFile;
+
+begin
+
+	SetAdminPassword();
+
+    szReferenceFile = svDir ^ @PRODUCT_KEY;
+    DeinstallSetReference( szReferenceFile );
+
+    return 0;
+end;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function: SetupRegistry
+//
+//  Purpose: This function makes the registry entries for this setup.
+//
+///////////////////////////////////////////////////////////////////////////////
+function SetupRegistry()
+    NUMBER nResult;
+
+begin
+
+    // TO DO : Add all your registry entry keys here.
+    // Call registry functions and/or create keys from
+    // the InstallShield IDE's Resources pane.
+
+    nResult = CreateRegistrySet( "" );
+
+    return nResult;
+ end;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function: SetupFolders
+//
+//  Purpose: This function creates all the folders and shortcuts for the
+//           setup.  This includes program groups and items for Windows 3.1.
+//
+///////////////////////////////////////////////////////////////////////////////
+function SetupFolders()
+    NUMBER nResult;
+	STRING szIsData;
+   	NUMBER nType;
+
+begin
+
+	if (Is(USER_ADMINISTRATOR,szIsData)==TRUE) then
+      nType = COMMON;
+   	else
+      nType = PERSONAL;
+
+   	endif;
+
+   	ProgDefGroupType(nType);
+
+	if (CreateProgramFolder(@FOLDER_NAME) < 0) then
+		MessageBox("CreateProgramFolder failed.", SEVERE);
+	endif;
+
+   	// The following adds the shortcuts.
+   	if (AddFolderIcon(@FOLDER_NAME, @README, "\"" + TARGETDIR ^ "README.TXT\"", "",
+                     "", 0, "", REPLACE) < 0) then
+      MessageBox("AddFolderIcon failed.", SEVERE);
+   	endif;
+
+   	if (AddFolderIcon(@FOLDER_NAME, @TEXT_UNINSTALL, UNINST + " -f\"" + svLogFile + "\"",
+   		 "", "", 0, "", REPLACE) < 0) then
+      MessageBox("AddFolderIcon failed.", SEVERE);
+   	endif;
+
+   	if (AddFolderIcon(@FOLDER_NAME, @FOLDER_NAME, "\"" + TARGETDIR ^ "server.exe\"", "",
+    	                 "", 0, "", REPLACE) < 0) then
+      		MessageBox("AddFolderIcon failed.", SEVERE);
+  	endif;
+
+    nResult = CreateShellObjects( "" );
+
+    return nResult;
+ end;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function: CleanUpInstall
+//
+//  Purpose: This cleans up the setup.  Anything that should
+//           be released or deleted at the end of the setup should
+//           be done here.
+//
+///////////////////////////////////////////////////////////////////////////////
+function CleanUpInstall()
+
+begin
+
+
+    if (bInstallAborted) then
+        return 0;
+    endif;
+
+    DialogShowSdFinishReboot();
+
+    if (BATCH_INSTALL) then // ensure locked files are properly transferred
+        CommitSharedFiles(0);
+    endif;
+
+    return 0;
+end;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function: SetupInstall
+//
+//  Purpose: This will initialize the setup.  Any general initialization
+//           needed for the installation should be performed here.
+//
+///////////////////////////////////////////////////////////////////////////////
+function SetupInstall()
+
+begin
+
+    Enable( CORECOMPONENTHANDLING );
+
+    bInstallAborted = FALSE;
+
+    svDir = PROGRAMFILES ^ "gsdl";
+    TARGETDIR  = svDir;
+
+    SdProductName( @PRODUCT_NAME );
+
+    Enable( DIALOGCACHE );
+
+    return 0;
+end;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function:  SetupScreen
+//
+//  Purpose:  This function establishes the screen look.  This includes
+//            colors, fonts, and text to be displayed.
+//
+///////////////////////////////////////////////////////////////////////////////
+function SetupScreen()
+
+begin
+
+    Enable( FULLWINDOWMODE );
+    Enable( INDVFILESTATUS );
+    SetTitle( @TITLE_MAIN, 24, WHITE );
+
+    SetTitle( @TITLE_CAPTIONBAR, 0, BACKGROUNDCAPTION ); // Caption bar text.
+
+    Enable( BACKGROUND );
+
+    Delay( 1 );
+end;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function:  CheckRequirements
+//
+//  Purpose:  This function checks all minimum requirements for the
+//            application being installed.  If any fail, then the user
+//            is informed and the setup is terminated.
+//
+///////////////////////////////////////////////////////////////////////////////
+function CheckRequirements()
+    NUMBER  nvDx, nvDy, nvResult;
+    STRING  svResult, szIsData;
+
+begin
+
+    bWinNT           = FALSE;
+    bIsShellExplorer = FALSE;
+
+    // Check screen resolution.
+    GetExtents( nvDx, nvDy );
+
+    if (nvDy < 480) then
+        MessageBox( @ERROR_VGARESOLUTION, WARNING );
+        abort;
+    endif;
+
+    // set 'setup' operation mode
+    bIs32BitSetup = TRUE;
+    GetSystemInfo( ISTYPE, nvResult, svResult );
+    if (nvResult = 16) then
+        bIs32BitSetup = FALSE; // running 16-bit setup
+        return 0; // no additional information required
+    endif;
+
+    // --- 32-bit testing after this point ---
+
+    // Determine the target system's operating system.
+    GetSystemInfo( OS, nvResult, svResult );
+
+    if (nvResult =  IS_WINDOWSNT) then
+        // Running Windows NT.
+        bWinNT = TRUE;
+
+        // Check to see if the shell being used is EXPLORER shell.
+        if (GetSystemInfo( OSMAJOR, nvResult, svResult ) = 0) then
+            if (nvResult >= 4) then
+                bIsShellExplorer = TRUE;
+            endif;
+        endif;
+
+    elseif (nvResult = IS_WINDOWS95) then
+        bIsShellExplorer = TRUE;
+
+    endif;
+
+end;
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Function: DialogShowSdLicense
+//
+//  Purpose: This function displays the license agreement dialog.
+//
+//
+///////////////////////////////////////////////////////////////////////////////
+function DialogShowSdLicense()
+    NUMBER nResult;
+    STRING szTitle, szMsg, szQuestion, szLicenseFile;
+
+begin
+
+    szLicenseFile = SUPPORTDIR ^ "license.txt";
+    szTitle    = "";
+    szMsg      = "";
+    szQuestion = "";
+    nResult    = SdLicense( szTitle, szMsg, szQuestion, szLicenseFile );
+
+    return nResult;
+end;
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+//  Function: DialogShowSdFinishReboot
+//
+//  Purpose: This function will show the last dialog of the product.
+//           It will allow the user to reboot and/or show some readme text.
+//
+///////////////////////////////////////////////////////////////////////////////
+function DialogShowSdFinishReboot()
+    NUMBER nResult, nDefOptions;
+    STRING szTitle, szMsg1, szMsg2, szOption1, szOption2;
+    NUMBER bOpt1, bOpt2;
+
+begin
+
+	szTitle = "";
+	szMsg1 = @TEXT_FINISH1;
+	szMsg2 = "";
+    bOpt1 = TRUE;
+    bOpt2 = FALSE;
+    szOption1 = @TEXT_README;
+    szOption2 = "";
+    nResult = SdFinish(szTitle, szMsg1, szMsg2, szOption1, szOption2, bOpt1, bOpt2);
+
+    if (bOpt1 = TRUE) then
+    	LaunchAppAndWait("notepad", TARGETDIR ^ "README.TXT", WAIT);
+    endif;
+
+    return 0;
+
+end;
+
+ function DialogSelectCollections()
+       NUMBER nResult;
+       STRING szTitle, szMsg;
+
+ begin
+
+       szTitle = @TEXT_SELECT_COLLECTIONS;
+       szMsg = @TEXT_SELECT_COLLECTIONS_DESC;
+
+       nResult = SdComponentDialog(szTitle, szMsg, svDir, "collections");
+       TARGETDIR  = svDir;
+
+       return nResult;
+ end;
+
+function DialogGetAdminPassword()
+	STRING szTitle, szMsg, szField1;
+	NUMBER nResult;
+
+begin
+
+	svAdminPassword = "admin"; // the default	
+
+	szTitle = @TEXT_ADMIN_PW;
+	szMsg = @TEXT_ADMIN_PW_DESC;
+	szField1 = @TEXT_PW;
+
+	nResult = SdShowDlgEdit1(szTitle, szMsg, szField1, svAdminPassword);
+
+	return nResult;
+end;
+
+
+// use setpw to set the admin password in the users.db database
+function SetAdminPassword()
+	STRING cmd, cmdline, dbfile;
+	
+begin
+
+	dbfile = TARGETDIR ^ "etc" ^ "users.db";
+	cmd = "\"" + SRCDIR ^ ".." ^ "bin" ^ "windows" ^ "setpw.exe\"";
+	cmdline = " -u admin -p " + svAdminPassword + " -o \"" + dbfile + "\"";
+
+	if (LaunchApp(cmd, cmdline) != 0) then
+		MessageBox(@TEXT_SETPW_FAIL, WARNING);
+	endif;
+
+end;
+
+function CheckWin32s()
+ STRING   szTitle, szMsg, svResult, szInfo, svPath, svVersionNumber;
+ NUMBER   nvResult,nResult, nvWin32, nvOSTYPE, nvOLDWIN32S, nvWIN32SINSTALLED;
+
+begin
+
+	if (GetSystemInfo (OS, nvOSTYPE, svResult) < 0) then
+    	MessageBox("Couldn't get Operating System info.", SEVERE);
+   	endif;
+   	
+	// get information about win32s
+   	nvOLDWIN32S=0;
+   	GetSystemInfo (WIN32SINSTALLED, nvWIN32SINSTALLED, svResult);
+   	if (nvWIN32SINSTALLED == TRUE) then
+   		GetSystemInfo (WIN32SMAJOR, nvWin32, svResult);
+    	if (nvWin32 == 0) then
+      		nvOLDWIN32S = 1;
+      	else
+    		GetSystemInfo (WIN32SMINOR, nvWin32, svResult);
+    		if (nvWin32 < 30) then
+    			nvOLDWIN32S = 1;
+    		endif;
+    	endif;
+   	endif;
+
+	// run Win32s installation if required.
+	if ((nvOSTYPE == IS_WINDOWS) || (nvOSTYPE == IS_WIN32S)) then
+	   if ((nvWIN32SINSTALLED == 0)) then
+	   		if (CreateProgramFolder(@FOLDER_NAME) < 0) then
+				MessageBox("CreateProgramFolder failed.", SEVERE);
+			endif;
+
+   			if (AddFolderIcon(@FOLDER_NAME, @INSTALL_GSDL, "\"" + SRCDIR ^ "setup.exe\"", "",
+                     "", 0, "", REPLACE) < 0) then
+      			MessageBox("AddFolderIcon failed.", SEVERE);
+   			endif;
+	
+	   		MessageBox(@TEXT_ERROR_NO_WIN32S, INFORMATION);
+	   		LaunchApp(SRCDIR ^ "bin" ^ "windows" ^ "win32s" ^ "setup.exe","");
+	   		exit;
+	 	else
+	   		if (nvOLDWIN32S == 1) then
+	   			MessageBox(@TEXT_ERROR_OLD_WIN32S, INFORMATION);
+			endif;
+		endif;
+	endif;
+end;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+//
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// --- include script file section ---
+
+#include "sddialog.rul"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: /tags/start/is_5_gsdl_cdrom/Setup Files/Compressed Files/Language Independent/OS Independent/license.txt
===================================================================
--- /tags/start/is_5_gsdl_cdrom/Setup Files/Compressed Files/Language Independent/OS Independent/license.txt	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/Setup Files/Compressed Files/Language Independent/OS Independent/license.txt	(revision 13666)
@@ -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/start/is_5_gsdl_cdrom/Shell Objects/Default.shl
===================================================================
--- /tags/start/is_5_gsdl_cdrom/Shell Objects/Default.shl	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/Shell Objects/Default.shl	(revision 13666)
@@ -0,0 +1,12 @@
+[Data]
+Folder3=<FOLDER_STARTUP>
+Group0=Main
+Group1=Startup
+Folder0=<FOLDER_DESKTOP>
+Folder1=<FOLDER_STARTMENU>
+Folder2=<FOLDER_PROGRAMS>
+
+[Info]
+Type=ShellObject
+Version=1.00.000
+
Index: /tags/start/is_5_gsdl_cdrom/String Tables/0009-English/value.shl
===================================================================
--- /tags/start/is_5_gsdl_cdrom/String Tables/0009-English/value.shl	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/String Tables/0009-English/value.shl	(revision 13666)
@@ -0,0 +1,83 @@
+[Data]
+TEXT_GSARCH=Greenstone mailing list archives (gsarch)
+TEXT_ADMIN_PW_DESC=In order to access certain parts of the Greenstone interface you need a password. A user with the username 'admin' will be created for you with the password you provide. The password must be between three and eight characters long.
+TEXT_SERVERTXT_01=To use the Greenstone Web Library you will need to have
+TEXT_SERVERTXT_12=Greenstone has been set up to expect %s
+TEXT_SERVERTXT_23=http://localhost/gsdl/cgi-bin/library.exe or
+TEXT_INSTALL_TYPE=Greenstone installation type
+TITLE_MAIN=Greenstone Digital Library Software
+TEXT_HDLSUB=Humanity Development Library Subset (hdlsub)
+TEXT_SERVERTXT_02=a webserver installed (you'll also need perl if you want
+TEXT_SERVERTXT_13=to be accessible from your webserver at the URL
+TEXT_SERVERTXT_24=http://your.server.com/gsdl/cgi-bin/library.exe
+TEXT_COLLORG=Would you like to install the Collection Organizer utility at this time?\n\nIf you choose not to install this utility you may install it from the CD-ROM at any time by double-clicking 'CollOrganizer.exe' in the 'windows_utilities' folder.
+TEXT_UNINSTALL=Uninstall Greenstone
+LOCAL_LIBRARY_DESC=Installs the local library. This version of Greenstone has a webserver built in and is suitable for building and viewing Greenstone collections on a stand-alone system. It also has limited web serving ability.
+TEXT_SELECT_COLLECTIONS_DESC=The 'Greenstone demo' collection will be installed for you. Select those additional collections you would like installed.
+TEXT_SERVERTXT_03=to build your own collections).
+TEXT_SERVERTXT_14=http://localhost/gsdl (localhost will of course be the
+TEXT_SERVERTXT_25=For more information on installing and configuring a
+COMPANY_NAME=New Zealand Digital Library Project
+ERROR_COMPONENT=Component:
+TEXT_SELECT_COLLECTIONS=Select collections
+TEXT_SERVERTXT_04=The following information is intended to help you
+TEXT_SERVERTXT_15=usual web address of your machine if it has one).
+TEXT_SERVERTXT_26=webserver see the Greenstone Installer's guide.
+INSTALL_GSDL=Install Greenstone
+COMPANY_NAME16=NZDL
+TEXT_SERVERTXT_05=configure your webserver for use with Greenstone.
+TEXT_SERVERTXT_16=Likewise, the %s
+TEXT_NOT_ADMIN=Greenstone could not be installed as you do not have administrator privileges on this system.\n\nPlease either log in using an administrator account and try again or contact your system administrator for help.
+TEXT_INSTALL_TYPE_DESC=Click the type of Greenstone installation you prefer, then click Next.
+SOURCE_CODE=Source Code
+PRODUCT_VERSION=2.38.000
+ERROR_MOVEDATA=An error occurred during the move data process: %d
+ERROR_FILEGROUP=File Group:
+TEXT_SERVERTXT_06=Particular attention is given to the Apache webserver
+TEXT_SERVERTXT_17=directory must be accessible as a cgi executable
+TEXT_SERVERTXT_07=which may be downloaded free from www.apache.org.
+TEXT_SERVERTXT_18=directory.
+UNINST_KEY=Greenstone Digital Library Software
+TEXT_FINISH1=Setup has finished installing Greenstone on your computer.\n\nTo use Greenstone select 'Greenstone Digital Library' from the programs in the start menu.
+TEXT_SERVERTXT_08=Greenstone will work with other webservers too if that is
+TEXT_SERVERTXT_19=For the Apache webserver this means adding the following
+TEXT_ERROR_NO_WIN32S=Setup has detected that you don't have Win32s installed on your computer. You will need to install Win32s to use the Greenstone Digital Library Software. As installing Win32s involves restarting your computer you will need to begin the Greenstone Setup process again once it has completed.
+WEB_LIBRARY_DESC=Installs the web library. This is the recommended option for those wanting to serve Greenstone collections to others on the web. It requires a webserver (e.g. Apache).
+TITLE_CAPTIONBAR=Greenstone Digital Library Software Setup
+TEXT_CHINESE=Chinese demonstration collection (chinese)
+TEXT_SERVERTXT_09=your preference.
+TEXT_FINISH2=Setup has finished installing Greenstone on your computer.\n\nTo use Greenstone you must first configure your webserver. See the SERVER.TXT file for details.
+TEXT_FINISH3=Setup has finished installing Greenstone on your computer.\n\nTo use Greenstone you must first compile it. See the Install.txt file for details.
+PRODUCT_NAME16=GSDL
+TEXT_WORDPDF=MSWord, PDF, RTF and Postscript demo collection (wordpdf)
+TEXT_ADMIN_PW=Set admin password
+FOLDER_NAME=Greenstone Digital Library
+TEXT_SETUP_TYPE_DESC=Select your prefered setup type. 'Full' will install all Greenstone components. 'Compact' will use less disk space by leaving out some of Greenstone's less important features.
+WEB_LIBRARY=Web Library (requires separate webserver)
+ERROR_VGARESOLUTION=This program requires VGA or better resolution.
+ERROR_FILE=File:
+TEXT_PW=Password
+TEXT_FULL=Full Installation (approx. 64Mb + collections)
+LOCAL_LIBRARY=Local Library (recommended)
+TEXT_COMPACT=Compact Installation (approx. 36Mb + collections)
+TEXT_SETPW_FAIL=Failed to set admin user's password. The password will default to 'admin'.
+UNINST_DISPLAY_NAME=Greenstone Digital Library Software
+PRODUCT_KEY=server.exe
+TEXT_SERVERTXT_20=directives to your httpd.conf configuration file.
+TEXT_ERROR_OLD_WIN32S=Setup has detected that you have an old version of Win32s. The Greenstone Digital Library Software will not run without Win32s. If the library doesn't run correctly with your version of Win32s try installing a later version from the cd-rom.
+SOURCE_CODE_DESC=Installs source code only (binary executables will not be installed). If using this option Greenstone will need to be compiled before it can be used. This installation does NOT compile Greenstone for you.
+PRODUCT_NAME=Greenstone Digital Library Software
+ERROR_UNINSTSETUP=unInstaller setup failed to initialize.  You may not be able to uninstall this product.
+TEXT_SERVERTXT_10=To refer back to this information later you can find it
+TEXT_SERVERTXT_21=Once your webserver is configured in this way you can
+README=README.TXT
+TEXT_README=view README.TXT file now
+TEXT_SERVERTXT_11=in the file %s
+TEXT_SERVERTXT_22=access Greenstone by pointing your web browser at
+TEXT_FILEGREP_FAILED=FileGrep failed
+
+[General]
+Language=0009
+Type=STRINGTABLESPECIFIC
+Version=1.00.000
+
Index: /tags/start/is_5_gsdl_cdrom/String Tables/000a-Spanish/value.shl
===================================================================
--- /tags/start/is_5_gsdl_cdrom/String Tables/000a-Spanish/value.shl	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/String Tables/000a-Spanish/value.shl	(revision 13666)
@@ -0,0 +1,83 @@
+[Data]
+TEXT_GSARCH=Greenstone mailing list archives (gsarch)
+TEXT_ADMIN_PW_DESC=In order to access certain parts of the Greenstone interface you need a password. A user with the username 'admin' will be created for you with the password you provide. The password must be between three and eight characters long.
+TEXT_SERVERTXT_01=To use the Greenstone Web Library you will need to have
+TEXT_SERVERTXT_12=Greenstone has been set up to expect %s
+TEXT_SERVERTXT_23=http://localhost/gsdl/cgi-bin/library.exe or
+TITLE_MAIN=Greenstone Digital Library Software
+TEXT_INSTALL_TYPE=Greenstone installation type
+TEXT_HDLSUB=Humanity Development Library Subset (hdlsub)
+TEXT_SERVERTXT_02=a webserver installed (you'll also need perl if you want
+TEXT_SERVERTXT_13=to be accessible from your webserver at the URL
+TEXT_SERVERTXT_24=http://your.server.com/gsdl/cgi-bin/library.exe
+LOCAL_LIBRARY_DESC=Installs the local library. This version of Greenstone has a webserver built in and is suitable for building and viewing Greenstone collections on a stand-alone system. It also has limited web serving ability.
+TEXT_SELECT_COLLECTIONS_DESC=The 'Greenstone demo' collection will be installed for you. Select those additional collections you would like installed.
+TEXT_UNINSTALL=Uninstall Greenstone
+TEXT_SERVERTXT_03=to build your own collections).
+TEXT_SERVERTXT_14=http://localhost/gsdl (localhost will of course be the
+TEXT_SERVERTXT_25=For more information on installing and configuring a
+TEXT_COLLORG=Would you like to install the Collection Organizer utility at this time?\n\nIf you choose not to install this utility you may install it from the CD-ROM at any time by double-clicking 'CollOrganizer.exe' in the 'windows_utilities' folder.
+COMPANY_NAME=New Zealand Digital Library Project
+ERROR_COMPONENT=Component:
+TEXT_SELECT_COLLECTIONS=Select collections
+TEXT_SERVERTXT_04=The following information is intended to help you
+TEXT_SERVERTXT_15=usual web address of your machine if it has one).
+TEXT_SERVERTXT_26=webserver see the Greenstone Installer's guide.
+COMPANY_NAME16=NZDL
+INSTALL_GSDL=Install Greenstone
+TEXT_SERVERTXT_05=configure your webserver for use with Greenstone.
+TEXT_SERVERTXT_16=Likewise, the %s
+TEXT_NOT_ADMIN=Greenstone could not be installed as you do not have administrator privileges on this system.\n\nPlease either log in using an administrator account and try again or contact your system administrator for help.
+PRODUCT_VERSION=2.37.000
+ERROR_MOVEDATA=An error occurred during the move data process: %d
+ERROR_FILEGROUP=File Group:
+SOURCE_CODE=Source Code
+TEXT_INSTALL_TYPE_DESC=Click the type of Greenstone installation you prefer, then click Next.
+TEXT_SERVERTXT_06=Particular attention is given to the Apache webserver
+TEXT_SERVERTXT_17=directory must be accessible as a cgi executable
+TEXT_SERVERTXT_07=which may be downloaded free from www.apache.org.
+TEXT_SERVERTXT_18=directory.
+UNINST_KEY=Greenstone Digital Library Software
+TEXT_FINISH1=Setup has finished installing Greenstone on your computer.\n\nTo use Greenstone select 'Greenstone Digital Library' from the programs in the start menu.
+TEXT_SERVERTXT_08=Greenstone will work with other webservers too if that is
+TEXT_SERVERTXT_19=For the Apache webserver this means adding the following
+TITLE_CAPTIONBAR=Greenstone Digital Library Software Setup
+WEB_LIBRARY_DESC=Installs the web library. This is the recommended option for those wanting to serve Greenstone collections to others on the web. It requires a webserver (e.g. Apache).
+TEXT_CHINESE=Chinese demonstration collection (chinese)
+TEXT_ERROR_NO_WIN32S=Setup has detected that you don't have Win32s installed on your computer. You will need to install Win32s to use the Greenstone Digital Library Software. As installing Win32s involves restarting your computer you will need to begin the Greenstone Setup process again once it has completed.
+TEXT_SERVERTXT_09=your preference.
+TEXT_FINISH2=Setup has finished installing Greenstone on your computer.\n\nTo use Greenstone you must first configure your webserver. See the SERVER.TXT file for details.
+TEXT_FINISH3=Setup has finished installing Greenstone on your computer.\n\nTo use Greenstone you must first compile it. See the Install.txt file for details.
+PRODUCT_NAME16=GSDL
+TEXT_WORDPDF=MSWord, PDF, RTF and Postscript demo collection (wordpdf)
+TEXT_ADMIN_PW=Set admin password
+ERROR_VGARESOLUTION=This program requires VGA or better resolution.
+ERROR_FILE=File:
+WEB_LIBRARY=Web Library (requires separate webserver)
+TEXT_SETUP_TYPE_DESC=Select your prefered setup type. 'Full' will install all Greenstone components. 'Compact' will use less disk space by leaving out some of Greenstone's less important features.
+TEXT_PW=Password
+FOLDER_NAME=Greenstone Digital Library
+LOCAL_LIBRARY=Local Library (recommended)
+TEXT_FULL=Full Installation (approx. 64Mb + collections)
+TEXT_COMPACT=Compact Installation (approx. 36Mb + collections)
+TEXT_SETPW_FAIL=Failed to set admin user's password. The password will default to 'admin'.
+UNINST_DISPLAY_NAME=Greenstone Digital Library Software
+PRODUCT_KEY=server.exe
+TEXT_SERVERTXT_20=directives to your httpd.conf configuration file.
+PRODUCT_NAME=Greenstone Digital Library Software
+ERROR_UNINSTSETUP=unInstaller setup failed to initialize.  You may not be able to uninstall this product.
+SOURCE_CODE_DESC=Installs source code only (binary executables will not be installed). If using this option Greenstone will need to be compiled before it can be used. This installation does NOT compile Greenstone for you.
+TEXT_ERROR_OLD_WIN32S=Setup has detected that you have an old version of Win32s. The Greenstone Digital Library Software will not run without Win32s. If the library doesn't run correctly with your version of Win32s try installing a later version from the cd-rom.
+TEXT_SERVERTXT_10=To refer back to this information later you can find it
+TEXT_SERVERTXT_21=Once your webserver is configured in this way you can
+TEXT_README=view README.TXT file now
+README=README.TXT
+TEXT_SERVERTXT_11=in the file %s
+TEXT_SERVERTXT_22=access Greenstone by pointing your web browser at
+TEXT_FILEGREP_FAILED=FileGrep failed
+
+[General]
+Language=000a
+Type=STRINGTABLESPECIFIC
+Version=1.00.000
+
Index: /tags/start/is_5_gsdl_cdrom/String Tables/040c-French (Standard)/value.shl
===================================================================
--- /tags/start/is_5_gsdl_cdrom/String Tables/040c-French (Standard)/value.shl	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/String Tables/040c-French (Standard)/value.shl	(revision 13666)
@@ -0,0 +1,83 @@
+[Data]
+TEXT_GSARCH=Greenstone mailing list archives (gsarch)
+TEXT_ADMIN_PW_DESC=In order to access certain parts of the Greenstone interface you need a password. A user with the username 'admin' will be created for you with the password you provide. The password must be between three and eight characters long.
+TEXT_SERVERTXT_01=To use the Greenstone Web Library you will need to have
+TEXT_SERVERTXT_12=Greenstone has been set up to expect %s
+TEXT_SERVERTXT_23=http://localhost/gsdl/cgi-bin/library.exe or
+TITLE_MAIN=Greenstone Digital Library Software
+TEXT_INSTALL_TYPE=Greenstone installation type
+TEXT_HDLSUB=Humanity Development Library Subset (hdlsub)
+TEXT_SERVERTXT_02=a webserver installed (you'll also need perl if you want
+TEXT_SERVERTXT_13=to be accessible from your webserver at the URL
+TEXT_SERVERTXT_24=http://your.server.com/gsdl/cgi-bin/library.exe
+LOCAL_LIBRARY_DESC=Installs the local library. This version of Greenstone has a webserver built in and is suitable for building and viewing Greenstone collections on a stand-alone system. It also has limited web serving ability.
+TEXT_SELECT_COLLECTIONS_DESC=The 'Greenstone demo' collection will be installed for you. Select those additional collections you would like installed.
+TEXT_UNINSTALL=Uninstall Greenstone
+TEXT_SERVERTXT_03=to build your own collections).
+TEXT_SERVERTXT_14=http://localhost/gsdl (localhost will of course be the
+TEXT_SERVERTXT_25=For more information on installing and configuring a
+TEXT_COLLORG=Would you like to install the Collection Organizer utility at this time?\n\nIf you choose not to install this utility you may install it from the CD-ROM at any time by double-clicking 'CollOrganizer.exe' in the 'windows_utilities' folder.
+COMPANY_NAME=New Zealand Digital Library Project
+ERROR_COMPONENT=Component:
+TEXT_SELECT_COLLECTIONS=Select collections
+TEXT_SERVERTXT_04=The following information is intended to help you
+TEXT_SERVERTXT_15=usual web address of your machine if it has one).
+TEXT_SERVERTXT_26=webserver see the Greenstone Installer's guide.
+COMPANY_NAME16=NZDL
+INSTALL_GSDL=Install Greenstone
+TEXT_SERVERTXT_05=configure your webserver for use with Greenstone.
+TEXT_SERVERTXT_16=Likewise, the %s
+TEXT_NOT_ADMIN=Greenstone could not be installed as you do not have administrator privileges on this system.\n\nPlease either log in using an administrator account and try again or contact your system administrator for help.
+PRODUCT_VERSION=2.37.000
+ERROR_MOVEDATA=An error occurred during the move data process: %d
+ERROR_FILEGROUP=File Group:
+SOURCE_CODE=Source Code
+TEXT_INSTALL_TYPE_DESC=Click the type of Greenstone installation you prefer, then click Next.
+TEXT_SERVERTXT_06=Particular attention is given to the Apache webserver
+TEXT_SERVERTXT_17=directory must be accessible as a cgi executable
+TEXT_SERVERTXT_07=which may be downloaded free from www.apache.org.
+TEXT_SERVERTXT_18=directory.
+UNINST_KEY=Greenstone Digital Library Software
+TEXT_FINISH1=Setup has finished installing Greenstone on your computer.\n\nTo use Greenstone select 'Greenstone Digital Library' from the programs in the start menu.
+TEXT_SERVERTXT_08=Greenstone will work with other webservers too if that is
+TEXT_SERVERTXT_19=For the Apache webserver this means adding the following
+TITLE_CAPTIONBAR=Greenstone Digital Library Software Setup
+WEB_LIBRARY_DESC=Installs the web library. This is the recommended option for those wanting to serve Greenstone collections to others on the web. It requires a webserver (e.g. Apache).
+TEXT_CHINESE=Chinese demonstration collection (chinese)
+TEXT_ERROR_NO_WIN32S=Setup has detected that you don't have Win32s installed on your computer. You will need to install Win32s to use the Greenstone Digital Library Software. As installing Win32s involves restarting your computer you will need to begin the Greenstone Setup process again once it has completed.
+TEXT_SERVERTXT_09=your preference.
+TEXT_FINISH2=Setup has finished installing Greenstone on your computer.\n\nTo use Greenstone you must first configure your webserver. See the SERVER.TXT file for details.
+TEXT_FINISH3=Setup has finished installing Greenstone on your computer.\n\nTo use Greenstone you must first compile it. See the Install.txt file for details.
+PRODUCT_NAME16=GSDL
+TEXT_WORDPDF=MSWord, PDF, RTF and Postscript demo collection (wordpdf)
+TEXT_ADMIN_PW=Set admin password
+ERROR_VGARESOLUTION=This program requires VGA or better resolution.
+ERROR_FILE=File:
+WEB_LIBRARY=Web Library (requires separate webserver)
+TEXT_SETUP_TYPE_DESC=Select your prefered setup type. 'Full' will install all Greenstone components. 'Compact' will use less disk space by leaving out some of Greenstone's less important features.
+TEXT_PW=Password
+FOLDER_NAME=Greenstone Digital Library
+LOCAL_LIBRARY=Local Library (recommended)
+TEXT_FULL=Full Installation (approx. 64Mb + collections)
+TEXT_COMPACT=Compact Installation (approx. 36Mb + collections)
+TEXT_SETPW_FAIL=Failed to set admin user's password. The password will default to 'admin'.
+UNINST_DISPLAY_NAME=Greenstone Digital Library Software
+PRODUCT_KEY=server.exe
+TEXT_SERVERTXT_20=directives to your httpd.conf configuration file.
+PRODUCT_NAME=Greenstone Digital Library Software
+ERROR_UNINSTSETUP=unInstaller setup failed to initialize.  You may not be able to uninstall this product.
+SOURCE_CODE_DESC=Installs source code only (binary executables will not be installed). If using this option Greenstone will need to be compiled before it can be used. This installation does NOT compile Greenstone for you.
+TEXT_ERROR_OLD_WIN32S=Setup has detected that you have an old version of Win32s. The Greenstone Digital Library Software will not run without Win32s. If the library doesn't run correctly with your version of Win32s try installing a later version from the cd-rom.
+TEXT_SERVERTXT_10=To refer back to this information later you can find it
+TEXT_SERVERTXT_21=Once your webserver is configured in this way you can
+TEXT_README=view README.TXT file now
+README=README.TXT
+TEXT_SERVERTXT_11=in the file %s
+TEXT_SERVERTXT_22=access Greenstone by pointing your web browser at
+TEXT_FILEGREP_FAILED=FileGrep failed
+
+[General]
+Language=040c
+Type=STRINGTABLESPECIFIC
+Version=1.00.000
+
Index: /tags/start/is_5_gsdl_cdrom/String Tables/Default.shl
===================================================================
--- /tags/start/is_5_gsdl_cdrom/String Tables/Default.shl	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/String Tables/Default.shl	(revision 13666)
@@ -0,0 +1,316 @@
+[TEXT_GSARCH]
+Comment=
+
+[TEXT_ADMIN_PW_DESC]
+Comment=
+
+[TEXT_SERVERTXT_01]
+Comment=
+
+[TEXT_SERVERTXT_12]
+Comment=
+
+[TEXT_SERVERTXT_23]
+Comment=
+
+[TEXT_INSTALL_TYPE]
+Comment=
+
+[TITLE_MAIN]
+Comment=
+
+[TEXT_HDLSUB]
+Comment=
+
+[TEXT_SERVERTXT_02]
+Comment=
+
+[TEXT_SERVERTXT_13]
+Comment=
+
+[TEXT_SERVERTXT_24]
+Comment=
+
+[TEXT_COLLORG]
+Comment=
+
+[TEXT_UNINSTALL]
+Comment=
+
+[LOCAL_LIBRARY_DESC]
+Comment=
+
+[TEXT_SELECT_COLLECTIONS_DESC]
+Comment=
+
+[TEXT_SERVERTXT_03]
+Comment=
+
+[TEXT_SERVERTXT_14]
+Comment=
+
+[TEXT_SERVERTXT_25]
+Comment=
+
+[COMPANY_NAME]
+Comment=
+
+[ERROR_COMPONENT]
+Comment=
+
+[TEXT_SELECT_COLLECTIONS]
+Comment=
+
+[TEXT_SERVERTXT_04]
+Comment=
+
+[TEXT_SERVERTXT_15]
+Comment=
+
+[TEXT_SERVERTXT_26]
+Comment=
+
+[INSTALL_GSDL]
+Comment=
+
+[COMPANY_NAME16]
+Comment=
+
+[TEXT_SERVERTXT_05]
+Comment=
+
+[TEXT_SERVERTXT_16]
+Comment=
+
+[TEXT_NOT_ADMIN]
+Comment=
+
+[TEXT_INSTALL_TYPE_DESC]
+Comment=
+
+[SOURCE_CODE]
+Comment=
+
+[PRODUCT_VERSION]
+Comment=
+
+[ERROR_MOVEDATA]
+Comment=
+
+[ERROR_FILEGROUP]
+Comment=
+
+[TEXT_SERVERTXT_06]
+Comment=
+
+[TEXT_SERVERTXT_17]
+Comment=
+
+[TEXT_SERVERTXT_07]
+Comment=
+
+[TEXT_SERVERTXT_18]
+Comment=
+
+[Language]
+Lang0=0009
+Lang1=040c
+Lang2=000a
+CurrentLang=2
+
+[UNINST_KEY]
+Comment=
+
+[TEXT_FINISH1]
+Comment=
+
+[TEXT_SERVERTXT_08]
+Comment=
+
+[TEXT_SERVERTXT_19]
+Comment=
+
+[TEXT_ERROR_NO_WIN32S]
+Comment=
+
+[WEB_LIBRARY_DESC]
+Comment=
+
+[TITLE_CAPTIONBAR]
+Comment=
+
+[TEXT_CHINESE]
+Comment=
+
+[TEXT_SERVERTXT_09]
+Comment=
+
+[TEXT_FINISH2]
+Comment=
+
+[TEXT_FINISH3]
+Comment=
+
+[Data]
+Entry18=WEB_LIBRARY
+Entry0=ERROR_VGARESOLUTION
+Entry29=TEXT_GSARCH
+Entry19=WEB_LIBRARY_DESC
+Entry1=TITLE_MAIN
+Entry2=TITLE_CAPTIONBAR
+Entry3=UNINST_KEY
+Entry70=TEXT_FINISH2
+Entry4=UNINST_DISPLAY_NAME
+Entry60=TEXT_SERVERTXT_17
+Entry71=TEXT_FINISH3
+Entry72=TEXT_COLLORG
+Entry5=COMPANY_NAME
+Entry50=TEXT_SERVERTXT_07
+Entry61=TEXT_SERVERTXT_18
+Entry40=TEXT_ERROR_NO_WIN32S
+Entry6=PRODUCT_NAME
+Entry51=TEXT_SERVERTXT_08
+Entry62=TEXT_SERVERTXT_19
+Entry73=TEXT_NOT_ADMIN
+Entry41=TEXT_ERROR_OLD_WIN32S
+Entry7=PRODUCT_VERSION
+Entry30=TEXT_WORDPDF
+Entry52=TEXT_SERVERTXT_09
+Entry63=TEXT_SERVERTXT_20
+Entry74=TEXT_SETPW_FAIL
+Entry42=README
+Entry20=SOURCE_CODE
+Entry8=PRODUCT_KEY
+Entry31=TEXT_CHINESE
+Entry53=TEXT_SERVERTXT_10
+Entry64=TEXT_SERVERTXT_21
+Entry75=TEXT_FILEGREP_FAILED
+Entry43=TEXT_UNINSTALL
+Entry21=SOURCE_CODE_DESC
+Entry9=ERROR_MOVEDATA
+Entry10=ERROR_UNINSTSETUP
+Entry32=TEXT_HDLSUB
+Entry54=TEXT_SERVERTXT_11
+Entry65=TEXT_SERVERTXT_22
+Entry22=TEXT_INSTALL_TYPE
+Entry11=COMPANY_NAME16
+Entry33=TEXT_ADMIN_PW
+Entry44=TEXT_SERVERTXT_01
+Entry55=TEXT_SERVERTXT_12
+Entry66=TEXT_SERVERTXT_23
+Entry23=TEXT_INSTALL_TYPE_DESC
+Entry12=PRODUCT_NAME16
+Entry34=TEXT_ADMIN_PW_DESC
+Entry45=TEXT_SERVERTXT_02
+Entry56=TEXT_SERVERTXT_13
+Entry67=TEXT_SERVERTXT_24
+Entry24=TEXT_SETUP_TYPE_DESC
+Entry13=ERROR_COMPONENT
+Entry35=TEXT_PW
+Entry46=TEXT_SERVERTXT_03
+Entry57=TEXT_SERVERTXT_14
+Entry68=TEXT_SERVERTXT_25
+Entry25=TEXT_COMPACT
+Entry14=ERROR_FILEGROUP
+Entry36=TEXT_FINISH1
+Entry47=TEXT_SERVERTXT_04
+Entry58=TEXT_SERVERTXT_15
+Entry69=TEXT_SERVERTXT_26
+Entry26=TEXT_FULL
+Entry15=ERROR_FILE
+Entry37=TEXT_README
+Entry48=TEXT_SERVERTXT_05
+Entry59=TEXT_SERVERTXT_16
+Entry38=FOLDER_NAME
+Entry16=LOCAL_LIBRARY
+Entry27=TEXT_SELECT_COLLECTIONS
+Entry49=TEXT_SERVERTXT_06
+Entry39=INSTALL_GSDL
+Entry17=LOCAL_LIBRARY_DESC
+Entry28=TEXT_SELECT_COLLECTIONS_DESC
+
+[PRODUCT_NAME16]
+Comment=
+
+[TEXT_WORDPDF]
+Comment=
+
+[TEXT_ADMIN_PW]
+Comment=
+
+[FOLDER_NAME]
+Comment=
+
+[TEXT_SETUP_TYPE_DESC]
+Comment=
+
+[WEB_LIBRARY]
+Comment=
+
+[ERROR_VGARESOLUTION]
+Comment=
+
+[ERROR_FILE]
+Comment=
+
+[TEXT_PW]
+Comment=
+
+[TEXT_FULL]
+Comment=
+
+[LOCAL_LIBRARY]
+Comment=
+
+[TEXT_COMPACT]
+Comment=
+
+[TEXT_SETPW_FAIL]
+Comment=
+
+[General]
+Type=STRINGTABLE
+Version=1.00.000
+
+[UNINST_DISPLAY_NAME]
+Comment=
+
+[PRODUCT_KEY]
+Comment=
+
+[TEXT_SERVERTXT_20]
+Comment=
+
+[TEXT_ERROR_OLD_WIN32S]
+Comment=
+
+[SOURCE_CODE_DESC]
+Comment=
+
+[PRODUCT_NAME]
+Comment=
+
+[ERROR_UNINSTSETUP]
+Comment=
+
+[TEXT_SERVERTXT_10]
+Comment=
+
+[TEXT_SERVERTXT_21]
+Comment=
+
+[README]
+Comment=
+
+[TEXT_README]
+Comment=
+
+[TEXT_SERVERTXT_11]
+Comment=
+
+[TEXT_SERVERTXT_22]
+Comment=
+
+[TEXT_FILEGREP_FAILED]
+Comment=
+
Index: /tags/start/is_5_gsdl_cdrom/Text Substitutions/Build.tsb
===================================================================
--- /tags/start/is_5_gsdl_cdrom/Text Substitutions/Build.tsb	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/Text Substitutions/Build.tsb	(revision 13666)
@@ -0,0 +1,70 @@
+[<ISPROJECTDIR>]
+KeyType=4
+Value=
+
+[<HKUS>]
+Value=
+KeyType=4
+
+[<HKCR>]
+Value=
+KeyType=4
+
+[<PROGRAMFILES>]
+Value=
+KeyType=4
+
+[<WINSYSDIR>]
+Value=
+KeyType=4
+
+[<COMMONFILES>]
+Value=
+KeyType=4
+
+[<WINDIR>]
+Value=
+KeyType=4
+
+[Data]
+Key0=<PROGRAMFILES>
+Key1=<COMMONFILES>
+Key2=<WINDIR>
+Key3=<WINSYSDIR>
+Key4=<ISPROJECTDIR>
+Key5=<HKCU>
+Key10=<SHELL_OBJECT_FOLDER>
+Key6=<HKCC>
+Key11=<UNINST>
+Key7=<HKDD>
+Key8=<HKUS>
+Key9=<HKCR>
+
+[<UNINST>]
+Value=
+KeyType=4
+
+[<SHELL_OBJECT_FOLDER>]
+Value=
+KeyType=4
+
+[General]
+Type=TEXTSUB
+Version=1.20.000
+
+[<HKLM>]
+Value=
+KeyType=4
+
+[<HKCU>]
+Value=
+KeyType=4
+
+[<HKCC>]
+Value=
+KeyType=4
+
+[<HKDD>]
+Value=
+KeyType=4
+
Index: /tags/start/is_5_gsdl_cdrom/Text Substitutions/Setup.tsb
===================================================================
--- /tags/start/is_5_gsdl_cdrom/Text Substitutions/Setup.tsb	(revision 13666)
+++ /tags/start/is_5_gsdl_cdrom/Text Substitutions/Setup.tsb	(revision 13666)
@@ -0,0 +1,81 @@
+[<SRCDIR>]
+Value=
+KeyType=4
+
+[<HKUS>]
+Value=
+KeyType=4
+
+[<HKCR>]
+Value=
+KeyType=4
+
+[<PROGRAMFILES>]
+Value=
+KeyType=4
+
+[<TARGETDIR>]
+Value=
+KeyType=4
+
+[<WINSYSDIR>]
+Value=
+KeyType=4
+
+[<COMMONFILES>]
+Value=
+KeyType=4
+
+[<WINDIR>]
+Value=
+KeyType=4
+
+[Data]
+Key0=<PROGRAMFILES>
+Key1=<COMMONFILES>
+Key2=<WINDIR>
+Key3=<WINSYSDIR>
+Key4=<TARGETDIR>
+Key5=<SUPPORTDIR>
+Key10=<HKDD>
+Key6=<SRCDIR>
+Key11=<HKUS>
+Key7=<HKLM>
+Key12=<HKCR>
+Key8=<HKCU>
+Key13=<SHELL_OBJECT_FOLDER>
+Key9=<HKCC>
+Key14=<UNINST>
+
+[<UNINST>]
+Value=
+KeyType=4
+
+[<SUPPORTDIR>]
+Value=
+KeyType=4
+
+[<SHELL_OBJECT_FOLDER>]
+Value=
+KeyType=4
+
+[General]
+Type=TEXTSUB
+Version=1.10.000
+
+[<HKLM>]
+Value=
+KeyType=4
+
+[<HKCU>]
+Value=
+KeyType=4
+
+[<HKCC>]
+Value=
+KeyType=4
+
+[<HKDD>]
+Value=
+KeyType=4
+
Index: /tags/start/java-client/Makefile
===================================================================
--- /tags/start/java-client/Makefile	(revision 13666)
+++ /tags/start/java-client/Makefile	(revision 13666)
@@ -0,0 +1,4 @@
+idltojava :
+	idlj -pkgPrefix gsdlInterface org.nzdl.corba corbaiface.idl
+	javac org/nzdl/corba/gsdlInterface/*.java
+#	setenv CLASSPATH /home/daven/research/corba/new/src:.
Index: /tags/start/java-client/corbaiface.idl
===================================================================
--- /tags/start/java-client/corbaiface.idl	(revision 13666)
+++ /tags/start/java-client/corbaiface.idl	(revision 13666)
@@ -0,0 +1,228 @@
+// basic elements for text
+
+module gsdlInterface {
+
+typedef sequence<unsigned short> usString;
+
+typedef sequence<string> stringSeq;
+
+struct corbatext_t
+{ 
+  usString text;
+  unsigned short encoding;
+  unsigned long  length;
+};
+
+typedef sequence<corbatext_t> corbatext_tarray;
+
+typedef corbatext_tarray corbatext_tset;
+
+struct corbatext_tmap
+{
+  corbatext_tarray names;
+  corbatext_tarray values;
+};
+
+// standard error values
+
+enum corbaComError
+{ corbaNoError, 
+  corbaAuthenticationFailure, 
+  corbaProtocolError, 
+  corbaConfigurationError, 
+  corbaSystemProblem
+};
+
+//
+// getColInfo response
+//
+
+struct corbaShortColInfo
+{
+  corbatext_t name;
+  corbatext_t host;
+  long        response;
+};
+
+struct corbaColInfoResponse
+{
+  corbaShortColInfo shoftInfo;
+  boolean           isPublic;
+  boolean           isBeta;
+  unsigned long     buildDate;
+  corbatext_tarray  ccsCols;        // Added 05/04/2000
+  corbatext_tarray  languages;
+  unsigned long     numDocs;
+  unsigned long     numWords;
+  unsigned long     numBytes;
+  corbatext_tmap    collectionMeta;
+  corbatext_tmap    format;
+  corbatext_tmap    building;
+  corbatext_t       httpdomain ;    // Added 27/07/2000
+  corbatext_t       httpprefix;     // Added 27/07/2000
+  corbatext_t       receptionist;
+};
+
+//
+// getDocument request
+//
+
+struct corbaDocRequest
+{ 
+  corbatext_t OID;
+  corbatext_t docType;
+  corbatext_t docFormat;
+};
+
+//
+// getDocument response
+//
+
+struct corbaDocResponse
+{ 
+  corbatext_t doc;
+};
+
+enum corbaFilterType
+{
+  booleanType,
+  integerType,
+  enumeratedType,
+  stringType
+};
+
+enum corbaFilterRepeatable
+{
+  onePerQuery,
+  onePerTerm,
+  nPerTerm
+};
+
+struct corbaFilterOption
+{
+  corbatext_t           name;
+  corbaFilterType       type;
+  corbaFilterRepeatable repeatable;
+  corbatext_t           defaultValue;
+  corbatext_tarray      validValues;
+};
+
+typedef sequence<corbaFilterOption> corbaFilterOptionList;
+
+struct corbaFilterOptionsResponse
+{
+  corbaFilterOptionList options;
+  corbatext_tarray      names;
+};
+
+//
+// structures for filter call
+//
+
+struct corbaOptionValue
+{
+  corbatext_t name;
+  corbatext_t value;
+};
+
+typedef sequence<corbaOptionValue> corbaOptionValue_array;
+
+struct corbaFilterRequest
+{ 
+  corbatext_t            filter;
+  corbaOptionValue_array filterOptions;
+  corbatext_tarray       docSet;
+  long                   filterResultOptions;
+  corbatext_t            requestParams;
+  corbatext_t            refParams;
+  corbatext_tset         fields;
+  boolean                getParents;
+};
+
+struct corbaTermInfo
+{
+  corbatext_t      term;
+  long             frequency;
+  corbatext_tarray matchTerms;
+};
+
+typedef sequence<corbaTermInfo> corbaTermInfo_array;
+
+struct corbaMetadataInfo
+{
+  corbatext_t      params;
+  boolean          isRef;
+  corbatext_tarray values;
+  long             id;
+  long             parentid; // dodge for avoiding pointers for the moment
+};
+
+typedef sequence<corbaMetadataInfo> corbaMetadataInfo_array;
+
+struct corbaMetadataInfo_map
+{ 
+  corbatext_tarray        names;
+  corbaMetadataInfo_array values;
+};
+
+typedef sequence<long> corbaDocFreq_array;
+
+struct corbaResultDocInfo
+{
+  corbatext_t             OID;
+  long                    resultNum;
+  long                    ranking;
+  long                    termsMatched;
+  long                    phraseMatched;
+  corbaDocFreq_array      docFreq;
+  corbaMetadataInfo_map   metadata;
+  corbatext_t             classifierMetadataType;    // Added 05/04/2000
+  long                    classifierMetadataOffset;  // Added 05/04/2000
+  corbaMetadataInfo_array metaparents;
+};
+
+typedef sequence<corbaResultDocInfo> corbaResultDocInfo_array;
+
+enum corbaIsApprox
+{
+  resultExact,
+  resultApprox,
+  resultMany
+};
+
+struct corbaFilterResponse
+{
+  long                     numDocs;
+  corbaIsApprox            isApprox;
+  corbaTermInfo_array      termInfo;
+  corbaResultDocInfo_array docInfo;
+};
+
+interface corbaiface
+{
+  boolean   initialise();
+  void      configure(in corbatext_t key, in corbatext_tarray cfgline);
+  void      collectionList(inout corbatext_tarray collist);
+  void      hasCollection(in corbatext_t corbaCollection, inout boolean has,
+		       inout corbaComError error);
+  boolean   ping(in corbatext_t collection, inout corbaComError error);
+  void      getDocument(in corbatext_t collection,
+			inout corbaDocRequest request, inout corbaDocResponse response,
+			inout corbaComError error);
+  void      getCollectInfo(in corbatext_t collection,
+			   inout corbaColInfoResponse response,
+			   inout corbaComError error);
+  void      getFilterInfo(in corbatext_t collection, 
+                          inout corbatext_tarray filterNames, 
+			  inout corbaComError error);
+  void      getFilterOptions(in corbatext_t collection,
+                             in corbatext_t option,
+                             inout corbaFilterOptionsResponse response,
+			     inout corbaComError error);
+  void      filter(in corbatext_t collection,
+		   in corbaFilterRequest request,
+                   inout corbaFilterResponse response,
+                   inout corbaComError error);
+};
+
+};
Index: /tags/start/java-client/org/nzdl/gsdl/SimpleClient.java
===================================================================
--- /tags/start/java-client/org/nzdl/gsdl/SimpleClient.java	(revision 13666)
+++ /tags/start/java-client/org/nzdl/gsdl/SimpleClient.java	(revision 13666)
@@ -0,0 +1,115 @@
+
+
+import java.util.*;
+import java.text.*; // for date processing
+import javax.swing.tree.*;
+import org.nzdl.service.*;
+
+
+public class SimpleClient {
+
+  public static final void main( String [] args ) {
+
+    NzdlService nzdl = new NzdlServiceImpl( args );
+
+    if (args.length < 3) {
+      System.err.println("WARNING: missing command line arguments. using defualts:");
+      System.err.println("usage: java <javaoptions> SimpleClient <collect> <xxx> <query>");
+      System.err.println("       <javaoptions> = options to the JVM ");
+      System.err.println("       <collect>     = the greenstone collection to use   (demo)");
+      System.err.println("       <xxx>         = a currently unused option          (xxx)");
+      System.err.println("       <query>       = the query to use on the collection (the)");
+      args = new  String [3];
+      args[0] = "demo";
+      args[1] = "xxx";
+      args[2] = "the";
+    }
+    
+    // extract some highlevel information on the collections on the server
+    // independent of the command line arguments passed in
+		
+    Set collectionSet = nzdl.getCollectionSet(); // set of strings of collection titles
+    System.out.println("Number of collections on the server: " + collectionSet.size());
+		
+    Iterator collectionSetIterator = collectionSet.iterator();
+    while (collectionSetIterator.hasNext() ) {
+      String collectionName = (String)collectionSetIterator.next(); // object -> String
+      NzdlCollectionInfo collectionInfo = nzdl.getCollectionInfo( collectionName );
+      // this next line should work but doesn't
+      System.out.println("Collection: " + collectionInfo.getName());
+      // so we revert to using the original string from the collectionSet
+      System.out.println("Collection: " + collectionName);  
+      if (nzdl.hasCollection(collectionName) ) {
+	System.out.println("\t" + "hasCollection(" + collectionName + ")" + " is true");
+	if (nzdl.pingCollection(collectionName) ) {
+	  System.out.println("\t" + "pingCollection(" + collectionName + ")" + " is true");		
+	  // these next statements make use of the NzdlCollection API  		 
+	  System.out.println("\t" + "Public: " + collectionInfo.isPublic());
+	  System.out.println("\t" + "Beta: " + collectionInfo.isBeta());
+	  int buildDate = collectionInfo.getBuildDate();
+	  //process buildDate into something sensible
+	  System.out.println("\t" + "Build Date: " + buildDate);
+	  System.out.println("\t" + "No. of Documents: " + collectionInfo.getNumOfDocs());
+	  System.out.println("\t" + "No. of Words: " + collectionInfo.getNumOfWords());
+	  System.out.println("\t" + "No. of Bytes: " + collectionInfo.getNumOfBytes()); 
+	}
+	else {
+	  System.out.println("\t" + "pingCollection(" + collectionName + ")" + " is false");
+	}
+      }
+      else
+	{ System.out.println("\t" + "hasCollection(" + collectionName + ")" + " is false"); }
+    } 
+		
+		
+		
+		
+    String collName = args[0];
+    NzdlCollectionInfo collInfo = nzdl.getCollectionInfo( collName );
+   
+    System.out.println("Searching collection: " + collName);
+		
+    int numResults = collInfo.getNumOfDocs(); // what precisely is this number ?
+    System.out.println("Collection " + collName + " suggests to get results in chunks of " + numResults + " hits" );
+    String method = args[1];
+    System.out.println("Search method: " + method);
+    String queryTerm = args[2];
+    System.out.println("Query Term: " + queryTerm);
+    String metaTag = "Title";
+		
+    System.out.println("Searching in '" + metaTag + "' metadata");
+
+    NzdlQuery query = new NzdlQuery( queryTerm );
+    // return the first numResults that match
+    //query.setEndResults( 15 );
+    // "-1" means consider all the documents that match
+    query.setMaxDocs( -1 );
+
+    NzdlRequest request = new NzdlRequest( query );
+    NzdlResponse response = new NzdlResponse( );
+    System.out.println("getting document IDs ... ");
+    nzdl.service( collName, request, response );
+
+    NzdlResultSet results = response.getResultSet();
+    List docIDs = results.getDocumentIDs();
+    System.out.println("Number of documents returned: " + docIDs.size());
+
+    System.out.println("getting '" + metaTag + "' meta data of documents ... ");
+    Map metaData = nzdl.getMetaData( collName, docIDs, metaTag );
+
+    for (ListIterator i = docIDs.listIterator(); i.hasNext(); ) {
+      String id = (String) i.next();
+      Set meta = (Set) metaData.get( id );
+      System.out.println(meta.toString()); 
+      System.out.println("getting document contents ... ");
+      String documentContents = nzdl.getDocument(collName, id);
+      System.out.println("got document contents. ");
+      System.out.println(" *************** START DOC " + id + " ***************"); 
+      System.out.println(documentContents);
+      System.out.println(" *************** END DOC " + id + " ***************"); 
+    }
+    
+  
+  } //main
+
+} // class
Index: /tags/start/java-client/org/nzdl/gsdl/service/NzdlCollectionInfo.java
===================================================================
--- /tags/start/java-client/org/nzdl/gsdl/service/NzdlCollectionInfo.java	(revision 13666)
+++ /tags/start/java-client/org/nzdl/gsdl/service/NzdlCollectionInfo.java	(revision 13666)
@@ -0,0 +1,55 @@
+
+package org.nzdl.service;
+
+/** gsdl corba stuff */
+import org.nzdl.corba.gsdlInterface.*;
+import org.nzdl.util.*;
+
+public class NzdlCollectionInfo extends Object {
+
+  /** */
+  private corbaColInfoResponse m_Info = null;
+
+  public NzdlCollectionInfo( corbaColInfoResponse _info ) {
+    m_Info = _info;
+  }
+
+  /** */
+  public String getName() {
+    return NzdlCorbaFactory.toString( m_Info.shoftInfo.name ) ;
+  }
+
+  public boolean isPublic() {
+    return m_Info.isPublic;
+  }
+
+  public boolean isBeta() {
+    return m_Info.isBeta;
+  }
+
+  public int getBuildDate() {
+    return m_Info.buildDate;
+  }
+
+  public int getNumOfDocs() {
+    return m_Info.numDocs;
+  }
+
+  public int getNumOfWords() {
+    return m_Info.numWords;
+  }
+
+  public int getNumOfBytes() {
+    return m_Info.numBytes;
+  }
+
+  /** */
+  public void print() {
+	/* daven@cs.waikato.ac.nz */
+	//System.out.println("Collection Information--------------");
+	//System.out.println("Collection Name = " + this.getName());
+	//System.out.println("Collection Name = " + m_info.getName());
+	
+  }
+
+}
Index: /tags/start/java-client/org/nzdl/gsdl/service/NzdlQuery.java
===================================================================
--- /tags/start/java-client/org/nzdl/gsdl/service/NzdlQuery.java	(revision 13666)
+++ /tags/start/java-client/org/nzdl/gsdl/service/NzdlQuery.java	(revision 13666)
@@ -0,0 +1,107 @@
+
+package org.nzdl.service;
+
+import java.util.*;
+
+import org.nzdl.util.NzdlConstants;
+
+public class NzdlQuery extends java.lang.Object {
+
+  /** */
+  private Map m_Options = null;
+
+  /** */
+
+  public NzdlQuery() {
+    m_Options = new HashMap();
+    setQueryTerm   ( NzdlConstants.DEFAULT_QUERY_TERM );
+    setQueryType   ( NzdlConstants.DEFAULT_QUERY_TYPE );
+    setCaseFolding ( NzdlConstants.DEFAULT_CASE_FOLDING );
+    setStemming    ( NzdlConstants.DEFAULT_STEMMING );
+    setStartResults( NzdlConstants.DEFAULT_START_RESULTS );
+    setEndResults  ( NzdlConstants.DEFAULT_END_RESULTS );
+    setMaxDocs     ( NzdlConstants.DEFAULT_MAX_DOCS );
+  }
+
+  public NzdlQuery( String _term ) {
+    m_Options = new HashMap();
+    setQueryTerm   ( _term );
+    setQueryType   ( NzdlConstants.DEFAULT_QUERY_TYPE );
+    setCaseFolding ( NzdlConstants.DEFAULT_CASE_FOLDING );
+    setStemming    ( NzdlConstants.DEFAULT_STEMMING );
+    setStartResults( NzdlConstants.DEFAULT_START_RESULTS );
+    setEndResults  ( NzdlConstants.DEFAULT_END_RESULTS );
+    setMaxDocs     ( NzdlConstants.DEFAULT_MAX_DOCS );
+  }
+
+  /** */
+
+  public void setQueryTerm(String _term) {
+    m_Options.put("Term", _term);
+  }
+
+  public void setQueryType(String _type) {
+    m_Options.put("QueryType", _type);
+  }
+
+  public void setCaseFolding(String _case) {
+    m_Options.put("CaseFold", _case);
+  }
+
+  public void setStemming(String _stem) {
+    m_Options.put("Stem", _stem);
+  }
+
+  public void setStartResults(int _start) {
+    m_Options.put("StartResults", new Integer(_start));
+  }
+
+  public void setEndResults(int _end) {
+    m_Options.put("EndResults", new Integer(_end));
+  }
+
+  public void setMaxDocs(int _max) {
+    m_Options.put("Maxdocs", new Integer(_max));
+  }
+
+  /** */
+
+  public String getQueryType() {
+    return (String)m_Options.get("QueryType");
+  }
+
+  public String getQueryTerm() {
+    return (String)m_Options.get("Term");
+  }
+
+  public String getCaseFolding() {
+    return (String)m_Options.get("CaseFold");
+  }
+
+  public String getStemming() {
+    return (String)m_Options.get("Stem");
+  }
+
+  public int getStartResults() {
+    return ((Integer) m_Options.get("StartResults")).intValue();
+  }
+
+  public int getEndResults() {
+    return ((Integer) m_Options.get("EndResults")).intValue();
+  }
+
+  public int getMaxDocs() {
+    return ((Integer) m_Options.get("Maxdocs")).intValue();
+  }
+
+  /** */
+
+  public Set queryKeySet() {
+    return m_Options.keySet();
+  }
+
+  public Collection queryValues() {
+    return m_Options.values();
+  }
+
+}
Index: /tags/start/java-client/org/nzdl/gsdl/service/NzdlQueryHit.java
===================================================================
--- /tags/start/java-client/org/nzdl/gsdl/service/NzdlQueryHit.java	(revision 13666)
+++ /tags/start/java-client/org/nzdl/gsdl/service/NzdlQueryHit.java	(revision 13666)
@@ -0,0 +1,87 @@
+
+package org.nzdl.service;
+
+import java.util.*;
+
+public class NzdlQueryHit extends java.lang.Object {
+
+  private String m_docID = null;
+  private int    m_resultNum = -1;   // I don't actually know what it means !!!
+  private int    m_ranking = -1;
+  private int    m_numTermsMatched = -1;
+  private int    m_numPhrasesMatched = -1;
+  private int [] m_docFreqs = null; // I don't actually know what it means !!!
+  /*
+   * The key in the map will be the metaData Tag
+   * The value for the key will be a Set of strings
+   * Ex: key = "Author", value = {A. Mahoui, S. Franks}
+   */
+  private Map m_metaData = null;
+
+  /** */
+
+  public void setDocumentID( String _docID ) {
+    m_docID = _docID;
+  }
+
+  public void setRanking( int _ranking ) {
+    m_ranking = _ranking;
+  }
+
+  public void setResultNumber( int _resultNum ) {
+    m_resultNum = _resultNum;
+  }
+
+  public void setNumOfTermsMatched( int _numTermsMatched ) {
+    m_numTermsMatched = _numTermsMatched;
+  }
+
+  public void setNumOfPhrasesMatched( int _numPhrasesMatched ) {
+    m_numPhrasesMatched = _numPhrasesMatched;
+  }
+
+  public void setMetaData( Map _metaData ) {
+    m_metaData = _metaData;
+  }
+
+  /** */
+
+  public String getDocumentID() {
+    return m_docID;
+  }
+
+  public int getRanking() {
+    return m_ranking;
+  }
+
+  public int getResultNumber() {
+    return m_resultNum;
+  }
+
+  public int getNumOfTermsMatched() {
+    return m_numTermsMatched;
+  }
+
+  public int getNumOfPhrasesMatched() {
+    return m_numPhrasesMatched;
+  }
+
+  public Map getMetaData() {
+    return m_metaData;
+  }
+
+  /** returns a set of String objects */
+  public Set getMetaDataValues( String _metaTag ) {
+    return (Set) m_metaData.get( _metaTag );
+  }
+
+  /** returns a set of key (String) objects */
+  public Set getMetaDataTags() {
+    return m_metaData.keySet();
+  }
+
+  public Collection getMetaDataValues() {
+    return m_metaData.values();
+  }
+
+}
Index: /tags/start/java-client/org/nzdl/gsdl/service/NzdlRequest.java
===================================================================
--- /tags/start/java-client/org/nzdl/gsdl/service/NzdlRequest.java	(revision 13666)
+++ /tags/start/java-client/org/nzdl/gsdl/service/NzdlRequest.java	(revision 13666)
@@ -0,0 +1,38 @@
+
+package org.nzdl.service;
+
+import org.nzdl.corba.gsdlInterface.*;
+import org.nzdl.util.*;
+import java.util.*;
+
+public class NzdlRequest extends java.lang.Object {
+
+  /** */
+
+  private corbaFilterRequest m_Filter = null;
+
+  /** */
+
+  public NzdlRequest( NzdlQuery _query ) {
+    m_Filter = NzdlCorbaFactory.createQueryFilterRequest( _query );
+  }
+
+  public NzdlRequest( String _docID ) {
+    m_Filter = NzdlCorbaFactory.createBrowseFilterRequest( _docID );
+  }
+
+  public NzdlRequest( String _docID, String _metaTag ) {
+    m_Filter = NzdlCorbaFactory.createMetaDataFilterRequest( _docID, _metaTag );
+  }
+
+  public NzdlRequest( List _docIDs, String _metaTag ) {
+    m_Filter = NzdlCorbaFactory.createMetaDataFilterRequest( _docIDs, _metaTag );
+  }
+
+  /** */
+
+  public corbaFilterRequest getFilter() {
+    return m_Filter;
+  }
+  
+}
Index: /tags/start/java-client/org/nzdl/gsdl/service/NzdlResponse.java
===================================================================
--- /tags/start/java-client/org/nzdl/gsdl/service/NzdlResponse.java	(revision 13666)
+++ /tags/start/java-client/org/nzdl/gsdl/service/NzdlResponse.java	(revision 13666)
@@ -0,0 +1,136 @@
+
+package org.nzdl.service;
+
+import java.util.*;
+
+import org.nzdl.service.*;
+import org.nzdl.corba.gsdlInterface.*;
+import org.nzdl.util.*;
+
+public class NzdlResponse extends java.lang.Object {
+
+  /** */
+
+  private corbaFilterResponseHolder m_responseHolder = null;
+  private corbaFilterResponse m_response = null;
+  private NzdlResultSet m_resultSet = null;
+  private Map m_frequencies = null;
+  private List m_queryTerms = null;
+
+  /** */
+
+  public NzdlResponse( ) {
+    m_responseHolder = NzdlCorbaFactory.createFilterResponseHolder();
+  }
+
+  public corbaFilterResponseHolder getHolder() {
+    return m_responseHolder;
+  }
+
+  public NzdlResultSet getResultSet() {
+    if ( m_resultSet == null ) {
+      parseResponse();
+    }
+    return m_resultSet;
+  }
+
+  /*
+    This is a short expansion of the content of a corbaFilterResponse object.
+    Some of the fields are not that clear to me (those with ?????). Therefore
+    I am ignoring some of them for the time being.
+
+    o Number of Documents
+    o Type of results
+    o Info on each of the search terms used:
+
+      o Term string
+      o Term frequency
+      o Matched terms ?????
+
+    o Info on each of the result docs returned:
+
+      o Document ID
+      o Result number ?????
+      o Number of terms matched in this document
+      o Number of phrases matched in this document
+      o Array of document frequencies ?????
+      o Info on the metadata:
+
+         o Array of the names of the meta tags
+         o Info on each of the meta data:
+
+           o Params string ?????
+           o Is the metadata a reference ?????
+           o Array of values
+	   o Id ?????
+	   o Parentid ?????
+  */
+
+  private void parseResponse () {
+    m_response = m_responseHolder.value;
+    m_resultSet = new NzdlResultSet();
+    m_resultSet.setNumOfDocs( m_response.numDocs );
+    m_resultSet.setResultType( m_response.isApprox.value() );
+    /** HAS SIDE EFFECT ! */
+    parseTermsInfo( m_response.termInfo );
+    /** HAS SIDE EFFECT ! */
+    parseDocsInfo( m_response.docInfo );
+  }
+
+  private void parseTermsInfo( corbaTermInfo [] _termsInfo ) {
+    String term = null;
+    m_frequencies = new HashMap();
+    m_queryTerms = new ArrayList();
+    for (int i=0; i<_termsInfo.length; i++) {
+      term = NzdlCorbaFactory.toString(_termsInfo[i].term);
+      m_queryTerms.add( term );
+      m_frequencies.put( term, new Integer(_termsInfo[i].frequency) );
+    }
+    m_resultSet.setQueryTerms( m_queryTerms );
+    m_resultSet.setTermFrequencies( m_frequencies );
+  }
+
+  private void parseDocsInfo( corbaResultDocInfo [] _docsInfo ) {
+    NzdlQueryHit queryHit = null;
+    //System.err.println("Size of DocsInfo: " + _docsInfo.length);
+    for (int i=0; i < _docsInfo.length; i++) {
+      queryHit = new NzdlQueryHit();
+      queryHit.setDocumentID( NzdlCorbaFactory.toString(_docsInfo[i].OID) );
+      queryHit.setResultNumber( _docsInfo[i].resultNum );
+      queryHit.setRanking( _docsInfo[i].ranking );
+      queryHit.setNumOfTermsMatched( _docsInfo[i].termsMatched );
+      queryHit.setNumOfPhrasesMatched( _docsInfo[i].phraseMatched );
+      /** TO DO: extract corbaDocFreq_array value */
+      queryHit.setMetaData( parseMetaData(_docsInfo[i].metadata) );
+      // add to the result set
+      m_resultSet.add( queryHit ) ;
+    }
+  }
+
+  private Map parseMetaData( corbaMetadataInfo_map _metaData ) {
+    /*
+     * The key in the map will be the metaData Tag
+     * The value for the key will be a Set of strings
+     * Ex: key = "Author", value = {A. Mahoui, S. Franks}
+     */
+    Map metaData = new HashMap();
+    // For each meta tag can be associated more than one value (example above)
+    Set metaTagValues = new HashSet();
+    corbaMetadataInfo c_metaDataInfo = null;
+
+    for (int i=0; i < _metaData.names.length; i++) {
+      // one meta data at a time please ...
+      c_metaDataInfo = _metaData.values[i];
+      // get the set of values associated with this meta tag ...
+      for (int j=0; j < c_metaDataInfo.values.length; j++) {
+	metaTagValues.add( NzdlCorbaFactory.toString(c_metaDataInfo.values[j]) );
+      }
+      // map the meta tag with its set of values ...
+      metaData.put( NzdlCorbaFactory.toString(_metaData.names[i]), metaTagValues);
+    }
+    return metaData;
+  }
+
+}
+
+
Index: /tags/start/java-client/org/nzdl/gsdl/service/NzdlResultSet.java
===================================================================
--- /tags/start/java-client/org/nzdl/gsdl/service/NzdlResultSet.java	(revision 13666)
+++ /tags/start/java-client/org/nzdl/gsdl/service/NzdlResultSet.java	(revision 13666)
@@ -0,0 +1,125 @@
+
+package org.nzdl.service;
+
+import java.util.*;
+
+public class NzdlResultSet extends java.lang.Object {
+
+  private List m_resultSet   = null;
+  private int m_numDocs     = -1;
+  private int m_resultType  = -1;
+  private List m_queryTerms  = null;
+  private List m_docIDs = null;
+  /** the key is the query term, the value its frequency */
+  private Map m_frequencies = null;
+  /** 
+   * the key is the docID, the value is the doc corresponding 
+   * meta data which is also a Map where the key is the meta tag
+   * and the value is a set of values for that tag
+   */
+  private Map m_docToMetaDataMap = null;
+
+  /** */
+  
+  public NzdlResultSet() {
+    m_resultSet = new ArrayList();
+    m_docToMetaDataMap = new HashMap();
+    m_docIDs = new ArrayList();
+  }
+
+  /** */
+
+  public void add( NzdlQueryHit _hit ) {
+    m_resultSet.add( _hit ) ;
+    String id = _hit.getDocumentID();
+    m_docIDs.add( id );
+    m_docToMetaDataMap.put( id, _hit.getMetaData() );
+  }
+
+  public void setNumOfDocs( int _num ) {
+    m_numDocs = _num;
+  }
+
+  public void setResultType( int _type ) {
+    m_resultType = _type;
+  }
+
+  public void setQueryTerms( List _terms ) {
+    m_queryTerms = _terms;
+  }
+
+//    public void setTermFrequency( String _term, int _freq ) {
+//      m_frequencies.put( _term, new Integer(_freq) );
+//    }
+
+  public void setTermFrequencies( Map _freqs ) {
+    m_frequencies = _freqs;
+  }
+
+  /** */
+
+  public int getNumOfDocs() {
+    return m_numDocs;
+  }
+
+  public int getResultType() {
+    return m_resultType;
+  }
+
+  public List getQueryTerms() {
+    return m_queryTerms;
+  }
+  
+  public Map getTermFrequencies() {
+    return m_frequencies;
+  }
+  
+//    public int getTermFrequency( String _term ) {
+//      return ((Integer)m_frequencies.get(_term)).intValue();
+//    }
+
+//    public List getDocumentIDs() {
+//      NzdlQueryHit hit = null;
+//      //Set docIDs = new HashSet();
+//      List docIDs = new ArrayList();
+//      for (ListIterator itr = m_resultSet.listIterator(); itr.hasNext(); ) {
+//        hit = (NzdlQueryHit) itr.next();
+//        docIDs.add( hit.getDocumentID() );
+//      }
+//      return docIDs;
+//    }
+
+    public List getDocumentIDs() {
+      return m_docIDs;
+    }
+
+//    public Set getMetaData( String _docID, String _metaTag ) {
+//      NzdlQueryHit hit = null;
+//      for (ListIterator itr = m_resultSet.listIterator(); itr.hasNext(); ) {
+//        hit = (NzdlQueryHit) itr.next();
+//        if ( _docID.equals( hit.getDocumentID() ) ) {
+//  	return hit.getMetaDataValues( _metaTag );
+//        }
+//      }
+//      return null;
+//    }
+
+  public Set getMetaData( String _docID, String _metaTag ) {
+    Map metaData = (Map) m_docToMetaDataMap.get( _docID );
+    return (Set) metaData.get( _metaTag );
+  }
+
+  public Map getMetaData( String _metaTag ) {
+    Map metaData = new HashMap();
+    for (ListIterator itr = m_resultSet.listIterator(); itr.hasNext(); ) {
+      NzdlQueryHit hit = (NzdlQueryHit) itr.next();
+      metaData.put( hit.getDocumentID(), hit.getMetaDataValues(_metaTag) );
+    }
+    return metaData;
+  }
+
+  public Map getAllMetaData( ) {
+    return m_docToMetaDataMap;
+  }
+
+}
Index: /tags/start/java-client/org/nzdl/gsdl/service/NzdlService.java
===================================================================
--- /tags/start/java-client/org/nzdl/gsdl/service/NzdlService.java	(revision 13666)
+++ /tags/start/java-client/org/nzdl/gsdl/service/NzdlService.java	(revision 13666)
@@ -0,0 +1,38 @@
+
+package org.nzdl.service;
+
+import java.util.*;
+
+public interface NzdlService {
+
+  public void configure( String key, Set values );
+  public Set getCollectionSet( );
+  public boolean hasCollection( String collectionName );
+  public boolean pingCollection( String collectionName );
+  public NzdlCollectionInfo getCollectionInfo( String collectionName );
+  public Set getFilterSet( String collectionName );
+  public Set getMetaTagSet( String collectionName );
+  public String getDocument( String collectionName, String documentID );
+  public Set getMetaData( String collectionName, String documentID, String metaTag );
+  public Map getMetaData( String collectionName, List documentIDs, String metaTag );
+  public void service( String collectionName, NzdlRequest request, NzdlResponse response );
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: /tags/start/java-client/org/nzdl/gsdl/service/NzdlServiceImpl.java
===================================================================
--- /tags/start/java-client/org/nzdl/gsdl/service/NzdlServiceImpl.java	(revision 13666)
+++ /tags/start/java-client/org/nzdl/gsdl/service/NzdlServiceImpl.java	(revision 13666)
@@ -0,0 +1,166 @@
+
+package org.nzdl.service;
+
+import java.io.*;
+import java.util.*;
+/** jdk 1.3 orb */
+import org.omg.CORBA.*;
+/** gsdl corba stuff */
+import org.nzdl.corba.gsdlInterface.*;
+import org.nzdl.util.*;
+
+public class NzdlServiceImpl extends java.lang.Object implements NzdlService {
+
+  private corbaiface m_nzdlServer = null;
+
+  public NzdlServiceImpl( String [] _args ) {
+    try {
+	System.err.println("before ORB.init");
+      // getting a reference to the remote NZDL server
+      org.omg.CORBA.ORB orb = ORB.init( _args, null );
+      System.err.println("after ORB.init - before IOR");
+      String ior = getIorKey();
+      System.err.println("ior = " + ior);
+	System.err.println("after IOR");
+	org.omg.CORBA.Object obj = orb.string_to_object(ior) ;
+      System.err.println("after org stringtoobject");
+	m_nzdlServer = corbaifaceHelper.narrow(obj);
+	System.err.println("after .narrow");
+      // basic setup
+      if (m_nzdlServer.initialise()) {
+	System.err.println("Nzdl init ... YES");
+      }
+      else {
+	System.err.println("Nzdl init ... NO");
+	System.err.println("Aborting service ...");
+	//System.exit(1);
+      }
+    } catch (Exception e) {
+      System.err.println("Error in service init:\n" + e) ;
+      System.err.println("Aborting service ...");
+      System.exit(1);
+    }
+    System.err.println("Service init ... YES");
+  }
+  
+  public void configure( String _key, Set _values ) {
+    m_nzdlServer.configure( NzdlCorbaFactory.toCorbaText( _key ),
+			    NzdlCorbaFactory.toCorbaTextArray( _values ));
+  }
+  
+  public Set getCollectionSet( ) {
+    corbatext_tarrayHolder c_collSet = NzdlCorbaFactory.createCorbaTextArrayHolder();
+    m_nzdlServer.collectionList(c_collSet);
+    Set collSet = new HashSet();
+    for (int i=0; i<c_collSet.value.length; i++) {
+      collSet.add( NzdlCorbaFactory.toString( c_collSet.value[i] ) );
+    }
+    return collSet ;
+  }
+  
+  public boolean hasCollection( String _name ) {
+    corbaComErrorHolder c_err = NzdlCorbaFactory.createComErrorHolder();
+    org.omg.CORBA.BooleanHolder c_has = new org.omg.CORBA.BooleanHolder();
+    m_nzdlServer.hasCollection( NzdlCorbaFactory.toCorbaText(_name), c_has, c_err );
+    if (c_err.value.value() != 0)
+      System.err.println("hasCollection error " + c_err.value.value());
+    return c_has.value;
+  }
+  
+  public boolean pingCollection( String _name ) {
+    corbaComErrorHolder c_err = NzdlCorbaFactory.createComErrorHolder();
+    boolean result  = m_nzdlServer.ping( NzdlCorbaFactory.toCorbaText(_name), c_err );
+    if (c_err.value.value() != 0)
+      System.err.println("pingCollection() error " + c_err.value.value());
+    return result;
+  }
+  
+  public NzdlCollectionInfo getCollectionInfo( String _name ) {
+    corbaComErrorHolder c_err = NzdlCorbaFactory.createComErrorHolder();
+    corbaColInfoResponseHolder c_info = NzdlCorbaFactory.createColInfoResponseHolder();
+    m_nzdlServer.getCollectInfo( NzdlCorbaFactory.toCorbaText(_name), c_info, c_err );
+    if (c_err.value.value() != 0)
+      System.err.println("getCollectionInfo() error " + c_err.value.value());
+    return new NzdlCollectionInfo( c_info.value );
+  }
+
+  public Set getFilterSet( String _name ) {
+    System.err.println("TO BE IMPLEMENTED !!!");
+    return null ;
+  }
+
+  public Set getMetaTagSet( String _name ) {
+    System.err.println("TO BE IMPLEMENTED: DON'T KNOW HOW YET !!!");
+    return null ;
+  }
+
+  public String getDocument( String _name, String _docID ) {
+    corbatext_t c_name = NzdlCorbaFactory.toCorbaText( _name );
+    corbaDocRequestHolder c_request = NzdlCorbaFactory.createDocRequestHolder( _docID );
+    corbaDocResponseHolder c_response = NzdlCorbaFactory.createDocResponseHolder( );
+    corbaComErrorHolder c_err = NzdlCorbaFactory.createComErrorHolder();
+    m_nzdlServer.getDocument( c_name, c_request, c_response, c_err );
+    if (c_err.value.value() != 0)
+      System.err.println("getDocument() error " + c_err.value.value());
+    return NzdlCorbaFactory.toString( c_response.value.doc );
+  }
+
+  public Set getMetaData( String _name, String _docID, String _metaTag ) {
+    NzdlRequest request  = new NzdlRequest( _docID, _metaTag );
+    NzdlResponse response = new NzdlResponse( );
+    service( _name, request, response );
+    NzdlResultSet resultSet = response.getResultSet();
+    /**
+     * Because a result set may contain several hits, we only return
+     * the set of metadata values of the specifed meta tag for the
+     * specified document ID.
+     */
+    return resultSet.getMetaData( _docID, _metaTag );
+  }
+
+  public Map getMetaData( String _name, List _docIDs, String _metaTag ) {
+    NzdlRequest request  = new NzdlRequest( _docIDs, _metaTag );
+    NzdlResponse response = new NzdlResponse( );
+    service( _name, request, response );
+    NzdlResultSet resultSet = response.getResultSet();
+    //return resultSet.getMetaData( _docID, _metaTag );
+    return resultSet.getMetaData( _metaTag );
+    //return resultSet.getAllMetaData( );
+  }
+
+  public void service( String _name, NzdlRequest _request, NzdlResponse _response ) {    
+    corbatext_t c_name = NzdlCorbaFactory.toCorbaText( _name );
+    corbaComErrorHolder c_err = NzdlCorbaFactory.createComErrorHolder();
+    m_nzdlServer.filter( c_name, _request.getFilter(), _response.getHolder(), c_err );
+    if (c_err.value.value() != 0)
+      System.err.println("service() error " + c_err.value.value());
+  }
+
+  private String getIorKey() {
+    String ior = null;
+    try  {
+      LineNumberReader input
+	= new LineNumberReader(new FileReader("/tmp/localcorba.objid"));
+      ior = input.readLine();
+    } 
+    catch (java.io.IOException e) { 
+      System.err.println("Error reading IOR key:\n" + e);
+      System.err.println("Aborting service...");
+      System.exit(1);
+    }
+    return ior;
+  }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
Index: /tags/start/java-client/org/nzdl/gsdl/util/NzdlConstants.java
===================================================================
--- /tags/start/java-client/org/nzdl/gsdl/util/NzdlConstants.java	(revision 13666)
+++ /tags/start/java-client/org/nzdl/gsdl/util/NzdlConstants.java	(revision 13666)
@@ -0,0 +1,41 @@
+
+package org.nzdl.util;
+
+
+public interface NzdlConstants {
+
+  String DEFAULT_QUERY_TERM   = "";
+  String DEFAULT_QUERY_TYPE   = "ranked";
+  String DEFAULT_CASE_FOLDING = "true";
+  String DEFAULT_STEMMING     = "false";
+
+  int    DEFAULT_START_RESULTS = 1;
+  int    DEFAULT_END_RESULTS   = 10;
+  int    DEFAULT_MAX_DOCS      = 200;
+
+/* these appear to have been generated by 
+the idlj compiler but not any more - so 
+they are are being placed here */
+
+public static final int FRtermFreq = 1;
+public static final int FRmatchterms = 2;
+public static final int FROID = 4 ;
+public static final int FRsubcol = 8;
+public static final int FRranking = 16;
+public static final int FRdocFreq = 32;
+public static final int FRmetadata = 64;
+public static final int FRfullTextBrowse = 128;
+
+/*
+#define FRtermFreq   1
+#define FRmatchTerms 2
+#define FROID        4
+#define FRsubCol     8
+#define FRranking    16
+#define FRdocFreq    32
+#define FRmetadata   64
+// used to indicate a full text browse query for mgpp
+#define FRfullTextBrowse  128
+*/
+
+}
Index: /tags/start/java-client/org/nzdl/gsdl/util/NzdlCorbaFactory.java
===================================================================
--- /tags/start/java-client/org/nzdl/gsdl/util/NzdlCorbaFactory.java	(revision 13666)
+++ /tags/start/java-client/org/nzdl/gsdl/util/NzdlCorbaFactory.java	(revision 13666)
@@ -0,0 +1,251 @@
+
+package org.nzdl.util;
+
+import java.util.*;
+import org.nzdl.service.NzdlQuery;
+import org.nzdl.corba.gsdlInterface.*;
+import org.nzdl.util.NzdlConstants;
+
+public final class NzdlCorbaFactory {
+
+
+  private NzdlCorbaFactory() {}
+
+  public static corbatext_t toCorbaText(String _text) {
+    int len = _text.length();
+    short[] shorts = new short[len];
+    for (int i=0; i<len; i++) {
+      shorts[i] = (short)_text.charAt(i);
+    }
+    short encoding = 0;
+    corbatext_t corba_t = new corbatext_t(shorts, encoding, len);
+    return corba_t;
+  }
+
+  public static String toString(corbatext_t _text) {
+    //    System.out.println("NzdlCorbaFactory.toString() called length = " + _text.text.length +
+    //		       " ecnoding = " + _text.encoding +
+    //		       " reported length = " + _text.length);
+    StringBuffer text = new StringBuffer(1000);
+    for (int j=0; j<_text.text.length; j++) {
+      text.append((char)_text.text[j]);
+    }
+    return text.toString();
+  }
+
+  public static corbaComErrorHolder createComErrorHolder() {
+    corbaComErrorHolder err
+      = new corbaComErrorHolder( corbaComError.from_int(0) );    
+    return err;
+  }
+
+  public static corbatext_tarrayHolder createCorbaTextArrayHolder() {
+    corbatext_t [] array = {};
+    corbatext_tarrayHolder arrayHolder = new corbatext_tarrayHolder( array );
+    return arrayHolder;
+  }
+
+  public static corbatext_t []  toCorbaTextArray( Set _configLines ) {
+    Object [] lines = _configLines.toArray();
+    corbatext_t [] array = new corbatext_t[ lines.length ];
+    for (int i=0; i<lines.length; i++) {
+      array[i] = toCorbaText( (String)lines[i] );
+    }
+    return array;
+  }
+
+  public static corbaColInfoResponseHolder createColInfoResponseHolder() {
+    corbaShortColInfo shortInfo = new corbaShortColInfo();
+    shortInfo.name = toCorbaText("");
+    shortInfo.host = toCorbaText("");
+    corbaColInfoResponse response = new corbaColInfoResponse();
+    response.shoftInfo = shortInfo; // shoft !! typo in corba interface !!
+    response.isPublic  = false;
+    response.isBeta    = false;
+    response.buildDate = 0;
+    response.ccsCols   = new corbatext_t[0];
+    response.languages = new corbatext_t[0];
+    response.numDocs   = 0;
+    response.numWords  = 0;
+    response.numBytes  = 0;
+    response.collectionMeta = new corbatext_tmap(new corbatext_t[0],new corbatext_t[0]);
+    response.format         = new corbatext_tmap(new corbatext_t[0],new corbatext_t[0]);
+    response.building       = new corbatext_tmap(new corbatext_t[0],new corbatext_t[0]);
+    response.httpdomain   = toCorbaText("");
+    response.httpprefix   = toCorbaText("");
+    response.receptionist = toCorbaText("");
+    corbaColInfoResponseHolder responseHolder 
+      = new corbaColInfoResponseHolder(response);
+    return responseHolder;
+  }
+
+  public static corbaFilterRequest 
+    createQueryFilterRequest( String _term, String _type, int _numOfHits ) {
+    return createQueryFilterRequest( _term,
+				     _type,
+				     NzdlConstants.DEFAULT_CASE_FOLDING,
+				     NzdlConstants.DEFAULT_STEMMING,
+				     String.valueOf(NzdlConstants.DEFAULT_START_RESULTS),
+				     String.valueOf(_numOfHits),
+				     String.valueOf(NzdlConstants.DEFAULT_MAX_DOCS)
+				     );
+  }
+
+  public static corbaFilterRequest 
+    createQueryFilterRequest( NzdlQuery _query ) {
+    return createQueryFilterRequest( _query.getQueryTerm(),
+				     _query.getQueryType(),
+				     _query.getCaseFolding(),
+				     _query.getStemming(),
+				     String.valueOf(_query.getStartResults()),
+				     String.valueOf(_query.getEndResults()),
+				     String.valueOf(_query.getMaxDocs())
+				     );
+  }
+
+  public static corbaFilterRequest 
+    createQueryFilterRequest( String _term, String _type,     String _case, 
+			      String _stem, String _startHit, String _endHit, String _maxDocs ) {
+
+    corbaFilterRequest queryFilter = new corbaFilterRequest();
+    queryFilter.filter        = toCorbaText("QueryFilter");
+
+    queryFilter.filterOptions = new corbaOptionValue[8];
+    queryFilter.filterOptions[0] 
+      = new corbaOptionValue(toCorbaText("Term"),
+			     toCorbaText(_term));
+    queryFilter.filterOptions[1] 
+      = new corbaOptionValue(toCorbaText("QueryType"),
+			     toCorbaText(_type));
+    queryFilter.filterOptions[2] 
+      = new corbaOptionValue(toCorbaText("Casefold"),
+			     toCorbaText(_case));
+    queryFilter.filterOptions[3] 
+      = new corbaOptionValue(toCorbaText("Stem"),
+			     toCorbaText(_stem));
+    queryFilter.filterOptions[4] 
+      = new corbaOptionValue(toCorbaText("StartResults"),
+			     toCorbaText(_startHit));
+    queryFilter.filterOptions[5] 
+      = new corbaOptionValue(toCorbaText("EndResults"),
+			     toCorbaText(_endHit));
+    queryFilter.filterOptions[6] 
+      = new corbaOptionValue(toCorbaText("Maxdocs"),
+			     toCorbaText(_maxDocs));
+
+      queryFilter.filterOptions[7] 
+        = new corbaOptionValue(toCorbaText("MatchMode"),
+  			     toCorbaText("all"));
+
+    queryFilter.docSet        = new corbatext_t[0];
+    int resultOptions = NzdlConstants.FROID|NzdlConstants.FRtermFreq|NzdlConstants.FRranking;
+    queryFilter.filterResultOptions = resultOptions;
+    queryFilter.requestParams = toCorbaText("");
+    queryFilter.refParams     = toCorbaText("");
+    queryFilter.fields        = new corbatext_t[0];
+    queryFilter.getParents    = false;
+    return queryFilter;
+  }
+  
+  public static corbaFilterRequest createBrowseFilterRequest(String _docID, String _metaTag) {
+
+    corbaFilterRequest browseFilter = new corbaFilterRequest();
+    browseFilter.filter        = toCorbaText("BrowseFilter");
+
+    browseFilter.filterOptions = new corbaOptionValue[1];
+    browseFilter.filterOptions[0] 
+      = new corbaOptionValue(toCorbaText("ParentNode"),
+			     toCorbaText(_docID));
+
+    browseFilter.docSet        = new corbatext_t[0];
+    int resultOptions = NzdlConstants.FROID|NzdlConstants.FRmetadata;
+    browseFilter.filterResultOptions = resultOptions;
+    browseFilter.requestParams = toCorbaText("");
+    browseFilter.refParams     = toCorbaText("");
+    browseFilter.fields        = new corbatext_t[1];
+    browseFilter.fields[0]     = toCorbaText(_metaTag);
+    browseFilter.getParents    = false;
+    return browseFilter;
+  }
+
+  public static corbaFilterRequest createBrowseFilterRequest( String _docID ) {
+    corbaFilterRequest browseFilter = new corbaFilterRequest();
+    browseFilter.filter        = toCorbaText("BrowseFilter");
+    browseFilter.filterOptions = new corbaOptionValue[1];
+    browseFilter.filterOptions[0] 
+      = new corbaOptionValue(toCorbaText("ParentNode"),
+			     toCorbaText(_docID));
+    browseFilter.docSet        = new corbatext_t[0];
+    int resultOptions = NzdlConstants.FROID;
+    browseFilter.filterResultOptions = resultOptions;
+    browseFilter.requestParams = toCorbaText("");
+    browseFilter.refParams     = toCorbaText("");
+    browseFilter.fields        = new corbatext_t[0];
+    browseFilter.getParents    = false;
+    return browseFilter;
+  }
+
+  public static corbaFilterRequest createMetaDataFilterRequest( String _docID, String _metaTag ) {
+    corbaFilterRequest nullFilter = new corbaFilterRequest();
+    nullFilter.filter        = toCorbaText("NullFilter");
+    nullFilter.filterOptions = new corbaOptionValue[0];
+    nullFilter.docSet        = new corbatext_t[1];
+    nullFilter.docSet[0]     = toCorbaText(_docID);
+    int resultOptions = NzdlConstants.FRmetadata;
+    nullFilter.filterResultOptions = resultOptions;
+    nullFilter.requestParams = toCorbaText("");
+    nullFilter.refParams     = toCorbaText("");
+    nullFilter.fields        = new corbatext_t[1];
+    nullFilter.fields[0]     = toCorbaText(_metaTag);
+    nullFilter.getParents    = false;
+    return nullFilter;
+  }
+
+  public static corbaFilterRequest createMetaDataFilterRequest( List _docIDs, String _metaTag ) {
+    corbaFilterRequest nullFilter = new corbaFilterRequest();
+    nullFilter.filter = toCorbaText("NullFilter");
+    nullFilter.filterOptions = new corbaOptionValue[0];
+    // we will request the meta data for all documents in _docIDs set
+    nullFilter.docSet = new corbatext_t[_docIDs.size()];
+    int i=0;
+    for (ListIterator itr = _docIDs.listIterator(); itr.hasNext(); ) {
+      nullFilter.docSet[i] = toCorbaText( (String)itr.next() );
+      i++;
+    }
+    int resultOptions = NzdlConstants.FRmetadata;
+    nullFilter.filterResultOptions = resultOptions;
+    nullFilter.requestParams = toCorbaText("");
+    nullFilter.refParams     = toCorbaText("");
+    nullFilter.fields        = new corbatext_t[1];
+    // this is the meta (_metaTag) data we need
+    nullFilter.fields[0]     = toCorbaText(_metaTag);
+    nullFilter.getParents    = false;
+    return nullFilter;
+  }
+
+  public static corbaFilterResponseHolder createFilterResponseHolder() {
+    corbaFilterResponse responseFilter = new corbaFilterResponse();
+    responseFilter.numDocs = 0;
+    responseFilter.isApprox = corbaIsApprox.from_int(0);
+    responseFilter.termInfo = new corbaTermInfo[0];
+    responseFilter.docInfo = new corbaResultDocInfo[0];
+    return new corbaFilterResponseHolder(responseFilter);
+  }
+
+  public static corbaDocRequestHolder createDocRequestHolder( String _docID ) {
+    corbaDocRequest docRequest 
+      = new corbaDocRequest( toCorbaText( _docID ), toCorbaText(""), toCorbaText("") );
+    return new corbaDocRequestHolder(docRequest);
+  }
+
+  public static corbaDocResponseHolder createDocResponseHolder( ) {
+    corbaDocResponse docResponse = new corbaDocResponse( toCorbaText("") );
+    return new corbaDocResponseHolder( docResponse );
+  }
+
+}
+
+
+
+
+
Index: /tags/start/niupepa/etc/collect.cfg
===================================================================
--- /tags/start/niupepa/etc/collect.cfg	(revision 13666)
+++ /tags/start/niupepa/etc/collect.cfg	(revision 13666)
@@ -0,0 +1,41 @@
+creator                sjboddie@cs.waikato.ac.nz
+maintainer             sjboddie@cs.waikato.ac.nz
+public                 true
+beta                   true
+
+macrofiles             style.dm base.dm query.dm help.dm \
+                       pref.dm about.dm home.dm document.dm \
+	               status.dm npepa.dm abexpl.dm \
+		       english.dm chinese.dm maori.dm
+
+subcollection          commentaries   Filename/\.commentary$/
+subcollection          abstracts      Filename/\.abstract$/
+subcollection          papers         !Filename/\.(abstract|commentary)$/
+indexsubcollections    papers,commentaries,abstracts papers commentaries abstracts
+defaultsubcollection   papers,commentaries,abstracts
+
+indexes                section:text
+defaultindex           section:text
+
+plugin                 GMLPlug 
+plugin                 NPPlug -create_log
+plugin                 ArcPlug 
+plugin                 RecPlug
+
+classify               NPepaList
+classify               NPDateList
+
+format                 SearchVList "<td valign=top>[link][icon][/link]</td><td>{If}{[parent:Series],[parent:Series],[Series]}: {If}{[parent(All': '):Title],[parent(All': '):Title]: }[link][Title][/link]</td>"
+
+# [link] is overridden for CL1VList in this collection (to include links/icons to abstracts as well as papers)
+format                 CL1VList "<td valign=top>[link]</td><td valign=top>[Title]{If}{[numleafdocs], <i>([numleafdocs])</i>}</td><td valign=top>{If}{[Date],[Date]}</td>"
+
+format                 CL2DateList "<td valign=top>{If}{[abstract],<a href=_httpdocument_&cl=_cgiargcl_&d=[abstract]>_document:iconabstract_}[link][icon][/link]</td><td>[Series]: [Title]</td><td>[Date]</td>"
+
+format                 DocumentHeading "<h3>{If}{[parent(Top):Title],[parent(Top):Title],[Title]}<br>{If}{[parent(Top):Date],[parent(Top):Date],[Date]}"
+
+receptionist           http://www.nzdl.org/fast-cgi-bin/niupepalibrary?a=p&p=about&c=niupepa&l=mi
+
+collectionmeta         collectionname      "Niupepa: M&auml;ori Newspapers"
+collectionmeta         iconcollection      "/gsdl/collect/niupepa/images/niupepa.gif"
+collectionmeta         iconcollectionsmall "/gsdl/collect/niupepa/images/niupepsm.gif"
Index: /tags/start/niupepa/macros/abexpl.dm
===================================================================
--- /tags/start/niupepa/macros/abexpl.dm	(revision 13666)
+++ /tags/start/niupepa/macros/abexpl.dm	(revision 13666)
@@ -0,0 +1,49 @@
+package abexpl
+
+_imagethispage_ {}
+_pagetitle_ {English Abstracts of the M&auml;ori Language Newspapers}
+
+_content_ {
+<center>
+_navigationbar_
+</center>
+<h2>English Abstracts of the M&auml;ori Language Newspapers</h2>
+<h3>Introduction</h3>
+<P>The English abstracts of the M&auml;ori language newspapers are designed to give an impression of a whole newspaper 
+issue and to guide researchers to particular topics or information for translation. Although every item in an issue 
+is noted, the abstracts do not represent a full translation of the entire contents. They summarise long items such 
+as editorials, articles, and letters, and briefly record, sometimes by a complete translation, small items such as 
+notices, advertisements, short news reports. In sum the abstracts represent an abbreviated form of a newspaper and 
+so to ensure a complete reading of any item researchers will need to refer to or seek translation of the M&auml;ori text.
+
+<P>The abstracts follow the order of  items in a newspaper and include the titles and subtitles. Apart from occasional 
+additions in square brackets to clarify or inform, the abstracts report only what is in the newspaper. Where English 
+translation is published in the paper this is noted together with a brief statement of content.
+<P>A few M&auml;ori words remain in the abstracts without translation because they are key words for researchers of M&auml;ori 
+language and culture. These are highlighted and can be clicked on for explanation in the glossary. M&auml;ori names (personal, 
+place and tribal) have been written according to contemporary spelling as far as this is known.
+<P>The English abstracts are being created by a team of researchers who, in 1999, began a three-year project into the 
+history and contents of  these newspapers. The project is funded by grants from the Marsden Fund and the Trustees of 
+the National Library. The research team, from the Department of M&auml;ori Studies at the University of Auckland, comprises 
+Professor Ngapare Hopa, Dr Jane McRae, Jenifer Curnow, and postgraduate researchers Dinah Paul, Hazel Petrie, Yvonne 
+Sutherland, and Lyn Waymouth. They work collaboratively with the History of Print Culture in New Zealand Research Project, 
+and with Professor Mark Apperley and Te Taka Keegan of the Computer Science Department, University of Waikato, who are 
+carrying out the on-line conversion of the abstracts.
+
+<h3>Glossary</h3>
+<P>M&auml;ori words
+<P>The following M&auml;ori words have been retained in the abstracts because they are key words for researchers into 
+M&auml;ori language and culture. They are used here generically and so refer to all the different kinds of texts within 
+these genres.
+<P>karakia: incantations
+<P>k&ouml;rero: narratives 
+<P>waiata: sung and recited poetry
+<P>whakapapa: genealogy
+<P>whakatauk&iuml;: sayings, set expressions
+
+<h3>Abbreviations</h3>
+CMS: Church Missionary Society
+<P>MLC: Member of the Legislative Council
+<P>MHR: Member of the House of Representatives
+<P>WMMS: Wesleyan Missionary Society
+}
Index: /tags/start/niupepa/macros/about.dm
===================================================================
--- /tags/start/niupepa/macros/about.dm	(revision 13666)
+++ /tags/start/niupepa/macros/about.dm	(revision 13666)
@@ -0,0 +1,135 @@
+package about
+
+#######################################################################
+# Icons
+#######################################################################
+
+_imagethispage_ [c=niupepa] {<img src="_httpiconhabout_" width=_widthhabout_ height=_heighthabout_>}
+
+# don't want link to 'about' page
+_imagecollection_ [c=niupepa] {<img src="_iconcollection_" border=0>}
+
+_imagemined_ [c=niupepa] {<a href="http://www.minedu.govt.nz/">_iconmined_</a>}
+
+_iconmined_ [c=niupepa] {<img src="_httpcollection_/images/mined.gif" border=0>}
+
+#######################################################################
+# English language text 
+#######################################################################
+
+_texthelpexpl_ [c=niupepa] {For help at any time, press this button at the top of the page}
+
+_textretabout_ {To return to this "about" page, click the "collection"
+icon at the top left of the page.}
+
+_textabcol_ [c=niupepa] {About this collection}
+
+_textabout_ [c=niupepa] {
+<h3>_textabcol_</h3>
+<p>This is a small but growing collection based on "Niupepa 1842-1933", a microfiche collection 
+produced by the Alexander Turnbull Library. Niupepa are periodicals published in Maori or 
+for a Maori readership. Between 1842 and 1933 there were three main types of Niupepa published: 
+Government sponsored, Iwi based and religious. By the twentieth century most Niupepa were religious 
+publications. 
+<p>
+Niupepa are an important source of information on individuals, Iwi, whaikorero, waiata, Maori 
+opinions and the development of Maori as a written language. 
+<p>
+There are four main parts to the collection:
+<ul>
+<li>facsimile images of the original images
+<li>text extracted from the newspapers (used for searching)
+<li>bibliographic commentaries for each newspaper title
+<li><a href="_httppagex_(abexpl)">English abstracts</a> for each issue
+</ul>
+<p>
+The newspapers are also available on 35mm microfilm and microfiche. They can be borrowed on 
+Interloan through your local library or they can be purchased from:
+<p>
+Copying Services<br>
+Alexander Turnbull Library<br>
+PO Box 12349<br>
+Wellington<br>
+04 474 3113<br>
+04 474 6063 (fax)<br>
+<a href="mailto:atl@natlib.govt.nz">atl@natlib.govt.nz</a>
+<p>
+Commentaries on titles provided by Gail Dallimore.
+<p>
+Digital image capture carried out by New Zealand Micrographic Services Ltd.
+<p>
+OCR work sponsored by:<br>
+_imagemined_
+<p>
+}
+
+
+
+
+#######################################################################
+# Maori language text 
+#######################################################################
+
+_texthelpexpl_ [c=niupepa,l=mi] {Kia titiro ki ng_amn_ kupu _amn_whina p_amn_whiritia t_emn_nei
+p_amn_tene kei runga r_amn_ o ia wh_amn_rangi}
+
+_textabcol_ [c=niupepa,l=mi] {He kupu whakam_amn_rama i te kohikohinga niupepa}
+
+_textabout_ [c=niupepa,l=mi] {
+<h3>_textabcol_</h3>
+<p>E puaki ana _emn_nei pukapuka i te kohinga "Niupepa 1842-1933". Ko taua kohinga he 
+mea whakaemia e te Alexander Turnball Library ki runga i te kiriata mororiki. 
+Kua t_amn_ngia aua niupepa hei p_amn_nuitanga m_amn_ te iwi M_amn_ori, _amn_, ko te nuinga kua 
+tuhia ki te reo M_amn_ori. E toru ng_amn_ kaupapa matua o ng_amn_ niupepa: he h_amn_painga m_omn_ 
+te Kawanatanga, he p_amn_nuitanga r_amn_nei n_omn_ ng_amn_ iwi M_amn_ori, he kupu whakapono r_amn_nei 
+n_omn_ ng_amn_ h_amn_hi. I te huringa o te rautau 1900 i rahi haere te kaupapa h_amn_hi.
+<p>
+Ka nui ng_amn_ taonga ka noho mai nei i ng_amn_ Niupepa: ko ng_amn_ whaikorero, ng_amn_ waiata, 
+me ng_amn_ karakia, ng_amn_ k_omn_rero o te tangata, o te Iwi, o te whenua, o ng_amn_ 
+huihuinga, o ng_amn_ whakaaro me ng_amn_ _amn_huatanga o taua w_amn_, _amn_, ko ng_amn_ tauira hoki o 
+te reo M_amn_ori.
+
+<p>
+Kei runga te kohinga "Niupepa 1842-1933" katoa i te kiriata m_omn_kito 35mm me te 
+kiriata mororiki. Ka taea te tono _emn_nei i te whare pukapuka o t_omn_ rohe, ka taea 
+r_amn_nei te hoko mai i te
+<p>
+Copying Services<br>
+Alexander Turnbull Library<br>
+PO Box 12349<br>
+Wellington<br>
+04 474 3113<br>
+04 474 6063 (fax)<br>
+<a href="mailto:atl@natlib.govt.nz">atl@natlib.govt.nz</a>
+<p>
+ko ng_amn_ mahi OCR ka tautokohia e:<br>
+_imagemined_
+<p>
+}
+
+
+##############
+# about page #
+##############
+
+
+_aboutextra_ [c=niupepa] {
+_If_("_cgiargl_" eq "mi",<a href="_httppageabout_&l=en">English language version</a><p>)
+<h3>_help:textsimplehelpheading_</h3>
+_help:simplehelp_
+}
+
+_pagetitle_ [c=niupepa] {_collectionname_: About this collection}
+
+_content_ [c=niupepa] {
+<center>
+_navigationbar_
+</center>
+_query:queryform_
+<p>
+_iconblankbar_<br>
+_aboutextra_
+<p>
+_iconblankbar_<br>
+_textabout_
+}
Index: /tags/start/niupepa/macros/npepa.dm
===================================================================
--- /tags/start/niupepa/macros/npepa.dm	(revision 13666)
+++ /tags/start/niupepa/macros/npepa.dm	(revision 13666)
@@ -0,0 +1,408 @@
+package Global
+
+_textbiblio_ [c=niupepa] {Bibliographic Details}
+_textbackground_ [c=niupepa] {Background}
+_textsubmat_ [c=niupepa] {Subject Matter}
+_textavail_ [c=niupepa] {Availability}
+_commentary_ [c=niupepa] {Commentary}
+
+_missingtext_ [c=niupepa] {Text has yet to be digitised for this page}
+
+_iconclosedbook_ [c=niupepa] {<img src="_httpimg_/np.gif" valign=top width=20 height=20 border=0 alt="_texticonclosedbook_">}
+_texticonclosedbook_ [c=niupepa] {view niupepa}
+_texticonclosedbook_ [c=niupepa,l=mi] {tirohia niupepa}
+
+_textbiblio_ [c=niupepa,l=mi] {K_omn_rero T_amn_}
+_textbackground_ [c=niupepa,l=mi] {He Whakam_amn_rama}
+_textsubmat_ [c=niupepa,l=mi] {Kaupapa}
+_textavail_ [c=niupepa,l=mi] {Nohoanga}
+_commentary_ [c=niupepa,l=mi] {Kupu Whakataki}
+
+_abstract_ [c=niupepa] {Abstract: }
+
+_abstract_ [c=niupepa,l=mi] {R_amn_popoto reo P_amn_keh_amn_: }
+
+#######################################################################
+# index option macros
+#######################################################################
+
+_stx_ [c=niupepa] {}
+
+_ab_ [c=niupepa] {english abstracts}
+_ab_ [c=niupepa,l=mi] {ng_amn_ r_amn_popoto reo P_amn_keh_amn_ anake}
+_cm_ [c=niupepa] {bibliographic commentaries}
+_cm_ [c=niupepa,l=mi] {ng_amn_ kupu whakataki anake}
+_pc_ [c=niupepa] {papers, commentaries, and abstracts}
+_pc_ [c=niupepa,l=mi] {niupepa, kupu whakataki, me ng_amn_ r_amn_popoto}
+_pp_ [c=niupepa] {newspapers}
+_pp_ [c=niupepa,l=mi] {ng_amn_ niupepa anake}
+
+
+package document
+
+#_abstract_ [c=niupepa] {Abstract<br>}
+#_abstract_ [c=niupepa,l=mi] {R_amn_popoto reo P_amn_keh_amn_<br>}
+
+_httpthiscommentary_ [c=niupepa] {}
+_httpiconthispaper_ [c=niupepa] {}
+_thispapericonwidth_ [c=niupepa] {0}
+_thispapericonheight_ [c=niupepa] {0}
+
+_01width_ {314}
+_01height_ {126}
+_03width_ {320}
+_03height_ {205}
+_04width_ {322}
+_04height_ {195}
+_05width_ {320}
+_05height_ {210}
+_15width_ {320}
+_15height_ {110}
+_18width_ {310}
+_18height_ {120}
+_19width_ {333}
+_19height_ {230}
+_25width_ {312}
+_25height_ {56}
+_36awidth_ {327}
+_36aheight_ {153}
+_39width_ {320}
+_39height_ {102}
+_40width_ {298}
+_40height_ {153}
+
+
+_iconabstract_ [c=niupepa] {<img src="_httpimg_/iabstr.gif" valign=top border=0 alt="_texticonabstract_">}
+_iconabstract_ [c=niupepa,v=1] {_texticonabstract_}
+
+_iconcommentary_ [c=niupepa] {<img src="_httpimg_/icomm.gif" valign=top border=0 alt="_texticoncommentary_">}
+_iconcommentary_ [c=niupepa,v=1] {_texticoncommentary_}
+
+# javalinks specific to this collection
+_javafullimage_ [c=niupepa] {
+        fullimage\_on = new Image(_widthefix_, _heightefix_); 
+        fullimage\_on.src = "_httpiconefion_";
+        fullimage\_off = new Image(_widthefix_, _heightefix_); 
+        fullimage\_off.src = "_httpiconefiof_";
+}
+
+_javaprevimage_ [c=niupepa] {
+        previmage\_on = new Image(_widthepix_, _widthepix_); 
+        previmage\_on.src = "_httpiconepion_";
+        previmage\_off = new Image(_widthepix_, _heightepix_); 
+        previmage\_off.src = "_httpiconepiof_";
+}
+
+_javaviewtext_ [c=niupepa] {
+        viewtext\_on = new Image(_widthetextx_, _heightetextx_); 
+        viewtext\_on.src = "_httpiconetexton_";
+        viewtext\_off = new Image(_widthetextx_, _heightetextx_); 
+        viewtext\_off.src = "_httpiconetextof_";
+}
+
+_javacommentary_ [c=niupepa] {
+	commentary\_on = new Image(_thispapericonwidth_, _thispapericonheight_);
+	commentary\_on.src = "_httpiconthispaper_on.gif";
+	commentary\_off = new Image(_thispapericonwidth_, _thispapericonheight_);
+        commentary\_off.src = "_httpiconthispaper_of.gif"; 
+}
+
+_javaviewabstract_ [c=niupepa] {
+        abstract\_on = new Image(_widtheabstrx_, _heighteabstrx_); 
+        abstract\_on.src = "_httpiconeabstron_";
+        abstract\_off = new Image(_widtheabstrx_, _heighteabstrx_); 
+        abstract\_off.src = "_httpiconeabstrof_";
+}
+
+_javaviewpaper_ [c=niupepa] {
+        paper\_on = new Image(_widthenpepax_, _heightenpepax_); 
+        paper\_on.src = "_httpiconenpepaon_";
+        paper\_off = new Image(_widthenpepax_, _heightenpepax_); 
+        paper\_off.src = "_httpiconenpepaof_";
+}
+
+_javaabstractintro_ [c=niupepa] {
+        intro\_on = new Image(_widtheintrox_, _heighteintrox_); 
+        intro\_on.src = "_httpiconeintroon_";
+        intro\_off = new Image(_widtheintrox_, _heighteintrox_); 
+        intro\_off.src = "_httpiconeintroof_";
+}
+
+_prevarrow_ [c=niupepa] {_If_(_httpprevarrow_,<a href="_httpprevarrow__1_">_iconprev_</a>)}
+_nextarrow_ [c=niupepa] {_If_(_httpnextarrow_,<a href="_httpnextarrow__1_">_iconnext_</a>)}
+
+
+_iconfullimage_ [c=niupepa] {<img name="fullimage" src="_httpiconefiof_" width="_widthefix_" height="_heightefix_" alt="_texticonfullimage_" border="0">}
+_iconfullimage_ [c=niupepa,v=1] {_texticonfullimage_}
+
+_iconprevimage_ [c=niupepa] {<img name="previmage" src="_httpiconepiof_" width="_widthepix_" height="_heightepix_" alt="_texticonprevimage_" border="0">}
+_iconprevimage_ [c=niupepa,v=1] {_texticonprevimage_}
+
+_iconviewtext_ [c=niupepa] {<img name="viewtext" src="_httpiconetextof_" width="_widthetextx_" height="_heightetextx_" alt="_texticonviewtext_" border="0">}
+_iconviewtext_[c=niupepa,v=1] {_texticonviewtext_}
+
+_iconviewabstract_ [c=niupepa] {<img name="abstract" src="_httpiconeabstrof_" width="_widtheabstrx_" height="_heighteabstrx_" alt="_texticonviewabstract_" border="0">}
+_iconviewabstract_[c=niupepa,v=1] {_texticonviewabstract_}
+
+_iconviewpaper_ [c=niupepa] {<img name="paper" src="_httpiconenpepaof_" width="_widthenpepax_" height="_heightenpepax_" alt="_texticonviewpaper_" border="0">}
+_iconviewpaper_[c=niupepa,v=1] {_texticonviewpaper_}
+
+_iconabstractintro_ [c=niupepa] {<img name="intro" src="_httpiconeintroof_" width="_widtheintrox_" height="_heighteintrox_" alt="_texticonabstractintro_" border="0">}
+_iconabstractintro_[c=niupepa,v=1] {_texticonabstractintro_}
+
+_iconthispaper_ [c=niupepa] {<img name="commentary" src="_httpiconthispaper_of.gif" 
+width="_thispapericonwidth_" height="_thispapericonheight_" border="0" alt="_texticoncommentary_">}
+
+
+_imagedetach_ [c=niupepa] {<a href="_httpcurrentdocument_&x=1&gg=_cgiarggg_" target=\_blank onMouseover = "img\_on('detach')"
+onMouseout = "img\_off('detach')">_icondetach_</a>}
+_imagedetach_[c=niupepa,v=1] {<a href="_httpcurrentdocument_&x=1&gg=cgiarggg_" target=\_blank>_texticondetach_</a><br>}
+
+
+_imagefullimage_ [c=niupepa] {<a href="_httpcurrentdocument_&gg=full" onMouseover = "img\_on('fullimage')"
+onMouseout = "img\_off('fullimage')">_iconfullimage_</a>}
+_imagefullimage_ [c=niupepa,v=1] {<a href="_httpcurrentdocument_&gg=full">_texticonfullimage_</a><br>}
+
+_imageprevimage_ [c=niupepa] {<a href="_httpcurrentdocument_&gg=prev" onMouseover = "img\_on('previmage')"
+onMouseout = "img\_off('previmage')">_iconprevimage_</a>}
+_imageprevimage_ [c=niupepa,v=1] {<a href="_httpcurrentdocument_&gg=prev">_texticonprevimage_</a><br>}
+
+_imageviewtext_ [c=niupepa] {<a href="_httpcurrentdocument_&gg=text" onMouseover = "img\_on('viewtext')"
+onMouseout = "img\_off('viewtext')">_iconviewtext_</a>}
+_imageviewtext_ [c=niupepa,v=1] {<a href="_httpcurrentdocument_&gg=text">_texticonviewtext_</a><br>}
+
+_imageviewabstract_ [c=niupepa] {<a href="_httpdocument_&gg=text&&cl=_cgiargcl_&d=_1_" onMouseover = "img\_on('abstract')"
+onMouseout = "img\_off('abstract')">_iconviewabstract_</a>}
+_imageviewabstract_ [c=niupepa,v=1] {<a href="_httpdocument_&gg=text&cl=_cgiargcl_&d=_1_">_texticonviewabstract_</a><br>}
+
+_imageviewpaper_ [c=niupepa] {<a href="_httpdocument_&cl=_cgiargcl_&d=_1_" onMouseover = "img\_on('paper')"
+onMouseout = "img\_off('paper')">_iconviewpaper_</a>}
+_imageviewpaper_ [c=niupepa,v=1] {<a href="_httpdocument_&cl=_cgiargcl_&d=_1_">_texticonviewpaper_</a><br>}
+
+_imageabstractintro_ [c=niupepa] {<a href="_httppagex_(abexpl)" onMouseover = "img\_on('intro')"
+onMouseout = "img\_off('intro')">_iconabstractintro_</a>}
+_imageabstractintro_ [c=niupepa,v=1] {<a href="_httppagex_(abexpl)">_texticonabstractintro_</a><br>}
+
+_imagethispaper_ [c=niupepa] {_If_(_httpthiscommentary_,_linkthispaper_,_nolinkthispaper_)}
+
+_linkthispaper_ [c=niupepa] {<a href="_httpthiscommentary_" 
+    onMouseover = "img\_on('commentary')" 
+    onMouseout = "img\_off('commentary')">_iconthispaper_</a>}
+_imagethispaper_ [c=niupepa,v=1] {<a href="_httpthiscommentary_">_texticoncommentary_</a><br>
+}
+
+# this occurs when we're at a commentary page - (no alt text, no link)
+_nolinkthispaper_ [c=niupepa] {<img src="_httpiconthispaper_on.gif" width="_thispapericonwidth_" 
+height="_thispapericonheight_" border="0">}
+
+
+_httpiconefiof_ [c=niupepa] {_httpimg_/efiof.gif}
+_httpiconefiof_ [c=niupepa,l=mi] {_httpimg_/mefiof.gif}
+_httpiconefion_ [c=niupepa] {_httpimg_/efion.gif}
+_httpiconefion_ [c=niupepa,l=mi] {_httpimg_/mefion.gif}
+_widthefix_ [c=niupepa] {65}
+_widthefix_ [c=niupepa,l=mi] {65}
+_heightefix_ [c=niupepa] {30}
+
+_httpiconepiof_ [c=niupepa] {_httpimg_/epiof.gif}
+_httpiconepiof_ [c=niupepa,l=mi] {_httpimg_/mepiof.gif}
+_httpiconepion_ [c=niupepa] {_httpimg_/epion.gif}
+_httpiconepion_ [c=niupepa,l=mi] {_httpimg_/mepion.gif}
+_widthepix_ [c=niupepa] {65}
+_widthepix_ [c=niupepa,l=mi] {65}
+_heightepix_ [c=niupepa] {30}
+
+_httpiconetextof_ [c=niupepa] {_httpimg_/etextof.gif}
+_httpiconetextof_ [c=niupepa,l=mi] {_httpimg_/metextof.gif}
+_httpiconetexton_ [c=niupepa] {_httpimg_/etexton.gif}
+_httpiconetexton_ [c=niupepa,l=mi] {_httpimg_/metexton.gif}
+_widthetextx_ [c=niupepa,l=mi] {65}
+_widthetextx_ [c=niupepa] {65}
+_heightetextx_ [c=niupepa] {30}
+
+_httpiconeabstrof_ [c=niupepa] {_httpimg_/eabstrof.gif}
+_httpiconeabstrof_ [c=niupepa,l=mi] {_httpimg_/mabstrof.gif}
+_httpiconeabstron_ [c=niupepa] {_httpimg_/eabstron.gif}
+_httpiconeabstron_ [c=niupepa,l=mi] {_httpimg_/mabstron.gif}
+_widtheabstrx_ [c=niupepa] {65}
+_widtheabstrx_ [c=niupepa,l=mi] {65}
+_heighteabstrx_ [c=niupepa] {30}
+
+_httpiconenpepaof_ [c=niupepa] {_httpimg_/enpepaof.gif}
+_httpiconenpepaof_ [c=niupepa,l=mi] {_httpimg_/mnpepaof.gif}
+_httpiconenpepaon_ [c=niupepa] {_httpimg_/enpepaon.gif}
+_httpiconenpepaon_ [c=niupepa,l=mi] {_httpimg_/mnpepaon.gif}
+_widthenpepax_ [c=niupepa] {65}
+_widthenpepax_ [c=niupepa,l=mi] {65}
+_heightenpepax_ [c=niupepa] {30}
+
+_httpiconeintroof_ [c=niupepa] {_httpimg_/eintroof.gif}
+_httpiconeintroof_ [c=niupepa,l=mi] {_httpimg_/mintroof.gif}
+_httpiconeintroon_ [c=niupepa] {_httpimg_/eintroon.gif}
+_httpiconeintroon_ [c=niupepa,l=mi] {_httpimg_/mintroon.gif}
+_widtheintrox_ [c=niupepa] {65}
+_widtheintrox_ [c=niupepa,l=mi] {65}
+_heighteintrox_ [c=niupepa] {30}
+
+_texticonsmalltext_ [c=niupepa] {_texticoncommentary_}
+_texticonabstract_ [c=niupepa] {View the english abstract}
+_texticonfullimage_ [c=niupepa] {View fullsize image of this page}
+_texticonprevimage_ [c=niupepa] {View preview image of this page}
+_texticonviewtext_ [c=niupepa] {View the text of this page}
+_texticoncommentary_ [c=niupepa] {View the commentary of this paper}
+_texticonviewabstract_ [c=niupepa] {View the English abstract of this issue}
+_texticonviewpaper_ [c=niupepa] {View niupepa issue}
+_texticonabstractintro_ [c=niupepa] {View introduction to English abstracts}
+
+_texticonsmalltext_ [c=niupepa,l=mi] {Tirohia kupu whakataki}
+_texticonabstract_ [c=niupepa,l=mi] {Tirohia ng_amn_ r_amn_popoto reo P_amn_keh_amn_}
+_texticonfullimage_ [c=niupepa,l=mi] {Titiro ki te whakaahua nui o t_emn_nei wh_amn_rangi niupepa}
+_texticonprevimage_ [c=niupepa,l=mi] {Titiro ki te whakaahua iti o t_emn_nei wh_amn_rangi niupepa}
+_texticonviewtext_ [c=niupepa,l=mi] {Titiro ki ng_amn_ kupu kua tuhia k_emn_ ki te rorohiko}
+_texticoncommentary_ [c=niupepa,l=mi] {Tirohia ng_amn_ kupu whakataki o t_emn_nei niupepa}
+_texticonviewabstract_ [c=niupepa,l=mi] {Tirohia te r_amn_popoto reo P_amn_keh_amn_ e p_amn_ 
+ana ki t_emn_nei w_amn_hanga}
+_texticonviewpaper_ [c=niupepa,l=mi] {Tirohia te wh_amn_rangi niupepa}
+_texticonabstractintro_ [c=niupepa,l=mi] {He whakam_amn_rama i ng_amn_ r_amn_popoto reo P_amn_keh_amn_}
+
+
+
+#################
+package help
+#################
+
+# no scope help for this collection
+_texthelpscope_ [c=niupepa] {}
+
+_textexplainbuttons_ [c=niupepa] {
+<p>
+<table cellspacing="0" cellpadding="2" border="0">
+<tr><td><img src="_httpimg_/smtext.gif" border="0"></td><td>_document:texticonsmalltext_</td></tr>
+<tr><td><img src="_httpimg_/clsdfldr.gif" border="0"></td><td>_document:texticonclosedfolder_</td></tr>
+<tr><td><img src="_httpimg_/more.gif"></td><td>_textnextbutton_</td></tr>
+<tr><td><img src="_httpimg_/less.gif"></td><td>_textprevbutton_</td></tr>
+<tr><td><img src="_httpicondtchdemo_"></td><td valign="center">_document:texticondetach_</td></tr>
+<tr><td><img src="_httpiconealltdemo_"></td><td valign="center">_document:texticonexpandtext_</td></tr>
+<tr><td><img src="_document:httpiconefiof_"></td><td valign="center">_document:texticonfullimage_</td></tr>
+<tr><td><img src="_document:httpiconepiof_"></td><td valign="center">_document:texticonprevimage_</td></tr>
+<tr><td><img src="_document:httpiconehlof_"></td><td valign="center">_document:texticonhighlight_</td></tr>
+</table>
+}
+
+_texthelptopics_ [c=niupepa,l=mi] {
+<h2 align=left>Kaupapa</h2>
+<ul>
+  <li><a href="\#finding-information">Ng_amn_ huarahi hei rapu k_omn_rero</a>
+  <li><a href="\#reading-books">Te p_amn_nui niupepa/kupu whakataki</a>
+  <li><a href="\#searching">Te rapu kupu</a>
+<ul>
+  <li><a href="\#query-terms">Ng_amn_ kupu hei rapu</a>
+  <li><a href="\#query-type">Ng_amn_ t_umn_momo rapu</a>
+  <li><a href="\#stemming">Ng_amn_ p_umn_ matua, p_umn_ iti me ng_amn_ k_umn_muri hoki</a>
+</ul>
+</ul>
+}
+
+_texthelptopics_ [c=niupepa] {
+<h2 align=left>Topics</h2>
+<ul>
+  <li><a href="\#finding-information">_textsimplehelpheading_</a>
+  <li><a href="\#reading-books">How to read the books</a>
+  <li><a href="\#searching">How to search for particular words</a>
+<ul>
+  <li><a href="\#query-terms">Search terms</a>
+  <li><a href="\#query-type">Query type</a>
+  <li><a href="\#stemming">Case sensitivity and stemming</a>
+</ul>
+</ul>
+}
+
+
+_texthelpreadingbooks_ [c=niupepa] {
+<h2>How to read Niupepa Pages</h2>
+
+<p>You can tell when you are looking at a Niupepa page because there is a picture
+of the Niupepa's insignia on the top right of the screen. Also, on the top left
+of the screen, the issue and number of the Niupepa is displayed, along with the
+publication date and some navigation buttons.
+
+<p>The lower half of the screen displays the digitized text of the Niupepa.
+It must be remembered that this text is captured by the computer from the
+pictures of the Niupepa pages. If the pages are dirty then errors will occur in the
+digitized text. View the picture of the Niupepa page to see the correct text.
+
+<p>If you click on the insignia of the Niupepa you will see the Bibliographic
+Commentary for that Niupepa. Other buttons are:
+}
+
+_texthelpreadingbooks_ [c=niupepa,l=mi] {
+<h2>Te P_amn_nui Niupepa</h2>
+
+<p>Mehemea ka kite atu koe i t_emn_tehi tohu niupepa i te taha katau o runga,
+ka m_omn_hio mai koe kei te titiro ki t_emn_tehi wh_amn_rangi o taua niupepa.
+Kei te taha maui o runga ka kite atu hoki i te nama me te w_amn_hanga o taua
+niupepa, te r_amn_ o taua niupepa, _amn_, kei reira hoki _emn_tehi p_amn_tene 
+hei whakatere i ng_amn_ wh_amn_rangi o te niupepa.
+
+<p>Kei raro r_amn_ ka kite atu i ng_amn_ k_omn_rero o t_emn_tehi wh_amn_rangi
+o te niupepa. Kia maumahara mai, ko _emn_nei kupu _amn_-rorohiko he mea hangaia 
+e te rorohiko i t_amn_na titiro ki te whakaahua o te wh_amn_rangi. Mehemea ka 
+paruparu te _amn_hua o te whakaahua, ka h_emn_ _emn_tehi kupu. Kia kite atu 
+i ng_amn_ kupu tika tirohia k_emn_tia te whakaahua o te wh_amn_rangi.
+
+<p>Mehemea ka p_amn_whiritia te tohu o te niupepa ka puta mai ng_amn_ kupu
+whakam_amn_rama m_omn_ taua niupepa. Ka p_emn_nei _emn_tehi atu p_amn_tene:
+}
+
+
+_textSeriesshort_ [c=niupepa] {access the niupepa by series}
+_textSeriesshort_ [c=niupepa,l=mi] {tirohia te whakar_amn_rangi taitara}
+_textDateshort_ [c=niupepa] {access the niupepa by date}
+_textDateshort_ [c=niupepa,l=mi] {tirohia te whakar_amn_rangi e p_amn_ ana ki te w_amn_}
+
+_textSerieslong_ [c=niupepa] {
+<p>You can <i>access the niupepa by series</i> by pressing the <i>series</i> button. 
+This brings up a list of those niupepa series which are currently in the collection. 
+Each series also contains a brief commentary which can be accessed from here.
+}
+
+_textSerieslong_ [c=niupepa,l=mi] {
+<p>Kia <i>tirohia te whakar_amn_rangi taitara</i> p_amn_whiritia te p_amn_tene 
+<i>whakar_amn_rangi taitara</i>. Ka puta mai te whakar_amn_rangi o ng_amn_
+niupepa e p_amn_ ana ki ng_amn_ taitara.
+}
+
+_textDatelong_ [c=niupepa] {
+<p>You can <i>access the niupepa by date</i> by pressing the <i>dates</i> button. 
+This brings up a list of all the niupepa issues, sorted chronologically.
+}
+
+_textDatelong_ [c=niupepa,l=mi] {<p>Kia <i>tirohia te whakar_amn_rangi e p_amn_ ana ki te w_amn_</i> p_amn_whiritia te
+p_amn_tene <i>w_amn_taka</i>. Ka puta mai te whakar_amn_rangi o ng_amn_ niupepa
+e p_amn_ ana ki te w_amn_ i puta mai ai aua niupepa.
+}
+
+_iconexplain_ [c=niupepa] {
+<table cellspacing="0" cellpadding="2" border="0">
+<tr valign="top"><td><img src="_httpimg_/np.gif" width="20" height="20" border="0"></td>
+<td>Click on a newspaper icon to read the corresponding niupepa issue</td></tr>
+<tr valign="top"><td><img src="_httpimg_/bshelf.gif" border="0" width=20 height=16></td>
+<td>Click on a bookshelf icon when browsing the niupepa series to view a list of all the issues
+in that series</td></tr>
+<tr valign="top"><td><img src="_httpimg_/iabstr.gif" border="0"></td>
+<td>Click on an abstract icon to read English abstracts of the given issue</td></tr>
+</table>
+}
+
+_iconexplain_ [c=niupepa,l=mi] {
+<table cellspacing="0" cellpadding="2" border="0">
+<tr valign="top"><td><img src="_httpimg_/np.gif" width="20" height="20" border="0"></td>
+<td>P_amn_whiritia te p_amn_tene niupepa kia puta mai ai taua niupepa</td></tr>
+<tr valign="top"><td><img src="_httpimg_/bshelf.gif" border="0" width=20 height=16></td>
+<td>P_amn_whiritia te p_amn_tene kohinga kia puta mai ai ng_amn_ niupepa o taua kohinga</td></tr>
+<tr valign="top"><td><img src="_httpimg_/iabstr.gif" border="0"></td>
+<td>P_amn_whiritia te p_amn_tene wh_amn_rangi kia puta mai ai te r_amn_popoto i te reo P_amn_keh_amn_</td></tr>
+</table>
+}
+
+
Index: /tags/start/niupepa/perllib/classify/NPDateList.pm
===================================================================
--- /tags/start/niupepa/perllib/classify/NPDateList.pm	(revision 13666)
+++ /tags/start/niupepa/perllib/classify/NPDateList.pm	(revision 13666)
@@ -0,0 +1,57 @@
+###########################################################################
+#
+# NPDateList.pm -- classifier plugin for sorting by date
+# 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.
+#
+###########################################################################
+
+# overridden for niupepa as we don't want to include abstracts directly in lists
+
+package NPDateList;
+
+use DateList;
+
+sub BEGIN {
+    @ISA = ('DateList');
+}
+
+sub classify {
+    my $self = shift (@_);
+    my ($doc_obj) = @_;
+
+    # want to ignore abstracts
+    my $doctype = $doc_obj->get_metadata_element($doc_obj->get_top_section(), 'doctype');
+    return if (defined $doctype && $doctype eq 'Description');
+
+    my $doc_OID = $doc_obj->get_OID();
+    my $date = $doc_obj->get_metadata_element ($doc_obj->get_top_section(), 'Date');
+
+    # if this document doesn't contain Date element we won't 
+    # include it in this classification
+    if (defined $date && $date =~ /\d/) {
+	if (defined $self->{'list'}->{$doc_OID}) {
+	    print STDERR "WARNING: DateList::classify called multiple times for $doc_OID\n";
+	} 
+	$self->{'list'}->{$doc_OID} = $date;
+    }
+}
+
+1;
Index: /tags/start/niupepa/perllib/classify/NPepaList.pm
===================================================================
--- /tags/start/niupepa/perllib/classify/NPepaList.pm	(revision 13666)
+++ /tags/start/niupepa/perllib/classify/NPepaList.pm	(revision 13666)
@@ -0,0 +1,111 @@
+###########################################################################
+#
+# NpepaList.pm -- website plugin
+#
+# 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.
+#
+###########################################################################
+
+# There should probably be a general classifier to do this kind of stuff
+
+package NPepaList;
+
+sub new {
+    my ($class, @options) = @_;
+
+    return bless {
+	'list'=>{},
+	'metaname' => 'Series',
+	'sortname' => 'Date'
+	}, $class;
+}
+
+sub init {
+    my $self = shift (@_);
+
+    $self->{'list'} = {};
+}
+
+
+sub classify {
+    my $self = shift (@_);
+    my ($doc_obj) = @_;
+
+    my $doc_OID = $doc_obj->get_OID();
+
+    # want to ignore abstracts
+    my $doctype = $doc_obj->get_metadata_element($doc_obj->get_top_section(), 'doctype');
+    return if (defined $doctype && $doctype eq 'Description');
+
+    my $date = $doc_obj->get_metadata_element($doc_obj->get_top_section(),
+					      $self->{'sortname'});
+    # commentaries have no date but we want them to sort to the top
+    $date = '00000000' unless defined $date;
+
+    my $series = $doc_obj->get_metadata_element ($doc_obj->get_top_section(),
+						 $self->{'metaname'});
+
+    if (defined $series) {
+	if (!defined $self->{'list'}->{$series}) {
+	    $self->{'list'}->{$series} = {};
+	}
+	if (defined $self->{'list'}->{$series}->{$doc_OID}) {
+	    print STDERR "WARNING: NPepaList::classify called multiple times for $doc_OID\n";
+	} 
+	$self->{'list'}->{$series}->{$doc_OID} = $date;
+    } else {
+	print STDERR "WARNING: NpepaList::classify $doc_OID has no Series metadata\n";
+    }
+}
+
+
+sub get_classify_info {
+    my $self = shift (@_);
+
+    my $classifyinfo = $self->get_entry ('Series', 'VList', 'Invisible');
+
+    foreach $series (sort keys %{$self->{'list'}}) {
+	my $cinfo = $self->get_entry ($series, 'VList');
+	foreach $OID (sort {$self->{'list'}->{$series}->{$a} 
+			    cmp $self->{'list'}->{$series}->{$b};} keys %{$self->{'list'}->{$series}}) {
+	    push (@{$cinfo->{'contains'}}, {'OID'=>$OID});
+	}
+	push (@{$classifyinfo->{'contains'}}, $cinfo);
+    }
+
+    return $classifyinfo;
+}
+
+sub get_entry {
+    my $self = shift (@_);
+    my ($title, $childtype, $thistype) = @_;
+    
+    # organise into classification structure
+    my %classifyinfo = ('childtype'=>$childtype,
+			'Title'=>$title,
+			'contains'=>[]);
+    $classifyinfo{'thistype'} = $thistype 
+	if defined $thistype && $thistype =~ /\w/;
+
+    return \%classifyinfo;
+}
+
+1;
Index: /tags/start/niupepa/perllib/plugins/NPPlug.pm
===================================================================
--- /tags/start/niupepa/perllib/plugins/NPPlug.pm	(revision 13666)
+++ /tags/start/niupepa/perllib/plugins/NPPlug.pm	(revision 13666)
@@ -0,0 +1,424 @@
+###########################################################################
+#
+# NPPlug.pm -- Plugin for the niupepa collection
+# 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.
+#
+###########################################################################
+
+# The niupepa collection has a file structure as follows:
+# Each niupepa series has its own directory containing some/all 
+# of the following:
+
+# meta.txt - file contains metadata to be associated with all documents
+# in series.
+# *.issue - each issue should have a .issue file which may or may not
+# contain metadata to associate with the issue. also contains the list
+# of filenames that make up the issue (i.e. one for each page). meta.txt
+# is read before *.issue so metadata in .issue files will override that in
+# meta.txt
+# *.commentary - the commentary of the niupepa series (1 per series)
+# text/*.txt/htm - text/html files of issue pages (1 per page) -
+# text files are expected to be either .htm or .txt (lower case).
+# images/*.gif - image files of issue pages (1 per page)
+# abstracts/*.abstract - html files of issue abstracts (1 per issue) 
+
+
+package NPPlug;
+
+use BasPlug;
+use util;
+
+sub BEGIN {
+    @ISA = ('BasPlug');
+}
+
+use strict;
+
+sub print_usage {
+    print STDERR "\nIncorrect options passed to NPPlug, check your collect.cfg configuration file\n";
+
+    print STDERR "\n  usage: plugin NPPlug [options]\n\n";
+    print STDERR "  options:\n";
+    print STDERR "   -create_log            Creates a log file containing info about which portions\n";
+    print STDERR "                          of papers are missing\n";
+    print STDERR "   -logfile               Path of logfile (defaults to ./log.txt)\n\n";
+}
+
+sub new {
+    my ($class) = @_;
+    my $self = new BasPlug ();
+
+    if (!parsargv::parse(\@_, 
+			 q^create_log^, \$self->{'create_log'},
+			 q^logfile/.*/./log.txt^, \$self->{'logfile'})) {
+	&print_usage();
+	die "\n";
+    }
+
+    $self->{'commentaries'} = {};
+    $self->{'num_issues'} = 0;
+    $self->{'num_text_pages'} = 0;
+    $self->{'num_images_pages'} = 0;
+    $self->{'num_abstracts'} = 0;
+    return bless $self, $class;
+}
+
+sub is_recursive {
+    my $self = shift (@_);
+
+    return 0; # this is not a recursive plugin
+}
+
+sub begin {
+    my $self = shift (@_);
+    my ($pluginfo, $base_dir, $processor, $maxdocs) = @_;
+
+    # open up logfile
+    # note that we append to logfile as building will otherwise
+    # overwrite a file generated at import time
+    if ($self->{'create_log'}) {
+	open (LOGFILE, ">>$self->{'logfile'}") || die 
+	    "NPPlug.pm: Couldn't open log file $self->{'logfile'}\n";
+
+	my @time = localtime (time);
+
+	print LOGFILE "------------------------------------------------------------\n";
+	print LOGFILE "Log start $time[3]/$time[4]/" . (1900 + $time[5]) . "\n";
+	print LOGFILE "------------------------------------------------------------\n";
+    }
+}
+
+sub end {
+    my $self = shift (@_);
+
+    if ($self->{'create_log'}) {
+	my $numseries = 0;
+	my $numcommentaries = 0;
+
+	# record missing commentaries in logfile
+	foreach my $key (keys %{$self->{'commentaries'}}) {
+	    $numseries ++;
+	    if (!$self->{'commentaries'}->{$key}) {
+		print LOGFILE "Commentary missing for series $key\n";
+	    } else {
+		$numcommentaries ++;
+	    }
+	}
+	
+	print LOGFILE "\n\nStatistics:\n";
+	print LOGFILE "series: $numseries\n";
+	print LOGFILE "commentaries: $numcommentaries\n";
+	print LOGFILE "issues: $self->{'num_issues'}\n";
+	print LOGFILE "abstracts: $self->{'num_abstracts'}\n";
+	print LOGFILE "text pages: $self->{'num_text_pages'}\n";
+	print LOGFILE "image pages: $self->{'num_image_pages'}\n";
+
+	# close logfile
+	close LOGFILE;
+    }
+}
+
+# return number of files processed, undef if can't process
+# Note that $base_dir might be "" and that $file might 
+# include directories
+sub read {
+    my $self = shift (@_);
+    my ($pluginfo, $base_dir, $file, $metadata, $processor) = @_;
+
+    my $filename = &util::filename_cat($base_dir, $file);
+
+    # we don't want RecPlug to go recursing into the text, images or 
+    # abstracts directories
+    return 0 if (-d $filename && $filename =~ /(abstracts|images|text)/);
+
+    return 0 if $filename =~ /meta\.txt$/i;
+
+    return undef unless ($filename =~ /\.(issue|commentary)$/i && (-e $filename));
+
+    $self->{'verbosity'} = $processor->{'verbosity'};
+    print STDERR "NPPlug: processing $filename\n" if $self->{'verbosity'};
+
+    my ($dir);
+    ($dir, $file) = $filename =~ /^(.*?)([^\/\\]*)$/;
+    my ($issuekey) = $file =~ /^([^\.\_]*)/;
+
+    if ($filename =~ /\.commentary$/i) {
+	# commentary
+	return $self->process_commentary ($filename, $issuekey, $dir, $file, $processor);
+    }
+
+    my $numprocessed = 0;
+    $self->{'commentaries'}->{$issuekey} = 0 unless defined $self->{'commentaries'}->{$issuekey};
+
+    my ($abstractfile) = $file =~ /^([^\.]*)\.issue/i;
+    my $abstractOID = $abstractfile . "abstract";
+    $abstractfile .= ".abstract";
+    my $afile = &util::filename_cat($dir, "abstracts", $abstractfile);
+    my $hasabstract = 0;
+    if (-e $afile) {$hasabstract = 1;}
+    else {$abstractOID = undef;}
+
+    # process the .issue file
+    my %meta = ();
+    $numprocessed += $self->process_issue ($filename, $issuekey, $dir, $file, 
+					   $abstractOID, $processor, \%meta);
+
+    # process abstract of this issue
+    if ($hasabstract) {
+	$numprocessed += $self->process_abstract ($afile, $issuekey, $dir, 
+						  $abstractfile, $processor, \%meta);
+    }
+
+    return $numprocessed;
+}
+
+sub process_issue {
+    my $self = shift (@_);
+    my ($filename, $issuekey, $dir, $file, $abstract, $processor, $meta) = @_;
+
+    $self->{'num_issues'} ++;
+    my $doc_obj = new doc ($file, "indexed_doc");
+    my $topsection = $doc_obj->get_top_section();
+    my $cursection = $topsection;
+    $self->associate_cover_images ($doc_obj, $dir, $issuekey);
+    $doc_obj->set_metadata_element ($topsection, 'Title', $self->get_title_string($file));
+    $doc_obj->set_metadata_element ($topsection, 'abstract', $abstract) if defined $abstract;
+    $self->set_main_metadata ($doc_obj, $dir);
+
+    open (ISSUEFILE, $filename) || die "couldn't open $filename\n";
+    my $line = "";
+    while (defined ($line = <ISSUEFILE>)) {
+	next unless $line =~ /\w/;
+	chomp $line;
+	if ($line =~ /^<([^>]*)>(.*?)\s*$/) {
+	    $doc_obj->set_metadata_element ($topsection, $1, $2);
+	    $meta->{$1} = $2;
+	} else {
+	    # should be a section name
+	    $line =~ s/^\s+//;
+	    $line =~ s/\s+$//;
+	    $cursection = $doc_obj->insert_section($doc_obj->get_end_child($topsection));
+	    my ($pagenum) = $line =~ /(\d+)$/;
+	    $doc_obj->set_metadata_element($cursection, 'Title', $pagenum);
+	    $self->process_text ($dir, $line, $doc_obj, $cursection);
+	    $self->process_images ($dir, $line, $doc_obj, $cursection);
+	}
+    }
+    $file =~ s/\.issue//i;
+    $doc_obj->set_OID ($file);
+    $processor->process ($doc_obj);
+    return 1;
+}
+
+sub process_images {
+    my $self = shift (@_);
+    my ($dir, $page, $doc_obj, $cursection) = @_;
+
+    my $filename = &util::filename_cat ($dir, "images", $page);
+
+    if (-e "$filename.gif") {
+	$self->{'num_image_pages'} ++;
+	$doc_obj->set_metadata_element ($cursection, "hasimg", "1");
+	$doc_obj->set_metadata_element ($cursection, "Source", $page);
+	$doc_obj->associate_file("$filename.gif", "$page.gif", "image/gif");	
+    } elsif ($self->{'create_log'}) {
+	$doc_obj->set_metadata_element ($cursection, "hasimg", "0");
+	print LOGFILE "no fullsize image file for $page\n";
+    }
+
+    if (-e "${filename}_p.gif") {
+	$doc_obj->set_metadata_element ($cursection, "hasprevimg", "1");
+	$doc_obj->set_metadata_element ($cursection, "Source", $page);
+	$doc_obj->associate_file("${filename}_p.gif", "${page}_p.gif", "image/gif");	
+    } elsif ($self->{'create_log'}) {
+	$doc_obj->set_metadata_element ($cursection, "hasprevimg", "0");
+	print LOGFILE "no preview image file for $page\n";
+    }
+}
+
+sub process_text {
+    my $self = shift (@_);
+    my ($dir, $page, $doc_obj, $cursection) = @_;
+    my ($text);
+
+    my $filename = &util::filename_cat ($dir, "text", $page);
+    if (-e "$filename.htm") {
+	$text = $self->get_text ("$filename.htm");
+    } elsif (-e "$filename.txt") {
+	$text = $self->get_text ("$filename.txt");
+    }
+
+    if (defined $text) {
+	$self->{'num_text_pages'} ++;
+	$doc_obj->add_text ($cursection, $text);
+    } elsif ($self->{'create_log'}) {
+	print LOGFILE "no txt or htm file for $page\n";
+    }
+}
+
+sub process_abstract {
+    my $self = shift (@_);
+    my ($filename, $issuekey, $dir, $file, $processor, $meta) = @_;
+
+    my $text = $self->get_text ($filename);
+    if (defined $text) {
+	# remove html header and stuff (assumes all future abstracts
+	# are same format as those for niupepa 01)
+	$text =~ s/^.*?<b>.*?<\/b>//is;
+	
+	$self->{'num_abstracts'} ++;
+	my $doc_obj = new doc ($file, "indexed_doc");
+	my $cursection = $doc_obj->get_top_section();
+	$self->associate_cover_images ($doc_obj, $dir, $issuekey);
+	$doc_obj->set_metadata_element ($cursection, 'Title', "_abstract_ " . 
+					$self->get_title_string($file));
+	$self->set_main_metadata ($doc_obj, $dir);
+	map { $doc_obj->set_metadata_element ($cursection, $_, $meta->{$_}); } keys %$meta;
+	$doc_obj->set_metadata_element ($cursection, "doctype", "Description");
+	$doc_obj->add_text ($cursection, $text);
+	$file =~ s/\.abstract//i;
+	$doc_obj->set_OID ($file . "abstract");
+	$processor->process ($doc_obj);
+	return 1;
+    }
+
+    if ($self->{'create_log'}) {
+	print LOGFILE "abstract file $filename doesn't exist\n";
+    }
+    return 0;
+}
+
+sub process_commentary { 
+    my $self = shift (@_);
+    my ($filename, $issuekey, $dir, $file, $processor) = @_;
+
+    my $text = $self->get_text ($filename);
+
+    return 0 unless defined $text;
+
+    $self->{'commentaries'}->{$issuekey} = 1;
+    my $doc_obj = new doc ($file, "indexed_doc");
+    my $cursection = $doc_obj->get_top_section();
+    $self->associate_cover_images ($doc_obj, $dir, $issuekey);
+    $doc_obj->set_metadata_element ($cursection, 'Title', "_commentary_");
+    $self->set_main_metadata ($doc_obj, $dir);
+    $doc_obj->set_metadata_element ($cursection, "doctype", "Commentary");
+    $doc_obj->add_text ($cursection, $text);
+    $doc_obj->set_OID ($issuekey . "commentary");
+    $processor->process ($doc_obj);
+    return 1;
+}
+
+sub associate_cover_images {
+    my $self = shift (@_);
+    my ($doc_obj, $dir, $issuekey) = @_;
+
+    my $cover = &util::filename_cat ($dir, $issuekey);
+    $doc_obj->associate_file("${cover}on.gif", "${issuekey}/coveron.gif", "image/gif");
+    $doc_obj->associate_file("${cover}of.gif", "${issuekey}/coverof.gif", "image/gif");
+}
+
+# reads in the meta.txt file and sets metadata
+sub set_main_metadata {
+    my $self = shift (@_);
+    my ($doc_obj, $dir) = @_;
+
+    my $metafile = &util::filename_cat ($dir, "meta.txt");
+    return unless (-e $metafile);
+
+    if (!open (METAFILE, $metafile)) {
+	print STDERR "NPPlug: Couldn't read $metafile\n" if $self->{'verbosity'};
+	return;
+    }
+
+    my $cursection = $doc_obj->get_top_section();
+    my $line = "";
+    while (defined ($line = <METAFILE>)) {
+	next unless $line =~ /\w/;
+	chomp $line;
+	if ($line =~ /<([^>]*)>(.*)$/) {
+	    # note we're using set_metadata_element (not add_metadata_element)
+	    # this will override any previously set metadata of the same name
+	    $doc_obj->set_metadata_element ($cursection, $1, $2);
+	} elsif ($self->{'verbosity'}) {
+	    print STDERR "NPPlug: Badly formatted line in $metafile\n";
+	    print STDERR "meta.txt lines should be formatted '<metaname>metavalue'\n";
+	}
+    }
+}
+
+sub get_text {
+    my $self = shift (@_);
+    my ($filename) = @_;
+
+    if (open (FILE, $filename)) {
+	my $text = "";
+	my $line = "";
+	if ($filename =~ /\.(htm|commentary|abstract)$/i) {
+	    my $savedtext = "";
+	    my $foundbody = 0;
+	    while (defined ($line = <FILE>)) {
+		if ($line =~ s/.*?<body[^>]*>//i) {
+		    $foundbody = 1;
+		}
+		$line =~ s/(<\/?html[^>]*>|<\/?head[^>]*>|<\/p>|<\/?font[^>]*>|<\/?body[^>]*>)//ig;
+		if ($foundbody) {
+		    $text .= $line; 
+		} else {
+		    $savedtext .= $line;
+		}
+	    }
+	    close FILE;
+	    if ($foundbody) {return $text;}
+	    else {return $savedtext;}
+
+	} else {
+	    while (defined ($line = <FILE>)) {
+		$line = "<p>\n" unless $line =~ /\w/;
+		$text .= $line;
+	    }
+	    close FILE;
+	    return $text;
+	}
+
+    } else {
+	print STDERR "NPPlug: Warning: get_text() couldn't open $filename\n" 
+	    if $self->{'verbosity'};
+	return undef;
+    }
+}
+
+sub get_title_string {
+    my $self = shift (@_);
+    my ($filename) = @_;
+
+    $filename =~ s/\.(issue|abstract)$//i;
+    my ($series, $vol, $num) = split /\_/, $filename;
+    my $title = "";
+    $title .= "_vol_ $vol" if defined $vol && $vol =~ /\w/;
+    if (defined $num && $num =~ /\w/) {
+	$title .= ": " if defined $vol && $vol =~ /\w/;
+	$title .= "_num_ $num";
+    }
+    return $title;
+}
+
+1;
Index: /tags/start/niupepa/src/recpt/Makefile.in
===================================================================
--- /tags/start/niupepa/src/recpt/Makefile.in	(revision 13666)
+++ /tags/start/niupepa/src/recpt/Makefile.in	(revision 13666)
@@ -0,0 +1,157 @@
+###########################################################################
+#
+# Makefile -- Makefile for niupepalibrary
+# 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.
+#
+###########################################################################
+
+GD = ../../../..
+MAINRECPTDIR = $(GD)/src/recpt
+MAINCOLSERVRDIR = $(GD)/src/colservr
+
+
+AR = ar
+CC = @CC@
+CCFLAGS = @CFLAGS@ -Wall -Wunused -pedantic -W -Woverloaded-virtual
+DEFS = -DNZDL -DQUIET -DSHORT_SUFFIX -DPARADOCNUM -DGSDLSERVER \
+       -DGSDLSERVER @DEFS@
+
+USE_FASTCGI = @USE_FASTCGI@
+ifneq ($(USE_FASTCGI), 1)
+INCLUDES = -I$(MAINRECPTDIR) -I$(MAINCOLSERVRDIR) -I$(GD)/lib \
+	   -I$(GD)/packages/mg -I$(GD)/packages/mg/lib -I$(GD)/packages/mg/src/text 
+else
+INCLUDES = -I$(MAINRECPTDIR) -I$(MAINCOLSERVRDIR) -I$(GD)/lib \
+	   -I$(GD)/packages/mg -I$(GD)/packages/mg/lib -I$(GD)/packages/mg/src/text \
+           -I$(GD)/packages/fcgi/include
+endif
+
+RANLIB = @RANLIB@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+GSDLOS = @gsdlos@
+
+
+COMPILE = $(CC) -c $(CCFLAGS) $(DEFS) $(INCLUDES)
+LINK = $(CC) $(LDFLAGS) -o $@
+
+.SUFFIXES:
+.SUFFIXES: .c .o
+.c.o:
+	$(COMPILE) $<
+
+.SUFFIXES: .cpp .o
+.cpp.o:
+	$(COMPILE) $< 
+
+
+HEADERS = niupepadocaction.h niupepapagedbrowserclass.h \
+	  niupepabrowsetools.h niupepavlistbrowserclass.h \
+	  niupepahlistbrowserclass.h
+
+SOURCES = niupepalibrarymain.cpp niupepadocaction.cpp \
+	  niupepapagedbrowserclass.cpp niupepabrowsetools.cpp \
+	  niupepavlistbrowserclass.cpp niupepahlistbrowserclass.cpp
+
+OBJECTS = niupepalibrarymain.o niupepadocaction.o \
+	  niupepapagedbrowserclass.o niupepabrowsetools.o \
+	  niupepavlistbrowserclass.o niupepahlistbrowserclass.o
+
+EXEC    = niupepalibrary
+
+all : $(EXEC)
+
+install: $(EXEC)
+	install -m 755 -s $(EXEC) $(GD)/cgi-bin/$(EXEC)
+
+clean:
+	rm -f $(OBJECTS) $(EXEC)
+
+depend:
+	makedepend -Y -- $(DEFS) $(INCLUDES) $(CCFLAGS) -- $(SOURCES)
+
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+
+NIUPEPALIBRARY_OBJS = $(OBJECTS) \
+    $(MAINRECPTDIR)/querytools.o \
+    $(MAINRECPTDIR)/browsetools.o \
+    $(MAINRECPTDIR)/browserclass.o \
+    $(MAINRECPTDIR)/vlistbrowserclass.o \
+    $(MAINRECPTDIR)/hlistbrowserclass.o \
+    $(MAINRECPTDIR)/datelistbrowserclass.o \
+    $(MAINRECPTDIR)/invbrowserclass.o \
+    $(MAINRECPTDIR)/pagedbrowserclass.o \
+    $(MAINRECPTDIR)/htmlbrowserclass.o \
+    $(MAINRECPTDIR)/receptionist.o \
+    $(MAINRECPTDIR)/recptconfig.o \
+    $(MAINRECPTDIR)/cgiwrapper.o \
+    $(MAINRECPTDIR)/cgiargs.o \
+    $(MAINRECPTDIR)/action.o \
+    $(MAINRECPTDIR)/converter.o \
+    $(MAINRECPTDIR)/cgiutils.o \
+    $(MAINRECPTDIR)/OIDtools.o \
+    $(MAINRECPTDIR)/htmlgen.o \
+    $(MAINRECPTDIR)/statusaction.o \
+    $(MAINRECPTDIR)/pageaction.o \
+    $(MAINRECPTDIR)/comtypes.o \
+    $(MAINRECPTDIR)/recptproto.o \
+    $(MAINRECPTDIR)/pingaction.o \
+    $(MAINRECPTDIR)/queryaction.o \
+    $(MAINRECPTDIR)/documentaction.o \
+    $(MAINRECPTDIR)/htmlutils.o \
+    $(MAINRECPTDIR)/nullproto.o \
+    $(MAINRECPTDIR)/infodbclass.o \
+    $(MAINRECPTDIR)/formattools.o \
+    $(MAINRECPTDIR)/tipaction.o \
+    $(MAINRECPTDIR)/authenaction.o \
+    $(MAINRECPTDIR)/usersaction.o \
+    $(MAINRECPTDIR)/userdb.o \
+    $(MAINRECPTDIR)/delhistoryaction.o \
+    $(MAINRECPTDIR)/historydb.o \
+    $(MAINCOLSERVRDIR)/mgq.o \
+    $(MAINCOLSERVRDIR)/querycache.o \
+    $(MAINCOLSERVRDIR)/queryinfo.o \
+    $(MAINCOLSERVRDIR)/collectserver.o \
+    $(MAINCOLSERVRDIR)/colservrconfig.o \
+    $(MAINCOLSERVRDIR)/maptools.o \
+    $(MAINCOLSERVRDIR)/filter.o \
+    $(MAINCOLSERVRDIR)/source.o \
+    $(MAINCOLSERVRDIR)/browsefilter.o \
+    $(MAINCOLSERVRDIR)/queryfilter.o \
+    $(MAINCOLSERVRDIR)/phrasequeryfilter.o \
+    $(MAINCOLSERVRDIR)/phrasesearch.o \
+    $(MAINCOLSERVRDIR)/mggdbmsource.o \
+    $(MAINCOLSERVRDIR)/mgsearch.o \
+    $(GD)/lib/gsdllib.a  \
+    $(GD)/packages/mg/src/text/libtextin.a \
+    $(GD)/packages/mg/lib/libmg.a
+
+ifneq ($(USE_FASTCGI), 1)
+NIUPEPALIB_OBJS = $(NIUPEPALIBRARY_OBJS)
+else
+NIUPEPALIB_OBJS = $(NIUPEPALIBRARY_OBJS) $(GD)/packages/fcgi/libfcgi/libfcgi.a
+endif
+
+niupepalibrary: $(NIUPEPALIB_OBJS)
+	$(LINK) $(NIUPEPALIB_OBJS) $(LIBS) 
Index: /tags/start/niupepa/src/recpt/niupepabrowsetools.cpp
===================================================================
--- /tags/start/niupepa/src/recpt/niupepabrowsetools.cpp	(revision 13666)
+++ /tags/start/niupepa/src/recpt/niupepabrowsetools.cpp	(revision 13666)
@@ -0,0 +1,186 @@
+/**********************************************************************
+ *
+ * niupepabrowsetools.cpp -- 
+ * Copyright (C) 1999  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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+#include "niupepabrowsetools.h"
+#include "OIDtools.h"
+#include "cgiutils.h"
+#include "browsetools.h"
+
+static void output_niupepa_controls (cgiargsclass &args, const text_tarray &ibuttons, 
+				     recptproto *collectproto, displayclass &disp,
+				     outconvertclass &outconvert, ostream &textout, 
+				     ostream &logout) {
+
+  bool hastxt = false, hasimg = false, hasprevimg = false;
+  text_tarray buttons;
+  text_t &arg_gg = args["gg"];
+  text_t &arg_d = args["d"];
+  FilterResponse_t response;
+  text_tset metadata;
+  text_t doctype;
+  metadata.insert ("hastxt");
+  metadata.insert ("hasimg");
+  metadata.insert ("hasprevimg");
+  metadata.insert ("doctype");
+  if (!get_info (arg_d, args["c"], metadata, false, collectproto, response, logout))
+    return;
+
+  if (response.docInfo[0].metadata["hastxt"].values[0] == "1") hastxt = true;
+  if (response.docInfo[0].metadata["hasimg"].values[0] == "1") hasimg = true;
+  if (response.docInfo[0].metadata["hasprevimg"].values[0] == "1") hasprevimg = true;
+
+  MetadataInfo_tmap::iterator it = response.docInfo[0].metadata.find ("doctype");
+  if (it != response.docInfo[0].metadata.end()) {
+    if (! (*it).second.values.empty()) doctype = (*it).second.values[0];
+  }
+
+  if (doctype == "Description") {
+    // abstract
+    text_t paper = substr (arg_d.begin(), (arg_d.end() - 8));
+    buttons.push_back ("_document:imageviewpaper_(" + paper + ")");
+    buttons.push_back ("_document:imageabstractintro_");
+
+  } else if (doctype == "Commentary") {
+    // commentary
+
+
+  } else {
+    // newspaper page
+
+    if (arg_gg == "full") {
+      if (hastxt) buttons.push_back ("_document:imageviewtext_");
+      if (hasprevimg) buttons.push_back ("_document:imageprevimage_");
+    } else if (arg_gg == "prev") {
+      if (hastxt) buttons.push_back ("_document:imageviewtext_");
+      if (hasimg) buttons.push_back ("_document:imagefullimage_");
+    } else {
+      if (hasimg) buttons.push_back ("_document:imagefullimage_");
+      if (hasprevimg) buttons.push_back ("_document:imageprevimage_");
+    }
+
+    // see if paper has an abstract
+    text_t abstract;
+    get_top (arg_d, abstract);
+    abstract += "abstract";
+    metadata.erase (metadata.begin(), metadata.end());
+    if (get_info (abstract, args["c"], metadata, false, collectproto, response, logout))
+      buttons.push_back ("_document:imageviewabstract_(" + abstract + "&gg=text)");
+  } 
+
+  if (args["u"] != "1") {
+
+    text_tarray::const_iterator here = ibuttons.begin();
+    text_tarray::const_iterator end = ibuttons.end();
+    
+    while (here != end) {
+      
+      if (*here == "Detach")
+	buttons.push_back ("_document:imagedetach_");
+      else if (*here == "Highlight" && arg_gg == "text") {
+	if (args["hl"] == "1") 
+	  buttons.push_back ("_document:imagenohighlight_");
+	else 
+	  buttons.push_back ("_document:imagehighlight_");
+	
+      } else if ((*here == "Expand Text") && (doctype.empty()) && (arg_gg == "text")) {
+	if (args.getintarg("gt"))
+	  buttons.push_back ("_document:imagecontracttext_");
+	else 
+	  buttons.push_back ("_document:imageexpandtext_");
+      }
+      here ++;
+    }
+    
+    here = buttons.begin();
+    end = buttons.end();
+    int count = 0;
+    while (here != end) {
+      if ((count != 0) && ((count % 3) == 0)) textout << "<br>\n";
+      textout << outconvert << disp << *here;
+      count ++;
+      here ++;
+    }
+  }
+}
+
+
+
+void output_niupepa_toc (cgiargsclass &args, browsermapclass *browsermap,
+			 formatinfo_t &formatinfo, recptproto *collectproto,
+			 displayclass &disp, outconvertclass &outconvert,
+			 ostream &textout, ostream &logout) {
+
+  int tabcount = 0;
+  text_t &arg_d = args["d"];
+  
+  // get the cover image (if there is one) and the control buttons
+  // if we're inside a book
+  if (!arg_d.empty()) {
+    textout << outconvert << disp 
+	    << "<center>\n"
+	    << "<p><table cellpadding=0 cellspacing=0 width=_pagewidth_><tr>\n"
+	    << "<td align=left valign=top>\n";
+    output_titles (args, collectproto, formatinfo, disp, outconvert, textout, logout);
+    textout << "<p>\n";
+  }
+
+  if (formatinfo.DocumentContents || arg_d.empty()) {
+    if (args.getintarg("gc") == 1) {
+      
+      // expanded table of contents
+      expanded_contents (args, tabcount, false, browsermap, formatinfo, 
+			 collectproto, disp, outconvert, textout, logout);
+    } else {
+      
+      // contracted table of contents
+      contracted_contents (args, tabcount, false, browsermap, formatinfo, 
+			   collectproto, disp, outconvert, textout, logout);
+    }
+  }
+
+  if (!arg_d.empty()) {
+    output_niupepa_controls (args, formatinfo.DocumentButtons, collectproto, 
+			     disp, outconvert, textout, logout);
+
+    textout << outconvert << disp
+	    << "</td>\n"
+	    << "<td align=right valign=top>"
+	    << "_document:imagethispaper_\n"
+	    << "</td></tr>\n"
+	    << "</table>\n"
+	    << "</center>\n";
+  }
+  textout << outconvert << disp << "_iconblankbar_\n";
+}
+
+
+
+
+
+
+
+
Index: /tags/start/niupepa/src/recpt/niupepabrowsetools.h
===================================================================
--- /tags/start/niupepa/src/recpt/niupepabrowsetools.h	(revision 13666)
+++ /tags/start/niupepa/src/recpt/niupepabrowsetools.h	(revision 13666)
@@ -0,0 +1,45 @@
+/**********************************************************************
+ *
+ * niupepabrowsetools.h -- 
+ * Copyright (C) 1999  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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+
+#ifndef NIUPEPABROWSETOOLS_H
+#define NIUPEPABROWSETOOLS_H
+
+#include "gsdlconf.h"
+#include "text_t.h"
+#include "cgiargs.h"
+#include "display.h"
+#include "recptproto.h"
+#include "formattools.h"
+#include "browsetools.h"
+
+void output_niupepa_toc (cgiargsclass &args, browsermapclass *browsermap,
+			 formatinfo_t &formatinfo, recptproto *collectproto,
+			 displayclass &disp, outconvertclass &outconvert,
+			 ostream &textout, ostream &logout);
+#endif
+
Index: /tags/start/niupepa/src/recpt/niupepadocaction.cpp
===================================================================
--- /tags/start/niupepa/src/recpt/niupepadocaction.cpp	(revision 13666)
+++ /tags/start/niupepa/src/recpt/niupepadocaction.cpp	(revision 13666)
@@ -0,0 +1,281 @@
+/**********************************************************************
+ *
+ * niupepadocaction.cpp -- 
+ * 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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2000/03/08 20:44:50  sjboddie
+   Initial revision
+
+   Revision 1.2  1999/09/07 22:19:50  sjboddie
+   added GPL header
+
+   Revision 1.1  1999/08/29 23:35:07  sjboddie
+   niupepa receptionist
+
+ */
+
+
+#include <string.h>
+#include "niupepadocaction.h"
+#include "niupepabrowsetools.h"
+#include "OIDtools.h"
+#include "querytools.h"
+#include "unitool.h"
+
+niupepadocaction::niupepadocaction () {
+  // this action uses cgi variable "gg" as well as
+  // those used by the standard documentaction
+
+  cgiarginfo arg_ainfo;
+
+  // in this action "gg" is the format of the
+  // document to view (i.e. "text", "prev" or "full")
+  arg_ainfo.shortname = "gg";
+  arg_ainfo.longname = "document format";
+  arg_ainfo.multiplechar = true;
+  arg_ainfo.defaultstatus = cgiarginfo::weak;
+  arg_ainfo.argdefault = "text";
+  arg_ainfo.savedarginfo = cgiarginfo::must;
+  argsinfo.addarginfo (NULL, arg_ainfo);
+}
+
+niupepadocaction::~niupepadocaction () {
+}
+
+void niupepadocaction::set_java_macros (cgiargsclass &args, displayclass &disp) {
+
+  text_t javaimagescontent = "_javaextras__javacommentary__javaviewabstract__javaviewpaper__javaabstractintro_";
+
+  text_t &arg_gg = args["gg"];
+
+  if (arg_gg == "full")
+    javaimagescontent += "_javaprevimage__javaviewtext_";
+  else if (arg_gg == "prev")
+    javaimagescontent += "_javafullimage__javaviewtext_";
+  else 
+    javaimagescontent += "_javafullimage__javaprevimage_";
+
+	
+  int arg_gt = args.getintarg("gt");
+  int arg_hl = args.getintarg("hl");
+
+  text_tarray::const_iterator button_here = formatinfo.DocumentButtons.begin();
+  text_tarray::const_iterator button_end = formatinfo.DocumentButtons.end();
+
+  while (button_here != button_end) {
+    if (*button_here == "Detach") 
+      javaimagescontent += "_javadetach_";
+    else if (*button_here == "Expand Text" && arg_gg == "text") {
+      if (arg_gt == 1)
+	javaimagescontent += "_javacontracttext__javacontinue_";
+      else if (arg_gt == 2)
+	javaimagescontent += "_javacontracttext_";
+      else
+	javaimagescontent += "_javaexpandtext_";
+    } else if (*button_here == "Highlight" && arg_gg == "text") {
+      if (arg_hl == 1)
+	javaimagescontent += "_javanohighlighting_";
+      else 
+	javaimagescontent += "_javahighlighting_";
+    }
+    button_here ++;
+  }
+  disp.setmacro ("javaimagescontent", "document", javaimagescontent);
+}
+
+// define all the macros which are related to pages generated
+// by this action. we also load up the formatinfo structure 
+// here (it's used in do_action as well as here)
+void niupepadocaction::define_internal_macros (displayclass &disp, cgiargsclass &args,
+					       recptprotolistclass *protos, ostream &logout) {
+
+
+  // define_internal_macros sets the following macros (as well as those defined
+  // by documentaction::define_internal_macros)
+
+  // _httpthiscommentary_   the link to the papers commentary
+
+  // _httpiconthispaper_    the http address of the cover image
+  
+  // _thispapericonwidth_   the width and height of the cover image
+  // _thispapericonheight_ 
+
+
+  documentaction::define_internal_macros (disp, args, protos, logout);
+
+  text_t &arg_d = args["d"];
+  text_t &collection = args["c"];
+  text_tset metadata;
+  FilterResponse_t response;
+
+  recptproto *collectproto = protos->getrecptproto (collection, logout);
+  if (collectproto == NULL) return;
+
+  if (!arg_d.empty()) {
+    // we're at document level
+
+    text_t series = substr (arg_d.begin(), findchar (arg_d.begin(), arg_d.end(), '_'));
+    if ((series.size() > 10) && (substr ((series.end()-10), series.end()) == "commentary")) {
+      series = substr (series.begin(), (series.end()-10));
+    } else {
+      text_t commentaryOID = series + "commentary";
+
+      // set _httpthiscommentary_ if commentary exists
+      if (get_info (commentaryOID, collection, metadata, false, collectproto, response, logout))
+	disp.setmacro ("httpthiscommentary", "document", "_httpdocument_&gg=text&d=" + commentaryOID);
+    }
+    // _httpiconthispaper_
+    disp.setmacro ("httpiconthispaper", "document", "_httpcollimg_/" + series + "/cover");
+
+    // _thispapericonwidth_ and _thispapericonheight_
+    disp.setmacro ("thispapericonwidth", "document", "_" + series + "width_");
+    disp.setmacro ("thispapericonheight", "document", "_" + series + "height_");
+  }
+}
+
+void niupepadocaction::output_document (const text_t &OID, cgiargsclass &args, 
+					recptproto *collectproto, displayclass &disp, 
+					outconvertclass &outconvert, ostream &textout, 
+					ostream &logout) {
+  FilterResponse_t response;
+  text_tset metadata;
+  text_t &arg_gg = args["gg"];
+  text_t &collection = args["c"];
+
+  if (arg_gg == "full") {
+    
+    // fullsize image
+
+    metadata.insert ("hasimg");
+    metadata.insert ("Source");
+    if (!get_info (OID, collection, metadata, false, collectproto, response, logout))
+      return;
+    if (response.docInfo[0].metadata["hasimg"].values[0] == "1") {
+      textout << outconvert << disp 
+	      << "<p><img src=\"_httpcollimg_/_thisOID_/" 
+	      << response.docInfo[0].metadata["Source"].values[0] << ".gif\">\n";
+    } else {
+      textout << outconvert << disp << "_missingimage_\n";
+    }
+
+  } else if (arg_gg == "prev") {
+
+    // preview image
+
+    metadata.insert ("hasprevimg");
+    metadata.insert ("Source");
+    if (!get_info (OID, collection, metadata, false, collectproto, response, logout))
+      return;
+    if (response.docInfo[0].metadata["hasprevimg"].values[0] == "1") {
+      textout << outconvert << disp 
+	      << "<center>\n"
+	      << "<p><img src=\"_httpcollimg_/_thisOID_/" 
+	      << response.docInfo[0].metadata["Source"].values[0] << "_p.gif\">\n"
+	      << "</center>\n";
+    } else {
+      textout << outconvert << disp << "_missingimage_\n";
+    }
+  } else {
+
+    // text
+    metadata.insert ("hastxt");
+    if (!get_info (OID, collection, metadata, false, collectproto, response, logout))
+      return;
+    if (response.docInfo[0].metadata["hastxt"].values[0] == "1") {
+      documentaction::output_document (OID, args, collectproto, disp, 
+				       outconvert, textout, logout);
+    } else {
+      textout << outconvert << disp << "_missingtext_\n";
+    }
+  }
+}
+
+
+// this is only overridden so we can call output_niupepa_toc instead
+// of output_toc -- we should find a tidier way to do this both here
+// and in the cstr collection
+bool niupepadocaction::do_action (cgiargsclass &args, recptprotolistclass *protos, 
+				  browsermapclass *browsers, displayclass &disp, 
+				  outconvertclass &outconvert, ostream &textout, 
+				  ostream &logout) {
+
+
+  // must have a valid collection server
+  recptproto *collectproto = protos->getrecptproto (args["c"], logout);
+  if (collectproto == NULL) {
+    logout << "documentaction::do_action called with NULL collectproto\n";
+    textout << outconvert << disp << "_document:header_\n" 
+	    << "Error: Attempt to get document without setting collection\n"
+	    << "_document:footer_\n";
+  } else {  
+    
+    text_t OID = args["d"];
+    if (OID.empty()) OID = args["cl"];
+    if (OID.empty()) {
+      textout << outconvert << disp << "Document contains no data_document:footer_\n";
+      return true;
+    }
+
+    if (formatinfo.DocumentUseHTML) {
+      
+      if (!args["d"].empty()) {
+	if (args["f"] == "1") {
+	  textout << outconvert << disp 
+		  << "<html><head></head>\n"
+		  << "<frameset rows=\"68,*\" noresize border=0>\n"
+		  << "<frame scrolling=no frameborder=0 src=\"_gwcgi_?e=_compressedoptions_&a=p&p=nav\">\n"
+		  << "<frame name=\"documenttop\" frameborder=0 src=\"_gwcgi_?e=_compressedoptions_&a=d&d=" 
+		  << args["d"] << "\">"
+		  << "<noframes>\n"
+		  << "<p>You must have a frame enabled browser to view this.</p>\n"
+		  << "</noframes>\n"
+		  << "</frameset>\n"
+		  << "</html>\n";
+	} else {
+	  output_document (OID, args, collectproto, disp, outconvert, textout, logout);	
+	}
+	return true;
+      }
+    }
+
+    textout << outconvert << disp << "_document:header_\n"
+	    << "_document:content_\n";
+      
+    // output the table of contents
+    output_niupepa_toc (args, browsers, formatinfo, collectproto, 
+			disp, outconvert, textout, logout);
+    
+    // output the document text
+    if (!args["d"].empty()) {
+      textout << "<p>\n";
+      output_document (OID, args, collectproto, disp, outconvert, textout, logout);
+    }
+
+    textout << outconvert << disp << "_document:footer_\n";
+  }
+  return true;
+}
Index: /tags/start/niupepa/src/recpt/niupepadocaction.h
===================================================================
--- /tags/start/niupepa/src/recpt/niupepadocaction.h	(revision 13666)
+++ /tags/start/niupepa/src/recpt/niupepadocaction.h	(revision 13666)
@@ -0,0 +1,62 @@
+/**********************************************************************
+ *
+ * niupepadocaction.h -- 
+ * 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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+
+#ifndef NIUPEPADOCACTION_H
+#define NIUPEPADOCACTION_H
+
+#include "documentaction.h"
+
+class niupepadocaction : public documentaction {
+
+protected:
+
+  void set_java_macros (cgiargsclass &args, displayclass &disp);
+
+  void output_document (const text_t &OID, cgiargsclass &args, 
+  			recptproto *collectproto, displayclass &disp, 
+  			outconvertclass &outconvert, ostream &textout, 
+  			ostream &logout);
+
+public:
+  niupepadocaction ();
+  virtual ~niupepadocaction ();
+
+  bool do_action (cgiargsclass &args, recptprotolistclass *protos, 
+		  browsermapclass *browsers, displayclass &disp, 
+		  outconvertclass &outconvert, ostream &textout, 
+		  ostream &logout);
+  
+  void define_internal_macros (displayclass &disp, cgiargsclass &args,
+			       recptprotolistclass *protos, ostream &logout);
+};
+
+
+
+#endif
+
+
Index: /tags/start/niupepa/src/recpt/niupepahlistbrowserclass.cpp
===================================================================
--- /tags/start/niupepa/src/recpt/niupepahlistbrowserclass.cpp	(revision 13666)
+++ /tags/start/niupepa/src/recpt/niupepahlistbrowserclass.cpp	(revision 13666)
@@ -0,0 +1,125 @@
+/**********************************************************************
+ *
+ * niupepahlistbrowserclass.cpp -- 
+ * Copyright (C) 1999  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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2000/03/08 20:44:50  sjboddie
+   Initial revision
+
+
+ */
+
+
+#include "niupepahlistbrowserclass.h"
+#include <assert.h>
+#include "OIDtools.h"
+
+niupepahlistbrowserclass::niupepahlistbrowserclass () {
+}
+
+niupepahlistbrowserclass::~niupepahlistbrowserclass () {
+}
+
+
+// overridden for niupepa so CL2 (date classification) wraps in the correct place
+// should probably do this in a more general way some time
+int niupepahlistbrowserclass::output_section_group (ResultDocInfo_t &section, cgiargsclass &args,
+						    const text_t &/*collection*/, int colnumber, 
+						    format_t *formatlistptr, bool use_table, 
+						    text_tset &metadata, bool &getParents, 
+						    recptproto *collectproto, displayclass &disp, 
+						    outconvertclass &outconvert, ostream &textout, 
+						    ostream &logout) {
+
+  // expanded contents are going to cause some nasty recursions
+  // so we'll only continue if being passed the current section
+  if ((args["gc"] == 1) && (section.OID != args["d"])) return 0;
+
+  // get all siblings
+  FilterResponse_t response;
+  text_t &arg_cl = args["cl"];
+  get_children (section.OID + ".pr", args["c"], metadata, getParents, 
+		collectproto, response, logout);
+
+					
+  if (use_table || colnumber > 0) {
+    textout << "<table><tr><td>";
+    // get tab size
+    text_t tab; int itab;
+    disp.expandstring ("Global", "_tabwidth_", tab);
+    itab = tab.getint();
+    if (colnumber > 0) textout << outconvert << disp 
+			       << "<img src=\"_httpimg_/space.gif\" width=" 
+			       << (itab*colnumber) << ">";
+    textout << "</td>\n";
+  }
+
+  textout << "<table><tr>\n";
+
+  ResultDocInfo_tarray::iterator tsibling = response.docInfo.begin();
+  ResultDocInfo_tarray::iterator esibling = response.docInfo.end();
+
+  text_t icon, link;
+  int scount = 1;
+  while (tsibling != esibling) {
+
+    bool highlight = false;
+    textout << "<td";
+    if (scount != 4 && scount != 5 && scount != 6 &&
+	scount != 7 && scount != 10 && scount != 11)
+      textout << " colspan=2";
+    textout << ">";
+
+    text_t &doctype = (*tsibling).metadata["doctype"].values[0];
+
+    if ((*tsibling).OID == section.OID) {
+      link.clear();
+      highlight = true;
+    } else {
+      link = "<a href=\"_httpdocument_";
+      if (doctype == "classify") 
+	link += "&cl=" + (*tsibling).OID + "\">";
+      else
+	link += "&cl=" + arg_cl + "&d=" + (*tsibling).OID + "\">";
+    }
+
+    textout << outconvert << disp 
+	    << get_formatted_string (*tsibling, formatlistptr, link, icon, highlight);
+
+    textout << "</td>\n";
+    if (scount == 12)
+      textout << "</tr><tr>\n";
+
+    tsibling ++;
+    scount ++;
+  }
+
+  textout << "<td colspan=2></td></tr></table>\n";
+  if (use_table  || colnumber > 0) textout << "</tr></table>\n";
+  return 0;
+}
+
Index: /tags/start/niupepa/src/recpt/niupepahlistbrowserclass.h
===================================================================
--- /tags/start/niupepa/src/recpt/niupepahlistbrowserclass.h	(revision 13666)
+++ /tags/start/niupepa/src/recpt/niupepahlistbrowserclass.h	(revision 13666)
@@ -0,0 +1,51 @@
+/**********************************************************************
+ *
+ * niupepahlistbrowserclass.h -- 
+ * Copyright (C) 1999  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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+
+#ifndef NIUPEPAHLISTBROWSERCLASS_H
+#define NIUPEPAHLISTBROWSERCLASS_H
+
+#include "hlistbrowserclass.h"
+
+class niupepahlistbrowserclass : public hlistbrowserclass {
+protected:
+
+public:
+  niupepahlistbrowserclass ();
+  virtual ~niupepahlistbrowserclass ();
+
+  int output_section_group (ResultDocInfo_t &section, cgiargsclass &args,
+			    const text_t &collection, int colnumber, format_t *formatlistptr, 
+			    bool use_table, text_tset &metadata, bool &getParents,
+			    recptproto *collectproto, displayclass &disp, 
+			    outconvertclass &outconvert, ostream &textout, 
+			    ostream &logout);
+  
+};
+
+#endif
+
Index: /tags/start/niupepa/src/recpt/niupepalibrarymain.cpp
===================================================================
--- /tags/start/niupepa/src/recpt/niupepalibrarymain.cpp	(revision 13666)
+++ /tags/start/niupepa/src/recpt/niupepalibrarymain.cpp	(revision 13666)
@@ -0,0 +1,191 @@
+/**********************************************************************
+ *
+ * niupepalibrarymain.cpp -- 
+ * 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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2000/03/08 20:44:49  sjboddie
+   Initial revision
+
+   Revision 1.2  1999/09/07 22:19:50  sjboddie
+   added GPL header
+
+   Revision 1.1  1999/08/29 23:35:08  sjboddie
+   niupepa receptionist
+
+ */
+
+#include "receptionist.h"
+#include "cgiwrapper.h"
+#include "nullproto.h"
+#include "collectserver.h"
+#include "filter.h"
+#include "browsefilter.h"
+#include "queryfilter.h"
+#include "infodbclass.h"
+#include "mgsearch.h"
+#include "mggdbmsource.h"
+#include "fileutil.h"
+#include <assert.h>
+
+#include "action.h"
+#include "statusaction.h"
+#include "pageaction.h"
+#include "pingaction.h"
+#include "queryaction.h"
+#include "niupepadocaction.h"
+#include "authenaction.h"
+#include "usersaction.h"
+#include "authenaction.h"
+
+#include "browserclass.h"
+#include "niupepavlistbrowserclass.h"
+#include "niupepahlistbrowserclass.h"
+#include "datelistbrowserclass.h"
+#include "invbrowserclass.h"
+#include "niupepapagedbrowserclass.h"
+#include "htmlbrowserclass.h"
+
+#include "recptconfig.h"
+
+int main () {
+  receptionist recpt;
+  nullproto nproto;
+  
+  // add a collection server
+  text_tarray collections;
+  collections.push_back ("niupepa");
+
+  // get gsdlhome (if we fail the error will be picked up later -- in
+  // cgiwrapper)
+  text_t gsdlhome;
+  site_cfg_read (gsdlhome);
+
+  text_tarray::const_iterator thiscol = collections.begin();
+  text_tarray::const_iterator endcol = collections.end();
+
+  while (thiscol != endcol) {
+
+    // this memory is created but never destroyed
+    // we're also not doing any error checking to make sure we didn't
+    // run out of memory
+    collectserver *cserver = new collectserver();
+    gdbmclass *gdbmhandler = new gdbmclass();
+    mgsearchclass *mgsearch = new mgsearchclass();
+    
+    // add a null filter
+    filterclass *filter = new filterclass ();
+    cserver->add_filter (filter);
+    
+    // add a browse filter
+    browsefilterclass *browsefilter = new browsefilterclass();
+    browsefilter->set_gdbmptr (gdbmhandler);
+    cserver->add_filter (browsefilter);
+    
+    // add a query filter
+    queryfilterclass *queryfilter = new queryfilterclass();
+    queryfilter->set_gdbmptr (gdbmhandler);
+    queryfilter->set_mgsearchptr (mgsearch);
+    cserver->add_filter (queryfilter);
+
+    // add a mg and gdbm source
+    mggdbmsourceclass *mggdbmsource = new mggdbmsourceclass ();
+    mggdbmsource->set_gdbmptr (gdbmhandler);
+    mggdbmsource->set_mgsearchptr (mgsearch);
+    cserver->add_source (mggdbmsource);
+    
+    // inform collection server and everything it contains about its
+    // collection name
+    cserver->configure ("collection", *thiscol);
+    
+    nproto.add_collectserver (cserver);
+    thiscol ++;
+  }
+  
+  // add the protocol to the receptionist
+  recpt.add_protocol (&nproto);
+
+  // add other converters
+  utf8inconvertclass utf8inconvert;
+  utf8outconvertclass utf8outconvert;
+  recpt.add_converter ("u", &utf8inconvert, &utf8outconvert);
+
+  if (!gsdlhome.empty()) {
+    mapinconvertclass gbinconvert;
+    gbinconvert.setmapfile (gsdlhome, "gbku", 0x25a1);
+    mapoutconvertclass gboutconvert;
+    gboutconvert.setmapfile (gsdlhome, "ugbk", 0xa1f5);
+    recpt.add_converter ("g", &gbinconvert, &gboutconvert);
+  }
+
+  // the list of actions. Note: these actions will become invalid
+  // at the end of this function.
+  statusaction astatusaction;
+  astatusaction.set_receptionist (&recpt);
+  recpt.add_action (&astatusaction);
+
+  pageaction apageaction;
+  recpt.add_action (&apageaction);
+
+  pingaction apingaction;
+  recpt.add_action (&apingaction);
+
+  queryaction aqueryaction;
+  recpt.add_action (&aqueryaction);
+
+  niupepadocaction adocumentaction;
+  recpt.add_action (&adocumentaction);
+
+  usersaction ausersaction;
+  recpt.add_action (&ausersaction);
+
+  authenaction aauthenaction;
+  aauthenaction.set_receptionist(&recpt);
+  recpt.add_action (&aauthenaction);
+
+  // list of browsers
+  niupepavlistbrowserclass avlistbrowserclass;
+  recpt.add_browser (&avlistbrowserclass);
+  recpt.setdefaultbrowser ("VList");
+
+  niupepahlistbrowserclass ahlistbrowserclass;
+  recpt.add_browser (&ahlistbrowserclass);
+
+  datelistbrowserclass adatelistbrowserclass;
+  recpt.add_browser (&adatelistbrowserclass);
+
+  invbrowserclass ainvbrowserclass;
+  recpt.add_browser (&ainvbrowserclass);
+
+  niupepapagedbrowserclass apagedbrowserclass;
+  recpt.add_browser (&apagedbrowserclass);
+
+  htmlbrowserclass ahtmlbrowserclass;
+  recpt.add_browser (&ahtmlbrowserclass);
+
+  cgiwrapper (recpt, "niupepa");
+  return 0;
+}
Index: /tags/start/niupepa/src/recpt/niupepapagedbrowserclass.cpp
===================================================================
--- /tags/start/niupepa/src/recpt/niupepapagedbrowserclass.cpp	(revision 13666)
+++ /tags/start/niupepa/src/recpt/niupepapagedbrowserclass.cpp	(revision 13666)
@@ -0,0 +1,113 @@
+/**********************************************************************
+ *
+ * niupepapagedbrowserclass.cpp -- 
+ * Copyright (C) 1999  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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2000/03/08 20:44:50  sjboddie
+   Initial revision
+
+
+ */
+
+
+#include "niupepapagedbrowserclass.h"
+#include <assert.h>
+#include "OIDtools.h"
+
+niupepapagedbrowserclass::niupepapagedbrowserclass () {
+}
+
+niupepapagedbrowserclass::~niupepapagedbrowserclass () {
+}
+
+// if the "gp" (go to page) argument is set we need to set
+// the "d" argument to the corresponding page
+// also want to set "d" argument to first child if we're at
+// an 'Invisible' top level
+// this is overridden for niupepa collection as we want to set "gg"
+// argument to be 'prev' if it's text and there isn't any text,
+// 'full' if it's prev and there is no prev, 'text' if it's prev
+// and there's no full or prev, 'prev' if it's full and there's
+// no full, 'text' if it's full and there's no full or prev.
+// default to text if all else fails 
+void niupepapagedbrowserclass::processOID (cgiargsclass &args, recptproto *collectproto,
+					   ostream &logout) {
+
+  text_t &arg_d = args["d"];
+  text_t &arg_gp = args["gp"];
+  text_t &arg_gg = args["gg"];
+  text_tset metadata;
+  FilterResponse_t response;
+
+  bool hastxt = false, hasimg = false, hasprevimg = false; 
+
+  if ((!arg_d.empty()) && (!arg_gp.empty()) && (is_number (arg_gp))) {
+    text_t top;
+    get_top (arg_d, top);
+    metadata.insert ("Title");
+    get_children (top, args["c"], metadata, false, collectproto, response, logout);
+    ResultDocInfo_tarray::iterator dochere = response.docInfo.begin();
+    ResultDocInfo_tarray::iterator docend = response.docInfo.end();
+    while (dochere != docend) {
+      if ((*dochere).metadata["Title"].values[0] == arg_gp) {
+        arg_d = (*dochere).OID;
+        break;
+      }
+      dochere ++;
+    }
+
+  } else if (!arg_d.empty() && is_top(arg_d)) { // if top level doc, check if not invisible
+    metadata.insert("thistype");
+    if (get_info(arg_d, args["c"], metadata, false, collectproto, response, logout)) {
+      text_t type = response.docInfo[0].metadata["thistype"].values[0];
+      if (type=="Invisible") { // display first child
+        arg_d = arg_d + ".fc";
+      }
+    }
+  }
+
+  metadata.erase (metadata.begin(), metadata.end());
+  metadata.insert ("hastxt");
+  metadata.insert ("hasimg");
+  metadata.insert ("hasprevimg");
+  if (get_info(arg_d, args["c"], metadata, false, collectproto, response, logout)) {
+    if (response.docInfo[0].metadata["hastxt"].values[0] == "1") hastxt = true;
+    if (response.docInfo[0].metadata["hasimg"].values[0] == "1") hasimg = true;
+    if (response.docInfo[0].metadata["hasprevimg"].values[0] == "1") hasprevimg = true;
+  }
+
+  if (arg_gg == "text" && !hastxt) {
+    if (hasprevimg) arg_gg = "prev";
+    else if (hasimg) arg_gg = "full";
+  } else if (arg_gg == "prev" && !hasprevimg) {
+    if (hasimg) arg_gg = "full";
+    else arg_gg = "text";
+  } else if (arg_gg == "full" && !hasimg) {
+    if (hasprevimg) arg_gg = "prev";
+    else arg_gg = "text";
+  }
+}
Index: /tags/start/niupepa/src/recpt/niupepapagedbrowserclass.h
===================================================================
--- /tags/start/niupepa/src/recpt/niupepapagedbrowserclass.h	(revision 13666)
+++ /tags/start/niupepa/src/recpt/niupepapagedbrowserclass.h	(revision 13666)
@@ -0,0 +1,46 @@
+/**********************************************************************
+ *
+ * niupepapagedbrowserclass.h -- 
+ * Copyright (C) 1999  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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+
+#ifndef NIUPEPAPAGEDBROWSERCLASS_H
+#define NIUPEPAPAGEDBROWSERCLASS_H
+
+#include "pagedbrowserclass.h"
+
+class niupepapagedbrowserclass : public pagedbrowserclass {
+protected:
+
+public:
+
+  niupepapagedbrowserclass ();
+  virtual ~niupepapagedbrowserclass ();
+
+  virtual void processOID (cgiargsclass &args, recptproto *collectproto,
+			   ostream &logout);
+};
+
+#endif
Index: /tags/start/niupepa/src/recpt/niupepavlistbrowserclass.cpp
===================================================================
--- /tags/start/niupepa/src/recpt/niupepavlistbrowserclass.cpp	(revision 13666)
+++ /tags/start/niupepa/src/recpt/niupepavlistbrowserclass.cpp	(revision 13666)
@@ -0,0 +1,145 @@
+/**********************************************************************
+ *
+ * niupepavlistbrowserclass.cpp -- 
+ * Copyright (C) 1999  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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+/*
+   $Log$
+   Revision 1.1  2000/03/08 20:44:50  sjboddie
+   Initial revision
+
+
+ */
+
+#include "niupepavlistbrowserclass.h"
+#include <assert.h>
+#include "OIDtools.h"
+
+niupepavlistbrowserclass::niupepavlistbrowserclass () {
+}
+
+niupepavlistbrowserclass::~niupepavlistbrowserclass () {
+}
+
+void niupepavlistbrowserclass::load_metadata_defaults (text_tset &metadata) {
+  metadata.insert ("haschildren");
+  metadata.insert ("doctype");
+  metadata.insert ("abstract");
+}
+
+// get_link_icon attempts to work out what type of icon should be displayed for
+// the given section and what it should link to.
+// overridden for niupepa to add links/icons for abstracts as well as 
+// papers
+void niupepavlistbrowserclass::get_link_icon (ResultDocInfo_t &section, cgiargsclass &args,
+					      const text_t &collink, text_t &link, text_t &icon) {
+
+  link = "<a href=\"_httpdocument_" + collink;
+  icon = "_document:icontext_";
+  int haschildren = 0;
+
+  if (section.metadata.count("haschildren") > 0)
+    haschildren = section.metadata["haschildren"].values[0].getint();
+
+  text_t doctype;
+  if (section.metadata.count("doctype") > 0)
+    doctype = section.metadata["doctype"].values[0];
+
+  text_t abstract;
+  if (section.metadata.count("abstract") > 0)
+    abstract = section.metadata["abstract"].values[0];
+
+  text_t &arg_d = args["d"];
+  text_t &arg_cl = args["cl"];
+
+  if (args["a"] == "q") {
+    // query results
+    if (doctype == "Description") {
+      icon = "_document:iconabstract_";
+      link += "&gg=text";
+    } else if (doctype == "Commentary") {
+      icon = "_document:iconcommentary_";
+      link += "&gg=text";
+    } else {
+      if (is_top (section.OID)) icon = "_document:iconclosedbook_";
+      else if (haschildren == 1) icon = "_document:iconclosedfolder_";
+    }
+    link += "&cl=search&d=" + section.OID + "\">";
+
+  } else if (!arg_d.empty()) {
+    // document level
+    if (is_top(section.OID)) {
+      icon = "_document:iconopenbook_";
+      if (arg_cl == "search") link = "<a href=\"_httpquery_\">";
+      else link += "&cl=" + arg_cl + "\">";
+    
+    } else if (haschildren == 1) {
+      if ((args["gc"] == "1") || 
+	  (is_child_of (section.OID, arg_d)) ||
+	  (section.OID == arg_d)) {
+	icon = "_document:iconopenfolder_";
+	link += "&cl=" + arg_cl + "&d=" + section.OID + ".pr\">";
+      } else {
+	icon = "_document:iconclosedfolder_";
+	link += "&cl=" + arg_cl + "&d=" + section.OID + "\">";
+      }
+    } else link += "&cl=" + arg_cl + "&d=" + section.OID + "\">";
+
+  } else {
+    // classification level
+    if (haschildren == 1) {
+      if (doctype == "classify") {
+	if ((args["gc"] == "1") || 
+	    (is_child_of (section.OID, arg_cl)) || 
+	    (section.OID == arg_cl)) {
+	  icon = "_document:iconopenbookshelf_";
+	  link += "&cl=" + section.OID + ".pr\">" + icon + "</a>";
+	} else {
+	  icon = "_document:iconclosedbookshelf_";
+	  link += "&cl=" + section.OID + "\">" + icon + "</a>";
+	}
+      } else {
+	icon = "_document:iconclosedbook_";
+	if (!abstract.empty())
+	  link += "&gg=text&cl=" + arg_cl + "&d=" + abstract + "\">"
+	    + "_document:iconabstract_</a>" + link +
+	    "&cl=" + arg_cl + "&d=" + section.OID + "\">"
+	    + icon + "</a>";
+	else 
+	  link += "&cl=" + arg_cl + "&d=" + section.OID + "\">"
+	    + icon + "</a>";
+      }
+    } else {
+      if (doctype == "classify") link = "";
+      else if (doctype == "Commentary")
+	link += "&gg=text&cl=" + arg_cl + "&d=" + section.OID + "\">"
+	  + "_document:iconcommentary_</a>";
+      else if (doctype == "Description")
+	link += "&cl=" + arg_cl + "&d=" + section.OID + "\">"
+	  + "_document:iconabstract_</a>";
+      else link += "&cl=" + arg_cl + "&d=" + section.OID + "\">";
+    }
+  }
+}
Index: /tags/start/niupepa/src/recpt/niupepavlistbrowserclass.h
===================================================================
--- /tags/start/niupepa/src/recpt/niupepavlistbrowserclass.h	(revision 13666)
+++ /tags/start/niupepa/src/recpt/niupepavlistbrowserclass.h	(revision 13666)
@@ -0,0 +1,49 @@
+/**********************************************************************
+ *
+ * niupepavlistbrowserclass.h -- 
+ * Copyright (C) 1999  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.
+ *
+ * $Id$
+ *
+ *********************************************************************/
+
+
+#ifndef NIUPEPAVLISTBROWSERCLASS_H
+#define NIUPEPAVLISTBROWSERCLASS_H
+
+#include "vlistbrowserclass.h"
+
+class niupepavlistbrowserclass : public vlistbrowserclass {
+protected:
+
+public:
+  niupepavlistbrowserclass ();
+  virtual ~niupepavlistbrowserclass ();
+
+  void load_metadata_defaults (text_tset &metadata);
+
+protected:
+  
+  void get_link_icon (ResultDocInfo_t &section, cgiargsclass &args,
+		      const text_t &collink, text_t &link, text_t &icon);
+};
+
+#endif
Index: /tags/start/nsa1/etc/collect.cfg
===================================================================
--- /tags/start/nsa1/etc/collect.cfg	(revision 13666)
+++ /tags/start/nsa1/etc/collect.cfg	(revision 13666)
@@ -0,0 +1,38 @@
+creator         sjboddie@cs.waikato.ac.nz
+maintainer      sjboddie@cs.waikato.ac.nz
+public          true
+beta            true
+indexes         document:Title paragraph:People document:ProgNumber document:CatNum document:zzabn document:text
+defaultindex    document:text
+plugin          ZIPPlug
+plugin          GMLPlug 
+plugin          ArcPlug 
+plugin          RecPlug 
+plugin          BRSPlug -input_encoding ascii
+
+dontgdbm ProgNumber
+dontgdbm People
+dontgdbm CatNum
+dontgdbm zzabn
+
+#ccscols         nsa1 bfi1 bfi2 bbc1 bbc2
+
+# Collection specific metadata
+#--
+collectionmeta  collectionname      "National Sound Archive (1900-2002)"
+collectionmeta  iconcollection      "_httpprefix_/collect/nsa1/images/bbc_online.gif"
+collectionmeta .document:Title      "titles"
+collectionmeta .paragraph:People    "people"
+collectionmeta .document:ProgNumber "programme numbers"
+collectionmeta .document:CatNum     "catalogue numbers"
+collectionmeta .document:zzabn      "zzAB/zzAN"
+collectionmeta .document:text       "all fields"
+collectionmeta collectionextra      ""
+
+
+format DocumentButtons ""
+format DocumentHeading ""
+
+format          SearchVList \
+    "<td valign=top>[link][icon][/link]</td><td>{If}{[ItemTitle],[ItemTitle]; [Title],[Title]}</td><td width=160>[Date]</td>"
+
Index: /tags/start/nsa1/perllib/docsave.pm
===================================================================
--- /tags/start/nsa1/perllib/docsave.pm	(revision 13666)
+++ /tags/start/nsa1/perllib/docsave.pm	(revision 13666)
@@ -0,0 +1,234 @@
+###########################################################################
+#
+# docsave.pm
+# 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 document processor saves a document in the 
+# archives directory of a collection
+
+# use with doc.pm rewound to version 1.25
+
+
+package docsave;
+
+use arcinfo;
+use docproc;
+use util;
+
+
+sub BEGIN {
+    @ISA = ('docproc');
+}
+
+sub new {
+    my ($class, $collection, $archive_info, $verbosity, 
+	$gzip, $groupsize, $outhandle) = @_;
+    my $self = new docproc ();
+    
+    
+    $groupsize=1 unless defined $groupsize;
+    $self->{'collection'} = $collection;
+    $self->{'archive_info'} = $archive_info;
+    $self->{'verbosity'} = $verbosity;
+    $self->{'gzip'} = $gzip;
+    
+    $self->{'groupsize'} = $groupsize;
+    $self->{'gs_count'} = 0;
+    
+    $self->{'outhandle'} = STDERR;
+    $self->{'outhandle'} = $outhandle if defined $outhandle;
+    
+    # set a default for the archive directory
+    $self->{'archive_dir'} = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, "archives");
+    
+    $self->{'sortmeta'} = undef;
+
+    if ($groupsize != 1)
+    {
+	print STDERR "Warning: -groupsize not supported in BBC collection\n";
+	print STDERR "         documents are automatically grouped by date\n";
+    }
+    
+    return bless $self, $class;
+}
+
+sub setarchivedir {
+    my $self = shift (@_);
+    my ($archive_dir) = @_;
+
+    $self->{'archive_dir'} = $archive_dir;
+    &util::mk_all_dir ($archive_dir);
+
+    $self->{'lower_year'} = 1900;
+
+    my @lt_array =localtime(time);
+    my $lt_year = $lt_array[5];
+    $self->{'upper_year'} = 1900 + $lt_year;
+
+    print STDERR "*" x 70, "\n";
+    print STDERR "Processing dates between ";
+    print STDERR "$self->{'lower_year'} and $self->{'upper_year'}\n";
+    print STDERR "*" x 70, "\n\n";
+
+    # set up table of file handles -- one for each year
+    $self->{'date_files'} = [];
+    my $i;
+    for ($i=$self->{'lower_year'}; $i<=$self->{'upper_year'}; $i++)
+    {
+	my $FH = "OUTDATE$i";
+	my $date_file = &util::filename_cat($archive_dir, "$i.gml");
+	my $short_date_file = "$i.gml";
+
+	if (!open ($FH, ">$date_file")) 
+	{
+	    print STDERR "Warning: ";
+	    print STDERR "docsave::new could not write to file $date_file\n";
+	    $self->{'date_files'}->[$i-$self->{'lower_year'}] = undef;
+	    next;
+	}
+
+	$self->{'date_files'}->[$i-$self->{'lower_year'}] 
+	    = { 'short_filename' => $short_date_file, 
+		'long_filename' => $date_file, 
+		'OUTDATE' => $FH };	
+    }
+}
+
+sub process {
+    my $self = shift (@_);
+    my ($doc_obj) = @_;
+
+    my $archive_dir = $self->{'archive_dir'};
+    my $OID = $doc_obj->get_OID();
+    $OID = "NULL" unless defined $OID;
+
+    if (scalar(@{$doc_obj->get_assoc_files()})>0)
+    {
+	# get the document's directory.
+	my $doc_info = $self->{'archive_info'}->get_info($OID);
+	my $doc_dir = "";
+	if (defined $doc_info && scalar(@$doc_info) >= 1) {
+	    # this OID already has an assigned directory, use the
+	    # same one.
+	    $doc_dir = $doc_info->[0];
+	    $doc_dir =~ s/\/?doc\.gml(\.gz)?$//;
+	    
+	} else {
+	    # have to get a new document directory
+	    my $doc_dir_rest = $OID;
+	    my $doc_dir_num = 0;
+	    do {
+		$doc_dir .= "/" if $doc_dir_num > 0;
+		if ($doc_dir_rest =~ s/^(.{1,8})//) {
+		    $doc_dir .= $1;
+		    $doc_dir_num++;
+		}
+	    } while ($doc_dir_rest ne "" && 
+		     ((-d &util::filename_cat ($archive_dir, "$doc_dir.dir")) || 
+		      ($self->{'archive_info'}->size() >= 1024 && $doc_dir_num < 2)));
+	    $doc_dir .= ".dir";
+	}
+
+	&util::mk_all_dir ("$archive_dir/$doc_dir");
+
+	# copy all the associated files, add this information as metadata
+	# to the document
+	my @assoc_files = ();
+	foreach $assoc_file (@{$doc_obj->get_assoc_files()}) {
+	    if (-e $assoc_file->[0]) {
+		my $afile = &util::filename_cat($archive_dir, $doc_dir, $assoc_file->[1]);
+		&util::cp ($assoc_file->[0], $afile);
+		$doc_obj->add_metadata ($doc_obj->get_top_section(), 
+					"gsdlassocfile", 
+					"$assoc_file->[1]:$assoc_file->[2]");
+	    } else {
+		print STDERR "docsave::process couldn't copy the associated file " .
+		    "$assoc_file->[0] to $afile\n";
+	    }
+	}
+    }
+
+    # save this document to appropriate DATE file
+    my $top_section = $doc_obj->get_top_section();
+    my $date_metadata = $doc_obj->get_metadata_element($top_section, "Date");
+
+    my ($year) = ($date_metadata =~ m/^(\d{4})/);
+    my $df_index = $year - $self->{'lower_year'};
+
+    if ($df_index<0)
+    {
+	print STDERR "Warning: Year $year is earlier than lower bound.";
+    }
+    elsif (!defined $self->{'date_files'}->[$df_index])
+    {
+	print STDERR "Warning: No file data present for year $year.";
+    }
+    else
+    {
+	my $df_rec = $self->{'date_files'}->[$df_index];
+	my $FH = $df_rec->{'OUTDATE'};
+
+	$doc_obj->output_section("docsave::".$FH, $top_section);
+    }    
+}
+
+sub close_file_output
+{
+    my ($self) = @_;
+
+    my $i;
+    for ($i=$self->{'lower_year'}; $i<=$self->{'upper_year'}; $i++)
+    {
+	my $date_rec = $self->{'date_files'}->[$i-$self->{'lower_year'}];
+	close $date_rec->{'OUTDATE'};
+
+	my $short_doc_file = $date_rec->{'short_filename'};
+	my $doc_file = $date_rec->{'long_filename'};
+
+	if (-z $doc_file)
+	{
+	    &util::rm($doc_file);
+	    next;
+	}
+
+	if ($self->{'gzip'}) 
+	{
+	    my $doc_file = $self->{'gs_filename'};
+	    `gzip $doc_file`;
+	    $doc_file .= ".gz";
+	    $short_doc_file .= ".gz";
+	    if (!-e $doc_file) 
+	    {
+		print STDERR "error while gzipping: $doc_file doesn't exist\n";
+		return 0;
+	    }
+	}
+
+	# store reference in the archive_info
+	$self->{'archive_info'}->add_info("Year_$i", $short_doc_file);
+    }
+
+    return 1;
+}
+
+1;
Index: /tags/start/nsa1/perllib/plugins/BRSPlug.pm
===================================================================
--- /tags/start/nsa1/perllib/plugins/BRSPlug.pm	(revision 13666)
+++ /tags/start/nsa1/perllib/plugins/BRSPlug.pm	(revision 13666)
@@ -0,0 +1,825 @@
+
+# plugin which processes an the BBC Sound archive exported in an ASCII format
+
+package BRSPlug;
+
+use BasPlug;
+use ghtml;
+
+sub BEGIN 
+{
+    @ISA = ('BasPlug');
+    unshift (@INC, "$ENV{'GSDLCOLLECTDIR'}/perllib");
+}
+
+%Exclude = ();
+
+
+# Note: sext is short for scrollable text
+
+#field_id  label     disp_type crit_type width  height  brs_para
+#----------------------------------------------------------------
+#10      sport prdcr     text    text    30      1       T006
+#1       text            sext    text    40      16      TEXT
+#16      scol ref text   text    text    30      1       SCOL
+#19      date            text    date    10      1       D001
+#25      Item title      text    text    20      1       T001
+#26      B/W Seqs        text    text    30      1       S001
+#27      Medium          text    text    30      1       S002
+#28      shot type       text    text    30      1       S003
+#29      B/W Prog/Item   text    text    30      1       S004
+#30      Seqs            text    text    10      1       S005
+#31      Format          text    text    30      1       S006
+#32      prog/item       text    text    30      1       S007
+#35      reg libno       text    text    30      1       S008
+#36      reg tape no     text    text    30      1       S009
+#37      C Indicator     text    text    30      1       S010
+#38      C Holder        text    text    30      1       T002
+#39      cprd ind        text    text    30      1       S011
+#40      cprd name       text    text    30      1       T003
+#44      reference       sext    text    30      5       R001
+#49      prog num        text    text    10      1       PRNO
+#59      news title      text    text    30      1       T005
+#65      cat num         text    text    10      1       CATN
+#72      Record number   text    text    30      1       T007
+#73      rx_date         text    date    10      1       S013
+#74      Music performer text    text    30      2       T008
+#75      Composer        text    text    30      2       T009
+#76      mono/stereo     text    text    30      1       S014
+#77      music medium    text    text    30      1       S015
+#82      Sound Tech      text    text    30      1       S016
+#83      Music publisher text    text    30      1       S017
+#84      music tape      text    text    30      1       T012
+#89      catalogue       text    text    3       1       CODE
+#104     subcat          text    text    10      1       SUBC
+#106     prog title      text    text    40      1       TTLE
+#109     screen type     text    text    10      1       DOCT
+#110     stock title     text    text    30      1       T013
+#113     stock ln 4      text    text    30      1       T015
+#114     stock lib 1     text    text    30      1       S020
+#115     stock lib 2     text    text    30      1       S021
+#----------------------------------------------------------------
+
+
+my @brs_field_table 
+  = (
+      { field_name => "TTLE",  field_id   => 106, label => "Prog title",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 40,      height     => 1       },
+      { field_name => "T001",  field_id   => 25,  label => "Item title",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 20,      height     => 1       },
+      { field_name => "T005",  field_id   => 59,  label => "News title",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "T013",  field_id   => 110, label => "Stock title",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "T007",  field_id   => 72,  label => "Record number",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "TEXT",  field_id   => 1,   label => "Text",
+        disp_type  => "scrl",  crit_type  => "text",
+	width      => 40,      height     => 16      },
+
+      { field_name => "T006",  field_id   => 10,  label => "Sport prdcr",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "SCOL",  field_id   => 16,  label => "Scol ref text",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "D001",  field_id   => 19,  label => "Date",
+        disp_type  => "text",  crit_type  => "date",
+        width      => 10,      height     => 1       },
+      { field_name => "S001",  field_id   => 26,  label => "B/W Seqs",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S002",  field_id   => 27,  label => "Medium",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S003",  field_id   => 28,  label => "Shot type",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S004",  field_id   => 29,  label => "B/W Prog/Item",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S005",  field_id   => 30,  label => "Seqs",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 10,      height     => 1       },
+      { field_name => "S006",  field_id   => 31,  label => "Format",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S007",  field_id   => 32,  label => "Prog/item",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S008",  field_id   => 35,  label => "Reg libno",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S009",  field_id   => 36,  label => "Reg tape no",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S010",  field_id   => 37,  label => "C Indicator",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "T002",  field_id   => 38,  label => "C Holder",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S011",  field_id   => 39,  label => "Cprd ind",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "T003",  field_id   => 40,  label => "Cprd name",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "R001",  field_id   => 44,  label => "Reference",
+        disp_type  => "scrl",  crit_type  => "text",
+        width      => 30,      height     => 5       },
+      { field_name => "PRNO",  field_id   => 49,  label => "Prog num",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 10,      height     => 1       },
+      { field_name => "CATN",  field_id   => 65,  label => "Cat num",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 10,      height     => 1       },
+      { field_name => "S013",  field_id   => 73,  label => "Rx_date",
+        disp_type  => "text",  crit_type  => "date",
+        width      => 10,      height     => 1       },
+      { field_name => "T008",  field_id   => 74,  label => "Music performer",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 2       },
+      { field_name => "T009",  field_id   => 75,  label => "Composer",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 2       },
+      { field_name => "S014",  field_id   => 76,  label => "Mono/stereo",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S015",  field_id   => 77,  label => "Music medium",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S016",  field_id   => 82,  label => "Sound Tech",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S017",  field_id   => 83,  label => "Music publisher",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "T012",  field_id   => 84,  label => "Music tape",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "CODE",  field_id   => 89,  label => "Catalogue",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 3,      height     => 1       },
+      { field_name => "SUBC",  field_id   => 104, label => "Subcat",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 10,      height     => 1       },
+      { field_name => "DOCT",  field_id   => 109, label => "Screen type",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 10,      height     => 1       },
+      { field_name => "T015",  field_id   => 113, label => "Stock ln 4",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S020",  field_id   => 114, label => "Stock lib 1",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       },
+      { field_name => "S021",  field_id   => 115, label => "Stock lib 2",
+        disp_type  => "text",  crit_type  => "text",
+        width      => 30,      height     => 1       }
+     );
+
+
+my @brs_title_list = ("TTLE", "T001", "T005", "T013", "T007", "zzTI");
+my %cat_num_list = ();
+
+sub new {
+    my ($class) = @_;
+    my $self = new BasPlug ($class, @_);
+
+    return bless $self, $class;
+}
+
+sub get_default_process_exp {
+    my $self = shift (@_);
+
+    return q^(?i)\.brs$^;
+}
+
+my $brs_doc_count = 0;
+my $brs_dot_count = 0;
+my $brs_line_no = 0;
+
+sub brs_error
+{
+    my ($file, $mess, $outhandle) = @_;
+
+    print $outhandle "Malformed BRS recorded at line $brs_line_no in $file:\n";
+    print $outhandle "  $mess\n";
+}
+
+sub read_brs_record
+{
+    my ($recordref, $file, $outhandle) = @_;
+
+    my $extra_trigger = '\s*>';
+    my $text_divider = "-" x 78;
+    my $text_end = "..R001";
+
+    # Print "." to signify processing if enough records have been read in
+    $brs_doc_count++;
+    if (($brs_doc_count % 10) == 0)
+    {
+	print $outhandle ".";
+	$brs_dot_count++;
+	print $outhandle "\n" if (($brs_dot_count % 80) == 0);
+    }
+
+    my $brs_rec = undef;
+    my $line = undef;
+
+    # read in the record
+    my @brs_lines = split /\n/, $$recordref;
+
+    while (scalar(@brs_lines)>0)
+    {
+	$line = shift(@brs_lines);
+	$line =~ s/\cM//g;
+
+	$brs_line_no++;
+
+	if  ($line =~ m/^\.\.([A-Z]|[0-9]){4}:$/) 
+	{
+	    my $field_name = substr($line,2,4);
+
+	    if ($field_name eq "TEXT")
+	    {
+		my $text_above = "";
+		my $text_extra = "";
+		my $text_below = "";
+		
+		my $add_mode = "above";
+		
+		while (scalar(@brs_lines)>0)
+		{
+		    last if ($brs_lines[0] =~ m/^$text_end/);
+
+		    $line = shift(@brs_lines);
+		    $brs_line_no++;
+		    
+		    if ($line =~ m/^$text_divider/)
+		    {
+			$add_mode = "below";
+			next;
+		    }
+		    
+		    if ($line =~ m/^$extra_trigger/)
+		    {
+			$text_extra .= "$line\n";
+			$add_mode = "below";
+			next;
+		    }
+			
+		    if ($line =~ m/^\.\.([A-Z]|[0-9]){4}:/)
+		    {
+			if ($line =~ m/^\.\.TEXT/)
+			{
+			    $add_mode = "above";
+			    next;
+			}
+			else
+			{
+			    brs_error($file, "Unexpected field $line", $outhandle);
+			    # put field name back
+			    unshift(@brs_lines, $line); 
+			    $brs_line_no--;
+			    last;
+			}
+		    }
+		    
+		    if ($line !~ m/^\s+(-){10,}$/)
+		    {
+			if ($add_mode eq "above")
+			{
+			    $text_above .= "$line ";
+			}
+			else
+			{
+			    $text_below .= "$line ";
+			}
+		    }
+		}
+
+		$brs_rec->{TEXTA} .= $text_above if ($text_above ne "");
+		$brs_rec->{TEXTB} .= $text_below if ($text_below ne "");
+		$brs_rec->{TEXTE} .= $text_extra if ($text_extra ne "");
+	    }
+	    elsif ($field_name eq "R001")
+	    {
+		# read zz fields until end of record
+		    
+		while (scalar(@brs_lines)>0)
+		{
+		    $line = shift(@brs_lines);
+		    $brs_line_no++;
+
+		    if ($line =~ m/^(zz[A-Z]+)( +)(.*)/)
+		    {
+			my $field_name = $1;
+			my $field_text = $3;
+
+			while (scalar(@brs_lines)>0)
+			{
+			    my $line_ahead = $brs_lines[0];
+
+			    last if ($line_ahead =~ m/^zz[A-Z]+/);
+					
+			    $line = shift(@brs_lines);
+			    $brs_line_no++;
+			    
+			    $field_text .= $line;
+			}
+			
+			if (!defined($brs_rec->{$field_name}))
+			{
+			    $brs_rec->{$field_name} = [$field_text];
+			}
+			else
+			{
+			    push(@{$brs_rec->{$field_name}},$field_text);
+			}
+		    }
+		    else
+		    {
+			brs_error($file, "Unexpected field $line", $outhandle);
+		    }
+		}
+	    }
+	    else
+	    {
+		my $field_entry = "";
+		while ($brs_lines[0] !~ m/^..([A-Z]|[0-9]){4}:$/)
+		{
+		    $field_entry .= shift(@brs_lines);
+		    $brs_line_no++;
+		    last if (scalar(@brs_lines)==0);
+		}		    
+
+		if (!defined($brs_rec->{$field_name}))
+		{
+		    $brs_rec->{$field_name} = $field_entry;
+		}
+		else
+		{
+		    brs_error($file, "$field_name already defined.", $outhandle);
+		}
+	    }		
+	}
+	else
+	{
+	    brs_error($file, "Malformed field: $line.", $outhandle);
+	}
+    }
+
+    # format the programme number if required
+    &format_prognum($brs_rec);
+
+    return ($brs_rec);
+}
+
+my $brs_processed_count = 0;
+
+sub brs_full_record_in_html
+{
+    my ($doc_obj,$cursection,$brs_rec) = @_;
+
+    my $html_table = "";
+    my $table_line = "";
+    my $cell_count = 0;
+    my $long_lines = "";
+
+    my $i;
+    for ($i=0; $i<=$#brs_field_table; $i++)
+    {
+	my $field_name = $brs_field_table[$i]->{'field_name'};
+	if (defined($brs_rec->{$field_name}))
+	{
+	    my $field_label = $brs_field_table[$i]->{'label'};
+	    my $field_value = $brs_rec->{$field_name};
+
+	    # these fields get their own line
+	    if ($field_label =~ /^(Prog|Item|News|Stock) title$/) {
+		my $safe_value = $field_value;
+		&ghtml::urlsafe ($safe_value);
+		$long_lines .= "<tr valign=top><td><b>$field_label:</b></td><td colspan=5>";
+		$long_lines .= "<a href=\"_httpquerytitle_&q=$safe_value\">$field_value</a></td></tr>\n";
+		$long_lines .= "$field_value</td></tr>\n";
+		
+	    } else {
+		
+		if (($cell_count>0) && ($cell_count%3 == 0))
+		{
+		    $html_table .= "\n<tr valign=top>\n$table_line\n</tr>\n";
+		    $table_line = "";
+		}
+		$cell_count++;
+		if ($field_name eq "D001") # a Dublin core style date
+		{
+		    my @mon_convert 
+			= ("Jan", "Feb", "Mar", "Apr", "May", "Jun",
+			   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
+		    
+		    my ($year,$monnum,$day) 
+			= ($field_value =~ m/(\d{4})(\d{2})(\d{2})/);
+		    my $moneng = $mon_convert[$monnum-1];
+		    
+		    $field_value = "$day $moneng $year";
+
+		} elsif ($field_name eq "PRNO") {
+		    my $safe_value = $field_value;
+		    &ghtml::urlsafe ($safe_value);
+		    $field_value = "<a href=\"_httpqueryprogname_&q=$safe_value\">$field_value</a>";
+
+		} elsif ($field_name eq "CATN") {
+		    my $safe_value = $field_value;
+		    &ghtml::urlsafe ($safe_value);
+		    $field_value = "<a href=\"_httpquerycatnum_&q=$safe_value\">$field_value</a>";
+
+		} elsif ($field_name eq "T003") {
+		    my $safe_value = $field_value;
+		    &ghtml::urlsafe ($safe_value);
+		    $field_value = "<a href=\"_httpqueryzzabn_&q=$safe_value\">$field_value</a>";
+		}
+		
+		$table_line .= "<td><b>$field_label:</b></td><td>$field_value</td>\n";
+	    }
+	}
+    }
+
+    if ($cell_count%3 != 0) {
+	$table_line .= "<td colspan=" . (3-($cell_count%3))*2 . "></td>";
+    }
+
+    $html_table .= "\n<tr>\n$table_line\n</tr>\n";    
+    $html_table = "<table>\n$long_lines$html_table\n</table>\n";
+
+    $doc_obj->add_utf8_text($cursection, $html_table);
+}
+
+sub process_brs_record
+{
+    my ($processor, $brs_rec, $file, $outhandle) = @_;
+
+    if (defined($brs_rec))
+    {
+
+	# only include those records in the chosen subcats - these lines
+	# should be commented out to build the entire collection
+
+	# National Sound Archive collection
+	if (!defined ($brs_rec->{'SUBC'}) || 
+	    $brs_rec->{'SUBC'} !~ /^(RADCOMP|RADIOX|RADPROG|RADNEWS|BDSPROG|UNCATRAD|RADIOREF|WILDSOUND)$/) {
+	    return;
+	}
+
+	# British Film Institute collection
+#	if (!defined ($brs_rec->{'SUBC'}) || 
+#	    $brs_rec->{'SUBC'} !~ /^(LONPROG|NEWS)$/) {
+#	    return;
+#	}
+
+	# "the rest" collection
+#	if (!defined ($brs_rec->{'SUBC'}) || 
+#	    $brs_rec->{'SUBC'} =~ /^(LONPROG|NEWS|RADCOMP|RADIOX|RADPROG|RADNEWS|BDSPROG|UNCATRAD|RADIOREF)$/) {
+#	    return;
+#	}
+
+	# don't include the secret stuff ;-)
+	if (defined ($brs_rec->{'SUBC'}) && $brs_rec->{'SUBC'} eq "HISTORY") {
+	    print STDERR "excluding secret stuff - line $brs_line_no\n";
+	    return;
+	}
+
+
+	my $doc_obj = new doc ($file, "indexed_doc");
+	$brs_processed_count++;
+
+	my $cursection = $doc_obj->get_top_section();
+
+	my $found_match = "no";
+
+	my $pot_title;	
+	foreach $pot_title ( @brs_title_list )
+	{
+	    if (defined ($brs_rec->{$pot_title}))
+	    {
+		my $title = "";
+
+		if ($pot_title =~ m/^zz/)
+		{
+		    my $zz_join = join(" ", @{$brs_rec->{$pot_title}});
+		    my @zz_split = split(" ", $zz_join);
+		    map { $title .= "$_ " if ($_ !~ m/^xx/); } @zz_split;
+		}
+		else
+		{
+		    $title =  $brs_rec->{$pot_title};
+		}
+
+		my $tl_ref = $doc_obj->get_metadata ($cursection, "Title");
+
+		if (scalar(@$tl_ref==0))
+		{
+		    $doc_obj->add_utf8_metadata ($cursection, "Title", $title);
+		}
+		else
+		{
+		    my $exists = "no";
+		    
+		    map { $exists = "yes" if ($title eq $_); } @$tl_ref;
+		    if ($exists eq "no")
+		    {
+			$doc_obj->add_utf8_metadata($cursection, "Title", $title);
+		    }
+		}
+		$found_match = "yes";
+	    }
+	}
+	if ($found_match eq "no")
+	{
+	    if (defined($brs_rec->{TEXTA}))
+	    {
+		my $sub_title = substr($brs_rec->{TEXTA},0,60) . " ... ";
+		$doc_obj->add_utf8_metadata ($cursection, "Title", $sub_title);
+	    }
+	    elsif (defined($brs_rec->{TEXTB}))
+	    {
+		my $sub_title = substr($brs_rec->{TEXTB},0,60) . " ... ";
+		$doc_obj->add_utf8_metadata ($cursection, "Title", $sub_title);
+	    }
+	    else
+	    {
+		print $outhandle " No title or text for record ending at line ";
+		print $outhandle $brs_line_no-1, " ";
+	    }
+	}
+
+	if (defined($brs_rec->{'T001'})) # item title
+	{
+	    $doc_obj->add_utf8_metadata ($cursection, "ItemTitle", $brs_rec->{'T001'});
+	}
+	
+	if (defined($brs_rec->{'D001'})) # date
+	{
+	    $doc_obj->add_utf8_metadata ($cursection, "Date", $brs_rec->{'D001'});
+	}
+	else
+	{
+	    print $outhandle " No date for record ending at line ";
+	    print $outhandle $brs_line_no-1, " ";
+	}
+
+	if (defined($brs_rec->{'PRNO'})) # programme number
+	{
+	    $doc_obj->add_utf8_metadata ($cursection, "ProgNumber", $brs_rec->{'PRNO'});
+	}
+
+	if (defined($brs_rec->{'CATN'})) # catalogue number
+	{
+	    $doc_obj->add_utf8_metadata ($cursection, "CatNum", $brs_rec->{'CATN'});
+	}
+
+	# zzAN, zzAB and T003 fields
+	if (defined($brs_rec->{'zzAB'}) || defined($brs_rec->{'zzAN'}) || defined($brs_rec->{'T003'}))
+	{
+	    my $zzabn = "";
+	    if (defined($brs_rec->{'zzAB'})) {
+		foreach my $a (@{$brs_rec->{'zzAB'}}) {
+		    $a =~ s/[^a-zA-Z0-9]//g;
+		    $zzabn .= " " . $a;
+		}
+	    } 
+	    if (defined($brs_rec->{'zzAN'})) {
+		foreach my $a (@{$brs_rec->{'zzAN'}}) {
+		    $a =~ s/[^a-zA-Z0-9]//g;
+		    $zzabn .= " " . $a;
+		}
+	    } 
+	    if (defined($brs_rec->{'T003'})) {
+		my $value = $brs_rec->{'T003'};
+		$value =~ s/[^a-zA-Z0-9]//g;
+		$zzabn .= " " . $value;
+	    } 
+	    print STDERR "zzabn: '$zzabn'\n";
+	    $doc_obj->add_utf8_metadata ($cursection, "zzabn", $zzabn);
+	}
+
+	if (defined($brs_rec->{zzN}))
+	{
+	    my $name;
+	    foreach $name (@{$brs_rec->{zzN}})
+	    {
+		$doc_obj->add_utf8_metadata ($cursection, "People", $name);
+	    }
+	}
+
+	brs_full_record_in_html($doc_obj,$cursection,$brs_rec);
+
+	if (defined($brs_rec->{TEXTA}))
+	{
+
+	    my $desc_texta = "<h3>Description</h3>$brs_rec->{TEXTA}";
+	    $doc_obj->add_utf8_text ($cursection, $desc_texta);
+
+	    if (defined($brs_rec->{TEXTE}))
+	    {
+		my $raw_texte = $brs_rec->{TEXTE};
+		$raw_texte =~ s/^\s*>\s*/<li>/mg;
+		
+		my $test_empty = $raw_texte;
+		$test_empty =~ s/(<li>)+//g;
+		
+		if ($test_empty ne "")
+		{
+		    my $desc_texte = $raw_texte;
+		    $desc_texte =~ s/^<li>(.*)$/<li><i>$1<\/i>/mg;
+		    $desc_texte = "<p>Additional:<ul>$desc_texte</ul>";
+		    $doc_obj->add_utf8_text ($cursection, $desc_texte);
+		}
+	    }
+	}
+
+	if (defined($brs_rec->{TEXTB}))
+	{
+	    my $desc_textb = "<h3>Comments</h3>$brs_rec->{TEXTB}";
+	    $doc_obj->add_utf8_text($cursection, $desc_textb);
+	}
+
+	my $full_text = "";
+	$full_text .= "$brs_rec->{TEXTA}\n" if (defined($brs_rec->{TEXTA}));
+	$full_text .= "$brs_rec->{TEXTE}\n" if (defined($brs_rec->{TEXTE}));
+	$full_text .= "$brs_rec->{TEXTB}\n" if (defined($brs_rec->{TEXTB}));
+
+	my @zz_list = ( "zzPG", "zzLO", "zzN" );
+	my $zz;
+	foreach $zz ( @zz_list)
+	{
+	    if (defined($brs_rec->{$zz}))
+	    {
+		my $filtered_text = "";
+
+		my $name;
+		foreach $name (@{$brs_rec->{$zz}})
+		{
+		    my @split_zz = split(' ',$name);
+		    map { $filtered_text .= "$_ " if ($_ =~ m/^xx/) } @split_zz
+		}
+	
+		$full_text .= "$filtered_text\n";
+	    }
+	}
+
+	# format zz fields (tail end of record)
+	my $zz_html = "<table>\n";
+
+	my $pot_zz;
+	foreach $pot_zz (keys %{$brs_rec})
+	{
+	    if ($pot_zz =~ m/^zz/)
+	    {
+		my $zz = $pot_zz;
+		my $name;
+		foreach $name (@{$brs_rec->{$zz}})
+		{
+		    if ($zz eq "zzN") {
+			my $safe_name = $name;
+			&ghtml::urlsafe ($safe_name);
+			$zz_html .= "<tr><td><b>$zz:</b></td><td><a href=\"_httpquerypeople_&q=$safe_name\">$name</a></td></tr>\n";
+		    } elsif ($zz =~ /^zzA[BN]$/) {
+			my $safe_name = $name;
+			&ghtml::urlsafe ($safe_name);
+			$zz_html .= "<tr><td><b>$zz:</b></td><td><a href=\"_httpqueryzzabn_&q=$safe_name\">$name</a></td></tr>\n";
+
+		    } else {
+			$zz_html .= "<tr><td><b>$zz:</b></td><td>$name</td></tr>\n";
+		    }
+		}
+	    }
+	}
+	$zz_html .= "</table>\n";
+	$doc_obj->add_utf8_text($cursection, $zz_html);
+
+	# add OID - we'll use the catalog number (hoping it's unique)
+	my $cat_num = $brs_rec->{'CATN'};
+	if (!defined $cat_num) {
+	    die "bugger!!\n";
+	}
+	if (defined ($cat_num_list{$cat_num})) {
+	    print $outhandle "WARNING: catalog number $cat_num used more than once\n";
+	}
+	$doc_obj->set_OID ("bbc" . $cat_num);
+	$cat_num_list{$cat_num} = 1;
+    
+	# process the document
+	$processor->process($doc_obj);
+    }
+    else
+    {
+	print $outhandle "BRS record empty\n";
+    }
+    
+}
+
+sub read {
+    my $self = shift (@_);
+    my ($pluginfo, $base_dir, $file, $metadata, $processor, $maxdocs) = @_;
+    my $outhandle = $self->{'outhandle'};
+
+    my $filename = &util::filename_cat($base_dir, $file);
+#    return 0 if $self->{'block_exp'} ne "" && $filename =~ /$self->{'block_exp'}/;
+    if ($filename !~ /$self->{'process_exp'}/ || !-f $filename) {
+	return undef;
+    }
+#    my $plugin_name = ref ($self);
+    $file =~ s/^[\/\\]+//; # $file often begins with / so we'll tidy it up
+    
+    # create a new document
+#    my $doc_obj = new doc ($filename, "indexed_doc");
+    
+    # read in file ($text will be in utf8)
+#    my $text = "";
+#    $self->read_file ($filename, \$text);
+
+#    if ($text !~ /\w/) {
+#	print $outhandle "$plugin_name: ERROR: $file contains no text\n" if $self->{'verbosity'};
+#	return 0;
+#    }
+
+    # text is always plain ascii
+    undef $/;
+    open (FILE, $filename) || die;
+    my $text = <FILE>;
+    close FILE;
+    $/ = "\n";
+
+
+    # include any metadata passed in from previous plugins 
+    # note that this metadata is associated with the top level section
+#    $self->extra_metadata ($doc_obj, $doc_obj->get_top_section(), $metadata);
+
+    print $outhandle "BBC Sound Archive Plug for BRS format: processing $file\n"
+	if $self->{'verbosity'} > 1;
+
+    my @records = split /\*\*\* BRS DOCUMENT BOUNDARY \*\*\*\s+/, $text;
+    $text = "";
+
+    foreach $record (@records) {
+	next if $record !~ /\w/; # first record will be empty
+	my $brs_rec = &read_brs_record(\$record, $file, $self->{'outhandle'});
+	&process_brs_record ($processor, $brs_rec, $file, $self->{'outhandle'});
+    }
+
+    print $outhandle "\nNumber of BRS records = $brs_doc_count\n";
+    print $outhandle "Number of BRS records processed = $brs_processed_count\n";
+
+    return 1; # processed the file
+}
+
+sub end {
+    my $self = shift (@_);
+    my ($processor) = @_;
+
+    $processor->close_file_output() if defined $processor;
+}
+
+sub format_prognum {
+    my ($brs_rec) = @_;
+
+    return unless defined $brs_rec->{'PRNO'};
+
+    my $old_num = $brs_rec->{'PRNO'};
+
+    if (defined $brs_rec->{'magazine'}) {
+	if ($brs_rec->{'PRNO'} =~ /^\S\S /) { # space at position 3
+	    if ($brs_rec->{'magazine'} =~ /(\d+)/) {
+		# algorithm A
+		my $magnumber = $1;
+		$brs_rec->{'PRNO'} =~ /(\S\S) (\S\S)(\S+)/;
+		$brs_rec->{'PRNO'} = $2 . $1 . $3 . $magnumber;
+	    } else {
+		# common algorithm
+		$brs_rec->{'PRNO'} =~ /(\S\S) (\S\S)(\S+)/;
+		$brs_rec->{'PRNO'} = $2 . $1 . $3;
+	    }
+	}
+    } else {
+	if ($brs_rec->{'PRNO'} =~ /^\S\S / && $brs_rec->{'PRNO'} !~ /:/) { # space at position 3 and no colon
+	    # common algorithm
+	    $brs_rec->{'PRNO'} =~ /(\S\S) (\S\S)(\S+)/;
+	    $brs_rec->{'PRNO'} = $2 . $1 . $3;
+	} elsif ($brs_rec->{'PRNO'} =~ /^(\S):(\S\S) (\S\S)(\S+)/) { # colon at position 2 and space at position 5
+	    # algorithm B
+	    $brs_rec->{'PRNO'} = $3 . $2 . $4 . $1;
+	}
+    }
+
+#    if ($brs_rec->{'PRNO'} ne $old_num) {
+#	print STDERR "\n$old_num ... " . $brs_rec->{'PRNO'} . "\n";
+#    }
+}
+
+1;
Index: /tags/start/protemix/etc/collect.cfg
===================================================================
--- /tags/start/protemix/etc/collect.cfg	(revision 13666)
+++ /tags/start/protemix/etc/collect.cfg	(revision 13666)
@@ -0,0 +1,30 @@
+creator	      sjboddie@cs.waikato.ac.nz
+maintainer    sjboddie@cs.waikato.ac.nz
+public        true
+
+buildtype     mgpp
+#indexes       text,Title,Class1,Class2,Class3
+indexes       text,metadata
+#levels        Section
+#defaultindex  text,Title,Class1,Class2,Class3
+defaultindex  text,metadata
+
+
+plugin        GAPlug
+plugin        ProtemixPlug 
+plugin        ArcPlug
+plugin        RecPlug
+
+classify      AZList -metadata Title
+
+format SearchVList \
+  "<td>[link][icon][/link]</td>{If}{[srclink],<td>[srclink]_iconpdf_</a></td>}<td>{If}{[parent(All': '):Title],[parent(All': '):Title]:}[link][Title][/link]</td>"
+
+format DocumentText \
+  "<center><table border=0 cellspacing=0 cellpadding=0 width=_pagewidth_><tr><td>[srclink]_iconpdf_ View PDF version</a></td></tr></table></center>[Text]"
+
+collectionmeta collectionname      "Protemix FDA Submission"
+collectionmeta collectionextra     ""
+
+
+
Index: /tags/start/protemix/macros/base.dm
===================================================================
--- /tags/start/protemix/macros/base.dm	(revision 13666)
+++ /tags/start/protemix/macros/base.dm	(revision 13666)
@@ -0,0 +1,317 @@
+#######################################################################
+# GLOBAL MACROS 
+#######################################################################
+
+package Global
+
+##########
+
+# not sure exactly what this is used for but it seems it needs to default
+# to something 
+_optsite_ {}
+
+
+##########
+
+_htmlextra_ {}
+
+_starthighlight_ {<span style="background: #FFFF77">}
+_endhighlight_ {</span>}
+
+#######################################################################
+# page content
+#
+# these should always be overridden for each page/collection 
+#######################################################################
+
+_content_ {<p><h2>oops</h2>
+_textdefaultcontent_}
+_pagetitle_ {_textdefaulttitle_}
+_imagethispage_ {}
+_iconcollection_ {}
+_collectionname_ {}
+
+_imagecollection_ {_If_("_iconcollection_" ne "",
+<a href="_httppageabout_"><img src="_iconcollection_" border=0></a>,
+_imagecollectionv_}
+_imagecollectionv_ {_If_(_collectionname_,<br><br><h2><a href="_httppageabout_">_collectionname_</a></h2>)}
+
+#######################################################################
+# these width macros are read in by the server when calculating 
+# width of navigation bar etc. There should be one for each 
+# classification that this receptionist supports, one for the 
+# search button, and the _pagewidth_ macro which is the total width
+# of the page
+#######################################################################
+
+# width of tabs when displaying tables of contents
+_tabwidth_ {25}
+
+_pagewidth_ {537}
+# defaultwidth is the width buttons default to if not included in this list
+_defaultwidth_ {87}
+_searchwidth_ {_widthtsrchx_}
+_Titlewidth_ {_widthttitlx_}
+
+#######################################################################
+# Macros whose values are set from within the server at runtime. These 
+# are here only for reference and to set default values if required.           
+#######################################################################
+
+# _win32_ will be set to 1 if we're on windows
+_win32_ {}
+
+_navigationbar_ {}
+_widthtspace_ {2}
+
+# all cgi args are set as _cgiargX_ macros - those I've put here 
+# are those that need to default to something
+_cgiargd_ {}
+_cgiargcl_ {}
+
+# set from within the query action
+_hselection_ {}
+_jselection_ {}
+_nselection_ {}
+#granularity selection for mgpp
+_gselection_ {}
+
+#######################################################################
+# flashy rollover image macro
+#
+#######################################################################
+
+# imagescript should always be included in html header if there are
+# flashy images on the page
+_imagescript_ {
+var loaded = new Array();
+function gbutton (image, onimage) \{
+  if (image && image.src && (image.out == null || typeof(image.out) == typeof(void(0)))) \{
+    s = image.src;
+    image.out = new Image();
+    image.out.src = s;
+    image.over = new Image();
+    image.over.src = onimage;
+    loaded[image.name] = image;
+  \}
+\}
+
+function roll (imagename, over) \{
+  if (document.images) \{
+    if (over) i = "over";
+    else i = "out";
+    image = loaded[imagename];
+    if (image) image.src = eval("image."+i+".src");
+  \}
+\}
+}
+
+# gsimage should be used to define an instance of a flashy image
+# parameters are:
+# 1. the url to go to when the button is clicked
+# 2. the url of the "off" image
+# 3. the url of the "on" image
+# 4. the name of the image (must be unique)
+# 5. image alt text
+_gsimage_ {<a href="_1_" onMouseover="roll('_4_',1);" onMouseOut="roll('_4_',0);"><img
+name="_4_" src="_2_" onLoad="gbutton(this,'_3_');" border=0 alt="_5_"></a>}
+
+#######################################################################
+# navigation bar images
+#
+#######################################################################
+
+# the spacer image - the width of this is set from server
+_imagespacer_ {<img 
+src="_httpicontspace_" width="_widthtspace_" height="_heighttspace_">}
+
+# image macros for all the classifications currently supported by
+# this receptionist.
+
+_imagesearch_ {_If_("_cgiargu_" ne "1",_imagesearch2_,_iconnosearch_)}
+_imagesearch2_ {_gsimage_(_httpquery_,_httpicontsrchof_,_httpicontsrchon_,srch,_textimagesearch_)}
+_imageTitle_ {_gsimage_(_httpbrowseTitle_,_httpiconttitlof_,_httpiconttitlon_,titles,_textimageTitle_)}
+
+#######################################################################
+# java images/scripts
+#######################################################################
+
+# the _javalinks_ macros are the flashy image links at the top right of
+# the page. 
+
+_javalinks_ {_imagehome_}
+
+
+#######################################################################
+# general web macros 
+#######################################################################
+
+_mailaddr_ {greenstone@cs.waikato.ac.nz}
+
+_gsdltop_ {_top}
+
+#######################################################################
+# http macros 
+#
+# These contain the url without any quotes
+#######################################################################
+
+_httpcollimg_ {_httpcollection_/index/assoc}
+_httpdocimg_ {_httpcollimg_/_thisOID_}
+
+_httpcollection_ {_httpprefix_/collect/_cgiargc_}
+
+_httppagex_ {_gwcgi_?e=_compressedoptions_&a=p&p=_1_}
+_httppageabout_ {_httppagex_(about)}
+_httppagehome_ {_httppageabout_}
+
+_httpcurrentdocument_ {_gwcgi_?e=_compressedoptions_&cl=_cgiargcl_&d=_cgiargd_}
+_httpquery_ {_gwcgi_?e=_compressedoptions_&a=q}
+_httpBrowse_ {_gwcgi_?e=_compressedoptions_&a=br}
+
+# _httpdoc_ is the same as _httpdocument_ - _httpdocument_
+# may occasionally be altered by the server however
+_httpdocument_ {_gwcgi_?e=_compressedoptions_&a=d}
+_httpdoc_  {_gwcgi_?e=_compressedoptions_&a=d}
+
+_httpextlink_ {_gwcgi_?e=_compressedoptions_&a=extlink}
+_httpbuild_ {_gwcgi_?e=_compressedoptions_&a=bc}
+
+_httpiconchalk_ {_httpimg_/chalk.gif}
+_widthchalk_ {2000}
+_heightchalk_ {10}
+
+_httpicondivb_ {_httpimg_/divb.gif}
+_widthdivb_ {_pagewidth_}
+_heightdivb_ {17}
+
+_httpicongsdl_ {_httpimg_/gsdl.gif}
+_widthgsdl_ {140}
+_heightgsdl_ {77}
+
+_httpiconitext_ {_httpimg_/itext.gif}
+_widthitext_ {16}
+_heightitext_ {21}
+
+_httpiconibtext_ {_httpimg_/ibtext.gif}
+_widthibtext_ {16}
+_heightibtext_ {21}
+
+_httpiconless_ {_httpimg_/less.gif}
+_widthless_ {30}
+_heightless_ {16}
+
+_httpiconmore_ {_httpimg_/more.gif}
+_widthmore_ {30}
+_heightmore_ {16}
+
+_httpiconspacer_ {_httpimg_/spacer.gif}
+_widthspacer_ {42}
+_heightspacer_ {4}
+
+_httpicontabspace_ {_httpimg_/tabspace.gif}
+_widthtabspace_ {23}
+_heighttabspace_ {1}
+
+_httpicontspace_ {_httpimg_/tspace.gif}
+_heighttspace_ {17}
+
+_httpiconhhome_ {_httpimg_/h\_home.gif}
+_widthhhome_ {200}
+_heighthhome_ {57}
+
+_httpiconarrrght_ {_httpimg_/arrrght.gif}
+_widtharrrght_ {23}
+_heightarrrght_ {15}
+
+_httpiconopenbook_ {_httpimg_/openbook.gif}
+_widthopenbook_ {28}
+_heightopenbook_ {23}
+
+_httpiconaopenbk_ {_httpimg_/aopenbk.gif}
+_widthaopenbk_ {28}
+_heightaopenbk_ {23}
+
+_httpiconopenfldr_ {_httpimg_/openfldr.gif}
+_widthopenfldr_ {23}
+_heightopenfldr_ {15}
+
+_httpiconaopenfdr_ {_httpimg_/aopenfdr.gif}
+_widthaopenfdr_ {23}
+_heightaopenfdr_ {15}
+
+_httpiconbook_ {_httpimg_/book.gif}
+_widthbook_ {18}
+_heightbook_ {11}
+
+_httpiconabook_ {_httpimg_/abook.gif}
+_widthabook_ {18}
+_heightabook_ {11}
+
+_httpiconbshelf_ {_httpimg_/bshelf.gif}
+_widthbshelf_ {20}
+_heightbshelf_ {16}
+
+_httpiconabshelf_ {_httpimg_/abshelf.gif}
+_widthabshelf_ {20}
+_heightabshelf_ {16}
+
+_httpiconsmtext_ {_httpimg_/smtext.gif}
+_widthsmtext_ {23}
+_heightsmtext_ {15}
+
+_httpiconasmtext_ {_httpimg_/asmtext.gif}
+_widthasmtext_ {23}
+_heightasmtext_ {15}
+
+_httpiconclsdfldr_ {_httpimg_/clsdfldr.gif}
+_widthclsdfldr_ {23}
+_heightclsdfldr_ {15}
+
+_httpiconaclsdfdr_ {_httpimg_/aclsdfdr.gif}
+_widthaclsdfdr_ {23}
+_heightaclsdfdr_ {15}
+
+_httpiconipdf_ {_httpimg_/ipdf.gif}
+_widthipdf_ {26}
+_heightipdf_ {26}
+
+#######################################################################
+# Icons 
+#
+# Must not include links (so they can be used as links). If you want to
+# include links use _image
+#######################################################################
+
+_iconnext_{<img src="_httpiconmore_" align=absbottom 
+width=_widthmore_ height=_heightmore_ border=0 alt="_texticonnext_">}
+
+_iconprev_{<img src="_httpiconless_" align=absbottom 
+width=_widthless_ height=_heightless_ border=0 alt="_texticonprev_">}
+
+_icontabsearchgreen_ {<img 
+src="_httpicontsrchgr_" width=_widthtsrchx_ border=0>}
+
+_icontabTitlegreen_ {<img 
+src="_httpiconttitlgr_" width=_widthttitlx_ border=0>}
+
+_iconblankbar_ {<center><img src="_httpicondivb_" width=_widthdivb_ height=_heightdivb_></center>}
+
+_icontext_ {<img border=0 align=absmiddle src="_httpiconitext_" width=_widthitext_ height=_heightitext_ alt="_texticontext_">}
+
+_iconblanktext_ {<img border=0 align=absmiddle src="_httpiconibtext_" width=_widthibtext_ height=_heightibtext_>}
+
+_iconclosedbook_ {<img src="_httpiconbook_" width=_widthbook_ height=_heightbook_ border=0 alt="_texticonclosedbook_">}
+
+_icondoc_ {<img border=0 align=absmiddle src="_httpiconimsword_" width=_widthimsword_ height=_heightimsword_ alt="_texticonmsword_">}
+
+_iconpdf_ {<img border=0 align=absmiddle src="_httpiconipdf_" width=_widthipdf_ height=_heightipdf_ alt="_texticonpdf_">}
+
+#######################################################################
+# Image links 
+#
+# These might include a link (not like an _icon_
+#######################################################################
+
+_imagehome_ {_If_("_cgiargu_" ne "1",_imagehome2_)}
+_imagehome2_ {_gsimage_(_httppagehome_,_httpiconchomeof_,_httpiconchomeon_,homer,_textimagehome_)}
Index: /tags/start/protemix/macros/english.dm
===================================================================
--- /tags/start/protemix/macros/english.dm	(revision 13666)
+++ /tags/start/protemix/macros/english.dm	(revision 13666)
@@ -0,0 +1,217 @@
+######################################################################
+# Global (base) package
+package Global
+######################################################################
+
+
+#------------------------------------------------------------
+# text macros
+#------------------------------------------------------------
+
+_textdefaultcontent_ {The requested page could not be found. Please use
+your browsers 'back' button or the above home button to return to the
+Greenstone Digital Library.}
+
+_textdefaulttitle_ {GSDL Error}
+
+_collectionextra_ {This collection contains _about:numdocs_ documents. 
+It was last built _about:builddate_ days ago.}
+
+_textimagecollection_ {}
+_textimageabout_ {About page}
+_textimagehome_ {Home page}
+
+_textimagesearch_ {Search for specific terms}
+_textimageTitle_ {Browse alphabetical list of titles}
+
+_texticontabsearchgreen_{Search}
+_texticontabtitlegreen_{Titles A-Z}
+
+_texticontext_ {View the document}
+_texticonclosedbook_ {open this document and view contents}
+_texticonnext_ {to next section}
+_texticonprev_ {to previous section}
+
+_texticonpdf_  {View the PDF document}
+
+_page_ {page }
+_pages_ {pages}
+_of_ { of }
+_vol_ {Vol.}
+_num_ {No.}
+
+_textmonth00_ {}
+_textmonth01_ {January}
+_textmonth02_ {February}
+_textmonth03_ {March}
+_textmonth04_ {April}
+_textmonth05_ {May}
+_textmonth06_ {June}
+_textmonth07_ {July}
+_textmonth08_ {August}
+_textmonth09_ {September}
+_textmonth10_ {October}
+_textmonth11_ {November}
+_textmonth12_ {December}
+
+_Document_ {Document}
+_Section_ {Section}
+_Paragraph_ {Paragraph}
+
+#------------------------------------------------------------
+# icons
+#------------------------------------------------------------
+
+## "HOME" ## top_nav_button ## chome ##
+_httpiconchomeof_ {_httpimg_/chomeof.gif}
+_httpiconchomeon_ {_httpimg_/chomeon.gif}
+
+## "search" ## nav_bar_button ## tsrch ##
+_httpicontsrchgr_ {_httpimg_/tsrchgr.gif}
+_httpicontsrchof_ {_httpimg_/tsrchof.gif}
+_httpicontsrchon_ {_httpimg_/tsrchon.gif}
+_widthtsrchx_ {87}
+
+## "titles a-z" ## nav_bar_button ## ttitl ##
+_httpiconttitlgr_ {_httpimg_/ttitlgr.gif}
+_httpiconttitlof_ {_httpimg_/ttitlof.gif}
+_httpiconttitlon_ {_httpimg_/ttitlon.gif}
+_widthttitlx_ {87}
+
+
+######################################################################
+# 'about' page
+package about
+######################################################################
+
+
+#------------------------------------------------------------
+# text macros
+#------------------------------------------------------------
+
+_textabcol_ {About this collection}
+
+
+#------------------------------------------------------------
+# icons
+#------------------------------------------------------------
+
+## "about" ## green_title ## h_about ##
+_httpiconhabout_ {_httpimg_/h\_about.gif}
+_widthhabout_ {200}
+_heighthabout_ {57}
+
+######################################################################
+# document package
+package document
+######################################################################
+
+
+#------------------------------------------------------------
+# text macros
+#------------------------------------------------------------
+
+_texticonhtitle_ {Titles A-Z}
+
+_texticonopenbookshelf_ {close this section of the library}
+_texticonclosedbookshelf_ {open this section of the library and view contents}
+_texticonopenbook_ {close this book}
+_texticonclosedfolder_ {Open this folder and view contents}
+_texticonclosedfolder2_ {open sub-section: }
+_texticonopenfolder_ {close this folder}
+_texticonopenfolder2_ {close sub-section: }
+_texticonsmalltext_ {View this section of the text}
+_texticonsmalltext2_ {view text: }
+_texticonpointer_ {current section}
+_texticondetach_ {Open this page in a new window}
+_texticonhighlight_ {Highlight search terms}
+_texticonnohighlight_ {Don't highlight search terms}
+_texticoncontracttoc_ {Collapse table of contents}
+_texticonexpandtoc_ {Expand table of contents}
+_texticonexpandtext_ {Display all text}
+_texticoncontracttext_ {Display text only for currently selected section}
+
+_textgoto_ {go to page}
+
+#------------------------------------------------------------
+# icons
+#------------------------------------------------------------
+
+## "titles a-z" ## green_title ## h_title ##
+_httpiconhtitle_ {_httpimg_/h\_title.gif}
+_widthhtitle_ {200}
+_heighthtitle_ {57}
+
+## "EXPAND TEXT" ## document_button ## eallt ## 
+_httpiconealltof_ {_httpimg_/ealltof.gif}
+_httpiconeallton_ {_httpimg_/eallton.gif}
+
+## "CONTRACT CONTENTS" ## document_button ## econc ##
+_httpiconeconcof_ {_httpimg_/econcof.gif}
+_httpiconeconcon_ {_httpimg_/econcon.gif}
+
+## "DETACH" ## document_button ## edtch ##
+_httpiconedtchof_ {_httpimg_/edtchof.gif}
+_httpiconedtchon_ {_httpimg_/edtchon.gif}
+
+## "EXPAND CONTENTS" ## document_button ## eexpc ##
+_httpiconeexpcof_ {_httpimg_/eexpcof.gif}
+_httpiconeexpcon_ {_httpimg_/eexpcon.gif}
+
+## "CONTRACT TEXT" ## document_button ## etsec ##
+_httpiconetsecof_ {_httpimg_/etsecof.gif}
+_httpiconetsecon_ {_httpimg_/etsecon.gif}
+
+## "HIGHLIGHTING" ## document_button ## ehl ##
+_httpiconehlof_ {_httpimg_/ehlof.gif}
+_httpiconehlon_ {_httpimg_/ehlon.gif}
+
+## "NO HIGHLIGHTING" ## document_button ## enhl ##
+_httpiconenhlof_ {_httpimg_/enhlof.gif}
+_httpiconenhlon_ {_httpimg_/enhlon.gif}
+
+######################################################################
+# 'search' page
+package query
+######################################################################
+
+
+#------------------------------------------------------------
+# text macros
+#------------------------------------------------------------
+
+# this if statement produces the text 'results n1 - nn for query: querystring' or 
+# 'No matches for query: querystring', depending on whether or not there were
+# any matches
+_textquerytitle_ {_If_(_thislast_,results _thisfirst_ - _thislast_ for query: _cgiargq_,No matches for query: _cgiargq_)}
+
+_texticonthispage_ {search}
+
+#alt text for query buttons
+_textusequery_ {use this query}
+_textfreqmsg1_ {Word count: }
+_textpostprocess_ {_If_(_quotedquery_,<br><i>post-processed to find _quotedquery_</i>
+)}
+
+_textmorethan_ {More than }
+_textapprox_ {About }
+_textnodocs_ {No documents matched the query.}
+_text1doc_ {1 document matched the query.}
+_textlotsdocs_ {documents matched the query.}
+_textmatches_ {Matches }
+_textbeginsearch_ {Begin Search}
+_textrunquery_{Run Query}
+
+#------------------------------------------------------------
+# icons
+#------------------------------------------------------------
+
+## "search" ## green_title ## h_search ##
+_httpiconhsearch_ {_httpimg_/h\_search.gif}
+_widthhsearch_ {200}
+_heighthsearch_ {57}
+
+## "results" ## green_bar_left_aligned ## qryresb ##
+_httpiconqryresb_ {_httpimg_/qryresb.gif}
+_widthqryresb_ {_pagewidth_}
+_heightqryresb_ {17}
Index: /tags/start/protemix/macros/query.dm
===================================================================
--- /tags/start/protemix/macros/query.dm	(revision 13666)
+++ /tags/start/protemix/macros/query.dm	(revision 13666)
@@ -0,0 +1,163 @@
+package query
+
+
+#######################################################################
+# Macros whose values are set from within the server at runtime. These 
+# are here only for reference and to set default values if required.           
+#######################################################################
+
+_quotedquery_ {}
+_freqmsg_ {}
+_resultline_ {}
+_thisfirst_ {}
+_thislast_ {}
+_nextfirst_ {}
+_nextlast_ {}
+_prevfirst_ {}
+_prevlast_ {}
+_searchhistorylist_ {}
+#_histvalue0_ to _histvalue19_
+_advformlist_ {}
+_regformlist_ {}
+_fqfselection_ {}
+
+
+#######################################################################
+# icons
+#######################################################################
+
+_iconthispage_ {<img src="_httpiconhsearch_" alt="_texticonthispage_" width="_widthhsearch_" height="_heighthsearch_">}
+_iconthispage_ [v=1] {<h2>_texticonthispage_</h2>}
+
+_iconqueryresultsbar_ {<img src="_httpiconqryresb_" width="_widthqryresb_" height="_heightqryresb_" alt="_texticonqueryresultsbar_">}
+_iconqueryresultsbar_[v=1] {_texticonqueryresultsbar_}
+
+# _iconnext_ and _iconprev_ are overridden in this package as we
+# don't want alt text here
+_iconnext_{<img src="_httpiconmore_" width=_widthmore_ height=_heightmore_ border=0 align=top>}
+_iconnext_ [v=1] {}
+_iconprev_{<img src="_httpiconless_" width=_widthless_ height=_heightless_ border=0 align=top>}
+_iconprev_ [v=1] {}
+
+#######################################################################
+# images
+#######################################################################
+
+_imagethispage_ {_iconthispage_}
+
+#######################################################################
+# page content
+#######################################################################
+
+_pagescriptextra_ {
+var options = new Array(7);
+options[0] = new Array('Any');
+options[1] = new Array('Any', 'Absorption', 'Distribution', 'Metabolism', 'Elimination',
+                       'Effect of Food', 'Drug Interactions', 'Special Populations');
+options[2] = new Array('Any', 'Trace Metal', 'Excretion', 'Selectivity', 'Copper', 'Zinc',
+                       'Manganese', 'Iron', 'Distribution', 'Brain', 'Heart', 'Plasma', 
+                       'Plasma', 'Fetal', 'Liver', 'Kidney');
+options[3] = new Array('Any', 'Acute Toxicity', 'Repeated Dose Toxicity', 'Studies in Rodents', 
+                       'Studies in Dogs', 'Overdosage', 'Reproductive Toxicity',
+                       'Teratogenicity', 'Mutagenecity', 'Carcinogenicity');
+options[4] = new Array('Any', 'Superoxide Dismutase', 'Ferroxidase I', 'Ferroxidase II',
+                       'Metallothienein', 'Ceruloplasmin');
+options[5] = new Array('Any', 'Heart', 'Complications', 'Microvascular', 'Renal', 'Diabetes');
+options[6] = new Array('Any');
+options[7] = new Array('Any');
+
+function initialize () \{
+
+  var form = document.QueryForm;
+  var c2 = form.c2.selectedIndex;
+  var i;
+
+  form.c3.options.length = 0;
+
+  for (i = 0; i < options[c2].length; i++) \{
+    form.c3.options[i] = new Option(options[c2][i], options[c2][i]);
+  \}
+
+  form.c3.selectedIndex = 0;
+
+\}
+}
+
+_header_ {_cgihead_
+_htmlhead_(background="_httpiconchalk_" onLoad="initialize();")_startspacer__pagebanner_
+}
+
+_pagetitle_ {_If_(_cgiargq_,_textquerytitle_,_textnoquerytitle_)}
+
+_content_ {
+<center>
+_navigationbar_
+</center>
+<center>
+_queryform_
+</center>
+_If_(_cgiargq_,<center>_iconqueryresultsbar_</center><br>
+<small>
+_freqmsg_
+_textpostprocess_</small><br>
+_resultline_
+,<center>_iconblankbar_</center>)<br>
+}
+
+_queryform_ {
+<form name=QueryForm method=get action="_gwcgi_">
+<input type=hidden name="a" value="q">
+<input type=hidden name="r" value="1">
+<input type=hidden name="e" value="_decodedcompressedoptions_">
+<p>
+<table border="0" cellspacing="0" cellpadding="0" width="_pagewidth_">
+
+<tr valign="top">
+<td align="center">
+<select name="c1">
+<option value="">Any
+<option value="Animal">Animal
+<option value="Human">Human
+<option value="Other">Other
+</select>
+</td>
+
+<td align="center">
+<b>AND</b>
+</td>
+
+<td align="center">
+<select name="c2" onChange='initialize()'>
+<option value="">Any
+<option value="Pharmacokinetics">Pharmacokinetics
+<option value="Pharmacodynamics">Pharmacodynamics
+<option value="Safety/Side Effects/Toxicity">Safety/Side Effects/Toxicity
+<option value="Other">Other
+<option value="Efficacy">Efficacy
+<option value="Contraindications">Contraindications
+<option value="Precautions">Precautions
+</select>
+</td>
+
+<td align="center">
+<b>AND</b>
+</td>
+
+<td align="center">
+<select name="c3">
+<option value="">Any
+</select>
+</td>
+
+</tr>
+
+<tr valign="top"><td colspan="5">
+<nobr>
+<input type="text" name="q" value="_cgiargq_" size="40">
+<input type="submit" value="_textbeginsearch_">
+</nobr>
+</td></tr>
+
+</table>
+</form>
+}
Index: /tags/start/protemix/perllib/plugins/ProtemixPlug.pm
===================================================================
--- /tags/start/protemix/perllib/plugins/ProtemixPlug.pm	(revision 13666)
+++ /tags/start/protemix/perllib/plugins/ProtemixPlug.pm	(revision 13666)
@@ -0,0 +1,169 @@
+###########################################################################
+#
+# ProtemixPlug.pm --
+#
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 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.
+#
+###########################################################################
+
+package ProtemixPlug;
+
+use HTMLPlug;
+use util;
+
+sub BEGIN {
+    @ISA = ('HTMLPlug');
+}
+
+use XML::Parser;
+
+sub new {
+    my $class = shift (@_);
+    
+    # $self must be global for XML parser routines
+    $self = new HTMLPlug ($class, @_);
+
+    $self->{'no_metadata'} = 1;
+    $self->{'nolinks'} = 1;
+    $self->{'section_metadata'} = {};
+    $self->{'Page'} = "TopLevel";
+    $self->{'metadata_name'} = "";
+
+    return bless $self, $class;
+}
+
+sub read {
+    my $self = shift (@_);  
+    my ($pluginfo, $base_dir, $file, $metadata, $processor, $maxdocs) = @_;
+
+    my $filename = $file;
+    $filename = &util::filename_cat ($base_dir, $file) if $base_dir =~ /\w/;
+
+    return 0 if $filename =~ /\.(pdf|html?|jpe?g)$/i;
+    return undef unless $filename =~ /meta\.xml$/;
+    
+    # create a new document
+    my $doc_obj = new doc ($filename, "indexed_doc");
+    $doc_obj->set_OIDtype ($processor->{'OIDtype'});
+    my $topsection = $doc_obj->get_top_section();
+
+    # process the meta.xml file and set top level metadata
+    my $parser = new XML::Parser('Style' => 'Stream');
+    $self->{'section_metadata'} = {};
+    $self->{'Page'} = "TopLevel";
+    $parser->parsefile($filename);
+    foreach my $key (keys %{$self->{'section_metadata'}->{'TopLevel'}}) {
+	$doc_obj->add_utf8_metadata ($topsection, $key, $self->{'section_metadata'}->{'TopLevel'}->{$key});
+    }
+
+    # read in directory and process individual files
+    my $dir = File::Basename::dirname($filename);
+
+    opendir(DIR, $dir) || die;
+    my @files = readdir DIR;
+    closedir DIR;
+    
+
+    # we rely on the files being named in such a way that they'll be read
+    # in the correct order
+    my $count = 1;
+    foreach my $thisfile (@files) {
+	if ($thisfile =~ /^(.*?)\.html?$/i) {
+	    my $filesuf = $1;
+	    $thisfile = &util::filename_cat($dir, $thisfile);
+	    my ($language, $encoding) = $self->textcat_get_language_encoding ($thisfile);
+	    # read in file ($text will be in utf8)
+	    my $text = "";
+	    $self->read_file ($thisfile, $encoding, $language, \$text);
+	    if (!length ($text)) {
+		die "$thisfile has no text\n";
+	    }
+
+	    my $cursection = $doc_obj->insert_section($doc_obj->get_end_child($topsection));
+
+	    # process HTML file with HTMLPlug
+	    $self->process_section (\$text, '', $thisfile, $doc_obj, $cursection);
+
+	    # associate PDF file with doc object
+	    my $pdffile = $thisfile;
+	    $pdffile =~ s/\.html?$/\.pdf/;
+	    die "no PDF file for $thisfile" unless -e $pdffile;
+	    $doc_obj->associate_file($pdffile, "doc$count.pdf", undef, $cursection);
+	    my $doclink = "<a href=\"_httpcollection_/index/assoc/[parent(Top):archivedir]/doc$count.pdf\">";
+#	    $doc_obj->add_utf8_metadata ($cursection, "srclink",  $doclink); 
+	    $doc_obj->add_utf8_metadata ($cursection, "Title", $count); 
+
+	    # add any section level metadata we have for this page (set from within the meta.xml file)
+#	    if (defined ($self->{'section_metadata'}->{$filesuf})) {
+#		foreach my $key (keys %{$self->{'section_metadata'}->{$filesuf}}) {
+#		    $doc_obj->add_utf8_metadata ($cursection, $key, $self->{'section_metadata'}->{$filesuf}->{$key});
+#		}
+#	    }
+
+	    $count ++;
+	}
+    }
+   
+    # add an OID
+    $doc_obj->set_OID();
+
+    # process the document
+    $processor->process($doc_obj);
+
+    $self->{'num_processed'} ++;
+
+    return 1; # processed the file
+}
+
+
+sub StartTag {
+    my ($expat, $element) = @_;
+
+    if ($element eq "Page") {
+	$self->{'Page'} = $_{'filename'};
+
+    } elsif ($element eq "Metadata") {
+	if (!defined $self->{'section_metadata'}->{$self->{'Page'}}) {
+	    $self->{'section_metadata'}->{$self->{'Page'}} = {};
+	}
+	$self->{'metadata_name'} = $_{'name'};
+	$self->{'section_metadata'}->{$self->{'Page'}}->{$_{'name'}} = "";
+    }
+}
+
+sub EndTag {
+    my ($expat, $element) = @_;
+
+    if ($element eq "Page") {
+	$self->{'Page'} eq "TopLevel";
+
+    } elsif ($element eq "Metadata") {
+	$self->{'metadata_name'} = "";
+    }
+}
+
+sub Text {
+    if ($self->{'metadata_name'} ne "") {
+	$self->{'section_metadata'}->{$self->{'Page'}}->{$self->{'metadata_name'}} .= $_;
+    }
+}
+
+1;
Index: /tags/start/protemix/rename.pl
===================================================================
--- /tags/start/protemix/rename.pl	(revision 13666)
+++ /tags/start/protemix/rename.pl	(revision 13666)
@@ -0,0 +1,170 @@
+#!/usr/bin/perl -w
+
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+}
+
+
+use File::Basename;
+use unicode;
+
+my %classifications = (
+		       'Pharmacokinetics' => ['Absorption', 'Distribution', 'Metabolism', 'Elimination',
+					       'Effect of Food', 'Drug Interactions', 'Special Populations'],
+		       'Pharmacodynamics' => ['Trace Metal', 'Excretion', 'Selectivity', 'Copper', 'Zinc',
+					      'Manganese', 'Iron', 'Distribution', 'Tissue', 'Brain',
+					      'Heart', 'Plasma', 'Fetal', 'Liver', 'Kidney'],
+		       'Safety/Side Effects/Toxicity' => ['Acute Toxicity', 'Repeated Dose Toxicity',
+							 'Studies in Rodents', 'Studies in Dogs',
+							 'Overdosage', 'Reproductive Toxicity',
+							 'Teratogenicity', 'Mutagenecity', 'Carcinogenicity'],
+		       'Other' => ['Superoxide Dismutase', 'Ferroxidase I', 'Ferroxidase II', 
+				   'Metallothienein', 'Ceruloplasmin'],
+		       'Efficacy' => ['Heart', 'Complications', 'Microvascular', 'Renal', 'Diabetes'],
+		       'Contraindications' => [],
+		       'Precautions' => []
+		       );
+
+my @meta_files = ();
+
+&recursive_rename("import");
+# process meta files
+foreach my $mfile (@meta_files) {
+    &process_meta_file($mfile);
+}
+
+sub recursive_rename {
+    my ($dir) = @_;
+
+    opendir (DIR, "$dir") || die;
+    my @files = readdir DIR;
+    closedir DIR;
+    
+    foreach $file (@files) {
+	next if $file eq "." || $file eq "..";
+	next if $file =~ /processed.htm$/;
+
+	my $path = "$dir/$file";
+	if (-d $path) {
+	    &recursive_rename($path);
+	} else {
+	    $newfile = &rename_file($file);
+	    if ($newfile ne $file) {
+		print STDERR "renaming $file --> $newfile\n";
+		`mv "$path" "$dir/$newfile"`;
+	    }
+
+	    if ($file =~ /^title\.txt$/) {
+		# we'll process all the title.txt files after we've finished 
+		# renaming everything
+		push(@meta_files, "$dir/$newfile");
+	    }
+
+	    if ($file =~ /\.html?$/i) {
+		&process_html_file("$dir/$newfile");
+	    }
+	}
+    }
+}
+
+# clean up the html (currently just use the non-css version)
+sub process_html_file {
+    my ($filename) = @_;
+
+    print STDERR "processing $filename\n";
+
+    open (FILE, $filename) || die;
+    undef $/;
+    my $file = <FILE>;
+    $/ = "\n";
+    close FILE;
+
+    my $header = "<html>\n<head></head>\n<body bgcolor=\"#FFFFFF\">\n";
+    my $footer = "</body>\n</html>\n";
+
+    my ($noncss, $css) = $file =~ /document\.write\(\"(.*?[^\\])\"\).*?document\.write\(\"(.*?[^\\])\"\)/si;
+
+    # remove backslashes added for javascript strings
+    $noncss =~ s/\\\"/\"/sg;
+    $noncss =~ s/\\\n/\n/sg;
+
+    # alter <img> tags to support renamed files
+    $noncss =~ s/(<img src=\")([^\"]+)/$1 . &rename_file($2)/sige;
+
+    # remove rules="all" attribute from table tags
+    $noncss =~ s/(<table.*?)rules=\"all\"\s+/$1/sig;
+
+    open (FILE, ">$filename") || die;
+    print FILE $header . $noncss . $footer;
+    close FILE;
+
+}
+
+sub rename_file {
+    my ($filename) = @_;
+
+    $filename =~ s/\s+//g;
+    $filename =~ s/^protemix\(\d+\)-?//;
+
+    return $filename;
+}
+
+# process a title.txt file and replace it with a meta.xml file
+sub process_meta_file {
+    my ($filename) = @_;
+
+    open (FILE, $filename) || die ("couldn't open $filename");
+    undef $/;
+    my $title = <FILE>;
+    $/ = "\n";
+    close FILE;
+
+    unlink($filename);
+
+    $title =~ s/\s+/ /gs;
+    $title =~ s/^\s+//;
+    $title =~ s/\s+$//;
+    $title = &unicode::ascii2utf8(\$title); # assumes title is iso-8859-1
+    my $metafile = "<Metafile>\n";
+    $metafile .= "  <Metadata name=\"Title\">$title</Metadata>\n";
+
+    # currently just write some random values for classification metadata
+    my @c1 = ('Animal', 'Human', 'Other');
+    my $rand = int(rand 3);
+    my $classtext = "    <Metadata name=\"Class1\">" . $c1[$rand] . "</Metadata>\n";
+    my @c2 = ('Pharmacokinetics', 'Pharmacodynamics', 'Safety/Side Effects/Toxicity',
+	      'Other', 'Efficacy', 'Contraindications', 'Precautions');
+    $rand = int(rand 7);
+    my $c2val = $c2[$rand];
+    $classtext .= "    <Metadata name=\"Class2\">$c2val</Metadata>\n";
+    if (defined $classifications{$c2val}) {
+	if (scalar(@{$classifications{$c2val}})) {
+	    my $numvals = scalar(@{$classifications{$c2val}});
+	    $rand = int(rand $numvals);
+	    my $c3val = $classifications{$c2val}->[$rand];
+	    $classtext .= "    <Metadata name=\"Class3\">$c3val</Metadata>\n";
+	}
+    } else {
+	print STDERR "ERROR: '$c2val' not in clasifications list\n";
+    }
+
+    my $dir = File::Basename::dirname($filename);
+
+    opendir(DIR, $dir) || die;
+    my @files = readdir DIR;
+    foreach my $file (@files) {
+	if ($file =~ s/\.html?$//i) {
+	    $metafile .= "  <Page filename=\"$file\">\n$classtext  </Page>\n";
+	}
+    }
+    $metafile .= "</Metafile>\n";
+
+    $filename = "$dir/meta.xml";
+    open (FILE, ">$filename") || die;
+    print FILE $metafile;
+    close FILE;
+}
+
+
Index: /tags/start/protemix/src/recpt/Makefile
===================================================================
--- /tags/start/protemix/src/recpt/Makefile	(revision 13666)
+++ /tags/start/protemix/src/recpt/Makefile	(revision 13666)
@@ -0,0 +1,143 @@
+###########################################################################
+#
+# Makefile -- Makefile for ptmx
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 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.
+#
+###########################################################################
+
+GD = ../../../..
+MAINRECPTDIR = $(GD)/src/recpt
+MAINCOLSERVRDIR = $(GD)/src/colservr
+
+
+AR = ar
+CC = gcc
+CCFLAGS = -g
+DEFS = -DNZDL -DQUIET -DSHORT_SUFFIX -DPARADOCNUM -DGSDLSERVER -DHAVE_CONFIG_H
+
+INCLUDES = -I. -I$(MAINRECPTDIR) -I$(MAINCOLSERVRDIR) -I$(GD)/lib \
+	   -I$(GD)/packages/mg -I$(GD)/packages/mg/lib -I$(GD)/packages/mg/src/text \
+	   -I$(GD)/src/mgpp/lib -I$(GD)/src/mgpp/text
+
+RANLIB = ranlib
+LDFLAGS = 
+LIBS = -lcrypt -lstdc++ -lm -lgdbm -lg 
+
+GSDLOS = linux
+
+
+COMPILE = $(CC) -c $(CCFLAGS) $(DEFS) $(INCLUDES)
+LINK = $(CC) $(LDFLAGS) -o $@
+
+.SUFFIXES:
+.SUFFIXES: .c .o
+.c.o:
+	$(COMPILE) $<
+
+.SUFFIXES: .cpp .o
+.cpp.o:
+	$(COMPILE) $< 
+
+HEADERS = ptmxqueryaction.h
+
+SOURCES = ptmxmain.cpp ptmxqueryaction.cpp
+
+OBJECTS = ptmxmain.o ptmxqueryaction.o
+
+EXEC    = ptmx
+
+all : $(EXEC)
+
+install: $(EXEC)
+	install -m 755 -s $(EXEC) $(GD)/cgi-bin/$(EXEC)
+
+distclean:
+	rm -f $(OBJECTS) $(EXEC) Makefile
+
+clean:
+	rm -f $(OBJECTS) $(EXEC)
+
+depend:
+	makedepend -Y -- $(DEFS) $(INCLUDES) $(CCFLAGS) -- $(SOURCES)
+
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+
+PTMX_OBJS = $(OBJECTS) \
+    $(MAINRECPTDIR)/browsetools.o \
+    $(MAINRECPTDIR)/browserclass.o \
+    $(MAINRECPTDIR)/vlistbrowserclass.o \
+    $(MAINRECPTDIR)/hlistbrowserclass.o \
+    $(MAINRECPTDIR)/datelistbrowserclass.o \
+    $(MAINRECPTDIR)/invbrowserclass.o \
+    $(MAINRECPTDIR)/pagedbrowserclass.o \
+    $(MAINRECPTDIR)/htmlbrowserclass.o \
+    $(MAINRECPTDIR)/receptionist.o \
+    $(MAINRECPTDIR)/recptconfig.o \
+    $(MAINRECPTDIR)/cgiwrapper.o \
+    $(MAINRECPTDIR)/cgiargs.o \
+    $(MAINRECPTDIR)/action.o \
+    $(MAINRECPTDIR)/converter.o \
+    $(MAINRECPTDIR)/cgiutils.o \
+    $(MAINRECPTDIR)/OIDtools.o \
+    $(MAINRECPTDIR)/htmlgen.o \
+    $(MAINRECPTDIR)/pageaction.o \
+    $(MAINRECPTDIR)/comtypes.o \
+    $(MAINRECPTDIR)/recptproto.o \
+    $(MAINRECPTDIR)/queryaction.o \
+    $(MAINRECPTDIR)/querytools.o \
+    $(MAINRECPTDIR)/documentaction.o \
+    $(MAINRECPTDIR)/htmlutils.o \
+    $(MAINRECPTDIR)/nullproto.o \
+    $(MAINRECPTDIR)/infodbclass.o \
+    $(MAINRECPTDIR)/formattools.o \
+    $(MAINRECPTDIR)/historydb.o \
+    $(MAINRECPTDIR)/summarise.o \
+    $(MAINRECPTDIR)/extlinkaction.o \
+    $(MAINRECPTDIR)/phindaction.o \
+    $(MAINRECPTDIR)/phindbrowserclass.o \
+    $(MAINCOLSERVRDIR)/mgq.o \
+    $(MAINCOLSERVRDIR)/querycache.o \
+    $(MAINCOLSERVRDIR)/queryinfo.o \
+    $(MAINCOLSERVRDIR)/collectset.o \
+    $(MAINCOLSERVRDIR)/collectserver.o \
+    $(MAINCOLSERVRDIR)/colservrconfig.o \
+    $(MAINCOLSERVRDIR)/maptools.o \
+    $(MAINCOLSERVRDIR)/filter.o \
+    $(MAINCOLSERVRDIR)/source.o \
+    $(MAINCOLSERVRDIR)/browsefilter.o \
+    $(MAINCOLSERVRDIR)/queryfilter.o \
+    $(MAINCOLSERVRDIR)/mgqueryfilter.o \
+    $(MAINCOLSERVRDIR)/mgppqueryfilter.o \
+    $(MAINCOLSERVRDIR)/phrasesearch.o \
+    $(MAINCOLSERVRDIR)/mggdbmsource.o \
+    $(MAINCOLSERVRDIR)/search.o \
+    $(MAINCOLSERVRDIR)/mgsearch.o \
+    $(MAINCOLSERVRDIR)/mgppsearch.o \
+    $(GD)/lib/gsdllib.a  \
+    $(GD)/packages/mg/src/text/libtextin.a \
+    $(GD)/packages/mg/lib/libmg.a \
+    $(GD)/src/mgpp/text/libtextin.a \
+    $(GD)/src/mgpp/lib/libmg.a
+
+ptmx: $(PTMX_OBJS)
+	$(LINK) $(PTMX_OBJS) $(LIBS) 
Index: /tags/start/protemix/src/recpt/Makefile.in
===================================================================
--- /tags/start/protemix/src/recpt/Makefile.in	(revision 13666)
+++ /tags/start/protemix/src/recpt/Makefile.in	(revision 13666)
@@ -0,0 +1,143 @@
+###########################################################################
+#
+# Makefile -- Makefile for ptmx
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 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.
+#
+###########################################################################
+
+GD = ../../../..
+MAINRECPTDIR = $(GD)/src/recpt
+MAINCOLSERVRDIR = $(GD)/src/colservr
+
+
+AR = ar
+CC = @CC@
+CCFLAGS = @CFLAGS@
+DEFS = -DNZDL -DQUIET -DSHORT_SUFFIX -DPARADOCNUM -DGSDLSERVER @DEFS@
+
+INCLUDES = -I. -I$(MAINRECPTDIR) -I$(MAINCOLSERVRDIR) -I$(GD)/lib \
+	   -I$(GD)/packages/mg -I$(GD)/packages/mg/lib -I$(GD)/packages/mg/src/text \
+	   -I$(GD)/src/mgpp/lib -I$(GD)/src/mgpp/text
+
+RANLIB = @RANLIB@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+
+GSDLOS = @gsdlos@
+
+
+COMPILE = $(CC) -c $(CCFLAGS) $(DEFS) $(INCLUDES)
+LINK = $(CC) $(LDFLAGS) -o $@
+
+.SUFFIXES:
+.SUFFIXES: .c .o
+.c.o:
+	$(COMPILE) $<
+
+.SUFFIXES: .cpp .o
+.cpp.o:
+	$(COMPILE) $< 
+
+HEADERS = ptmxqueryaction.h
+
+SOURCES = ptmxmain.cpp ptmxqueryaction.cpp
+
+OBJECTS = ptmxmain.o ptmxqueryaction.o
+
+EXEC    = ptmx
+
+all : $(EXEC)
+
+install: $(EXEC)
+	install -m 755 -s $(EXEC) $(GD)/cgi-bin/$(EXEC)
+
+distclean:
+	rm -f $(OBJECTS) $(EXEC) Makefile
+
+clean:
+	rm -f $(OBJECTS) $(EXEC)
+
+depend:
+	makedepend -Y -- $(DEFS) $(INCLUDES) $(CCFLAGS) -- $(SOURCES)
+
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+
+PTMX_OBJS = $(OBJECTS) \
+    $(MAINRECPTDIR)/browsetools.o \
+    $(MAINRECPTDIR)/browserclass.o \
+    $(MAINRECPTDIR)/vlistbrowserclass.o \
+    $(MAINRECPTDIR)/hlistbrowserclass.o \
+    $(MAINRECPTDIR)/datelistbrowserclass.o \
+    $(MAINRECPTDIR)/invbrowserclass.o \
+    $(MAINRECPTDIR)/pagedbrowserclass.o \
+    $(MAINRECPTDIR)/htmlbrowserclass.o \
+    $(MAINRECPTDIR)/receptionist.o \
+    $(MAINRECPTDIR)/recptconfig.o \
+    $(MAINRECPTDIR)/cgiwrapper.o \
+    $(MAINRECPTDIR)/cgiargs.o \
+    $(MAINRECPTDIR)/action.o \
+    $(MAINRECPTDIR)/converter.o \
+    $(MAINRECPTDIR)/cgiutils.o \
+    $(MAINRECPTDIR)/OIDtools.o \
+    $(MAINRECPTDIR)/htmlgen.o \
+    $(MAINRECPTDIR)/pageaction.o \
+    $(MAINRECPTDIR)/comtypes.o \
+    $(MAINRECPTDIR)/recptproto.o \
+    $(MAINRECPTDIR)/queryaction.o \
+    $(MAINRECPTDIR)/querytools.o \
+    $(MAINRECPTDIR)/documentaction.o \
+    $(MAINRECPTDIR)/htmlutils.o \
+    $(MAINRECPTDIR)/nullproto.o \
+    $(MAINRECPTDIR)/infodbclass.o \
+    $(MAINRECPTDIR)/formattools.o \
+    $(MAINRECPTDIR)/historydb.o \
+    $(MAINRECPTDIR)/summarise.o \
+    $(MAINRECPTDIR)/extlinkaction.o \
+    $(MAINRECPTDIR)/phindaction.o \
+    $(MAINRECPTDIR)/phindbrowserclass.o \
+    $(MAINCOLSERVRDIR)/mgq.o \
+    $(MAINCOLSERVRDIR)/querycache.o \
+    $(MAINCOLSERVRDIR)/queryinfo.o \
+    $(MAINCOLSERVRDIR)/collectset.o \
+    $(MAINCOLSERVRDIR)/collectserver.o \
+    $(MAINCOLSERVRDIR)/colservrconfig.o \
+    $(MAINCOLSERVRDIR)/maptools.o \
+    $(MAINCOLSERVRDIR)/filter.o \
+    $(MAINCOLSERVRDIR)/source.o \
+    $(MAINCOLSERVRDIR)/browsefilter.o \
+    $(MAINCOLSERVRDIR)/queryfilter.o \
+    $(MAINCOLSERVRDIR)/mgqueryfilter.o \
+    $(MAINCOLSERVRDIR)/mgppqueryfilter.o \
+    $(MAINCOLSERVRDIR)/phrasesearch.o \
+    $(MAINCOLSERVRDIR)/mggdbmsource.o \
+    $(MAINCOLSERVRDIR)/search.o \
+    $(MAINCOLSERVRDIR)/mgsearch.o \
+    $(MAINCOLSERVRDIR)/mgppsearch.o \
+    $(GD)/lib/gsdllib.a  \
+    $(GD)/packages/mg/src/text/libtextin.a \
+    $(GD)/packages/mg/lib/libmg.a \
+    $(GD)/src/mgpp/text/libtextin.a \
+    $(GD)/src/mgpp/lib/libmg.a
+
+ptmx: $(PTMX_OBJS)
+	$(LINK) $(PTMX_OBJS) $(LIBS) 
Index: /tags/start/protemix/src/recpt/acconfig.h
===================================================================
--- /tags/start/protemix/src/recpt/acconfig.h	(revision 13666)
+++ /tags/start/protemix/src/recpt/acconfig.h	(revision 13666)
@@ -0,0 +1,43 @@
+/* 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
+
+
+
+
+
Index: /tags/start/protemix/src/recpt/aclocal.m4
===================================================================
--- /tags/start/protemix/src/recpt/aclocal.m4	(revision 13666)
+++ /tags/start/protemix/src/recpt/aclocal.m4	(revision 13666)
@@ -0,0 +1,141 @@
+# 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)
+  LIBOBJS="$LIBOBJS regex.o"
+fi])
+if test -z "$ac_with_regex"; then
+  AC_MSG_RESULT(rx)
+  AC_CHECK_FUNC(re_rx_search, , [LIBOBJS="$LIBOBJS rx.o"])
+fi
+AC_SUBST(LIBOBJS)dnl
+])
Index: /tags/start/protemix/src/recpt/config.h
===================================================================
--- /tags/start/protemix/src/recpt/config.h	(revision 13666)
+++ /tags/start/protemix/src/recpt/config.h	(revision 13666)
@@ -0,0 +1,193 @@
+/* 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 "gsdl"
+
+/* Define to the version of the distribution.  */
+#define VERSION "2.38"
+
+/* 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 */
+/* #undef HAVE_PR_BRKSIZE */
+
+/* Define FASTCGI if needsbe */
+/* #undef USE_FASTCGI */
+
+/* Define if you have the ftime function.  */
+#define HAVE_FTIME 1
+
+/* Define if you have the ftruncate function.  */
+#define HAVE_FTRUNCATE 1
+
+/* Define if you have the getpagesize function.  */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the getrusage function.  */
+#define HAVE_GETRUSAGE 1
+
+/* Define if you have the mallinfo function.  */
+#define HAVE_MALLINFO 1
+
+/* Define if you have the select function.  */
+#define HAVE_SELECT 1
+
+/* Define if you have the setbuffer function.  */
+#define HAVE_SETBUFFER 1
+
+/* Define if you have the strcasecmp function.  */
+#define HAVE_STRCASECMP 1
+
+/* 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 <crypt.h> header file.  */
+#define HAVE_CRYPT_H 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 crypt library (-lcrypt).  */
+#define HAVE_LIBCRYPT 1
+
+/* Define if you have the g library (-lg).  */
+#define HAVE_LIBG 1
+
+/* Define if you have the gdbm library (-lgdbm).  */
+#define HAVE_LIBGDBM 1
+
+/* Define if you have the m library (-lm).  */
+#define HAVE_LIBM 1
+
+/* Define if you have the stdc++ library (-lstdc++).  */
+#define HAVE_LIBSTDC__ 1
Index: /tags/start/protemix/src/recpt/config.h.in
===================================================================
--- /tags/start/protemix/src/recpt/config.h.in	(revision 13666)
+++ /tags/start/protemix/src/recpt/config.h.in	(revision 13666)
@@ -0,0 +1,192 @@
+/* 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.  */
+#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 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 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__
Index: /tags/start/protemix/src/recpt/config.log
===================================================================
--- /tags/start/protemix/src/recpt/config.log	(revision 13666)
+++ /tags/start/protemix/src/recpt/config.log	(revision 13666)
@@ -0,0 +1,676 @@
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by configure, which was
+generated by GNU Autoconf 2.50.  Invocation command line was
+
+  $ ./configure 
+
+## ---------- ##
+## Platform.  ##
+## ---------- ##
+
+hostname = lomu
+uname -m = i686
+uname -r = 2.4.18
+uname -s = Linux
+uname -v = #1 SMP Fri Apr 19 11:01:35 NZST 2002
+
+/usr/bin/uname -p = unknown
+/bin/uname -X     = unknown
+
+/bin/arch              = i686
+/usr/bin/arch -k       = unknown
+/usr/convex/getsysinfo = unknown
+hostinfo               = unknown
+/bin/machine           = unknown
+/usr/bin/oslevel       = unknown
+/bin/universe          = unknown
+
+PATH = /usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games:/usr/local/j2sdk1.4.0/bin:/usr/local/gsdl/bin/script:/usr/local/gsdl/bin/linux
+
+## ------------ ##
+## Core tests.  ##
+## ------------ ##
+
+configure:935: PATH=".;."; conftest.sh
+./configure: conftest.sh: command not found
+configure:938: $? = 127
+configure:1032: checking for gcc
+configure:1047: found /usr/bin/gcc
+configure:1055: result: gcc
+configure:1299: checking for C compiler default output
+configure:1302: gcc -O2   conftest.c  >&5
+configure:1305: $? = 0
+configure:1328: result: a.out
+configure:1333: checking whether the C compiler works
+configure:1339: ./a.out
+configure:1342: $? = 0
+configure:1357: result: yes
+configure:1364: checking whether we are cross compiling
+configure:1366: result: no
+configure:1369: checking for executable suffix
+configure:1371: gcc -o conftest -O2   conftest.c  >&5
+configure:1374: $? = 0
+configure:1396: result: 
+configure:1402: checking for object suffix
+configure:1420: gcc -c -O2  conftest.c >&5
+configure:1423: $? = 0
+configure:1442: result: o
+configure:1446: checking whether we are using the GNU C compiler
+configure:1467: gcc -c -O2  conftest.c >&5
+configure:1470: $? = 0
+configure:1473: test -s conftest.o
+configure:1476: $? = 0
+configure:1488: result: yes
+configure:1494: checking whether gcc accepts -g
+configure:1512: gcc -c -g  conftest.c >&5
+configure:1515: $? = 0
+configure:1518: test -s conftest.o
+configure:1521: $? = 0
+configure:1531: result: yes
+configure:1558: gcc -c -O2  conftest.c >&5
+conftest.c:2: parse error before `me'
+configure:1561: $? = 1
+configure: failed program was:
+#ifndef __cplusplus
+  choke me
+#endif
+configure:1705: checking for g++
+configure:1720: found /usr/bin/g++
+configure:1728: result: g++
+configure:1742: checking whether we are using the GNU C++ compiler
+configure:1763: g++ -c   conftest.cc >&5
+configure:1766: $? = 0
+configure:1769: test -s conftest.o
+configure:1772: $? = 0
+configure:1784: result: yes
+configure:1790: checking whether g++ accepts -g
+configure:1808: g++ -c -g  conftest.cc >&5
+configure:1811: $? = 0
+configure:1814: test -s conftest.o
+configure:1817: $? = 0
+configure:1827: result: yes
+configure:1867: g++ -c -g -O2  conftest.cc >&5
+configure:1870: $? = 0
+configure:1873: test -s conftest.o
+configure:1876: $? = 0
+configure:1898: g++ -c -g -O2  conftest.cc >&5
+configure:1901: $? = 0
+configure:1904: test -s conftest.o
+configure:1907: $? = 0
+configure:1930: checking for mawk
+configure:1945: found /usr/bin/mawk
+configure:1953: result: mawk
+configure:1967: checking for bison
+configure:1982: found /usr/bin/bison
+configure:1990: result: bison -y
+configure:2038: checking for a BSD compatible install
+configure:2087: result: /usr/bin/install -c
+configure:2098: checking whether ln -s works
+configure:2102: result: yes
+configure:2109: checking whether make sets ${MAKE}
+configure:2129: result: yes
+configure:2176: checking for ranlib
+configure:2191: found /usr/bin/ranlib
+configure:2200: result: ranlib
+configure:2217: checking how to run the C preprocessor
+configure:2244: gcc -E  conftest.c
+configure:2250: $? = 0
+configure:2277: gcc -E  conftest.c
+configure:2274: ac_nonexistent.h: No such file or directory
+configure:2283: $? = 1
+configure: failed program was:
+#line 2273 "configure"
+#include "confdefs.h"
+#include <ac_nonexistent.h>
+configure:2320: result: gcc -E
+configure:2335: gcc -E  conftest.c
+configure:2341: $? = 0
+configure:2368: gcc -E  conftest.c
+configure:2365: ac_nonexistent.h: No such file or directory
+configure:2374: $? = 1
+configure: failed program was:
+#line 2364 "configure"
+#include "confdefs.h"
+#include <ac_nonexistent.h>
+configure:2413: checking for AIX
+configure:2432: result: no
+configure:2437: checking for POSIXized ISC
+configure:2456: result: no
+configure:2461: checking for minix/config.h
+configure:2471: gcc -E  conftest.c
+configure:2468: minix/config.h: No such file or directory
+configure:2477: $? = 1
+configure: failed program was:
+#line 2467 "configure"
+#include "confdefs.h"
+#include <minix/config.h>
+configure:2496: result: no
+configure:2520: checking for gcc option to accept ANSI C
+configure:2554: gcc -c -O2   conftest.c >&5
+configure:2557: $? = 0
+configure:2560: test -s conftest.o
+configure:2563: $? = 0
+configure:2576: result: 
+configure:2583: checking for function prototypes
+configure:2586: result: yes
+configure:2599: checking for gcc option to accept ANSI C
+configure:2682: result: none needed
+configure:2690: checking for an ANSI C-conforming const
+configure:2754: gcc -c -O2  conftest.c >&5
+configure:2757: $? = 0
+configure:2760: test -s conftest.o
+configure:2763: $? = 0
+configure:2773: result: yes
+configure:2783: checking for ANSI C header files
+configure:2797: gcc -E  conftest.c
+configure:2803: $? = 0
+configure:2890: gcc -o conftest -O2   conftest.c  >&5
+configure:2893: $? = 0
+configure:2895: ./conftest
+configure:2898: $? = 0
+configure:2911: result: yes
+configure:2924: checking for stdlib.h
+configure:2934: gcc -E  conftest.c
+configure:2940: $? = 0
+configure:2959: result: yes
+configure:2924: checking for string.h
+configure:2934: gcc -E  conftest.c
+configure:2940: $? = 0
+configure:2959: result: yes
+configure:2924: checking for memory.h
+configure:2934: gcc -E  conftest.c
+configure:2940: $? = 0
+configure:2959: result: yes
+configure:2924: checking for strings.h
+configure:2934: gcc -E  conftest.c
+configure:2940: $? = 0
+configure:2959: result: yes
+configure:2924: checking for inttypes.h
+configure:2934: gcc -E  conftest.c
+configure:2940: $? = 0
+configure:2959: result: yes
+configure:2924: checking for unistd.h
+configure:2934: gcc -E  conftest.c
+configure:2940: $? = 0
+configure:2959: result: yes
+configure:2969: checking for off_t
+configure:2990: gcc -c -O2  conftest.c >&5
+configure:2993: $? = 0
+configure:2996: test -s conftest.o
+configure:2999: $? = 0
+configure:3009: result: yes
+configure:3021: checking for size_t
+configure:3042: gcc -c -O2  conftest.c >&5
+configure:3045: $? = 0
+configure:3048: test -s conftest.o
+configure:3051: $? = 0
+configure:3061: result: yes
+configure:3073: checking whether time.h and sys/time.h may both be included
+configure:3094: gcc -c -O2  conftest.c >&5
+configure:3097: $? = 0
+configure:3100: test -s conftest.o
+configure:3103: $? = 0
+configure:3113: result: yes
+configure:3123: checking whether struct tm is in sys/time.h or time.h
+configure:3143: gcc -c -O2  conftest.c >&5
+configure:3146: $? = 0
+configure:3149: test -s conftest.o
+configure:3152: $? = 0
+configure:3162: result: time.h
+configure:3207: checking for main in -lg
+configure:3227: gcc -o conftest -O2   conftest.c -lg   >&5
+configure:3230: $? = 0
+configure:3233: test -s conftest
+configure:3236: $? = 0
+configure:3247: result: yes
+configure:3258: checking for main in -lgdbm
+configure:3278: gcc -o conftest -O2   conftest.c -lgdbm  -lg  >&5
+configure:3281: $? = 0
+configure:3284: test -s conftest
+configure:3287: $? = 0
+configure:3298: result: yes
+configure:3309: checking for main in -lm
+configure:3329: gcc -o conftest -O2   conftest.c -lm  -lgdbm -lg  >&5
+configure:3332: $? = 0
+configure:3335: test -s conftest
+configure:3338: $? = 0
+configure:3349: result: yes
+configure:3360: checking for main in -lstdc++
+configure:3380: gcc -o conftest -O2   conftest.c -lstdc++  -lm -lgdbm -lg  >&5
+configure:3383: $? = 0
+configure:3386: test -s conftest
+configure:3389: $? = 0
+configure:3400: result: yes
+configure:3411: checking for main in -lcrypt
+configure:3431: gcc -o conftest -O2   conftest.c -lcrypt  -lstdc++ -lm -lgdbm -lg  >&5
+configure:3434: $? = 0
+configure:3437: test -s conftest
+configure:3440: $? = 0
+configure:3451: result: yes
+configure:3465: checking for dirent.h that defines DIR
+configure:3485: gcc -c -O2  conftest.c >&5
+configure:3488: $? = 0
+configure:3491: test -s conftest.o
+configure:3494: $? = 0
+configure:3504: result: yes
+configure:3517: checking for opendir in -ldir
+configure:3544: gcc -o conftest -O2   conftest.c -ldir  -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+/usr/bin/ld: cannot find -ldir
+collect2: ld returned 1 exit status
+configure:3547: $? = 1
+configure: failed program was:
+#line 3525 "configure"
+#include "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;
+}
+configure:3564: result: no
+configure:3626: checking for ANSI C header files
+configure:3754: result: yes
+configure:3767: checking for fcntl.h
+configure:3777: gcc -E  conftest.c
+configure:3783: $? = 0
+configure:3802: result: yes
+configure:3767: checking for limits.h
+configure:3777: gcc -E  conftest.c
+configure:3783: $? = 0
+configure:3802: result: yes
+configure:3767: checking for sys/time.h
+configure:3777: gcc -E  conftest.c
+configure:3783: $? = 0
+configure:3802: result: yes
+configure:3767: checking for unistd.h
+configure:3802: result: yes
+configure:3767: checking for crypt.h
+configure:3777: gcc -E  conftest.c
+configure:3783: $? = 0
+configure:3802: result: yes
+configure:3767: checking for string.h
+configure:3802: result: yes
+configure:3767: checking for memory.h
+configure:3802: result: yes
+configure:3767: checking for sys/procfs.h
+configure:3777: gcc -E  conftest.c
+configure:3783: $? = 0
+configure:3802: result: yes
+configure:3859: checking for working alloca.h
+configure:3877: gcc -o conftest -O2   conftest.c -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+configure:3880: $? = 0
+configure:3883: test -s conftest
+configure:3886: $? = 0
+configure:3896: result: yes
+configure:3906: checking for alloca
+configure:3944: gcc -o conftest -O2   conftest.c -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+configure:3947: $? = 0
+configure:3950: test -s conftest
+configure:3953: $? = 0
+configure:3963: result: yes
+configure:4145: checking whether gcc needs -traditional
+configure:4180: result: no
+configure:4187: checking return type of signal handlers
+configure:4215: gcc -c -O2  conftest.c >&5
+configure:4218: $? = 0
+configure:4221: test -s conftest.o
+configure:4224: $? = 0
+configure:4234: result: void
+configure:4244: checking for vprintf
+configure:4281: gcc -o conftest -O2   conftest.c -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+configure:4284: $? = 0
+configure:4287: test -s conftest
+configure:4290: $? = 0
+configure:4300: result: yes
+configure:4307: checking for _doprnt
+configure:4344: gcc -o conftest -O2   conftest.c -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+/tmp/ccCb3VyG.o: In function `main':
+/tmp/ccCb3VyG.o(.text+0x9): undefined reference to `_doprnt'
+collect2: ld returned 1 exit status
+configure:4347: $? = 1
+configure: failed program was:
+#line 4313 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char _doprnt (); below.  */
+#include <assert.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 _doprnt ();
+char (*f) ();
+
+int
+main ()
+{
+/* 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
+f = _doprnt;
+#endif
+
+  ;
+  return 0;
+}
+configure:4363: result: no
+configure:4379: checking for ftime
+configure:4416: gcc -o conftest -O2   conftest.c -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+configure:4419: $? = 0
+configure:4422: test -s conftest
+configure:4425: $? = 0
+configure:4435: result: yes
+configure:4379: checking for select
+configure:4416: gcc -o conftest -O2   conftest.c -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+configure:4419: $? = 0
+configure:4422: test -s conftest
+configure:4425: $? = 0
+configure:4435: result: yes
+configure:4379: checking for strftime
+configure:4416: gcc -o conftest -O2   conftest.c -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+configure:4419: $? = 0
+configure:4422: test -s conftest
+configure:4425: $? = 0
+configure:4435: result: yes
+configure:4379: checking for strtol
+configure:4416: gcc -o conftest -O2   conftest.c -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+configure:4419: $? = 0
+configure:4422: test -s conftest
+configure:4425: $? = 0
+configure:4435: result: yes
+configure:4379: checking for getrusage
+configure:4416: gcc -o conftest -O2   conftest.c -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+configure:4419: $? = 0
+configure:4422: test -s conftest
+configure:4425: $? = 0
+configure:4435: result: yes
+configure:4379: checking for times
+configure:4416: gcc -o conftest -O2   conftest.c -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+configure:4419: $? = 0
+configure:4422: test -s conftest
+configure:4425: $? = 0
+configure:4435: result: yes
+configure:4379: checking for mallinfo
+configure:4416: gcc -o conftest -O2   conftest.c -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+configure:4419: $? = 0
+configure:4422: test -s conftest
+configure:4425: $? = 0
+configure:4435: result: yes
+configure:4379: checking for setbuffer
+configure:4416: gcc -o conftest -O2   conftest.c -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+configure:4419: $? = 0
+configure:4422: test -s conftest
+configure:4425: $? = 0
+configure:4435: result: yes
+configure:4379: checking for getpagesize
+configure:4416: gcc -o conftest -O2   conftest.c -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+configure:4419: $? = 0
+configure:4422: test -s conftest
+configure:4425: $? = 0
+configure:4435: result: yes
+configure:4379: checking for strerror
+configure:4416: gcc -o conftest -O2   conftest.c -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+configure:4419: $? = 0
+configure:4422: test -s conftest
+configure:4425: $? = 0
+configure:4435: result: yes
+configure:4448: checking for ftruncate
+configure:4485: gcc -o conftest -O2   conftest.c -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+configure:4488: $? = 0
+configure:4491: test -s conftest
+configure:4494: $? = 0
+configure:4504: result: yes
+configure:4448: checking for strstr
+configure:4485: gcc -o conftest -O2   conftest.c -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+configure:4488: $? = 0
+configure:4491: test -s conftest
+configure:4494: $? = 0
+configure:4504: result: yes
+configure:4448: checking for strcasecmp
+configure:4485: gcc -o conftest -O2   conftest.c -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+configure:4488: $? = 0
+configure:4491: test -s conftest
+configure:4494: $? = 0
+configure:4504: result: yes
+configure:4518: checking for HP-UX needing gmalloc
+configure:4529: result: no
+configure:4535: checking for valloc
+configure:4572: gcc -o conftest -O2   conftest.c -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+configure:4575: $? = 0
+configure:4578: test -s conftest
+configure:4581: $? = 0
+configure:4591: result: yes
+configure:4603: checking if malloc debugging is wanted
+configure:4623: result: no
+configure:4627: checking which of rx or regex is wanted
+configure:4645: result: rx
+configure:4647: checking for re_rx_search
+configure:4684: gcc -o conftest -O2   conftest.c -lcrypt -lstdc++ -lm -lgdbm -lg  >&5
+/tmp/ccmD11tE.o: In function `main':
+/tmp/ccmD11tE.o(.text+0x9): undefined reference to `re_rx_search'
+collect2: ld returned 1 exit status
+configure:4687: $? = 1
+configure: failed program was:
+#line 4653 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char re_rx_search (); below.  */
+#include <assert.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 re_rx_search ();
+char (*f) ();
+
+int
+main ()
+{
+/* 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
+f = re_rx_search;
+#endif
+
+  ;
+  return 0;
+}
+configure:4703: result: no
+configure:4726: checking "that the GDBM library is available"
+configure:4743: g++ -c -g -O2  conftest.cc >&5
+configure:4746: $? = 0
+configure:4749: test -s conftest.o
+configure:4752: $? = 0
+configure:4762: result: yes
+configure:4771: checking "whether STL library has known faults"
+configure:4788: g++ -c -g -O2  conftest.cc >&5
+configure:4791: $? = 0
+configure:4794: test -s conftest.o
+configure:4797: $? = 0
+configure:4875: result: "no"
+configure:4887: checking for HP-UX needing gmalloc
+configure:4898: result: no
+configure:4904: checking for valloc
+configure:4960: result: yes
+configure:4972: checking if malloc debugging is wanted
+configure:4992: result: no
+configure:4996: checking which of rx or regex is wanted
+configure:5014: result: rx
+configure:5016: checking for re_rx_search
+configure:5072: result: no
+configure:5169: creating ./config.status
+
+## ----------------------- ##
+## Running config.status.  ##
+## ----------------------- ##
+
+This file was extended by config.status 2.50, executed with
+  > ./config.status 
+on lomu
+
+config.status:5606: creating Makefile
+config.status:5698: creating config.h
+config.status:5839: config.h is unchanged
+
+## ----------------- ##
+## Cache variables.  ##
+## ----------------- ##
+
+ac_cv_c_compiler_gnu=yes
+ac_cv_c_const=yes
+ac_cv_cxx_compiler_gnu=yes
+ac_cv_env_CC_set=
+ac_cv_env_CC_value=
+ac_cv_env_CFLAGS_set=
+ac_cv_env_CFLAGS_value=
+ac_cv_env_CPPFLAGS_set=
+ac_cv_env_CPPFLAGS_value=
+ac_cv_env_CPP_set=
+ac_cv_env_CPP_value=
+ac_cv_env_CXXFLAGS_set=
+ac_cv_env_CXXFLAGS_value=
+ac_cv_env_CXX_set=
+ac_cv_env_CXX_value=
+ac_cv_env_LDFLAGS_set=
+ac_cv_env_LDFLAGS_value=
+ac_cv_env_build_alias_set=
+ac_cv_env_build_alias_value=
+ac_cv_env_host_alias_set=
+ac_cv_env_host_alias_value=
+ac_cv_env_target_alias_set=
+ac_cv_env_target_alias_value=
+ac_cv_func__doprnt=no
+ac_cv_func_alloca_works=yes
+ac_cv_func_ftime=yes
+ac_cv_func_ftruncate=yes
+ac_cv_func_getpagesize=yes
+ac_cv_func_getrusage=yes
+ac_cv_func_mallinfo=yes
+ac_cv_func_re_rx_search=no
+ac_cv_func_select=yes
+ac_cv_func_setbuffer=yes
+ac_cv_func_strcasecmp=yes
+ac_cv_func_strerror=yes
+ac_cv_func_strftime=yes
+ac_cv_func_strstr=yes
+ac_cv_func_strtol=yes
+ac_cv_func_times=yes
+ac_cv_func_valloc=yes
+ac_cv_func_vprintf=yes
+ac_cv_header_crypt_h=yes
+ac_cv_header_dirent_dirent_h=yes
+ac_cv_header_fcntl_h=yes
+ac_cv_header_inttypes_h=yes
+ac_cv_header_limits_h=yes
+ac_cv_header_memory_h=yes
+ac_cv_header_minix_config_h=no
+ac_cv_header_stdc=yes
+ac_cv_header_stdlib_h=yes
+ac_cv_header_string_h=yes
+ac_cv_header_strings_h=yes
+ac_cv_header_sys_procfs_h=yes
+ac_cv_header_sys_time_h=yes
+ac_cv_header_time=yes
+ac_cv_header_unistd_h=yes
+ac_cv_lib_crypt_main=yes
+ac_cv_lib_dir_opendir=no
+ac_cv_lib_g_main=yes
+ac_cv_lib_gdbm_main=yes
+ac_cv_lib_m_main=yes
+ac_cv_lib_stdcpp_main=yes
+ac_cv_objext=o
+ac_cv_path_install='/usr/bin/install -c'
+ac_cv_prog_AWK=mawk
+ac_cv_prog_CPP='gcc -E'
+ac_cv_prog_YACC='bison -y'
+ac_cv_prog_ac_ct_CC=gcc
+ac_cv_prog_ac_ct_CXX=g++
+ac_cv_prog_ac_ct_RANLIB=ranlib
+ac_cv_prog_cc_g=yes
+ac_cv_prog_cc_stdc=
+ac_cv_prog_cxx_g=yes
+ac_cv_prog_gcc_traditional=no
+ac_cv_prog_make_make_set=yes
+ac_cv_struct_tm=time.h
+ac_cv_type_off_t=yes
+ac_cv_type_signal=void
+ac_cv_type_size_t=yes
+ac_cv_working_alloca_h=yes
+
+## ------------ ##
+## confdefs.h.  ##
+## ------------ ##
+
+#define PACKAGE "gsdl"
+#define VERSION "2.38"
+#ifdef __cplusplus
+#endif
+#define PROTOTYPES 1
+#define STDC_HEADERS 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_STRINGS_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_UNISTD_H 1
+#define TIME_WITH_SYS_TIME 1
+#define HAVE_LIBG 1
+#define HAVE_LIBGDBM 1
+#define HAVE_LIBM 1
+#define HAVE_LIBSTDC__ 1
+#define HAVE_LIBCRYPT 1
+#define HAVE_DIRENT_H 1
+#define STDC_HEADERS 1
+#define HAVE_FCNTL_H 1
+#define HAVE_LIMITS_H 1
+#define HAVE_SYS_TIME_H 1
+#define HAVE_UNISTD_H 1
+#define HAVE_CRYPT_H 1
+#define HAVE_STRING_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_SYS_PROCFS_H 1
+#define HAVE_FREAD_DECL 1
+#define HAVE_FGETC_DECL 1
+#define HAVE_ALLOCA_H 1
+#define HAVE_ALLOCA 1
+#define RETSIGTYPE void
+#define HAVE_VPRINTF 1
+#define HAVE_FTIME 1
+#define HAVE_SELECT 1
+#define HAVE_STRFTIME 1
+#define HAVE_STRTOL 1
+#define HAVE_GETRUSAGE 1
+#define HAVE_TIMES 1
+#define HAVE_MALLINFO 1
+#define HAVE_SETBUFFER 1
+#define HAVE_GETPAGESIZE 1
+#define HAVE_STRERROR 1
+#define HAVE_FTRUNCATE 1
+#define HAVE_STRSTR 1
+#define HAVE_STRCASECMP 1
+#define HAVE_VALLOC 1
+#define HAVE_VALLOC 1
+
+
+configure: exit 0
Index: /tags/start/protemix/src/recpt/config.status
===================================================================
--- /tags/start/protemix/src/recpt/config.status	(revision 13666)
+++ /tags/start/protemix/src/recpt/config.status	(revision 13666)
@@ -0,0 +1,708 @@
+#! /bin/sh
+# Generated automatically by configure.
+# 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
+SHELL=${CONFIG_SHELL-/bin/sh}
+ac_cs_invocation="$0 $@"
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+
+# Name of the executable.
+as_me=`echo "$0" |sed 's,.*[\\/],,'`
+
+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
+
+as_executable_p="test -f"
+
+# Support unset when possible.
+if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+# NLS nuisances.
+$as_unset LANG || test "${LANG+set}" != set || { LANG=C; export LANG; }
+$as_unset LC_ALL || test "${LC_ALL+set}" != set || { LC_ALL=C; export LC_ALL; }
+$as_unset LC_TIME || test "${LC_TIME+set}" != set || { LC_TIME=C; export LC_TIME; }
+$as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set || { LC_CTYPE=C; export LC_CTYPE; }
+$as_unset LANGUAGE || test "${LANGUAGE+set}" != set || { LANGUAGE=C; export LANGUAGE; }
+$as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set || { LC_COLLATE=C; export LC_COLLATE; }
+$as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set || { LC_NUMERIC=C; export LC_NUMERIC; }
+$as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set || { LC_MESSAGES=C; export LC_MESSAGES; }
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=:; export CDPATH; }
+
+exec 6>&1
+
+config_files=" Makefile"
+config_headers=" config.h"
+
+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
+  -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>."
+ac_cs_version="\
+config.status
+configured by ./configure, generated by GNU Autoconf 2.50,
+  with options \"\"
+
+Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+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=.
+INSTALL="/usr/bin/install -c"
+# 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[^=]*=\(.*\)'`
+    shift
+    set dummy "$ac_option" "$ac_optarg" ${1+"$@"}
+    shift
+    ;;
+  -*);;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_need_defaults=false;;
+  esac
+
+  case $1 in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    echo "running /bin/sh ./configure "  " --no-create --no-recursion"
+    exec /bin/sh ./configure  --no-create --no-recursion ;;
+  --version | --vers* | -V )
+    echo "$ac_cs_version"; exit 0 ;;
+  --he | --h)
+    # Conflict between --help and --header
+    { { echo "$as_me:5342: 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 )
+    shift
+    CONFIG_FILES="$CONFIG_FILES $1"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $1"
+    ac_need_defaults=false;;
+
+  # Handling of arguments.
+  'Makefile' ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+  'config.h' ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+
+  # This is an error.
+  -*) { { echo "$as_me:5365: 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; }; } ;;
+  *) { { echo "$as_me:5370: error: invalid argument: $1" >&5
+echo "$as_me: error: invalid argument: $1" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+  shift
+done
+
+exec 5>>config.log
+cat >&5 << _ACEOF
+
+## ----------------------- ##
+## Running config.status.  ##
+## ----------------------- ##
+
+This file was extended by $as_me 2.50, executed with
+  > $ac_cs_invocation
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+
+_ACEOF
+# 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
+
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit $?); exit $?; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+: ${TMPDIR=/tmp}
+{
+  tmp=`(umask 077 && mktemp -d -q "$TMPDIR/csXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=$TMPDIR/cs$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in $TMPDIR" >&2
+   { (exit 1); exit 1; }
+}
+
+
+#
+# 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@,/bin/sh,;t t
+s,@exec_prefix@,${prefix},;t t
+s,@prefix@,/usr/local,;t t
+s,@program_transform_name@,s,x,x,,;t t
+s,@bindir@,${exec_prefix}/bin,;t t
+s,@sbindir@,${exec_prefix}/sbin,;t t
+s,@libexecdir@,${exec_prefix}/libexec,;t t
+s,@datadir@,${prefix}/share,;t t
+s,@sysconfdir@,${prefix}/etc,;t t
+s,@sharedstatedir@,${prefix}/com,;t t
+s,@localstatedir@,${prefix}/var,;t t
+s,@libdir@,${exec_prefix}/lib,;t t
+s,@includedir@,${prefix}/include,;t t
+s,@oldincludedir@,/usr/include,;t t
+s,@infodir@,${prefix}/info,;t t
+s,@mandir@,${prefix}/man,;t t
+s,@PACKAGE_NAME@,,;t t
+s,@PACKAGE_TARNAME@,,;t t
+s,@PACKAGE_VERSION@,,;t t
+s,@PACKAGE_STRING@,,;t t
+s,@PACKAGE_BUGREPORT@,,;t t
+s,@ECHO_C@,,;t t
+s,@ECHO_N@,-n,;t t
+s,@ECHO_T@,,;t t
+s,@PATH_SEPARATOR@,:,;t t
+s,@DEFS@,-DHAVE_CONFIG_H,;t t
+s,@LIBS@,-lcrypt -lstdc++ -lm -lgdbm -lg ,;t t
+s,@PACKAGE@,gsdl,;t t
+s,@VERSION@,2.38,;t t
+s,@USE_FASTCGI@,0,;t t
+s,@CFLAGS@,-O2,;t t
+s,@CC@,gcc,;t t
+s,@LDFLAGS@,,;t t
+s,@CPPFLAGS@,,;t t
+s,@ac_ct_CC@,gcc,;t t
+s,@EXEEXT@,,;t t
+s,@OBJEXT@,o,;t t
+s,@CXX@,g++,;t t
+s,@CXXFLAGS@,-g -O2,;t t
+s,@ac_ct_CXX@,g++,;t t
+s,@AWK@,mawk,;t t
+s,@YACC@,bison -y,;t t
+s,@INSTALL_PROGRAM@,${INSTALL},;t t
+s,@INSTALL_SCRIPT@,${INSTALL},;t t
+s,@INSTALL_DATA@,${INSTALL} -m 644,;t t
+s,@LN_S@,ln -s,;t t
+s,@SET_MAKE@,,;t t
+s,@RANLIB@,ranlib,;t t
+s,@ac_ct_RANLIB@,ranlib,;t t
+s,@CPP@,gcc -E,;t t
+s,@U@,,;t t
+s,@ANSI2KNR@,,;t t
+s,@ALLOCA@,,;t t
+s,@LIBOBJS@, rx.o rx.o,;t t
+s,@gsdlos@,linux,;t t
+CEOF
+
+  # 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"
+
+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=`$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 test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+    { case "$ac_dir" in
+  [\\/]* | ?:[\\/]* ) as_incr_dir=;;
+  *)                      as_incr_dir=.;;
+esac
+as_dummy="$ac_dir"
+for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do
+  case $as_mkdir_dir in
+    # Skip DOS drivespec
+    ?:) as_incr_dir=$as_mkdir_dir ;;
+    *)
+      as_incr_dir=$as_incr_dir/$as_mkdir_dir
+      test -d "$as_incr_dir" || mkdir "$as_incr_dir"
+    ;;
+  esac
+done; }
+
+    ac_dir_suffix="/`echo $ac_dir|sed 's,^\./,,'`"
+    # A "../" for each directory in $ac_dir_suffix.
+    ac_dots=`echo "$ac_dir_suffix" | sed 's,/[^/]*,../,g'`
+  else
+    ac_dir_suffix= ac_dots=
+  fi
+
+  case $srcdir in
+  .)  ac_srcdir=.
+      if test -z "$ac_dots"; then
+         ac_top_srcdir=.
+      else
+         ac_top_srcdir=`echo $ac_dots | sed 's,/$,,'`
+      fi ;;
+  [\\/]* | ?:[\\/]* )
+      ac_srcdir=$srcdir$ac_dir_suffix;
+      ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_dots$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_dots$srcdir ;;
+  esac
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_dots$INSTALL ;;
+  esac
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:5606: 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 automatically by config.status.  */
+  configure_input="Generated automatically 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:5624: 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:5637: 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; }
+  sed "/^[ 	]*VPATH[ 	]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[ 	]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[ 	]*$//;
+}
+
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;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
+
+#
+# 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:5698: 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:5709: 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:5722: 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
+
+  # Handle all the #define templates only if necessary.
+  if egrep "^[ 	]*#[ 	]*define" $tmp/in >/dev/null; then
+  # If there are no defines, we may have an empty if/fi
+  :
+  cat >$tmp/defines.sed <<CEOF
+/^[ 	]*#[ 	]*define/!b
+t clr
+: clr
+${ac_dA}PACKAGE${ac_dB}PACKAGE${ac_dC}"gsdl"${ac_dD}
+${ac_dA}VERSION${ac_dB}VERSION${ac_dC}"2.38"${ac_dD}
+${ac_dA}PROTOTYPES${ac_dB}PROTOTYPES${ac_dC}1${ac_dD}
+${ac_dA}STDC_HEADERS${ac_dB}STDC_HEADERS${ac_dC}1${ac_dD}
+${ac_dA}HAVE_STDLIB_H${ac_dB}HAVE_STDLIB_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_STRING_H${ac_dB}HAVE_STRING_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_MEMORY_H${ac_dB}HAVE_MEMORY_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_STRINGS_H${ac_dB}HAVE_STRINGS_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_INTTYPES_H${ac_dB}HAVE_INTTYPES_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_UNISTD_H${ac_dB}HAVE_UNISTD_H${ac_dC}1${ac_dD}
+${ac_dA}TIME_WITH_SYS_TIME${ac_dB}TIME_WITH_SYS_TIME${ac_dC}1${ac_dD}
+${ac_dA}HAVE_LIBG${ac_dB}HAVE_LIBG${ac_dC}1${ac_dD}
+${ac_dA}HAVE_LIBGDBM${ac_dB}HAVE_LIBGDBM${ac_dC}1${ac_dD}
+${ac_dA}HAVE_LIBM${ac_dB}HAVE_LIBM${ac_dC}1${ac_dD}
+${ac_dA}HAVE_LIBSTDC__${ac_dB}HAVE_LIBSTDC__${ac_dC}1${ac_dD}
+${ac_dA}HAVE_LIBCRYPT${ac_dB}HAVE_LIBCRYPT${ac_dC}1${ac_dD}
+${ac_dA}HAVE_DIRENT_H${ac_dB}HAVE_DIRENT_H${ac_dC}1${ac_dD}
+${ac_dA}STDC_HEADERS${ac_dB}STDC_HEADERS${ac_dC}1${ac_dD}
+${ac_dA}HAVE_FCNTL_H${ac_dB}HAVE_FCNTL_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_LIMITS_H${ac_dB}HAVE_LIMITS_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_SYS_TIME_H${ac_dB}HAVE_SYS_TIME_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_UNISTD_H${ac_dB}HAVE_UNISTD_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_CRYPT_H${ac_dB}HAVE_CRYPT_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_STRING_H${ac_dB}HAVE_STRING_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_MEMORY_H${ac_dB}HAVE_MEMORY_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_SYS_PROCFS_H${ac_dB}HAVE_SYS_PROCFS_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_FREAD_DECL${ac_dB}HAVE_FREAD_DECL${ac_dC}1${ac_dD}
+${ac_dA}HAVE_FGETC_DECL${ac_dB}HAVE_FGETC_DECL${ac_dC}1${ac_dD}
+${ac_dA}HAVE_ALLOCA_H${ac_dB}HAVE_ALLOCA_H${ac_dC}1${ac_dD}
+${ac_dA}HAVE_ALLOCA${ac_dB}HAVE_ALLOCA${ac_dC}1${ac_dD}
+${ac_dA}RETSIGTYPE${ac_dB}RETSIGTYPE${ac_dC}void${ac_dD}
+${ac_dA}HAVE_VPRINTF${ac_dB}HAVE_VPRINTF${ac_dC}1${ac_dD}
+${ac_dA}HAVE_FTIME${ac_dB}HAVE_FTIME${ac_dC}1${ac_dD}
+${ac_dA}HAVE_SELECT${ac_dB}HAVE_SELECT${ac_dC}1${ac_dD}
+${ac_dA}HAVE_STRFTIME${ac_dB}HAVE_STRFTIME${ac_dC}1${ac_dD}
+${ac_dA}HAVE_STRTOL${ac_dB}HAVE_STRTOL${ac_dC}1${ac_dD}
+${ac_dA}HAVE_GETRUSAGE${ac_dB}HAVE_GETRUSAGE${ac_dC}1${ac_dD}
+${ac_dA}HAVE_TIMES${ac_dB}HAVE_TIMES${ac_dC}1${ac_dD}
+CEOF
+  sed -f $tmp/defines.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+
+  cat >$tmp/defines.sed <<CEOF
+/^[ 	]*#[ 	]*define/!b
+t clr
+: clr
+${ac_dA}HAVE_MALLINFO${ac_dB}HAVE_MALLINFO${ac_dC}1${ac_dD}
+${ac_dA}HAVE_SETBUFFER${ac_dB}HAVE_SETBUFFER${ac_dC}1${ac_dD}
+${ac_dA}HAVE_GETPAGESIZE${ac_dB}HAVE_GETPAGESIZE${ac_dC}1${ac_dD}
+${ac_dA}HAVE_STRERROR${ac_dB}HAVE_STRERROR${ac_dC}1${ac_dD}
+${ac_dA}HAVE_FTRUNCATE${ac_dB}HAVE_FTRUNCATE${ac_dC}1${ac_dD}
+${ac_dA}HAVE_STRSTR${ac_dB}HAVE_STRSTR${ac_dC}1${ac_dD}
+${ac_dA}HAVE_STRCASECMP${ac_dB}HAVE_STRCASECMP${ac_dC}1${ac_dD}
+${ac_dA}HAVE_VALLOC${ac_dB}HAVE_VALLOC${ac_dC}1${ac_dD}
+CEOF
+  sed -f $tmp/defines.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+
+  fi # egrep
+
+  # Handle all the #undef templates
+  cat >$tmp/undefs.sed <<CEOF
+/^[ 	]*#[ 	]*undef/!b
+t clr
+: clr
+${ac_uA}PACKAGE${ac_uB}PACKAGE${ac_uC}"gsdl"${ac_uD}
+${ac_uA}VERSION${ac_uB}VERSION${ac_uC}"2.38"${ac_uD}
+${ac_uA}PROTOTYPES${ac_uB}PROTOTYPES${ac_uC}1${ac_uD}
+${ac_uA}STDC_HEADERS${ac_uB}STDC_HEADERS${ac_uC}1${ac_uD}
+${ac_uA}HAVE_STDLIB_H${ac_uB}HAVE_STDLIB_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_STRING_H${ac_uB}HAVE_STRING_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_MEMORY_H${ac_uB}HAVE_MEMORY_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_STRINGS_H${ac_uB}HAVE_STRINGS_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_INTTYPES_H${ac_uB}HAVE_INTTYPES_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_UNISTD_H${ac_uB}HAVE_UNISTD_H${ac_uC}1${ac_uD}
+${ac_uA}TIME_WITH_SYS_TIME${ac_uB}TIME_WITH_SYS_TIME${ac_uC}1${ac_uD}
+${ac_uA}HAVE_LIBG${ac_uB}HAVE_LIBG${ac_uC}1${ac_uD}
+${ac_uA}HAVE_LIBGDBM${ac_uB}HAVE_LIBGDBM${ac_uC}1${ac_uD}
+${ac_uA}HAVE_LIBM${ac_uB}HAVE_LIBM${ac_uC}1${ac_uD}
+${ac_uA}HAVE_LIBSTDC__${ac_uB}HAVE_LIBSTDC__${ac_uC}1${ac_uD}
+${ac_uA}HAVE_LIBCRYPT${ac_uB}HAVE_LIBCRYPT${ac_uC}1${ac_uD}
+${ac_uA}HAVE_DIRENT_H${ac_uB}HAVE_DIRENT_H${ac_uC}1${ac_uD}
+${ac_uA}STDC_HEADERS${ac_uB}STDC_HEADERS${ac_uC}1${ac_uD}
+${ac_uA}HAVE_FCNTL_H${ac_uB}HAVE_FCNTL_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_LIMITS_H${ac_uB}HAVE_LIMITS_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_SYS_TIME_H${ac_uB}HAVE_SYS_TIME_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_UNISTD_H${ac_uB}HAVE_UNISTD_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_CRYPT_H${ac_uB}HAVE_CRYPT_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_STRING_H${ac_uB}HAVE_STRING_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_MEMORY_H${ac_uB}HAVE_MEMORY_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_SYS_PROCFS_H${ac_uB}HAVE_SYS_PROCFS_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_FREAD_DECL${ac_uB}HAVE_FREAD_DECL${ac_uC}1${ac_uD}
+${ac_uA}HAVE_FGETC_DECL${ac_uB}HAVE_FGETC_DECL${ac_uC}1${ac_uD}
+${ac_uA}HAVE_ALLOCA_H${ac_uB}HAVE_ALLOCA_H${ac_uC}1${ac_uD}
+${ac_uA}HAVE_ALLOCA${ac_uB}HAVE_ALLOCA${ac_uC}1${ac_uD}
+${ac_uA}RETSIGTYPE${ac_uB}RETSIGTYPE${ac_uC}void${ac_uD}
+${ac_uA}HAVE_VPRINTF${ac_uB}HAVE_VPRINTF${ac_uC}1${ac_uD}
+${ac_uA}HAVE_FTIME${ac_uB}HAVE_FTIME${ac_uC}1${ac_uD}
+${ac_uA}HAVE_SELECT${ac_uB}HAVE_SELECT${ac_uC}1${ac_uD}
+${ac_uA}HAVE_STRFTIME${ac_uB}HAVE_STRFTIME${ac_uC}1${ac_uD}
+${ac_uA}HAVE_STRTOL${ac_uB}HAVE_STRTOL${ac_uC}1${ac_uD}
+${ac_uA}HAVE_GETRUSAGE${ac_uB}HAVE_GETRUSAGE${ac_uC}1${ac_uD}
+${ac_uA}HAVE_TIMES${ac_uB}HAVE_TIMES${ac_uC}1${ac_uD}
+CEOF
+  sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+
+  cat >$tmp/undefs.sed <<CEOF
+/^[ 	]*#[ 	]*undef/!b
+t clr
+: clr
+${ac_uA}HAVE_MALLINFO${ac_uB}HAVE_MALLINFO${ac_uC}1${ac_uD}
+${ac_uA}HAVE_SETBUFFER${ac_uB}HAVE_SETBUFFER${ac_uC}1${ac_uD}
+${ac_uA}HAVE_GETPAGESIZE${ac_uB}HAVE_GETPAGESIZE${ac_uC}1${ac_uD}
+${ac_uA}HAVE_STRERROR${ac_uB}HAVE_STRERROR${ac_uC}1${ac_uD}
+${ac_uA}HAVE_FTRUNCATE${ac_uB}HAVE_FTRUNCATE${ac_uC}1${ac_uD}
+${ac_uA}HAVE_STRSTR${ac_uB}HAVE_STRSTR${ac_uC}1${ac_uD}
+${ac_uA}HAVE_STRCASECMP${ac_uB}HAVE_STRCASECMP${ac_uC}1${ac_uD}
+${ac_uA}HAVE_VALLOC${ac_uB}HAVE_VALLOC${ac_uC}1${ac_uD}
+s,^[ 	]*#[ 	]*undef[ 	][ 	]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+CEOF
+  sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+
+  # 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 automatically by config.status.  */
+  if test x"$ac_file" = x-; then
+    echo "/* Generated automatically by configure.  */" >$tmp/config.h
+  else
+    echo "/* $ac_file.  Generated automatically by configure.  */" >$tmp/config.h
+  fi
+  cat $tmp/in >>$tmp/config.h
+  rm -f $tmp/in
+  if test x"$ac_file" != x-; then
+    if cmp -s $ac_file $tmp/config.h 2>/dev/null; then
+      { echo "$as_me:5839: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      ac_dir=`$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 test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+        { case "$ac_dir" in
+  [\\/]* | ?:[\\/]* ) as_incr_dir=;;
+  *)                      as_incr_dir=.;;
+esac
+as_dummy="$ac_dir"
+for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do
+  case $as_mkdir_dir in
+    # Skip DOS drivespec
+    ?:) as_incr_dir=$as_mkdir_dir ;;
+    *)
+      as_incr_dir=$as_incr_dir/$as_mkdir_dir
+      test -d "$as_incr_dir" || mkdir "$as_incr_dir"
+    ;;
+  esac
+done; }
+
+      fi
+      rm -f $ac_file
+      mv $tmp/config.h $ac_file
+    fi
+  else
+    cat $tmp/config.h
+    rm -f $tmp/config.h
+  fi
+done
+
+{ (exit 0); exit 0; }
Index: /tags/start/protemix/src/recpt/configure
===================================================================
--- /tags/start/protemix/src/recpt/configure	(revision 13666)
+++ /tags/start/protemix/src/recpt/configure	(revision 13666)
@@ -0,0 +1,5905 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by Autoconf 2.50.
+#
+# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+
+# Name of the executable.
+as_me=`echo "$0" |sed 's,.*[\\/],,'`
+
+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
+
+as_executable_p="test -f"
+
+# Support unset when possible.
+if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+# NLS nuisances.
+$as_unset LANG || test "${LANG+set}" != set || { LANG=C; export LANG; }
+$as_unset LC_ALL || test "${LC_ALL+set}" != set || { LC_ALL=C; export LC_ALL; }
+$as_unset LC_TIME || test "${LC_TIME+set}" != set || { LC_TIME=C; export LC_TIME; }
+$as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set || { LC_CTYPE=C; export LC_CTYPE; }
+$as_unset LANGUAGE || test "${LANGUAGE+set}" != set || { LANGUAGE=C; export LANGUAGE; }
+$as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set || { LC_COLLATE=C; export LC_COLLATE; }
+$as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set || { LC_NUMERIC=C; export LC_NUMERIC; }
+$as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set || { LC_MESSAGES=C; export LC_MESSAGES; }
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=:; export 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
+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}
+
+# Avoid depending upon Character Ranges.
+ac_cr_az='abcdefghijklmnopqrstuvwxyz'
+ac_cr_AZ='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ac_cr_09='0123456789'
+ac_cr_alnum=$ac_cr_az$ac_cr_AZ$ac_cr_09
+
+# Sed expression to map a string onto a valid sh and CPP variable names.
+ac_tr_sh="sed y%*+%pp%;s%[^_$ac_cr_alnum]%_%g"
+ac_tr_cpp="sed y%*$ac_cr_az%P$ac_cr_AZ%;s%[^_$ac_cr_alnum]%_%g"
+
+ac_unique_file="ptmxmain.cpp"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#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>
+#else
+# if HAVE_STRINGS_H
+#  include <strings.h>
+# endif
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+# 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'
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+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" : ".*[^-_$ac_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" : ".*[^-_$ac_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)
+    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" : ".*[^-_$ac_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" : ".*[^-_$ac_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" : ".*[^_$ac_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" : ".*[^-._$ac_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 bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+              localstatedir libdir includedir oldincludedir infodir mandir \
+              exec_prefix prefix
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* ) ;;
+    NONE ) ;;
+    *)  { echo "$as_me: error: expected an absolute path 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.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: should be removed in autoconf 3.0.
+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_prog=$0
+  ac_confdir=`echo "$ac_prog" | sed 's%[\\/][^\\/][^\\/]*$%%'`
+  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+  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 in $ac_confdir or .." >&2
+   { (exit 1); exit 1; }; }
+  else
+    { echo "$as_me: error: cannot find sources in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+  fi
+fi
+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 <<EOF
+\`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 \`..']
+
+EOF
+
+  cat <<EOF
+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]
+EOF
+
+  cat <<\EOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+EOF
+fi
+
+if test -n "$ac_init_help"; then
+
+  cat <<\EOF
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --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.
+
+EOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  ac_popdir=`pwd`
+  for ac_subdir in : $ac_subdirs_all; do test "x$ac_subdir" = x: && continue
+    cd $ac_subdir
+    # A "../" for each directory in /$ac_subdir.
+    ac_dots=`echo $ac_subdir |
+             sed 's,^\./,,;s,[^/]$,&/,;s,[^/]*/,../,g'`
+
+    case $srcdir in
+    .) # No --srcdir option.  We are building in place.
+      ac_sub_srcdir=$srcdir ;;
+    [\\/]* | ?:[\\/]* ) # Absolute path.
+      ac_sub_srcdir=$srcdir/$ac_subdir ;;
+    *) # Relative path.
+      ac_sub_srcdir=$ac_dots$srcdir/$ac_subdir ;;
+    esac
+
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_sub_srcdir/configure.gnu; then
+      echo
+      $SHELL $ac_sub_srcdir/configure.gnu  --help=recursive
+    elif test -f $ac_sub_srcdir/configure; then
+      echo
+      $SHELL $ac_sub_srcdir/configure  --help=recursive
+    elif test -f $ac_sub_srcdir/configure.ac ||
+           test -f $ac_sub_srcdir/configure.in; then
+      echo
+      $ac_configure --help
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_subdir" >&2
+    fi
+    cd $ac_popdir
+  done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+  cat <<\EOF
+
+Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+EOF
+  exit 0
+fi
+exec 5>config.log
+cat >&5 <<EOF
+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.50.  Invocation command line was
+
+  $ $0 $@
+
+EOF
+{
+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`
+
+PATH = $PATH
+
+_ASUNAME
+} >&5
+
+cat >&5 <<EOF
+## ------------ ##
+## Core tests.  ##
+## ------------ ##
+
+EOF
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell meta-characters.
+ac_configure_args=
+ac_sep=
+for ac_arg
+do
+  case $ac_arg in
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c) ;;
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+  *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+    ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"`
+    ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+    ac_sep=" " ;;
+  *) ac_configure_args="$ac_configure_args$ac_sep$ac_arg"
+     ac_sep=" " ;;
+  esac
+  # Get rid of the leading space.
+done
+
+# 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.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  echo >&5
+  echo "## ----------------- ##" >&5
+  echo "## Cache variables.  ##" >&5
+  echo "## ----------------- ##" >&5
+  echo >&5
+  # 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/^\\([_$ac_cr_alnum]*_cv_[_$ac_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+      ;;
+    *)
+      sed -n \
+        "s/^\\([_$ac_cr_alnum]*_cv_[_$ac_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} >&5
+  sed "/^$/d" confdefs.h >conftest.log
+  if test -s conftest.log; then
+    echo >&5
+    echo "## ------------ ##" >&5
+    echo "## confdefs.h.  ##" >&5
+    echo "## ------------ ##" >&5
+    echo >&5
+    cat conftest.log >&5
+  fi
+  (echo; echo) >&5
+  test "$ac_signal" != 0 &&
+    echo "$as_me: caught signal $ac_signal" >&5
+  echo "$as_me: exit $exit_status" >&5
+  rm -rf conftest* confdefs* core core.* *.core conf$$* $ac_clean_files &&
+    exit $exit_status
+     ' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_status=$?; ac_signal='$ac_signal'; { (exit $ac_status); exit $ac_status; }' $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
+
+# 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:858: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    cat "$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:869: 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:877: 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_suggest_removing_cache=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:893: WARNING: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: WARNING: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_suggest_removing_cache=: ;;
+    ,set)
+      { echo "$as_me:897: WARNING: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: WARNING: \`$ac_var' was not set in the previous run" >&2;}
+      ac_suggest_removing_cache=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+        { echo "$as_me:903: WARNING: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: WARNING: \`$ac_var' has changed since the previous run:" >&2;}
+        { echo "$as_me:905: WARNING:   former value:  $ac_old_val" >&5
+echo "$as_me: WARNING:   former value:  $ac_old_val" >&2;}
+        { echo "$as_me:907: WARNING:   current value: $ac_new_val" >&5
+echo "$as_me: WARNING:   current value: $ac_new_val" >&2;}
+        ac_suggest_removing_cache=:
+      fi;;
+  esac
+done
+if $ac_suggest_removing_cache; then
+  { echo "$as_me:914: WARNING: changes in the environment can compromise the build" >&5
+echo "$as_me: WARNING: changes in the environment can compromise the build" >&2;}
+  { echo "$as_me:916: WARNING: consider removing $cache_file and starting over" >&5
+echo "$as_me: WARNING: consider removing $cache_file and starting over" >&2;}
+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
+
+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
+echo "#! $SHELL" >conftest.sh
+echo  "exit 0"   >>conftest.sh
+chmod +x conftest.sh
+if { (echo "$as_me:935: PATH=\".;.\"; conftest.sh") >&5
+  (PATH=".;."; conftest.sh) 2>&5
+  ac_status=$?
+  echo "$as_me:938: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  ac_path_separator=';'
+else
+  ac_path_separator=:
+fi
+PATH_SEPARATOR="$ac_path_separator"
+rm -f conftest.sh
+
+ac_config_headers="$ac_config_headers config.h"
+
+if test "$program_transform_name" = s,x,x,; then
+  program_transform_name=
+else
+  # Double any \ or $.  echo might interpret backslashes.
+  cat <<\EOF >conftest.sed
+s,\\,\\\\,g; s,\$,$$,g
+EOF
+  program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+  rm -f conftest.sed
+fi
+test "$program_prefix" != NONE &&
+  program_transform_name="s,^,${program_prefix},;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s,\$\$,${program_suffix},;$program_transform_name"
+
+# sed with no file args requires a program.
+test -z "$program_transform_name" && program_transform_name="s,x,x,"
+
+PACKAGE=gsdl
+VERSION=2.38
+cat >>confdefs.h <<EOF
+#define PACKAGE "$PACKAGE"
+EOF
+
+cat >>confdefs.h <<EOF
+#define VERSION "$VERSION"
+EOF
+
+USE_FASTCGI=0
+if test USE_FASTCGI = 1; then
+cat >>confdefs.h <<\EOF
+#define USE_FASTCGI 1
+EOF
+
+fi
+
+LDFLAGS=
+CFLAGS=-O2
+
+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:997: 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_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+  IFS=$ac_save_IFS
+  test -z "$ac_dir" && ac_dir=.
+  $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_CC="${ac_tool_prefix}gcc"
+echo "$as_me:1012: found $ac_dir/$ac_word" >&5
+break
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:1020: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:1023: 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:1032: 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
+  ac_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+  IFS=$ac_save_IFS
+  test -z "$ac_dir" && ac_dir=.
+  $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_ac_ct_CC="gcc"
+echo "$as_me:1047: found $ac_dir/$ac_word" >&5
+break
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:1055: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:1058: 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:1071: 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_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+  IFS=$ac_save_IFS
+  test -z "$ac_dir" && ac_dir=.
+  $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_CC="${ac_tool_prefix}cc"
+echo "$as_me:1086: found $ac_dir/$ac_word" >&5
+break
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:1094: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:1097: 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:1106: 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
+  ac_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+  IFS=$ac_save_IFS
+  test -z "$ac_dir" && ac_dir=.
+  $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_ac_ct_CC="cc"
+echo "$as_me:1121: found $ac_dir/$ac_word" >&5
+break
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:1129: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:1132: 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:1145: 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
+  ac_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+  IFS=$ac_save_IFS
+  test -z "$ac_dir" && ac_dir=.
+  $as_executable_p "$ac_dir/$ac_word" || continue
+if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+  ac_prog_rejected=yes
+  continue
+fi
+ac_cv_prog_CC="cc"
+echo "$as_me:1165: found $ac_dir/$ac_word" >&5
+break
+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
+    set dummy "$ac_dir/$ac_word" ${1+"$@"}
+    shift
+    ac_cv_prog_CC="$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:1187: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:1190: 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:1201: 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_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+  IFS=$ac_save_IFS
+  test -z "$ac_dir" && ac_dir=.
+  $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+echo "$as_me:1216: found $ac_dir/$ac_word" >&5
+break
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:1224: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:1227: 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:1240: 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
+  ac_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+  IFS=$ac_save_IFS
+  test -z "$ac_dir" && ac_dir=.
+  $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_ac_ct_CC="$ac_prog"
+echo "$as_me:1255: found $ac_dir/$ac_word" >&5
+break
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:1263: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:1266: 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:1278: error: no acceptable cc found in \$PATH" >&5
+echo "$as_me: error: no acceptable cc found in \$PATH" >&2;}
+   { (exit 1); exit 1; }; }
+
+cat >conftest.$ac_ext <<_ACEOF
+#line 1283 "configure"
+#include "confdefs.h"
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compiler, and finding out an intuition
+# of exeext.
+echo "$as_me:1299: checking for C compiler default output" >&5
+echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:1302: \"$ac_link_default\"") >&5
+  (eval $ac_link_default) 2>&5
+  ac_status=$?
+  echo "$as_me:1305: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in `ls a.exe conftest.exe a.* conftest conftest.* 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb ) ;;
+    a.out ) # We found the default executable, but exeext='' is most
+            # certainly right.
+            break;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+          export ac_cv_exeext
+          break;;
+    * ) break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+{ { echo "$as_me:1322: error: C compiler cannot create executables" >&5
+echo "$as_me: error: C compiler cannot create executables" >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:1328: 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:1333: 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:1339: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:1342: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { echo "$as_me:1349: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+echo "$as_me:1357: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext
+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:1364: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:1366: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:1369: checking for executable suffix" >&5
+echo $ECHO_N "checking for executable suffix... $ECHO_C" >&6
+if { (eval echo "$as_me:1371: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:1374: \$? = $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 `(ls conftest.exe; ls conftest; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+          export ac_cv_exeext
+          break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:1390: error: cannot compute EXEEXT: cannot compile and link" >&5
+echo "$as_me: error: cannot compute EXEEXT: cannot compile and link" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:1396: 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:1402: checking for object suffix" >&5
+echo $ECHO_N "checking for object suffix... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 1408 "configure"
+#include "confdefs.h"
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:1420: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:1423: \$? = $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 ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+{ { echo "$as_me:1435: error: cannot compute OBJEXT: cannot compile" >&5
+echo "$as_me: error: cannot compute OBJEXT: cannot compile" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:1442: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:1446: 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
+#line 1452 "configure"
+#include "confdefs.h"
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:1467: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:1470: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:1473: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:1476: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_compiler_gnu=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:1488: 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:1494: 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
+#line 1500 "configure"
+#include "confdefs.h"
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:1512: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:1515: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:1518: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:1521: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:1531: 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
+# 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:1558: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:1561: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:1564: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:1567: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  for ac_declaration in \
+   ''\
+   '#include <stdlib.h>' \
+   '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
+#line 1579 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:1592: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:1595: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:1598: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:1601: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+continue
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+#line 1611 "configure"
+#include "confdefs.h"
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:1623: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:1626: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:1629: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:1632: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+done
+echo '#ifdef __cplusplus' >>confdefs.h
+echo $ac_declaration      >>confdefs.h
+echo '#endif'             >>confdefs.h
+
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f 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 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:1666: 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
+  ac_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+  IFS=$ac_save_IFS
+  test -z "$ac_dir" && ac_dir=.
+  $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+echo "$as_me:1681: found $ac_dir/$ac_word" >&5
+break
+done
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  echo "$as_me:1689: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6
+else
+  echo "$as_me:1692: 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 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:1705: 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
+  ac_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+  IFS=$ac_save_IFS
+  test -z "$ac_dir" && ac_dir=.
+  $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_ac_ct_CXX="$ac_prog"
+echo "$as_me:1720: found $ac_dir/$ac_word" >&5
+break
+done
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  echo "$as_me:1728: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6
+else
+  echo "$as_me:1731: 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
+
+echo "$as_me:1742: 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
+#line 1748 "configure"
+#include "confdefs.h"
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:1763: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:1766: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:1769: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:1772: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_compiler_gnu=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:1784: 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:1790: 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
+#line 1796 "configure"
+#include "confdefs.h"
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:1808: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:1811: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:1814: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:1817: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cxx_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_prog_cxx_g=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:1827: 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 \
+   ''\
+   '#include <stdlib.h>' \
+   '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
+#line 1854 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:1867: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:1870: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:1873: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:1876: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+continue
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+#line 1886 "configure"
+#include "confdefs.h"
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:1898: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:1901: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:1904: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:1907: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+done
+echo '#ifdef __cplusplus' >>confdefs.h
+echo $ac_declaration      >>confdefs.h
+echo '#endif'             >>confdefs.h
+
+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 mawk gawk 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:1930: 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
+  ac_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+  IFS=$ac_save_IFS
+  test -z "$ac_dir" && ac_dir=.
+  $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_AWK="$ac_prog"
+echo "$as_me:1945: found $ac_dir/$ac_word" >&5
+break
+done
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  echo "$as_me:1953: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6
+else
+  echo "$as_me:1956: 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:1967: 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
+  ac_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+  IFS=$ac_save_IFS
+  test -z "$ac_dir" && ac_dir=.
+  $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_YACC="$ac_prog"
+echo "$as_me:1982: found $ac_dir/$ac_word" >&5
+break
+done
+
+fi
+fi
+YACC=$ac_cv_prog_YACC
+if test -n "$YACC"; then
+  echo "$as_me:1990: result: $YACC" >&5
+echo "${ECHO_T}$YACC" >&6
+else
+  echo "$as_me:1993: 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:2018: 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"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:2038: 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
+    ac_save_IFS=$IFS; IFS=$ac_path_separator
+  for ac_dir in $PATH; do
+    IFS=$ac_save_IFS
+    # Account for people who put trailing slashes in PATH elements.
+    case $ac_dir/ in
+    / | ./ | .// | /cC/* \
+    | /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* \
+    | /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
+        if $as_executable_p "$ac_dir/$ac_prog"; then
+	  if test $ac_prog = install &&
+            grep dspmsg "$ac_dir/$ac_prog" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$ac_dir/$ac_prog" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    ac_cv_path_install="$ac_dir/$ac_prog -c"
+	    break 2
+	  fi
+	fi
+      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:2087: 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:2098: 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:2102: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+  echo "$as_me:2105: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6
+fi
+
+echo "$as_me:2109: 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 <<\EOF
+all:
+	@echo 'ac_maketemp="${MAKE}"'
+EOF
+# 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:2129: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  SET_MAKE=
+else
+  echo "$as_me:2133: 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:2141: 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
+  ac_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+  IFS=$ac_save_IFS
+  test -z "$ac_dir" && ac_dir=.
+  $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+echo "$as_me:2156: found $ac_dir/$ac_word" >&5
+break
+done
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  echo "$as_me:2164: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
+else
+  echo "$as_me:2167: 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:2176: 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
+  ac_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+  IFS=$ac_save_IFS
+  test -z "$ac_dir" && ac_dir=.
+  $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_ac_ct_RANLIB="ranlib"
+echo "$as_me:2191: found $ac_dir/$ac_word" >&5
+break
+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:2200: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+  echo "$as_me:2203: 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:2217: 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
+      # break 2 since there is a loop in there.
+      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.
+  # 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
+#line 2239 "configure"
+#include "confdefs.h"
+#include <assert.h>
+                     Syntax error
+_ACEOF
+if { (eval echo "$as_me:2244: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:2250: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_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
+  cat 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
+#line 2273 "configure"
+#include "confdefs.h"
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:2277: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:2283: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_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
+  cat 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 2
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:2320: 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.
+  # 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
+#line 2330 "configure"
+#include "confdefs.h"
+#include <assert.h>
+                     Syntax error
+_ACEOF
+if { (eval echo "$as_me:2335: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:2341: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_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
+  cat 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
+#line 2364 "configure"
+#include "confdefs.h"
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:2368: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:2374: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_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
+  cat 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:2402: error: C preprocessor \"$CPP\" fails sanity check" >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check" >&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:2413: checking for AIX" >&5
+echo $ECHO_N "checking for AIX... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line 2416 "configure"
+#include "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:2425: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+cat >>confdefs.h <<\EOF
+#define _ALL_SOURCE 1
+EOF
+
+else
+  echo "$as_me:2432: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest*
+
+echo "$as_me:2437: checking for POSIXized ISC" >&5
+echo $ECHO_N "checking for POSIXized ISC... $ECHO_C" >&6
+if test -d /etc/conf/kconfig.d &&
+   grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
+then
+  echo "$as_me:2442: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  ISC=yes # If later tests want to check for ISC.
+
+cat >>confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+  if test "$GCC" = yes; then
+    CC="$CC -posix"
+  else
+    CC="$CC -Xp"
+  fi
+else
+  echo "$as_me:2456: result: no" >&5
+echo "${ECHO_T}no" >&6
+  ISC=
+fi
+
+echo "$as_me:2461: 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
+  cat >conftest.$ac_ext <<_ACEOF
+#line 2467 "configure"
+#include "confdefs.h"
+#include <minix/config.h>
+_ACEOF
+if { (eval echo "$as_me:2471: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:2477: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_cv_header_minix_config_h=yes
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_header_minix_config_h=no
+fi
+rm -f conftest.err conftest.$ac_ext
+fi
+echo "$as_me:2496: result: $ac_cv_header_minix_config_h" >&5
+echo "${ECHO_T}$ac_cv_header_minix_config_h" >&6
+if test $ac_cv_header_minix_config_h = yes; then
+  MINIX=yes
+else
+  MINIX=
+fi
+
+if test "$MINIX" = yes; then
+
+cat >>confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+cat >>confdefs.h <<\EOF
+#define _POSIX_1_SOURCE 2
+EOF
+
+cat >>confdefs.h <<\EOF
+#define _MINIX 1
+EOF
+
+fi
+
+echo "$as_me:2520: 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
+#line 2537 "configure"
+#include "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:2554: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:2557: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:2560: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:2563: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_stdc="$ac_arg"; break
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+done
+CFLAGS="$ac_save_CFLAGS"
+
+fi
+
+echo "$as_me:2576: 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:2583: 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:2586: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  cat >>confdefs.h <<\EOF
+#define PROTOTYPES 1
+EOF
+
+  U= ANSI2KNR=
+else
+  echo "$as_me:2594: result: no" >&5
+echo "${ECHO_T}no" >&6
+  U=_ ANSI2KNR=ansi2knr
+fi
+
+echo "$as_me:2599: 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
+#line 2607 "configure"
+#include "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;
+}
+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:2656: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:2659: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:2662: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:2665: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f 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:2682: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+  *)
+    echo "$as_me:2685: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+    CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+echo "$as_me:2690: 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
+#line 2696 "configure"
+#include "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:2754: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:2757: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:2760: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:2763: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_const=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_c_const=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:2773: 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 <<\EOF
+#define const
+EOF
+
+fi
+
+echo "$as_me:2783: 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
+#line 2789 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+_ACEOF
+if { (eval echo "$as_me:2797: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:2803: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_header_stdc=no
+fi
+rm -f conftest.err 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
+#line 2825 "configure"
+#include "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
+#line 2843 "configure"
+#include "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
+#line 2864 "configure"
+#include "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:2890: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:2893: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:2895: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:2898: \$? = $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
+cat conftest.$ac_ext >&5
+ac_cv_header_stdc=no
+fi
+rm -f core core.* *.core conftest$ac_exeext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:2911: 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 <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+for ac_header in stdlib.h string.h memory.h strings.h inttypes.h unistd.h
+do
+ac_ac_Header=`echo "ac_cv_header_$ac_header" | $ac_tr_sh`
+echo "$as_me:2924: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$ac_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 2930 "configure"
+#include "confdefs.h"
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:2934: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:2940: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  eval "$ac_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  eval "$ac_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_ext
+fi
+echo "$as_me:2959: result: `eval echo '${'$ac_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$ac_ac_Header'}'`" >&6
+if test `eval echo '${'$ac_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<EOF
+#define `echo "HAVE_$ac_header" | $ac_tr_cpp` 1
+EOF
+
+fi
+done
+
+echo "$as_me:2969: 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
+#line 2975 "configure"
+#include "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:2990: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:2993: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:2996: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:2999: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_off_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_type_off_t=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:3009: 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 <<EOF
+#define off_t long
+EOF
+
+fi
+
+echo "$as_me:3021: 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
+#line 3027 "configure"
+#include "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:3042: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:3045: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:3048: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:3051: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_size_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_type_size_t=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:3061: 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 <<EOF
+#define size_t unsigned
+EOF
+
+fi
+
+echo "$as_me:3073: 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
+#line 3079 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+struct tm *tp;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:3094: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:3097: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:3100: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:3103: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_header_time=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_header_time=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:3113: 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 <<\EOF
+#define TIME_WITH_SYS_TIME 1
+EOF
+
+fi
+
+echo "$as_me:3123: 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
+#line 3129 "configure"
+#include "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:3143: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:3146: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:3149: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:3152: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_struct_tm=time.h
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_struct_tm=sys/time.h
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:3162: 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 <<\EOF
+#define TM_IN_SYS_TIME 1
+EOF
+
+fi
+
+if test "$ac_cv_prog_cc_stdc" = '-Xc'; then
+cat >conftest.$ac_ext <<_ACEOF
+#line 3174 "configure"
+#include "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:3187: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:3190: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:3193: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:3196: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+CC="`echo $CC | sed 's/-Xc/-Xa/'`"    ac_cv_prog_cc_stdc='-Xa'
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+
+echo "$as_me:3207: 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
+#line 3215 "configure"
+#include "confdefs.h"
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:3227: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:3230: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:3233: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:3236: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_g_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_g_main=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:3247: 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 <<EOF
+#define HAVE_LIBG 1
+EOF
+
+  LIBS="-lg $LIBS"
+
+fi
+
+echo "$as_me:3258: checking for main in -lgdbm" >&5
+echo $ECHO_N "checking for main in -lgdbm... $ECHO_C" >&6
+if test "${ac_cv_lib_gdbm_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgdbm  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line 3266 "configure"
+#include "confdefs.h"
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:3278: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:3281: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:3284: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:3287: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_gdbm_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_gdbm_main=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:3298: result: $ac_cv_lib_gdbm_main" >&5
+echo "${ECHO_T}$ac_cv_lib_gdbm_main" >&6
+if test $ac_cv_lib_gdbm_main = yes; then
+  cat >>confdefs.h <<EOF
+#define HAVE_LIBGDBM 1
+EOF
+
+  LIBS="-lgdbm $LIBS"
+
+fi
+
+echo "$as_me:3309: 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
+#line 3317 "configure"
+#include "confdefs.h"
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:3329: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:3332: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:3335: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:3338: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_m_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_m_main=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:3349: 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 <<EOF
+#define HAVE_LIBM 1
+EOF
+
+  LIBS="-lm $LIBS"
+
+fi
+
+echo "$as_me:3360: checking for main in -lstdc++" >&5
+echo $ECHO_N "checking for main in -lstdc++... $ECHO_C" >&6
+if test "${ac_cv_lib_stdcpp_main+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lstdc++  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line 3368 "configure"
+#include "confdefs.h"
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:3380: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:3383: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:3386: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:3389: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_stdcpp_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_stdcpp_main=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:3400: result: $ac_cv_lib_stdcpp_main" >&5
+echo "${ECHO_T}$ac_cv_lib_stdcpp_main" >&6
+if test $ac_cv_lib_stdcpp_main = yes; then
+  cat >>confdefs.h <<EOF
+#define HAVE_LIBSTDC__ 1
+EOF
+
+  LIBS="-lstdc++ $LIBS"
+
+fi
+
+echo "$as_me:3411: 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
+#line 3419 "configure"
+#include "confdefs.h"
+
+int
+main ()
+{
+main ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:3431: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:3434: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:3437: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:3440: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_crypt_main=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_crypt_main=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:3451: 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 <<EOF
+#define HAVE_LIBCRYPT 1
+EOF
+
+  LIBS="-lcrypt $LIBS"
+
+fi
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
+  ac_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $ac_tr_sh`
+echo "$as_me:3465: checking for $ac_hdr that defines DIR" >&5
+echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6
+if eval "test \"\${$ac_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 3471 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <$ac_hdr>
+
+int
+main ()
+{
+DIR *dirp = 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:3485: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:3488: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:3491: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:3494: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$ac_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$ac_ac_Header=no"
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:3504: result: `eval echo '${'$ac_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$ac_ac_Header'}'`" >&6
+if test `eval echo '${'$ac_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<EOF
+#define `echo "HAVE_$ac_hdr" | $ac_tr_cpp` 1
+EOF
+
+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:3517: checking for opendir in -ldir" >&5
+echo $ECHO_N "checking for opendir in -ldir... $ECHO_C" >&6
+if test "${ac_cv_lib_dir_opendir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldir  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line 3525 "configure"
+#include "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:3544: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:3547: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:3550: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:3553: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_dir_opendir=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_dir_opendir=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:3564: result: $ac_cv_lib_dir_opendir" >&5
+echo "${ECHO_T}$ac_cv_lib_dir_opendir" >&6
+if test $ac_cv_lib_dir_opendir = yes; then
+  LIBS="$LIBS -ldir"
+fi
+
+else
+  echo "$as_me:3571: checking for opendir in -lx" >&5
+echo $ECHO_N "checking for opendir in -lx... $ECHO_C" >&6
+if test "${ac_cv_lib_x_opendir+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lx  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line 3579 "configure"
+#include "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:3598: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:3601: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:3604: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:3607: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_x_opendir=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_x_opendir=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:3618: result: $ac_cv_lib_x_opendir" >&5
+echo "${ECHO_T}$ac_cv_lib_x_opendir" >&6
+if test $ac_cv_lib_x_opendir = yes; then
+  LIBS="$LIBS -lx"
+fi
+
+fi
+
+echo "$as_me:3626: 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
+#line 3632 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+_ACEOF
+if { (eval echo "$as_me:3640: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:3646: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_header_stdc=no
+fi
+rm -f conftest.err 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
+#line 3668 "configure"
+#include "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
+#line 3686 "configure"
+#include "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
+#line 3707 "configure"
+#include "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:3733: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:3736: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:3738: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:3741: \$? = $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
+cat conftest.$ac_ext >&5
+ac_cv_header_stdc=no
+fi
+rm -f core core.* *.core conftest$ac_exeext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:3754: 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 <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+for ac_header in fcntl.h limits.h sys/time.h unistd.h crypt.h string.h memory.h sys/procfs.h
+do
+ac_ac_Header=`echo "ac_cv_header_$ac_header" | $ac_tr_sh`
+echo "$as_me:3767: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$ac_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 3773 "configure"
+#include "confdefs.h"
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:3777: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:3783: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  eval "$ac_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  eval "$ac_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_ext
+fi
+echo "$as_me:3802: result: `eval echo '${'$ac_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$ac_ac_Header'}'`" >&6
+if test `eval echo '${'$ac_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<EOF
+#define `echo "HAVE_$ac_header" | $ac_tr_cpp` 1
+EOF
+
+fi
+done
+
+cat >conftest.$ac_ext <<_ACEOF
+#line 3813 "configure"
+#include "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 <<\EOF
+#define HAVE_FREAD_DECL 1
+EOF
+
+fi
+rm -f conftest*
+
+cat >conftest.$ac_ext <<_ACEOF
+#line 3828 "configure"
+#include "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 <<\EOF
+#define HAVE_FGETC_DECL 1
+EOF
+
+fi
+rm -f conftest*
+
+cat >conftest.$ac_ext <<_ACEOF
+#line 3843 "configure"
+#include "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 <<\EOF
+#define HAVE_PR_BRKSIZE 1
+EOF
+
+fi
+rm -f conftest*
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments.  Useless!
+echo "$as_me:3859: 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
+#line 3865 "configure"
+#include "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:3877: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:3880: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:3883: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:3886: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_working_alloca_h=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_working_alloca_h=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:3896: 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 <<\EOF
+#define HAVE_ALLOCA_H 1
+EOF
+
+fi
+
+echo "$as_me:3906: 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
+#line 3912 "configure"
+#include "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:3944: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:3947: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:3950: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:3953: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_alloca_works=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_func_alloca_works=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:3963: 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 <<\EOF
+#define HAVE_ALLOCA 1
+EOF
+
+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 <<\EOF
+#define C_ALLOCA 1
+EOF
+
+echo "$as_me:3984: 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
+#line 3990 "configure"
+#include "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:4008: 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
+    ac_ac_var=`echo "ac_cv_func_$ac_func" | $ac_tr_sh`
+echo "$as_me:4013: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$ac_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 4019 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.  */
+#include <assert.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 $ac_func ();
+char (*f) ();
+
+int
+main ()
+{
+/* 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
+f = $ac_func;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:4050: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:4053: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:4056: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:4059: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$ac_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$ac_ac_var=no"
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:4069: result: `eval echo '${'$ac_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$ac_ac_var'}'`" >&6
+if test `eval echo '${'$ac_ac_var'}'` = yes; then
+
+cat >>confdefs.h <<EOF
+#define CRAY_STACKSEG_END $ac_func
+EOF
+
+    break
+fi
+
+  done
+fi
+
+echo "$as_me:4083: 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
+#line 4092 "configure"
+#include "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:4115: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:4118: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:4120: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:4123: \$? = $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
+cat conftest.$ac_ext >&5
+ac_cv_c_stack_direction=-1
+fi
+rm -f core core.* *.core conftest$ac_exeext conftest.$ac_ext
+fi
+fi
+echo "$as_me:4135: result: $ac_cv_c_stack_direction" >&5
+echo "${ECHO_T}$ac_cv_c_stack_direction" >&6
+
+cat >>confdefs.h <<EOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+EOF
+
+fi
+
+if test $ac_cv_c_compiler_gnu = yes; then
+    echo "$as_me:4145: 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
+#line 4152 "configure"
+#include "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
+#line 4167 "configure"
+#include "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:4180: 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:4187: 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
+#line 4193 "configure"
+#include "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:4215: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:4218: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:4221: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:4224: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_signal=void
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_type_signal=int
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:4234: result: $ac_cv_type_signal" >&5
+echo "${ECHO_T}$ac_cv_type_signal" >&6
+
+cat >>confdefs.h <<EOF
+#define RETSIGTYPE $ac_cv_type_signal
+EOF
+
+for ac_func in vprintf
+do
+ac_ac_var=`echo "ac_cv_func_$ac_func" | $ac_tr_sh`
+echo "$as_me:4244: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$ac_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 4250 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.  */
+#include <assert.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 $ac_func ();
+char (*f) ();
+
+int
+main ()
+{
+/* 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
+f = $ac_func;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:4281: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:4284: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:4287: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:4290: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$ac_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$ac_ac_var=no"
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:4300: result: `eval echo '${'$ac_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$ac_ac_var'}'`" >&6
+if test `eval echo '${'$ac_ac_var'}'` = yes; then
+  cat >>confdefs.h <<EOF
+#define `echo "HAVE_$ac_func" | $ac_tr_cpp` 1
+EOF
+
+echo "$as_me:4307: 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
+#line 4313 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char _doprnt (); below.  */
+#include <assert.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 _doprnt ();
+char (*f) ();
+
+int
+main ()
+{
+/* 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
+f = _doprnt;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:4344: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:4347: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:4350: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:4353: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func__doprnt=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_func__doprnt=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:4363: 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 <<\EOF
+#define HAVE_DOPRNT 1
+EOF
+
+fi
+
+fi
+done
+
+for ac_func in ftime select strftime strtol getrusage times mallinfo setbuffer getpagesize strerror
+do
+ac_ac_var=`echo "ac_cv_func_$ac_func" | $ac_tr_sh`
+echo "$as_me:4379: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$ac_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 4385 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.  */
+#include <assert.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 $ac_func ();
+char (*f) ();
+
+int
+main ()
+{
+/* 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
+f = $ac_func;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:4416: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:4419: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:4422: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:4425: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$ac_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$ac_ac_var=no"
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:4435: result: `eval echo '${'$ac_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$ac_ac_var'}'`" >&6
+if test `eval echo '${'$ac_ac_var'}'` = yes; then
+  cat >>confdefs.h <<EOF
+#define `echo "HAVE_$ac_func" | $ac_tr_cpp` 1
+EOF
+
+fi
+done
+
+for ac_func in ftruncate strstr strcasecmp
+do
+ac_ac_var=`echo "ac_cv_func_$ac_func" | $ac_tr_sh`
+echo "$as_me:4448: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$ac_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 4454 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.  */
+#include <assert.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 $ac_func ();
+char (*f) ();
+
+int
+main ()
+{
+/* 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
+f = $ac_func;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:4485: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:4488: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:4491: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:4494: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$ac_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$ac_ac_var=no"
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:4504: result: `eval echo '${'$ac_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$ac_ac_var'}'`" >&6
+if test `eval echo '${'$ac_ac_var'}'` = yes; then
+  cat >>confdefs.h <<EOF
+#define `echo "HAVE_$ac_func" | $ac_tr_cpp` 1
+EOF
+
+else
+  LIBOBJS="$LIBOBJS $ac_func.$ac_objext"
+fi
+done
+
+# *** Custom checking (based on GNU tar configure.in) ***
+# ---------------------------------------------------------------------------
+echo "$as_me:4518: 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:4521: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  LIBOBJS="$LIBOBJS gmalloc.o"
+  cat >>confdefs.h <<\EOF
+#define HAVE_VALLOC 1
+EOF
+
+else
+  echo "$as_me:4529: result: no" >&5
+echo "${ECHO_T}no" >&6
+
+for ac_func in valloc
+do
+ac_ac_var=`echo "ac_cv_func_$ac_func" | $ac_tr_sh`
+echo "$as_me:4535: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$ac_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 4541 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.  */
+#include <assert.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 $ac_func ();
+char (*f) ();
+
+int
+main ()
+{
+/* 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
+f = $ac_func;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:4572: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:4575: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:4578: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:4581: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$ac_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$ac_ac_var=no"
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:4591: result: `eval echo '${'$ac_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$ac_ac_var'}'`" >&6
+if test `eval echo '${'$ac_ac_var'}'` = yes; then
+  cat >>confdefs.h <<EOF
+#define `echo "HAVE_$ac_func" | $ac_tr_cpp` 1
+EOF
+
+fi
+done
+
+fi
+
+echo "$as_me:4603: 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:4610: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  cat >>confdefs.h <<\EOF
+#define WITH_DMALLOC 1
+EOF
+
+  LIBS="$LIBS -ldmalloc"
+  LDFLAGS="$LDFLAGS -g"
+else
+  echo "$as_me:4619: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+else
+  echo "$as_me:4623: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi;
+
+echo "$as_me:4627: 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:4635: result: regex" >&5
+echo "${ECHO_T}regex" >&6
+  cat >>confdefs.h <<\EOF
+#define WITH_REGEX 1
+EOF
+
+  LIBOBJS="$LIBOBJS regex.o"
+fi
+fi;
+if test -z "$ac_with_regex"; then
+  echo "$as_me:4645: result: rx" >&5
+echo "${ECHO_T}rx" >&6
+  echo "$as_me:4647: 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
+#line 4653 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char re_rx_search (); below.  */
+#include <assert.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 re_rx_search ();
+char (*f) ();
+
+int
+main ()
+{
+/* 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
+f = re_rx_search;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:4684: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:4687: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:4690: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:4693: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_re_rx_search=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_func_re_rx_search=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:4703: 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
+  LIBOBJS="$LIBOBJS rx.o"
+fi
+
+fi
+
+# ---------------------------------------------------------------------------
+if test "$ac_cv_func_alloca" = 'no'; then
+  LIBOBJS="$LIBOBJS xmalloc.o error.o"
+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:4726: checking \"that the GDBM library is available\"" >&5
+echo $ECHO_N "checking \"that the GDBM library is available\"... $ECHO_C" >&6
+
+cat >conftest.$ac_ext <<_ACEOF
+#line 4730 "configure"
+#include "confdefs.h"
+#include <gdbm.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:4743: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:4746: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:4749: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:4752: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  success=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+success=no
+
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:4762: result: $success" >&5
+echo "${ECHO_T}$success" >&6
+if test $success = "no"; then
+{ { echo "$as_me:4765: error: \"GDBM Library not available - cannot install\"" >&5
+echo "$as_me: error: \"GDBM Library not available - cannot install\"" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+success=no
+echo "$as_me:4771: 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
+#line 4775 "configure"
+#include "confdefs.h"
+#include <vector>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:4788: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:4791: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:4794: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:4797: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  success=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+
+if test $success = "no"; then
+cat >conftest.$ac_ext <<_ACEOF
+#line 4808 "configure"
+#include "confdefs.h"
+#include <vector.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:4821: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:4824: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:4827: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:4830: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  success="yes"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+
+if test $success = "no"; then
+cat >conftest.$ac_ext <<_ACEOF
+#line 4842 "configure"
+#include "confdefs.h"
+#include <ospace\\std\\vector>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:4855: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:4858: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:4861: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:4864: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  success="yes"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+
+if test $success = yes; then
+echo "$as_me:4875: result: \"no\"" >&5
+echo "${ECHO_T}\"no\"" >&6
+else
+echo "$as_me:4878: result: \"yes\"" >&5
+echo "${ECHO_T}\"yes\"" >&6
+{ { echo "$as_me:4880: 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 A-Z a-z`
+
+echo "$as_me:4887: 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:4890: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  LIBOBJS="$LIBOBJS gmalloc.o"
+  cat >>confdefs.h <<\EOF
+#define HAVE_VALLOC 1
+EOF
+
+else
+  echo "$as_me:4898: result: no" >&5
+echo "${ECHO_T}no" >&6
+
+for ac_func in valloc
+do
+ac_ac_var=`echo "ac_cv_func_$ac_func" | $ac_tr_sh`
+echo "$as_me:4904: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$ac_ac_var+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line 4910 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.  */
+#include <assert.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 $ac_func ();
+char (*f) ();
+
+int
+main ()
+{
+/* 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
+f = $ac_func;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:4941: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:4944: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:4947: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:4950: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$ac_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$ac_ac_var=no"
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:4960: result: `eval echo '${'$ac_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$ac_ac_var'}'`" >&6
+if test `eval echo '${'$ac_ac_var'}'` = yes; then
+  cat >>confdefs.h <<EOF
+#define `echo "HAVE_$ac_func" | $ac_tr_cpp` 1
+EOF
+
+fi
+done
+
+fi
+
+echo "$as_me:4972: 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:4979: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  cat >>confdefs.h <<\EOF
+#define WITH_DMALLOC 1
+EOF
+
+  LIBS="$LIBS -ldmalloc"
+  LDFLAGS="$LDFLAGS -g"
+else
+  echo "$as_me:4988: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+else
+  echo "$as_me:4992: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi;
+
+echo "$as_me:4996: 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:5004: result: regex" >&5
+echo "${ECHO_T}regex" >&6
+  cat >>confdefs.h <<\EOF
+#define WITH_REGEX 1
+EOF
+
+  LIBOBJS="$LIBOBJS regex.o"
+fi
+fi;
+if test -z "$ac_with_regex"; then
+  echo "$as_me:5014: result: rx" >&5
+echo "${ECHO_T}rx" >&6
+  echo "$as_me:5016: 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
+#line 5022 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char re_rx_search (); below.  */
+#include <assert.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 re_rx_search ();
+char (*f) ();
+
+int
+main ()
+{
+/* 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
+f = re_rx_search;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:5053: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:5056: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:5059: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:5062: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_re_rx_search=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_func_re_rx_search=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:5072: 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
+  LIBOBJS="$LIBOBJS rx.o"
+fi
+
+fi
+
+# ---------------------------------------------------------------------------
+if test "$ac_cv_func_alloca" = 'no'; then
+  LIBOBJS="$LIBOBJS xmalloc.o error.o"
+fi
+
+# ---------------------------------------------------------------------------
+
+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 overriden 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/^\\([_$ac_cr_alnum]*_cv_[_$ac_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+        "s/^\\([_$ac_cr_alnum]*_cv_[_$ac_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 cmp -s $cache_file confcache; 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
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:5169: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated automatically by configure.
+# 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
+SHELL=\${CONFIG_SHELL-$SHELL}
+ac_cs_invocation="\$0 \$@"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+
+# Name of the executable.
+as_me=`echo "$0" |sed 's,.*[\\/],,'`
+
+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
+
+as_executable_p="test -f"
+
+# Support unset when possible.
+if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+# NLS nuisances.
+$as_unset LANG || test "${LANG+set}" != set || { LANG=C; export LANG; }
+$as_unset LC_ALL || test "${LC_ALL+set}" != set || { LC_ALL=C; export LC_ALL; }
+$as_unset LC_TIME || test "${LC_TIME+set}" != set || { LC_TIME=C; export LC_TIME; }
+$as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set || { LC_CTYPE=C; export LC_CTYPE; }
+$as_unset LANGUAGE || test "${LANGUAGE+set}" != set || { LANGUAGE=C; export LANGUAGE; }
+$as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set || { LC_COLLATE=C; export LC_COLLATE; }
+$as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set || { LC_NUMERIC=C; export LC_NUMERIC; }
+$as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set || { LC_MESSAGES=C; export LC_MESSAGES; }
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" 	$as_nl"
+
+# CDPATH.
+$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=:; export CDPATH; }
+
+exec 6>&1
+
+_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 <<\EOF
+
+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
+  -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>."
+EOF
+
+cat >>$CONFIG_STATUS <<EOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.50,
+  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+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"
+EOF
+
+cat >>$CONFIG_STATUS <<\EOF
+# 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[^=]*=\(.*\)'`
+    shift
+    set dummy "$ac_option" "$ac_optarg" ${1+"$@"}
+    shift
+    ;;
+  -*);;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_need_defaults=false;;
+  esac
+
+  case $1 in
+  # Handling of the options.
+EOF
+cat >>$CONFIG_STATUS <<EOF
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    echo "running $SHELL $0 " $ac_configure_args " --no-create --no-recursion"
+    exec $SHELL $0 $ac_configure_args --no-create --no-recursion ;;
+EOF
+cat >>$CONFIG_STATUS <<\EOF
+  --version | --vers* | -V )
+    echo "$ac_cs_version"; exit 0 ;;
+  --he | --h)
+    # Conflict between --help and --header
+    { { echo "$as_me:5342: 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 )
+    shift
+    CONFIG_FILES="$CONFIG_FILES $1"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $1"
+    ac_need_defaults=false;;
+
+  # Handling of arguments.
+  'Makefile' ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+  'config.h' ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+
+  # This is an error.
+  -*) { { echo "$as_me:5365: 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; }; } ;;
+  *) { { echo "$as_me:5370: error: invalid argument: $1" >&5
+echo "$as_me: error: invalid argument: $1" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+  shift
+done
+
+exec 5>>config.log
+cat >&5 << _ACEOF
+
+## ----------------------- ##
+## Running config.status.  ##
+## ----------------------- ##
+
+This file was extended by $as_me 2.50, executed with
+  > $ac_cs_invocation
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+
+_ACEOF
+EOF
+
+cat >>$CONFIG_STATUS <<\EOF
+# 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
+
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit $?); exit $?; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+: ${TMPDIR=/tmp}
+{
+  tmp=`(umask 077 && mktemp -d -q "$TMPDIR/csXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=$TMPDIR/cs$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in $TMPDIR" >&2
+   { (exit 1); exit 1; }
+}
+
+EOF
+
+cat >>$CONFIG_STATUS <<EOF
+
+#
+# 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,@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,@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,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@DEFS@,$DEFS,;t t
+s,@LIBS@,$LIBS,;t t
+s,@PACKAGE@,$PACKAGE,;t t
+s,@VERSION@,$VERSION,;t t
+s,@USE_FASTCGI@,$USE_FASTCGI,;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,@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,@U@,$U,;t t
+s,@ANSI2KNR@,$ANSI2KNR,;t t
+s,@ALLOCA@,$ALLOCA,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@gsdlos@,$gsdlos,;t t
+CEOF
+
+EOF
+
+  cat >>$CONFIG_STATUS <<\EOF
+  # 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"
+
+EOF
+cat >>$CONFIG_STATUS <<\EOF
+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=`$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 test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+    { case "$ac_dir" in
+  [\\/]* | ?:[\\/]* ) as_incr_dir=;;
+  *)                      as_incr_dir=.;;
+esac
+as_dummy="$ac_dir"
+for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do
+  case $as_mkdir_dir in
+    # Skip DOS drivespec
+    ?:) as_incr_dir=$as_mkdir_dir ;;
+    *)
+      as_incr_dir=$as_incr_dir/$as_mkdir_dir
+      test -d "$as_incr_dir" || mkdir "$as_incr_dir"
+    ;;
+  esac
+done; }
+
+    ac_dir_suffix="/`echo $ac_dir|sed 's,^\./,,'`"
+    # A "../" for each directory in $ac_dir_suffix.
+    ac_dots=`echo "$ac_dir_suffix" | sed 's,/[^/]*,../,g'`
+  else
+    ac_dir_suffix= ac_dots=
+  fi
+
+  case $srcdir in
+  .)  ac_srcdir=.
+      if test -z "$ac_dots"; then
+         ac_top_srcdir=.
+      else
+         ac_top_srcdir=`echo $ac_dots | sed 's,/$,,'`
+      fi ;;
+  [\\/]* | ?:[\\/]* )
+      ac_srcdir=$srcdir$ac_dir_suffix;
+      ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_dots$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_dots$srcdir ;;
+  esac
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_dots$INSTALL ;;
+  esac
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:5606: 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 automatically by config.status.  */
+  configure_input="Generated automatically 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:5624: 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:5637: 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; }
+EOF
+cat >>$CONFIG_STATUS <<EOF
+  sed "$ac_vpsub
+$extrasub
+EOF
+cat >>$CONFIG_STATUS <<\EOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;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
+EOF
+cat >>$CONFIG_STATUS <<\EOF
+
+#
+# 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:5698: 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:5709: 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:5722: 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
+
+EOF
+
+# 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 <<\EOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[ 	]*#[ 	]*define[ 	][ 	]*\(\([^ 	(][^ 	(]*\)([^)]*)\)[ 	]*\(.*\)$,${ac_dA}\2${ac_dB}\1${ac_dC}\3${ac_dD},gp
+t end
+s,^[ 	]*#[ 	]*define[ 	][ 	]*\([^ 	][^ 	]*\)[ 	]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+EOF
+# 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 <<\EOF
+s,^[ 	]*#[ 	]*undef[ 	][ 	]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+EOF
+
+# 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 egrep "^[ 	]*#[ 	]*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 # egrep' >>$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 <<\EOF
+  # 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 automatically by config.status.  */
+  if test x"$ac_file" = x-; then
+    echo "/* Generated automatically by configure.  */" >$tmp/config.h
+  else
+    echo "/* $ac_file.  Generated automatically by configure.  */" >$tmp/config.h
+  fi
+  cat $tmp/in >>$tmp/config.h
+  rm -f $tmp/in
+  if test x"$ac_file" != x-; then
+    if cmp -s $ac_file $tmp/config.h 2>/dev/null; then
+      { echo "$as_me:5839: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      ac_dir=`$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 test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+        { case "$ac_dir" in
+  [\\/]* | ?:[\\/]* ) as_incr_dir=;;
+  *)                      as_incr_dir=.;;
+esac
+as_dummy="$ac_dir"
+for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do
+  case $as_mkdir_dir in
+    # Skip DOS drivespec
+    ?:) as_incr_dir=$as_mkdir_dir ;;
+    *)
+      as_incr_dir=$as_incr_dir/$as_mkdir_dir
+      test -d "$as_incr_dir" || mkdir "$as_incr_dir"
+    ;;
+  esac
+done; }
+
+      fi
+      rm -f $ac_file
+      mv $tmp/config.h $ac_file
+    fi
+  else
+    cat $tmp/config.h
+    rm -f $tmp/config.h
+  fi
+done
+EOF
+
+cat >>$CONFIG_STATUS <<\EOF
+
+{ (exit 0); exit 0; }
+EOF
+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=:
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS || 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/start/protemix/src/recpt/configure.in
===================================================================
--- /tags/start/protemix/src/recpt/configure.in	(revision 13666)
+++ /tags/start/protemix/src/recpt/configure.in	(revision 13666)
@@ -0,0 +1,208 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(ptmxmain.cpp)
+AC_CONFIG_HEADER(config.h)
+AC_ARG_PROGRAM
+
+PACKAGE=gsdl
+VERSION=2.38
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE")
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION")
+AC_SUBST(PACKAGE)
+AC_SUBST(VERSION)
+
+USE_FASTCGI=0
+if test USE_FASTCGI = 1; then
+AC_DEFINE(USE_FASTCGI)
+AC_SUBST(USE_FASTCGI)
+fi
+
+dnl Checks for programs.
+LDFLAGS=
+CFLAGS=-O2
+AC_SUBST(CFLAGS)
+
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_AWK
+AC_PROG_YACC
+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 Replace `main' with a function in -lg:
+AC_CHECK_LIB(g, main)
+dnl Replace `main' with a function in -lgdbm:
+AC_CHECK_LIB(gdbm, main)
+dnl Replace `main' with a function in -lm:
+AC_CHECK_LIB(m, main)
+dnl Replace `main' with a function in -lstdc++:
+AC_CHECK_LIB(stdc++, main)
+dnl Replace `main' with a function in -lcrypt:
+AC_CHECK_LIB(crypt, main)
+
+
+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)
+
+
+# *** 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)
+  LIBOBJS="$LIBOBJS gmalloc.o"
+  AC_DEFINE(HAVE_VALLOC)
+else
+  AC_MSG_RESULT(no)
+  AC_CHECK_FUNCS(valloc)
+fi
+
+fp_WITH_DMALLOC
+fp_WITH_REGEX
+
+# ---------------------------------------------------------------------------
+if test "$ac_cv_func_alloca" = 'no'; then
+dnl    support functions for alloca.c
+  LIBOBJS="$LIBOBJS xmalloc.o error.o"
+fi
+
+
+# ---------------------------------------------------------------------------
+
+dnl
+dnl Switch into C++
+dnl
+AC_LANG_CPLUSPLUS
+
+dnl
+dnl Check that the GDBM library is available
+dnl
+AC_MSG_CHECKING("that the GDBM library is available")
+AC_TRY_COMPILE(
+[#include <gdbm.h>
+],
+[],
+success=yes,
+success=no
+)
+AC_MSG_RESULT($success)
+if test $success = "no"; then
+AC_MSG_ERROR("GDBM Library 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 A-Z a-z`
+AC_SUBST(gsdlos)
+
+AC_MSG_CHECKING(for HP-UX needing gmalloc)
+if test "`(uname -s) 2> /dev/null`" = 'HP-UX'; then
+  AC_MSG_RESULT(yes)
+  LIBOBJS="$LIBOBJS gmalloc.o"
+  AC_DEFINE(HAVE_VALLOC)
+else
+  AC_MSG_RESULT(no)
+  AC_CHECK_FUNCS(valloc)
+fi
+
+fp_WITH_DMALLOC
+fp_WITH_REGEX
+
+# ---------------------------------------------------------------------------
+if test "$ac_cv_func_alloca" = 'no'; then
+dnl    support functions for alloca.c
+  LIBOBJS="$LIBOBJS xmalloc.o error.o"
+fi
+
+
+# ---------------------------------------------------------------------------
+
+AC_OUTPUT(Makefile)
+
+
Index: /tags/start/protemix/src/recpt/gsdlsite.cfg
===================================================================
--- /tags/start/protemix/src/recpt/gsdlsite.cfg	(revision 13666)
+++ /tags/start/protemix/src/recpt/gsdlsite.cfg	(revision 13666)
@@ -0,0 +1,28 @@
+# this file should be placed in the same directory as your library
+# executable file. it should be edited to suit your site.
+
+# points to the GSDLHOME directory
+gsdlhome    /usr/local/gsdl
+
+# this is the http address of GSDLHOME
+# if your webservers DocumentRoot is set to $GSDLHOME
+# then httpprefix can remain commented out
+httpprefix  /gsdl
+
+# this is the http address of the directory which
+# contains the images for the interface.
+# if your webservers DocumentRoot is set to $GSDLHOME
+# then httpimg will be /images
+httpimg     /gsdl/images
+
+# should contain the http address of this cgi script. This 
+# is not needed if the http server sets the environment variable 
+# SCRIPT_NAME
+#gwcgi       /cgi-bin/library
+
+# maxrequests is the most requests a fastcgi process
+# will serve before it exits. This can be set to a
+# low figure (like 1) while debugging and then set
+# to a high figure (like 10000) when everything is
+# working well.
+maxrequests 10000
Index: /tags/start/protemix/src/recpt/install-sh
===================================================================
--- /tags/start/protemix/src/recpt/install-sh	(revision 13666)
+++ /tags/start/protemix/src/recpt/install-sh	(revision 13666)
@@ -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/start/protemix/src/recpt/ptmxmain.cpp
===================================================================
--- /tags/start/protemix/src/recpt/ptmxmain.cpp	(revision 13666)
+++ /tags/start/protemix/src/recpt/ptmxmain.cpp	(revision 13666)
@@ -0,0 +1,126 @@
+/**********************************************************************
+ *
+ * ptmxmain.cpp -- 
+ * Copyright (C) 2002  The New Zaland 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.
+ *
+ *********************************************************************/
+
+#include "receptionist.h"
+#include "cgiwrapper.h"
+#include "fileutil.h"
+#include "nullproto.h"
+#include "collectserver.h"
+#include "filter.h"
+#include "browsefilter.h"
+#include "mgqueryfilter.h"
+#include "mgppqueryfilter.h"
+#include "infodbclass.h"
+#include "mggdbmsource.h"
+#include "mgsearch.h"
+#include "mgppsearch.h"
+#include "collectset.h"
+#include <assert.h>
+
+#include "action.h"
+#include "pageaction.h"
+#include "ptmxqueryaction.h"
+#include "documentaction.h"
+#include "extlinkaction.h"
+#include "phindaction.h"
+
+#include "browserclass.h"
+#include "vlistbrowserclass.h"
+#include "hlistbrowserclass.h"
+#include "datelistbrowserclass.h"
+#include "invbrowserclass.h"
+#include "pagedbrowserclass.h"
+#include "htmlbrowserclass.h"
+#include "phindbrowserclass.h"
+
+#include "recptconfig.h"
+
+int main () {
+  receptionist recpt;
+  nullproto    nproto;
+  
+  text_t gsdlhome, httpdomain, httpprefix;
+  // get gsdlhome (if we fail the error will be picked up later -- in
+  // cgiwrapper)
+  site_cfg_read (gsdlhome, httpdomain, httpprefix);
+  collectset *cservers = new collectset();
+  cservers->add_collection ("protemix", &recpt, gsdlhome, gsdlhome);
+
+  // set up the null protocol
+  nproto.set_collectset(cservers);
+
+  // configure the receptionist server list
+  cservers->setReceptionistServers(recpt, gsdlhome);  
+
+  // add the protocol to the receptionist
+  recpt.add_protocol (&nproto);
+
+  // the list of actions. Note: these actions will become invalid
+  // at the end of this function.
+  pageaction apageaction;
+  apageaction.set_receptionist (&recpt);
+  recpt.add_action (&apageaction);
+
+  ptmxqueryaction aqueryaction;
+  aqueryaction.set_receptionist (&recpt);
+  recpt.add_action (&aqueryaction);
+
+  documentaction adocumentaction;
+  adocumentaction.set_receptionist (&recpt);
+  recpt.add_action (&adocumentaction);
+
+  extlinkaction anextlinkaction;
+  recpt.add_action (&anextlinkaction);
+
+  phindaction aphindaction;
+  recpt.add_action(&aphindaction);
+
+  // list of browsers
+  vlistbrowserclass avlistbrowserclass;
+  recpt.add_browser (&avlistbrowserclass);
+  recpt.setdefaultbrowser ("VList");
+
+  hlistbrowserclass ahlistbrowserclass;
+  recpt.add_browser (&ahlistbrowserclass);
+
+  datelistbrowserclass adatelistbrowserclass;
+  recpt.add_browser (&adatelistbrowserclass);
+
+  invbrowserclass ainvbrowserclass;
+  recpt.add_browser (&ainvbrowserclass);
+
+  pagedbrowserclass apagedbrowserclass;
+  recpt.add_browser (&apagedbrowserclass);
+
+  htmlbrowserclass ahtmlbrowserclass;
+  recpt.add_browser (&ahtmlbrowserclass);
+
+  phindbrowserclass aphindbrowserclass;
+  recpt.add_browser (&aphindbrowserclass);
+
+  cgiwrapper (recpt, "protemix");
+  delete cservers;
+  return 0;
+}
Index: /tags/start/protemix/src/recpt/ptmxqueryaction.cpp
===================================================================
--- /tags/start/protemix/src/recpt/ptmxqueryaction.cpp	(revision 13666)
+++ /tags/start/protemix/src/recpt/ptmxqueryaction.cpp	(revision 13666)
@@ -0,0 +1,196 @@
+/**********************************************************************
+ *
+ * ptmxqueryaction.cpp -- 
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Copyright (C) 2002  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.
+ *
+ *
+ *********************************************************************/
+
+#include "ptmxqueryaction.h"
+#include "querytools.h"
+#include "formattools.h"
+#include "htmlutils.h"
+#include "gsdltools.h"
+#include "cgiutils.h"
+
+ptmxqueryaction::ptmxqueryaction () {
+
+  cgiarginfo arg_ainfo;
+  arg_ainfo.shortname = "c1";
+  arg_ainfo.longname = "classification 1";
+  arg_ainfo.multiplechar = true;
+  arg_ainfo.defaultstatus = cgiarginfo::weak;
+  arg_ainfo.argdefault = "";
+  arg_ainfo.savedarginfo = cgiarginfo::must;
+  argsinfo.addarginfo (NULL, arg_ainfo);
+
+  arg_ainfo.shortname = "c2";
+  arg_ainfo.longname = "classification 2";
+  arg_ainfo.multiplechar = true;
+  arg_ainfo.defaultstatus = cgiarginfo::weak;
+  arg_ainfo.argdefault = "";
+  arg_ainfo.savedarginfo = cgiarginfo::must;
+  argsinfo.addarginfo (NULL, arg_ainfo);
+
+  arg_ainfo.shortname = "c3";
+  arg_ainfo.longname = "classification 3";
+  arg_ainfo.multiplechar = true;
+  arg_ainfo.defaultstatus = cgiarginfo::weak;
+  arg_ainfo.argdefault = "";
+  arg_ainfo.savedarginfo = cgiarginfo::must;
+  argsinfo.addarginfo (NULL, arg_ainfo);
+
+}
+
+ptmxqueryaction::~ptmxqueryaction () {
+}
+
+
+bool ptmxqueryaction::search_single_collection (cgiargsclass &args, const text_t &collection,
+						recptprotolistclass *protos, browsermapclass *browsers, 
+						displayclass &disp, outconvertclass &outconvert, 
+						ostream &textout, ostream &logout) {
+
+  recptproto *collectproto = protos->getrecptproto (collection, logout);
+  if (collectproto == NULL) {
+    logout << outconvert << "queryaction::search_single_collection: " << collection
+	   << " collection has a NULL collectproto\n";
+    return false;
+  }
+
+  // queryaction uses "VList" browser to display results,
+  // a queries clasification is "Search"
+  text_t browsertype = "VList";
+  text_t classification = "Search";
+
+  comerror_t err;
+  ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, collection, logout);
+
+  if (cinfo == NULL) {
+    logout << "ERROR (query_action::search_single_collection): get_collectinfo_ptr returned NULL\n";
+    return false;
+  }
+    
+  browserclass *bptr = browsers->getbrowser (browsertype);
+
+  // get the formatstring if there is one 
+  text_t formatstring;
+  if (!get_formatstring (classification, browsertype, 
+			 cinfo->format, formatstring))
+    formatstring = bptr->get_default_formatstring();
+
+  FilterRequest_t request;
+  FilterResponse_t response;
+  bptr->set_filter_options (request, args);
+  bptr->load_metadata_defaults (request.fields);
+
+  format_t *formatlistptr = new format_t();
+  parse_formatstring (formatstring, formatlistptr, request.fields, request.getParents);
+    
+  // do the query
+  request.filterResultOptions = FROID | FRmetadata | FRtermFreq;
+  text_t formattedstring = "";
+
+  logout << "here we go...\n";
+
+  if (args["qt"]=="0") { // normal text search
+    logout << "normal text search ...\n";
+    formattedstring = args["q"];
+    format_querystring (formattedstring, args.getintarg("b"));
+    add_dates(formattedstring, args.getintarg("ds"), args.getintarg("de"),
+	    args.getintarg("dsbc"), args.getintarg("debc"));
+  }
+  else if (args["qt"]=="1" ){ // form search
+
+    logout << "form search ...\n";
+
+    if (args["b"]=="1" && args["fqa"]=="1") { // explicit query
+      formattedstring = args["q"];
+    }
+    else { // form search
+      if (args["b"]=="0") { // regular form
+	parse_reg_query_form(formattedstring, args);
+      }
+      else  { // advanced form
+	parse_adv_query_form(formattedstring, args);
+      }
+      args["q"] = formattedstring;
+      
+      // reset the cgiargfqv macro - need to escape any quotes in it
+      disp.setmacro("cgiargfqv", "query", escape_quotes(args["fqv"]));
+
+      // also reset the _cgiargq_ macro as it has changed now
+      disp.setmacro("cgiargq", "Global", html_safe(args["q"]));
+      
+      // reset the compressed options to include the q arg
+      text_t compressedoptions = recpt->get_compressed_arg(args, logout);
+      if (!compressedoptions.empty()) {
+	disp.setmacro ("compressedoptions", "Global", dm_safe(compressedoptions));
+	// need a decoded version of compressedoptions for use within forms
+	// as browsers encode values from forms before sending to server
+	// (e.g. %25 becomes %2525)
+	decode_cgi_arg (compressedoptions);
+	disp.setmacro ("decodedcompressedoptions", "Global", dm_safe(compressedoptions));
+      }
+    } // form search
+  } // args["qt"]=1
+  else {
+    logout << "ERROR (query_action::search_single_collection): querytype not defined\n";
+    return false;
+  }
+
+  if (!formattedstring.empty()) { // do the query
+    // note! formattedstring is in unicode! mg and mgpp must convert!
+    set_queryfilter_options (request, formattedstring, args);
+    collectproto->filter (collection, request, response, err, logout);
+    if (err != noError) {
+      outconvertclass text_t2ascii;
+      logout << text_t2ascii
+	     << "queryaction::search_single_collections: call to QueryFilter failed "
+	     << "for " << collection << " collection (" << get_comerror_string (err) << ")\n";
+      return false;
+    }
+ 
+    define_query_macros (args, disp, response);
+
+    // save the query if appropriate
+    if (!save_search_history(args, response))
+      logout << "save failed"; 
+  }
+
+  define_history_macros (disp, args, protos, logout);
+  
+  textout << outconvert << disp << "_query:header_\n"
+	  << "_query:content_";
+
+  // output the results
+  bool use_table = is_table_content (formatlistptr);
+  bptr->output_section_group (response, args, collection, 0, formatlistptr, 
+			      use_table, request.fields, request.getParents, 
+			      collectproto, disp, outconvert, textout, logout);
+  
+
+  textout << outconvert << disp << "_query:footer_";
+  
+  delete (formatlistptr);
+  
+  return true;
+}
Index: /tags/start/protemix/src/recpt/ptmxqueryaction.h
===================================================================
--- /tags/start/protemix/src/recpt/ptmxqueryaction.h	(revision 13666)
+++ /tags/start/protemix/src/recpt/ptmxqueryaction.h	(revision 13666)
@@ -0,0 +1,55 @@
+/**********************************************************************
+ *
+ * ptmxqueryaction.h -- 
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Copyright (C) 2002  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.
+ *
+ *
+ *********************************************************************/
+
+
+#ifndef PTMXQUERYDOCACTION_H
+#define PTMXQUERYACTION_H
+
+#include "queryaction.h"
+
+class ptmxqueryaction : public queryaction {
+
+protected:
+
+  virtual bool search_single_collection (cgiargsclass &args, 
+					 const text_t &collection,
+					 recptprotolistclass *protos, 
+					 browsermapclass *browsers, 
+					 displayclass &disp, 
+					 outconvertclass &outconvert, 
+					 ostream &textout, ostream &logout);
+
+public:
+  ptmxqueryaction ();
+  virtual ~ptmxqueryaction ();
+
+  
+
+};
+
+#endif
+
+
